summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErich Schubert <erich@debian.org>2013-10-29 20:02:37 +0100
committerAndrej Shadura <andrewsh@debian.org>2019-03-09 22:30:37 +0000
commitec7f409f6e795bbcc6f3c005687954e9475c600c (patch)
treefbf36c0ab791c556198b487ca40ae56ae5ab1ee5
parent974d4cf6d54cadc06258039f2cd0515cc34aeac6 (diff)
parent8300861dc4c62c5567a4e654976072f854217544 (diff)
Import Debian changes 0.6.0~beta2-1
elki (0.6.0~beta2-1) unstable; urgency=low * New upstream beta release. * 3DPC extension is not yet included.
-rw-r--r--LICENSE.txt2
-rw-r--r--debian/changelog7
-rw-r--r--debian/patches/build.patch8
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.Algorithm36
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.DistanceBasedAlgorithm (renamed from src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm)32
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.ClusteringAlgorithm4
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical.HierarchicalClusteringAlgorithm3
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical.LinkageMethod7
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMeans6
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMeansInitialization6
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMedoidsInitialization3
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.quality.KMeansQualityMeasure2
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.outlier.OutlierAlgorithm26
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.application.AbstractApplication4
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.data.projection.Projection5
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.datasource.filter.ObjectFilter11
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.datasource.filter.StreamFilter7
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.datasource.parser.Parser1
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction56
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.DoubleNorm27
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.LPNormDistanceFunction5
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.NumberVectorDistanceFunction33
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction42
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction40
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDistanceFunction25
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDoubleDistanceFunction25
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.LPNormDistanceFunction7
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.DimensionSelectingSubspaceDistanceFunction (renamed from src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.AbstractDimensionsSelectingDoubleDistanceFunction)1
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.similarityfunction.PrimitiveSimilarityFunction2
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.similarityfunction.SimilarityFunction2
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.evaluation.Evaluator3
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.index.IndexFactory11
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.index.KNNIndex7
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.index.RKNNIndex3
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.index.RangeIndex6
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.index.lsh.hashfamilies.LocalitySensitiveHashFunctionFamily2
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.insert.MTreeInsert1
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.split.MTreeSplit4
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk.BulkSplit2
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.math.geodesy.EarthModel9
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.math.linearalgebra.randomprojections.RandomProjectionFamily4
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.math.statistics.KernelDensityFunction4
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.math.statistics.distribution.Distribution19
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.math.statistics.distribution.DistributionWithRandom9
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.DistributionEstimator49
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.math.statistics.kernelfunctions.KernelDensityFunction8
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.persistent.PageFileFactory4
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.result.ResultHandler3
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.utilities.ensemble.EnsembleVoting4
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.utilities.scaling.ScalingFunction1
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.utilities.scaling.outlier.OutlierScalingFunction3
-rw-r--r--src/de/lmu/ifi/dbs/elki/KDDTask.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/LICENSE.txt2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/APRIORI.java20
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/AbstractAlgorithm.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/AbstractDistanceBasedAlgorithm.java15
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/AbstractPrimitiveDistanceBasedAlgorithm.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/Algorithm.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/DependencyDerivator.java12
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/DistanceBasedAlgorithm.java49
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/DummyAlgorithm.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/KNNDistanceOrder.java12
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/KNNJoin.java30
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/MaterializeDistances.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/NullAlgorithm.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/benchmark/KNNBenchmarkAlgorithm.java51
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/benchmark/RangeQueryBenchmarkAlgorithm.java28
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/benchmark/ValidateApproximativeKNNIndex.java430
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/benchmark/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/AbstractProjectedClustering.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/AbstractProjectedDBSCAN.java30
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/CanopyPreClustering.java236
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/ClusteringAlgorithm.java3
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/DBSCAN.java20
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/DeLiClu.java29
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/EM.java54
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/NaiveMeanShiftClustering.java28
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/OPTICS.java38
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/OPTICSTypeAlgorithm.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/OPTICSXi.java33
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/SLINK.java818
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/SNNClustering.java14
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/CASH.java57
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/COPAC.java22
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/ERiC.java178
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/FourC.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/HiCO.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/LMCLUS.java12
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/ORCLUS.java34
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/cash/CASHInterval.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/cash/CASHIntervalSplit.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/cash/ParameterizationFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/cash/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/CorePredicate.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/EpsilonNeighborPredicate.java20
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/GeneralizedDBSCAN.java173
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/MinPtsCorePredicate.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/NeighborPredicate.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/CentroidLinkageMethod.java84
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/CompleteLinkageMethod.java70
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/ExtractFlatClusteringFromHierarchy.java854
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/GroupAverageLinkageMethod.java82
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/HierarchicalClusteringAlgorithm.java51
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/LinkageMethod.java56
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/MedianLinkageMethod.java80
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/NaiveAgglomerativeHierarchicalClustering.java303
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/PointerHierarchyRepresentationResult.java97
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/SLINK.java368
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/SingleLinkageMethod.java80
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/WardLinkageMethod.java86
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/WeightedAverageLinkageMethod.java84
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/AbstractKMeans.java182
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/AbstractKMeansInitialization.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/BestOfMultipleKMeans.java219
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/FarthestPointsInitialMeans.java186
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/FirstKInitialMeans.java9
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeans.java46
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeansBisecting.java231
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeansInitialization.java12
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeansLloyd.java86
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeansMacQueen.java88
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeansPlusPlusInitialMeans.java16
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMediansLloyd.java76
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMedoidsEM.java22
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMedoidsInitialization.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMedoidsPAM.java22
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/PAMInitialMeans.java12
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/RandomlyChosenInitialMeans.java11
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/RandomlyGeneratedInitialMeans.java9
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/SampleKMeansInitialization.java160
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/quality/KMeansQualityMeasure.java54
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/quality/WithinClusterMeanDistanceQualityMeasure.java89
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/quality/WithinClusterVarianceQualityMeasure.java83
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/quality/package-info.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/CLIQUE.java30
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/DiSH.java74
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/HiSC.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/PROCLUS.java214
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/PreDeCon.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/SUBCLU.java140
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/SubspaceClusteringAlgorithm.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/clique/CLIQUESubspace.java12
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/clique/CLIQUEUnit.java12
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/clique/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/ByLabelClustering.java12
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/ByLabelHierarchicalClustering.java65
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/ByLabelOrAllInOneClustering.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/ByModelClustering.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/TrivialAllInOne.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/TrivialAllNoise.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/ABOD.java67
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/AbstractAggarwalYuOutlier.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/AbstractDBOutlier.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/AggarwalYuEvolutionary.java168
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/AggarwalYuNaive.java14
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/COP.java70
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/DBOutlierDetection.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/DBOutlierScore.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/EMOutlier.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/GaussianModel.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/GaussianUniformMixture.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/HilOut.java287
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/KNNOutlier.java12
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/KNNWeightOutlier.java18
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/ODIN.java192
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/OPTICSOF.java18
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/OutlierAlgorithm.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/ReferenceBasedOutlierDetection.java30
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/SimpleCOP.java22
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/ALOCI.java (renamed from src/de/lmu/ifi/dbs/elki/algorithm/outlier/ALOCI.java)15
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/FlexibleLOF.java (renamed from src/de/lmu/ifi/dbs/elki/algorithm/outlier/LOF.java)204
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/INFLO.java (renamed from src/de/lmu/ifi/dbs/elki/algorithm/outlier/INFLO.java)13
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/LDF.java (renamed from src/de/lmu/ifi/dbs/elki/algorithm/outlier/LDF.java)72
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/LDOF.java (renamed from src/de/lmu/ifi/dbs/elki/algorithm/outlier/LDOF.java)19
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/LOCI.java (renamed from src/de/lmu/ifi/dbs/elki/algorithm/outlier/LOCI.java)29
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/LOF.java293
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/LoOP.java (renamed from src/de/lmu/ifi/dbs/elki/algorithm/outlier/LoOP.java)37
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/OnlineLOF.java (renamed from src/de/lmu/ifi/dbs/elki/algorithm/outlier/OnlineLOF.java)242
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/SimpleKernelDensityLOF.java (renamed from src/de/lmu/ifi/dbs/elki/algorithm/outlier/SimpleKernelDensityLOF.java)43
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/SimplifiedLOF.java (renamed from src/de/lmu/ifi/dbs/elki/algorithm/outlier/SimpleLOF.java)57
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/package-info.java27
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/ExternalDoubleOutlierScore.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/FeatureBagging.java18
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/HiCS.java36
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/RescaleMetaOutlierAlgorithm.java9
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/SimpleOutlierEnsemble.java11
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/AbstractDistanceBasedSpatialOutlier.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/AbstractNeighborhoodOutlier.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuGLSBackwardSearchAlgorithm.java28
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuMeanMultipleAttributes.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuMedianAlgorithm.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuMedianMultipleAttributes.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuMoranScatterplotOutlier.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuRandomWalkEC.java9
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuScatterplotOutlier.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuZTestOutlier.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/SLOM.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/SOF.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/TrimmedMeanApproach.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/AbstractPrecomputedNeighborhood.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/ExtendedNeighborhood.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/ExternalNeighborhood.java19
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/NeighborSetPredicate.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/PrecomputedKNearestNeighborNeighborhood.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/weighted/LinearWeightedExtendedNeighborhood.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/weighted/UnweightedNeighborhoodAdapter.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/weighted/WeightedNeighborSetPredicate.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/weighted/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/subspace/OUTRES.java42
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/subspace/OutRankS1.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/subspace/SOD.java12
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/subspace/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/ByLabelOutlier.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/TrivialAllOutlier.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/TrivialAverageCoordinateOutlier.java98
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/TrivialGeneratedOutlier.java79
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/TrivialNoOutlier.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/statistics/AddSingleScale.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/statistics/AveragePrecisionAtK.java96
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/statistics/DistanceStatisticsWithClasses.java18
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/statistics/EvaluateRankingQuality.java22
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/statistics/RankingQualityHistogram.java12
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/statistics/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/AbstractApplication.java83
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/ComputeSingleColorHistogram.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/ConvertToBundleApplication.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/ELKILauncher.java52
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/GeneratorXMLSpec.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/KDDCLIApplication.java9
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/cache/CacheDoubleDistanceInOnDiskMatrix.java92
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/cache/CacheDoubleDistanceKNNLists.java272
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/cache/CacheDoubleDistanceRangeQueries.java277
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/cache/CacheFloatDistanceInOnDiskMatrix.java77
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/cache/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/geo/VisualizeGeodesicDistances.java121
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/geo/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/greedyensemble/ComputeKNNOutlierScores.java194
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/greedyensemble/GreedyEnsembleExperiment.java513
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/greedyensemble/VisualizePairwiseGainMatrix.java160
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/greedyensemble/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/internal/CheckELKIServices.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/internal/CheckParameterizables.java5
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/internal/DocumentParameters.java526
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/internal/DocumentReferences.java16
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/internal/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/jsmap/JSONBuffer.java34
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/jsmap/JSONResultHandler.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/jsmap/JSONWebServer.java117
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/jsmap/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/visualization/KNNExplorer.java586
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/AbstractNumberVector.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/Arithmetic.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/Bit.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/BitVector.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/ClassLabel.java7
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/Cluster.java264
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/Clustering.java98
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/DoubleVector.java22
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/ExternalID.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/FeatureVector.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/FloatVector.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/HierarchicalClassLabel.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/HyperBoundingBox.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/IntegerVector.java14
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/Interval.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/LabelList.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/ModifiableHyperBoundingBox.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/NumberVector.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/OneDimensionalDoubleVector.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/RationalNumber.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/SimpleClassLabel.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/SparseDoubleVector.java66
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/SparseFeatureVector.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/SparseFloatVector.java60
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/SparseNumberVector.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/Subspace.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/VectorUtil.java89
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/images/AbstractComputeColorHistogram.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/images/BlendComposite.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/images/ComputeColorHistogram.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/images/ComputeHSBColorHistogram.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/images/ComputeNaiveHSBColorHistogram.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/images/ComputeNaiveRGBColorHistogram.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/images/ImageUtil.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/images/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/model/BaseModel.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/model/Bicluster.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/model/BiclusterWithInverted.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/model/ClusterModel.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/model/CoreObjectsModel.java (renamed from src/de/lmu/ifi/dbs/elki/utilities/iterator/OneItemIterator.java)50
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/model/CorrelationAnalysisSolution.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/model/CorrelationModel.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/model/DendrogramModel.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/model/DimensionModel.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/model/EMModel.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/model/KMeansModel.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/model/LinearEquationModel.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/model/MeanModel.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/model/MedoidModel.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/model/Model.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/model/OPTICSModel.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/model/SubspaceModel.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/model/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/projection/FeatureSelection.java74
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/projection/LatLngToECEFProjection.java113
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/projection/LngLatToECEFProjection.java113
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/projection/NumericalFeatureSelection.java71
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/projection/Projection.java34
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/projection/RandomProjection.java166
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/projection/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/spatial/Polygon.java78
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/spatial/PolygonsObject.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/spatial/SpatialComparable.java9
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/spatial/SpatialSingleMaxComparator.java64
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/spatial/SpatialSingleMeanComparator.java66
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/spatial/SpatialSingleMinComparator.java64
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/spatial/SpatialUtil.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/spatial/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/GeneratorInterface.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/GeneratorInterfaceDynamic.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/GeneratorMain.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/GeneratorSingleCluster.java16
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/GeneratorStatic.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/synthetic/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/type/AlternativeTypeInformation.java20
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/type/CombinedTypeInformation.java5
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/type/NoSupportedDataTypeException.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/type/SimpleTypeInformation.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/type/TypeInformation.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/type/TypeInformationSerializer.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/type/TypeUtil.java52
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/type/VectorFieldTypeInformation.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/type/VectorTypeInformation.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/type/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/AbstractDatabase.java12
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/Database.java16
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/DatabaseEventManager.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/HashmapDatabase.java50
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ProxyDatabase.java34
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/QueryUtil.java18
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/StaticArrayDatabase.java66
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/UpdatableDatabase.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/DBIDDataStore.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/DataStore.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreEvent.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreFactory.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreIDMap.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreListener.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreUtil.java16
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/DoubleDataStore.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/DoubleDistanceDataStore.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/IntegerDataStore.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/RecordStore.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/WritableDBIDDataStore.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/WritableDataStore.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/WritableDoubleDataStore.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/WritableDoubleDistanceDataStore.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/WritableIntegerDataStore.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/WritableRecordStore.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayDBIDStore.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayDoubleDistanceStore.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayDoubleStore.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayIntegerStore.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayRecordStore.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayStore.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDDBIDStore.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDDoubleDistanceStore.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDDoubleStore.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDIntegerStore.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDRecordStore.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDStore.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapRecordStore.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapStore.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/memory/MemoryDataStoreFactory.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/memory/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/ArrayDBIDs.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/ArrayModifiableDBIDs.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/ArrayStaticDBIDs.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/DBID.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/DBIDArrayIter.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/DBIDArrayMIter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/DBIDFactory.java27
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/DBIDIter.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/DBIDMIter.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/DBIDPair.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/DBIDRange.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/DBIDRef.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/DBIDUtil.java87
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/DBIDVar.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/DBIDs.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/DoubleDBIDPair.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/EmptyDBIDs.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/HashSetDBIDs.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/HashSetModifiableDBIDs.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/ModifiableDBIDs.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/SetDBIDs.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/StaticDBIDs.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/distance/DistanceDBIDList.java (renamed from src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/DistanceDBIDResult.java)17
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/distance/DistanceDBIDListIter.java (renamed from src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/DistanceDBIDResultIter.java)10
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/distance/DistanceDBIDPair.java (renamed from src/de/lmu/ifi/dbs/elki/database/ids/DistanceDBIDPair.java)5
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceDBIDList.java39
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceDBIDListIter.java (renamed from src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/DoubleDistanceDBIDResultIter.java)9
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceDBIDPair.java (renamed from src/de/lmu/ifi/dbs/elki/database/ids/DoubleDistanceDBIDPair.java)5
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceDBIDPairList.java (renamed from src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/DoubleDistanceDBIDList.java)46
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceKNNHeap.java100
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceKNNList.java55
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/distance/KNNHeap.java (renamed from src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/KNNHeap.java)14
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/distance/KNNList.java (renamed from src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/KNNResult.java)8
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/distance/ModifiableDistanceDBIDList.java (renamed from src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/ModifiableDistanceDBIDResult.java)6
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/distance/ModifiableDoubleDistanceDBIDList.java63
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/distance/package-info.java26
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/generic/AbstractKNNHeap.java (renamed from src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/AbstractKNNHeap.java)34
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/generic/DBIDIterAdapter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/generic/DistanceDBIDPairKNNHeap.java (renamed from src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/GenericKNNHeap.java)24
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/generic/DistanceDBIDPairKNNList.java (renamed from src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/GenericKNNList.java)54
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/generic/DoubleDistanceDBIDPairKNNHeap.java (renamed from src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/DoubleDistanceKNNHeap.java)31
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/generic/DoubleDistanceDBIDPairKNNList.java (renamed from src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/DoubleDistanceKNNList.java)83
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/generic/DoubleDistanceKNNSubList.java190
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/generic/GenericDistanceDBIDList.java (renamed from src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/GenericDistanceDBIDList.java)41
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/generic/KNNSubList.java180
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/generic/MaskedDBIDs.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/generic/MergedDBIDs.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/generic/UnmodifiableArrayDBIDs.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/generic/UnmodifiableDBIDs.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/generic/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/AbstractIntegerDBIDFactory.java201
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/ArrayModifiableIntegerDBIDs.java306
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/ArrayStaticIntegerDBIDs.java (renamed from src/de/lmu/ifi/dbs/elki/database/ids/integer/IntArrayStaticDBIDs.java)10
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/DistanceIntegerDBIDPair.java12
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDKNNHeap.java252
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDKNNList.java298
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDKNNListHeap.java315
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDListIter.java (renamed from src/de/lmu/ifi/dbs/elki/math/statistics/distribution/DistributionWithRandom.java)19
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDPair.java17
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleIntegerArrayQuickSort.java181
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerArrayDBIDs.java (renamed from src/de/lmu/ifi/dbs/elki/utilities/InspectionUtilFrequentlyScanned.java)15
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerArrayStaticDBIDs.java5
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBID.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDArrayIter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDArrayMIter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDArrayQuickSort.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDIter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDMIter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDPair.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDRange.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDRef.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDVar.java15
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDs.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDoubleDBIDPair.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/ReusingDBIDFactory.java14
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/SimpleDBIDFactory.java139
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/TrivialDBIDFactory.java140
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveArrayDBIDs.java7
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveArrayModifiableDBIDs.java3
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveHashSetModifiableDBIDs.java5
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/UnmodifiableIntegerArrayDBIDs.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/UnmodifiableIntegerDBIDs.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/AbstractDataBasedQuery.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/DatabaseQuery.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/DistanceSimilarityQuery.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/LinearScanQuery.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/distance/AbstractDatabaseDistanceQuery.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/distance/AbstractDistanceQuery.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/distance/DBIDDistanceQuery.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/distance/DistanceQuery.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/distance/PrimitiveDistanceQuery.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/distance/PrimitiveDistanceSimilarityQuery.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/distance/SpatialDistanceQuery.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/distance/SpatialPrimitiveDistanceQuery.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/distance/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/knn/AbstractDistanceKNNQuery.java29
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/knn/DoubleOptimizedKNNQuery.java309
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/knn/KNNQuery.java12
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/knn/LinearScanKNNQuery.java53
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/knn/LinearScanPrimitiveDistanceKNNQuery.java20
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/knn/LinearScanRawDoubleDistanceKNNQuery.java143
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/knn/PreprocessorKNNQuery.java24
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/knn/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/range/AbstractDistanceRangeQuery.java12
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/range/DoubleOptimizedRangeQuery.java95
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/range/LinearScanPrimitiveDistanceRangeQuery.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/range/LinearScanRangeQuery.java14
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/range/LinearScanRawDoubleDistanceRangeQuery.java99
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/range/RangeQuery.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/range/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/rknn/AbstractRKNNQuery.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/rknn/LinearScanRKNNQuery.java36
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/rknn/PreprocessorRKNNQuery.java12
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/rknn/RKNNQuery.java12
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/rknn/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/similarity/AbstractDBIDSimilarityQuery.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/similarity/AbstractSimilarityQuery.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/similarity/PrimitiveSimilarityQuery.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/similarity/SimilarityQuery.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/similarity/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/relation/ConvertToStringView.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/relation/DBIDView.java20
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/relation/MaterializedRelation.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/relation/ProjectedView.java3
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/relation/ProxyView.java19
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/relation/Relation.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/relation/RelationUtil.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/relation/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/AbstractDatabaseConnection.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/ArrayAdapterDatabaseConnection.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/BundleDatabaseConnection.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/ConcatenateFilesDatabaseConnection.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/DBIDRangeDatabaseConnection.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/DatabaseConnection.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/EmptyDatabaseConnection.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/ExternalIDJoinDatabaseConnection.java12
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/FileBasedDatabaseConnection.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/GeneratorXMLDatabaseConnection.java14
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/InputStreamDatabaseConnection.java27
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/LabelJoinDatabaseConnection.java12
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/PresortedBlindJoinDatabaseConnection.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/RandomDoubleVectorDatabaseConnection.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/bundle/BundleMeta.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/bundle/BundleReader.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/bundle/BundleStreamSource.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/bundle/BundleWriter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/bundle/MultipleObjectsBundle.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/bundle/ObjectBundle.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/bundle/SingleObjectBundle.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/bundle/StreamFromBundle.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/bundle/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractConversionFilter.java25
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractStreamConversionFilter.java5
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractStreamFilter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractVectorConversionFilter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractVectorStreamConversionFilter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/ByLabelFilter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/ClassLabelFilter.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/ClassLabelFromPatternFilter.java213
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/ExternalIDFilter.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/FilterUtil.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/FixedDBIDsFilter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/HistogramJitterFilter.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/NaNFilter.java185
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/NoMissingValuesFilter.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/NoOpFilter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/ObjectFilter.java5
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/RandomSamplingStreamFilter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/ShuffleObjectsFilter.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/SortByLabelFilter.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/SparseVectorFieldFilter.java17
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/SplitNumberVectorFilter.java14
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/StreamFilter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AbstractNormalization.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AbstractStreamNormalization.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AttributeWiseCDFNormalization.java294
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AttributeWiseErfNormalization.java15
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AttributeWiseMADNormalization.java202
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AttributeWiseMinMaxNormalization.java56
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AttributeWiseVarianceNormalization.java24
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/InverseDocumentFrequencyNormalization.java13
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/LengthNormalization.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/NonNumericFeaturesException.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/Normalization.java13
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/RankTieNormalization.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/TFIDFNormalization.java13
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/transform/AbstractSupervisedProjectionVectorFilter.java230
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/transform/ClassicMultidimensionalScalingTransform.java274
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/transform/GlobalPrincipalComponentAnalysisTransform.java50
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/transform/LatLngToECEFFilter.java111
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/transform/LinearDiscriminantAnalysisFilter.java165
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/transform/LngLatToECEFFilter.java111
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/transform/NumberVectorFeatureSelectionFilter.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/transform/NumberVectorRandomFeatureSelectionFilter.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/transform/ProjectionFilter.java113
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/transform/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/parser/AbstractParser.java122
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/parser/AbstractStreamingParser.java20
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/parser/ArffParser.java62
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/parser/BitVectorLabelParser.java74
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/parser/DoubleVectorLabelParser.java20
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/parser/FloatVectorLabelParser.java17
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/parser/NumberVectorLabelParser.java109
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/parser/Parser.java5
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/parser/SimplePolygonParser.java93
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/parser/SparseBitVectorLabelParser.java73
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/parser/SparseFloatVectorLabelParser.java9
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/parser/SparseNumberVectorLabelParser.java38
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/parser/StreamingParser.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/parser/StringParser.java146
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/parser/TermFrequencyParser.java53
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/parser/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/DistanceUtil.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractDBIDDistanceFunction.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractDatabaseDistanceFunction.java3
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractIndexBasedDistanceFunction.java5
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractPrimitiveDistanceFunction.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractSpatialDoubleDistanceFunction.java52
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractSpatialDoubleDistanceNorm.java54
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractVectorDoubleDistanceFunction.java43
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractVectorDoubleDistanceNorm.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/ArcCosineDistanceFunction.java30
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/BrayCurtisDistanceFunction.java149
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/CanberraDistanceFunction.java68
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/ClarkDistanceFunction.java112
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/CosineDistanceFunction.java30
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/DBIDDistanceFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/DistanceFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/DoubleNorm.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/EuclideanDistanceFunction.java179
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/FilteredLocalPCABasedDistanceFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/IndexBasedDistanceFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/Kulczynski1DistanceFunction.java103
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/LocallyWeightedDistanceFunction.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/LorentzianDistanceFunction.java115
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/MinKDistance.java15
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/Norm.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/PrimitiveDistanceFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/PrimitiveDoubleDistanceFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/ProxyDistanceFunction.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/RandomStableDistanceFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/SharedNearestNeighborJaccardDistanceFunction.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/SpatialPrimitiveDistanceFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/SpatialPrimitiveDoubleDistanceFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/SquaredEuclideanDistanceFunction.java196
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/WeightedCanberraDistanceFunction.java91
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/WeightedDistanceFunction.java14
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/AbstractSimilarityAdapter.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/ArccosSimilarityAdapter.java (renamed from src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/SimilarityAdapterArccos.java)12
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/LinearAdapterLinear.java (renamed from src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/SimilarityAdapterLinear.java)12
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/LnSimilarityAdapter.java (renamed from src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/SimilarityAdapterLn.java)12
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/colorhistogram/HSBHistogramQuadraticDistanceFunction.java12
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/colorhistogram/HistogramIntersectionDistanceFunction.java57
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/colorhistogram/RGBHistogramQuadraticDistanceFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/colorhistogram/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/ERiCDistanceFunction.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/PCABasedCorrelationDistanceFunction.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/PearsonCorrelationDistanceFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/SquaredPearsonCorrelationDistanceFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/WeightedPearsonCorrelationDistanceFunction.java7
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/WeightedSquaredPearsonCorrelationDistanceFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/DiskCacheBasedDoubleDistanceFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/DiskCacheBasedFloatDistanceFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/DistanceParser.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/DistanceParsingResult.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/FileBasedDoubleDistanceFunction.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/FileBasedFloatDistanceFunction.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/NumberDistanceParser.java71
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/geo/DimensionSelectingLatLngDistanceFunction.java85
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/geo/LatLngDistanceFunction.java86
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/geo/LngLatDistanceFunction.java87
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/geo/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/histogram/HistogramMatchDistanceFunction.java (renamed from src/de/lmu/ifi/dbs/elki/distance/distancefunction/JeffreyDivergenceDistanceFunction.java)45
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/histogram/KolmogorovSmirnovDistanceFunction.java101
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/histogram/package-info.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/EuclideanDistanceFunction.java167
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/LPNormDistanceFunction.java (renamed from src/de/lmu/ifi/dbs/elki/distance/distancefunction/LPNormDistanceFunction.java)143
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/ManhattanDistanceFunction.java (renamed from src/de/lmu/ifi/dbs/elki/distance/distancefunction/ManhattanDistanceFunction.java)111
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/MaximumDistanceFunction.java (renamed from src/de/lmu/ifi/dbs/elki/distance/distancefunction/MaximumDistanceFunction.java)86
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/MinimumDistanceFunction.java (renamed from src/de/lmu/ifi/dbs/elki/distance/distancefunction/MinimumDistanceFunction.java)110
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/SparseEuclideanDistanceFunction.java (renamed from src/de/lmu/ifi/dbs/elki/distance/distancefunction/SparseEuclideanDistanceFunction.java)52
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/SparseLPNormDistanceFunction.java (renamed from src/de/lmu/ifi/dbs/elki/distance/distancefunction/SparseLPNormDistanceFunction.java)39
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/SparseManhattanDistanceFunction.java (renamed from src/de/lmu/ifi/dbs/elki/distance/distancefunction/SparseManhattanDistanceFunction.java)35
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/SparseMaximumDistanceFunction.java (renamed from src/de/lmu/ifi/dbs/elki/distance/distancefunction/SparseMaximumDistanceFunction.java)35
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/SquaredEuclideanDistanceFunction.java166
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/WeightedEuclideanDistanceFunction.java124
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/WeightedLPNormDistanceFunction.java (renamed from src/de/lmu/ifi/dbs/elki/distance/distancefunction/WeightedLPNormDistanceFunction.java)85
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/WeightedManhattanDistanceFunction.java110
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/WeightedSquaredEuclideanDistanceFunction.java (renamed from src/de/lmu/ifi/dbs/elki/distance/distancefunction/WeightedSquaredEuclideanDistanceFunction.java)71
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/package-info.java (renamed from src/de/lmu/ifi/dbs/elki/utilities/iterator/package-info.java)6
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/probabilistic/ChiSquaredDistanceFunction.java135
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/probabilistic/JeffreyDivergenceDistanceFunction.java137
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/probabilistic/JensenShannonDivergenceDistanceFunction.java74
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/probabilistic/KullbackLeiblerDivergenceAsymmetricDistanceFunction.java121
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/probabilistic/KullbackLeiblerDivergenceReverseAsymmetricDistanceFunction.java122
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/probabilistic/SqrtJensenShannonDivergenceDistanceFunction.java120
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/probabilistic/package-info.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/strings/LevenshteinDistanceFunction.java135
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/strings/NormalizedLevenshteinDistanceFunction.java96
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/strings/package-info.java27
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/AbstractDimensionsSelectingDoubleDistanceFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/AbstractPreferenceVectorBasedCorrelationDistanceFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/DiSHDistanceFunction.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/DimensionSelectingDistanceFunction.java68
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/DimensionSelectingSubspaceDistanceFunction.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/HiSCDistanceFunction.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/LocalSubspaceDistanceFunction.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/SubspaceEuclideanDistanceFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/SubspaceLPNormDistanceFunction.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/SubspaceManhattanDistanceFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/timeseries/AbstractEditDistanceFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/timeseries/DTWDistanceFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/timeseries/EDRDistanceFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/timeseries/ERPDistanceFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/timeseries/LCSSDistanceFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/timeseries/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/DistanceDBIDResultUtil.java25
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/KNNUtil.java372
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/package-info.java29
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancevalue/AbstractDistance.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancevalue/BitDistance.java12
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancevalue/CorrelationDistance.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancevalue/Distance.java19
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancevalue/DoubleDistance.java38
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancevalue/FloatDistance.java38
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancevalue/IntegerDistance.java12
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancevalue/NumberDistance.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancevalue/PCACorrelationDistance.java12
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancevalue/PreferenceVectorBasedCorrelationDistance.java38
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancevalue/SubspaceDistance.java12
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancevalue/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/similarityfunction/AbstractDBIDSimilarityFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/similarityfunction/AbstractIndexBasedSimilarityFunction.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/similarityfunction/AbstractPrimitiveSimilarityFunction.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/similarityfunction/DBIDSimilarityFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/similarityfunction/FractionalSharedNearestNeighborSimilarityFunction.java25
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/similarityfunction/IndexBasedSimilarityFunction.java3
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/similarityfunction/InvertedDistanceSimilarityFunction.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/similarityfunction/Kulczynski1SimilarityFunction.java110
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/similarityfunction/Kulczynski2SimilarityFunction.java113
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/similarityfunction/NormalizedPrimitiveSimilarityFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/similarityfunction/NormalizedSimilarityFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/similarityfunction/PrimitiveSimilarityFunction.java3
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/similarityfunction/SharedNearestNeighborSimilarityFunction.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/similarityfunction/SimilarityFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/similarityfunction/kernel/FooKernelFunction.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/similarityfunction/kernel/KernelMatrix.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/similarityfunction/kernel/LinearKernelFunction.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/similarityfunction/kernel/PolynomialKernelFunction.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/similarityfunction/kernel/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/similarityfunction/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/AutomaticEvaluation.java40
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/Evaluator.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/NoAutomaticEvaluation.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/clustering/BCubed.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/clustering/ClusterContingencyTable.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/clustering/EditDistance.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/clustering/Entropy.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/clustering/EvaluateClustering.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/clustering/PairCounting.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/clustering/SetMatchingPurity.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/clustering/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/clustering/pairsegments/ClusterPairSegmentAnalysis.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/clustering/pairsegments/Segment.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/clustering/pairsegments/Segments.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/clustering/pairsegments/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/histogram/ComputeOutlierHistogram.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/histogram/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/index/IndexPurity.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/index/IndexStatistics.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/index/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/outlier/JudgeOutlierScores.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/outlier/OutlierPrecisionAtKCurve.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/outlier/OutlierPrecisionRecallCurve.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/outlier/OutlierROCCurve.java27
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/outlier/OutlierSmROCCurve.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/outlier/OutlierThresholdClustering.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/outlier/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/roc/ROC.java549
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/roc/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/similaritymatrix/ComputeSimilarityMatrixImage.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/similaritymatrix/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/GUIUtil.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/configurator/AbstractParameterConfigurator.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/configurator/AbstractSingleParameterConfigurator.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/configurator/ClassListParameterConfigurator.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/configurator/ClassParameterConfigurator.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/configurator/ConfiguratorPanel.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/configurator/EnumParameterConfigurator.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/configurator/FileParameterConfigurator.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/configurator/FlagParameterConfigurator.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/configurator/ParameterConfigurator.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/configurator/TextParameterConfigurator.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/configurator/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/icons/StockIcon.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/icons/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/minigui/MiniGUI.java15
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/minigui/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/multistep/MultiStepGUI.java121
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/multistep/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/multistep/panels/AlgorithmTabPanel.java38
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/multistep/panels/EvaluationTabPanel.java13
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/multistep/panels/InputTabPanel.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/multistep/panels/LoggingTabPanel.java12
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/multistep/panels/OutputTabPanel.java13
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/multistep/panels/ParameterTabPanel.java36
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/multistep/panels/SavedSettingsTabPanel.java27
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/multistep/panels/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/util/DynamicParameters.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/util/LogPane.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/util/LogPanel.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/util/ParameterTable.java299
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/util/ParametersModel.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/util/SavedSettingsFile.java17
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/util/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/AbstractIndex.java34
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/AbstractRefiningIndex.java111
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/DynamicIndex.java66
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/Index.java49
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/IndexFactory.java3
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/KNNIndex.java3
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/PagedIndexFactory.java110
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/RKNNIndex.java3
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/RangeIndex.java3
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/lsh/InMemoryLSHIndex.java418
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/AbstractHashFunctionFamily.java164
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/EuclideanHashFunctionFamily.java74
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/LocalitySensitiveHashFunctionFamily.java65
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/ManhattanHashFunctionFamily.java76
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/package-info.java27
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/lsh/hashfunctions/LocalitySensitiveHashFunction.java (renamed from src/de/lmu/ifi/dbs/elki/utilities/designpattern/Observer.java)20
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/lsh/hashfunctions/MultipleProjectionsLocalitySensitiveHashFunction.java119
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/lsh/hashfunctions/package-info.java27
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/lsh/package-info.java27
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/AbstractPreprocessorIndex.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/LocalProjectionIndex.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/AbstractMaterializeKNNPreprocessor.java23
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/CachedDoubleDistanceKNNPreprocessor.java205
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/KNNChangeEvent.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/KNNJoinMaterializeKNNPreprocessor.java17
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/KNNListener.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/MaterializeKNNAndRKNNPreprocessor.java63
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/MaterializeKNNPreprocessor.java123
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/MetricalIndexApproximationMaterializeKNNPreprocessor.java28
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/PartitionApproximationMaterializeKNNPreprocessor.java28
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/RandomSampleKNNPreprocessor.java35
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/SpatialApproximationMaterializeKNNPreprocessor.java28
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/AbstractFilteredPCAIndex.java20
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/FilteredLocalPCAIndex.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/KNNQueryFilteredPCAIndex.java32
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/RangeQueryFilteredPCAIndex.java19
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/AbstractPreferenceVectorIndex.java9
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/DiSHPreferenceVectorIndex.java27
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/HiSCPreferenceVectorIndex.java19
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/PreferenceVectorIndex.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/snn/SharedNearestNeighborIndex.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/snn/SharedNearestNeighborPreprocessor.java27
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/snn/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/AbstractSubspaceProjectionIndex.java28
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/FourCSubspaceIndex.java19
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/PreDeConSubspaceIndex.java15
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/SubspaceProjectionIndex.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/projected/LatLngAsECEFIndex.java292
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/projected/LngLatAsECEFIndex.java287
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/projected/PINN.java166
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/projected/ProjectedIndex.java648
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/projected/package-info.java26
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/AbstractDirectoryEntry.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/AbstractLeafEntry.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/AbstractNode.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/BreadthFirstEnumeration.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/DirectoryEntry.java7
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/Entry.java3
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/IndexTree.java56
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/IndexTreePath.java11
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/LeafEntry.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/Node.java3
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexFactory.java184
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexHeader.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexPathComponent.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/MetricalIndexTree.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTree.java373
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTreeFactory.java107
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTreeNode.java82
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeDirectoryEntry.java44
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeEntry.java14
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeLeafEntry.java48
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeSettings.java56
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTree.java44
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTreeUnified.java36
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTreeUnifiedFactory.java58
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/MkTreeHeader.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/MkTreeSettings.java46
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppDirectoryEntry.java11
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppEntry.java7
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppLeafEntry.java9
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTree.java215
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeFactory.java77
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeIndex.java111
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeNode.java14
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeSettings.java47
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/PolynomialApproximation.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/ApproximationLine.java24
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/ConvexHull.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPDirectoryEntry.java29
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPEntry.java13
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPLeafEntry.java37
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTree.java335
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTreeIndex.java112
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTreeNode.java18
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCopTreeFactory.java43
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxDirectoryEntry.java34
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxEntry.java22
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxLeafEntry.java30
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTree.java230
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeFactory.java37
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeIndex.java100
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeNode.java35
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabDirectoryEntry.java60
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabEntry.java37
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabLeafEntry.java63
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTree.java146
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTreeFactory.java33
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTreeIndex.java136
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTreeNode.java44
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTree.java90
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeFactory.java34
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeIndex.java144
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeNode.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/DoubleDistanceMetricalIndexKNNQuery.java48
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/DoubleDistanceMetricalIndexRangeQuery.java42
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MTreeQueryUtil.java24
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MetricalIndexKNNQuery.java83
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MetricalIndexRangeQuery.java56
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MkTreeRKNNQuery.java21
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/MTreeSplit.java138
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/package-info.java26
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/insert/MTreeInsert.java50
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/insert/MinimumEnlargementInsert.java117
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/insert/package-info.java26
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/package-info.java26
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/Assignments.java (renamed from src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/Assignments.java)39
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/DistanceEntry.java (renamed from src/de/lmu/ifi/dbs/elki/index/tree/DistanceEntry.java)28
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/MLBDistSplit.java (renamed from src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/MLBDistSplit.java)63
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/MMRadSplit.java88
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/MRadSplit.java (renamed from src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/MRadSplit.java)54
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/MTreeSplit.java223
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/RandomSplit.java136
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/package-info.java26
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/query/DoubleDistanceSearchCandidate.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/query/DoubleMTreeDistanceSearchCandidate.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/query/GenericDistanceSearchCandidate.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/query/GenericMTreeDistanceSearchCandidate.java54
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/query/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialDirectoryEntry.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialEntry.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialIndexTree.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialNode.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialPair.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialPointLeafEntry.java56
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/kd/MinimalisticMemoryKDTree.java443
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/kd/package-info.java (renamed from src/de/lmu/ifi/dbs/elki/application/visualization/package-info.java)7
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRStarTree.java463
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRStarTreeFactory.java134
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRStarTreeNode.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRTreeSettings.java121
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/NonFlatRStarTree.java13
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluDirectoryEntry.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluEntry.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluLeafEntry.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluNode.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluTree.java41
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluTreeFactory.java42
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluTreeIndex.java20
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/DoubleDistanceRStarTreeKNNQuery.java51
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/DoubleDistanceRStarTreeRangeQuery.java30
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/GenericRStarTreeKNNQuery.java110
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/GenericRStarTreeRangeQuery.java34
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/RStarTreeUtil.java14
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTree.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTreeFactory.java45
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTreeIndex.java20
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTreeNode.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/AbstractBulkSplit.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/AdaptiveSortTileRecursiveBulkSplit.java151
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/BulkSplit.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/FileOrderBulkSplit.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/MaxExtensionBulkSplit.java40
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/MaxExtensionSortTileRecursiveBulkSplit.java134
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/OneDimSortBulkSplit.java19
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/SortTileRecursiveBulkSplit.java50
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/SpatialSortBulkSplit.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/ApproximativeLeastOverlapInsertionStrategy.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/CombinedInsertionStrategy.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/InsertionStrategy.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastEnlargementInsertionStrategy.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastEnlargementWithAreaInsertionStrategy.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastOverlapInsertionStrategy.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/LimitedReinsertOverflowTreatment.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/OverflowTreatment.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/SplitOnlyOverflowTreatment.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/AbstractPartialReinsert.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/CloseReinsert.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/FarReinsert.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/ReinsertStrategy.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/AngTanLinearSplit.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/GreeneSplit.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/RTreeLinearSplit.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/RTreeQuadraticSplit.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/SplitStrategy.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/TopologicalSplitter.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/NodeArrayAdapter.java3
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/SpatialComparator.java103
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/vafile/PartialVAFile.java146
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/vafile/VAFile.java115
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/vafile/VALPNormDistance.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/vafile/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/logging/CLISmartHandler.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/logging/ELKILogRecord.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/logging/ErrorFormatter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/logging/Logging.java181
-rw-r--r--src/de/lmu/ifi/dbs/elki/logging/LoggingConfiguration.java108
-rw-r--r--src/de/lmu/ifi/dbs/elki/logging/LoggingUtil.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/logging/MessageFormatter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/logging/OutputStreamLogger.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/logging/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/logging/progress/AbstractProgress.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/logging/progress/FiniteProgress.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/logging/progress/IndefiniteProgress.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/logging/progress/Progress.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/logging/progress/ProgressLogRecord.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/logging/progress/ProgressTracker.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/logging/progress/StepProgress.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/logging/progress/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/logging/statistics/AbstractStatistic.java (renamed from src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveArrayStaticDBIDs.java)30
-rw-r--r--src/de/lmu/ifi/dbs/elki/logging/statistics/AtomicLongCounter.java (renamed from src/de/lmu/ifi/dbs/elki/utilities/iterator/EmptyIterator.java)63
-rw-r--r--src/de/lmu/ifi/dbs/elki/logging/statistics/Counter.java62
-rw-r--r--src/de/lmu/ifi/dbs/elki/logging/statistics/DoubleStatistic.java72
-rw-r--r--src/de/lmu/ifi/dbs/elki/logging/statistics/Duration.java64
-rw-r--r--src/de/lmu/ifi/dbs/elki/logging/statistics/LongStatistic.java70
-rw-r--r--src/de/lmu/ifi/dbs/elki/logging/statistics/MillisTimeDuration.java75
-rw-r--r--src/de/lmu/ifi/dbs/elki/logging/statistics/NanoDuration.java75
-rw-r--r--src/de/lmu/ifi/dbs/elki/logging/statistics/Statistic.java (renamed from src/de/lmu/ifi/dbs/elki/math/statistics/KernelDensityFunction.java)25
-rw-r--r--src/de/lmu/ifi/dbs/elki/logging/statistics/StringStatistic.java70
-rw-r--r--src/de/lmu/ifi/dbs/elki/logging/statistics/UnsynchronizedLongCounter.java (renamed from src/de/lmu/ifi/dbs/elki/utilities/iterator/UnmodifiableIterator.java)51
-rw-r--r--src/de/lmu/ifi/dbs/elki/logging/statistics/package-info.java24
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/DoubleMinMax.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/GeoUtil.java670
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/IntegerMinMax.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/MathUtil.java121
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/Mean.java42
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/MeanVariance.java64
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/MeanVarianceMinMax.java40
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/MinMax.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/PearsonCorrelation.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/Primes.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/SinCosTable.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/StatisticalMoments.java282
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/CovarianceDimensionSimilarity.java5
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/DimensionSimilarity.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/DimensionSimilarityMatrix.java27
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/HSMDimensionSimilarity.java48
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/HiCSDimensionSimilarity.java29
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/MCEDimensionSimilarity.java11
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/SURFINGDimensionSimilarity.java18
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/SlopeDimensionSimilarity.java13
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/SlopeInversionDimensionSimilarity.java13
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/geodesy/AbstractEarthModel.java207
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/geodesy/Clarke1858SpheroidEarthModel.java80
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/geodesy/Clarke1880SpheroidEarthModel.java80
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/geodesy/EarthModel.java221
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/geodesy/GRS67SpheroidEarthModel.java80
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/geodesy/GRS80SpheroidEarthModel.java81
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/geodesy/SphereUtil.java881
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/geodesy/SphericalCosineEarthModel.java97
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/geodesy/SphericalHaversineEarthModel.java97
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/geodesy/SphericalVincentyEarthModel.java96
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/geodesy/WGS72SpheroidEarthModel.java81
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/geodesy/WGS84SpheroidEarthModel.java (renamed from src/de/lmu/ifi/dbs/elki/evaluation/roc/ComputeROCCurve.java)70
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/geometry/AlphaShape.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/geometry/GrahamScanConvexHull2D.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/geometry/PrimsMinimumSpanningTree.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/geometry/SweepHullDelaunay2D.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/geometry/XYCurve.java43
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/geometry/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/AffineTransformation.java13
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/Centroid.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/CholeskyDecomposition.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/CovarianceMatrix.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/EigenPair.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/EigenvalueDecomposition.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/LUDecomposition.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/LinearEquationSystem.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/Matrix.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/ProjectedCentroid.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/ProjectionResult.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/QRDecomposition.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/SingularValueDecomposition.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/SortedEigenPairs.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/SubspaceProjectionResult.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/VMath.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/Vector.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/fitting/FittingFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/fitting/FittingFunctionResult.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/fitting/GaussianFittingFunction.java11
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/fitting/LevenbergMarquardtMethod.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/fitting/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/AbstractCovarianceMatrixBuilder.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/CompositeEigenPairFilter.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/CovarianceMatrixBuilder.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/DropEigenPairFilter.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/EigenPairFilter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/FilteredEigenPairs.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/FirstNEigenPairFilter.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/LimitEigenPairFilter.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/NormalizingEigenPairFilter.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/PCAFilteredAutotuningRunner.java28
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/PCAFilteredResult.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/PCAFilteredRunner.java14
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/PCAResult.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/PCARunner.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/PercentageEigenPairFilter.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/ProgressiveEigenPairFilter.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/RANSACCovarianceMatrixBuilder.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/RelativeEigenPairFilter.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/SignificantEigenPairFilter.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/StandardCovarianceMatrixBuilder.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/WeakEigenPairFilter.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/WeightedCovarianceMatrixBuilder.java22
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/ConstantWeight.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/ErfcStddevWeight.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/ErfcWeight.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/ExponentialStddevWeight.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/ExponentialWeight.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/GaussStddevWeight.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/GaussWeight.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/InverseLinearWeight.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/InverseProportionalStddevWeight.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/InverseProportionalWeight.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/LinearWeight.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/QuadraticStddevWeight.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/QuadraticWeight.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/WeightFunction.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/randomprojections/AbstractRandomProjectionFamily.java131
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/randomprojections/AchlioptasRandomProjectionFamily.java124
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/randomprojections/CauchyRandomProjectionFamily.java78
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/randomprojections/GaussianRandomProjectionFamily.java77
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/randomprojections/RandomProjectionFamily.java66
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/randomprojections/RandomSubsetProjectionFamily.java167
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/randomprojections/package-info.java26
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/scales/LinearScale.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/scales/Scales.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/scales/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/AbstractSpatialSorter.java20
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/BinarySplitSpatialSorter.java55
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/HilbertSpatialSorter.java17
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/PeanoSpatialSorter.java59
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/SpatialSorter.java5
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/ZCurveSpatialSorter.java54
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/ZCurveTransformer.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/KernelDensityEstimator.java79
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/LinearRegression.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/MultipleLinearRegression.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/PolynomialRegression.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/ProbabilityWeightedMoments.java176
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/BetaDistribution.java199
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/CauchyDistribution.java135
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/ChiDistribution.java7
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/ChiSquaredDistribution.java15
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/ConstantDistribution.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/Distribution.java15
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/ExponentialDistribution.java58
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/ExponentiallyModifiedGaussianDistribution.java188
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/GammaDistribution.java317
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/GeneralizedExtremeValueDistribution.java167
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/GeneralizedLogisticAlternateDistribution.java162
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/GeneralizedLogisticDistribution.java184
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/GumbelDistribution.java134
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/HaltonUniformDistribution.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/KappaDistribution.java223
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/LaplaceDistribution.java172
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/LogGammaAlternateDistribution.java209
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/LogGammaDistribution.java194
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/LogLogisticDistribution.java137
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/LogNormalDistribution.java165
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/LogisticDistribution.java186
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/NormalDistribution.java136
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/PoissonDistribution.java129
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/RayleighDistribution.java165
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/SkewGeneralizedNormalDistribution.java169
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/StudentsTDistribution.java17
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/UniformDistribution.java34
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/WaldDistribution.java173
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/WeibullDistribution.java182
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/AbstractExpMADEstimator.java96
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/AbstractLMMEstimator.java71
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/AbstractLogMADEstimator.java101
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/AbstractLogMOMEstimator.java94
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/AbstractLogMeanVarianceEstimator.java80
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/AbstractMADEstimator.java109
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/AbstractMOMEstimator.java66
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/AbstractMeanVarianceEstimator.java67
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/CauchyMADEstimator.java80
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/DistributionEstimator.java52
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/EMGOlivierNorbergEstimator.java82
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/ExpMADDistributionEstimator.java45
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/ExponentialLMMEstimator.java92
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/ExponentialMADEstimator.java85
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/ExponentialMOMEstimator.java77
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/ExponentialMedianEstimator.java83
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/GammaChoiWetteEstimator.java118
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/GammaLMMEstimator.java113
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/GammaMADEstimator.java96
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/GammaMOMEstimator.java93
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/GeneralizedExtremeValueLMMEstimator.java161
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/GeneralizedLogisticAlternateLMMEstimator.java98
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/GumbelLMMEstimator.java90
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/GumbelMADEstimator.java82
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LMMDistributionEstimator.java51
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LaplaceLMMEstimator.java78
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LaplaceMADEstimator.java82
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LaplaceMLEEstimator.java94
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogGammaAlternateExpMADEstimator.java85
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogGammaChoiWetteEstimator.java126
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogGammaLogMADEstimator.java85
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogGammaLogMOMEstimator.java85
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogLogisticMADEstimator.java81
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogMADDistributionEstimator.java45
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogMOMDistributionEstimator.java46
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogNormalBilkovaLMMEstimator.java104
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogNormalLMMEstimator.java130
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogNormalLevenbergMarquardtKDEEstimator.java122
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogNormalLogMADEstimator.java89
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogNormalLogMOMEstimator.java74
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogisticLMMEstimator.java90
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogisticMADEstimator.java80
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/MADDistributionEstimator.java45
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/MOMDistributionEstimator.java45
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/MeanVarianceDistributionEstimator.java45
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/NormalLMMEstimator.java87
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/NormalLevenbergMarquardtKDEEstimator.java118
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/NormalMADEstimator.java88
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/NormalMOMEstimator.java76
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/RayleighLMMEstimator.java85
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/RayleighMADEstimator.java90
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/RayleighMLEEstimator.java84
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/SkewGNormalLMMEstimator.java125
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/UniformEnhancedMinMaxEstimator.java100
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/UniformLMMEstimator.java77
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/UniformMADEstimator.java80
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/UniformMinMaxEstimator.java107
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/WaldMLEstimator.java85
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/WaldMOMEstimator.java71
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/WeibullLMMEstimator.java85
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/WeibullLogMADEstimator.java85
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/WeibullLogMOMEstimator.java101
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/meta/BestFitEstimator.java472
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/meta/TrimmedEstimator.java156
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/meta/WinsorisingEstimator.java166
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/meta/package-info.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/package-info.java (renamed from src/de/lmu/ifi/dbs/elki/utilities/iterator/MIter.java)22
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/BiweightKernelDensityFunction.java102
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/CosineKernelDensityFunction.java99
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/EpanechnikovKernelDensityFunction.java (renamed from src/de/lmu/ifi/dbs/elki/math/statistics/EpanechnikovKernelDensityFunction.java)59
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/GaussianKernelDensityFunction.java (renamed from src/de/lmu/ifi/dbs/elki/math/statistics/GaussianKernelDensityFunction.java)49
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/KernelDensityFunction.java76
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/TriangularKernelDensityFunction.java (renamed from src/de/lmu/ifi/dbs/elki/math/statistics/TriangularKernelDensityFunction.java)57
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/TricubeKernelDensityFunction.java105
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/TriweightKernelDensityFunction.java102
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/UniformKernelDensityFunction.java (renamed from src/de/lmu/ifi/dbs/elki/math/statistics/UniformKernelDensityFunction.java)57
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/package-info.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/tests/KolmogorovSmirnovTest.java63
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/tests/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/AbstractExternalizablePage.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/AbstractPageFile.java58
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/AbstractPageFileFactory.java100
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/AbstractStoringPageFile.java17
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/ByteArrayUtil.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/ByteBufferInputStream.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/ByteBufferOutputStream.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/ByteBufferSerializer.java5
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/DefaultPageHeader.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/ExternalizablePage.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/FixedSizeByteBufferSerializer.java3
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/LRUCache.java32
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/LRUCachePageFileFactory.java135
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/MemoryPageFile.java25
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/MemoryPageFileFactory.java (renamed from src/de/lmu/ifi/dbs/elki/persistent/PageFileStatistics.java)52
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/OnDiskArray.java55
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/OnDiskArrayPageFile.java83
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/OnDiskArrayPageFileFactory.java101
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/OnDiskUpperTriangleMatrix.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/Page.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/PageFile.java14
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/PageFileFactory.java48
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/PageFileUtil.java100
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/PageHeader.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/PersistentPageFile.java19
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/PersistentPageFileFactory.java101
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/AbstractHierarchicalResult.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/AprioriResult.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/BasicResult.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/CollectionResult.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/DBIDSelection.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/DiscardResultHandler.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/HierarchicalResult.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/HistogramResult.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/IterableResult.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/KMLOutputHandler.java214
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/KNNDistanceOrderResult.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/LogResultStructureResultHandler.java22
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/OrderingFromDataStore.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/OrderingResult.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/PixmapResult.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/RangeSelection.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/ReferencePointsResult.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/Result.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/ResultAdapter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/ResultHandler.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/ResultHierarchy.java38
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/ResultListener.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/ResultProcessor.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/ResultUtil.java81
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/ResultWriter.java116
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/SamplingResult.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/ScalesResult.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/SelectionResult.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/SettingsResult.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/optics/ClusterOrderEntry.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/optics/ClusterOrderResult.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/optics/DoubleDistanceClusterOrderEntry.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/optics/GenericClusterOrderEntry.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/optics/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/outlier/BasicOutlierScoreMeta.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/outlier/InvertedOutlierScoreMeta.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/outlier/OrderingFromRelation.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/outlier/OutlierResult.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/outlier/OutlierScoreMeta.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/outlier/ProbabilisticOutlierScore.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/outlier/QuotientOutlierScoreMeta.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/outlier/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/textwriter/MultipleFilesOutput.java61
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/textwriter/SingleStreamOutput.java30
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/textwriter/StreamFactory.java21
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriteable.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriter.java288
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriterStream.java76
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriterWriterInterface.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/textwriter/naming/NamingScheme.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/textwriter/naming/SimpleEnumeratingScheme.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/textwriter/naming/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/textwriter/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterDoubleDoublePair.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterObjectArray.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterObjectComment.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterObjectInline.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterPair.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterTextWriteable.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterTriple.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterVector.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/textwriter/writers/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/Alias.java47
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/Base64.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/BitsUtil.java64
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/ClassGenericsUtil.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/DatabaseUtil.java13
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/ELKIServiceLoader.java42
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/FileUtil.java57
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/FormatUtil.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/HandlerList.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/InspectionUtil.java286
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/QueryStatistic.java98
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/RandomFactory.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/Util.java49
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/AnyMap.java94
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/HashMapList.java124
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/MaskedArrayList.java174
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/QuickSelect.java767
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ArrayAdapter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ArrayDBIDsAdapter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ArrayLikeUtil.java67
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/DoubleArrayAdapter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ExtendedArray.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/FeatureVectorAdapter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/FloatArrayAdapter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/IdentityArrayAdapter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ListArrayAdapter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/NumberArrayAdapter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/NumberListArrayAdapter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/NumberVectorAdapter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/SingleSubsetArrayAdapter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/SubsetArrayAdapter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/SubsetNumberArrayAdapter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/TDoubleListAdapter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/VectorAdapter.java85
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arrays/IntegerArrayQuickSort.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arrays/IntegerComparator.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arrays/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/AbstractHeap.java103
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/ComparableMaxHeap.java402
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/ComparableMinHeap.java402
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/ComparatorMaxHeap.java440
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/ComparatorMinHeap.java440
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleHeap.java222
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleIntegerHeap.java127
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleIntegerMaxHeap.java478
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleIntegerMinHeap.java478
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleLongHeap.java127
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleLongMaxHeap.java478
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleLongMinHeap.java478
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleMaxHeap.java394
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleMinHeap.java394
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleObjMaxHeap.java328
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleObjMinHeap.java328
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleObjectHeap.java129
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleObjectMaxHeap.java482
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleObjectMinHeap.java482
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoublePriorityObject.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/Heap.java192
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerHeap.java222
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerMaxHeap.java394
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerMinHeap.java394
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerObjectHeap.java129
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerObjectMaxHeap.java482
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerObjectMinHeap.java482
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerPriorityObject.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/ObjectHeap.java227
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TiedTopBoundedHeap.java53
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TiedTopBoundedUpdatableHeap.java11
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TopBoundedHeap.java3
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TopBoundedUpdatableHeap.java3
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/UpdatableHeap.java114
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/HashMapHierarchy.java580
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/Hierarchical.java90
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/Hierarchy.java68
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/HierarchyHashmapList.java299
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/HierarchyReferenceLists.java232
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/ModifiableHierarchy.java32
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/AbstractObjDynamicHistogram.java37
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/AbstractObjStaticHistogram.java42
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/AbstractStaticHistogram.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/DoubleArrayStaticHistogram.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/DoubleDynamicHistogram.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/DoubleHistogram.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/DoubleStaticHistogram.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/FloatDynamicHistogram.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/FloatHistogram.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/FloatStaticHistogram.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/Histogram.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/IntArrayStaticHistogram.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/IntDynamicHistogram.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/IntHistogram.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/IntStaticHistogram.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/LongArrayStaticHistogram.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/LongDynamicHistogram.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/LongHistogram.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/LongStaticHistogram.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/MeanVarianceStaticHistogram.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/ObjHistogram.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/ShortDynamicHistogram.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/ShortHistogram.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/ShortStaticHistogram.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/iterator/ArrayIter.java (renamed from src/de/lmu/ifi/dbs/elki/utilities/iterator/ArrayIter.java)12
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/iterator/ArrayListIter.java (renamed from src/de/lmu/ifi/dbs/elki/utilities/iterator/ReverseListIterator.java)82
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/iterator/Iter.java (renamed from src/de/lmu/ifi/dbs/elki/utilities/iterator/Iter.java)9
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/iterator/MIter.java54
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/iterator/package-info.java40
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/designpattern/Observers.java80
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/designpattern/package-info.java26
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/documentation/Description.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/documentation/DocumentationUtil.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/documentation/Reference.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/documentation/Restricted.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/documentation/Title.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/documentation/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVoting.java12
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingBayes.java106
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingInverseMultiplicative.java75
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingMax.java15
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingMean.java15
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingMedian.java9
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingMin.java15
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingMultiplicative.java75
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingRestrictedBayes.java127
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/ensemble/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/exceptions/APIViolationException.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/exceptions/AbortException.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/exceptions/ExceptionMessages.java57
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/exceptions/NotImplementedException.java57
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/exceptions/ObjectNotFoundException.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/exceptions/UnableToComplyException.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/exceptions/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/iterator/AbstractFilteredIterator.java120
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/iterator/MergedIterator.java115
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/iterator/TypeFilterIterator.java86
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/iterator/UnmodifiableListIterator.java98
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/AbstractParameterizer.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/InternalParameterizationErrors.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/NoParameterValueException.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/OptionID.java81
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/OptionUtil.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/ParameterException.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/Parameterizable.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/Parameterizer.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/UnspecifiedParameterException.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/UnusedParameterException.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/WrongParameterValueException.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/AbstractNumberConstraint.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/AllOrNoneMustBeSetGlobalConstraint.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/EqualSizeGlobalConstraint.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/EqualStringConstraint.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GlobalListSizeConstraint.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GlobalParameterConstraint.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GlobalVectorListElementSizeConstraint.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GreaterConstraint.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GreaterEqualConstraint.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/IntervalConstraint.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessConstraint.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessEqualConstraint.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessEqualGlobalConstraint.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessGlobalConstraint.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ListEachConstraint.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ListParameterNoDuplicateValueConstraint.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ListSizeConstraint.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/NoDuplicateValueGlobalConstraint.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/OneMustBeSetGlobalConstraint.java13
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/OnlyOneIsAllowedToBeSetGlobalConstraint.java27
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ParameterConstraint.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ParameterFlagGlobalConstraint.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/StringLengthConstraint.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/AbstractParameterization.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/ChainedParameterization.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/EmptyParameterization.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/ListParameterization.java34
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/MergedParameterization.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/Parameterization.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/SerializedParameterization.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/TrackParameters.java14
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/UnParameterization.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/AbstractParameter.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ClassListParameter.java90
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ClassParameter.java42
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/DistanceParameter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/DoubleListParameter.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/DoubleParameter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/EnumParameter.java18
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/FileListParameter.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/FileParameter.java11
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/Flag.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/IntListParameter.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/IntParameter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ListParameter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/LongParameter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/NumberParameter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ObjectListParameter.java12
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ObjectParameter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/Parameter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/PatternParameter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/RandomParameter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/StringParameter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/VectorListParameter.java7
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/package-info.java3
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/pairs/CPair.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/pairs/CTriple.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/pairs/DoubleDoublePair.java11
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/pairs/DoubleIntPair.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/pairs/DoubleObjPair.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/pairs/FCPair.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/pairs/IntDoublePair.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/pairs/IntIntPair.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/pairs/Pair.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/pairs/PairInterface.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/pairs/PairUtil.java18
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/pairs/SCPair.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/pairs/Triple.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/pairs/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/referencepoints/AxisBasedReferencePoints.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/referencepoints/FullDatabaseReferencePoints.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/referencepoints/GridBasedReferencePoints.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/referencepoints/RandomGeneratedReferencePoints.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/referencepoints/RandomSampleReferencePoints.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/referencepoints/ReferencePointsHeuristic.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/referencepoints/StarBasedReferencePoints.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/referencepoints/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/ClipScaling.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/GammaScaling.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/IdentityScaling.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/LinearScaling.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/MinusLogScaling.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/ScalingFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/StaticScalingFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/COPOutlierScaling.java172
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/HeDESNormalizationOutlierScaling.java35
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MinusLogGammaScaling.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MinusLogStandardDeviationScaling.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MixtureModelOutlierScalingFunction.java127
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MultiplicativeInverseScaling.java30
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierGammaScaling.java34
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierLinearScaling.java101
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierMinusLogScaling.java23
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierScalingFunction.java18
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierSqrtScaling.java96
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/RankingPseudoOutlierScaling.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/SigmoidOutlierScalingFunction.java260
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/SqrtStandardDeviationScaling.java166
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/StandardDeviationScaling.java108
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/TopKOutlierScaling.java55
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/xml/DOMCloner.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/xml/HTMLUtil.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/xml/XMLNodeIterator.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/xml/XMLNodeListIterator.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/xml/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/ExportVisualizations.java9
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/VisualizationTask.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/VisualizerContext.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/VisualizerParameterizer.java26
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/batikutil/AddCSSClass.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/batikutil/AttributeModifier.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/batikutil/BatikUtil.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/batikutil/CSSHoverClass.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/batikutil/CloneInlineImages.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/batikutil/DragableArea.java42
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/batikutil/JSVGSynchronizedCanvas.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/batikutil/JSVGUpdateSynchronizer.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/batikutil/LazyCanvasResizer.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/batikutil/NodeAppendChild.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/batikutil/NodeReplaceChild.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/batikutil/NodeReplacer.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/batikutil/RemoveCSSClass.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/batikutil/ThumbnailRegistryEntry.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/batikutil/ThumbnailTranscoder.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/batikutil/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/colors/ColorLibrary.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/colors/ListBasedColorLibrary.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/colors/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/css/CSSClass.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/css/CSSClassManager.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/css/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/gui/ResultVisualizer.java19
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/gui/ResultWindow.java13
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/gui/SelectionTableWindow.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/gui/SimpleSVGViewer.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/gui/detail/DetailView.java49
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/gui/detail/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/gui/overview/DetailViewSelectedEvent.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/gui/overview/LayerMap.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/gui/overview/OverviewPlot.java37
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/gui/overview/PlotItem.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/gui/overview/RectangleArranger.java21
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/gui/overview/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/gui/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSColorAdapter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSColorFromStylingPolicy.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSColorStatic.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSCorrelationDimensionalityDistance.java7
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSCut.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSDistanceAdapter.java12
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSNumberDistance.java9
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSPlot.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/opticsplot/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projections/AbstractFullProjection.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projections/AbstractProjection.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projections/AbstractSimpleProjection.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projections/AffineProjection.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projections/CanvasSize.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projections/FullProjection.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projections/OPTICSProjection.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projections/Projection.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projections/Projection1D.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projections/Projection2D.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projections/ProjectionParallel.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projections/Simple1D.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projections/Simple2D.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projections/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projector/HistogramFactory.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projector/HistogramProjector.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projector/OPTICSProjector.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projector/OPTICSProjectorFactory.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projector/ParallelPlotFactory.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projector/ParallelPlotProjector.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projector/Projector.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projector/ProjectorFactory.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projector/ScatterPlotFactory.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projector/ScatterPlotProjector.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projector/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/savedialog/SVGSaveDialog.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/savedialog/SaveOptionsPanel.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/savedialog/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/ClassStylingPolicy.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/ClusterStylingPolicy.java47
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/PropertiesBasedStyleLibrary.java9
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/SingleObjectsStylingPolicy.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/StyleLibrary.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/StyleResult.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/StylingPolicy.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/classic.properties6
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/default.properties6
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/greyscale.properties6
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/lines/DashedLineStyleLibrary.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/lines/LineStyleLibrary.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/lines/SolidLineStyleLibrary.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/lines/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/marker/CircleMarkers.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/marker/MarkerLibrary.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/marker/MinimalMarkers.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/marker/PrettyMarkers.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/marker/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/neon.properties6
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/presentation.properties6
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/print.properties6
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/wikipedia.properties77
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/svg/SVGArrow.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/svg/SVGButton.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/svg/SVGCheckbox.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/svg/SVGCloneVisible.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/svg/SVGEffects.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/svg/SVGHyperCube.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/svg/SVGHyperSphere.java58
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/svg/SVGPath.java32
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/svg/SVGPlot.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/svg/SVGScoreBar.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/svg/SVGSimpleLinearAxis.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/svg/SVGUtil.java23
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/svg/UpdateRunner.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/svg/UpdateSynchronizer.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/svg/VoronoiDraw.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/svg/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/AbstractVisFactory.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/AbstractVisualization.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/StaticVisualizationInstance.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/VisFactory.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/Visualization.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/VisualizerUtil.java96
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/histogram/AbstractHistogramVisualization.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/histogram/ColoredHistogramVisualizer.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/histogram/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/AbstractOPTICSVisualization.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSClusterVisualization.java43
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSPlotCutVisualization.java45
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSPlotVisualizer.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSSteepAreaVisualization.java32
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/pairsegments/CircleSegmentsVisualizer.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/pairsegments/SegmentsStylingPolicy.java22
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/pairsegments/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/AxisVisibilityVisualization.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/cluster/ClusterOutlineVisualization.java9
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/cluster/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/index/RTreeParallelVisualization.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/index/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/selection/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/AbstractScatterplotVisualization.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/AbstractTooltipVisualization.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/AxisVisualization.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/MarkerVisualization.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/PolygonVisualization.java9
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/ReferencePointsVisualization.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/ToolBox2DVisualization.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/TooltipScoreVisualization.java7
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/TooltipStringVisualization.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/ClusterHullVisualization.java224
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/ClusterOrderVisualization.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/EMClusterVisualization.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/VoronoiVisualization.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/density/DensityEstimationOverlay.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/density/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/index/TreeMBRVisualization.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/index/TreeSphereVisualization.java32
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/index/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/outlier/BubbleVisualization.java61
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/outlier/COPVectorVisualization.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/outlier/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/selection/DistanceFunctionVisualization.java23
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/selection/MoveObjectsToolVisualization.java3
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/selection/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/thumbs/ThumbnailThread.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/thumbs/ThumbnailVisualization.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/thumbs/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/ClusterEvaluationVisualization.java25
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/HistogramVisualization.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/KeyVisualization.java232
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/LabelVisualization.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/PixmapVisualizer.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/SettingsVisualization.java3
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/SimilarityMatrixVisualizer.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/XYCurveVisualization.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/workflow/AlgorithmStep.java74
-rw-r--r--src/de/lmu/ifi/dbs/elki/workflow/EvaluationStep.java24
-rw-r--r--src/de/lmu/ifi/dbs/elki/workflow/InputStep.java24
-rw-r--r--src/de/lmu/ifi/dbs/elki/workflow/LoggingStep.java64
-rw-r--r--src/de/lmu/ifi/dbs/elki/workflow/OutputStep.java38
-rw-r--r--src/de/lmu/ifi/dbs/elki/workflow/WorkflowStep.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/workflow/package-info.java2
-rw-r--r--src/tutorial/clustering/NaiveAgglomerativeHierarchicalClustering1.java241
-rw-r--r--src/tutorial/clustering/NaiveAgglomerativeHierarchicalClustering2.java278
-rw-r--r--src/tutorial/clustering/NaiveAgglomerativeHierarchicalClustering3.java398
-rw-r--r--src/tutorial/clustering/NaiveAgglomerativeHierarchicalClustering4.java343
-rw-r--r--src/tutorial/clustering/SameSizeKMeansAlgorithm.java20
-rw-r--r--src/tutorial/clustering/package-info.java2
-rw-r--r--src/tutorial/distancefunction/MultiLPNorm.java4
-rw-r--r--src/tutorial/distancefunction/TutorialDistanceFunction.java20
-rw-r--r--src/tutorial/distancefunction/package-info.java2
-rw-r--r--src/tutorial/outlier/DistanceStddevOutlier.java12
-rw-r--r--src/tutorial/outlier/ODIN.java196
-rw-r--r--src/tutorial/outlier/SimpleScoreDumper.java53
-rw-r--r--src/tutorial/package-info.java2
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/AbstractSimpleAlgorithmTest.java30
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/TestKNNJoin.java28
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestDeLiCluResults.java3
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/TestCASHResults.java2
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/TestNaiveAgglomerativeHierarchicalClustering.java140
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/TestSLINKResults.java (renamed from test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestSLINKResults.java)14
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/TestKMeansBisecting.java90
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/TestKMeansQualityMeasure.java110
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/TestKMeansResults.java6
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/TestPROCLUSResults.java14
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/TestINFLO.java (renamed from test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestINFLO.java)3
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/TestLDOF.java (renamed from test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestLDOF.java)3
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/TestLOCI.java (renamed from test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestLOCI.java)3
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/TestLOF.java (renamed from test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestLOF.java)5
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/TestLoOP.java (renamed from test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestLoOP.java)3
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/TestOnlineLOF.java (renamed from test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestOnlineLOF.java)13
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/TestFeatureBagging.java6
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/TestHiCS.java14
-rw-r--r--test/de/lmu/ifi/dbs/elki/data/spatial/TestPolygon.java6
-rw-r--r--test/de/lmu/ifi/dbs/elki/datasource/parser/TestTermFrequencyParser.java129
-rw-r--r--test/de/lmu/ifi/dbs/elki/distance/distancefunction/SpatialPrimitiveDistanceFunctionTest.java10
-rw-r--r--test/de/lmu/ifi/dbs/elki/distance/distancefunction/strings/LevenshteinDistanceFunctionTest.java66
-rw-r--r--test/de/lmu/ifi/dbs/elki/distance/distancefunction/strings/NormalizedLevenshteinDistanceFunctionTest.java66
-rw-r--r--test/de/lmu/ifi/dbs/elki/evaluation/roc/TestComputeROC.java30
-rw-r--r--test/de/lmu/ifi/dbs/elki/index/TestIndexStructures.java29
-rw-r--r--test/de/lmu/ifi/dbs/elki/index/preprocessed/TestMaterializedKNNAndRKNNPreprocessor.java36
-rw-r--r--test/de/lmu/ifi/dbs/elki/logging/TestOutputStreamLogger.java1
-rw-r--r--test/de/lmu/ifi/dbs/elki/math/TestKernelDensityFitting.java6
-rw-r--r--test/de/lmu/ifi/dbs/elki/math/TestLevenbergMarquardtGaussianFitting.java14
-rw-r--r--test/de/lmu/ifi/dbs/elki/math/TestMathUtil.java24
-rw-r--r--test/de/lmu/ifi/dbs/elki/math/TestSlidingVariance.java68
-rw-r--r--test/de/lmu/ifi/dbs/elki/math/TestStatisticalMoments.java120
-rw-r--r--test/de/lmu/ifi/dbs/elki/math/geodesy/TestEarthModels.java385
-rw-r--r--test/de/lmu/ifi/dbs/elki/math/statistics/distribution/AbstractDistributionTest.java3
-rw-r--r--test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestBetaDistribution.java32
-rw-r--r--test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestExponentiallyModifiedGaussianDistribution.java110
-rw-r--r--test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestGammaDistribution.java19
-rw-r--r--test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestGeneralizedExtremeValueDistribution.java1294
-rw-r--r--test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestGeneralizedLogisticDistribution.java364
-rw-r--r--test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestGumbelDistribution.java672
-rw-r--r--test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestLogGammaAlternateDistribution.java672
-rw-r--r--test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestLogNormalDistribution.java518
-rw-r--r--test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestLogisticDistribution.java210
-rw-r--r--test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestWeibullDistribution.java1291
-rw-r--r--test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestDoubleObjectHeaps.java (renamed from test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestDoubleObjHeaps.java)6
-rw-r--r--test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestHeap.java11
-rw-r--r--test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestHeapPerformance.java35
-rw-r--r--test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestIntegerHeap.java232
-rw-r--r--test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestIntegerMinHeapPerformance.java124
-rw-r--r--test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestTiedTopBoundedHeap.java14
-rw-r--r--test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestTiedTopBoundedUpdatableHeap.java6
-rw-r--r--test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestTopBoundedHeap.java4
-rw-r--r--test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestUpdatableHeap.java8
-rw-r--r--test/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/TestHashMapHierarchy.java85
1923 files changed, 65689 insertions, 20880 deletions
diff --git a/LICENSE.txt b/LICENSE.txt
index 50b0b4d9..af4068b6 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,6 +1,6 @@
ELKI: Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2011 Lehr- und Forschungseinheit für Datenbanksysteme, Ludwig-Maximilians-Universität München
+Copyright (C) 2013 Lehr- und Forschungseinheit für Datenbanksysteme, Ludwig-Maximilians-Universität München
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
diff --git a/debian/changelog b/debian/changelog
index 09cdebf4..420cb62a 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+elki (0.6.0~beta2-1) unstable; urgency=low
+
+ * New upstream beta release.
+ * 3DPC extension is not yet included.
+
+ -- Erich Schubert <erich@debian.org> Tue, 29 Oct 2013 20:02:37 +0100
+
elki (0.5.5-2) unstable; urgency=low
* Fix package name in suggests: s/openjdk7-jdk/openjdk-7-jdk/
diff --git a/debian/patches/build.patch b/debian/patches/build.patch
index 4b378aef..c3173a85 100644
--- a/debian/patches/build.patch
+++ b/debian/patches/build.patch
@@ -1,7 +1,7 @@
-Index: elki-0.5.0~beta2/build.xml
+Index: elki-0.6.0~beta2/build.xml
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ elki-0.5.0~beta2/build.xml 2012-05-03 06:41:16.000000000 +0200
++++ elki-0.6.0~beta2/build.xml 2012-05-03 06:41:16.000000000 +0200
@@ -0,0 +1,58 @@
+<project name="ELKI" default="dist" basedir=".">
+ <property name="src" location="src"/>
@@ -10,7 +10,7 @@ Index: elki-0.5.0~beta2/build.xml
+ <property name="elki" value="de.lmu.ifi.dbs.elki"/>
+ <property name="title" value="ELKI: Environment for DeveLoping KDD-Applications Supported by Index-Structures"/>
+ <property name="url" value="http://elki.dbs.ifi.lmu.de/"/>
-+ <property name="version" value="0.5.0~beta2"/>
++ <property name="version" value="0.6.0~beta2"/>
+
+ <target name="init">
+ <!-- Create the build directory structure used by compile -->
@@ -19,7 +19,7 @@ Index: elki-0.5.0~beta2/build.xml
+
+ <target name="compile" depends="init">
+ <!-- Compile the java code from ${src} into ${build} -->
-+ <javac destdir="${build}" includeantruntime="false" deprecation="false" debug="false" optimize="true" source="1.6" target="1.6" debuglevel="" encoding="UTF-8">
++ <javac destdir="${build}" includeantruntime="false" deprecation="false" debug="false" optimize="true" source="1.7" target="1.7" debuglevel="" encoding="UTF-8">
+ <compilerarg value="-Xlint:all" />
+ <classpath>
+ <pathelement path="${src}" />
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.Algorithm b/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.Algorithm
index 25c3f6e9..de720fef 100644
--- a/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.Algorithm
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.Algorithm
@@ -1,17 +1,22 @@
de.lmu.ifi.dbs.elki.algorithm.NullAlgorithm
+de.lmu.ifi.dbs.elki.algorithm.clustering.CanopyPreClustering
de.lmu.ifi.dbs.elki.algorithm.clustering.DBSCAN
de.lmu.ifi.dbs.elki.algorithm.clustering.DeLiClu
de.lmu.ifi.dbs.elki.algorithm.clustering.EM
de.lmu.ifi.dbs.elki.algorithm.clustering.gdbscan.GeneralizedDBSCAN
+de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical.ExtractFlatClusteringFromHierarchy
+de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical.NaiveAgglomerativeHierarchicalClustering
+de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical.SLINK
de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMeansLloyd
de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMeansMacQueen
de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMediansLloyd
de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMedoidsPAM
de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMedoidsEM
+de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.BestOfMultipleKMeans
+de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMeansBisecting
de.lmu.ifi.dbs.elki.algorithm.clustering.NaiveMeanShiftClustering
de.lmu.ifi.dbs.elki.algorithm.clustering.OPTICSXi
de.lmu.ifi.dbs.elki.algorithm.clustering.OPTICS
-de.lmu.ifi.dbs.elki.algorithm.clustering.SLINK
de.lmu.ifi.dbs.elki.algorithm.clustering.SNNClustering
de.lmu.ifi.dbs.elki.algorithm.clustering.correlation.CASH
de.lmu.ifi.dbs.elki.algorithm.clustering.correlation.COPAC
@@ -35,7 +40,6 @@ de.lmu.ifi.dbs.elki.algorithm.clustering.trivial.ByLabelOrAllInOneClustering
de.lmu.ifi.dbs.elki.algorithm.outlier.ABOD
de.lmu.ifi.dbs.elki.algorithm.outlier.AggarwalYuEvolutionary
de.lmu.ifi.dbs.elki.algorithm.outlier.AggarwalYuNaive
-de.lmu.ifi.dbs.elki.algorithm.outlier.ALOCI
de.lmu.ifi.dbs.elki.algorithm.outlier.COP
de.lmu.ifi.dbs.elki.algorithm.outlier.DBOutlierDetection
de.lmu.ifi.dbs.elki.algorithm.outlier.DBOutlierScore
@@ -43,20 +47,23 @@ de.lmu.ifi.dbs.elki.algorithm.outlier.EMOutlier
de.lmu.ifi.dbs.elki.algorithm.outlier.GaussianModel
de.lmu.ifi.dbs.elki.algorithm.outlier.GaussianUniformMixture
de.lmu.ifi.dbs.elki.algorithm.outlier.HilOut
-de.lmu.ifi.dbs.elki.algorithm.outlier.INFLO
de.lmu.ifi.dbs.elki.algorithm.outlier.KNNOutlier
de.lmu.ifi.dbs.elki.algorithm.outlier.KNNWeightOutlier
-de.lmu.ifi.dbs.elki.algorithm.outlier.LDF
-de.lmu.ifi.dbs.elki.algorithm.outlier.LDOF
-de.lmu.ifi.dbs.elki.algorithm.outlier.LOCI
-de.lmu.ifi.dbs.elki.algorithm.outlier.LOF
-de.lmu.ifi.dbs.elki.algorithm.outlier.LoOP
+de.lmu.ifi.dbs.elki.algorithm.outlier.ODIN
de.lmu.ifi.dbs.elki.algorithm.outlier.OPTICSOF
de.lmu.ifi.dbs.elki.algorithm.outlier.ReferenceBasedOutlierDetection
-de.lmu.ifi.dbs.elki.algorithm.outlier.OnlineLOF
-de.lmu.ifi.dbs.elki.algorithm.outlier.SimpleLOF
-de.lmu.ifi.dbs.elki.algorithm.outlier.SimpleKernelDensityLOF
de.lmu.ifi.dbs.elki.algorithm.outlier.SimpleCOP
+de.lmu.ifi.dbs.elki.algorithm.outlier.lof.ALOCI
+de.lmu.ifi.dbs.elki.algorithm.outlier.lof.FlexibleLOF
+de.lmu.ifi.dbs.elki.algorithm.outlier.lof.INFLO
+de.lmu.ifi.dbs.elki.algorithm.outlier.lof.LDF
+de.lmu.ifi.dbs.elki.algorithm.outlier.lof.LDOF
+de.lmu.ifi.dbs.elki.algorithm.outlier.lof.LOCI
+de.lmu.ifi.dbs.elki.algorithm.outlier.lof.LOF
+de.lmu.ifi.dbs.elki.algorithm.outlier.lof.LoOP
+de.lmu.ifi.dbs.elki.algorithm.outlier.lof.OnlineLOF
+de.lmu.ifi.dbs.elki.algorithm.outlier.lof.SimplifiedLOF
+de.lmu.ifi.dbs.elki.algorithm.outlier.lof.SimpleKernelDensityLOF
de.lmu.ifi.dbs.elki.algorithm.outlier.subspace.OUTRES
de.lmu.ifi.dbs.elki.algorithm.outlier.subspace.OutRankS1
de.lmu.ifi.dbs.elki.algorithm.outlier.subspace.SOD
@@ -80,6 +87,7 @@ de.lmu.ifi.dbs.elki.algorithm.outlier.trivial.ByLabelOutlier
de.lmu.ifi.dbs.elki.algorithm.outlier.trivial.TrivialAllOutlier
de.lmu.ifi.dbs.elki.algorithm.outlier.trivial.TrivialNoOutlier
de.lmu.ifi.dbs.elki.algorithm.outlier.trivial.TrivialGeneratedOutlier
+de.lmu.ifi.dbs.elki.algorithm.outlier.trivial.TrivialAverageCoordinateOutlier
de.lmu.ifi.dbs.elki.algorithm.statistics.AddSingleScale
de.lmu.ifi.dbs.elki.algorithm.statistics.AveragePrecisionAtK
de.lmu.ifi.dbs.elki.algorithm.statistics.EvaluateRankingQuality
@@ -93,5 +101,11 @@ de.lmu.ifi.dbs.elki.algorithm.KNNJoin
de.lmu.ifi.dbs.elki.algorithm.MaterializeDistances
de.lmu.ifi.dbs.elki.algorithm.benchmark.KNNBenchmarkAlgorithm
de.lmu.ifi.dbs.elki.algorithm.benchmark.RangeQueryBenchmarkAlgorithm
+de.lmu.ifi.dbs.elki.algorithm.benchmark.ValidateApproximativeKNNIndex
+tutorial.clustering.NaiveAgglomerativeHierarchicalClustering1
+tutorial.clustering.NaiveAgglomerativeHierarchicalClustering2
+tutorial.clustering.NaiveAgglomerativeHierarchicalClustering3
+tutorial.clustering.NaiveAgglomerativeHierarchicalClustering4
tutorial.clustering.SameSizeKMeansAlgorithm
tutorial.outlier.DistanceStddevOutlier
+tutorial.outlier.ODIN \ No newline at end of file
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm b/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.DistanceBasedAlgorithm
index 217954ca..8189b637 100644
--- a/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.DistanceBasedAlgorithm
@@ -1,13 +1,20 @@
de.lmu.ifi.dbs.elki.algorithm.KNNDistanceOrder
de.lmu.ifi.dbs.elki.algorithm.KNNJoin
de.lmu.ifi.dbs.elki.algorithm.MaterializeDistances
+de.lmu.ifi.dbs.elki.algorithm.clustering.CanopyPreClustering
de.lmu.ifi.dbs.elki.algorithm.clustering.DBSCAN
de.lmu.ifi.dbs.elki.algorithm.clustering.NaiveMeanShiftClustering
de.lmu.ifi.dbs.elki.algorithm.clustering.OPTICS
de.lmu.ifi.dbs.elki.algorithm.clustering.DeLiClu
-de.lmu.ifi.dbs.elki.algorithm.clustering.SLINK
+de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical.NaiveAgglomerativeHierarchicalClustering
+de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical.SLINK
+de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMeansLloyd
+de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMeansMacQueen
+de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMediansLloyd
de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMedoidsPAM
de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMedoidsEM
+de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.BestOfMultipleKMeans
+de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMeansBisecting
de.lmu.ifi.dbs.elki.algorithm.clustering.correlation.HiCO
de.lmu.ifi.dbs.elki.algorithm.clustering.subspace.HiSC
de.lmu.ifi.dbs.elki.algorithm.outlier.ABOD
@@ -15,16 +22,18 @@ de.lmu.ifi.dbs.elki.algorithm.outlier.COP
de.lmu.ifi.dbs.elki.algorithm.outlier.DBOutlierDetection
de.lmu.ifi.dbs.elki.algorithm.outlier.DBOutlierScore
de.lmu.ifi.dbs.elki.algorithm.outlier.HilOut
-de.lmu.ifi.dbs.elki.algorithm.outlier.INFLO
de.lmu.ifi.dbs.elki.algorithm.outlier.KNNOutlier
de.lmu.ifi.dbs.elki.algorithm.outlier.KNNWeightOutlier
-de.lmu.ifi.dbs.elki.algorithm.outlier.LDF
-de.lmu.ifi.dbs.elki.algorithm.outlier.LDOF
-de.lmu.ifi.dbs.elki.algorithm.outlier.LOCI
+de.lmu.ifi.dbs.elki.algorithm.outlier.ODIN
de.lmu.ifi.dbs.elki.algorithm.outlier.OPTICSOF
-de.lmu.ifi.dbs.elki.algorithm.outlier.SimpleLOF
-de.lmu.ifi.dbs.elki.algorithm.outlier.SimpleKernelDensityLOF
de.lmu.ifi.dbs.elki.algorithm.outlier.SimpleCOP
+de.lmu.ifi.dbs.elki.algorithm.outlier.lof.LOF
+de.lmu.ifi.dbs.elki.algorithm.outlier.lof.INFLO
+de.lmu.ifi.dbs.elki.algorithm.outlier.lof.LDF
+de.lmu.ifi.dbs.elki.algorithm.outlier.lof.LDOF
+de.lmu.ifi.dbs.elki.algorithm.outlier.lof.LOCI
+de.lmu.ifi.dbs.elki.algorithm.outlier.lof.SimplifiedLOF
+de.lmu.ifi.dbs.elki.algorithm.outlier.lof.SimpleKernelDensityLOF
de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.CTLuGLSBackwardSearchAlgorithm
de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.CTLuRandomWalkEC
de.lmu.ifi.dbs.elki.algorithm.statistics.AveragePrecisionAtK
@@ -33,4 +42,11 @@ de.lmu.ifi.dbs.elki.algorithm.statistics.DistanceStatisticsWithClasses
de.lmu.ifi.dbs.elki.algorithm.statistics.EvaluateRankingQuality
de.lmu.ifi.dbs.elki.algorithm.benchmark.KNNBenchmarkAlgorithm
de.lmu.ifi.dbs.elki.algorithm.benchmark.RangeQueryBenchmarkAlgorithm
-tutorial.outlier.DistanceStddevOutlier \ No newline at end of file
+de.lmu.ifi.dbs.elki.algorithm.benchmark.ValidateApproximativeKNNIndex
+tutorial.clustering.NaiveAgglomerativeHierarchicalClustering1
+tutorial.clustering.NaiveAgglomerativeHierarchicalClustering2
+tutorial.clustering.NaiveAgglomerativeHierarchicalClustering3
+tutorial.clustering.NaiveAgglomerativeHierarchicalClustering4
+tutorial.clustering.SameSizeKMeansAlgorithm
+tutorial.outlier.DistanceStddevOutlier
+tutorial.outlier.ODIN \ No newline at end of file
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.ClusteringAlgorithm b/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.ClusteringAlgorithm
index 678db72f..6d96c265 100644
--- a/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.ClusteringAlgorithm
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.ClusteringAlgorithm
@@ -1,11 +1,15 @@
+de.lmu.ifi.dbs.elki.algorithm.clustering.CanopyPreClustering
de.lmu.ifi.dbs.elki.algorithm.clustering.DBSCAN
de.lmu.ifi.dbs.elki.algorithm.clustering.EM
de.lmu.ifi.dbs.elki.algorithm.clustering.gdbscan.GeneralizedDBSCAN
+de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical.ExtractFlatClusteringFromHierarchy
de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMeansLloyd
de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMeansMacQueen
de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMediansLloyd
de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMedoidsPAM
de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMedoidsEM
+de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.BestOfMultipleKMeans
+de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMeansBisecting
de.lmu.ifi.dbs.elki.algorithm.clustering.NaiveMeanShiftClustering
de.lmu.ifi.dbs.elki.algorithm.clustering.OPTICSXi
de.lmu.ifi.dbs.elki.algorithm.clustering.SNNClustering
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical.HierarchicalClusteringAlgorithm b/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical.HierarchicalClusteringAlgorithm
new file mode 100644
index 00000000..e9d9750f
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical.HierarchicalClusteringAlgorithm
@@ -0,0 +1,3 @@
+de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical.NaiveAgglomerativeHierarchicalClustering
+de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical.SLINK
+tutorial.clustering.NaiveAgglomerativeHierarchicalClustering4 \ No newline at end of file
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical.LinkageMethod b/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical.LinkageMethod
new file mode 100644
index 00000000..eb51137a
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical.LinkageMethod
@@ -0,0 +1,7 @@
+de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical.WardLinkageMethod
+de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical.SingleLinkageMethod
+de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical.CompleteLinkageMethod
+de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical.GroupAverageLinkageMethod
+de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical.WeightedAverageLinkageMethod
+de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical.CentroidLinkageMethod
+de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical.MedianLinkageMethod
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMeans b/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMeans
new file mode 100644
index 00000000..3fe49ec6
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMeans
@@ -0,0 +1,6 @@
+de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMeansLloyd
+de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMeansMacQueen
+de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMediansLloyd
+de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.BestOfMultipleKMeans
+de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMeansBisecting
+tutorial.clustering.SameSizeKMeansAlgorithm \ No newline at end of file
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMeansInitialization b/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMeansInitialization
index 5734e7bf..dd91455e 100644
--- a/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMeansInitialization
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMeansInitialization
@@ -1,5 +1,7 @@
-de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.RandomlyGeneratedInitialMeans
de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.RandomlyChosenInitialMeans
de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.FirstKInitialMeans
de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMeansPlusPlusInitialMeans
-de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.PAMInitialMeans \ No newline at end of file
+de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.SampleKMeansInitialization
+de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.FarthestPointsInitialMeans
+de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.RandomlyGeneratedInitialMeans
+de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.PAMInitialMeans
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMedoidsInitialization b/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMedoidsInitialization
index c75b1cf1..dffb5448 100644
--- a/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMedoidsInitialization
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMedoidsInitialization
@@ -1,4 +1,5 @@
de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.PAMInitialMeans
de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.RandomlyChosenInitialMeans
de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.FirstKInitialMeans
-de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMeansPlusPlusInitialMeans \ No newline at end of file
+de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMeansPlusPlusInitialMeans
+de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.FarthestPointsInitialMeans \ No newline at end of file
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.quality.KMeansQualityMeasure b/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.quality.KMeansQualityMeasure
new file mode 100644
index 00000000..4785c3f9
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.quality.KMeansQualityMeasure
@@ -0,0 +1,2 @@
+de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.quality.WithinClusterVarianceQualityMeasure
+de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.quality.WithinClusterMeanDistanceQualityMeasure
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.outlier.OutlierAlgorithm b/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.outlier.OutlierAlgorithm
index b8ebe564..f9924515 100644
--- a/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.outlier.OutlierAlgorithm
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.outlier.OutlierAlgorithm
@@ -1,7 +1,6 @@
de.lmu.ifi.dbs.elki.algorithm.outlier.ABOD
de.lmu.ifi.dbs.elki.algorithm.outlier.AggarwalYuEvolutionary
de.lmu.ifi.dbs.elki.algorithm.outlier.AggarwalYuNaive
-de.lmu.ifi.dbs.elki.algorithm.outlier.ALOCI
de.lmu.ifi.dbs.elki.algorithm.outlier.COP
de.lmu.ifi.dbs.elki.algorithm.outlier.DBOutlierDetection
de.lmu.ifi.dbs.elki.algorithm.outlier.DBOutlierScore
@@ -9,19 +8,22 @@ de.lmu.ifi.dbs.elki.algorithm.outlier.EMOutlier
de.lmu.ifi.dbs.elki.algorithm.outlier.GaussianModel
de.lmu.ifi.dbs.elki.algorithm.outlier.GaussianUniformMixture
de.lmu.ifi.dbs.elki.algorithm.outlier.HilOut
-de.lmu.ifi.dbs.elki.algorithm.outlier.INFLO
de.lmu.ifi.dbs.elki.algorithm.outlier.KNNOutlier
de.lmu.ifi.dbs.elki.algorithm.outlier.KNNWeightOutlier
-de.lmu.ifi.dbs.elki.algorithm.outlier.LDF
-de.lmu.ifi.dbs.elki.algorithm.outlier.LDOF
-de.lmu.ifi.dbs.elki.algorithm.outlier.LOCI
-de.lmu.ifi.dbs.elki.algorithm.outlier.LOF
-de.lmu.ifi.dbs.elki.algorithm.outlier.LoOP
+de.lmu.ifi.dbs.elki.algorithm.outlier.lof.ALOCI
+de.lmu.ifi.dbs.elki.algorithm.outlier.lof.FlexibleLOF
+de.lmu.ifi.dbs.elki.algorithm.outlier.lof.INFLO
+de.lmu.ifi.dbs.elki.algorithm.outlier.lof.LDF
+de.lmu.ifi.dbs.elki.algorithm.outlier.lof.LDOF
+de.lmu.ifi.dbs.elki.algorithm.outlier.lof.LOCI
+de.lmu.ifi.dbs.elki.algorithm.outlier.lof.LOF
+de.lmu.ifi.dbs.elki.algorithm.outlier.lof.LoOP
+de.lmu.ifi.dbs.elki.algorithm.outlier.lof.OnlineLOF
+de.lmu.ifi.dbs.elki.algorithm.outlier.lof.SimplifiedLOF
+de.lmu.ifi.dbs.elki.algorithm.outlier.lof.SimpleKernelDensityLOF
+de.lmu.ifi.dbs.elki.algorithm.outlier.ODIN
de.lmu.ifi.dbs.elki.algorithm.outlier.OPTICSOF
de.lmu.ifi.dbs.elki.algorithm.outlier.ReferenceBasedOutlierDetection
-de.lmu.ifi.dbs.elki.algorithm.outlier.OnlineLOF
-de.lmu.ifi.dbs.elki.algorithm.outlier.SimpleLOF
-de.lmu.ifi.dbs.elki.algorithm.outlier.SimpleKernelDensityLOF
de.lmu.ifi.dbs.elki.algorithm.outlier.SimpleCOP
de.lmu.ifi.dbs.elki.algorithm.outlier.subspace.OUTRES
de.lmu.ifi.dbs.elki.algorithm.outlier.subspace.OutRankS1
@@ -46,4 +48,6 @@ de.lmu.ifi.dbs.elki.algorithm.outlier.trivial.ByLabelOutlier
de.lmu.ifi.dbs.elki.algorithm.outlier.trivial.TrivialAllOutlier
de.lmu.ifi.dbs.elki.algorithm.outlier.trivial.TrivialNoOutlier
de.lmu.ifi.dbs.elki.algorithm.outlier.trivial.TrivialGeneratedOutlier
-tutorial.outlier.DistanceStddevOutlier \ No newline at end of file
+de.lmu.ifi.dbs.elki.algorithm.outlier.trivial.TrivialAverageCoordinateOutlier
+tutorial.outlier.DistanceStddevOutlier
+tutorial.outlier.ODIN \ No newline at end of file
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.application.AbstractApplication b/src/META-INF/elki/de.lmu.ifi.dbs.elki.application.AbstractApplication
index b2eb6445..3ff2c408 100644
--- a/src/META-INF/elki/de.lmu.ifi.dbs.elki.application.AbstractApplication
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.application.AbstractApplication
@@ -1,12 +1,14 @@
de.lmu.ifi.dbs.elki.gui.minigui.MiniGUI
de.lmu.ifi.dbs.elki.application.KDDCLIApplication
+de.lmu.ifi.dbs.elki.gui.multistep.MultiStepGUI
de.lmu.ifi.dbs.elki.application.GeneratorXMLSpec
de.lmu.ifi.dbs.elki.application.ConvertToBundleApplication
de.lmu.ifi.dbs.elki.application.cache.CacheDoubleDistanceInOnDiskMatrix
de.lmu.ifi.dbs.elki.application.cache.CacheFloatDistanceInOnDiskMatrix
+de.lmu.ifi.dbs.elki.application.cache.CacheDoubleDistanceKNNLists
+de.lmu.ifi.dbs.elki.application.cache.CacheDoubleDistanceRangeQueries
de.lmu.ifi.dbs.elki.application.geo.VisualizeGeodesicDistances
de.lmu.ifi.dbs.elki.application.greedyensemble.ComputeKNNOutlierScores
de.lmu.ifi.dbs.elki.application.greedyensemble.GreedyEnsembleExperiment
de.lmu.ifi.dbs.elki.application.greedyensemble.VisualizePairwiseGainMatrix
-de.lmu.ifi.dbs.elki.application.visualization.KNNExplorer
de.lmu.ifi.dbs.elki.application.ComputeSingleColorHistogram
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.data.projection.Projection b/src/META-INF/elki/de.lmu.ifi.dbs.elki.data.projection.Projection
new file mode 100644
index 00000000..2f8fa9b7
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.data.projection.Projection
@@ -0,0 +1,5 @@
+de.lmu.ifi.dbs.elki.data.projection.FeatureSelection
+de.lmu.ifi.dbs.elki.data.projection.NumericalFeatureSelection
+de.lmu.ifi.dbs.elki.data.projection.RandomProjection
+de.lmu.ifi.dbs.elki.data.projection.LatLngToECEFProjection
+de.lmu.ifi.dbs.elki.data.projection.LngLatToECEFProjection \ No newline at end of file
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.datasource.filter.ObjectFilter b/src/META-INF/elki/de.lmu.ifi.dbs.elki.datasource.filter.ObjectFilter
index 4ae2cece..3ac4a5ac 100644
--- a/src/META-INF/elki/de.lmu.ifi.dbs.elki.datasource.filter.ObjectFilter
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.datasource.filter.ObjectFilter
@@ -1,22 +1,31 @@
de.lmu.ifi.dbs.elki.datasource.filter.FixedDBIDsFilter
de.lmu.ifi.dbs.elki.datasource.filter.NoOpFilter
de.lmu.ifi.dbs.elki.datasource.filter.ClassLabelFilter
+de.lmu.ifi.dbs.elki.datasource.filter.ClassLabelFromPatternFilter
de.lmu.ifi.dbs.elki.datasource.filter.ExternalIDFilter
de.lmu.ifi.dbs.elki.datasource.filter.SparseVectorFieldFilter
de.lmu.ifi.dbs.elki.datasource.filter.ByLabelFilter
de.lmu.ifi.dbs.elki.datasource.filter.RandomSamplingStreamFilter
de.lmu.ifi.dbs.elki.datasource.filter.ShuffleObjectsFilter
de.lmu.ifi.dbs.elki.datasource.filter.SortByLabelFilter
+de.lmu.ifi.dbs.elki.datasource.filter.NaNFilter
de.lmu.ifi.dbs.elki.datasource.filter.NoMissingValuesFilter
de.lmu.ifi.dbs.elki.datasource.filter.HistogramJitterFilter
de.lmu.ifi.dbs.elki.datasource.filter.SplitNumberVectorFilter
-de.lmu.ifi.dbs.elki.datasource.filter.normalization.AttributeWiseErfNormalization
de.lmu.ifi.dbs.elki.datasource.filter.normalization.AttributeWiseMinMaxNormalization
de.lmu.ifi.dbs.elki.datasource.filter.normalization.AttributeWiseVarianceNormalization
+de.lmu.ifi.dbs.elki.datasource.filter.normalization.AttributeWiseMADNormalization
+de.lmu.ifi.dbs.elki.datasource.filter.normalization.AttributeWiseErfNormalization
+de.lmu.ifi.dbs.elki.datasource.filter.normalization.AttributeWiseCDFNormalization
de.lmu.ifi.dbs.elki.datasource.filter.normalization.LengthNormalization
de.lmu.ifi.dbs.elki.datasource.filter.normalization.InverseDocumentFrequencyNormalization
de.lmu.ifi.dbs.elki.datasource.filter.normalization.RankTieNormalization
de.lmu.ifi.dbs.elki.datasource.filter.normalization.TFIDFNormalization
de.lmu.ifi.dbs.elki.datasource.filter.transform.GlobalPrincipalComponentAnalysisTransform
+de.lmu.ifi.dbs.elki.datasource.filter.transform.ClassicMultidimensionalScalingTransform
+de.lmu.ifi.dbs.elki.datasource.filter.transform.LinearDiscriminantAnalysisFilter
de.lmu.ifi.dbs.elki.datasource.filter.transform.NumberVectorFeatureSelectionFilter
de.lmu.ifi.dbs.elki.datasource.filter.transform.NumberVectorRandomFeatureSelectionFilter
+de.lmu.ifi.dbs.elki.datasource.filter.transform.LatLngToECEFFilter
+de.lmu.ifi.dbs.elki.datasource.filter.transform.LngLatToECEFFilter
+de.lmu.ifi.dbs.elki.datasource.filter.transform.ProjectionFilter \ No newline at end of file
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.datasource.filter.StreamFilter b/src/META-INF/elki/de.lmu.ifi.dbs.elki.datasource.filter.StreamFilter
index 4c4a71cc..00e42cc7 100644
--- a/src/META-INF/elki/de.lmu.ifi.dbs.elki.datasource.filter.StreamFilter
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.datasource.filter.StreamFilter
@@ -1,9 +1,14 @@
de.lmu.ifi.dbs.elki.datasource.filter.NoOpFilter
de.lmu.ifi.dbs.elki.datasource.filter.FixedDBIDsFilter
de.lmu.ifi.dbs.elki.datasource.filter.ByLabelFilter
+de.lmu.ifi.dbs.elki.datasource.filter.ClassLabelFromPatternFilter
+de.lmu.ifi.dbs.elki.datasource.filter.NaNFilter
de.lmu.ifi.dbs.elki.datasource.filter.NoMissingValuesFilter
de.lmu.ifi.dbs.elki.datasource.filter.RandomSamplingStreamFilter
de.lmu.ifi.dbs.elki.datasource.filter.HistogramJitterFilter
de.lmu.ifi.dbs.elki.datasource.filter.normalization.LengthNormalization
de.lmu.ifi.dbs.elki.datasource.filter.transform.NumberVectorFeatureSelectionFilter
-de.lmu.ifi.dbs.elki.datasource.filter.transform.NumberVectorRandomFeatureSelectionFilter \ No newline at end of file
+de.lmu.ifi.dbs.elki.datasource.filter.transform.NumberVectorRandomFeatureSelectionFilter
+de.lmu.ifi.dbs.elki.datasource.filter.transform.LatLngToECEFFilter
+de.lmu.ifi.dbs.elki.datasource.filter.transform.LngLatToECEFFilter
+de.lmu.ifi.dbs.elki.datasource.filter.transform.ProjectionFilter
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.datasource.parser.Parser b/src/META-INF/elki/de.lmu.ifi.dbs.elki.datasource.parser.Parser
index 3d005531..f8f352f1 100644
--- a/src/META-INF/elki/de.lmu.ifi.dbs.elki.datasource.parser.Parser
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.datasource.parser.Parser
@@ -5,6 +5,7 @@ de.lmu.ifi.dbs.elki.datasource.parser.SparseBitVectorLabelParser
de.lmu.ifi.dbs.elki.datasource.parser.TermFrequencyParser
de.lmu.ifi.dbs.elki.datasource.parser.BitVectorLabelParser
de.lmu.ifi.dbs.elki.datasource.parser.SimplePolygonParser
+de.lmu.ifi.dbs.elki.datasource.parser.StringParser
# deprecated: de.lmu.ifi.dbs.elki.datasource.parser.DoubleVectorLabelParser
# deprecated: de.lmu.ifi.dbs.elki.datasource.parser.FloatVectorLabelParser
# deprecated: de.lmu.ifi.dbs.elki.datasource.parser.SparseFloatVectorLabelParser \ No newline at end of file
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction
index 249db041..14892064 100644
--- a/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction
@@ -1,28 +1,34 @@
-de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.ManhattanDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.LPNormDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.MaximumDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.MinimumDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.ManhattanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.LPNormDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.MaximumDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.MinimumDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.ArcCosineDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.CosineDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.RandomStableDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.SquaredEuclideanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SquaredEuclideanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.BrayCurtisDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.CanberraDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.JeffreyDivergenceDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.WeightedCanberraDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.ClarkDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.Kulczynski1DistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.LorentzianDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.SharedNearestNeighborJaccardDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.LocallyWeightedDistanceFunction
# de.lmu.ifi.dbs.elki.distance.distancefunction.WeightedDistanceFunction
# de.lmu.ifi.dbs.elki.distance.distancefunction.MinKDistance
# de.lmu.ifi.dbs.elki.distance.distancefunction.ProxyDistanceFunction
-# de.lmu.ifi.dbs.elki.distance.distancefunction.WeightedLPNormDistanceFunction
-# de.lmu.ifi.dbs.elki.distance.distancefunction.WeightedSquaredEuclideanDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.SparseEuclideanDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.SparseManhattanDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.SparseLPNormDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.SparseMaximumDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.adapter.SimilarityAdapterArccos
-de.lmu.ifi.dbs.elki.distance.distancefunction.adapter.SimilarityAdapterLn
-de.lmu.ifi.dbs.elki.distance.distancefunction.adapter.SimilarityAdapterLinear
+# de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.WeightedLPNormDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.WeightedEuclideanDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.WeightedManhattanDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.WeightedSquaredEuclideanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SparseEuclideanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SparseManhattanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SparseLPNormDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SparseMaximumDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.adapter.ArccosSimilarityAdapter
+de.lmu.ifi.dbs.elki.distance.distancefunction.adapter.LinearAdapterLinear
+de.lmu.ifi.dbs.elki.distance.distancefunction.adapter.LnSimilarityAdapter
de.lmu.ifi.dbs.elki.distance.distancefunction.colorhistogram.HSBHistogramQuadraticDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.colorhistogram.HistogramIntersectionDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.colorhistogram.RGBHistogramQuadraticDistanceFunction
@@ -35,10 +41,16 @@ de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.PCABasedCorrelationDis
de.lmu.ifi.dbs.elki.distance.distancefunction.geo.DimensionSelectingLatLngDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.geo.LatLngDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.geo.LngLatDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.external.DiskCacheBasedDoubleDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.external.DiskCacheBasedFloatDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.external.FileBasedDoubleDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.external.FileBasedFloatDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.histogram.HistogramMatchDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.histogram.KolmogorovSmirnovDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic.JeffreyDivergenceDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic.ChiSquaredDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic.JensenShannonDivergenceDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic.KullbackLeiblerDivergenceAsymmetricDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic.KullbackLeiblerDivergenceReverseAsymmetricDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic.SqrtJensenShannonDivergenceDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.strings.LevenshteinDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.strings.NormalizedLevenshteinDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.DimensionSelectingDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.SubspaceEuclideanDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.SubspaceLPNormDistanceFunction
@@ -50,6 +62,10 @@ de.lmu.ifi.dbs.elki.distance.distancefunction.timeseries.DTWDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.timeseries.EDRDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.timeseries.ERPDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.timeseries.LCSSDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.external.DiskCacheBasedDoubleDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.external.DiskCacheBasedFloatDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.external.FileBasedDoubleDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.external.FileBasedFloatDistanceFunction
# de.lmu.ifi.dbs.elki.distance.similarityfunction.kernel.FooKernelFunction
# de.lmu.ifi.dbs.elki.distance.similarityfunction.kernel.LinearKernelFunction
# de.lmu.ifi.dbs.elki.distance.similarityfunction.kernel.PolynomialKernelFunction
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.DoubleNorm b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.DoubleNorm
index 2714a376..69aec8b7 100644
--- a/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.DoubleNorm
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.DoubleNorm
@@ -1,14 +1,19 @@
-de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.ManhattanDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.MaximumDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.MinimumDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.LPNormDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.SquaredEuclideanDistanceFunction
-# de.lmu.ifi.dbs.elki.distance.distancefunction.WeightedLPNormDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.SparseEuclideanDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.SparseManhattanDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.SparseLPNormDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.SparseMaximumDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.ManhattanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.MaximumDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.MinimumDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.LPNormDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SquaredEuclideanDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.WeightedLPNormDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.WeightedEuclideanDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.WeightedManhattanDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.WeightedSquaredEuclideanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SparseEuclideanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SparseManhattanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SparseLPNormDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SparseMaximumDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.SubspaceEuclideanDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.SubspaceLPNormDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.SubspaceManhattanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.DimensionSelectingDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.LorentzianDistanceFunction
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.LPNormDistanceFunction b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.LPNormDistanceFunction
deleted file mode 100644
index 4cac929a..00000000
--- a/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.LPNormDistanceFunction
+++ /dev/null
@@ -1,5 +0,0 @@
-de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.ManhattanDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.LPNormDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.MaximumDistanceFunction
-# de.lmu.ifi.dbs.elki.distance.distancefunction.WeightedLPNormDistanceFunction \ No newline at end of file
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.NumberVectorDistanceFunction b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.NumberVectorDistanceFunction
index a9c0f46d..67a6ccf1 100644
--- a/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.NumberVectorDistanceFunction
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.NumberVectorDistanceFunction
@@ -1,16 +1,22 @@
-de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.ManhattanDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.LPNormDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.MaximumDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.MinimumDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.ManhattanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.LPNormDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.MaximumDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.MinimumDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.ArcCosineDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.CosineDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.SquaredEuclideanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SquaredEuclideanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.BrayCurtisDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.CanberraDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.JeffreyDivergenceDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.WeightedCanberraDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.ClarkDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.Kulczynski1DistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.LorentzianDistanceFunction
# de.lmu.ifi.dbs.elki.distance.distancefunction.WeightedDistanceFunction
-# de.lmu.ifi.dbs.elki.distance.distancefunction.WeightedLPNormDistanceFunction
-# de.lmu.ifi.dbs.elki.distance.distancefunction.WeightedSquaredEuclideanDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.WeightedLPNormDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.WeightedEuclideanDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.WeightedManhattanDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.WeightedSquaredEuclideanDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.colorhistogram.HSBHistogramQuadraticDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.colorhistogram.HistogramIntersectionDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.colorhistogram.RGBHistogramQuadraticDistanceFunction
@@ -21,6 +27,15 @@ de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.SquaredPearsonCorrelat
de.lmu.ifi.dbs.elki.distance.distancefunction.geo.DimensionSelectingLatLngDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.geo.LatLngDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.geo.LngLatDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.histogram.HistogramMatchDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.histogram.KolmogorovSmirnovDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic.JeffreyDivergenceDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic.ChiSquaredDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic.JensenShannonDivergenceDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic.KullbackLeiblerDivergenceAsymmetricDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic.KullbackLeiblerDivergenceReverseAsymmetricDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic.SqrtJensenShannonDivergenceDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.DimensionSelectingDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.timeseries.DTWDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.timeseries.EDRDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.timeseries.ERPDistanceFunction
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction
index 9dc29f22..917ac511 100644
--- a/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction
@@ -1,20 +1,26 @@
-de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.ManhattanDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.LPNormDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.ManhattanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.LPNormDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.ArcCosineDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.CosineDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.MaximumDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.MinimumDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.SquaredEuclideanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.MaximumDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.MinimumDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SquaredEuclideanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.BrayCurtisDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.CanberraDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.JeffreyDivergenceDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.WeightedCanberraDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.ClarkDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.Kulczynski1DistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.LorentzianDistanceFunction
# de.lmu.ifi.dbs.elki.distance.distancefunction.WeightedDistanceFunction
-# de.lmu.ifi.dbs.elki.distance.distancefunction.WeightedLPNormDistanceFunction
-# de.lmu.ifi.dbs.elki.distance.distancefunction.WeightedSquaredEuclideanDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.SparseEuclideanDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.SparseManhattanDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.SparseLPNormDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.SparseMaximumDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.WeightedLPNormDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.WeightedEuclideanDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.WeightedManhattanDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.WeightedSquaredEuclideanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SparseEuclideanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SparseManhattanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SparseLPNormDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SparseMaximumDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.colorhistogram.HSBHistogramQuadraticDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.colorhistogram.HistogramIntersectionDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.colorhistogram.RGBHistogramQuadraticDistanceFunction
@@ -25,6 +31,16 @@ de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.SquaredPearsonCorrelat
de.lmu.ifi.dbs.elki.distance.distancefunction.geo.DimensionSelectingLatLngDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.geo.LatLngDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.geo.LngLatDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.histogram.HistogramMatchDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.histogram.KolmogorovSmirnovDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic.JeffreyDivergenceDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic.ChiSquaredDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic.JensenShannonDivergenceDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic.KullbackLeiblerDivergenceAsymmetricDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic.KullbackLeiblerDivergenceReverseAsymmetricDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic.SqrtJensenShannonDivergenceDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.strings.LevenshteinDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.strings.NormalizedLevenshteinDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.DimensionSelectingDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.SubspaceEuclideanDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.SubspaceLPNormDistanceFunction
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction
index 35baef47..a22e3dc0 100644
--- a/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction
@@ -1,20 +1,26 @@
-de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.ManhattanDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.LPNormDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.ManhattanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.LPNormDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.ArcCosineDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.CosineDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.MaximumDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.MinimumDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.SquaredEuclideanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.MaximumDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.MinimumDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SquaredEuclideanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.BrayCurtisDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.CanberraDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.JeffreyDivergenceDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.WeightedCanberraDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.ClarkDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.Kulczynski1DistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.LorentzianDistanceFunction
# de.lmu.ifi.dbs.elki.distance.distancefunction.WeightedDistanceFunction
-# de.lmu.ifi.dbs.elki.distance.distancefunction.WeightedLPNormDistanceFunction
-# de.lmu.ifi.dbs.elki.distance.distancefunction.WeightedSquaredEuclideanDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.SparseEuclideanDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.SparseManhattanDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.SparseLPNormDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.SparseMaximumDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.WeightedLPNormDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.WeightedEuclideanDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.WeightedManhattanDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.WeightedSquaredEuclideanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SparseEuclideanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SparseManhattanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SparseLPNormDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SparseMaximumDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.colorhistogram.HSBHistogramQuadraticDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.colorhistogram.HistogramIntersectionDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.colorhistogram.RGBHistogramQuadraticDistanceFunction
@@ -25,6 +31,14 @@ de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.SquaredPearsonCorrelat
de.lmu.ifi.dbs.elki.distance.distancefunction.geo.DimensionSelectingLatLngDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.geo.LatLngDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.geo.LngLatDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.histogram.HistogramMatchDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.histogram.KolmogorovSmirnovDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic.JeffreyDivergenceDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic.ChiSquaredDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic.JensenShannonDivergenceDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic.KullbackLeiblerDivergenceAsymmetricDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic.KullbackLeiblerDivergenceReverseAsymmetricDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic.SqrtJensenShannonDivergenceDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.DimensionSelectingDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.SubspaceEuclideanDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.SubspaceLPNormDistanceFunction
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDistanceFunction b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDistanceFunction
index bf2810a7..383bfde1 100644
--- a/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDistanceFunction
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDistanceFunction
@@ -1,17 +1,28 @@
-de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.ManhattanDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.LPNormDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.MaximumDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.MinimumDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.ManhattanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.LPNormDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.MaximumDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.MinimumDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.ArcCosineDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.CosineDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.BrayCurtisDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.CanberraDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.SquaredEuclideanDistanceFunction
-# de.lmu.ifi.dbs.elki.distance.distancefunction.WeightedLPNormDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.WeightedCanberraDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.ClarkDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.Kulczynski1DistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.LorentzianDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SquaredEuclideanDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.WeightedLPNormDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.WeightedEuclideanDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.WeightedManhattanDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.WeightedSquaredEuclideanDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.colorhistogram.HistogramIntersectionDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.geo.LatLngDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.geo.LngLatDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.geo.DimensionSelectingLatLngDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic.ChiSquaredDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic.JeffreyDivergenceDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic.JensenShannonDivergenceDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.DimensionSelectingDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.SubspaceEuclideanDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.SubspaceLPNormDistanceFunction
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDoubleDistanceFunction b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDoubleDistanceFunction
index 1ff7d635..c8ca0d10 100644
--- a/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDoubleDistanceFunction
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDoubleDistanceFunction
@@ -1,17 +1,28 @@
-de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.ManhattanDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.LPNormDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.MaximumDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.MinimumDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.ManhattanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.LPNormDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.MaximumDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.MinimumDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.ArcCosineDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.CosineDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.BrayCurtisDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.CanberraDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.WeightedLPNormDistanceFunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.SquaredEuclideanDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.WeightedCanberraDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.ClarkDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.Kulczynski1DistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.LorentzianDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.WeightedLPNormDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.WeightedEuclideanDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.WeightedManhattanDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.WeightedSquaredEuclideanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SquaredEuclideanDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.colorhistogram.HistogramIntersectionDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.geo.LatLngDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.geo.LngLatDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.geo.DimensionSelectingLatLngDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic.ChiSquaredDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic.JeffreyDivergenceDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic.JensenShannonDivergenceDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.DimensionSelectingDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.SubspaceEuclideanDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.SubspaceLPNormDistanceFunction
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.LPNormDistanceFunction b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.LPNormDistanceFunction
new file mode 100644
index 00000000..95441a56
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.LPNormDistanceFunction
@@ -0,0 +1,7 @@
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.ManhattanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.LPNormDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.MaximumDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.WeightedLPNormDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.WeightedEuclideanDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.WeightedManhattanDistanceFunction \ No newline at end of file
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.AbstractDimensionsSelectingDoubleDistanceFunction b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.DimensionSelectingSubspaceDistanceFunction
index f0a38487..51b11e3b 100644
--- a/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.AbstractDimensionsSelectingDoubleDistanceFunction
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.DimensionSelectingSubspaceDistanceFunction
@@ -1,3 +1,4 @@
de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.SubspaceEuclideanDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.SubspaceLPNormDistanceFunction
de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.SubspaceManhattanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.DimensionSelectingDistanceFunction \ No newline at end of file
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.similarityfunction.PrimitiveSimilarityFunction b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.similarityfunction.PrimitiveSimilarityFunction
index 33284aa0..55b1755e 100644
--- a/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.similarityfunction.PrimitiveSimilarityFunction
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.similarityfunction.PrimitiveSimilarityFunction
@@ -2,3 +2,5 @@ de.lmu.ifi.dbs.elki.distance.similarityfunction.kernel.FooKernelFunction
de.lmu.ifi.dbs.elki.distance.similarityfunction.kernel.LinearKernelFunction
de.lmu.ifi.dbs.elki.distance.similarityfunction.kernel.PolynomialKernelFunction
de.lmu.ifi.dbs.elki.distance.similarityfunction.InvertedDistanceSimilarityFunction
+de.lmu.ifi.dbs.elki.distance.similarityfunction.Kulczynski1SimilarityFunction
+de.lmu.ifi.dbs.elki.distance.similarityfunction.Kulczynski2SimilarityFunction \ No newline at end of file
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.similarityfunction.SimilarityFunction b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.similarityfunction.SimilarityFunction
index bc5ffaa6..c8b5c993 100644
--- a/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.similarityfunction.SimilarityFunction
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.similarityfunction.SimilarityFunction
@@ -1,5 +1,7 @@
de.lmu.ifi.dbs.elki.distance.similarityfunction.FractionalSharedNearestNeighborSimilarityFunction
de.lmu.ifi.dbs.elki.distance.similarityfunction.SharedNearestNeighborSimilarityFunction
+de.lmu.ifi.dbs.elki.distance.similarityfunction.Kulczynski1SimilarityFunction
+de.lmu.ifi.dbs.elki.distance.similarityfunction.Kulczynski2SimilarityFunction
de.lmu.ifi.dbs.elki.distance.similarityfunction.InvertedDistanceSimilarityFunction
# de.lmu.ifi.dbs.elki.distance.similarityfunction.kernel.FooKernelFunction
# de.lmu.ifi.dbs.elki.distance.similarityfunction.kernel.LinearKernelFunction
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.evaluation.Evaluator b/src/META-INF/elki/de.lmu.ifi.dbs.elki.evaluation.Evaluator
index 1bacadda..728e472f 100644
--- a/src/META-INF/elki/de.lmu.ifi.dbs.elki.evaluation.Evaluator
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.evaluation.Evaluator
@@ -11,5 +11,4 @@ de.lmu.ifi.dbs.elki.evaluation.outlier.OutlierPrecisionAtKCurve
de.lmu.ifi.dbs.elki.evaluation.outlier.OutlierPrecisionRecallCurve
de.lmu.ifi.dbs.elki.evaluation.outlier.OutlierSmROCCurve
de.lmu.ifi.dbs.elki.evaluation.outlier.JudgeOutlierScores
-de.lmu.ifi.dbs.elki.evaluation.similaritymatrix.ComputeSimilarityMatrixImage
-# de.lmu.ifi.dbs.elki.evaluation.roc.ComputeROCCurve \ No newline at end of file
+de.lmu.ifi.dbs.elki.evaluation.similaritymatrix.ComputeSimilarityMatrixImage \ No newline at end of file
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.IndexFactory b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.IndexFactory
index 50052cb3..24e24eaa 100644
--- a/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.IndexFactory
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.IndexFactory
@@ -1,14 +1,17 @@
de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rstar.RStarTreeFactory
de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.deliclu.DeLiCluTreeFactory
-de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.flat.FlatRStarTreeFactory
+# de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.flat.FlatRStarTreeFactory
# de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rdknn.RdKNNTreeFactory
+de.lmu.ifi.dbs.elki.index.tree.spatial.kd.MinimalisticMemoryKDTree$Factory
de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mtree.MTreeFactory
de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkapp.MkAppTreeFactory
# de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkcop.MkCopTreeFactory
de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkmax.MkMaxTreeFactory
de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mktab.MkTabTreeFactory
+de.lmu.ifi.dbs.elki.index.lsh.InMemoryLSHIndex
de.lmu.ifi.dbs.elki.index.vafile.VAFile$Factory
de.lmu.ifi.dbs.elki.index.vafile.PartialVAFile$Factory
+de.lmu.ifi.dbs.elki.index.preprocessed.knn.CachedDoubleDistanceKNNPreprocessor$Factory
de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNAndRKNNPreprocessor$Factory
de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNPreprocessor$Factory
de.lmu.ifi.dbs.elki.index.preprocessed.knn.KNNJoinMaterializeKNNPreprocessor$Factory
@@ -22,4 +25,8 @@ de.lmu.ifi.dbs.elki.index.preprocessed.preference.DiSHPreferenceVectorIndex$Fact
de.lmu.ifi.dbs.elki.index.preprocessed.preference.HiSCPreferenceVectorIndex$Factory
de.lmu.ifi.dbs.elki.index.preprocessed.snn.SharedNearestNeighborPreprocessor$Factory
de.lmu.ifi.dbs.elki.index.preprocessed.subspaceproj.FourCSubspaceIndex$Factory
-de.lmu.ifi.dbs.elki.index.preprocessed.subspaceproj.PreDeConSubspaceIndex$Factory \ No newline at end of file
+de.lmu.ifi.dbs.elki.index.preprocessed.subspaceproj.PreDeConSubspaceIndex$Factory
+de.lmu.ifi.dbs.elki.index.projected.LatLngAsECEFIndex$Factory
+de.lmu.ifi.dbs.elki.index.projected.LngLatAsECEFIndex$Factory
+de.lmu.ifi.dbs.elki.index.projected.ProjectedIndex$Factory
+de.lmu.ifi.dbs.elki.index.projected.PINN \ No newline at end of file
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.KNNIndex b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.KNNIndex
index c3a3fc1b..4d76c75a 100644
--- a/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.KNNIndex
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.KNNIndex
@@ -2,11 +2,13 @@ de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rstar.RStarTreeIndex
de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.deliclu.DeLiCluTreeIndex
de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.flat.FlatRStarTreeIndex
# de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rdknn.RdKNNTree
+de.lmu.ifi.dbs.elki.index.tree.spatial.kd.MinimalisticMemoryKDTree
de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mtree.MTreeIndex
de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkapp.MkAppTreeIndex
# de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkcop.MkCoPTreeIndex
de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkmax.MkMaxTreeIndex
de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mktab.MkTabTreeIndex
+de.lmu.ifi.dbs.elki.index.preprocessed.knn.CachedDoubleDistanceKNNPreprocessor
de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNAndRKNNPreprocessor
de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNPreprocessor
de.lmu.ifi.dbs.elki.index.preprocessed.knn.KNNJoinMaterializeKNNPreprocessor
@@ -15,4 +17,7 @@ de.lmu.ifi.dbs.elki.index.preprocessed.knn.PartitionApproximationMaterializeKNNP
de.lmu.ifi.dbs.elki.index.preprocessed.knn.RandomSampleKNNPreprocessor
de.lmu.ifi.dbs.elki.index.preprocessed.knn.SpatialApproximationMaterializeKNNPreprocessor
de.lmu.ifi.dbs.elki.index.vafile.VAFile
-de.lmu.ifi.dbs.elki.index.vafile.PartialVAFile \ No newline at end of file
+de.lmu.ifi.dbs.elki.index.vafile.PartialVAFile
+de.lmu.ifi.dbs.elki.index.projected.LatLngAsECEFIndex
+de.lmu.ifi.dbs.elki.index.projected.LngLatAsECEFIndex
+de.lmu.ifi.dbs.elki.index.projected.ProjectedIndex
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.RKNNIndex b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.RKNNIndex
index 04293f79..980543c4 100644
--- a/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.RKNNIndex
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.RKNNIndex
@@ -4,3 +4,6 @@ de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkapp.MkAppTreeInd
de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkmax.MkMaxTreeIndex
de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mktab.MkTabTreeIndex
# de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rdknn.RdKNNTree
+de.lmu.ifi.dbs.elki.index.projected.LatLngAsECEFIndex
+de.lmu.ifi.dbs.elki.index.projected.LngLatAsECEFIndex
+de.lmu.ifi.dbs.elki.index.projected.ProjectedIndex
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.RangeIndex b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.RangeIndex
index ce559a88..24f683a6 100644
--- a/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.RangeIndex
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.RangeIndex
@@ -2,10 +2,14 @@ de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rstar.RStarTreeIndex
de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.deliclu.DeLiCluTreeIndex
de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.flat.FlatRStarTreeIndex
# de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rdknn.RdKNNTree
+de.lmu.ifi.dbs.elki.index.tree.spatial.kd.MinimalisticMemoryKDTree
de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mtree.MTreeIndex
de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkapp.MkAppTreeIndex
# de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkcop.MkCoPTreeIndex
de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkmax.MkMaxTreeIndex
de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mktab.MkTabTreeIndex
+de.lmu.ifi.dbs.elki.index.vafile.PartialVAFile
de.lmu.ifi.dbs.elki.index.vafile.VAFile
-de.lmu.ifi.dbs.elki.index.vafile.PartialVAFile \ No newline at end of file
+de.lmu.ifi.dbs.elki.index.projected.LatLngAsECEFIndex
+de.lmu.ifi.dbs.elki.index.projected.LngLatAsECEFIndex
+de.lmu.ifi.dbs.elki.index.projected.ProjectedIndex
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.lsh.hashfamilies.LocalitySensitiveHashFunctionFamily b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.lsh.hashfamilies.LocalitySensitiveHashFunctionFamily
new file mode 100644
index 00000000..ba204c2f
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.lsh.hashfamilies.LocalitySensitiveHashFunctionFamily
@@ -0,0 +1,2 @@
+de.lmu.ifi.dbs.elki.index.lsh.hashfamilies.EuclideanHashFunctionFamily
+de.lmu.ifi.dbs.elki.index.lsh.hashfamilies.ManhattanHashFunctionFamily \ No newline at end of file
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.insert.MTreeInsert b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.insert.MTreeInsert
new file mode 100644
index 00000000..3d5ebe31
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.insert.MTreeInsert
@@ -0,0 +1 @@
+de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.insert.MinimumEnlargementInsert
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.split.MTreeSplit b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.split.MTreeSplit
new file mode 100644
index 00000000..2e49d269
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.split.MTreeSplit
@@ -0,0 +1,4 @@
+de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.split.MMRadSplit
+de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.split.MLBDistSplit
+de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.split.MRadSplit
+de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.split.RandomSplit \ No newline at end of file
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk.BulkSplit b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk.BulkSplit
index c40d3887..e42306f3 100644
--- a/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk.BulkSplit
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk.BulkSplit
@@ -1,5 +1,7 @@
de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk.SortTileRecursiveBulkSplit
+de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk.AdaptiveSortTileRecursiveBulkSplit
de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk.SpatialSortBulkSplit
de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk.MaxExtensionBulkSplit
de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk.OneDimSortBulkSplit
de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk.FileOrderBulkSplit
+de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk.MaxExtensionSortTileRecursiveBulkSplit
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.geodesy.EarthModel b/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.geodesy.EarthModel
new file mode 100644
index 00000000..e1b45f08
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.geodesy.EarthModel
@@ -0,0 +1,9 @@
+de.lmu.ifi.dbs.elki.math.geodesy.SphericalHaversineEarthModel
+de.lmu.ifi.dbs.elki.math.geodesy.SphericalVincentyEarthModel
+de.lmu.ifi.dbs.elki.math.geodesy.SphericalCosineEarthModel
+de.lmu.ifi.dbs.elki.math.geodesy.WGS84SpheroidEarthModel
+de.lmu.ifi.dbs.elki.math.geodesy.GRS80SpheroidEarthModel
+de.lmu.ifi.dbs.elki.math.geodesy.WGS72SpheroidEarthModel
+de.lmu.ifi.dbs.elki.math.geodesy.GRS67SpheroidEarthModel
+de.lmu.ifi.dbs.elki.math.geodesy.Clarke1880SpheroidEarthModel
+de.lmu.ifi.dbs.elki.math.geodesy.Clarke1858SpheroidEarthModel \ No newline at end of file
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.linearalgebra.randomprojections.RandomProjectionFamily b/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.linearalgebra.randomprojections.RandomProjectionFamily
new file mode 100644
index 00000000..f1ddc0cd
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.linearalgebra.randomprojections.RandomProjectionFamily
@@ -0,0 +1,4 @@
+de.lmu.ifi.dbs.elki.math.linearalgebra.randomprojections.AchlioptasRandomProjectionFamily
+de.lmu.ifi.dbs.elki.math.linearalgebra.randomprojections.GaussianRandomProjectionFamily
+de.lmu.ifi.dbs.elki.math.linearalgebra.randomprojections.CauchyRandomProjectionFamily
+de.lmu.ifi.dbs.elki.math.linearalgebra.randomprojections.RandomSubsetProjectionFamily
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.statistics.KernelDensityFunction b/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.statistics.KernelDensityFunction
deleted file mode 100644
index 84f29b30..00000000
--- a/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.statistics.KernelDensityFunction
+++ /dev/null
@@ -1,4 +0,0 @@
-de.lmu.ifi.dbs.elki.math.statistics.EpanechnikovKernelDensityFunction
-de.lmu.ifi.dbs.elki.math.statistics.GaussianKernelDensityFunction
-de.lmu.ifi.dbs.elki.math.statistics.TriangularKernelDensityFunction
-de.lmu.ifi.dbs.elki.math.statistics.UniformKernelDensityFunction
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.statistics.distribution.Distribution b/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.statistics.distribution.Distribution
index cb0541ea..8c11d1b6 100644
--- a/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.statistics.distribution.Distribution
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.statistics.distribution.Distribution
@@ -3,9 +3,26 @@ de.lmu.ifi.dbs.elki.math.statistics.distribution.NormalDistribution
de.lmu.ifi.dbs.elki.math.statistics.distribution.ExponentialDistribution
de.lmu.ifi.dbs.elki.math.statistics.distribution.GammaDistribution
de.lmu.ifi.dbs.elki.math.statistics.distribution.BetaDistribution
+de.lmu.ifi.dbs.elki.math.statistics.distribution.CauchyDistribution
de.lmu.ifi.dbs.elki.math.statistics.distribution.ChiDistribution
de.lmu.ifi.dbs.elki.math.statistics.distribution.ChiSquaredDistribution
+de.lmu.ifi.dbs.elki.math.statistics.distribution.LaplaceDistribution
+de.lmu.ifi.dbs.elki.math.statistics.distribution.LogisticDistribution
+de.lmu.ifi.dbs.elki.math.statistics.distribution.LogLogisticDistribution
+de.lmu.ifi.dbs.elki.math.statistics.distribution.GeneralizedLogisticDistribution
+de.lmu.ifi.dbs.elki.math.statistics.distribution.GeneralizedLogisticAlternateDistribution
+de.lmu.ifi.dbs.elki.math.statistics.distribution.LogNormalDistribution
+de.lmu.ifi.dbs.elki.math.statistics.distribution.SkewGeneralizedNormalDistribution
+de.lmu.ifi.dbs.elki.math.statistics.distribution.LogGammaDistribution
+de.lmu.ifi.dbs.elki.math.statistics.distribution.LogGammaAlternateDistribution
de.lmu.ifi.dbs.elki.math.statistics.distribution.PoissonDistribution
de.lmu.ifi.dbs.elki.math.statistics.distribution.StudentsTDistribution
+de.lmu.ifi.dbs.elki.math.statistics.distribution.WeibullDistribution
+de.lmu.ifi.dbs.elki.math.statistics.distribution.GumbelDistribution
+de.lmu.ifi.dbs.elki.math.statistics.distribution.GeneralizedExtremeValueDistribution
+de.lmu.ifi.dbs.elki.math.statistics.distribution.ExponentiallyModifiedGaussianDistribution
+de.lmu.ifi.dbs.elki.math.statistics.distribution.RayleighDistribution
+de.lmu.ifi.dbs.elki.math.statistics.distribution.WaldDistribution
+de.lmu.ifi.dbs.elki.math.statistics.distribution.KappaDistribution
de.lmu.ifi.dbs.elki.math.statistics.distribution.ConstantDistribution
-de.lmu.ifi.dbs.elki.math.statistics.distribution.HaltonUniformDistribution \ No newline at end of file
+de.lmu.ifi.dbs.elki.math.statistics.distribution.HaltonUniformDistribution
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.statistics.distribution.DistributionWithRandom b/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.statistics.distribution.DistributionWithRandom
deleted file mode 100644
index 0e27040e..00000000
--- a/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.statistics.distribution.DistributionWithRandom
+++ /dev/null
@@ -1,9 +0,0 @@
-de.lmu.ifi.dbs.elki.math.statistics.distribution.UniformDistribution
-de.lmu.ifi.dbs.elki.math.statistics.distribution.NormalDistribution
-de.lmu.ifi.dbs.elki.math.statistics.distribution.ExponentialDistribution
-de.lmu.ifi.dbs.elki.math.statistics.distribution.GammaDistribution
-de.lmu.ifi.dbs.elki.math.statistics.distribution.BetaDistribution
-de.lmu.ifi.dbs.elki.math.statistics.distribution.ChiDistribution
-de.lmu.ifi.dbs.elki.math.statistics.distribution.ChiSquaredDistribution
-de.lmu.ifi.dbs.elki.math.statistics.distribution.ConstantDistribution
-de.lmu.ifi.dbs.elki.math.statistics.distribution.HaltonUniformDistribution \ No newline at end of file
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.DistributionEstimator b/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.DistributionEstimator
new file mode 100644
index 00000000..ce1fcbe4
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.DistributionEstimator
@@ -0,0 +1,49 @@
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.meta.BestFitEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.meta.TrimmedEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.meta.WinsorisingEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.NormalMOMEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.NormalMADEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.NormalLMMEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.GammaMOMEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.GammaMADEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.GammaChoiWetteEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.GammaLMMEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.LogNormalLogMOMEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.LogNormalLogMADEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.LogNormalLMMEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.LogNormalBilkovaLMMEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.SkewGNormalLMMEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.LogGammaLogMOMEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.LogGammaLogMADEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.LogGammaChoiWetteEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.LogGammaAlternateExpMADEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.UniformEnhancedMinMaxEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.UniformMinMaxEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.UniformMADEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.UniformLMMEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.ExponentialMOMEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.ExponentialMADEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.ExponentialMedianEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.ExponentialLMMEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.LaplaceMLEEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.LaplaceMADEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.LaplaceLMMEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.LogisticMADEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.LogisticLMMEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.LogLogisticMADEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.GeneralizedLogisticAlternateLMMEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.GeneralizedExtremeValueLMMEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.WeibullLogMOMEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.WeibullLogMADEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.WeibullLMMEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.GumbelMADEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.GumbelLMMEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.CauchyMADEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.RayleighMADEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.RayleighMLEEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.RayleighLMMEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.WaldMLEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.WaldMOMEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.EMGOlivierNorbergEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.NormalLevenbergMarquardtKDEEstimator
+de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.LogNormalLevenbergMarquardtKDEEstimator
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.statistics.kernelfunctions.KernelDensityFunction b/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.statistics.kernelfunctions.KernelDensityFunction
new file mode 100644
index 00000000..624bb1ce
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.statistics.kernelfunctions.KernelDensityFunction
@@ -0,0 +1,8 @@
+de.lmu.ifi.dbs.elki.math.statistics.kernelfunctions.EpanechnikovKernelDensityFunction
+de.lmu.ifi.dbs.elki.math.statistics.kernelfunctions.GaussianKernelDensityFunction
+de.lmu.ifi.dbs.elki.math.statistics.kernelfunctions.CosineKernelDensityFunction
+de.lmu.ifi.dbs.elki.math.statistics.kernelfunctions.UniformKernelDensityFunction
+de.lmu.ifi.dbs.elki.math.statistics.kernelfunctions.TriangularKernelDensityFunction
+de.lmu.ifi.dbs.elki.math.statistics.kernelfunctions.BiweightKernelDensityFunction
+de.lmu.ifi.dbs.elki.math.statistics.kernelfunctions.TriweightKernelDensityFunction
+de.lmu.ifi.dbs.elki.math.statistics.kernelfunctions.TricubeKernelDensityFunction \ No newline at end of file
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.persistent.PageFileFactory b/src/META-INF/elki/de.lmu.ifi.dbs.elki.persistent.PageFileFactory
new file mode 100644
index 00000000..43f3bf45
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.persistent.PageFileFactory
@@ -0,0 +1,4 @@
+de.lmu.ifi.dbs.elki.persistent.MemoryPageFileFactory
+de.lmu.ifi.dbs.elki.persistent.LRUCachePageFileFactory
+de.lmu.ifi.dbs.elki.persistent.PersistentPageFileFactory
+de.lmu.ifi.dbs.elki.persistent.OnDiskArrayPageFileFactory \ No newline at end of file
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.result.ResultHandler b/src/META-INF/elki/de.lmu.ifi.dbs.elki.result.ResultHandler
index c16f1124..d14bbc81 100644
--- a/src/META-INF/elki/de.lmu.ifi.dbs.elki.result.ResultHandler
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.result.ResultHandler
@@ -4,4 +4,5 @@ de.lmu.ifi.dbs.elki.result.DiscardResultHandler
de.lmu.ifi.dbs.elki.result.KMLOutputHandler
de.lmu.ifi.dbs.elki.visualization.ExportVisualizations
de.lmu.ifi.dbs.elki.application.jsmap.JSONResultHandler
-de.lmu.ifi.dbs.elki.result.LogResultStructureResultHandler \ No newline at end of file
+de.lmu.ifi.dbs.elki.result.LogResultStructureResultHandler
+tutorial.outlier.SimpleScoreDumper \ No newline at end of file
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.utilities.ensemble.EnsembleVoting b/src/META-INF/elki/de.lmu.ifi.dbs.elki.utilities.ensemble.EnsembleVoting
index 7cb9359d..5d327cdc 100644
--- a/src/META-INF/elki/de.lmu.ifi.dbs.elki.utilities.ensemble.EnsembleVoting
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.utilities.ensemble.EnsembleVoting
@@ -2,5 +2,5 @@ de.lmu.ifi.dbs.elki.utilities.ensemble.EnsembleVotingMean
de.lmu.ifi.dbs.elki.utilities.ensemble.EnsembleVotingMin
de.lmu.ifi.dbs.elki.utilities.ensemble.EnsembleVotingMax
de.lmu.ifi.dbs.elki.utilities.ensemble.EnsembleVotingMedian
-de.lmu.ifi.dbs.elki.utilities.ensemble.EnsembleVotingBayes
-de.lmu.ifi.dbs.elki.utilities.ensemble.EnsembleVotingRestrictedBayes \ No newline at end of file
+de.lmu.ifi.dbs.elki.utilities.ensemble.EnsembleVotingMultiplicative
+de.lmu.ifi.dbs.elki.utilities.ensemble.EnsembleVotingInverseMultiplicative
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.utilities.scaling.ScalingFunction b/src/META-INF/elki/de.lmu.ifi.dbs.elki.utilities.scaling.ScalingFunction
index ccd91844..8447f3eb 100644
--- a/src/META-INF/elki/de.lmu.ifi.dbs.elki.utilities.scaling.ScalingFunction
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.utilities.scaling.ScalingFunction
@@ -5,6 +5,7 @@ de.lmu.ifi.dbs.elki.utilities.scaling.LinearScaling
de.lmu.ifi.dbs.elki.utilities.scaling.MinusLogScaling
de.lmu.ifi.dbs.elki.utilities.scaling.outlier.OutlierLinearScaling
de.lmu.ifi.dbs.elki.utilities.scaling.outlier.TopKOutlierScaling
+de.lmu.ifi.dbs.elki.utilities.scaling.outlier.COPOutlierScaling
de.lmu.ifi.dbs.elki.utilities.scaling.outlier.MinusLogGammaScaling
de.lmu.ifi.dbs.elki.utilities.scaling.outlier.MinusLogStandardDeviationScaling
de.lmu.ifi.dbs.elki.utilities.scaling.outlier.MultiplicativeInverseScaling
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.utilities.scaling.outlier.OutlierScalingFunction b/src/META-INF/elki/de.lmu.ifi.dbs.elki.utilities.scaling.outlier.OutlierScalingFunction
index 49617959..d7ec5869 100644
--- a/src/META-INF/elki/de.lmu.ifi.dbs.elki.utilities.scaling.outlier.OutlierScalingFunction
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.utilities.scaling.outlier.OutlierScalingFunction
@@ -1,6 +1,7 @@
de.lmu.ifi.dbs.elki.utilities.scaling.outlier.OutlierLinearScaling
de.lmu.ifi.dbs.elki.utilities.scaling.outlier.RankingPseudoOutlierScaling
de.lmu.ifi.dbs.elki.utilities.scaling.outlier.TopKOutlierScaling
+de.lmu.ifi.dbs.elki.utilities.scaling.outlier.COPOutlierScaling
de.lmu.ifi.dbs.elki.utilities.scaling.outlier.MinusLogGammaScaling
de.lmu.ifi.dbs.elki.utilities.scaling.outlier.MinusLogStandardDeviationScaling
de.lmu.ifi.dbs.elki.utilities.scaling.outlier.MultiplicativeInverseScaling
@@ -11,4 +12,4 @@ de.lmu.ifi.dbs.elki.utilities.scaling.outlier.SqrtStandardDeviationScaling
de.lmu.ifi.dbs.elki.utilities.scaling.outlier.StandardDeviationScaling
de.lmu.ifi.dbs.elki.utilities.scaling.outlier.HeDESNormalizationOutlierScaling
de.lmu.ifi.dbs.elki.utilities.scaling.outlier.MixtureModelOutlierScalingFunction
-de.lmu.ifi.dbs.elki.utilities.scaling.outlier.SigmoidOutlierScalingFunction
+de.lmu.ifi.dbs.elki.utilities.scaling.outlier.SigmoidOutlierScalingFunction \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/KDDTask.java b/src/de/lmu/ifi/dbs/elki/KDDTask.java
index 3d71a8c4..38570301 100644
--- a/src/de/lmu/ifi/dbs/elki/KDDTask.java
+++ b/src/de/lmu/ifi/dbs/elki/KDDTask.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/LICENSE.txt b/src/de/lmu/ifi/dbs/elki/LICENSE.txt
index 50b0b4d9..af4068b6 100644
--- a/src/de/lmu/ifi/dbs/elki/LICENSE.txt
+++ b/src/de/lmu/ifi/dbs/elki/LICENSE.txt
@@ -1,6 +1,6 @@
ELKI: Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2011 Lehr- und Forschungseinheit für Datenbanksysteme, Ludwig-Maximilians-Universität München
+Copyright (C) 2013 Lehr- und Forschungseinheit für Datenbanksysteme, Ludwig-Maximilians-Universität München
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/APRIORI.java b/src/de/lmu/ifi/dbs/elki/algorithm/APRIORI.java
index 70706df8..07aaf3fc 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/APRIORI.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/APRIORI.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -51,7 +51,6 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.OnlyOneIsAllowed
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleParameter;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Parameter;
/**
* Provides the APRIORI algorithm for Mining Association Rules.
@@ -128,8 +127,8 @@ public class APRIORI extends AbstractAlgorithm<AprioriResult> {
* @return the AprioriResult learned by this APRIORI
*/
public AprioriResult run(Database database, Relation<BitVector> relation) {
- Map<BitSet, Integer> support = new HashMap<BitSet, Integer>();
- List<BitSet> solution = new ArrayList<BitSet>();
+ Map<BitSet, Integer> support = new HashMap<>();
+ List<BitSet> solution = new ArrayList<>();
final int size = relation.size();
if(size > 0) {
int dim;
@@ -176,7 +175,7 @@ public class APRIORI extends AbstractAlgorithm<AprioriResult> {
* frequent already
*/
protected BitSet[] prune(Map<BitSet, Integer> support, BitSet[] candidates, int size) {
- List<BitSet> candidateList = new ArrayList<BitSet>();
+ List<BitSet> candidateList = new ArrayList<>();
// MinFreq pruning
if(minfreq >= 0) {
for(BitSet bitSet : candidates) {
@@ -229,7 +228,7 @@ public class APRIORI extends AbstractAlgorithm<AprioriResult> {
* increasing the length by 1
*/
protected BitSet[] join(BitSet[] frequentItemsets) {
- List<BitSet> joined = new ArrayList<BitSet>();
+ List<BitSet> joined = new ArrayList<>();
for(int i = 0; i < frequentItemsets.length; i++) {
for(int j = i + 1; j < frequentItemsets.length; j++) {
BitSet b1 = (BitSet) frequentItemsets[i].clone();
@@ -272,7 +271,7 @@ public class APRIORI extends AbstractAlgorithm<AprioriResult> {
}
}
}
- List<BitSet> frequentItemsets = new ArrayList<BitSet>();
+ List<BitSet> frequentItemsets = new ArrayList<>();
if(minfreq >= 0.0) {
// TODO: work with integers?
double critsupp = minfreq * database.size();
@@ -340,11 +339,8 @@ public class APRIORI extends AbstractAlgorithm<AprioriResult> {
}
// global parameter constraints
- ArrayList<Parameter<?>> globalConstraints = new ArrayList<Parameter<?>>();
- globalConstraints.add(minfreqP);
- globalConstraints.add(minsuppP);
- config.checkConstraint(new OnlyOneIsAllowedToBeSetGlobalConstraint(globalConstraints));
- config.checkConstraint(new OneMustBeSetGlobalConstraint(globalConstraints));
+ config.checkConstraint(new OnlyOneIsAllowedToBeSetGlobalConstraint(minfreqP, minsuppP));
+ config.checkConstraint(new OneMustBeSetGlobalConstraint(minfreqP, minsuppP));
}
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/AbstractAlgorithm.java b/src/de/lmu/ifi/dbs/elki/algorithm/AbstractAlgorithm.java
index b36df094..68ac9595 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/AbstractAlgorithm.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/AbstractAlgorithm.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -177,6 +177,6 @@ public abstract class AbstractAlgorithm<R extends Result> implements Algorithm {
* @return Parameter object
*/
public static <F extends DistanceFunction<?, ?>> ObjectParameter<F> makeParameterDistanceFunction(Class<?> defaultDistanceFunction, Class<?> restriction) {
- return new ObjectParameter<F>(AbstractDistanceBasedAlgorithm.DISTANCE_FUNCTION_ID, restriction, defaultDistanceFunction);
+ return new ObjectParameter<>(AbstractDistanceBasedAlgorithm.DISTANCE_FUNCTION_ID, restriction, defaultDistanceFunction);
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/AbstractDistanceBasedAlgorithm.java b/src/de/lmu/ifi/dbs/elki/algorithm/AbstractDistanceBasedAlgorithm.java
index e9d638dc..3420e279 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/AbstractDistanceBasedAlgorithm.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/AbstractDistanceBasedAlgorithm.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,11 +24,10 @@ package de.lmu.ifi.dbs.elki.algorithm;
*/
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.result.Result;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
@@ -45,15 +44,10 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
* @param <D> the type of Distance used by this Algorithm
* @param <R> the type of result to retrieve from this Algorithm
*/
-public abstract class AbstractDistanceBasedAlgorithm<O, D extends Distance<D>, R extends Result> extends AbstractAlgorithm<R> {
- /**
- * OptionID for {@link #DISTANCE_FUNCTION_ID}.
- */
- public static final OptionID DISTANCE_FUNCTION_ID = new OptionID("algorithm.distancefunction", "Distance function to determine the distance between database objects.");
-
+public abstract class AbstractDistanceBasedAlgorithm<O, D extends Distance<D>, R extends Result> extends AbstractAlgorithm<R> implements DistanceBasedAlgorithm<O, D> {
/**
* Holds the instance of the distance function specified by
- * {@link #DISTANCE_FUNCTION_ID}.
+ * {@link DistanceBasedAlgorithm#DISTANCE_FUNCTION_ID}.
*/
private DistanceFunction<? super O, D> distanceFunction;
@@ -72,6 +66,7 @@ public abstract class AbstractDistanceBasedAlgorithm<O, D extends Distance<D>, R
*
* @return the distanceFunction
*/
+ @Override
public DistanceFunction<? super O, D> getDistanceFunction() {
return distanceFunction;
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/AbstractPrimitiveDistanceBasedAlgorithm.java b/src/de/lmu/ifi/dbs/elki/algorithm/AbstractPrimitiveDistanceBasedAlgorithm.java
index 7bca1931..40fe67c3 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/AbstractPrimitiveDistanceBasedAlgorithm.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/AbstractPrimitiveDistanceBasedAlgorithm.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,8 +23,8 @@ package de.lmu.ifi.dbs.elki.algorithm;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.result.Result;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
@@ -50,7 +50,7 @@ public abstract class AbstractPrimitiveDistanceBasedAlgorithm<O, D extends Dista
* Holds the instance of the distance function specified by
* {@link AbstractDistanceBasedAlgorithm#DISTANCE_FUNCTION_ID}.
*/
- private PrimitiveDistanceFunction<? super O, D> distanceFunction;
+ protected PrimitiveDistanceFunction<? super O, D> distanceFunction;
/**
* Constructor.
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/Algorithm.java b/src/de/lmu/ifi/dbs/elki/algorithm/Algorithm.java
index e5a4cc07..9b367db4 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/Algorithm.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/Algorithm.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/DependencyDerivator.java b/src/de/lmu/ifi/dbs/elki/algorithm/DependencyDerivator.java
index 2992ae4a..cc40d13b 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/DependencyDerivator.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/DependencyDerivator.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -33,10 +33,10 @@ import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Centroid;
@@ -163,7 +163,7 @@ public class DependencyDerivator<V extends NumberVector<?>, D extends Distance<D
}
else {
DistanceQuery<V, D> distanceQuery = database.getDistanceQuery(relation, getDistanceFunction());
- KNNResult<D> queryResults = database.getKNNQuery(distanceQuery, this.sampleSize).getKNNForObject(centroidDV, this.sampleSize);
+ KNNList<D> queryResults = database.getKNNQuery(distanceQuery, this.sampleSize).getKNNForObject(centroidDV, this.sampleSize);
ids = DBIDUtil.newHashSet(queryResults);
}
}
@@ -210,7 +210,7 @@ public class DependencyDerivator<V extends NumberVector<?>, D extends Distance<D
// TODO: what if we don't have any weak eigenvectors?
if(weakEigenvectors.getColumnDimensionality() == 0) {
- sol = new CorrelationAnalysisSolution<V>(null, db, strongEigenvectors, weakEigenvectors, pcares.similarityMatrix(), centroid);
+ sol = new CorrelationAnalysisSolution<>(null, db, strongEigenvectors, weakEigenvectors, pcares.similarityMatrix(), centroid);
}
else {
Matrix transposedWeakEigenvectors = weakEigenvectors.transpose();
@@ -249,7 +249,7 @@ public class DependencyDerivator<V extends NumberVector<?>, D extends Distance<D
LinearEquationSystem lq = new LinearEquationSystem(a, b.getArrayRef());
lq.solveByTotalPivotSearch();
- sol = new CorrelationAnalysisSolution<V>(lq, db, strongEigenvectors, pcares.getWeakEigenvectors(), pcares.similarityMatrix(), centroid);
+ sol = new CorrelationAnalysisSolution<>(lq, db, strongEigenvectors, pcares.getWeakEigenvectors(), pcares.similarityMatrix(), centroid);
if(LOG.isDebuggingFine()) {
StringBuilder log = new StringBuilder();
@@ -331,7 +331,7 @@ public class DependencyDerivator<V extends NumberVector<?>, D extends Distance<D
nf.setMaximumFractionDigits(outputAccuracy);
nf.setMinimumFractionDigits(outputAccuracy);
- return new DependencyDerivator<V, D>(distanceFunction, nf, pca, sampleSize, randomSample);
+ return new DependencyDerivator<>(distanceFunction, nf, pca, sampleSize, randomSample);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/DistanceBasedAlgorithm.java b/src/de/lmu/ifi/dbs/elki/algorithm/DistanceBasedAlgorithm.java
new file mode 100644
index 00000000..048d2782
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/DistanceBasedAlgorithm.java
@@ -0,0 +1,49 @@
+package de.lmu.ifi.dbs.elki.algorithm;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+
+/**
+ * Very broad interface for distance based algorithms.
+ *
+ * @author Erich Schubert
+ *
+ * @param <O> Object type
+ * @param <D> Distance type
+ */
+public interface DistanceBasedAlgorithm<O, D extends Distance<?>> extends Algorithm {
+ /**
+ * OptionID for {@link #DISTANCE_FUNCTION_ID}.
+ */
+ public static final OptionID DISTANCE_FUNCTION_ID = new OptionID("algorithm.distancefunction", "Distance function to determine the distance between database objects.");
+
+ /**
+ * Returns the distanceFunction.
+ *
+ * @return the distanceFunction
+ */
+ DistanceFunction<? super O, D> getDistanceFunction();
+}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/DummyAlgorithm.java b/src/de/lmu/ifi/dbs/elki/algorithm/DummyAlgorithm.java
index 0f871535..24de36ce 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/DummyAlgorithm.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/DummyAlgorithm.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -31,7 +31,7 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.result.Result;
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/KNNDistanceOrder.java b/src/de/lmu/ifi/dbs/elki/algorithm/KNNDistanceOrder.java
index 7e9ce77e..b696ed36 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/KNNDistanceOrder.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/KNNDistanceOrder.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -32,11 +32,11 @@ import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.result.KNNDistanceOrderResult;
@@ -114,15 +114,15 @@ public class KNNDistanceOrder<O, D extends Distance<D>> extends AbstractDistance
final KNNQuery<O, D> knnQuery = database.getKNNQuery(distanceQuery, k);
final Random random = new Random();
- List<D> knnDistances = new ArrayList<D>(relation.size());
+ List<D> knnDistances = new ArrayList<>(relation.size());
for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
if(random.nextDouble() < percentage) {
- final KNNResult<D> neighbors = knnQuery.getKNNForDBID(iditer, k);
+ final KNNList<D> neighbors = knnQuery.getKNNForDBID(iditer, k);
knnDistances.add(neighbors.getKNNDistance());
}
}
Collections.sort(knnDistances, Collections.reverseOrder());
- return new KNNDistanceOrderResult<D>("kNN distance order", "knn-order", knnDistances);
+ return new KNNDistanceOrderResult<>("kNN distance order", "knn-order", knnDistances);
}
@Override
@@ -179,7 +179,7 @@ public class KNNDistanceOrder<O, D extends Distance<D>> extends AbstractDistance
@Override
protected KNNDistanceOrder<O, D> makeInstance() {
- return new KNNDistanceOrder<O, D>(distanceFunction, k, percentage);
+ return new KNNDistanceOrder<>(distanceFunction, k, percentage);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/KNNJoin.java b/src/de/lmu/ifi/dbs/elki/algorithm/KNNJoin.java
index 9e73d959..dddd8fdb 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/KNNJoin.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/KNNJoin.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -36,16 +36,16 @@ import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
import de.lmu.ifi.dbs.elki.database.datastore.WritableDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNHeap;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNHeap;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.DistanceUtil;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDoubleDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceKNNHeap;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNHeap;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNUtil;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.index.tree.LeafEntry;
import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry;
@@ -56,7 +56,7 @@ import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
import de.lmu.ifi.dbs.elki.logging.progress.IndefiniteProgress;
import de.lmu.ifi.dbs.elki.result.ResultUtil;
-import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.Heap;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.ComparableMinHeap;
import de.lmu.ifi.dbs.elki.utilities.documentation.Description;
import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
@@ -84,7 +84,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
*/
@Title("K-Nearest Neighbor Join")
@Description("Algorithm to find the k-nearest neighbors of each object in a spatial database")
-public class KNNJoin<V extends NumberVector<?>, D extends Distance<D>, N extends SpatialNode<N, E>, E extends SpatialEntry> extends AbstractDistanceBasedAlgorithm<V, D, DataStore<KNNResult<D>>> {
+public class KNNJoin<V extends NumberVector<?>, D extends Distance<D>, N extends SpatialNode<N, E>, E extends SpatialEntry> extends AbstractDistanceBasedAlgorithm<V, D, DataStore<KNNList<D>>> {
/**
* The logger for this class.
*/
@@ -120,7 +120,7 @@ public class KNNJoin<V extends NumberVector<?>, D extends Distance<D>, N extends
* @return result
*/
@SuppressWarnings("unchecked")
- public WritableDataStore<KNNResult<D>> run(Database database, Relation<V> relation) {
+ public WritableDataStore<KNNList<D>> run(Database database, Relation<V> relation) {
if (!(getDistanceFunction() instanceof SpatialPrimitiveDistanceFunction)) {
throw new IllegalStateException("Distance Function must be an instance of " + SpatialPrimitiveDistanceFunction.class.getName());
}
@@ -134,10 +134,10 @@ public class KNNJoin<V extends NumberVector<?>, D extends Distance<D>, N extends
DBIDs ids = relation.getDBIDs();
// data pages
- List<E> ps_candidates = new ArrayList<E>(index.getLeaves());
+ List<E> ps_candidates = new ArrayList<>(index.getLeaves());
// knn heaps
- List<List<KNNHeap<D>>> heaps = new ArrayList<List<KNNHeap<D>>>(ps_candidates.size());
- Heap<Task> pq = new Heap<Task>(ps_candidates.size() * ps_candidates.size() / 10);
+ List<List<KNNHeap<D>>> heaps = new ArrayList<>(ps_candidates.size());
+ ComparableMinHeap<Task> pq = new ComparableMinHeap<>(ps_candidates.size() * ps_candidates.size() / 10);
// Initialize with the page self-pairing
for (int i = 0; i < ps_candidates.size(); i++) {
@@ -217,7 +217,7 @@ public class KNNJoin<V extends NumberVector<?>, D extends Distance<D>, N extends
fprogress.setCompleted(LOG);
}
- WritableDataStore<KNNResult<D>> knnLists = DataStoreUtil.makeStorage(ids, DataStoreFactory.HINT_STATIC, KNNResult.class);
+ WritableDataStore<KNNList<D>> knnLists = DataStoreUtil.makeStorage(ids, DataStoreFactory.HINT_STATIC, KNNList.class);
// FiniteProgress progress = logger.isVerbose() ? new
// FiniteProgress(this.getClass().getName(), relation.size(), logger) :
// null;
@@ -259,10 +259,10 @@ public class KNNJoin<V extends NumberVector<?>, D extends Distance<D>, N extends
* @return List of heaps
*/
private List<KNNHeap<D>> initHeaps(SpatialPrimitiveDistanceFunction<V, D> distFunction, N pr) {
- List<KNNHeap<D>> pr_heaps = new ArrayList<KNNHeap<D>>(pr.getNumEntries());
+ List<KNNHeap<D>> pr_heaps = new ArrayList<>(pr.getNumEntries());
// Create for each data object a knn heap
for (int j = 0; j < pr.getNumEntries(); j++) {
- pr_heaps.add(KNNUtil.newHeap(distFunction, k));
+ pr_heaps.add(DBIDUtil.newHeap(distFunction.getDistanceFactory(), k));
}
// Self-join first, as this is expected to improve most and cannot be
// pruned.
@@ -429,7 +429,7 @@ public class KNNJoin<V extends NumberVector<?>, D extends Distance<D>, N extends
@Override
protected KNNJoin<V, D, N, E> makeInstance() {
- return new KNNJoin<V, D, N, E>(distanceFunction, k);
+ return new KNNJoin<>(distanceFunction, k);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/MaterializeDistances.java b/src/de/lmu/ifi/dbs/elki/algorithm/MaterializeDistances.java
index 95a2a2b9..b02e9fed 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/MaterializeDistances.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/MaterializeDistances.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -82,7 +82,7 @@ public class MaterializeDistances<O, D extends NumberDistance<D, ?>> extends Abs
DistanceQuery<O, D> distFunc = database.getDistanceQuery(relation, getDistanceFunction());
final int size = relation.size();
- Collection<CTriple<DBID, DBID, Double>> r = new ArrayList<CTriple<DBID, DBID, Double>>(size * (size + 1) >> 1);
+ Collection<CTriple<DBID, DBID, Double>> r = new ArrayList<>(size * (size + 1) >> 1);
for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
for(DBIDIter iditer2 = relation.iterDBIDs(); iditer2.valid(); iditer2.advance()) {
@@ -91,10 +91,10 @@ public class MaterializeDistances<O, D extends NumberDistance<D, ?>> extends Abs
continue;
}
double d = distFunc.distance(iditer, iditer2).doubleValue();
- r.add(new CTriple<DBID, DBID, Double>(DBIDUtil.deref(iditer), DBIDUtil.deref(iditer2), d));
+ r.add(new CTriple<>(DBIDUtil.deref(iditer), DBIDUtil.deref(iditer2), d));
}
}
- return new CollectionResult<CTriple<DBID, DBID, Double>>("Distance Matrix", "distance-matrix", r);
+ return new CollectionResult<>("Distance Matrix", "distance-matrix", r);
}
@Override
@@ -117,7 +117,7 @@ public class MaterializeDistances<O, D extends NumberDistance<D, ?>> extends Abs
public static class Parameterizer<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBasedAlgorithm.Parameterizer<O, D> {
@Override
protected MaterializeDistances<O, D> makeInstance() {
- return new MaterializeDistances<O, D>(distanceFunction);
+ return new MaterializeDistances<>(distanceFunction);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/NullAlgorithm.java b/src/de/lmu/ifi/dbs/elki/algorithm/NullAlgorithm.java
index abd4c963..bb3f7f0d 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/NullAlgorithm.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/NullAlgorithm.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/benchmark/KNNBenchmarkAlgorithm.java b/src/de/lmu/ifi/dbs/elki/algorithm/benchmark/KNNBenchmarkAlgorithm.java
index b0ea8cc1..40726793 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/benchmark/KNNBenchmarkAlgorithm.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/benchmark/KNNBenchmarkAlgorithm.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.benchmark;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -31,14 +31,15 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRange;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.datasource.DatabaseConnection;
import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
import de.lmu.ifi.dbs.elki.math.MeanVariance;
@@ -117,7 +118,7 @@ public class KNNBenchmarkAlgorithm<O, D extends Distance<D>> extends AbstractDis
public Result run(Database database, Relation<O> relation) {
// Get a distance and kNN query instance.
DistanceQuery<O, D> distQuery = database.getDistanceQuery(relation, getDistanceFunction());
- KNNQuery<O, D> knnQuery = database.getKNNQuery(distQuery, 10);
+ KNNQuery<O, D> knnQuery = database.getKNNQuery(distQuery, k);
// No query set - use original database.
if (queries == null) {
@@ -131,17 +132,21 @@ public class KNNBenchmarkAlgorithm<O, D extends Distance<D>> extends AbstractDis
int size = (int) Math.min(sampling, relation.size());
sample = DBIDUtil.randomSample(relation.getDBIDs(), size, random);
}
- FiniteProgress prog = LOG.isVerbose() ? new FiniteProgress("kNN queries", sample.size(), LOG) : null;
+ FiniteProgress prog = LOG.isVeryVerbose() ? new FiniteProgress("kNN queries", sample.size(), LOG) : null;
int hash = 0;
- MeanVariance mv = new MeanVariance();
+ MeanVariance mv = new MeanVariance(), mvdist = new MeanVariance();
for (DBIDIter iditer = sample.iter(); iditer.valid(); iditer.advance()) {
- KNNResult<D> knns = knnQuery.getKNNForDBID(iditer, k);
+ KNNList<D> knns = knnQuery.getKNNForDBID(iditer, k);
int ichecksum = 0;
for (DBIDIter it = knns.iter(); it.valid(); it.advance()) {
ichecksum += it.internalGetIndex();
}
hash = Util.mixHashCodes(hash, ichecksum);
mv.put(knns.size());
+ D kdist = knns.getKNNDistance();
+ if (kdist instanceof NumberDistance) {
+ mvdist.put(((NumberDistance<?, ?>) kdist).doubleValue());
+ }
if (prog != null) {
prog.incrementProcessed(LOG);
}
@@ -149,9 +154,12 @@ public class KNNBenchmarkAlgorithm<O, D extends Distance<D>> extends AbstractDis
if (prog != null) {
prog.ensureCompleted(LOG);
}
- if (LOG.isVerbose()) {
- LOG.verbose("Result hashcode: " + hash);
- LOG.verbose("Mean number of results: "+mv.toString());
+ if (LOG.isStatistics()) {
+ LOG.statistics("Result hashcode: " + hash);
+ LOG.statistics("Mean number of results: " + mv.getMean() + " +- " + mv.getNaiveStddev());
+ if (mvdist.getCount() > 0) {
+ LOG.statistics("Mean k-distance: " + mvdist.getMean() + " +- " + mvdist.getNaiveStddev());
+ }
}
} else {
// Separate query set.
@@ -181,32 +189,39 @@ public class KNNBenchmarkAlgorithm<O, D extends Distance<D>> extends AbstractDis
int size = (int) Math.min(sampling, sids.size());
sample = DBIDUtil.randomSample(sids, size, random);
}
- FiniteProgress prog = LOG.isVerbose() ? new FiniteProgress("kNN queries", sample.size(), LOG) : null;
+ FiniteProgress prog = LOG.isVeryVerbose() ? new FiniteProgress("kNN queries", sample.size(), LOG) : null;
int hash = 0;
- MeanVariance mv = new MeanVariance();
+ MeanVariance mv = new MeanVariance(), mvdist = new MeanVariance();
for (DBIDIter iditer = sample.iter(); iditer.valid(); iditer.advance()) {
int off = sids.binarySearch(iditer);
assert (off >= 0);
@SuppressWarnings("unchecked")
O o = (O) bundle.data(off, col);
- KNNResult<D> knns = knnQuery.getKNNForObject(o, k);
+ KNNList<D> knns = knnQuery.getKNNForObject(o, k);
int ichecksum = 0;
for (DBIDIter it = knns.iter(); it.valid(); it.advance()) {
ichecksum += it.internalGetIndex();
}
hash = Util.mixHashCodes(hash, ichecksum);
mv.put(knns.size());
+ D kdist = knns.getKNNDistance();
+ if (kdist instanceof NumberDistance) {
+ mvdist.put(((NumberDistance<?, ?>) kdist).doubleValue());
+ }
if (prog != null) {
prog.incrementProcessed(LOG);
}
- if (LOG.isVerbose()) {
- LOG.verbose("Result hashcode: " + hash);
- LOG.verbose("Mean number of results: "+mv.toString());
- }
}
if (prog != null) {
prog.ensureCompleted(LOG);
}
+ if (LOG.isStatistics()) {
+ LOG.statistics("Result hashcode: " + hash);
+ LOG.statistics("Mean number of results: " + mv.getMean() + " +- " + mv.getNaiveStddev());
+ if (mvdist.getCount() > 0) {
+ LOG.statistics("Mean k-distance: " + mvdist.getMean() + " +- " + mvdist.getNaiveStddev());
+ }
+ }
}
return null;
}
@@ -279,7 +294,7 @@ public class KNNBenchmarkAlgorithm<O, D extends Distance<D>> extends AbstractDis
if (config.grab(kP)) {
k = kP.intValue();
}
- ObjectParameter<DatabaseConnection> queryP = new ObjectParameter<DatabaseConnection>(QUERY_ID, DatabaseConnection.class);
+ ObjectParameter<DatabaseConnection> queryP = new ObjectParameter<>(QUERY_ID, DatabaseConnection.class);
queryP.setOptional(true);
if (config.grab(queryP)) {
queries = queryP.instantiateClass(config);
@@ -297,7 +312,7 @@ public class KNNBenchmarkAlgorithm<O, D extends Distance<D>> extends AbstractDis
@Override
protected KNNBenchmarkAlgorithm<O, D> makeInstance() {
- return new KNNBenchmarkAlgorithm<O, D>(distanceFunction, k, queries, sampling, random);
+ return new KNNBenchmarkAlgorithm<>(distanceFunction, k, queries, sampling, random);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/benchmark/RangeQueryBenchmarkAlgorithm.java b/src/de/lmu/ifi/dbs/elki/algorithm/benchmark/RangeQueryBenchmarkAlgorithm.java
index f483321d..1b5e827b 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/benchmark/RangeQueryBenchmarkAlgorithm.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/benchmark/RangeQueryBenchmarkAlgorithm.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.benchmark;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -34,6 +34,7 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRange;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
@@ -41,7 +42,6 @@ import de.lmu.ifi.dbs.elki.database.relation.RelationUtil;
import de.lmu.ifi.dbs.elki.datasource.DatabaseConnection;
import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
@@ -160,12 +160,12 @@ public class RangeQueryBenchmarkAlgorithm<O extends NumberVector<?>, D extends N
int size = (int) Math.min(sampling, relation.size());
sample = DBIDUtil.randomSample(relation.getDBIDs(), size, random);
}
- FiniteProgress prog = LOG.isVerbose() ? new FiniteProgress("kNN queries", sample.size(), LOG) : null;
+ FiniteProgress prog = LOG.isVeryVerbose() ? new FiniteProgress("kNN queries", sample.size(), LOG) : null;
int hash = 0;
MeanVariance mv = new MeanVariance();
for (DBIDIter iditer = sample.iter(); iditer.valid(); iditer.advance()) {
D r = dfactory.fromDouble(radrel.get(iditer).doubleValue(0));
- DistanceDBIDResult<D> rres = rangeQuery.getRangeForDBID(iditer, r);
+ DistanceDBIDList<D> rres = rangeQuery.getRangeForDBID(iditer, r);
int ichecksum = 0;
for (DBIDIter it = rres.iter(); it.valid(); it.advance()) {
ichecksum += it.internalGetIndex();
@@ -179,9 +179,9 @@ public class RangeQueryBenchmarkAlgorithm<O extends NumberVector<?>, D extends N
if (prog != null) {
prog.ensureCompleted(LOG);
}
- if (LOG.isVerbose()) {
- LOG.verbose("Result hashcode: " + hash);
- LOG.verbose("Mean number of results: "+mv.toString());
+ if (LOG.isStatistics()) {
+ LOG.statistics("Result hashcode: " + hash);
+ LOG.statistics("Mean number of results: " + mv.getMean() + " +- " + mv.getNaiveStddev());
}
return null;
}
@@ -241,7 +241,7 @@ public class RangeQueryBenchmarkAlgorithm<O extends NumberVector<?>, D extends N
int size = (int) Math.min(sampling, sids.size());
sample = DBIDUtil.randomSample(sids, size, random);
}
- FiniteProgress prog = LOG.isVerbose() ? new FiniteProgress("kNN queries", sample.size(), LOG) : null;
+ FiniteProgress prog = LOG.isVeryVerbose() ? new FiniteProgress("kNN queries", sample.size(), LOG) : null;
int hash = 0;
MeanVariance mv = new MeanVariance();
double[] buf = new double[dim];
@@ -254,7 +254,7 @@ public class RangeQueryBenchmarkAlgorithm<O extends NumberVector<?>, D extends N
}
O v = ofactory.newNumberVector(buf);
D r = dfactory.fromDouble(o.doubleValue(dim));
- DistanceDBIDResult<D> rres = rangeQuery.getRangeForObject(v, r);
+ DistanceDBIDList<D> rres = rangeQuery.getRangeForObject(v, r);
int ichecksum = 0;
for (DBIDIter it = rres.iter(); it.valid(); it.advance()) {
ichecksum += it.internalGetIndex();
@@ -268,9 +268,9 @@ public class RangeQueryBenchmarkAlgorithm<O extends NumberVector<?>, D extends N
if (prog != null) {
prog.ensureCompleted(LOG);
}
- if (LOG.isVerbose()) {
- LOG.verbose("Result hashcode: " + hash);
- LOG.verbose("Mean number of results: "+mv.toString());
+ if (LOG.isStatistics()) {
+ LOG.statistics("Result hashcode: " + hash);
+ LOG.statistics("Mean number of results: " + mv.getMean() + " +- " + mv.getNaiveStddev());
}
return null;
}
@@ -333,7 +333,7 @@ public class RangeQueryBenchmarkAlgorithm<O extends NumberVector<?>, D extends N
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- ObjectParameter<DatabaseConnection> queryP = new ObjectParameter<DatabaseConnection>(QUERY_ID, DatabaseConnection.class);
+ ObjectParameter<DatabaseConnection> queryP = new ObjectParameter<>(QUERY_ID, DatabaseConnection.class);
queryP.setOptional(true);
if (config.grab(queryP)) {
queries = queryP.instantiateClass(config);
@@ -351,7 +351,7 @@ public class RangeQueryBenchmarkAlgorithm<O extends NumberVector<?>, D extends N
@Override
protected RangeQueryBenchmarkAlgorithm<O, D> makeInstance() {
- return new RangeQueryBenchmarkAlgorithm<O, D>(distanceFunction, queries, sampling, random);
+ return new RangeQueryBenchmarkAlgorithm<>(distanceFunction, queries, sampling, random);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/benchmark/ValidateApproximativeKNNIndex.java b/src/de/lmu/ifi/dbs/elki/algorithm/benchmark/ValidateApproximativeKNNIndex.java
new file mode 100644
index 00000000..3d0ea52a
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/benchmark/ValidateApproximativeKNNIndex.java
@@ -0,0 +1,430 @@
+package de.lmu.ifi.dbs.elki.algorithm.benchmark;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.regex.Pattern;
+
+import de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm;
+import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
+import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.database.Database;
+import de.lmu.ifi.dbs.elki.database.QueryUtil;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDRange;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
+import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery;
+import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
+import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
+import de.lmu.ifi.dbs.elki.database.query.knn.LinearScanKNNQuery;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.datasource.DatabaseConnection;
+import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
+import de.lmu.ifi.dbs.elki.math.MeanVariance;
+import de.lmu.ifi.dbs.elki.result.Result;
+import de.lmu.ifi.dbs.elki.utilities.DatabaseUtil;
+import de.lmu.ifi.dbs.elki.utilities.RandomFactory;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleParameter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Flag;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.PatternParameter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.RandomParameter;
+
+/**
+ * Algorithm to validate the quality of an approximative kNN index, by
+ * performing a number of queries and comparing them to the results obtained by
+ * exact indexing (e.g. linear scanning).
+ *
+ * @author Erich Schubert
+ *
+ * @param <O> Object type
+ *
+ * @apiviz.uses KNNQuery
+ */
+public class ValidateApproximativeKNNIndex<O, D extends Distance<D>> extends AbstractDistanceBasedAlgorithm<O, D, Result> {
+ /**
+ * The logger for this class.
+ */
+ private static final Logging LOG = Logging.getLogger(ValidateApproximativeKNNIndex.class);
+
+ /**
+ * Number of neighbors to retrieve.
+ */
+ protected int k = 10;
+
+ /**
+ * The alternate query point source. Optional.
+ */
+ protected DatabaseConnection queries = null;
+
+ /**
+ * Sampling size.
+ */
+ protected double sampling = -1;
+
+ /**
+ * Force linear scanning.
+ */
+ protected boolean forcelinear = false;
+
+ /**
+ * Random generator factory
+ */
+ protected RandomFactory random;
+
+ /**
+ * Filter pattern
+ */
+ protected Pattern pattern;
+
+ /**
+ * Constructor.
+ *
+ * @param distanceFunction Distance function to use
+ * @param k K parameter
+ * @param queries Query data set (may be null!)
+ * @param sampling Sampling rate
+ * @param random Random factory
+ * @param forcelinear Force the use of linear scanning.
+ * @param pattern
+ */
+ public ValidateApproximativeKNNIndex(DistanceFunction<? super O, D> distanceFunction, int k, DatabaseConnection queries, double sampling, boolean forcelinear, RandomFactory random, Pattern pattern) {
+ super(distanceFunction);
+ this.k = k;
+ this.queries = queries;
+ this.sampling = sampling;
+ this.forcelinear = forcelinear;
+ this.random = random;
+ this.pattern = pattern;
+ }
+
+ /**
+ * Run the algorithm.
+ *
+ * @param database Database
+ * @param relation Relation
+ * @return Null result
+ */
+ public Result run(Database database, Relation<O> relation) {
+ // Get a distance and kNN query instance.
+ DistanceQuery<O, D> distQuery = database.getDistanceQuery(relation, getDistanceFunction());
+ // Approximate query:
+ KNNQuery<O, D> knnQuery = database.getKNNQuery(distQuery, k, DatabaseQuery.HINT_OPTIMIZED_ONLY);
+ if (knnQuery == null || knnQuery instanceof LinearScanKNNQuery) {
+ throw new AbortException("Expected an accelerated query, but got a linear scan -- index is not used.");
+ }
+ // Exact query:
+ KNNQuery<O, D> truekNNQuery;
+ if (forcelinear) {
+ truekNNQuery = QueryUtil.getLinearScanKNNQuery(distQuery);
+ } else {
+ truekNNQuery = database.getKNNQuery(distQuery, k, DatabaseQuery.HINT_EXACT);
+ }
+ if (knnQuery.getClass().equals(truekNNQuery.getClass())) {
+ LOG.warning("Query classes are the same. This experiment may be invalid!");
+ }
+
+ // No query set - use original database.
+ if (queries == null || pattern != null) {
+ // Relation to filter on
+ Relation<String> lrel = (pattern != null) ? DatabaseUtil.guessLabelRepresentation(database) : null;
+
+ final DBIDs sample;
+ if (sampling <= 0) {
+ sample = relation.getDBIDs();
+ } else if (sampling < 1.1) {
+ int size = (int) Math.min(sampling * relation.size(), relation.size());
+ sample = DBIDUtil.randomSample(relation.getDBIDs(), size, random);
+ } else {
+ int size = (int) Math.min(sampling, relation.size());
+ sample = DBIDUtil.randomSample(relation.getDBIDs(), size, random);
+ }
+ FiniteProgress prog = LOG.isVeryVerbose() ? new FiniteProgress("kNN queries", sample.size(), LOG) : null;
+ MeanVariance mv = new MeanVariance(), mvrec = new MeanVariance();
+ MeanVariance mvdist = new MeanVariance(), mvdaerr = new MeanVariance(), mvdrerr = new MeanVariance();
+ int misses = 0;
+ for (DBIDIter iditer = sample.iter(); iditer.valid(); iditer.advance()) {
+ if (pattern == null || pattern.matcher(lrel.get(iditer)).find()) {
+ // Query index:
+ KNNList<D> knns = knnQuery.getKNNForDBID(iditer, k);
+ // Query reference:
+ KNNList<D> trueknns = truekNNQuery.getKNNForDBID(iditer, k);
+
+ // Put adjusted knn size:
+ mv.put(knns.size() * k / (double) trueknns.size());
+
+ // Put recall:
+ mvrec.put(DBIDUtil.intersectionSize(knns, trueknns) / trueknns.size());
+
+ if (knns.size() >= k) {
+ D kdist = knns.getKNNDistance();
+ if (kdist instanceof NumberDistance) {
+ final double dist = ((NumberDistance<?, ?>) kdist).doubleValue();
+ final double tdist = ((NumberDistance<?, ?>) trueknns.getKNNDistance()).doubleValue();
+ if (tdist > 0.0) {
+ mvdist.put(dist);
+ mvdaerr.put(dist - tdist);
+ mvdrerr.put(dist / tdist);
+ }
+ }
+ } else {
+ // Less than k objects.
+ misses++;
+ }
+ }
+ if (prog != null) {
+ prog.incrementProcessed(LOG);
+ }
+ }
+ if (prog != null) {
+ prog.ensureCompleted(LOG);
+ }
+ if (LOG.isStatistics()) {
+ LOG.statistics("Mean number of results: " + mv.getMean() + " +- " + mv.getNaiveStddev());
+ LOG.statistics("Recall of true results: " + mvrec.getMean() + " +- " + mvrec.getNaiveStddev());
+ if (mvdist.getCount() > 0) {
+ LOG.statistics("Mean k-distance: " + mvdist.getMean() + " +- " + mvdist.getNaiveStddev());
+ LOG.statistics("Mean absolute k-error: " + mvdaerr.getMean() + " +- " + mvdaerr.getNaiveStddev());
+ LOG.statistics("Mean relative k-error: " + mvdrerr.getMean() + " +- " + mvdrerr.getNaiveStddev());
+ }
+ if (misses > 0) {
+ LOG.statistics(String.format("Number of queries that returned less than k=%d objects: %d (%.2f%%)", k, misses, misses * 100. / mv.getCount()));
+ }
+ }
+ } else {
+ // Separate query set.
+ TypeInformation res = getDistanceFunction().getInputTypeRestriction();
+ MultipleObjectsBundle bundle = queries.loadData();
+ int col = -1;
+ for (int i = 0; i < bundle.metaLength(); i++) {
+ if (res.isAssignableFromType(bundle.meta(i))) {
+ col = i;
+ break;
+ }
+ }
+ if (col < 0) {
+ throw new AbortException("No compatible data type in query input was found. Expected: " + res.toString());
+ }
+ // Random sampling is a bit of hack, sorry.
+ // But currently, we don't (yet) have an "integer random sample" function.
+ DBIDRange sids = DBIDUtil.generateStaticDBIDRange(bundle.dataLength());
+
+ final DBIDs sample;
+ if (sampling <= 0) {
+ sample = sids;
+ } else if (sampling < 1.1) {
+ int size = (int) Math.min(sampling * relation.size(), relation.size());
+ sample = DBIDUtil.randomSample(sids, size, random);
+ } else {
+ int size = (int) Math.min(sampling, sids.size());
+ sample = DBIDUtil.randomSample(sids, size, random);
+ }
+ FiniteProgress prog = LOG.isVeryVerbose() ? new FiniteProgress("kNN queries", sample.size(), LOG) : null;
+ MeanVariance mv = new MeanVariance(), mvrec = new MeanVariance();
+ MeanVariance mvdist = new MeanVariance(), mvdaerr = new MeanVariance(), mvdrerr = new MeanVariance();
+ int misses = 0;
+ for (DBIDIter iditer = sample.iter(); iditer.valid(); iditer.advance()) {
+ int off = sids.binarySearch(iditer);
+ assert (off >= 0);
+ @SuppressWarnings("unchecked")
+ O o = (O) bundle.data(off, col);
+
+ // Query index:
+ KNNList<D> knns = knnQuery.getKNNForObject(o, k);
+ // Query reference:
+ KNNList<D> trueknns = truekNNQuery.getKNNForObject(o, k);
+
+ // Put adjusted knn size:
+ mv.put(knns.size() * k / (double) trueknns.size());
+
+ // Put recall:
+ mvrec.put(DBIDUtil.intersectionSize(knns, trueknns) / trueknns.size());
+
+ if (knns.size() >= k) {
+ D kdist = knns.getKNNDistance();
+ if (kdist instanceof NumberDistance) {
+ final double dist = ((NumberDistance<?, ?>) kdist).doubleValue();
+ final double tdist = ((NumberDistance<?, ?>) trueknns.getKNNDistance()).doubleValue();
+ if (tdist > 0.0) {
+ mvdist.put(dist);
+ mvdaerr.put(dist - tdist);
+ mvdrerr.put(dist / tdist);
+ }
+ }
+ } else {
+ // Less than k objects.
+ misses++;
+ }
+ if (prog != null) {
+ prog.incrementProcessed(LOG);
+ }
+ }
+ if (prog != null) {
+ prog.ensureCompleted(LOG);
+ }
+ if (LOG.isStatistics()) {
+ LOG.statistics("Mean number of results: " + mv.getMean() + " +- " + mv.getNaiveStddev());
+ LOG.statistics("Recall of true results: " + mvrec.getMean() + " +- " + mvrec.getNaiveStddev());
+ if (mvdist.getCount() > 0) {
+ LOG.statistics("Mean absolute k-error: " + mvdaerr.getMean() + " +- " + mvdaerr.getNaiveStddev());
+ LOG.statistics("Mean relative k-error: " + mvdrerr.getMean() + " +- " + mvdrerr.getNaiveStddev());
+ }
+ if (misses > 0) {
+ LOG.statistics(String.format("Number of queries that returned less than k=%d objects: %d (%.2f%%)", k, misses, misses * 100. / mv.getCount()));
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public TypeInformation[] getInputTypeRestriction() {
+ return TypeUtil.array(getDistanceFunction().getInputTypeRestriction());
+ }
+
+ @Override
+ protected Logging getLogger() {
+ return LOG;
+ }
+
+ /**
+ * Parameterization class
+ *
+ * @apiviz.exclude
+ *
+ * @author Erich Schubert
+ *
+ * @param <O> Object type
+ * @param <D> Distance type
+ */
+ public static class Parameterizer<O, D extends Distance<D>> extends AbstractDistanceBasedAlgorithm.Parameterizer<O, D> {
+ /**
+ * Parameter for the number of neighbors.
+ */
+ public static final OptionID K_ID = new OptionID("validateknn.k", "Number of neighbors to retreive for kNN benchmarking.");
+
+ /**
+ * Parameter for the query dataset.
+ */
+ public static final OptionID QUERY_ID = new OptionID("validateknn.query", "Data source for the queries. If not set, the queries are taken from the database.");
+
+ /**
+ * Parameter for the sampling size.
+ */
+ public static final OptionID SAMPLING_ID = new OptionID("validateknn.sampling", "Sampling size parameter. If the value is less or equal 1, it is assumed to be the relative share. Larger values will be interpreted as integer sizes. By default, all data will be used.");
+
+ /**
+ * Force linear scanning.
+ */
+ public static final OptionID FORCE_ID = new OptionID("validateknn.force-linear", "Force the use of linear scanning as reference.");
+
+ /**
+ * Parameter for the random generator.
+ */
+ public static final OptionID RANDOM_ID = new OptionID("validateknn.random", "Random generator for sampling.");
+
+ /**
+ * Parameter to select query points.
+ */
+ public static final OptionID PATTERN_ID = new OptionID("validateknn.pattern", "Pattern to select query points.");
+
+ /**
+ * K parameter
+ */
+ protected int k = 10;
+
+ /**
+ * The alternate query point source. Optional.
+ */
+ protected DatabaseConnection queries = null;
+
+ /**
+ * Sampling size.
+ */
+ protected double sampling = -1;
+
+ /**
+ * Force linear scanning.
+ */
+ protected boolean forcelinear = false;
+
+ /**
+ * Random generator factory
+ */
+ protected RandomFactory random;
+
+ /**
+ * Filter pattern for query points.
+ */
+ protected Pattern pattern;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ IntParameter kP = new IntParameter(K_ID);
+ if (config.grab(kP)) {
+ k = kP.intValue();
+ }
+ PatternParameter patternP = new PatternParameter(PATTERN_ID);
+ patternP.setOptional(true);
+ if (config.grab(patternP)) {
+ pattern = patternP.getValue();
+ } else {
+ ObjectParameter<DatabaseConnection> queryP = new ObjectParameter<>(QUERY_ID, DatabaseConnection.class);
+ queryP.setOptional(true);
+ if (config.grab(queryP)) {
+ queries = queryP.instantiateClass(config);
+ }
+ }
+ DoubleParameter samplingP = new DoubleParameter(SAMPLING_ID);
+ samplingP.setOptional(true);
+ if (config.grab(samplingP)) {
+ sampling = samplingP.doubleValue();
+ }
+ Flag forceP = new Flag(FORCE_ID);
+ if (config.grab(forceP)) {
+ forcelinear = forceP.isTrue();
+ }
+ RandomParameter randomP = new RandomParameter(RANDOM_ID, RandomFactory.DEFAULT);
+ if (config.grab(randomP)) {
+ random = randomP.getValue();
+ }
+ }
+
+ @Override
+ protected ValidateApproximativeKNNIndex<O, D> makeInstance() {
+ return new ValidateApproximativeKNNIndex<>(distanceFunction, k, queries, sampling, forcelinear, random, pattern);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/benchmark/package-info.java b/src/de/lmu/ifi/dbs/elki/algorithm/benchmark/package-info.java
index 6a98fa64..b10ef2ed 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/benchmark/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/benchmark/package-info.java
@@ -8,7 +8,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/AbstractProjectedClustering.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/AbstractProjectedClustering.java
index 05cc2b4f..0c4eb5fc 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/AbstractProjectedClustering.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/AbstractProjectedClustering.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -31,7 +31,7 @@ import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.database.QueryUtil;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/AbstractProjectedDBSCAN.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/AbstractProjectedDBSCAN.java
index f8b73f48..ee3b234c 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/AbstractProjectedDBSCAN.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/AbstractProjectedDBSCAN.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -41,14 +41,14 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDMIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter;
import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancefunction.IndexBasedDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancefunction.LocallyWeightedDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultIter;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
@@ -179,7 +179,7 @@ public abstract class AbstractProjectedDBSCAN<R extends Clustering<Model>, V ext
public Clustering<Model> run(Database database, Relation<V> relation) {
FiniteProgress objprog = getLogger().isVerbose() ? new FiniteProgress("Processing objects", relation.size(), getLogger()) : null;
IndefiniteProgress clusprog = getLogger().isVerbose() ? new IndefiniteProgress("Number of clusters", getLogger()) : null;
- resultList = new ArrayList<ModifiableDBIDs>();
+ resultList = new ArrayList<>();
noise = DBIDUtil.newHashSet();
processedIDs = DBIDUtil.newHashSet(relation.size());
@@ -215,14 +215,14 @@ public abstract class AbstractProjectedDBSCAN<R extends Clustering<Model>, V ext
clusprog.setProcessed(resultList.size(), getLogger());
}
- Clustering<Model> result = new Clustering<Model>(getLongResultName(), getShortResultName());
+ Clustering<Model> result = new Clustering<>(getLongResultName(), getShortResultName());
for(Iterator<ModifiableDBIDs> resultListIter = resultList.iterator(); resultListIter.hasNext();) {
Cluster<Model> c = new Cluster<Model>(resultListIter.next(), ClusterModel.CLUSTER);
- result.addCluster(c);
+ result.addToplevelCluster(c);
}
Cluster<Model> n = new Cluster<Model>(noise, true, ClusterModel.CLUSTER);
- result.addCluster(n);
+ result.addToplevelCluster(n);
if(objprog != null && clusprog != null) {
objprog.setProcessed(processedIDs.size(), getLogger());
@@ -279,7 +279,7 @@ public abstract class AbstractProjectedDBSCAN<R extends Clustering<Model>, V ext
}
// compute weighted epsilon neighborhood
- DistanceDBIDResult<DoubleDistance> neighbors = rangeQuery.getRangeForDBID(startObjectID, epsilon);
+ DistanceDBIDList<DoubleDistance> neighbors = rangeQuery.getRangeForDBID(startObjectID, epsilon);
// neighbors < minPts -> noise
if(neighbors.size() < minpts) {
noise.add(startObjectID);
@@ -294,7 +294,7 @@ public abstract class AbstractProjectedDBSCAN<R extends Clustering<Model>, V ext
// try to expand the cluster
ModifiableDBIDs currentCluster = DBIDUtil.newArray();
ModifiableDBIDs seeds = DBIDUtil.newHashSet();
- for (DistanceDBIDResultIter<DoubleDistance> seed = neighbors.iter(); seed.valid(); seed.advance()) {
+ for (DistanceDBIDListIter<DoubleDistance> seed = neighbors.iter(); seed.valid(); seed.advance()) {
int nextID_corrDim = distFunc.getIndex().getLocalProjection(seed).getCorrelationDimension();
// nextID is not reachable from start object
if(nextID_corrDim > lambda) {
@@ -320,11 +320,11 @@ public abstract class AbstractProjectedDBSCAN<R extends Clustering<Model>, V ext
continue;
}
- DistanceDBIDResult<DoubleDistance> reachables = rangeQuery.getRangeForDBID(iter, epsilon);
+ DistanceDBIDList<DoubleDistance> reachables = rangeQuery.getRangeForDBID(iter, epsilon);
iter.remove();
if(reachables.size() > minpts) {
- for (DistanceDBIDResultIter<DoubleDistance> r = reachables.iter(); r.valid(); r.advance()) {
+ for (DistanceDBIDListIter<DoubleDistance> r = reachables.iter(); r.valid(); r.advance()) {
int corrDim_r = distFunc.getIndex().getLocalProjection(r).getCorrelationDimension();
// r is not reachable from q
if(corrDim_r > lambda) {
@@ -395,7 +395,7 @@ public abstract class AbstractProjectedDBSCAN<R extends Clustering<Model>, V ext
protected Integer lambda;
protected void configInnerDistance(Parameterization config) {
- ObjectParameter<DistanceFunction<V, D>> innerdistP = new ObjectParameter<DistanceFunction<V, D>>(AbstractProjectedDBSCAN.INNER_DISTANCE_FUNCTION_ID, DistanceFunction.class, EuclideanDistanceFunction.class);
+ ObjectParameter<DistanceFunction<V, D>> innerdistP = new ObjectParameter<>(AbstractProjectedDBSCAN.INNER_DISTANCE_FUNCTION_ID, DistanceFunction.class, EuclideanDistanceFunction.class);
if(config.grab(innerdistP)) {
innerdist = innerdistP.instantiateClass(config);
}
@@ -403,7 +403,7 @@ public abstract class AbstractProjectedDBSCAN<R extends Clustering<Model>, V ext
protected void configEpsilon(Parameterization config, DistanceFunction<V, D> innerdist) {
D distanceParser = innerdist != null ? innerdist.getDistanceFactory() : null;
- DistanceParameter<D> epsilonP = new DistanceParameter<D>(EPSILON_ID, distanceParser);
+ DistanceParameter<D> epsilonP = new DistanceParameter<>(EPSILON_ID, distanceParser);
if(config.grab(epsilonP)) {
epsilon = epsilonP.getValue();
}
@@ -418,7 +418,7 @@ public abstract class AbstractProjectedDBSCAN<R extends Clustering<Model>, V ext
}
protected void configOuterDistance(Parameterization config, D epsilon, int minpts, Class<?> preprocessorClass, DistanceFunction<V, D> innerdist) {
- ObjectParameter<LocallyWeightedDistanceFunction<V>> outerdistP = new ObjectParameter<LocallyWeightedDistanceFunction<V>>(OUTER_DISTANCE_FUNCTION_ID, LocallyWeightedDistanceFunction.class, LocallyWeightedDistanceFunction.class);
+ ObjectParameter<LocallyWeightedDistanceFunction<V>> outerdistP = new ObjectParameter<>(OUTER_DISTANCE_FUNCTION_ID, LocallyWeightedDistanceFunction.class, LocallyWeightedDistanceFunction.class);
if(config.grab(outerdistP)) {
// parameters for the distance function
ListParameterization distanceFunctionParameters = new ListParameterization();
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/CanopyPreClustering.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/CanopyPreClustering.java
new file mode 100644
index 00000000..2dff7554
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/CanopyPreClustering.java
@@ -0,0 +1,236 @@
+package de.lmu.ifi.dbs.elki.algorithm.clustering;
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.ArrayList;
+
+import de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm;
+import de.lmu.ifi.dbs.elki.data.Cluster;
+import de.lmu.ifi.dbs.elki.data.Clustering;
+import de.lmu.ifi.dbs.elki.data.model.ClusterModel;
+import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
+import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.database.Database;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDMIter;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDVar;
+import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.WrongParameterValueException;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DistanceParameter;
+
+/**
+ * Canopy pre-clustering is a simple preprocessing step for clustering.
+ *
+ * <p>
+ * Reference:<br>
+ * A. McCallum, K. Nigam, L.H. Ungar<br />
+ * Efficient Clustering of High Dimensional Data Sets with Application to
+ * Reference Matching<br />
+ * Proc. 6th ACM SIGKDD international conference on Knowledge discovery and data
+ * mining
+ * </p>
+ *
+ * @author Erich Schubert
+ *
+ * @param <O> Object type
+ * @param <D> Distance type
+ */
+@Reference(authors = "A. McCallum, K. Nigam, L.H. Ungar", title = "Efficient Clustering of High Dimensional Data Sets with Application to Reference Matching", booktitle = "Proc. 6th ACM SIGKDD international conference on Knowledge discovery and data mining", url = "http://dx.doi.org/10.1145%2F347090.347123")
+public class CanopyPreClustering<O, D extends Distance<D>> extends AbstractDistanceBasedAlgorithm<O, D, Clustering<ClusterModel>> implements ClusteringAlgorithm<Clustering<ClusterModel>> {
+ /**
+ * Class logger.
+ */
+ private static final Logging LOG = Logging.getLogger(CanopyPreClustering.class);
+
+ /**
+ * Threshold for inclusion
+ */
+ private D t1;
+
+ /**
+ * Threshold for removal
+ */
+ private D t2;
+
+ /**
+ * Constructor.
+ *
+ * @param distanceFunction Distance function
+ * @param t1 Inclusion threshold
+ * @param t2 Exclusion threshold
+ */
+ public CanopyPreClustering(DistanceFunction<? super O, D> distanceFunction, D t1, D t2) {
+ super(distanceFunction);
+ this.t1 = t1;
+ this.t2 = t2;
+ }
+
+ /**
+ * Run the algorithm
+ *
+ * @param database Database
+ * @param relation Relation to process
+ */
+ public Clustering<ClusterModel> run(Database database, Relation<O> relation) {
+ DistanceQuery<O, D> dq = database.getDistanceQuery(relation, getDistanceFunction());
+ ModifiableDBIDs ids = DBIDUtil.newHashSet(relation.getDBIDs());
+ ArrayList<Cluster<ClusterModel>> clusters = new ArrayList<>();
+ final int size = relation.size();
+
+ if(t1.compareTo(t2) <= 0) {
+ LOG.warning(Parameterizer.T1_ID.getName() + " must be larger than " + Parameterizer.T2_ID.getName());
+ }
+
+ FiniteProgress prog = LOG.isVerbose() ? new FiniteProgress("Canopy clustering", size, LOG) : null;
+
+ DBIDVar first = DBIDUtil.newVar();
+ while(!ids.isEmpty()) {
+ // Remove first element:
+ DBIDMIter iter = ids.iter();
+ first.set(iter);
+ iter.remove();
+ iter.advance();
+
+ // Start a new cluster:
+ ModifiableDBIDs cids = DBIDUtil.newArray();
+ cids.add(first);
+
+ // Compare to remaining objects:
+ for(; iter.valid(); iter.advance()) {
+ D dist = dq.distance(first, iter);
+ // Inclusion threshold:
+ if(t1.compareTo(dist) >= 0) {
+ cids.add(iter);
+ }
+ // Removal threshold:
+ if(t2.compareTo(dist) >= 0) {
+ iter.remove();
+ }
+ }
+ // TODO: remember the central object using a CanopyModel?
+ // Construct cluster:
+ clusters.add(new Cluster<>(cids, ClusterModel.CLUSTER));
+
+ if(prog != null) {
+ prog.setProcessed(size - ids.size(), LOG);
+ }
+ }
+ if(prog != null) {
+ prog.ensureCompleted(LOG);
+ }
+
+ return new Clustering<>("Canopy clustering", "canopy-clustering", clusters);
+ }
+
+ @Override
+ public TypeInformation[] getInputTypeRestriction() {
+ return TypeUtil.array(getDistanceFunction().getInputTypeRestriction());
+ }
+
+ @Override
+ protected Logging getLogger() {
+ return LOG;
+ }
+
+ /**
+ * Parameterization class
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ *
+ * @param <O> Object type
+ * @param <D> Distance type
+ */
+ public static class Parameterizer<O, D extends Distance<D>> extends AbstractDistanceBasedAlgorithm.Parameterizer<O, D> {
+ /**
+ * Parameter for the inclusion threshold of canopy clustering.
+ *
+ * Note: t1 > t2
+ *
+ * Syntax:
+ *
+ * <pre>
+ * -canopy.t1 &lt;value&gt;
+ * </pre>
+ */
+ public static final OptionID T1_ID = new OptionID("canopy.t1", "Inclusion threshold for canopy clustering. t1 > t2!");
+
+ /**
+ * Parameter for the removal threshold of canopy clustering.
+ *
+ * Note: t1 > t2
+ *
+ * Syntax:
+ *
+ * <pre>
+ * -canopy.t2 &lt;value&gt;
+ * </pre>
+ */
+ public static final OptionID T2_ID = new OptionID("canopy.t2", "Removal threshold for canopy clustering. t1 > t2!");
+
+ /**
+ * Threshold for inclusion
+ */
+ private D t1;
+
+ /**
+ * Threshold for removal
+ */
+ private D t2;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+
+ DistanceParameter<D> t1P = new DistanceParameter<>(T1_ID, distanceFunction);
+ if(config.grab(t1P)) {
+ t1 = t1P.getValue();
+ }
+
+ DistanceParameter<D> t2P = new DistanceParameter<>(T2_ID, distanceFunction);
+ // TODO: add distance constraint t1 > t2
+ if(config.grab(t2P)) {
+ t2 = t2P.getValue();
+ if(t1.compareTo(t2) <= 0) {
+ config.reportError(new WrongParameterValueException(t2P, T1_ID.getName() + " must be larger than " + T2_ID.getName()));
+ }
+ }
+ }
+
+ @Override
+ protected CanopyPreClustering<O, D> makeInstance() {
+ return new CanopyPreClustering<>(distanceFunction, t1, t2);
+ }
+
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/ClusteringAlgorithm.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/ClusteringAlgorithm.java
index 8f637460..249dc313 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/ClusteringAlgorithm.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/ClusteringAlgorithm.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -42,6 +42,7 @@ import de.lmu.ifi.dbs.elki.database.Database;
*
* @apiviz.has Clustering
* @apiviz.has Model
+ * @apiviz.excludeSubtypes
*
* @param <C> Clustering type
*/
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/DBSCAN.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/DBSCAN.java
index fcf81faa..57dcb435 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/DBSCAN.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/DBSCAN.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -40,10 +40,10 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.HashSetModifiableDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
@@ -140,7 +140,7 @@ public class DBSCAN<O, D extends Distance<D>> extends AbstractDistanceBasedAlgor
FiniteProgress objprog = LOG.isVerbose() ? new FiniteProgress("Processing objects", size, LOG) : null;
IndefiniteProgress clusprog = LOG.isVerbose() ? new IndefiniteProgress("Number of clusters", LOG) : null;
- resultList = new ArrayList<ModifiableDBIDs>();
+ resultList = new ArrayList<>();
noise = DBIDUtil.newHashSet();
processedIDs = DBIDUtil.newHashSet(size);
if(size < minpts) {
@@ -170,14 +170,14 @@ public class DBSCAN<O, D extends Distance<D>> extends AbstractDistanceBasedAlgor
clusprog.setCompleted(LOG);
}
- Clustering<Model> result = new Clustering<Model>("DBSCAN Clustering", "dbscan-clustering");
+ Clustering<Model> result = new Clustering<>("DBSCAN Clustering", "dbscan-clustering");
for(ModifiableDBIDs res : resultList) {
Cluster<Model> c = new Cluster<Model>(res, ClusterModel.CLUSTER);
- result.addCluster(c);
+ result.addToplevelCluster(c);
}
Cluster<Model> n = new Cluster<Model>(noise, true, ClusterModel.CLUSTER);
- result.addCluster(n);
+ result.addToplevelCluster(n);
return result;
}
@@ -193,7 +193,7 @@ public class DBSCAN<O, D extends Distance<D>> extends AbstractDistanceBasedAlgor
* @param objprog the progress object for logging the current status
*/
protected void expandCluster(Relation<O> relation, RangeQuery<O, D> rangeQuery, DBIDRef startObjectID, FiniteProgress objprog, IndefiniteProgress clusprog) {
- DistanceDBIDResult<D> neighbors = rangeQuery.getRangeForDBID(startObjectID, epsilon);
+ DistanceDBIDList<D> neighbors = rangeQuery.getRangeForDBID(startObjectID, epsilon);
// startObject is no core-object
if(neighbors.size() < minpts) {
@@ -224,7 +224,7 @@ public class DBSCAN<O, D extends Distance<D>> extends AbstractDistanceBasedAlgor
while(seeds.size() > 0) {
DBIDMIter o = seeds.iter();
- DistanceDBIDResult<D> neighborhood = rangeQuery.getRangeForDBID(o, epsilon);
+ DistanceDBIDList<D> neighborhood = rangeQuery.getRangeForDBID(o, epsilon);
o.remove();
if(neighborhood.size() >= minpts) {
@@ -289,7 +289,7 @@ public class DBSCAN<O, D extends Distance<D>> extends AbstractDistanceBasedAlgor
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- DistanceParameter<D> epsilonP = new DistanceParameter<D>(EPSILON_ID, distanceFunction);
+ DistanceParameter<D> epsilonP = new DistanceParameter<>(EPSILON_ID, distanceFunction);
if(config.grab(epsilonP)) {
epsilon = epsilonP.getValue();
}
@@ -303,7 +303,7 @@ public class DBSCAN<O, D extends Distance<D>> extends AbstractDistanceBasedAlgor
@Override
protected DBSCAN<O, D> makeInstance() {
- return new DBSCAN<O, D>(distanceFunction, epsilon, minpts);
+ return new DBSCAN<>(distanceFunction, epsilon, minpts);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/DeLiClu.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/DeLiClu.java
index 22875715..3c2e0278 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/DeLiClu.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/DeLiClu.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,9 +23,10 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import gnu.trove.set.TIntSet;
+
import java.util.Collection;
import java.util.List;
-import java.util.Set;
import de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm;
import de.lmu.ifi.dbs.elki.algorithm.KNNJoin;
@@ -37,11 +38,11 @@ import de.lmu.ifi.dbs.elki.database.datastore.DataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.DistanceUtil;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.index.tree.LeafEntry;
import de.lmu.ifi.dbs.elki.index.tree.TreeIndexPathComponent;
@@ -119,14 +120,14 @@ public class DeLiClu<NV extends NumberVector<?>, D extends Distance<D>> extends
*/
public DeLiClu(DistanceFunction<? super NV, D> distanceFunction, int minpts) {
super(distanceFunction);
- this.knnJoin = new KNNJoin<NV, D, DeLiCluNode, DeLiCluEntry>(distanceFunction, minpts);
+ this.knnJoin = new KNNJoin<>(distanceFunction, minpts);
this.minpts = minpts;
}
public ClusterOrderResult<D> run(Database database, Relation<NV> relation) {
Collection<DeLiCluTreeIndex<NV>> indexes = ResultUtil.filterResults(database, DeLiCluTreeIndex.class);
if(indexes.size() != 1) {
- throw new AbortException("DeLiClu found " + indexes.size() + " DeLiCluTree indexes, expected exactly one.");
+ throw new AbortException("DeLiClu found " + indexes.size() + " DeLiCluTree indexes. DeLiClu needs a special index to operate, therefore you need to add this index to your database.");
}
DeLiCluTreeIndex<NV> index = indexes.iterator().next();
// FIXME: check that the index matches the relation!
@@ -141,13 +142,13 @@ public class DeLiClu<NV extends NumberVector<?>, D extends Distance<D>> extends
if(LOG.isVerbose()) {
LOG.verbose("knnJoin...");
}
- DataStore<KNNResult<D>> knns = knnJoin.run(database, relation);
+ DataStore<KNNList<D>> knns = knnJoin.run(database, relation);
FiniteProgress progress = LOG.isVerbose() ? new FiniteProgress("DeLiClu", relation.size(), LOG) : null;
final int size = relation.size();
- ClusterOrderResult<D> clusterOrder = new ClusterOrderResult<D>("DeLiClu Clustering", "deliclu-clustering");
- heap = new UpdatableHeap<SpatialObjectPair>();
+ ClusterOrderResult<D> clusterOrder = new ClusterOrderResult<>("DeLiClu Clustering", "deliclu-clustering");
+ heap = new UpdatableHeap<>();
// add start object to cluster order and (root, root) to priority queue
DBID startID = getStartObject(relation);
@@ -217,7 +218,7 @@ public class DeLiClu<NV extends NumberVector<?>, D extends Distance<D>> extends
* @param nodePair the pair of nodes to be expanded
* @param knns the knn list
*/
- private void expandNodes(DeLiCluTree index, SpatialPrimitiveDistanceFunction<NV, D> distFunction, SpatialObjectPair nodePair, DataStore<KNNResult<D>> knns) {
+ private void expandNodes(DeLiCluTree index, SpatialPrimitiveDistanceFunction<NV, D> distFunction, SpatialObjectPair nodePair, DataStore<KNNList<D>> knns) {
DeLiCluNode node1 = index.getNode(((SpatialDirectoryEntry) nodePair.entry1).getPageID());
DeLiCluNode node2 = index.getNode(((SpatialDirectoryEntry) nodePair.entry2).getPageID());
@@ -274,7 +275,7 @@ public class DeLiClu<NV extends NumberVector<?>, D extends Distance<D>> extends
* @param node2 the second node
* @param knns the knn list
*/
- private void expandLeafNodes(SpatialPrimitiveDistanceFunction<NV, D> distFunction, DeLiCluNode node1, DeLiCluNode node2, DataStore<KNNResult<D>> knns) {
+ private void expandLeafNodes(SpatialPrimitiveDistanceFunction<NV, D> distFunction, DeLiCluNode node1, DeLiCluNode node2, DataStore<KNNList<D>> knns) {
if(LOG.isDebuggingFinest()) {
LOG.debugFinest("ExpandLeafNodes: " + node1.getPageID() + " + " + node2.getPageID());
}
@@ -310,12 +311,12 @@ public class DeLiClu<NV extends NumberVector<?>, D extends Distance<D>> extends
* @param path the path of the object inserted last
* @param knns the knn list
*/
- private void reinsertExpanded(SpatialPrimitiveDistanceFunction<NV, D> distFunction, DeLiCluTree index, List<TreeIndexPathComponent<DeLiCluEntry>> path, DataStore<KNNResult<D>> knns) {
+ private void reinsertExpanded(SpatialPrimitiveDistanceFunction<NV, D> distFunction, DeLiCluTree index, List<TreeIndexPathComponent<DeLiCluEntry>> path, DataStore<KNNList<D>> knns) {
SpatialDirectoryEntry rootEntry = (SpatialDirectoryEntry) path.remove(0).getEntry();
reinsertExpanded(distFunction, index, path, 0, rootEntry, knns);
}
- private void reinsertExpanded(SpatialPrimitiveDistanceFunction<NV, D> distFunction, DeLiCluTree index, List<TreeIndexPathComponent<DeLiCluEntry>> path, int pos, SpatialDirectoryEntry parentEntry, DataStore<KNNResult<D>> knns) {
+ private void reinsertExpanded(SpatialPrimitiveDistanceFunction<NV, D> distFunction, DeLiCluTree index, List<TreeIndexPathComponent<DeLiCluEntry>> path, int pos, SpatialDirectoryEntry parentEntry, DataStore<KNNList<D>> knns) {
DeLiCluNode parentNode = index.getNode(parentEntry.getPageID());
SpatialEntry entry2 = path.get(pos).getEntry();
@@ -332,7 +333,7 @@ public class DeLiClu<NV extends NumberVector<?>, D extends Distance<D>> extends
}
}
else {
- Set<Integer> expanded = index.getExpanded(entry2);
+ TIntSet expanded = index.getExpanded(entry2);
for(int i = 0; i < parentNode.getNumEntries(); i++) {
SpatialDirectoryEntry entry1 = (SpatialDirectoryEntry) parentNode.getEntry(i);
@@ -503,7 +504,7 @@ public class DeLiClu<NV extends NumberVector<?>, D extends Distance<D>> extends
@Override
protected DeLiClu<NV, D> makeInstance() {
- return new DeLiClu<NV, D>(distanceFunction, minpts);
+ return new DeLiClu<>(distanceFunction, minpts);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/EM.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/EM.java
index 514e63bd..c66442a1 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/EM.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/EM.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -46,7 +46,7 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.database.relation.RelationUtil;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.math.MathUtil;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Matrix;
@@ -179,13 +179,13 @@ public class EM<V extends NumberVector<?>> extends AbstractAlgorithm<Clustering<
if (LOG.isVerbose()) {
LOG.verbose("initializing " + k + " models");
}
- List<Vector> means = new ArrayList<Vector>();
- for (NumberVector<?> nv : initializer.chooseInitialMeans(relation, k, EuclideanDistanceFunction.STATIC)) {
+ List<Vector> means = new ArrayList<>();
+ for (NumberVector<?> nv : initializer.chooseInitialMeans(database, relation, k, EuclideanDistanceFunction.STATIC)) {
means.add(nv.getColumnVector());
}
- List<Matrix> covarianceMatrices = new ArrayList<Matrix>(k);
+ List<Matrix> covarianceMatrices = new ArrayList<>(k);
double[] normDistrFactor = new double[k];
- List<Matrix> invCovMatr = new ArrayList<Matrix>(k);
+ List<Matrix> invCovMatr = new ArrayList<>(k);
double[] clusterWeights = new double[k];
probClusterIGivenX = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_SORTED, double[].class);
@@ -193,7 +193,13 @@ public class EM<V extends NumberVector<?>> extends AbstractAlgorithm<Clustering<
for (int i = 0; i < k; i++) {
Matrix m = Matrix.identity(dimensionality, dimensionality);
covarianceMatrices.add(m);
- normDistrFactor[i] = 1.0 / Math.sqrt(Math.pow(MathUtil.TWOPI, dimensionality) * m.det());
+ final double det = m.det();
+ if (det > 0.) {
+ normDistrFactor[i] = 1.0 / Math.sqrt(Math.pow(MathUtil.TWOPI, dimensionality) * det);
+ } else {
+ LOG.warning("Encountered matrix with 0 determinant - degenerated.");
+ normDistrFactor[i] = 1.0; // Not really well defined
+ }
invCovMatr.add(m.inverse());
clusterWeights[i] = 1.0 / k;
if (LOG.isDebuggingFinest()) {
@@ -201,7 +207,7 @@ public class EM<V extends NumberVector<?>> extends AbstractAlgorithm<Clustering<
msg.append(" model ").append(i).append(":\n");
msg.append(" mean: ").append(means.get(i)).append('\n');
msg.append(" m:\n").append(FormatUtil.format(m, " ")).append('\n');
- msg.append(" m.det(): ").append(m.det()).append('\n');
+ msg.append(" m.det(): ").append(det).append('\n');
msg.append(" cluster weight: ").append(clusterWeights[i]).append('\n');
msg.append(" normDistFact: ").append(normDistrFactor[i]).append('\n');
LOG.debugFine(msg.toString());
@@ -222,7 +228,7 @@ public class EM<V extends NumberVector<?>> extends AbstractAlgorithm<Clustering<
em = emNew;
// recompute models
- List<Vector> meanSums = new ArrayList<Vector>(k);
+ List<Vector> meanSums = new ArrayList<>(k);
double[] sumOfClusterProbabilities = new double[k];
for (int i = 0; i < k; i++) {
@@ -260,7 +266,13 @@ public class EM<V extends NumberVector<?>> extends AbstractAlgorithm<Clustering<
covarianceMatrices.set(i, covarianceMatrices.get(i).times(1 / sumOfClusterProbabilities[i]).cheatToAvoidSingularity(SINGULARITY_CHEAT));
}
for (int i = 0; i < k; i++) {
- normDistrFactor[i] = 1.0 / Math.sqrt(Math.pow(MathUtil.TWOPI, dimensionality) * covarianceMatrices.get(i).det());
+ final double det = covarianceMatrices.get(i).det();
+ if (det > 0.) {
+ normDistrFactor[i] = 1.0 / Math.sqrt(Math.pow(MathUtil.TWOPI, dimensionality) * det);
+ } else {
+ LOG.warning("Encountered matrix with 0 determinant - degenerated.");
+ normDistrFactor[i] = 1.0; // Not really well defined
+ }
invCovMatr.set(i, covarianceMatrices.get(i).inverse());
}
// reassign probabilities
@@ -279,7 +291,7 @@ public class EM<V extends NumberVector<?>> extends AbstractAlgorithm<Clustering<
}
// fill result with clusters and models
- List<ModifiableDBIDs> hardClusters = new ArrayList<ModifiableDBIDs>(k);
+ List<ModifiableDBIDs> hardClusters = new ArrayList<>(k);
for (int i = 0; i < k; i++) {
hardClusters.add(DBIDUtil.newHashSet());
}
@@ -298,14 +310,14 @@ public class EM<V extends NumberVector<?>> extends AbstractAlgorithm<Clustering<
hardClusters.get(maxIndex).add(iditer);
}
final NumberVector.Factory<V, ?> factory = RelationUtil.getNumberVectorFactory(relation);
- Clustering<EMModel<V>> result = new Clustering<EMModel<V>>("EM Clustering", "em-clustering");
+ Clustering<EMModel<V>> result = new Clustering<>("EM Clustering", "em-clustering");
// provide models within the result
for (int i = 0; i < k; i++) {
// TODO: re-do labeling.
// SimpleClassLabel label = new SimpleClassLabel();
// label.init(result.canonicalClusterLabel(i));
- Cluster<EMModel<V>> model = new Cluster<EMModel<V>>(hardClusters.get(i), new EMModel<V>(factory.newNumberVector(means.get(i).getArrayRef()), covarianceMatrices.get(i)));
- result.addCluster(model);
+ Cluster<EMModel<V>> model = new Cluster<>(hardClusters.get(i), new EMModel<>(factory.newNumberVector(means.get(i).getArrayRef()), covarianceMatrices.get(i)));
+ result.addToplevelCluster(model);
}
return result;
}
@@ -339,6 +351,9 @@ public class EM<V extends NumberVector<?>> extends AbstractAlgorithm<Clustering<
if (LOG.isDebuggingFinest()) {
LOG.debugFinest(" difference vector= ( " + difference.toString() + " )\n" + " difference:\n" + FormatUtil.format(difference, " ") + "\n" + " rowTimesCovTimesCol:\n" + rowTimesCovTimesCol + "\n" + " power= " + power + "\n" + " prob=" + prob + "\n" + " inv cov matrix: \n" + FormatUtil.format(invCovMatr.get(i), " "));
}
+ if (!(prob >= 0.)) {
+ LOG.warning("Invalid probability: " + prob + " power: " + power + " factor: " + normDistrFactor[i]);
+ }
probabilities[i] = prob;
}
double priorProbability = 0.0;
@@ -352,13 +367,12 @@ public class EM<V extends NumberVector<?>> extends AbstractAlgorithm<Clustering<
double[] clusterProbabilities = new double[k];
for (int i = 0; i < k; i++) {
- assert (priorProbability >= 0.0);
assert (clusterWeights[i] >= 0.0);
// do not divide by zero!
- if (priorProbability == 0.0) {
- clusterProbabilities[i] = 0.0;
- } else {
+ if (priorProbability > 0.0) {
clusterProbabilities[i] = probabilities[i] / priorProbability * clusterWeights[i];
+ } else {
+ clusterProbabilities[i] = 0.0;
}
}
probClusterIGivenX.put(iditer, clusterProbabilities);
@@ -412,7 +426,7 @@ public class EM<V extends NumberVector<?>> extends AbstractAlgorithm<Clustering<
k = kP.getValue();
}
- ObjectParameter<KMeansInitialization<V>> initialP = new ObjectParameter<KMeansInitialization<V>>(INIT_ID, KMeansInitialization.class, RandomlyGeneratedInitialMeans.class);
+ ObjectParameter<KMeansInitialization<V>> initialP = new ObjectParameter<>(INIT_ID, KMeansInitialization.class, RandomlyGeneratedInitialMeans.class);
if (config.grab(initialP)) {
initializer = initialP.instantiateClass(config);
}
@@ -433,7 +447,7 @@ public class EM<V extends NumberVector<?>> extends AbstractAlgorithm<Clustering<
@Override
protected EM<V> makeInstance() {
- return new EM<V>(k, delta, initializer, maxiter);
+ return new EM<>(k, delta, initializer, maxiter);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/NaiveMeanShiftClustering.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/NaiveMeanShiftClustering.java
index 8429d8ac..a4d6e307 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/NaiveMeanShiftClustering.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/NaiveMeanShiftClustering.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -36,19 +36,19 @@ import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.database.relation.RelationUtil;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultIter;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Centroid;
-import de.lmu.ifi.dbs.elki.math.statistics.EpanechnikovKernelDensityFunction;
-import de.lmu.ifi.dbs.elki.math.statistics.KernelDensityFunction;
+import de.lmu.ifi.dbs.elki.math.statistics.kernelfunctions.EpanechnikovKernelDensityFunction;
+import de.lmu.ifi.dbs.elki.math.statistics.kernelfunctions.KernelDensityFunction;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
@@ -135,7 +135,7 @@ public class NaiveMeanShiftClustering<V extends NumberVector<?>, D extends Numbe
final double threshold = bandwidth * 1E-10;
// Result store:
- ArrayList<Pair<V, ModifiableDBIDs>> clusters = new ArrayList<Pair<V, ModifiableDBIDs>>();
+ ArrayList<Pair<V, ModifiableDBIDs>> clusters = new ArrayList<>();
ModifiableDBIDs noise = DBIDUtil.newArray();
@@ -148,11 +148,11 @@ public class NaiveMeanShiftClustering<V extends NumberVector<?>, D extends Numbe
// Compute new position:
V newvec = null;
{
- DistanceDBIDResult<D> neigh = rangeq.getRangeForObject(position, range);
+ DistanceDBIDList<D> neigh = rangeq.getRangeForObject(position, range);
boolean okay = (neigh.size() > 1) || (neigh.size() >= 1 && j > 1);
if (okay) {
Centroid newpos = new Centroid(dim);
- for (DistanceDBIDResultIter<D> niter = neigh.iter(); niter.valid(); niter.advance()) {
+ for (DistanceDBIDListIter<D> niter = neigh.iter(); niter.valid(); niter.advance()) {
final double weight = kernel.density(niter.getDistance().doubleValue() / bandwidth);
newpos.put(relation.get(niter), weight);
}
@@ -206,14 +206,14 @@ public class NaiveMeanShiftClustering<V extends NumberVector<?>, D extends Numbe
prog.ensureCompleted(LOG);
}
- ArrayList<Cluster<MeanModel<V>>> cs = new ArrayList<Cluster<MeanModel<V>>>(clusters.size());
+ ArrayList<Cluster<MeanModel<V>>> cs = new ArrayList<>(clusters.size());
for (Pair<V, ModifiableDBIDs> pair : clusters) {
- cs.add(new Cluster<MeanModel<V>>(pair.second, new MeanModel<V>(pair.first)));
+ cs.add(new Cluster<>(pair.second, new MeanModel<>(pair.first)));
}
if (noise.size() > 0) {
cs.add(new Cluster<MeanModel<V>>(noise, true));
}
- Clustering<MeanModel<V>> c = new Clustering<MeanModel<V>>("Mean-shift Clustering", "mean-shift-clustering", cs);
+ Clustering<MeanModel<V>> c = new Clustering<>("Mean-shift Clustering", "mean-shift-clustering", cs);
return c;
}
@@ -261,11 +261,11 @@ public class NaiveMeanShiftClustering<V extends NumberVector<?>, D extends Numbe
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- ObjectParameter<KernelDensityFunction> kernelP = new ObjectParameter<KernelDensityFunction>(KERNEL_ID, KernelDensityFunction.class, EpanechnikovKernelDensityFunction.class);
+ ObjectParameter<KernelDensityFunction> kernelP = new ObjectParameter<>(KERNEL_ID, KernelDensityFunction.class, EpanechnikovKernelDensityFunction.class);
if (config.grab(kernelP)) {
kernel = kernelP.instantiateClass(config);
}
- DistanceParameter<D> rangeP = new DistanceParameter<D>(RANGE_ID, distanceFunction);
+ DistanceParameter<D> rangeP = new DistanceParameter<>(RANGE_ID, distanceFunction);
if (config.grab(rangeP)) {
range = rangeP.getValue();
}
@@ -273,7 +273,7 @@ public class NaiveMeanShiftClustering<V extends NumberVector<?>, D extends Numbe
@Override
protected NaiveMeanShiftClustering<V, D> makeInstance() {
- return new NaiveMeanShiftClustering<V, D>(distanceFunction, kernel, range);
+ return new NaiveMeanShiftClustering<>(distanceFunction, kernel, range);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/OPTICS.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/OPTICS.java
index 2c098dc0..e928d041 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/OPTICS.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/OPTICS.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -31,17 +31,17 @@ import de.lmu.ifi.dbs.elki.database.QueryUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
-import de.lmu.ifi.dbs.elki.database.ids.DistanceDBIDPair;
-import de.lmu.ifi.dbs.elki.database.ids.DoubleDistanceDBIDPair;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDListIter;
import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.DistanceUtil;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultIter;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceDBIDResultIter;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.logging.Logging;
@@ -139,7 +139,7 @@ public class OPTICS<O, D extends Distance<D>> extends AbstractDistanceBasedAlgor
final FiniteProgress progress = LOG.isVerbose() ? new FiniteProgress("OPTICS", size, LOG) : null;
processedIDs = DBIDUtil.newHashSet(size);
- ClusterOrderResult<D> clusterOrder = new ClusterOrderResult<D>("OPTICS Clusterorder", "optics-clusterorder");
+ ClusterOrderResult<D> clusterOrder = new ClusterOrderResult<>("OPTICS Clusterorder", "optics-clusterorder");
if(getDistanceFunction() instanceof PrimitiveDoubleDistanceFunction && DoubleDistance.class.isInstance(epsilon)) {
// Optimized codepath for double-based distances. Avoids Java
@@ -182,25 +182,25 @@ public class OPTICS<O, D extends Distance<D>> extends AbstractDistanceBasedAlgor
* the algorithm
*/
protected void expandClusterOrder(ClusterOrderResult<D> clusterOrder, Database database, RangeQuery<O, D> rangeQuery, DBID objectID, D epsilon, FiniteProgress progress) {
- UpdatableHeap<ClusterOrderEntry<D>> heap = new UpdatableHeap<ClusterOrderEntry<D>>();
- heap.add(new GenericClusterOrderEntry<D>(objectID, null, getDistanceFunction().getDistanceFactory().infiniteDistance()));
+ UpdatableHeap<ClusterOrderEntry<D>> heap = new UpdatableHeap<>();
+ heap.add(new GenericClusterOrderEntry<>(objectID, null, getDistanceFunction().getDistanceFactory().infiniteDistance()));
while(!heap.isEmpty()) {
final ClusterOrderEntry<D> current = heap.poll();
clusterOrder.add(current);
processedIDs.add(current.getID());
- DistanceDBIDResult<D> neighbors = rangeQuery.getRangeForDBID(current.getID(), epsilon);
+ DistanceDBIDList<D> neighbors = rangeQuery.getRangeForDBID(current.getID(), epsilon);
if(neighbors.size() >= minpts) {
final DistanceDBIDPair<D> last = neighbors.get(minpts - 1);
D coreDistance = last.getDistance();
- for(DistanceDBIDResultIter<D> neighbor = neighbors.iter(); neighbor.valid(); neighbor.advance()) {
+ for(DistanceDBIDListIter<D> neighbor = neighbors.iter(); neighbor.valid(); neighbor.advance()) {
if(processedIDs.contains(neighbor)) {
continue;
}
D reachability = DistanceUtil.max(neighbor.getDistance(), coreDistance);
- heap.add(new GenericClusterOrderEntry<D>(DBIDUtil.deref(neighbor), current.getID(), reachability));
+ heap.add(new GenericClusterOrderEntry<>(DBIDUtil.deref(neighbor), current.getID(), reachability));
}
}
if(progress != null) {
@@ -221,7 +221,7 @@ public class OPTICS<O, D extends Distance<D>> extends AbstractDistanceBasedAlgor
* the algorithm
*/
protected void expandClusterOrderDouble(ClusterOrderResult<DoubleDistance> clusterOrder, Database database, RangeQuery<O, DoubleDistance> rangeQuery, DBID objectID, DoubleDistance epsilon, FiniteProgress progress) {
- UpdatableHeap<DoubleDistanceClusterOrderEntry> heap = new UpdatableHeap<DoubleDistanceClusterOrderEntry>();
+ UpdatableHeap<DoubleDistanceClusterOrderEntry> heap = new UpdatableHeap<>();
heap.add(new DoubleDistanceClusterOrderEntry(objectID, null, Double.POSITIVE_INFINITY));
while(!heap.isEmpty()) {
@@ -229,17 +229,17 @@ public class OPTICS<O, D extends Distance<D>> extends AbstractDistanceBasedAlgor
clusterOrder.add(current);
processedIDs.add(current.getID());
- DistanceDBIDResult<DoubleDistance> neighbors = rangeQuery.getRangeForDBID(current.getID(), epsilon);
+ DistanceDBIDList<DoubleDistance> neighbors = rangeQuery.getRangeForDBID(current.getID(), epsilon);
if(neighbors.size() >= minpts) {
final DistanceDBIDPair<DoubleDistance> last = neighbors.get(minpts - 1);
if(last instanceof DoubleDistanceDBIDPair) {
double coreDistance = ((DoubleDistanceDBIDPair) last).doubleDistance();
- for(DistanceDBIDResultIter<DoubleDistance> neighbor = neighbors.iter(); neighbor.valid(); neighbor.advance()) {
+ for(DistanceDBIDListIter<DoubleDistance> neighbor = neighbors.iter(); neighbor.valid(); neighbor.advance()) {
if(processedIDs.contains(neighbor)) {
continue;
}
- double reachability = Math.max(((DoubleDistanceDBIDResultIter) neighbor).doubleDistance(), coreDistance);
+ double reachability = Math.max(((DoubleDistanceDBIDListIter) neighbor).doubleDistance(), coreDistance);
heap.add(new DoubleDistanceClusterOrderEntry(DBIDUtil.deref(neighbor), current.getID(), reachability));
}
}
@@ -248,7 +248,7 @@ public class OPTICS<O, D extends Distance<D>> extends AbstractDistanceBasedAlgor
// Only if we got an optimized result before.
double coreDistance = last.getDistance().doubleValue();
- for(DistanceDBIDResultIter<DoubleDistance> neighbor = neighbors.iter(); neighbor.valid(); neighbor.advance()) {
+ for(DistanceDBIDListIter<DoubleDistance> neighbor = neighbors.iter(); neighbor.valid(); neighbor.advance()) {
if(processedIDs.contains(neighbor)) {
continue;
}
@@ -298,7 +298,7 @@ public class OPTICS<O, D extends Distance<D>> extends AbstractDistanceBasedAlgor
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- DistanceParameter<D> epsilonP = new DistanceParameter<D>(EPSILON_ID, distanceFunction, true);
+ DistanceParameter<D> epsilonP = new DistanceParameter<>(EPSILON_ID, distanceFunction, true);
if(config.grab(epsilonP)) {
epsilon = epsilonP.getValue();
}
@@ -312,7 +312,7 @@ public class OPTICS<O, D extends Distance<D>> extends AbstractDistanceBasedAlgor
@Override
protected OPTICS<O, D> makeInstance() {
- return new OPTICS<O, D>(distanceFunction, epsilon, minpts);
+ return new OPTICS<>(distanceFunction, epsilon, minpts);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/OPTICSTypeAlgorithm.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/OPTICSTypeAlgorithm.java
index 3ead6f3e..82d7ec88 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/OPTICSTypeAlgorithm.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/OPTICSTypeAlgorithm.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/OPTICSXi.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/OPTICSXi.java
index 39a0ebd6..583d402b 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/OPTICSXi.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/OPTICSXi.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -46,8 +46,6 @@ import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.result.IterableResult;
import de.lmu.ifi.dbs.elki.result.optics.ClusterOrderEntry;
import de.lmu.ifi.dbs.elki.result.optics.ClusterOrderResult;
-import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.HierarchyHashmapList;
-import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.ModifiableHierarchy;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterEqualConstraint;
@@ -135,13 +133,13 @@ public class OPTICSXi<N extends NumberDistance<N, ?>> extends AbstractAlgorithm<
double mib = 0.0;
// TODO: make it configurable to keep this list; this is mostly useful for
// visualization
- List<SteepArea> salist = new ArrayList<SteepArea>();
- List<SteepDownArea> sdaset = new ArrayList<SteepDownArea>();
- ModifiableHierarchy<Cluster<OPTICSModel>> hier = new HierarchyHashmapList<Cluster<OPTICSModel>>();
- HashSet<Cluster<OPTICSModel>> curclusters = new HashSet<Cluster<OPTICSModel>>();
+ List<SteepArea> salist = new ArrayList<>();
+ List<SteepDownArea> sdaset = new ArrayList<>();
+ final Clustering<OPTICSModel> clustering = new Clustering<>("OPTICS Xi-Clusters", "optics");
+ HashSet<Cluster<OPTICSModel>> curclusters = new HashSet<>();
HashSetModifiableDBIDs unclaimedids = DBIDUtil.newHashSet(relation.getDBIDs());
- SteepScanPosition<N> scan = new SteepScanPosition<N>(clusterOrder);
+ SteepScanPosition<N> scan = new SteepScanPosition<>(clusterOrder);
while(scan.hasNext()) {
final int curpos = scan.index;
// Update maximum-inbetween
@@ -285,7 +283,7 @@ public class OPTICSXi<N extends NumberDistance<N, ?>> extends AbstractAlgorithm<
LOG.debugFine("Found cluster with " + dbids.size() + " new objects, length " + (cstart - cend + 1));
}
OPTICSModel model = new OPTICSModel(cstart, cend);
- Cluster<OPTICSModel> cluster = new Cluster<OPTICSModel>("Cluster_" + cstart + "_" + cend, dbids, model, hier);
+ Cluster<OPTICSModel> cluster = new Cluster<>("Cluster_" + cstart + "_" + cend, dbids, model);
// Build the hierarchy
{
Iterator<Cluster<OPTICSModel>> iter = curclusters.iterator();
@@ -293,7 +291,7 @@ public class OPTICSXi<N extends NumberDistance<N, ?>> extends AbstractAlgorithm<
Cluster<OPTICSModel> clus = iter.next();
OPTICSModel omodel = clus.getModel();
if(model.getStartIndex() <= omodel.getStartIndex() && omodel.getEndIndex() <= model.getEndIndex()) {
- hier.add(cluster, clus);
+ clustering.addChildCluster(cluster, clus);
iter.remove();
}
}
@@ -308,23 +306,22 @@ public class OPTICSXi<N extends NumberDistance<N, ?>> extends AbstractAlgorithm<
}
}
if(curclusters.size() > 0 || unclaimedids.size() > 0) {
- final Clustering<OPTICSModel> clustering = new Clustering<OPTICSModel>("OPTICS Xi-Clusters", "optics");
if(unclaimedids.size() > 0) {
final Cluster<OPTICSModel> allcluster;
if(clusterOrder.get(clusterOrder.size() - 1).getReachability().isInfiniteDistance()) {
- allcluster = new Cluster<OPTICSModel>("Noise", unclaimedids, true, new OPTICSModel(0, clusterOrder.size() - 1), hier);
+ allcluster = new Cluster<>("Noise", unclaimedids, true, new OPTICSModel(0, clusterOrder.size() - 1));
}
else {
- allcluster = new Cluster<OPTICSModel>("Cluster", unclaimedids, new OPTICSModel(0, clusterOrder.size() - 1), hier);
+ allcluster = new Cluster<>("Cluster", unclaimedids, new OPTICSModel(0, clusterOrder.size() - 1));
}
for(Cluster<OPTICSModel> cluster : curclusters) {
- hier.add(allcluster, cluster);
+ clustering.addChildCluster(allcluster, cluster);
}
- clustering.addCluster(allcluster);
+ clustering.addToplevelCluster(allcluster);
}
else {
for(Cluster<OPTICSModel> cluster : curclusters) {
- clustering.addCluster(cluster);
+ clustering.addToplevelCluster(cluster);
}
}
clustering.addChildResult(clusterOrderResult);
@@ -663,7 +660,7 @@ public class OPTICSXi<N extends NumberDistance<N, ?>> extends AbstractAlgorithm<
xi = xiP.doubleValue();
}
- ClassParameter<OPTICSTypeAlgorithm<D>> opticsP = new ClassParameter<OPTICSTypeAlgorithm<D>>(XIALG_ID, OPTICSTypeAlgorithm.class, OPTICS.class);
+ ClassParameter<OPTICSTypeAlgorithm<D>> opticsP = new ClassParameter<>(XIALG_ID, OPTICSTypeAlgorithm.class, OPTICS.class);
if(config.grab(opticsP)) {
optics = opticsP.instantiateClass(config);
}
@@ -671,7 +668,7 @@ public class OPTICSXi<N extends NumberDistance<N, ?>> extends AbstractAlgorithm<
@Override
protected OPTICSXi<D> makeInstance() {
- return new OPTICSXi<D>(optics, xi);
+ return new OPTICSXi<>(optics, xi);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/SLINK.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/SLINK.java
deleted file mode 100644
index 3e1f0650..00000000
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/SLINK.java
+++ /dev/null
@@ -1,818 +0,0 @@
-package de.lmu.ifi.dbs.elki.algorithm.clustering;
-
-/*
- This file is part of ELKI:
- Environment for Developing KDD-Applications Supported by Index-Structures
-
- Copyright (C) 2012
- Ludwig-Maximilians-Universität München
- Lehr- und Forschungseinheit für Datenbanksysteme
- ELKI Development Team
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-import gnu.trove.list.array.TDoubleArrayList;
-
-import java.util.ArrayList;
-import java.util.Comparator;
-
-import de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm;
-import de.lmu.ifi.dbs.elki.data.Cluster;
-import de.lmu.ifi.dbs.elki.data.Clustering;
-import de.lmu.ifi.dbs.elki.data.model.DendrogramModel;
-import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
-import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
-import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
-import de.lmu.ifi.dbs.elki.database.Database;
-import de.lmu.ifi.dbs.elki.database.datastore.DBIDDataStore;
-import de.lmu.ifi.dbs.elki.database.datastore.DataStore;
-import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory;
-import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
-import de.lmu.ifi.dbs.elki.database.datastore.DoubleDistanceDataStore;
-import de.lmu.ifi.dbs.elki.database.datastore.WritableDBIDDataStore;
-import de.lmu.ifi.dbs.elki.database.datastore.WritableDataStore;
-import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDistanceDataStore;
-import de.lmu.ifi.dbs.elki.database.datastore.WritableIntegerDataStore;
-import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs;
-import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDArrayIter;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDVar;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
-import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
-import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
-import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
-import de.lmu.ifi.dbs.elki.database.relation.Relation;
-import de.lmu.ifi.dbs.elki.distance.DistanceUtil;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
-import de.lmu.ifi.dbs.elki.logging.Logging;
-import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
-import de.lmu.ifi.dbs.elki.result.BasicResult;
-import de.lmu.ifi.dbs.elki.result.OrderingFromDataStore;
-import de.lmu.ifi.dbs.elki.result.Result;
-import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.HierarchyHashmapList;
-import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.ModifiableHierarchy;
-import de.lmu.ifi.dbs.elki.utilities.documentation.Description;
-import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
-import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterEqualConstraint;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
-
-/**
- * Implementation of the efficient Single-Link Algorithm SLINK of R. Sibson.
- * <p>
- * Reference: R. Sibson: SLINK: An optimally efficient algorithm for the
- * single-link cluster method. <br>
- * In: The Computer Journal 16 (1973), No. 1, p. 30-34.
- * </p>
- *
- * @author Elke Achtert
- * @param <O> the type of DatabaseObject the algorithm is applied on
- * @param <D> the type of Distance used
- */
-@Title("SLINK: Single Link Clustering")
-@Description("Hierarchical clustering algorithm based on single-link connectivity.")
-@Reference(authors = "R. Sibson", title = "SLINK: An optimally efficient algorithm for the single-link cluster method", booktitle = "The Computer Journal 16 (1973), No. 1, p. 30-34.", url = "http://dx.doi.org/10.1093/comjnl/16.1.30")
-public class SLINK<O, D extends Distance<D>> extends AbstractDistanceBasedAlgorithm<O, D, Result> {
- /**
- * The logger for this class.
- */
- private static final Logging LOG = Logging.getLogger(SLINK.class);
-
- /**
- * Minimum number of clusters to extract
- */
- private int minclusters = -1;
-
- /**
- * Constructor.
- *
- * @param distanceFunction Distance function
- * @param minclusters Minimum clusters to extract. Can be {@code -1}.
- */
- public SLINK(DistanceFunction<? super O, D> distanceFunction, int minclusters) {
- super(distanceFunction);
- this.minclusters = minclusters;
- }
-
- /**
- * Performs the SLINK algorithm on the given database.
- */
- public Result run(Database database, Relation<O> relation) {
- DistanceQuery<O, D> distQuery = database.getDistanceQuery(relation, getDistanceFunction());
- @SuppressWarnings("unchecked")
- Class<D> distCls = (Class<D>) getDistanceFunction().getDistanceFactory().getClass();
- WritableDBIDDataStore pi = DataStoreUtil.makeDBIDStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_STATIC);
- WritableDataStore<D> lambda = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_STATIC, distCls);
- // Temporary storage for m.
- WritableDataStore<D> m = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP, distCls);
-
- FiniteProgress progress = LOG.isVerbose() ? new FiniteProgress("Running SLINK", relation.size(), LOG) : null;
- // has to be an array for monotonicity reasons!
- ModifiableDBIDs processedIDs = DBIDUtil.newArray(relation.size());
-
- // Optimized code path for double distances
- if (getDistanceFunction() instanceof PrimitiveDoubleDistanceFunction && lambda instanceof WritableDoubleDistanceDataStore && m instanceof WritableDoubleDistanceDataStore) {
- @SuppressWarnings("unchecked")
- PrimitiveDoubleDistanceFunction<? super O> dist = (PrimitiveDoubleDistanceFunction<? super O>) getDistanceFunction();
- WritableDoubleDistanceDataStore lambdad = (WritableDoubleDistanceDataStore) lambda;
- WritableDoubleDistanceDataStore md = (WritableDoubleDistanceDataStore) m;
- // apply the algorithm
- for (DBIDIter id = relation.iterDBIDs(); id.valid(); id.advance()) {
- step1double(id, pi, lambdad);
- step2double(id, processedIDs, distQuery.getRelation(), dist, md);
- step3double(id, pi, lambdad, processedIDs, md);
- step4double(id, pi, lambdad, processedIDs);
-
- processedIDs.add(id);
-
- if (progress != null) {
- progress.incrementProcessed(LOG);
- }
- }
- } else {
- // apply the algorithm
- for (DBIDIter id = relation.iterDBIDs(); id.valid(); id.advance()) {
- step1(id, pi, lambda);
- step2(id, processedIDs, distQuery, m);
- step3(id, pi, lambda, processedIDs, m);
- step4(id, pi, lambda, processedIDs);
-
- processedIDs.add(id);
-
- if (progress != null) {
- progress.incrementProcessed(LOG);
- }
- }
- }
-
- if (progress != null) {
- progress.ensureCompleted(LOG);
- }
- // We don't need m anymore.
- m.destroy();
- m = null;
-
- // Build dendrogam clusters identified by their target object
- if (LOG.isVerbose()) {
- LOG.verbose("Extracting clusters.");
- }
- final BasicResult result;
- if (lambda instanceof DoubleDistanceDataStore) {
- result = extractClustersDouble(relation.getDBIDs(), pi, (DoubleDistanceDataStore) lambda, minclusters);
- } else {
- result = extractClusters(relation.getDBIDs(), pi, lambda, minclusters);
- }
-
- result.addChildResult(new MaterializedRelation<DBID>("SLINK pi", "slink-order", TypeUtil.DBID, pi, processedIDs));
- result.addChildResult(new MaterializedRelation<D>("SLINK lambda", "slink-order", new SimpleTypeInformation<D>(distCls), lambda, processedIDs));
- result.addChildResult(new OrderingFromDataStore<D>("SLINK order", "slink-order", processedIDs, lambda));
- return result;
- }
-
- /**
- * First step: Initialize P(id) = id, L(id) = infinity.
- *
- * @param id the id of the object to be inserted into the pointer
- * representation
- * @param pi Pi data store
- * @param lambda Lambda data store
- */
- private void step1(DBIDRef id, WritableDBIDDataStore pi, WritableDataStore<D> lambda) {
- // P(n+1) = n+1:
- pi.put(id, id);
- // L(n+1) = infinity
- lambda.put(id, getDistanceFunction().getDistanceFactory().infiniteDistance());
- }
-
- /**
- * Second step: Determine the pairwise distances from all objects in the
- * pointer representation to the new object with the specified id.
- *
- * @param id the id of the object to be inserted into the pointer
- * representation
- * @param processedIDs the already processed ids
- * @param m Data store
- * @param distFunc Distance function to use
- */
- private void step2(DBIDRef id, DBIDs processedIDs, DistanceQuery<O, D> distFunc, WritableDataStore<D> m) {
- O newObj = distFunc.getRelation().get(id);
- for (DBIDIter it = processedIDs.iter(); it.valid(); it.advance()) {
- // M(i) = dist(i, n+1)
- m.put(it, distFunc.distance(it, newObj));
- }
- }
-
- /**
- * Third step: Determine the values for P and L
- *
- * @param id the id of the object to be inserted into the pointer
- * representation
- * @param pi Pi data store
- * @param lambda Lambda data store
- * @param processedIDs the already processed ids
- * @param m Data store
- */
- private void step3(DBIDRef id, WritableDBIDDataStore pi, WritableDataStore<D> lambda, DBIDs processedIDs, WritableDataStore<D> m) {
- DBIDVar p_i = DBIDUtil.newVar();
- // for i = 1..n
- for (DBIDIter it = processedIDs.iter(); it.valid(); it.advance()) {
- D l_i = lambda.get(it);
- D m_i = m.get(it);
- pi.assignVar(it, p_i); // p_i = pi(it)
- D mp_i = m.get(p_i);
-
- // if L(i) >= M(i)
- if (l_i.compareTo(m_i) >= 0) {
- // M(P(i)) = min { M(P(i)), L(i) }
- m.put(p_i, DistanceUtil.min(mp_i, l_i));
-
- // L(i) = M(i)
- lambda.put(it, m_i);
-
- // P(i) = n+1;
- pi.put(it, id);
- } else {
- // M(P(i)) = min { M(P(i)), M(i) }
- m.put(p_i, DistanceUtil.min(mp_i, m_i));
- }
- }
- }
-
- /**
- * Fourth step: Actualize the clusters if necessary
- *
- * @param id the id of the current object
- * @param pi Pi data store
- * @param lambda Lambda data store
- * @param processedIDs the already processed ids
- */
- private void step4(DBIDRef id, WritableDBIDDataStore pi, WritableDataStore<D> lambda, DBIDs processedIDs) {
- DBIDVar p_i = DBIDUtil.newVar();
- // for i = 1..n
- for (DBIDIter it = processedIDs.iter(); it.valid(); it.advance()) {
- D l_i = lambda.get(it);
- pi.assignVar(it, p_i); // p_i = pi(it)
- D lp_i = lambda.get(p_i);
-
- // if L(i) >= L(P(i))
- if (l_i.compareTo(lp_i) >= 0) {
- // P(i) = n+1
- pi.put(it, id);
- }
- }
- }
-
- /**
- * First step: Initialize P(id) = id, L(id) = infinity.
- *
- * @param id the id of the object to be inserted into the pointer
- * representation
- * @param pi Pi data store
- * @param lambda Lambda data store
- */
- private void step1double(DBIDRef id, WritableDBIDDataStore pi, WritableDoubleDistanceDataStore lambda) {
- // P(n+1) = n+1:
- pi.put(id, id);
- // L(n+1) = infinity
- lambda.putDouble(id, Double.POSITIVE_INFINITY);
- }
-
- /**
- * Second step: Determine the pairwise distances from all objects in the
- * pointer representation to the new object with the specified id.
- *
- * @param id the id of the object to be inserted into the pointer
- * representation
- * @param processedIDs the already processed ids
- * @param m Data store
- * @param relation Data relation
- * @param distFunc Distance function to use
- */
- private void step2double(DBIDRef id, DBIDs processedIDs, Relation<? extends O> relation, PrimitiveDoubleDistanceFunction<? super O> distFunc, WritableDoubleDistanceDataStore m) {
- O newObj = relation.get(id);
- for (DBIDIter it = processedIDs.iter(); it.valid(); it.advance()) {
- // M(i) = dist(i, n+1)
- m.putDouble(it, distFunc.doubleDistance(relation.get(it), newObj));
- }
- }
-
- /**
- * Third step: Determine the values for P and L
- *
- * @param id the id of the object to be inserted into the pointer
- * representation
- * @param pi Pi data store
- * @param lambda Lambda data store
- * @param processedIDs the already processed ids
- * @param m Data store
- */
- private void step3double(DBIDRef id, WritableDBIDDataStore pi, WritableDoubleDistanceDataStore lambda, DBIDs processedIDs, WritableDoubleDistanceDataStore m) {
- DBIDVar p_i = DBIDUtil.newVar();
- // for i = 1..n
- for (DBIDIter it = processedIDs.iter(); it.valid(); it.advance()) {
- double l_i = lambda.doubleValue(it);
- double m_i = m.doubleValue(it);
- pi.assignVar(it, p_i); // p_i = pi(it)
- double mp_i = m.doubleValue(p_i);
-
- // if L(i) >= M(i)
- if (l_i >= m_i) {
- // M(P(i)) = min { M(P(i)), L(i) }
- m.putDouble(p_i, Math.min(mp_i, l_i));
-
- // L(i) = M(i)
- lambda.putDouble(it, m_i);
-
- // P(i) = n+1;
- pi.put(it, id);
- } else {
- // M(P(i)) = min { M(P(i)), M(i) }
- m.putDouble(p_i, Math.min(mp_i, m_i));
- }
- }
- }
-
- /**
- * Fourth step: Actualize the clusters if necessary
- *
- * @param id the id of the current object
- * @param pi Pi data store
- * @param lambda Lambda data store
- * @param processedIDs the already processed ids
- */
- private void step4double(DBIDRef id, WritableDBIDDataStore pi, WritableDoubleDistanceDataStore lambda, DBIDs processedIDs) {
- DBIDVar p_i = DBIDUtil.newVar();
- // for i = 1..n
- for (DBIDIter it = processedIDs.iter(); it.valid(); it.advance()) {
- double l_i = lambda.doubleValue(it);
- pi.assignVar(it, p_i); // p_i = pi(it)
- double lp_i = lambda.doubleValue(p_i);
-
- // if L(i) >= L(P(i))
- if (l_i >= lp_i) {
- // P(i) = n+1
- pi.put(it, id);
- }
- }
- }
-
- /**
- * Extract all clusters from the pi-lambda-representation.
- *
- * @param ids Object ids to process
- * @param pi Pi store
- * @param lambda Lambda store
- * @param minclusters Minimum number of clusters to extract
- *
- * @return Hierarchical clustering
- */
- private Clustering<DendrogramModel<D>> extractClusters(DBIDs ids, final DBIDDataStore pi, final DataStore<D> lambda, int minclusters) {
- FiniteProgress progress = LOG.isVerbose() ? new FiniteProgress("Extracting clusters", ids.size(), LOG) : null;
- D nulldist = getDistanceFunction().getDistanceFactory().nullDistance();
-
- // Sort DBIDs by lambda. We need this for two things:
- // a) to determine the stop distance from "minclusters" parameter
- // b) to process arrows in decreasing / increasing order
- ArrayModifiableDBIDs order = DBIDUtil.newArray(ids);
- order.sort(new CompareByLambda<D>(lambda));
-
- // Stop distance:
- final D stopdist = (minclusters > 0) ? lambda.get(order.get(ids.size() - minclusters)) : null;
-
- // The initial pass is top-down.
- DBIDArrayIter it = order.iter();
- int split = (minclusters > 0) ? Math.max(ids.size() - minclusters, 0) : 0;
- // Tie handling: decrement split.
- if (stopdist != null) {
- while (split > 0) {
- it.seek(split - 1);
- if (stopdist.compareTo(lambda.get(it)) == 0) {
- split--;
- minclusters++;
- } else {
- break;
- }
- }
- }
-
- // Extract the child clusters
- int cnum = 0;
- int expcnum = Math.max(0, minclusters);
- WritableIntegerDataStore cluster_map = DataStoreUtil.makeIntegerStorage(ids, DataStoreFactory.HINT_TEMP, -1);
- ArrayList<ModifiableDBIDs> cluster_dbids = new ArrayList<ModifiableDBIDs>(expcnum);
- ArrayList<D> cluster_dist = new ArrayList<D>(expcnum);
- ArrayModifiableDBIDs cluster_leads = DBIDUtil.newArray(expcnum);
-
- DBIDVar succ = DBIDUtil.newVar(); // Variable for successor.
- // Go backwards on the lower part.
- for (it.seek(split - 1); it.valid(); it.retract()) {
- D dist = lambda.get(it); // Distance to successor
- pi.assignVar(it, succ); // succ = pi(it)
- int clusterid = cluster_map.intValue(succ);
- // Successor cluster has already been created:
- if (clusterid >= 0) {
- cluster_dbids.get(clusterid).add(it);
- cluster_map.putInt(it, clusterid);
- // Update distance to maximum encountered:
- if (cluster_dist.get(clusterid).compareTo(dist) < 0) {
- cluster_dist.set(clusterid, dist);
- }
- } else {
- // Need to start a new cluster:
- clusterid = cnum; // next cluster number.
- ModifiableDBIDs cids = DBIDUtil.newArray();
- // Add element and successor as initial members:
- cids.add(succ);
- cluster_map.putInt(succ, clusterid);
- cids.add(it);
- cluster_map.putInt(it, clusterid);
- // Store new cluster.
- cluster_dbids.add(cids);
- cluster_leads.add(succ);
- cluster_dist.add(dist);
- cnum++;
- }
-
- // Decrement counter
- if (progress != null) {
- progress.incrementProcessed(LOG);
- }
- }
- // Build a hierarchy out of these clusters.
- Cluster<DendrogramModel<D>> root = null;
- ModifiableHierarchy<Cluster<DendrogramModel<D>>> hier = new HierarchyHashmapList<Cluster<DendrogramModel<D>>>();
- ArrayList<Cluster<DendrogramModel<D>>> clusters = new ArrayList<Cluster<DendrogramModel<D>>>(ids.size() + expcnum - split);
- // Convert initial clusters to cluster objects
- {
- int i = 0;
- for (DBIDIter it2 = cluster_leads.iter(); it2.valid(); it2.advance(), i++) {
- clusters.add(makeCluster(it2, cluster_dist.get(i), cluster_dbids.get(i), hier));
- }
- cluster_dist = null; // Invalidate
- cluster_dbids = null; // Invalidate
- }
- // Process the upper part, bottom-up.
- for (it.seek(split); it.valid(); it.advance()) {
- int clusterid = cluster_map.intValue(it);
- // The current cluster:
- final Cluster<DendrogramModel<D>> clus;
- if (clusterid >= 0) {
- clus = clusters.get(clusterid);
- } else {
- ArrayModifiableDBIDs cids = DBIDUtil.newArray(1);
- cids.add(it);
- clus = makeCluster(it, nulldist, cids, hier);
- // No need to store in clusters: cannot have another incoming pi
- // pointer!
- }
- // The successor to join:
- pi.assignVar(it, succ); // succ = pi(it)
- if (DBIDUtil.equal(it, succ)) {
- assert (root == null);
- root = clus;
- } else {
- // Parent cluster:
- int parentid = cluster_map.intValue(succ);
- D depth = lambda.get(it);
- // Parent cluster exists - merge as a new cluster:
- if (parentid >= 0) {
- Cluster<DendrogramModel<D>> pclus = makeCluster(succ, depth, DBIDUtil.EMPTYDBIDS, hier);
- hier.add(pclus, clusters.get(parentid));
- hier.add(pclus, clus);
- clusters.set(parentid, pclus); // Replace existing parent cluster
- } else {
- // Create a new, one-element, parent cluster.
- parentid = cnum;
- cnum++;
- ArrayModifiableDBIDs cids = DBIDUtil.newArray(1);
- cids.add(succ);
- Cluster<DendrogramModel<D>> pclus = makeCluster(succ, depth, cids, hier);
- hier.add(pclus, clus);
- assert (clusters.size() == parentid);
- clusters.add(pclus); // Remember parent cluster
- cluster_map.putInt(succ, parentid); // Reference
- }
- }
-
- // Decrement counter
- if (progress != null) {
- progress.incrementProcessed(LOG);
- }
- }
-
- if (progress != null) {
- progress.ensureCompleted(LOG);
- }
- // build hierarchy
- final Clustering<DendrogramModel<D>> dendrogram = new Clustering<DendrogramModel<D>>("Single-Link-Dendrogram", "slink-dendrogram");
- dendrogram.addCluster(root);
-
- return dendrogram;
- }
-
- /**
- * Extract all clusters from the pi-lambda-representation.
- *
- * @param ids Object ids to process
- * @param pi Pi store
- * @param lambda Lambda store
- * @param minclusters Minimum number of clusters to extract
- *
- * @return Hierarchical clustering
- */
- private Clustering<DendrogramModel<D>> extractClustersDouble(DBIDs ids, final DBIDDataStore pi, final DoubleDistanceDataStore lambda, int minclusters) {
- FiniteProgress progress = LOG.isVerbose() ? new FiniteProgress("Extracting clusters", ids.size(), LOG) : null;
- D nulldist = getDistanceFunction().getDistanceFactory().nullDistance();
-
- // Sort DBIDs by lambda. We need this for two things:
- // a) to determine the stop distance from "minclusters" parameter
- // b) to process arrows in decreasing / increasing order
- ArrayModifiableDBIDs order = DBIDUtil.newArray(ids);
- order.sort(new CompareByDoubleLambda(lambda));
-
- // Stop distance:
- final double stopdist = (minclusters > 0) ? lambda.doubleValue(order.get(ids.size() - minclusters)) : Double.POSITIVE_INFINITY;
-
- // The initial pass is top-down.
- DBIDArrayIter it = order.iter();
- int split = (minclusters > 0) ? Math.max(ids.size() - minclusters, 0) : 0;
- // Tie handling: decrement split.
- if (minclusters > 0) {
- while (split > 0) {
- it.seek(split - 1);
- if (stopdist <= lambda.doubleValue(it)) {
- split--;
- minclusters++;
- } else {
- break;
- }
- }
- }
-
- // Extract the child clusters
- int cnum = 0;
- int expcnum = Math.max(0, minclusters);
- WritableIntegerDataStore cluster_map = DataStoreUtil.makeIntegerStorage(ids, DataStoreFactory.HINT_TEMP, -1);
- ArrayList<ModifiableDBIDs> cluster_dbids = new ArrayList<ModifiableDBIDs>(expcnum);
- TDoubleArrayList cluster_dist = new TDoubleArrayList(expcnum);
- ArrayModifiableDBIDs cluster_leads = DBIDUtil.newArray(expcnum);
-
- DBIDVar succ = DBIDUtil.newVar(); // Variable for successor.
- // Go backwards on the lower part.
- for (it.seek(split - 1); it.valid(); it.retract()) {
- double dist = lambda.doubleValue(it); // Distance to successor
- pi.assignVar(it, succ); // succ = pi(it)
- int clusterid = cluster_map.intValue(succ);
- // Successor cluster has already been created:
- if (clusterid >= 0) {
- cluster_dbids.get(clusterid).add(it);
- cluster_map.putInt(it, clusterid);
- // Update distance to maximum encountered:
- if (cluster_dist.get(clusterid) < dist) {
- cluster_dist.set(clusterid, dist);
- }
- } else {
- // Need to start a new cluster:
- clusterid = cnum; // next cluster number.
- ModifiableDBIDs cids = DBIDUtil.newArray();
- // Add element and successor as initial members:
- cids.add(succ);
- cluster_map.putInt(succ, clusterid);
- cids.add(it);
- cluster_map.putInt(it, clusterid);
- // Store new cluster.
- cluster_dbids.add(cids);
- cluster_leads.add(succ);
- cluster_dist.add(dist);
- cnum++;
- }
-
- // Decrement counter
- if (progress != null) {
- progress.incrementProcessed(LOG);
- }
- }
- // Build a hierarchy out of these clusters.
- Cluster<DendrogramModel<D>> root = null;
- ModifiableHierarchy<Cluster<DendrogramModel<D>>> hier = new HierarchyHashmapList<Cluster<DendrogramModel<D>>>();
- ArrayList<Cluster<DendrogramModel<D>>> clusters = new ArrayList<Cluster<DendrogramModel<D>>>(ids.size() + expcnum - split);
- // Convert initial clusters to cluster objects
- {
- int i = 0;
- for (DBIDIter it2 = cluster_leads.iter(); it2.valid(); it2.advance(), i++) {
- @SuppressWarnings("unchecked")
- D depth = (D) new DoubleDistance(cluster_dist.get(i));
- clusters.add(makeCluster(it2, depth, cluster_dbids.get(i), hier));
- }
- cluster_dist = null; // Invalidate
- cluster_dbids = null; // Invalidate
- }
- // Process the upper part, bottom-up.
- for (it.seek(split); it.valid(); it.advance()) {
- int clusterid = cluster_map.intValue(it);
- // The current cluster:
- final Cluster<DendrogramModel<D>> clus;
- if (clusterid >= 0) {
- clus = clusters.get(clusterid);
- } else {
- ArrayModifiableDBIDs cids = DBIDUtil.newArray(1);
- cids.add(it);
- clus = makeCluster(it, nulldist, cids, hier);
- // No need to store in clusters: cannot have another incoming pi
- // pointer!
- }
- // The successor to join:
- pi.assignVar(it, succ); // succ = pi(it)
- if (DBIDUtil.equal(it, succ)) {
- assert (root == null);
- root = clus;
- } else {
- // Parent cluster:
- int parentid = cluster_map.intValue(succ);
- @SuppressWarnings("unchecked")
- D depth = (D) new DoubleDistance(lambda.doubleValue(it));
- // Parent cluster exists - merge as a new cluster:
- if (parentid >= 0) {
- Cluster<DendrogramModel<D>> pclus = makeCluster(succ, depth, DBIDUtil.EMPTYDBIDS, hier);
- hier.add(pclus, clusters.get(parentid));
- hier.add(pclus, clus);
- clusters.set(parentid, pclus); // Replace existing parent cluster
- } else {
- // Create a new, one-element, parent cluster.
- parentid = cnum;
- cnum++;
- ArrayModifiableDBIDs cids = DBIDUtil.newArray(1);
- cids.add(succ);
- Cluster<DendrogramModel<D>> pclus = makeCluster(succ, depth, cids, hier);
- hier.add(pclus, clus);
- assert (clusters.size() == parentid);
- clusters.add(pclus); // Remember parent cluster
- cluster_map.putInt(succ, parentid); // Reference
- }
- }
-
- // Decrement counter
- if (progress != null) {
- progress.incrementProcessed(LOG);
- }
- }
-
- if (progress != null) {
- progress.ensureCompleted(LOG);
- }
- // build hierarchy
- final Clustering<DendrogramModel<D>> dendrogram = new Clustering<DendrogramModel<D>>("Single-Link-Dendrogram", "slink-dendrogram");
- dendrogram.addCluster(root);
-
- return dendrogram;
- }
-
- /**
- * Make the cluster for the given object
- *
- * @param lead Leading object
- * @param depth Linkage depth
- * @param members Member objects
- * @param hier Cluster hierarchy
- * @return Cluster
- */
- private Cluster<DendrogramModel<D>> makeCluster(DBIDRef lead, D depth, DBIDs members, ModifiableHierarchy<Cluster<DendrogramModel<D>>> hier) {
- final String name;
- if (members.size() == 0) {
- name = "merge_" + lead + "_" + depth;
- } else if (depth.isInfiniteDistance()) {
- assert (members.contains(lead));
- name = "object_" + lead;
- } else {
- name = "cluster_" + lead + "_" + depth;
- }
- Cluster<DendrogramModel<D>> cluster = new Cluster<DendrogramModel<D>>(name, members, new DendrogramModel<D>(depth), hier);
- return cluster;
- }
-
- @Override
- public TypeInformation[] getInputTypeRestriction() {
- return TypeUtil.array(getDistanceFunction().getInputTypeRestriction());
- }
-
- @Override
- protected Logging getLogger() {
- return LOG;
- }
-
- /**
- * Order a DBID collection by the lambda value.
- *
- * @author Erich Schubert
- *
- * @apiviz.exclude
- *
- * @param <D> Distance type
- */
- private static final class CompareByLambda<D extends Distance<D>> implements Comparator<DBIDRef> {
- /**
- * Lambda storage
- */
- private final DataStore<D> lambda;
-
- /**
- * Constructor.
- *
- * @param lambda Lambda storage
- */
- protected CompareByLambda(DataStore<D> lambda) {
- this.lambda = lambda;
- }
-
- @Override
- public int compare(DBIDRef id1, DBIDRef id2) {
- D k1 = lambda.get(id1);
- D k2 = lambda.get(id2);
- assert (k1 != null);
- assert (k2 != null);
- return k1.compareTo(k2);
- }
- }
-
- /**
- * Order a DBID collection by the lambda value.
- *
- * @author Erich Schubert
- *
- * @apiviz.exclude
- */
- private static final class CompareByDoubleLambda implements Comparator<DBIDRef> {
- /**
- * Lambda storage
- */
- private final DoubleDistanceDataStore lambda;
-
- /**
- * Constructor.
- *
- * @param lambda Lambda storage
- */
- protected CompareByDoubleLambda(DoubleDistanceDataStore lambda) {
- this.lambda = lambda;
- }
-
- @Override
- public int compare(DBIDRef id1, DBIDRef id2) {
- double k1 = lambda.doubleValue(id1);
- double k2 = lambda.doubleValue(id2);
- return Double.compare(k1, k2);
- }
- }
-
- /**
- * Parameterization class.
- *
- * @author Erich Schubert
- *
- * @apiviz.exclude
- */
- public static class Parameterizer<O, D extends Distance<D>> extends AbstractDistanceBasedAlgorithm.Parameterizer<O, D> {
- /**
- * The minimum number of clusters to extract
- */
- public static final OptionID SLINK_MINCLUSTERS_ID = new OptionID("slink.minclusters", "The maximum number of clusters to extract.");
-
- protected int minclusters = -1;
-
- @Override
- protected void makeOptions(Parameterization config) {
- super.makeOptions(config);
- IntParameter minclustersP = new IntParameter(SLINK_MINCLUSTERS_ID);
- minclustersP.addConstraint(new GreaterEqualConstraint(1));
- minclustersP.setOptional(true);
- if (config.grab(minclustersP)) {
- minclusters = minclustersP.intValue();
- }
- }
-
- @Override
- protected SLINK<O, D> makeInstance() {
- return new SLINK<O, D>(distanceFunction, minclusters);
- }
- }
-}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/SNNClustering.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/SNNClustering.java
index f3b59c42..95d9f23c 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/SNNClustering.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/SNNClustering.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -151,7 +151,7 @@ public class SNNClustering<O> extends AbstractAlgorithm<Clustering<Model>> imple
FiniteProgress objprog = LOG.isVerbose() ? new FiniteProgress("SNNClustering", relation.size(), LOG) : null;
IndefiniteProgress clusprog = LOG.isVerbose() ? new IndefiniteProgress("Number of clusters", LOG) : null;
- resultList = new ArrayList<ModifiableDBIDs>();
+ resultList = new ArrayList<>();
noise = DBIDUtil.newHashSet();
processedIDs = DBIDUtil.newHashSet(relation.size());
if(relation.size() >= minpts) {
@@ -183,11 +183,11 @@ public class SNNClustering<O> extends AbstractAlgorithm<Clustering<Model>> imple
clusprog.setCompleted(LOG);
}
- Clustering<Model> result = new Clustering<Model>("Shared-Nearest-Neighbor Clustering", "snn-clustering");
+ Clustering<Model> result = new Clustering<>("Shared-Nearest-Neighbor Clustering", "snn-clustering");
for(Iterator<ModifiableDBIDs> resultListIter = resultList.iterator(); resultListIter.hasNext();) {
- result.addCluster(new Cluster<Model>(resultListIter.next(), ClusterModel.CLUSTER));
+ result.addToplevelCluster(new Cluster<Model>(resultListIter.next(), ClusterModel.CLUSTER));
}
- result.addCluster(new Cluster<Model>(noise, true, ClusterModel.CLUSTER));
+ result.addToplevelCluster(new Cluster<Model>(noise, true, ClusterModel.CLUSTER));
return result;
}
@@ -322,7 +322,7 @@ public class SNNClustering<O> extends AbstractAlgorithm<Clustering<Model>> imple
Class<SharedNearestNeighborSimilarityFunction<O>> cls = ClassGenericsUtil.uglyCastIntoSubclass(SharedNearestNeighborSimilarityFunction.class);
similarityFunction = config.tryInstantiate(cls);
- DistanceParameter<IntegerDistance> epsilonP = new DistanceParameter<IntegerDistance>(EPSILON_ID, IntegerDistance.FACTORY);
+ DistanceParameter<IntegerDistance> epsilonP = new DistanceParameter<>(EPSILON_ID, IntegerDistance.FACTORY);
if(config.grab(epsilonP)) {
epsilon = epsilonP.getValue();
}
@@ -336,7 +336,7 @@ public class SNNClustering<O> extends AbstractAlgorithm<Clustering<Model>> imple
@Override
protected SNNClustering<O> makeInstance() {
- return new SNNClustering<O>(similarityFunction, epsilon, minpts);
+ return new SNNClustering<>(similarityFunction, epsilon, minpts);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/CASH.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/CASH.java
index 1cb1eb0d..0d82add9 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/CASH.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/CASH.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.correlation;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -66,8 +66,9 @@ import de.lmu.ifi.dbs.elki.math.linearalgebra.Matrix;
import de.lmu.ifi.dbs.elki.math.linearalgebra.pca.FirstNEigenPairFilter;
import de.lmu.ifi.dbs.elki.math.linearalgebra.pca.PCAFilteredRunner;
import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
-import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.Heap;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.ComparableMinHeap;
import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.IntegerPriorityObject;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.ObjectHeap;
import de.lmu.ifi.dbs.elki.utilities.documentation.Description;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
@@ -263,8 +264,8 @@ public class CASH<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
*/
private Relation<ParameterizationFunction> preprocess(Database db, Relation<V> vrel) {
DBIDs ids = vrel.getDBIDs();
- SimpleTypeInformation<ParameterizationFunction> type = new SimpleTypeInformation<ParameterizationFunction>(ParameterizationFunction.class);
- MaterializedRelation<ParameterizationFunction> prep = new MaterializedRelation<ParameterizationFunction>(db, type, ids);
+ SimpleTypeInformation<ParameterizationFunction> type = new SimpleTypeInformation<>(ParameterizationFunction.class);
+ MaterializedRelation<ParameterizationFunction> prep = new MaterializedRelation<>(db, type, ids);
// Project
for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
@@ -284,12 +285,12 @@ public class CASH<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
* @return a mapping of subspace dimensionalities to clusters
*/
private Clustering<Model> doRun(Relation<ParameterizationFunction> relation, FiniteProgress progress) {
- Clustering<Model> res = new Clustering<Model>("CASH clustering", "cash-clustering");
+ Clustering<Model> res = new Clustering<>("CASH clustering", "cash-clustering");
final int dim = dimensionality(relation);
// init heap
- Heap<IntegerPriorityObject<CASHInterval>> heap = new Heap<IntegerPriorityObject<CASHInterval>>();
+ ObjectHeap<IntegerPriorityObject<CASHInterval>> heap = new ComparableMinHeap<>();
ModifiableDBIDs noiseIDs = DBIDUtil.newHashSet(relation.getDBIDs());
initHeap(heap, relation, dim, noiseIDs);
@@ -338,7 +339,7 @@ public class CASH<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
// add result of dim-1 to this result
Clustering<Model> res_dim_minus_1 = doRun(db, progress);
for (Cluster<Model> cluster : res_dim_minus_1.getAllClusters()) {
- res.addCluster(cluster);
+ res.addToplevelCluster(cluster);
noiseIDs.removeDBIDs(cluster.getIDs());
clusterIDs.addDBIDs(cluster.getIDs());
processedIDs.addDBIDs(cluster.getIDs());
@@ -349,23 +350,23 @@ public class CASH<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
else {
LinearEquationSystem les = runDerivator(relation, dim - 1, interval.getIDs());
Cluster<Model> c = new Cluster<Model>(interval.getIDs(), new LinearEquationModel(les));
- res.addCluster(c);
+ res.addToplevelCluster(c);
noiseIDs.removeDBIDs(interval.getIDs());
clusterIDs.addDBIDs(interval.getIDs());
processedIDs.addDBIDs(interval.getIDs());
}
// Rebuild heap
- ArrayList<IntegerPriorityObject<CASHInterval>> heapVector = new ArrayList<IntegerPriorityObject<CASHInterval>>(heap.size());
- for (IntegerPriorityObject<CASHInterval> obj : heap) {
- heapVector.add(obj);
+ ArrayList<IntegerPriorityObject<CASHInterval>> heapVector = new ArrayList<>(heap.size());
+ for (ObjectHeap.UnsortedIter<IntegerPriorityObject<CASHInterval>> iter = heap.unsortedIter(); iter.valid(); iter.advance()) {
+ heapVector.add(iter.get());
}
heap.clear();
for (IntegerPriorityObject<CASHInterval> pair : heapVector) {
CASHInterval currentInterval = pair.getObject();
currentInterval.removeIDs(clusterIDs);
if (currentInterval.getIDs().size() >= minPts) {
- heap.add(new IntegerPriorityObject<CASHInterval>(currentInterval.priority(), currentInterval));
+ heap.add(new IntegerPriorityObject<>(currentInterval.priority(), currentInterval));
}
}
@@ -378,12 +379,12 @@ public class CASH<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
if (!noiseIDs.isEmpty()) {
if (dim == noiseDim) {
Cluster<Model> c = new Cluster<Model>(noiseIDs, true, ClusterModel.CLUSTER);
- res.addCluster(c);
+ res.addToplevelCluster(c);
processedIDs.addDBIDs(noiseIDs);
} else if (noiseIDs.size() >= minPts) {
LinearEquationSystem les = runDerivator(fulldatabase, dim - 1, noiseIDs);
Cluster<Model> c = new Cluster<Model>(noiseIDs, true, new LinearEquationModel(les));
- res.addCluster(c);
+ res.addToplevelCluster(c);
processedIDs.addDBIDs(noiseIDs);
}
}
@@ -427,7 +428,7 @@ public class CASH<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
* @param dim the dimensionality of the database
* @param ids the ids of the database
*/
- private void initHeap(Heap<IntegerPriorityObject<CASHInterval>> heap, Relation<ParameterizationFunction> relation, int dim, DBIDs ids) {
+ private void initHeap(ObjectHeap<IntegerPriorityObject<CASHInterval>> heap, Relation<ParameterizationFunction> relation, int dim, DBIDs ids) {
CASHIntervalSplit split = new CASHIntervalSplit(relation, minPts);
// determine minimum and maximum function value of all functions
@@ -479,7 +480,7 @@ public class CASH<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
ModifiableDBIDs intervalIDs = split.determineIDs(ids, alphaInterval, d_mins[i], d_maxs[i]);
if (intervalIDs != null && intervalIDs.size() >= minPts) {
CASHInterval rootInterval = new CASHInterval(alphaMin, alphaMax, split, intervalIDs, -1, 0, d_mins[i], d_maxs[i]);
- heap.add(new IntegerPriorityObject<CASHInterval>(rootInterval.priority(), rootInterval));
+ heap.add(new IntegerPriorityObject<>(rootInterval.priority(), rootInterval));
}
}
@@ -503,8 +504,8 @@ public class CASH<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
*/
private MaterializedRelation<ParameterizationFunction> buildDB(int dim, Matrix basis, DBIDs ids, Relation<ParameterizationFunction> relation) {
ProxyDatabase proxy = new ProxyDatabase(ids);
- SimpleTypeInformation<ParameterizationFunction> type = new SimpleTypeInformation<ParameterizationFunction>(ParameterizationFunction.class);
- MaterializedRelation<ParameterizationFunction> prep = new MaterializedRelation<ParameterizationFunction>(proxy, type, ids);
+ SimpleTypeInformation<ParameterizationFunction> type = new SimpleTypeInformation<>(ParameterizationFunction.class);
+ MaterializedRelation<ParameterizationFunction> prep = new MaterializedRelation<>(proxy, type, ids);
proxy.addRelation(prep);
// Project
@@ -566,7 +567,7 @@ public class CASH<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
private double sinusProduct(int start, int end, double[] alpha) {
double result = 1;
for (int j = start; j < end; j++) {
- result *= StrictMath.sin(alpha[j]);
+ result *= Math.sin(alpha[j]);
}
return result;
}
@@ -578,7 +579,7 @@ public class CASH<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
* @param heap the heap storing the intervals
* @return the next ''best'' interval at maximum level
*/
- private CASHInterval determineNextIntervalAtMaxLevel(Heap<IntegerPriorityObject<CASHInterval>> heap) {
+ private CASHInterval determineNextIntervalAtMaxLevel(ObjectHeap<IntegerPriorityObject<CASHInterval>> heap) {
CASHInterval next = doDetermineNextIntervalAtMaxLevel(heap);
// noise path was chosen
while (next == null) {
@@ -598,7 +599,7 @@ public class CASH<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
* @param heap the heap storing the intervals
* @return the next ''best'' interval at maximum level
*/
- private CASHInterval doDetermineNextIntervalAtMaxLevel(Heap<IntegerPriorityObject<CASHInterval>> heap) {
+ private CASHInterval doDetermineNextIntervalAtMaxLevel(ObjectHeap<IntegerPriorityObject<CASHInterval>> heap) {
CASHInterval interval = heap.poll().getObject();
int dim = interval.getDimensionality();
while (true) {
@@ -632,10 +633,10 @@ public class CASH<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
int comp = interval.getLeftChild().compareTo(interval.getRightChild());
if (comp < 0) {
bestInterval = interval.getRightChild();
- heap.add(new IntegerPriorityObject<CASHInterval>(interval.getLeftChild().priority(), interval.getLeftChild()));
+ heap.add(new IntegerPriorityObject<>(interval.getLeftChild().priority(), interval.getLeftChild()));
} else {
bestInterval = interval.getLeftChild();
- heap.add(new IntegerPriorityObject<CASHInterval>(interval.getRightChild().priority(), interval.getRightChild()));
+ heap.add(new IntegerPriorityObject<>(interval.getRightChild().priority(), interval.getRightChild()));
}
} else if (interval.getLeftChild() == null) {
bestInterval = interval.getRightChild();
@@ -733,8 +734,8 @@ public class CASH<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
DBIDs ids = interval.getIDs();
ProxyDatabase proxy = new ProxyDatabase(ids);
int dim = dimensionality(relation);
- SimpleTypeInformation<DoubleVector> type = new VectorFieldTypeInformation<DoubleVector>(DoubleVector.FACTORY, dim);
- MaterializedRelation<DoubleVector> prep = new MaterializedRelation<DoubleVector>(proxy, type, ids);
+ SimpleTypeInformation<DoubleVector> type = new VectorFieldTypeInformation<>(DoubleVector.FACTORY, dim);
+ MaterializedRelation<DoubleVector> prep = new MaterializedRelation<>(proxy, type, ids);
proxy.addRelation(prep);
// Project
@@ -792,8 +793,8 @@ public class CASH<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
private Database buildDerivatorDB(Relation<ParameterizationFunction> relation, DBIDs ids) {
ProxyDatabase proxy = new ProxyDatabase(ids);
int dim = dimensionality(relation);
- SimpleTypeInformation<DoubleVector> type = new VectorFieldTypeInformation<DoubleVector>(DoubleVector.FACTORY, dim);
- MaterializedRelation<DoubleVector> prep = new MaterializedRelation<DoubleVector>(proxy, type, ids);
+ SimpleTypeInformation<DoubleVector> type = new VectorFieldTypeInformation<>(DoubleVector.FACTORY, dim);
+ MaterializedRelation<DoubleVector> prep = new MaterializedRelation<>(proxy, type, ids);
proxy.addRelation(prep);
// Project
@@ -864,7 +865,7 @@ public class CASH<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
@Override
protected CASH<NumberVector<?>> makeInstance() {
- return new CASH<NumberVector<?>>(minpts, maxlevel, mindim, jitter, adjust);
+ return new CASH<>(minpts, maxlevel, mindim, jitter, adjust);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/COPAC.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/COPAC.java
index ac50559e..9a4b8512 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/COPAC.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/COPAC.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.correlation;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -185,7 +185,7 @@ public class COPAC<V extends NumberVector<?>, D extends Distance<D>> extends Abs
LocalProjectionIndex<V, ?> preprocin = partitionDistanceQuery.getIndex();
// partitioning
- Map<Integer, ModifiableDBIDs> partitionMap = new HashMap<Integer, ModifiableDBIDs>();
+ Map<Integer, ModifiableDBIDs> partitionMap = new HashMap<>();
FiniteProgress partitionProgress = LOG.isVerbose() ? new FiniteProgress("Partitioning", relation.size(), LOG) : null;
int processed = 1;
@@ -214,7 +214,7 @@ public class COPAC<V extends NumberVector<?>, D extends Distance<D>> extends Abs
// convert for partition algorithm.
// TODO: do this with DynamicDBIDs instead
- Map<Integer, DBIDs> pmap = new HashMap<Integer, DBIDs>();
+ Map<Integer, DBIDs> pmap = new HashMap<>();
for(Entry<Integer, ModifiableDBIDs> ent : partitionMap.entrySet()) {
pmap.put(ent.getKey(), ent.getValue());
}
@@ -230,14 +230,14 @@ public class COPAC<V extends NumberVector<?>, D extends Distance<D>> extends Abs
* @param query The preprocessor based query function
*/
private Clustering<Model> runPartitionAlgorithm(Relation<V> relation, Map<Integer, DBIDs> partitionMap, DistanceQuery<V, D> query) {
- Clustering<Model> result = new Clustering<Model>("COPAC clustering", "copac-clustering");
+ Clustering<Model> result = new Clustering<>("COPAC clustering", "copac-clustering");
// TODO: use an extra finite progress for the partitions?
for(Entry<Integer, DBIDs> pair : partitionMap.entrySet()) {
// noise partition
if(pair.getKey() == RelationUtil.dimensionality(relation)) {
// Make a Noise cluster
- result.addCluster(new Cluster<Model>(pair.getValue(), true, ClusterModel.CLUSTER));
+ result.addToplevelCluster(new Cluster<Model>(pair.getValue(), true, ClusterModel.CLUSTER));
}
else {
DBIDs partids = pair.getValue();
@@ -251,10 +251,10 @@ public class COPAC<V extends NumberVector<?>, D extends Distance<D>> extends Abs
// Re-Wrap resulting Clusters as DimensionModel clusters.
for(Cluster<Model> clus : p.getAllClusters()) {
if(clus.isNoise()) {
- result.addCluster(new Cluster<Model>(clus.getIDs(), true, ClusterModel.CLUSTER));
+ result.addToplevelCluster(new Cluster<Model>(clus.getIDs(), true, ClusterModel.CLUSTER));
}
else {
- result.addCluster(new Cluster<Model>(clus.getIDs(), new DimensionModel(pair.getKey())));
+ result.addToplevelCluster(new Cluster<Model>(clus.getIDs(), new DimensionModel(pair.getKey())));
}
}
}
@@ -316,12 +316,12 @@ public class COPAC<V extends NumberVector<?>, D extends Distance<D>> extends Abs
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- ClassParameter<Factory<V, ?>> indexP = new ClassParameter<LocalProjectionIndex.Factory<V, ?>>(PREPROCESSOR_ID, LocalProjectionIndex.Factory.class);
+ ClassParameter<Factory<V, ?>> indexP = new ClassParameter<>(PREPROCESSOR_ID, LocalProjectionIndex.Factory.class);
if(config.grab(indexP)) {
indexI = indexP.instantiateClass(config);
}
- ObjectParameter<FilteredLocalPCABasedDistanceFunction<V, ?, D>> pdistP = new ObjectParameter<FilteredLocalPCABasedDistanceFunction<V, ?, D>>(PARTITION_DISTANCE_ID, FilteredLocalPCABasedDistanceFunction.class, LocallyWeightedDistanceFunction.class);
+ ObjectParameter<FilteredLocalPCABasedDistanceFunction<V, ?, D>> pdistP = new ObjectParameter<>(PARTITION_DISTANCE_ID, FilteredLocalPCABasedDistanceFunction.class, LocallyWeightedDistanceFunction.class);
if(config.grab(pdistP)) {
ListParameterization predefinedDist = new ListParameterization();
predefinedDist.addParameter(IndexBasedDistanceFunction.INDEX_ID, indexI);
@@ -332,7 +332,7 @@ public class COPAC<V extends NumberVector<?>, D extends Distance<D>> extends Abs
}
// Parameterize algorithm:
- ClassParameter<ClusteringAlgorithm<Clustering<Model>>> algP = new ClassParameter<ClusteringAlgorithm<Clustering<Model>>>(PARTITION_ALGORITHM_ID, ClusteringAlgorithm.class);
+ ClassParameter<ClusteringAlgorithm<Clustering<Model>>> algP = new ClassParameter<>(PARTITION_ALGORITHM_ID, ClusteringAlgorithm.class);
if(config.grab(algP)) {
ListParameterization predefined = new ListParameterization();
predefined.addParameter(AbstractDistanceBasedAlgorithm.DISTANCE_FUNCTION_ID, pdistI);
@@ -348,7 +348,7 @@ public class COPAC<V extends NumberVector<?>, D extends Distance<D>> extends Abs
@Override
protected COPAC<V, D> makeInstance() {
- return new COPAC<V, D>(pdistI, algC, algO);
+ return new COPAC<>(pdistI, algC, algO);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/ERiC.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/ERiC.java
index 7e7314b4..d535e136 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/ERiC.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/ERiC.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.correlation;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,8 +25,6 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.correlation;
import java.util.ArrayList;
import java.util.List;
-import java.util.SortedMap;
-import java.util.TreeMap;
import de.lmu.ifi.dbs.elki.algorithm.AbstractAlgorithm;
import de.lmu.ifi.dbs.elki.algorithm.clustering.ClusteringAlgorithm;
@@ -58,6 +56,8 @@ import de.lmu.ifi.dbs.elki.math.linearalgebra.pca.FirstNEigenPairFilter;
import de.lmu.ifi.dbs.elki.math.linearalgebra.pca.PCAFilteredResult;
import de.lmu.ifi.dbs.elki.math.linearalgebra.pca.PCAFilteredRunner;
import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.Hierarchy;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.Hierarchy.Iter;
import de.lmu.ifi.dbs.elki.utilities.documentation.Description;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
@@ -125,7 +125,7 @@ public class ERiC<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
StepProgress stepprog = LOG.isVerbose() ? new StepProgress(3) : null;
// run COPAC
- if(stepprog != null) {
+ if (stepprog != null) {
stepprog.beginStep(1, "Preprocessing local correlation dimensionalities and partitioning data", LOG);
}
Clustering<Model> copacResult = copacAlgorithm.run(relation);
@@ -133,16 +133,16 @@ public class ERiC<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
DistanceQuery<V, IntegerDistance> query = copacAlgorithm.getPartitionDistanceQuery();
// extract correlation clusters
- if(stepprog != null) {
+ if (stepprog != null) {
stepprog.beginStep(2, "Extract correlation clusters", LOG);
}
- SortedMap<Integer, List<Cluster<CorrelationModel<V>>>> clusterMap = extractCorrelationClusters(copacResult, relation, dimensionality);
- if(LOG.isDebugging()) {
+ List<List<Cluster<CorrelationModel<V>>>> clusterMap = extractCorrelationClusters(copacResult, relation, dimensionality);
+ if (LOG.isDebugging()) {
StringBuilder msg = new StringBuilder("Step 2: Extract correlation clusters...");
- for(Integer corrDim : clusterMap.keySet()) {
+ for (int corrDim = 0; corrDim < clusterMap.size(); corrDim++) {
List<Cluster<CorrelationModel<V>>> correlationClusters = clusterMap.get(corrDim);
msg.append("\n\ncorrDim ").append(corrDim);
- for(Cluster<CorrelationModel<V>> cluster : correlationClusters) {
+ for (Cluster<CorrelationModel<V>> cluster : correlationClusters) {
msg.append("\n cluster ").append(cluster).append(", ids: ").append(cluster.getIDs().size());
// .append(", level: ").append(cluster.getLevel()).append(", index: ").append(cluster.getLevelIndex());
// msg.append("\n basis " +
@@ -152,45 +152,45 @@ public class ERiC<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
}
LOG.debugFine(msg.toString());
}
- if(LOG.isVerbose()) {
+ if (LOG.isVerbose()) {
int clusters = 0;
- for(List<Cluster<CorrelationModel<V>>> correlationClusters : clusterMap.values()) {
+ for (List<Cluster<CorrelationModel<V>>> correlationClusters : clusterMap) {
clusters += correlationClusters.size();
}
LOG.verbose(clusters + " clusters extracted.");
}
// build hierarchy
- if(stepprog != null) {
+ if (stepprog != null) {
stepprog.beginStep(3, "Building hierarchy", LOG);
}
- buildHierarchy(clusterMap, query);
- if(LOG.isDebugging()) {
+ Clustering<CorrelationModel<V>> clustering = new Clustering<>("ERiC clustering", "eric-clustering");
+ buildHierarchy(clustering, clusterMap, query);
+ if (LOG.isDebugging()) {
StringBuilder msg = new StringBuilder("Step 3: Build hierarchy");
- for(Integer corrDim : clusterMap.keySet()) {
+ for (int corrDim = 0; corrDim < clusterMap.size(); corrDim++) {
List<Cluster<CorrelationModel<V>>> correlationClusters = clusterMap.get(corrDim);
- for(Cluster<CorrelationModel<V>> cluster : correlationClusters) {
+ for (Cluster<CorrelationModel<V>> cluster : correlationClusters) {
msg.append("\n cluster ").append(cluster).append(", ids: ").append(cluster.getIDs().size());
// .append(", level: ").append(cluster.getLevel()).append(", index: ").append(cluster.getLevelIndex());
- for(int i = 0; i < cluster.getParents().size(); i++) {
- msg.append("\n parent ").append(cluster.getParents().get(i));
+ for (Iter<Cluster<CorrelationModel<V>>> iter = clustering.getClusterHierarchy().iterParents(cluster); iter.valid(); iter.advance()) {
+ msg.append("\n parent ").append(iter.get());
}
- for(int i = 0; i < cluster.numChildren(); i++) {
- msg.append("\n child ").append(cluster.getChildren().get(i));
+ for (Iter<Cluster<CorrelationModel<V>>> iter = clustering.getClusterHierarchy().iterChildren(cluster); iter.valid(); iter.advance()) {
+ msg.append("\n child ").append(iter.get());
}
}
}
LOG.debugFine(msg.toString());
}
- if(stepprog != null) {
+ if (stepprog != null) {
stepprog.setCompleted(LOG);
}
- Clustering<CorrelationModel<V>> result = new Clustering<CorrelationModel<V>>("ERiC clustering", "eric-clustering");
- for(Cluster<CorrelationModel<V>> rc : clusterMap.get(clusterMap.lastKey())) {
- result.addCluster(rc);
+ for (Cluster<CorrelationModel<V>> rc : clusterMap.get(clusterMap.size() - 1)) {
+ clustering.addToplevelCluster(rc);
}
- return result;
+ return clustering;
}
/**
@@ -203,77 +203,75 @@ public class ERiC<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
*
* @param database the database containing the objects
* @param dimensionality the dimensionality of the feature space
- * @return a mapping of correlation dimension to maps of clusters
+ * @return a list of clusters for each dimensionality
*/
- private SortedMap<Integer, List<Cluster<CorrelationModel<V>>>> extractCorrelationClusters(Clustering<Model> copacResult, Relation<V> database, int dimensionality) {
+ private List<List<Cluster<CorrelationModel<V>>>> extractCorrelationClusters(Clustering<Model> copacResult, Relation<V> database, int dimensionality) {
// result
- SortedMap<Integer, List<Cluster<CorrelationModel<V>>>> clusterMap = new TreeMap<Integer, List<Cluster<CorrelationModel<V>>>>();
+ List<List<Cluster<CorrelationModel<V>>>> clusterMap = new ArrayList<>();
+ for (int i = 0; i <= dimensionality; i++) {
+ clusterMap.add(new ArrayList<Cluster<CorrelationModel<V>>>());
+ }
// noise cluster containing all noise objects over all partitions
Cluster<Model> noise = null;
// iterate over correlation dimensions
- for(Cluster<Model> clus : copacResult.getAllClusters()) {
+ for (Cluster<Model> clus : copacResult.getAllClusters()) {
DBIDs group = clus.getIDs();
- if(clus.getModel() != null && clus.getModel() instanceof DimensionModel) {
+ if (clus.getModel() != null && clus.getModel() instanceof DimensionModel) {
int correlationDimension = ((DimensionModel) clus.getModel()).getDimension();
ListParameterization parameters = pcaParameters(correlationDimension);
Class<PCAFilteredRunner<V>> cls = ClassGenericsUtil.uglyCastIntoSubclass(PCAFilteredRunner.class);
PCAFilteredRunner<V> pca = parameters.tryInstantiate(cls);
- for(ParameterException e : parameters.getErrors()) {
- LOG.warning("Error in internal parameterization: " + e.getMessage());
- }
+ parameters.failOnErrors();
// get cluster list for this dimension.
List<Cluster<CorrelationModel<V>>> correlationClusters = clusterMap.get(correlationDimension);
- if(correlationClusters == null) {
- correlationClusters = new ArrayList<Cluster<CorrelationModel<V>>>();
- clusterMap.put(correlationDimension, correlationClusters);
- }
-
PCAFilteredResult pcares = pca.processIds(group, database);
V centroid = Centroid.make(database, group).toVector(database);
- Cluster<CorrelationModel<V>> correlationCluster = new Cluster<CorrelationModel<V>>("[" + correlationDimension + "_" + correlationClusters.size() + "]", group, new CorrelationModel<V>(pcares, centroid), new ArrayList<Cluster<CorrelationModel<V>>>(), new ArrayList<Cluster<CorrelationModel<V>>>());
+ Cluster<CorrelationModel<V>> correlationCluster = new Cluster<>("[" + correlationDimension + "_" + correlationClusters.size() + "]", group, new CorrelationModel<>(pcares, centroid));
correlationClusters.add(correlationCluster);
}
// partition containing noise
- else if(clus.getModel() != null && clus.isNoise()) {
- if(noise == null) {
+ else if (clus.getModel() != null && clus.isNoise()) {
+ if (noise == null) {
noise = clus;
- }
- else {
+ } else {
ModifiableDBIDs merged = DBIDUtil.newHashSet(noise.getIDs());
merged.addDBIDs(clus.getIDs());
noise.setIDs(merged);
}
- }
- else {
+ } else {
throw new IllegalStateException("Unexpected group returned: " + clus.getClass().getName());
}
}
- if(noise != null && noise.size() > 0) {
+ if (noise != null && noise.size() > 0) {
// get cluster list for this dimension.
List<Cluster<CorrelationModel<V>>> correlationClusters = clusterMap.get(dimensionality);
- if(correlationClusters == null) {
- correlationClusters = new ArrayList<Cluster<CorrelationModel<V>>>();
- clusterMap.put(dimensionality, correlationClusters);
- }
ListParameterization parameters = pcaParameters(dimensionality);
Class<PCAFilteredRunner<V>> cls = ClassGenericsUtil.uglyCastIntoSubclass(PCAFilteredRunner.class);
PCAFilteredRunner<V> pca = parameters.tryInstantiate(cls);
- for(ParameterException e : parameters.getErrors()) {
+ for (ParameterException e : parameters.getErrors()) {
LOG.warning("Error in internal parameterization: " + e.getMessage());
}
PCAFilteredResult pcares = pca.processIds(noise.getIDs(), database);
V centroid = Centroid.make(database, noise.getIDs()).toVector(database);
- Cluster<CorrelationModel<V>> correlationCluster = new Cluster<CorrelationModel<V>>("[noise]", noise.getIDs(), new CorrelationModel<V>(pcares, centroid), new ArrayList<Cluster<CorrelationModel<V>>>(), new ArrayList<Cluster<CorrelationModel<V>>>());
+ Cluster<CorrelationModel<V>> correlationCluster = new Cluster<>("[noise]", noise.getIDs(), new CorrelationModel<>(pcares, centroid));
correlationClusters.add(correlationCluster);
}
+ // Delete dimensionalities not found.
+ for (int i = dimensionality; i > 0; i--) {
+ if (clusterMap.get(i).size() > 0) {
+ break;
+ }
+ clusterMap.remove(i);
+ }
+
return clusterMap;
}
@@ -292,48 +290,48 @@ public class ERiC<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
return parameters;
}
- private void buildHierarchy(SortedMap<Integer, List<Cluster<CorrelationModel<V>>>> clusterMap, DistanceQuery<V, IntegerDistance> query) {
- StringBuilder msg = new StringBuilder();
+ private void buildHierarchy(Clustering<CorrelationModel<V>> clustering, List<List<Cluster<CorrelationModel<V>>>> clusterMap, DistanceQuery<V, IntegerDistance> query) {
+ StringBuilder msg = LOG.isDebuggingFine() ? new StringBuilder() : null;
+ Hierarchy<Cluster<CorrelationModel<V>>> hier = clustering.getClusterHierarchy();
DBSCAN<V, DoubleDistance> dbscan = ClassGenericsUtil.castWithGenericsOrNull(DBSCAN.class, copacAlgorithm.getPartitionAlgorithm(query));
- if(dbscan == null) {
+ if (dbscan == null) {
// TODO: appropriate exception class?
throw new IllegalArgumentException("ERiC was run without DBSCAN as COPAC algorithm!");
}
DistanceFunction<? super V, ?> dfun = ProxyDistanceFunction.unwrapDistance(dbscan.getDistanceFunction());
ERiCDistanceFunction distanceFunction = ClassGenericsUtil.castWithGenericsOrNull(ERiCDistanceFunction.class, dfun);
- if(distanceFunction == null) {
+ if (distanceFunction == null) {
// TODO: appropriate exception class?
throw new IllegalArgumentException("ERiC was run without ERiCDistanceFunction as distance function: got " + dfun.getClass());
}
- Integer lambda_max = clusterMap.lastKey();
+ // Find maximum dimensionality found:
+ int lambda_max = clusterMap.size() - 1;
- for(Integer childCorrDim : clusterMap.keySet()) {
+ for (int childCorrDim = 0; childCorrDim < lambda_max; childCorrDim++) {
List<Cluster<CorrelationModel<V>>> children = clusterMap.get(childCorrDim);
- SortedMap<Integer, List<Cluster<CorrelationModel<V>>>> parentMap = clusterMap.tailMap(childCorrDim + 1);
- if(LOG.isDebugging()) {
+ // SortedMap<Integer, List<Cluster<CorrelationModel<V>>>> parentMap =
+ // clusterMap.tailMap(childCorrDim + 1);
+ if (msg != null) {
msg.append("\ncorrdim ").append(childCorrDim);
- msg.append("\nparents ").append(parentMap.keySet());
+ // msg.append("\nparents ").append(parentMap.keySet());
}
- for(Cluster<CorrelationModel<V>> child : children) {
- for(Integer parentCorrDim : parentMap.keySet()) {
- List<Cluster<CorrelationModel<V>>> parents = parentMap.get(parentCorrDim);
- for(Cluster<CorrelationModel<V>> parent : parents) {
+ for (Cluster<CorrelationModel<V>> child : children) {
+ for (int parentCorrDim = childCorrDim + 1; parentCorrDim <= lambda_max; parentCorrDim++) {
+ List<Cluster<CorrelationModel<V>>> parents = clusterMap.get(parentCorrDim);
+ for (Cluster<CorrelationModel<V>> parent : parents) {
int subspaceDim_parent = parent.getModel().getPCAResult().getCorrelationDimension();
- if(subspaceDim_parent == lambda_max && child.getParents().isEmpty()) {
- parent.getChildren().add(child);
- child.getParents().add(parent);
- if(LOG.isDebugging()) {
+ if (subspaceDim_parent == lambda_max && hier.numParents(child) == 0) {
+ clustering.addChildCluster(parent, child);
+ if (msg != null) {
msg.append('\n').append(parent).append(" is parent of ").append(child);
}
- }
- else {
+ } else {
BitDistance dist = distanceFunction.distance(parent.getModel().getCentroid(), child.getModel().getCentroid(), parent.getModel().getPCAResult(), child.getModel().getPCAResult());
- if(!dist.bitValue() && (child.getParents().isEmpty() || !isParent(distanceFunction, parent, child.getParents()))) {
- parent.getChildren().add(child);
- child.getParents().add(parent);
- if(LOG.isDebugging()) {
+ if (!dist.bitValue() && (hier.numParents(child) == 0 || !isParent(distanceFunction, parent, hier.iterParents(child)))) {
+ clustering.addChildCluster(parent, child);
+ if (msg != null) {
msg.append('\n').append(parent).append(" is parent of ").append(child);
}
}
@@ -342,7 +340,7 @@ public class ERiC<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
}
}
}
- if(LOG.isDebugging()) {
+ if (msg != null) {
LOG.debugFine(msg.toString());
}
@@ -355,32 +353,32 @@ public class ERiC<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
* @param distanceFunction the distance function for distance computation
* between the clusters
* @param parent the parent to be tested
- * @param children the list of children to be tested
+ * @param iter the list of children to be tested
* @return true, if the specified parent cluster is a parent of one child of
* the children clusters, false otherwise
*/
- private boolean isParent(ERiCDistanceFunction distanceFunction, Cluster<CorrelationModel<V>> parent, List<Cluster<CorrelationModel<V>>> children) {
-
- StringBuilder msg = new StringBuilder();
+ private boolean isParent(ERiCDistanceFunction distanceFunction, Cluster<CorrelationModel<V>> parent, Iter<Cluster<CorrelationModel<V>>> iter) {
+ StringBuilder msg = LOG.isDebugging() ? new StringBuilder() : null;
- for(Cluster<CorrelationModel<V>> child : children) {
- if(parent.getModel().getPCAResult().getCorrelationDimension() == child.getModel().getPCAResult().getCorrelationDimension()) {
+ for (; iter.valid(); iter.advance()) {
+ Cluster<CorrelationModel<V>> child = iter.get();
+ if (parent.getModel().getPCAResult().getCorrelationDimension() == child.getModel().getPCAResult().getCorrelationDimension()) {
return false;
}
BitDistance dist = distanceFunction.distance(parent.getModel().getCentroid(), child.getModel().getCentroid(), parent.getModel().getPCAResult(), child.getModel().getPCAResult());
- if(LOG.isDebugging()) {
+ if (msg != null) {
msg.append("\ndist(").append(child).append(" - ").append(parent).append(") = ").append(dist);
}
- if(!dist.bitValue()) {
- if(LOG.isDebugging()) {
- LOG.debugFine(msg.toString());
+ if (!dist.bitValue()) {
+ if (msg != null) {
+ LOG.debugFine(msg);
}
return true;
}
}
- if(LOG.isDebugging()) {
+ if (msg != null) {
LOG.debugFine(msg.toString());
}
return false;
@@ -395,7 +393,7 @@ public class ERiC<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
protected Logging getLogger() {
return LOG;
}
-
+
/**
* Parameterization class.
*
@@ -418,7 +416,7 @@ public class ERiC<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
@Override
protected ERiC<V> makeInstance() {
- return new ERiC<V>(copac);
+ return new ERiC<>(copac);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/FourC.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/FourC.java
index f56342e0..5235273c 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/FourC.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/FourC.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.correlation;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -115,7 +115,7 @@ public class FourC<V extends NumberVector<?>> extends AbstractProjectedDBSCAN<Cl
@Override
protected FourC<O> makeInstance() {
- return new FourC<O>(epsilon, minpts, outerdist, lambda);
+ return new FourC<>(epsilon, minpts, outerdist, lambda);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/HiCO.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/HiCO.java
index 759e8f59..d1b714bf 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/HiCO.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/HiCO.java
@@ -64,7 +64,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
*/
@Title("Mining Hierarchies of Correlation Clusters")
@Description("Algorithm for detecting hierarchies of correlation clusters.")
-@Reference(authors = "E. Achtert, C. Böhm, P. Kröger, A. Zimek", title = "Mining Hierarchies of Correlation Clusterse", booktitle = "Proc. Int. Conf. on Scientific and Statistical Database Management (SSDBM'06), Vienna, Austria, 2006", url = "http://dx.doi.org/10.1109/SSDBM.2006.35")
+@Reference(authors = "E. Achtert, C. Böhm, P. Kröger, A. Zimek", title = "Mining Hierarchies of Correlation Clusters", booktitle = "Proc. Int. Conf. on Scientific and Statistical Database Management (SSDBM'06), Vienna, Austria, 2006", url = "http://dx.doi.org/10.1109/SSDBM.2006.35")
public class HiCO<V extends NumberVector<?>> extends OPTICS<V, PCACorrelationDistance> {
/**
* The logger for this class.
@@ -207,7 +207,7 @@ public class HiCO<V extends NumberVector<?>> extends OPTICS<V, PCACorrelationDis
@Override
protected HiCO<V> makeInstance() {
- return new HiCO<V>(distance, mu);
+ return new HiCO<>(distance, mu);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/LMCLUS.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/LMCLUS.java
index fdea8b35..f9531be0 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/LMCLUS.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/LMCLUS.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.correlation;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -159,7 +159,7 @@ public class LMCLUS extends AbstractAlgorithm<Clustering<Model>> {
* @return Clustering result
*/
public Clustering<Model> run(Database database, Relation<NumberVector<?>> relation) {
- Clustering<Model> ret = new Clustering<Model>("LMCLUS Clustering", "lmclus-clustering");
+ Clustering<Model> ret = new Clustering<>("LMCLUS Clustering", "lmclus-clustering");
FiniteProgress progress = LOG.isVerbose() ? new FiniteProgress("Clustered objects", relation.size(), LOG) : null;
IndefiniteProgress cprogress = LOG.isVerbose() ? new IndefiniteProgress("Clusters found", LOG) : null;
ModifiableDBIDs unclustered = DBIDUtil.newHashSet(relation.getDBIDs());
@@ -204,10 +204,10 @@ public class LMCLUS extends AbstractAlgorithm<Clustering<Model>> {
}
// New cluster found
// TODO: annotate cluster with dimensionality
- final Cluster<Model> cluster = new Cluster<Model>(current);
+ final Cluster<Model> cluster = new Cluster<>(current);
cluster.setName("Cluster_" + lmDim + "d_" + cnum);
cnum++;
- ret.addCluster(cluster);
+ ret.addToplevelCluster(cluster);
// Remove from main working set.
unclustered.removeDBIDs(current);
if (progress != null) {
@@ -219,7 +219,7 @@ public class LMCLUS extends AbstractAlgorithm<Clustering<Model>> {
}
// Remaining objects are noise
if (unclustered.size() > 0) {
- ret.addCluster(new Cluster<Model>(unclustered, true));
+ ret.addToplevelCluster(new Cluster<>(unclustered, true));
}
if (progress != null) {
progress.setProcessed(relation.size(), LOG);
@@ -281,7 +281,7 @@ public class LMCLUS extends AbstractAlgorithm<Clustering<Model>> {
// Build orthogonal basis from remainder
Matrix basis;
{
- List<Vector> vectors = new ArrayList<Vector>(sample.size() - 1);
+ List<Vector> vectors = new ArrayList<>(sample.size() - 1);
for (; iter.valid(); iter.advance()) {
Vector vec = relation.get(iter).getColumnVector();
vectors.add(vec.minusEquals(originV));
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/ORCLUS.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/ORCLUS.java
index f567098b..a9c67a58 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/ORCLUS.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/ORCLUS.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.correlation;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -42,10 +42,10 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.generic.GenericDistanceDBIDList;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.database.relation.RelationUtil;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.GenericDistanceDBIDList;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.progress.IndefiniteProgress;
@@ -178,9 +178,9 @@ public class ORCLUS<V extends NumberVector<?>> extends AbstractProjectedClusteri
}
// get the result
- Clustering<Model> r = new Clustering<Model>("ORCLUS clustering", "orclus-clustering");
+ Clustering<Model> r = new Clustering<>("ORCLUS clustering", "orclus-clustering");
for (ORCLUSCluster c : clusters) {
- r.addCluster(new Cluster<Model>(c.objectIDs, ClusterModel.CLUSTER));
+ r.addToplevelCluster(new Cluster<Model>(c.objectIDs, ClusterModel.CLUSTER));
}
return r;
} catch (Exception e) {
@@ -198,7 +198,7 @@ public class ORCLUS<V extends NumberVector<?>> extends AbstractProjectedClusteri
private List<ORCLUSCluster> initialSeeds(Relation<V> database, int k) {
DBIDs randomSample = DBIDUtil.randomSample(database.getDBIDs(), k, rnd);
NumberVector.Factory<V, ?> factory = RelationUtil.getNumberVectorFactory(database);
- List<ORCLUSCluster> seeds = new ArrayList<ORCLUSCluster>();
+ List<ORCLUSCluster> seeds = new ArrayList<>();
for (DBIDIter iter = randomSample.iter(); iter.valid(); iter.advance()) {
seeds.add(new ORCLUSCluster(database.get(iter), iter, factory));
}
@@ -222,7 +222,7 @@ public class ORCLUS<V extends NumberVector<?>> extends AbstractProjectedClusteri
}
// projected centroids of the clusters
- List<V> projectedCentroids = new ArrayList<V>(clusters.size());
+ List<V> projectedCentroids = new ArrayList<>(clusters.size());
for (ORCLUSCluster c : clusters) {
projectedCentroids.add(projection(c, c.centroid, factory));
}
@@ -270,7 +270,7 @@ public class ORCLUS<V extends NumberVector<?>> extends AbstractProjectedClusteri
private Matrix findBasis(Relation<V> database, DistanceQuery<V, DoubleDistance> distFunc, ORCLUSCluster cluster, int dim) {
// covariance matrix of cluster
// Matrix covariance = Util.covarianceMatrix(database, cluster.objectIDs);
- GenericDistanceDBIDList<DoubleDistance> results = new GenericDistanceDBIDList<DoubleDistance>(cluster.objectIDs.size());
+ GenericDistanceDBIDList<DoubleDistance> results = new GenericDistanceDBIDList<>(cluster.objectIDs.size());
for (DBIDIter it = cluster.objectIDs.iter(); it.valid(); it.advance()) {
DoubleDistance distance = distFunc.distance(cluster.centroid, database.get(it));
results.add(distance, it);
@@ -303,7 +303,7 @@ public class ORCLUS<V extends NumberVector<?>> extends AbstractProjectedClusteri
* @param d_new the new dimensionality of the subspaces for each seed
*/
private void merge(Relation<V> database, DistanceQuery<V, DoubleDistance> distFunc, List<ORCLUSCluster> clusters, int k_new, int d_new, IndefiniteProgress cprogress) {
- ArrayList<ProjectedEnergy> projectedEnergies = new ArrayList<ProjectedEnergy>();
+ ArrayList<ProjectedEnergy> projectedEnergies = new ArrayList<>();
for (int i = 0; i < clusters.size(); i++) {
for (int j = 0; j < clusters.size(); j++) {
if (i >= j) {
@@ -387,16 +387,16 @@ public class ORCLUS<V extends NumberVector<?>> extends AbstractProjectedClusteri
ORCLUSCluster c_ij = union(database, distFunc, c_i, c_j, dim);
NumberVector.Factory<V, ?> factory = RelationUtil.getNumberVectorFactory(database);
- DoubleDistance sum = getDistanceFunction().getDistanceFactory().nullDistance();
+ double sum = 0.;
V c_proj = projection(c_ij, c_ij.centroid, factory);
for (DBIDIter iter = c_ij.objectIDs.iter(); iter.valid(); iter.advance()) {
V o_proj = projection(c_ij, database.get(iter), factory);
- DoubleDistance dist = distFunc.distance(o_proj, c_proj);
- sum = sum.plus(dist.times(dist));
+ double dist = distFunc.distance(o_proj, c_proj).doubleValue();
+ sum += dist * dist;
}
- DoubleDistance projectedEnergy = sum.times(1.0 / c_ij.objectIDs.size());
+ sum /= c_ij.objectIDs.size();
- return new ProjectedEnergy(i, j, c_ij, projectedEnergy);
+ return new ProjectedEnergy(i, j, c_ij, sum);
}
/**
@@ -520,9 +520,9 @@ public class ORCLUS<V extends NumberVector<?>> extends AbstractProjectedClusteri
ORCLUSCluster cluster;
- DoubleDistance projectedEnergy;
+ double projectedEnergy;
- ProjectedEnergy(int i, int j, ORCLUSCluster cluster, DoubleDistance projectedEnergy) {
+ ProjectedEnergy(int i, int j, ORCLUSCluster cluster, double projectedEnergy) {
this.i = i;
this.j = j;
this.cluster = cluster;
@@ -538,7 +538,7 @@ public class ORCLUS<V extends NumberVector<?>> extends AbstractProjectedClusteri
*/
@Override
public int compareTo(ProjectedEnergy o) {
- return this.projectedEnergy.compareTo(o.projectedEnergy);
+ return Double.compare(projectedEnergy, o.projectedEnergy);
}
}
@@ -606,7 +606,7 @@ public class ORCLUS<V extends NumberVector<?>> extends AbstractProjectedClusteri
@Override
protected ORCLUS<V> makeInstance() {
- return new ORCLUS<V>(k, k_i, l, alpha, rnd, pca);
+ return new ORCLUS<>(k, k_i, l, alpha, rnd, pca);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/cash/CASHInterval.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/cash/CASHInterval.java
index 0153ddc3..95cb2e58 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/cash/CASHInterval.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/cash/CASHInterval.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.correlation.cash;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/cash/CASHIntervalSplit.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/cash/CASHIntervalSplit.java
index 12f10725..328fe3b3 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/cash/CASHIntervalSplit.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/cash/CASHIntervalSplit.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.correlation.cash;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -81,8 +81,8 @@ public class CASHIntervalSplit {
this.database = database;
this.minPts = minPts;
- this.f_minima = new HashMap<HyperBoundingBox, Map<DBID, Double>>();
- this.f_maxima = new HashMap<HyperBoundingBox, Map<DBID, Double>>();
+ this.f_minima = new HashMap<>();
+ this.f_maxima = new HashMap<>();
}
/**
@@ -108,9 +108,9 @@ public class CASHIntervalSplit {
Map<DBID, Double> minima = f_minima.get(interval);
Map<DBID, Double> maxima = f_maxima.get(interval);
if(minima == null || maxima == null) {
- minima = new HashMap<DBID, Double>();
+ minima = new HashMap<>();
f_minima.put(interval, minima);
- maxima = new HashMap<DBID, Double>();
+ maxima = new HashMap<>();
f_maxima.put(interval, maxima);
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/cash/ParameterizationFunction.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/cash/ParameterizationFunction.java
index 56e68bfe..5c690feb 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/cash/ParameterizationFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/cash/ParameterizationFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.correlation.cash;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/cash/package-info.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/cash/package-info.java
index 8b6d104c..bfc272fd 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/cash/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/cash/package-info.java
@@ -7,7 +7,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/package-info.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/package-info.java
index 665de632..89d3c930 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/package-info.java
@@ -7,7 +7,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/CorePredicate.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/CorePredicate.java
index a4440a29..27cc48d6 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/CorePredicate.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/CorePredicate.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.gdbscan;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/EpsilonNeighborPredicate.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/EpsilonNeighborPredicate.java
index 2b946f1c..545a8171 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/EpsilonNeighborPredicate.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/EpsilonNeighborPredicate.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.gdbscan;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -32,11 +32,11 @@ import de.lmu.ifi.dbs.elki.database.QueryUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
@@ -91,7 +91,7 @@ public class EpsilonNeighborPredicate<O, D extends Distance<D>> implements Neigh
public <T> NeighborPredicate.Instance<T> instantiate(Database database, SimpleTypeInformation<?> type) {
DistanceQuery<O, D> dq = QueryUtil.getDistanceQuery(database, distFunc);
RangeQuery<O, D> rq = database.getRangeQuery(dq);
- return (NeighborPredicate.Instance<T>) new Instance<D>(epsilon, rq, dq.getRelation().getDBIDs());
+ return (NeighborPredicate.Instance<T>) new Instance<>(epsilon, rq, dq.getRelation().getDBIDs());
}
@Override
@@ -109,7 +109,7 @@ public class EpsilonNeighborPredicate<O, D extends Distance<D>> implements Neigh
*
* @author Erich Schubert
*/
- public static class Instance<D extends Distance<D>> implements NeighborPredicate.Instance<DistanceDBIDResult<D>> {
+ public static class Instance<D extends Distance<D>> implements NeighborPredicate.Instance<DistanceDBIDList<D>> {
/**
* Range to query with
*/
@@ -145,12 +145,12 @@ public class EpsilonNeighborPredicate<O, D extends Distance<D>> implements Neigh
}
@Override
- public DistanceDBIDResult<D> getNeighbors(DBIDRef reference) {
+ public DistanceDBIDList<D> getNeighbors(DBIDRef reference) {
return rq.getRangeForDBID(reference, epsilon);
}
@Override
- public void addDBIDs(ModifiableDBIDs ids, DistanceDBIDResult<D> neighbors) {
+ public void addDBIDs(ModifiableDBIDs ids, DistanceDBIDList<D> neighbors) {
ids.addDBIDs(neighbors);
}
}
@@ -177,14 +177,14 @@ public class EpsilonNeighborPredicate<O, D extends Distance<D>> implements Neigh
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
// Get a distance function.
- ObjectParameter<DistanceFunction<O, D>> distanceP = new ObjectParameter<DistanceFunction<O, D>>(AbstractDistanceBasedAlgorithm.DISTANCE_FUNCTION_ID, DistanceFunction.class, EuclideanDistanceFunction.class);
+ ObjectParameter<DistanceFunction<O, D>> distanceP = new ObjectParameter<>(AbstractDistanceBasedAlgorithm.DISTANCE_FUNCTION_ID, DistanceFunction.class, EuclideanDistanceFunction.class);
D distanceFactory = null;
if(config.grab(distanceP)) {
distfun = distanceP.instantiateClass(config);
distanceFactory = distfun.getDistanceFactory();
}
// Get the epsilon parameter
- DistanceParameter<D> epsilonP = new DistanceParameter<D>(de.lmu.ifi.dbs.elki.algorithm.clustering.DBSCAN.EPSILON_ID, distanceFactory);
+ DistanceParameter<D> epsilonP = new DistanceParameter<>(de.lmu.ifi.dbs.elki.algorithm.clustering.DBSCAN.EPSILON_ID, distanceFactory);
if(config.grab(epsilonP)) {
epsilon = epsilonP.getValue();
}
@@ -192,7 +192,7 @@ public class EpsilonNeighborPredicate<O, D extends Distance<D>> implements Neigh
@Override
protected EpsilonNeighborPredicate<O, D> makeInstance() {
- return new EpsilonNeighborPredicate<O, D>(epsilon, distfun);
+ return new EpsilonNeighborPredicate<>(epsilon, distfun);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/GeneralizedDBSCAN.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/GeneralizedDBSCAN.java
index ef1cb0dc..1e0a8642 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/GeneralizedDBSCAN.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/GeneralizedDBSCAN.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.gdbscan;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -32,6 +32,7 @@ import de.lmu.ifi.dbs.elki.algorithm.clustering.ClusteringAlgorithm;
import de.lmu.ifi.dbs.elki.data.Cluster;
import de.lmu.ifi.dbs.elki.data.Clustering;
import de.lmu.ifi.dbs.elki.data.model.ClusterModel;
+import de.lmu.ifi.dbs.elki.data.model.CoreObjectsModel;
import de.lmu.ifi.dbs.elki.data.model.Model;
import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
@@ -53,6 +54,7 @@ import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Flag;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
/**
@@ -67,7 +69,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
*
* @author Erich Schubert
* @author Arthur Zimek
- *
+ *
* @apiviz.landmark
*
* @apiviz.has Instance
@@ -92,22 +94,29 @@ public class GeneralizedDBSCAN extends AbstractAlgorithm<Clustering<Model>> impl
CorePredicate corepred;
/**
+ * Track which objects are "core" objects.
+ */
+ boolean coremodel = false;
+
+ /**
* Constructor for parameterized algorithm.
*
- * @param npred Neighbor predicate
- * @param corepred Core point predicate
+ * @param npred Neighbor predicate.
+ * @param corepred Core point predicate.
+ * @param coremodel Keep track of core points.
*/
- public GeneralizedDBSCAN(NeighborPredicate npred, CorePredicate corepred) {
+ public GeneralizedDBSCAN(NeighborPredicate npred, CorePredicate corepred, boolean coremodel) {
super();
this.npred = npred;
this.corepred = corepred;
+ this.coremodel = coremodel;
}
@Override
public Clustering<Model> run(Database database) {
for (SimpleTypeInformation<?> t : npred.getOutputType()) {
if (corepred.acceptsType(t)) {
- return new Instance<Object>(npred.instantiate(database, t), corepred.instantiate(database, t)).run();
+ return new Instance<>(npred.instantiate(database, t), corepred.instantiate(database, t), coremodel).run();
}
}
throw new AbortException("No compatible types found.");
@@ -127,7 +136,7 @@ public class GeneralizedDBSCAN extends AbstractAlgorithm<Clustering<Model>> impl
* Instance for a particular data set.
*
* @author Erich Schubert
- *
+ *
* @apiviz.composedOf CorePredicate.Instance
* @apiviz.composedOf NeighborPredicate.Instance
*/
@@ -135,17 +144,12 @@ public class GeneralizedDBSCAN extends AbstractAlgorithm<Clustering<Model>> impl
/**
* Unprocessed IDs
*/
- private static final int UNPROCESSED = -2;
-
- /**
- * Noise IDs
- */
- private static final int NOISE = -1;
+ private static final int UNPROCESSED = 0;
/**
* Noise IDs
*/
- private static final int FIRST_CLUSTER = 0;
+ private static final int NOISE = 1;
/**
* The neighborhood predicate
@@ -158,15 +162,22 @@ public class GeneralizedDBSCAN extends AbstractAlgorithm<Clustering<Model>> impl
final CorePredicate.Instance<T> corepred;
/**
+ * Track which objects are "core" objects.
+ */
+ boolean coremodel = false;
+
+ /**
* Full Constructor
*
* @param npred Neighborhood predicate
* @param corepred Core object predicate
+ * @param coremodel Keep track of core points.
*/
- public Instance(NeighborPredicate.Instance<T> npred, CorePredicate.Instance<T> corepred) {
+ public Instance(NeighborPredicate.Instance<T> npred, CorePredicate.Instance<T> corepred, boolean coremodel) {
super();
this.npred = npred;
this.corepred = corepred;
+ this.coremodel = coremodel;
}
/**
@@ -177,78 +188,85 @@ public class GeneralizedDBSCAN extends AbstractAlgorithm<Clustering<Model>> impl
public Clustering<Model> run() {
final DBIDs ids = npred.getIDs();
// Setup progress logging
- final FiniteProgress progress = LOG.isVerbose() ? new FiniteProgress("Clustering", ids.size(), LOG) : null;
- final IndefiniteProgress clusprogress = LOG.isVerbose() ? new IndefiniteProgress("Clusters", LOG) : null;
+ final FiniteProgress progress = LOG.isVerbose() ? new FiniteProgress("Generalized DBSCAN Clustering", ids.size(), LOG) : null;
+ final IndefiniteProgress clusprogress = LOG.isVerbose() ? new IndefiniteProgress("Number of clusters found", LOG) : null;
// (Temporary) store the cluster ID assigned.
final WritableIntegerDataStore clusterids = DataStoreUtil.makeIntegerStorage(ids, DataStoreFactory.HINT_TEMP, UNPROCESSED);
- // Note: these are not exact!
+ // Note: these are not exact, as objects may be stolen from noise.
final TIntArrayList clustersizes = new TIntArrayList();
+ clustersizes.add(0); // Unprocessed dummy value.
+ clustersizes.add(0); // Noise counter.
// Implementation Note: using Integer objects should result in
// reduced memory use in the HashMap!
- int clusterid = FIRST_CLUSTER;
- int clustersize = 0;
- int noisesize = 0;
+ int clusterid = NOISE + 1;
// Iterate over all objects in the database.
- for(DBIDIter id = ids.iter(); id.valid(); id.advance()) {
+ for (DBIDIter id = ids.iter(); id.valid(); id.advance()) {
// Skip already processed ids.
- if(clusterids.intValue(id) != UNPROCESSED) {
+ if (clusterids.intValue(id) != UNPROCESSED) {
continue;
}
// Evaluate Neighborhood predicate
final T neighbors = npred.getNeighbors(id);
// Evaluate Core-Point predicate:
- if(corepred.isCorePoint(id, neighbors)) {
+ if (corepred.isCorePoint(id, neighbors)) {
clusterids.putInt(id, clusterid);
- clustersize = 1 + setbasedExpandCluster(clusterid, clusterids, neighbors, progress);
+ clustersizes.add(expandCluster(clusterid, clusterids, neighbors, progress));
// start next cluster on next iteration.
- clustersizes.add(clustersize);
- clustersize = 0;
- clusterid += 1;
- if(clusprogress != null) {
+ ++clusterid;
+ if (clusprogress != null) {
clusprogress.setProcessed(clusterid, LOG);
}
- }
- else {
+ } else {
// otherwise, it's a noise point
clusterids.putInt(id, NOISE);
- noisesize += 1;
+ clustersizes.set(NOISE, clustersizes.get(NOISE) + 1);
}
// We've completed this element
- if(progress != null) {
+ if (progress != null) {
progress.incrementProcessed(LOG);
}
}
// Finish progress logging.
- if(progress != null) {
+ if (progress != null) {
progress.ensureCompleted(LOG);
}
- if(clusprogress != null) {
+ if (clusprogress != null) {
clusprogress.setCompleted(LOG);
}
// Transform cluster ID mapping into a clustering result:
- ArrayList<ArrayModifiableDBIDs> clusterlists = new ArrayList<ArrayModifiableDBIDs>(clusterid + 1);
- // add noise cluster storage
- clusterlists.add(DBIDUtil.newArray(noisesize));
+ ArrayList<ArrayModifiableDBIDs> clusterlists = new ArrayList<>(clusterid);
+ ArrayList<ArrayModifiableDBIDs> corelists = coremodel ? new ArrayList<ArrayModifiableDBIDs>(clusterid) : null;
// add storage containers for clusters
- for(int i = 0; i < clustersizes.size(); i++) {
+ for (int i = 0; i < clustersizes.size(); i++) {
clusterlists.add(DBIDUtil.newArray(clustersizes.get(i)));
+ if (corelists != null) {
+ corelists.add(DBIDUtil.newArray(clustersizes.get(i)));
+ }
}
// do the actual inversion
- for(DBIDIter id = ids.iter(); id.valid(); id.advance()) {
- int cluster = clusterids.intValue(id);
- clusterlists.get(cluster + 1).add(id);
+ for (DBIDIter id = ids.iter(); id.valid(); id.advance()) {
+ // Negative values are non-core points:
+ int cid = clusterids.intValue(id);
+ int cluster = Math.abs(cid);
+ clusterlists.get(cluster).add(id);
+ if (corelists != null && cid > NOISE) {
+ corelists.get(cluster).add(id);
+ }
}
clusterids.destroy();
- Clustering<Model> result = new Clustering<Model>("GDBSCAN", "gdbscan-clustering");
- int cid = 0;
- for(ArrayModifiableDBIDs res : clusterlists) {
- boolean isNoise = (cid == 0);
- Cluster<Model> c = new Cluster<Model>(res, isNoise, ClusterModel.CLUSTER);
- result.addCluster(c);
- cid++;
+ Clustering<Model> result = new Clustering<>("GDBSCAN", "gdbscan-clustering");
+ for (int cid = NOISE; cid < clusterlists.size(); cid++) {
+ boolean isNoise = (cid == NOISE);
+ Cluster<Model> c;
+ if (corelists != null) {
+ c = new Cluster<Model>(clusterlists.get(cid), isNoise, new CoreObjectsModel(corelists.get(cid)));
+ } else {
+ c = new Cluster<Model>(clusterlists.get(cid), isNoise, ClusterModel.CLUSTER);
+ }
+ result.addToplevelCluster(c);
}
return result;
}
@@ -263,28 +281,36 @@ public class GeneralizedDBSCAN extends AbstractAlgorithm<Clustering<Model>> impl
*
* @return cluster size
*/
- protected int setbasedExpandCluster(final int clusterid, final WritableIntegerDataStore clusterids, final T neighbors, final FiniteProgress progress) {
- int clustersize = 0;
+ protected int expandCluster(final int clusterid, final WritableIntegerDataStore clusterids, final T neighbors, final FiniteProgress progress) {
+ int clustersize = 1; // initial seed!
final ArrayModifiableDBIDs activeSet = DBIDUtil.newArray();
npred.addDBIDs(activeSet, neighbors);
// run expandCluster as long as this set is non-empty (non-recursive
// implementation)
- while(!activeSet.isEmpty()) {
+ while (!activeSet.isEmpty()) {
final DBID id = activeSet.remove(activeSet.size() - 1);
- clustersize += 1;
// Assign object to cluster
- final int oldclus = clusterids.putInt(id, clusterid);
- if(oldclus == -2) {
+ final int oldclus = clusterids.intValue(id);
+ if (oldclus == NOISE) {
+ clustersize += 1;
+ // Non core point cluster member:
+ clusterids.putInt(id, -clusterid);
+ } else if (oldclus == UNPROCESSED) {
+ clustersize += 1;
// expandCluster again:
// Evaluate Neighborhood predicate
final T newneighbors = npred.getNeighbors(id);
// Evaluate Core-Point predicate
- if(corepred.isCorePoint(id, newneighbors)) {
+ if (corepred.isCorePoint(id, newneighbors)) {
// Note: the recursion is unrolled into iteration over the active
// set.
npred.addDBIDs(activeSet, newneighbors);
+ clusterids.putInt(id, clusterid);
+ } else {
+ // Non core point cluster member:
+ clusterids.putInt(id, -clusterid);
}
- if(progress != null) {
+ if (progress != null) {
progress.incrementProcessed(LOG);
}
}
@@ -302,43 +328,58 @@ public class GeneralizedDBSCAN extends AbstractAlgorithm<Clustering<Model>> impl
*/
public static class Parameterizer extends AbstractParameterizer {
/**
- * Neighborhood predicate
+ * Neighborhood predicate.
*/
NeighborPredicate npred = null;
/**
- * Core point predicate
+ * Core point predicate.
*/
CorePredicate corepred = null;
/**
- * Parameter for neighborhood predicate
+ * Track which objects are "core" objects.
+ */
+ boolean coremodel = false;
+
+ /**
+ * Parameter for neighborhood predicate.
*/
public static final OptionID NEIGHBORHOODPRED_ID = new OptionID("gdbscan.neighborhood", "Neighborhood predicate for GDBSCAN");
/**
- * Parameter for core predicate
+ * Parameter for core predicate.
*/
public static final OptionID COREPRED_ID = new OptionID("gdbscan.core", "Core point predicate for GDBSCAN");
+ /**
+ * Flag to keep track of core points.
+ */
+ public static final OptionID COREMODEL_ID = new OptionID("gdbscan.core-model", "Use a model that keeps track of core points. Needs more memory.");
+
@Override
protected void makeOptions(Parameterization config) {
// Neighborhood predicate
- ObjectParameter<NeighborPredicate> npredOpt = new ObjectParameter<NeighborPredicate>(NEIGHBORHOODPRED_ID, NeighborPredicate.class, EpsilonNeighborPredicate.class);
- if(config.grab(npredOpt)) {
+ ObjectParameter<NeighborPredicate> npredOpt = new ObjectParameter<>(NEIGHBORHOODPRED_ID, NeighborPredicate.class, EpsilonNeighborPredicate.class);
+ if (config.grab(npredOpt)) {
npred = npredOpt.instantiateClass(config);
}
// Core point predicate
- ObjectParameter<CorePredicate> corepredOpt = new ObjectParameter<CorePredicate>(COREPRED_ID, CorePredicate.class, MinPtsCorePredicate.class);
- if(config.grab(corepredOpt)) {
+ ObjectParameter<CorePredicate> corepredOpt = new ObjectParameter<>(COREPRED_ID, CorePredicate.class, MinPtsCorePredicate.class);
+ if (config.grab(corepredOpt)) {
corepred = corepredOpt.instantiateClass(config);
}
+
+ Flag coremodelOpt = new Flag(COREMODEL_ID);
+ if (config.grab(coremodelOpt)) {
+ coremodel = coremodelOpt.isTrue();
+ }
}
@Override
protected GeneralizedDBSCAN makeInstance() {
- return new GeneralizedDBSCAN(npred, corepred);
+ return new GeneralizedDBSCAN(npred, corepred, coremodel);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/MinPtsCorePredicate.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/MinPtsCorePredicate.java
index 47097f9b..a6e62e2e 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/MinPtsCorePredicate.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/MinPtsCorePredicate.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.gdbscan;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/NeighborPredicate.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/NeighborPredicate.java
index ed927696..c3e1e8c9 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/NeighborPredicate.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/NeighborPredicate.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.gdbscan;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/package-info.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/package-info.java
index 8be23c7d..7ea3c7e4 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/package-info.java
@@ -22,7 +22,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/CentroidLinkageMethod.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/CentroidLinkageMethod.java
new file mode 100644
index 00000000..72b6fb57
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/CentroidLinkageMethod.java
@@ -0,0 +1,84 @@
+package de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.utilities.Alias;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Centroid linkage clustering method, aka UPGMC: Unweighted Pair-Group Method
+ * using Centroids.
+ *
+ * Reference:
+ * <p>
+ * A. K. Jain and R. C. Dubes<br />
+ * Algorithms for Clustering Data<br />
+ * Prentice-Hall
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@Alias({ "centroid", "upgmc" })
+@Reference(authors = "A. K. Jain and R. C. Dubes", title = "Algorithms for Clustering Data", booktitle = "Algorithms for Clustering Data, Prentice-Hall")
+public class CentroidLinkageMethod implements LinkageMethod {
+ /**
+ * Static instance of class.
+ */
+ public static final CentroidLinkageMethod STATIC = new CentroidLinkageMethod();
+
+ /**
+ * Constructor.
+ *
+ * @deprecated use the static instance {@link #STATIC} instead.
+ */
+ @Deprecated
+ public CentroidLinkageMethod() {
+ super();
+ }
+
+ @Override
+ public double combine(int sizex, double dx, int sizey, double dy, int sizej, double dxy) {
+ final double wx = sizex / (double) (sizex + sizey);
+ final double wy = sizey / (double) (sizex + sizey);
+ final double beta = (sizex * sizey) / (double) ((sizex + sizey) * (sizex + sizey));
+ return wx * dx + wy * dy - beta * dxy;
+ }
+
+ /**
+ * Class parameterizer.
+ *
+ * Returns the static instance.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected CentroidLinkageMethod makeInstance() {
+ return STATIC;
+ }
+ }
+} // Sokal and Michener (1958), Gower (1967)
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/CompleteLinkageMethod.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/CompleteLinkageMethod.java
new file mode 100644
index 00000000..0cb47fa7
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/CompleteLinkageMethod.java
@@ -0,0 +1,70 @@
+package de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.utilities.Alias;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Complete-linkage clustering method.
+ *
+ * @author Erich Schubert
+ */
+@Alias({ "complete", "clink", "complete-link", "farthest-neighbor" })
+public class CompleteLinkageMethod implements LinkageMethod {
+ /**
+ * Static instance of class.
+ */
+ public static final CompleteLinkageMethod STATIC = new CompleteLinkageMethod();
+
+ /**
+ * Constructor.
+ *
+ * @deprecated use the static instance {@link #STATIC} instead.
+ */
+ @Deprecated
+ public CompleteLinkageMethod() {
+ super();
+ }
+
+ @Override
+ public double combine(int sizex, double dx, int sizey, double dy, int sizej, double dxy) {
+ return Math.max(dx, dy);
+ }
+
+ /**
+ * Class parameterizer.
+ *
+ * Returns the static instance.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected CompleteLinkageMethod makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/ExtractFlatClusteringFromHierarchy.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/ExtractFlatClusteringFromHierarchy.java
new file mode 100644
index 00000000..ac5cb77c
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/ExtractFlatClusteringFromHierarchy.java
@@ -0,0 +1,854 @@
+package de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import gnu.trove.list.array.TDoubleArrayList;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+
+import de.lmu.ifi.dbs.elki.algorithm.clustering.ClusteringAlgorithm;
+import de.lmu.ifi.dbs.elki.data.Cluster;
+import de.lmu.ifi.dbs.elki.data.Clustering;
+import de.lmu.ifi.dbs.elki.data.model.DendrogramModel;
+import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
+import de.lmu.ifi.dbs.elki.database.Database;
+import de.lmu.ifi.dbs.elki.database.datastore.DBIDDataStore;
+import de.lmu.ifi.dbs.elki.database.datastore.DataStore;
+import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory;
+import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
+import de.lmu.ifi.dbs.elki.database.datastore.DoubleDistanceDataStore;
+import de.lmu.ifi.dbs.elki.database.datastore.WritableIntegerDataStore;
+import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDArrayIter;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDVar;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterEqualConstraint;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DistanceParameter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.EnumParameter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Flag;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
+import de.lmu.ifi.dbs.elki.workflow.AlgorithmStep;
+
+/**
+ * Extract a flat clustering from a full hierarchy, represented in pointer form.
+ *
+ * FIXME: re-check tie handling!
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.uses HierarchicalClusteringAlgorithm
+ * @apiviz.uses PointerHierarchyRepresentationResult
+ * @apiviz.has Clustering
+ */
+public class ExtractFlatClusteringFromHierarchy<D extends Distance<D>> implements ClusteringAlgorithm<Clustering<DendrogramModel<D>>> {
+ /**
+ * Class logger.
+ */
+ private static final Logging LOG = Logging.getLogger(ExtractFlatClusteringFromHierarchy.class);
+
+ /**
+ * Threshold mode.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static enum ThresholdMode {
+ /** Cut by minimum number of clusters */
+ BY_MINCLUSTERS,
+ /** Cut by threshold */
+ BY_THRESHOLD,
+ /** No thresholding */
+ NO_THRESHOLD,
+ }
+
+ /**
+ * Output mode.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static enum OutputMode {
+ /** Strict partitioning. */
+ STRICT_PARTITIONS,
+ /** Partial hierarchy. */
+ PARTIAL_HIERARCHY,
+ }
+
+ /**
+ * Minimum number of clusters to extract
+ */
+ private final int minclusters;
+
+ /**
+ * Clustering algorithm to run to obtain the hierarchy.
+ */
+ private HierarchicalClusteringAlgorithm<D> algorithm;
+
+ /**
+ * Include empty cluster in the hierarchy produced.
+ */
+ private OutputMode outputmode = OutputMode.PARTIAL_HIERARCHY;
+
+ /**
+ * Threshold for extracting clusters.
+ */
+ private D threshold = null;
+
+ /**
+ * Disallow singleton clusters, but add them to the parent cluster instead.
+ */
+ private boolean singletons = false;
+
+ /**
+ * Constructor.
+ *
+ * @param algorithm Algorithm to run
+ * @param minclusters Minimum number of clusters
+ * @param outputmode Output mode: truncated hierarchy or strict partitions.
+ * @param singletons Allow producing singleton clusters.
+ */
+ public ExtractFlatClusteringFromHierarchy(HierarchicalClusteringAlgorithm<D> algorithm, int minclusters, OutputMode outputmode, boolean singletons) {
+ super();
+ this.algorithm = algorithm;
+ this.threshold = null;
+ this.minclusters = minclusters;
+ this.outputmode = outputmode;
+ this.singletons = singletons;
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param algorithm Algorithm to run
+ * @param threshold Distance threshold
+ * @param outputmode Output mode: truncated hierarchy or strict partitions.
+ * @param singletons Allow producing singleton clusters.
+ */
+ public ExtractFlatClusteringFromHierarchy(HierarchicalClusteringAlgorithm<D> algorithm, D threshold, OutputMode outputmode, boolean singletons) {
+ super();
+ this.algorithm = algorithm;
+ this.threshold = threshold;
+ this.minclusters = -1;
+ this.outputmode = outputmode;
+ this.singletons = singletons;
+ }
+
+ @Override
+ public Clustering<DendrogramModel<D>> run(Database database) {
+ PointerHierarchyRepresentationResult<D> pointerresult = algorithm.run(database);
+ DBIDs ids = pointerresult.getDBIDs();
+ DBIDDataStore pi = pointerresult.getParentStore();
+ DataStore<D> lambda = pointerresult.getParentDistanceStore();
+
+ Clustering<DendrogramModel<D>> result;
+ if (lambda instanceof DoubleDistanceDataStore) {
+ result = extractClustersDouble(ids, pi, (DoubleDistanceDataStore) lambda);
+ } else {
+ result = extractClusters(ids, pi, lambda);
+ }
+ result.addChildResult(pointerresult);
+
+ return result;
+ }
+
+ /**
+ * Extract all clusters from the pi-lambda-representation.
+ *
+ * @param ids Object ids to process
+ * @param pi Pi store
+ * @param lambda Lambda store
+ *
+ * @return Hierarchical clustering
+ */
+ private Clustering<DendrogramModel<D>> extractClusters(DBIDs ids, final DBIDDataStore pi, final DataStore<D> lambda) {
+ FiniteProgress progress = LOG.isVerbose() ? new FiniteProgress("Extracting clusters", ids.size(), LOG) : null;
+
+ // Sort DBIDs by lambda. We need this for two things:
+ // a) to determine the stop distance from "minclusters" parameter
+ // b) to process arrows in decreasing / increasing order
+ ArrayModifiableDBIDs order = DBIDUtil.newArray(ids);
+ order.sort(new CompareByLambda<>(lambda));
+ DBIDArrayIter it = order.iter(); // Used multiple times!
+
+ int split;
+ if (minclusters > 0) {
+ split = Math.max(ids.size() - minclusters, 0);
+ // Stop distance:
+ final D stopdist = lambda.get(order.get(split));
+
+ // Tie handling: decrement split.
+ while (split > 0) {
+ it.seek(split - 1);
+ if (stopdist.compareTo(lambda.get(it)) <= 0) {
+ split--;
+ } else {
+ break;
+ }
+ }
+ } else if (threshold != null) {
+ split = ids.size();
+ it.seek(split - 1);
+ while (threshold.compareTo(lambda.get(it)) <= 0 && it.valid()) {
+ split--;
+ it.retract();
+ }
+ } else { // full hierarchy
+ split = 0;
+ }
+
+ // Extract the child clusters
+ int expcnum = ids.size() - split;
+ WritableIntegerDataStore cluster_map = DataStoreUtil.makeIntegerStorage(ids, DataStoreFactory.HINT_TEMP, -1);
+ ArrayList<ModifiableDBIDs> cluster_dbids = new ArrayList<>(expcnum);
+ ArrayList<D> cluster_dist = new ArrayList<>(expcnum);
+ ArrayModifiableDBIDs cluster_leads = DBIDUtil.newArray(expcnum);
+
+ DBIDVar succ = DBIDUtil.newVar(); // Variable for successor.
+ // Go backwards on the lower part.
+ for (it.seek(split - 1); it.valid(); it.retract()) {
+ D dist = lambda.get(it); // Distance to successor
+ pi.assignVar(it, succ); // succ = pi(it)
+ int clusterid = cluster_map.intValue(succ);
+ // Successor cluster has already been created:
+ if (clusterid >= 0) {
+ cluster_dbids.get(clusterid).add(it);
+ cluster_map.putInt(it, clusterid);
+ // Update distance to maximum encountered:
+ if (cluster_dist.get(clusterid).compareTo(dist) < 0) {
+ cluster_dist.set(clusterid, dist);
+ }
+ } else {
+ // Need to start a new cluster:
+ clusterid = cluster_dbids.size(); // next cluster number.
+ ModifiableDBIDs cids = DBIDUtil.newArray();
+ // Add element and successor as initial members:
+ cids.add(succ);
+ cluster_map.putInt(succ, clusterid);
+ cids.add(it);
+ cluster_map.putInt(it, clusterid);
+ // Store new cluster.
+ cluster_dbids.add(cids);
+ cluster_leads.add(succ);
+ cluster_dist.add(dist);
+ }
+
+ // Decrement counter
+ if (progress != null) {
+ progress.incrementProcessed(LOG);
+ }
+ }
+ final Clustering<DendrogramModel<D>> dendrogram;
+ switch(outputmode) {
+ case PARTIAL_HIERARCHY: {
+ // Build a hierarchy out of these clusters.
+ dendrogram = new Clustering<>("Hierarchical Clustering", "hierarchical-clustering");
+ Cluster<DendrogramModel<D>> root = null;
+ ArrayList<Cluster<DendrogramModel<D>>> clusters = new ArrayList<>(expcnum);
+ // Convert initial clusters to cluster objects
+ {
+ int i = 0;
+ for (DBIDIter it2 = cluster_leads.iter(); it2.valid(); it2.advance(), i++) {
+ clusters.add(makeCluster(it2, cluster_dist.get(i), cluster_dbids.get(i)));
+ }
+ cluster_dist = null; // Invalidate
+ cluster_dbids = null; // Invalidate
+ }
+ // Process the upper part, bottom-up.
+ for (it.seek(split); it.valid(); it.advance()) {
+ int clusterid = cluster_map.intValue(it);
+ // The current cluster led by the current element:
+ final Cluster<DendrogramModel<D>> clus;
+ if (clusterid >= 0) {
+ clus = clusters.get(clusterid);
+ } else if (!singletons && ids.size() != 1) {
+ clus = null;
+ } else {
+ clus = makeCluster(it, null, DBIDUtil.deref(it));
+ }
+ // The successor to join:
+ pi.assignVar(it, succ); // succ = pi(it)
+ if (DBIDUtil.equal(it, succ)) {
+ assert (root == null);
+ root = clus;
+ } else {
+ // Parent cluster:
+ int parentid = cluster_map.intValue(succ);
+ D depth = lambda.get(it);
+ // Parent cluster exists - merge as a new cluster:
+ if (parentid >= 0) {
+ final Cluster<DendrogramModel<D>> pclus = clusters.get(parentid);
+ if (pclus.getModel().getDistance().equals(depth)) {
+ if (clus == null) {
+ ((ModifiableDBIDs) pclus.getIDs()).add(it);
+ } else {
+ dendrogram.addChildCluster(pclus, clus);
+ }
+ } else {
+ // Merge at new depth:
+ ModifiableDBIDs cids = DBIDUtil.newArray(clus == null ? 1 : 0);
+ if (clus == null) {
+ cids.add(it);
+ }
+ Cluster<DendrogramModel<D>> npclus = makeCluster(succ, depth, cids);
+ if (clus != null) {
+ dendrogram.addChildCluster(npclus, clus);
+ }
+ dendrogram.addChildCluster(npclus, pclus);
+ // Replace existing parent cluster: new depth
+ clusters.set(parentid, npclus);
+ }
+ } else {
+ // Merge with parent at this depth:
+ final Cluster<DendrogramModel<D>> pclus;
+ if (!singletons) {
+ ModifiableDBIDs cids = DBIDUtil.newArray(clus == null ? 2 : 1);
+ cids.add(succ);
+ if (clus == null) {
+ cids.add(it);
+ }
+ // New cluster for parent and/or new point
+ pclus = makeCluster(succ, depth, cids);
+ } else {
+ // Create a new, one-element cluster for parent, and a merged
+ // cluster on top.
+ pclus = makeCluster(succ, depth, DBIDUtil.EMPTYDBIDS);
+ dendrogram.addChildCluster(pclus, makeCluster(succ, null, DBIDUtil.deref(succ)));
+ }
+ if (clus != null) {
+ dendrogram.addChildCluster(pclus, clus);
+ }
+ // Store cluster:
+ parentid = clusters.size();
+ clusters.add(pclus); // Remember parent cluster
+ cluster_map.putInt(succ, parentid); // Reference
+ }
+ }
+
+ // Decrement counter
+ if (progress != null) {
+ progress.incrementProcessed(LOG);
+ }
+ }
+ assert (root != null);
+ // attach root
+ dendrogram.addToplevelCluster(root);
+ break;
+ }
+ case STRICT_PARTITIONS: {
+ // Build a hierarchy out of these clusters.
+ dendrogram = new Clustering<>("Flattened Hierarchical Clustering", "flattened-hierarchical-clustering");
+ // Convert initial clusters to cluster objects
+ {
+ int i = 0;
+ for (DBIDIter it2 = cluster_leads.iter(); it2.valid(); it2.advance(), i++) {
+ dendrogram.addToplevelCluster(makeCluster(it2, cluster_dist.get(i), cluster_dbids.get(i)));
+ }
+ cluster_dist = null; // Invalidate
+ cluster_dbids = null; // Invalidate
+ }
+ // Process the upper part, bottom-up.
+ for (it.seek(split); it.valid(); it.advance()) {
+ int clusterid = cluster_map.intValue(it);
+ if (clusterid < 0) {
+ dendrogram.addToplevelCluster(makeCluster(it, null, DBIDUtil.deref(it)));
+ }
+
+ // Decrement counter
+ if (progress != null) {
+ progress.incrementProcessed(LOG);
+ }
+ }
+ break;
+ }
+ default:
+ throw new AbortException("Unsupported output mode.");
+ }
+
+ if (progress != null) {
+ progress.ensureCompleted(LOG);
+ }
+
+ return dendrogram;
+ }
+
+ /**
+ * Extract all clusters from the pi-lambda-representation.
+ *
+ * @param ids Object ids to process
+ * @param pi Pi store
+ * @param lambda Lambda store
+ *
+ * @return Hierarchical clustering
+ */
+ private Clustering<DendrogramModel<D>> extractClustersDouble(DBIDs ids, final DBIDDataStore pi, final DoubleDistanceDataStore lambda) {
+ FiniteProgress progress = LOG.isVerbose() ? new FiniteProgress("Extracting clusters", ids.size(), LOG) : null;
+
+ // Sort DBIDs by lambda. We need this for two things:
+ // a) to determine the stop distance from "minclusters" parameter
+ // b) to process arrows in decreasing / increasing order
+ ArrayModifiableDBIDs order = DBIDUtil.newArray(ids);
+ order.sort(new CompareByDoubleLambda(lambda));
+ DBIDArrayIter it = order.iter(); // Used multiple times!
+
+ int split;
+ if (minclusters > 0) {
+ split = Math.max(ids.size() - minclusters, 0);
+ // Stop distance:
+ final double stopdist = lambda.doubleValue(order.get(split));
+
+ // Tie handling: decrement split.
+ while (split > 0) {
+ it.seek(split - 1);
+ if (stopdist <= lambda.doubleValue(it)) {
+ split--;
+ } else {
+ break;
+ }
+ }
+ } else if (threshold != null) {
+ split = ids.size();
+ it.seek(split - 1);
+ double stopdist = ((DoubleDistance) threshold).doubleValue();
+ while (stopdist <= lambda.doubleValue(it) && it.valid()) {
+ split--;
+ it.retract();
+ }
+ } else { // full hierarchy
+ split = 0;
+ }
+
+ // Extract the child clusters
+ int expcnum = ids.size() - split;
+ WritableIntegerDataStore cluster_map = DataStoreUtil.makeIntegerStorage(ids, DataStoreFactory.HINT_TEMP, -1);
+ ArrayList<ModifiableDBIDs> cluster_dbids = new ArrayList<>(expcnum);
+ TDoubleArrayList cluster_dist = new TDoubleArrayList(expcnum);
+ ArrayModifiableDBIDs cluster_leads = DBIDUtil.newArray(expcnum);
+
+ DBIDVar succ = DBIDUtil.newVar(); // Variable for successor.
+ // Go backwards on the lower part.
+ for (it.seek(split - 1); it.valid(); it.retract()) {
+ double dist = lambda.doubleValue(it); // Distance to successor
+ pi.assignVar(it, succ); // succ = pi(it)
+ int clusterid = cluster_map.intValue(succ);
+ // Successor cluster has already been created:
+ if (clusterid >= 0) {
+ cluster_dbids.get(clusterid).add(it);
+ cluster_map.putInt(it, clusterid);
+ // Update distance to maximum encountered:
+ if (cluster_dist.get(clusterid) < dist) {
+ cluster_dist.set(clusterid, dist);
+ }
+ } else {
+ // Need to start a new cluster:
+ clusterid = cluster_dbids.size(); // next cluster number.
+ ModifiableDBIDs cids = DBIDUtil.newArray();
+ // Add element and successor as initial members:
+ cids.add(succ);
+ cluster_map.putInt(succ, clusterid);
+ cids.add(it);
+ cluster_map.putInt(it, clusterid);
+ // Store new cluster.
+ cluster_dbids.add(cids);
+ cluster_leads.add(succ);
+ cluster_dist.add(dist);
+ }
+
+ // Decrement counter
+ if (progress != null) {
+ progress.incrementProcessed(LOG);
+ }
+ }
+ final Clustering<DendrogramModel<D>> dendrogram;
+ switch(outputmode) {
+ case PARTIAL_HIERARCHY: {
+ // Build a hierarchy out of these clusters.
+ dendrogram = new Clustering<>("Hierarchical Clustering", "hierarchical-clustering");
+ Cluster<DendrogramModel<D>> root = null;
+ ArrayList<Cluster<DendrogramModel<D>>> clusters = new ArrayList<>(expcnum);
+ // Convert initial clusters to cluster objects
+ {
+ int i = 0;
+ for (DBIDIter it2 = cluster_leads.iter(); it2.valid(); it2.advance(), i++) {
+ @SuppressWarnings("unchecked")
+ D depth = (D) new DoubleDistance(cluster_dist.get(i));
+ clusters.add(makeCluster(it2, depth, cluster_dbids.get(i)));
+ }
+ cluster_dist = null; // Invalidate
+ cluster_dbids = null; // Invalidate
+ }
+ // Process the upper part, bottom-up.
+ for (it.seek(split); it.valid(); it.advance()) {
+ int clusterid = cluster_map.intValue(it);
+ // The current cluster led by the current element:
+ final Cluster<DendrogramModel<D>> clus;
+ if (clusterid >= 0) {
+ clus = clusters.get(clusterid);
+ } else if (!singletons && ids.size() != 1) {
+ clus = null;
+ } else {
+ clus = makeCluster(it, null, DBIDUtil.deref(it));
+ }
+ // The successor to join:
+ pi.assignVar(it, succ); // succ = pi(it)
+ if (DBIDUtil.equal(it, succ)) {
+ assert (root == null);
+ root = clus;
+ } else {
+ // Parent cluster:
+ int parentid = cluster_map.intValue(succ);
+ @SuppressWarnings("unchecked")
+ D depth = (D) new DoubleDistance(lambda.doubleValue(it));
+ // Parent cluster exists - merge as a new cluster:
+ if (parentid >= 0) {
+ final Cluster<DendrogramModel<D>> pclus = clusters.get(parentid);
+ if (pclus.getModel().getDistance().equals(depth)) {
+ if (clus == null) {
+ ((ModifiableDBIDs) pclus.getIDs()).add(it);
+ } else {
+ dendrogram.addChildCluster(pclus, clus);
+ }
+ } else {
+ // Merge at new depth:
+ ModifiableDBIDs cids = DBIDUtil.newArray(clus == null ? 1 : 0);
+ if (clus == null) {
+ cids.add(it);
+ }
+ Cluster<DendrogramModel<D>> npclus = makeCluster(succ, depth, cids);
+ if (clus != null) {
+ dendrogram.addChildCluster(npclus, clus);
+ }
+ dendrogram.addChildCluster(npclus, pclus);
+ // Replace existing parent cluster: new depth
+ clusters.set(parentid, npclus);
+ }
+ } else {
+ // Merge with parent at this depth:
+ final Cluster<DendrogramModel<D>> pclus;
+ if (!singletons) {
+ ModifiableDBIDs cids = DBIDUtil.newArray(clus == null ? 2 : 1);
+ cids.add(succ);
+ if (clus == null) {
+ cids.add(it);
+ }
+ // New cluster for parent and/or new point
+ pclus = makeCluster(succ, depth, cids);
+ } else {
+ // Create a new, one-element cluster for parent, and a merged
+ // cluster on top.
+ pclus = makeCluster(succ, depth, DBIDUtil.EMPTYDBIDS);
+ dendrogram.addChildCluster(pclus, makeCluster(succ, null, DBIDUtil.deref(succ)));
+ }
+ if (clus != null) {
+ dendrogram.addChildCluster(pclus, clus);
+ }
+ // Store cluster:
+ parentid = clusters.size();
+ clusters.add(pclus); // Remember parent cluster
+ cluster_map.putInt(succ, parentid); // Reference
+ }
+ }
+
+ // Decrement counter
+ if (progress != null) {
+ progress.incrementProcessed(LOG);
+ }
+ }
+ assert (root != null);
+ // attach root
+ dendrogram.addToplevelCluster(root);
+ break;
+ }
+ case STRICT_PARTITIONS: {
+ // Build a hierarchy out of these clusters.
+ dendrogram = new Clustering<>("Flattened Hierarchical Clustering", "flattened-hierarchical-clustering");
+ // Convert initial clusters to cluster objects
+ {
+ int i = 0;
+ for (DBIDIter it2 = cluster_leads.iter(); it2.valid(); it2.advance(), i++) {
+ @SuppressWarnings("unchecked")
+ D depth = (D) new DoubleDistance(cluster_dist.get(i));
+ dendrogram.addToplevelCluster(makeCluster(it2, depth, cluster_dbids.get(i)));
+ }
+ cluster_dist = null; // Invalidate
+ cluster_dbids = null; // Invalidate
+ }
+ // Process the upper part, bottom-up.
+ for (it.seek(split); it.valid(); it.advance()) {
+ int clusterid = cluster_map.intValue(it);
+ if (clusterid < 0) {
+ dendrogram.addToplevelCluster(makeCluster(it, null, DBIDUtil.deref(it)));
+ }
+
+ // Decrement counter
+ if (progress != null) {
+ progress.incrementProcessed(LOG);
+ }
+ }
+ break;
+ }
+ default:
+ throw new AbortException("Unsupported output mode.");
+ }
+
+ if (progress != null) {
+ progress.ensureCompleted(LOG);
+ }
+
+ return dendrogram;
+ }
+
+ /**
+ * Make the cluster for the given object
+ *
+ * @param lead Leading object
+ * @param depth Linkage depth
+ * @param members Member objects
+ * @return Cluster
+ */
+ private Cluster<DendrogramModel<D>> makeCluster(DBIDRef lead, D depth, DBIDs members) {
+ final String name;
+ if (members.size() == 0) {
+ name = "mrg_" + DBIDUtil.toString(lead) + "_" + depth;
+ } else if (depth != null && depth.isInfiniteDistance() || (members.size() == 1 && members.contains(lead))) {
+ name = "obj_" + DBIDUtil.toString(lead);
+ } else if (depth != null) {
+ name = "clu_" + DBIDUtil.toString(lead) + "_" + depth;
+ } else {
+ // Complete data set only?
+ name = "clu_" + DBIDUtil.toString(lead);
+ }
+ Cluster<DendrogramModel<D>> cluster = new Cluster<>(name, members, new DendrogramModel<>(depth));
+ return cluster;
+ }
+
+ @Override
+ public TypeInformation[] getInputTypeRestriction() {
+ return algorithm.getInputTypeRestriction();
+ }
+
+ /**
+ * Order a DBID collection by the lambda value.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ *
+ * @param <D> Distance type
+ */
+ private static final class CompareByLambda<D extends Distance<D>> implements Comparator<DBIDRef> {
+ /**
+ * Lambda storage
+ */
+ private final DataStore<D> lambda;
+
+ /**
+ * Constructor.
+ *
+ * @param lambda Lambda storage
+ */
+ protected CompareByLambda(DataStore<D> lambda) {
+ this.lambda = lambda;
+ }
+
+ @Override
+ public int compare(DBIDRef id1, DBIDRef id2) {
+ D k1 = lambda.get(id1);
+ D k2 = lambda.get(id2);
+ assert (k1 != null);
+ assert (k2 != null);
+ return k1.compareTo(k2);
+ }
+ }
+
+ /**
+ * Order a DBID collection by the lambda value.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ private static final class CompareByDoubleLambda implements Comparator<DBIDRef> {
+ /**
+ * Lambda storage
+ */
+ private final DoubleDistanceDataStore lambda;
+
+ /**
+ * Constructor.
+ *
+ * @param lambda Lambda storage
+ */
+ protected CompareByDoubleLambda(DoubleDistanceDataStore lambda) {
+ this.lambda = lambda;
+ }
+
+ @Override
+ public int compare(DBIDRef id1, DBIDRef id2) {
+ double k1 = lambda.doubleValue(id1);
+ double k2 = lambda.doubleValue(id2);
+ return Double.compare(k1, k2);
+ }
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer<D extends Distance<D>> extends AbstractParameterizer {
+ /**
+ * Extraction mode to use.
+ */
+ public static final OptionID MODE_ID = new OptionID("hierarchical.threshold-mode", "The thresholding mode to use for extracting clusters: by desired number of clusters, or by distance threshold.");
+
+ /**
+ * The minimum number of clusters to extract.
+ */
+ public static final OptionID MINCLUSTERS_ID = new OptionID("hierarchical.minclusters", "The minimum number of clusters to extract (there may be more clusters when tied).");
+
+ /**
+ * The threshold level for which to extract the clustering.
+ */
+ public static final OptionID THRESHOLD_ID = new OptionID("hierarchical.threshold", "The threshold level for which to extract the clusters.");
+
+ /**
+ * Parameter to configure the output mode (nested or truncated clusters).
+ */
+ public static final OptionID OUTPUTMODE_ID = new OptionID("hierarchical.output-mode", "The output mode: a truncated cluster hierarchy, or a strict (flat) partitioning of the data set.");
+
+ /**
+ * Flag to produce singleton clusters.
+ */
+ public static final OptionID SINGLETONS_ID = new OptionID("hierarchical.singletons", "Do not avoid singleton clusters. This produces a more complex hierarchy.");
+
+ /**
+ * Number of clusters to extract.
+ */
+ int minclusters = -1;
+
+ /**
+ * Threshold level.
+ */
+ D threshold = null;
+
+ /**
+ * Flag to produce empty clusters to model the hierarchy above.
+ */
+ OutputMode outputmode = null;
+
+ /**
+ * The hierarchical clustering algorithm to run.
+ */
+ HierarchicalClusteringAlgorithm<D> algorithm;
+
+ /**
+ * Threshold mode.
+ */
+ ThresholdMode thresholdmode = null;
+
+ /**
+ * Also create singleton clusters.
+ */
+ boolean singletons = false;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ ObjectParameter<HierarchicalClusteringAlgorithm<D>> algorithmP = new ObjectParameter<>(AlgorithmStep.Parameterizer.ALGORITHM_ID, HierarchicalClusteringAlgorithm.class);
+ if (config.grab(algorithmP)) {
+ algorithm = algorithmP.instantiateClass(config);
+ }
+
+ EnumParameter<ThresholdMode> modeP = new EnumParameter<>(MODE_ID, ThresholdMode.class, ThresholdMode.BY_MINCLUSTERS);
+ if (config.grab(modeP)) {
+ thresholdmode = modeP.getValue();
+ }
+
+ if (thresholdmode == null || ThresholdMode.BY_MINCLUSTERS.equals(thresholdmode)) {
+ IntParameter minclustersP = new IntParameter(MINCLUSTERS_ID);
+ minclustersP.addConstraint(new GreaterEqualConstraint(1));
+ if (config.grab(minclustersP)) {
+ minclusters = minclustersP.intValue();
+ }
+ }
+
+ if (thresholdmode == null || ThresholdMode.BY_THRESHOLD.equals(thresholdmode)) {
+ // Fallback to double when no algorithm chosen yet:
+ @SuppressWarnings("unchecked")
+ final D factory = algorithm != null ? algorithm.getDistanceFactory() : (D) DoubleDistance.FACTORY;
+ DistanceParameter<D> distP = new DistanceParameter<>(THRESHOLD_ID, factory);
+ if (config.grab(distP)) {
+ threshold = distP.getValue();
+ }
+ }
+
+ if (thresholdmode == null || !ThresholdMode.NO_THRESHOLD.equals(thresholdmode)) {
+ EnumParameter<OutputMode> outputP = new EnumParameter<>(OUTPUTMODE_ID, OutputMode.class);
+ if (config.grab(outputP)) {
+ outputmode = outputP.getValue();
+ }
+ } else {
+ // This becomes full hierarchy:
+ minclusters = -1;
+ outputmode = OutputMode.PARTIAL_HIERARCHY;
+ }
+
+ Flag singletonsF = new Flag(SINGLETONS_ID);
+ if (config.grab(singletonsF)) {
+ singletons = singletonsF.isTrue();
+ }
+ }
+
+ @Override
+ protected ExtractFlatClusteringFromHierarchy<D> makeInstance() {
+ switch(thresholdmode) {
+ case NO_THRESHOLD:
+ case BY_MINCLUSTERS:
+ return new ExtractFlatClusteringFromHierarchy<>(algorithm, minclusters, outputmode, singletons);
+ case BY_THRESHOLD:
+ return new ExtractFlatClusteringFromHierarchy<>(algorithm, threshold, outputmode, singletons);
+ default:
+ throw new AbortException("Unknown extraction mode.");
+ }
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/GroupAverageLinkageMethod.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/GroupAverageLinkageMethod.java
new file mode 100644
index 00000000..079fb69b
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/GroupAverageLinkageMethod.java
@@ -0,0 +1,82 @@
+package de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.utilities.Alias;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Group-average linkage clustering method.
+ *
+ * Reference:
+ * <p>
+ * A. K. Jain and R. C. Dubes<br />
+ * Algorithms for Clustering Data<br />
+ * Prentice-Hall
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@Alias({ "upgma", "average", "average-link", "average-linkage", "UPGMA" })
+@Reference(authors = "A. K. Jain and R. C. Dubes", title = "Algorithms for Clustering Data", booktitle = "Algorithms for Clustering Data, Prentice-Hall")
+public class GroupAverageLinkageMethod implements LinkageMethod {
+ /**
+ * Static instance of class.
+ */
+ public static final GroupAverageLinkageMethod STATIC = new GroupAverageLinkageMethod();
+
+ /**
+ * Constructor.
+ *
+ * @deprecated use the static instance {@link #STATIC} instead.
+ */
+ @Deprecated
+ public GroupAverageLinkageMethod() {
+ super();
+ }
+
+ @Override
+ public double combine(int sizex, double dx, int sizey, double dy, int sizej, double dxy) {
+ final double wx = sizex / (double) (sizex + sizey);
+ final double wy = sizey / (double) (sizex + sizey);
+ return wx * dx + wy * dy;
+ }
+
+ /**
+ * Class parameterizer.
+ *
+ * Returns the static instance.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected GroupAverageLinkageMethod makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/HierarchicalClusteringAlgorithm.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/HierarchicalClusteringAlgorithm.java
new file mode 100644
index 00000000..f3595d51
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/HierarchicalClusteringAlgorithm.java
@@ -0,0 +1,51 @@
+package de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.algorithm.Algorithm;
+import de.lmu.ifi.dbs.elki.database.Database;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+
+/**
+ * Interface for hierarchical clustering algorithms.
+ *
+ * This interface allows the algorithms to be used by e.g.
+ * {@link ExtractFlatClusteringFromHierarchy}.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has PointerHierarchyRepresentationResult
+ *
+ * @param <D> Distance type
+ */
+public interface HierarchicalClusteringAlgorithm<D extends Distance<D>> extends Algorithm {
+ @Override
+ public PointerHierarchyRepresentationResult<D> run(Database db);
+
+ /**
+ * Return the distance type that will be used by the algorithm.
+ *
+ * @return Distance factory.
+ */
+ public D getDistanceFactory();
+}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/LinkageMethod.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/LinkageMethod.java
new file mode 100644
index 00000000..68d0b4d8
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/LinkageMethod.java
@@ -0,0 +1,56 @@
+package de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical;
+
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Abstract interface for implementing a new linkage method into hierarchical
+ * clustering.
+ *
+ * Reference:
+ * <p>
+ * G. N. Lance and W. T. Williams<br />
+ * A general theory of classificatory sorting strategies 1. Hierarchical systems
+ * <br/>
+ * The computer journal 9.4 (1967): 373-380.
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@Reference(authors = "G. N. Lance and W. T. Williams", title = "A general theory of classificatory sorting strategies 1. Hierarchical systems", booktitle = "The computer journal 9.4", url = "http://dx.doi.org/ 10.1093/comjnl/9.4.373")
+public interface LinkageMethod {
+ /**
+ * Compute combined linkage for two clusters.
+ *
+ * @param sizex Size of first cluster x before merging
+ * @param dx Distance of cluster x to j before merging
+ * @param sizey Size of second cluster y before merging
+ * @param dy Distance of cluster y to j before merging
+ * @param sizej Size of candidate cluster j
+ * @param dxy Distance between clusters x and y before merging
+ * @return Combined distance
+ */
+ double combine(int sizex, double dx, int sizey, double dy, int sizej, double dxy);
+}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/MedianLinkageMethod.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/MedianLinkageMethod.java
new file mode 100644
index 00000000..fe167cec
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/MedianLinkageMethod.java
@@ -0,0 +1,80 @@
+package de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.utilities.Alias;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Median-linkage clustering method: Weighted pair group method using centroids
+ * (WPGMC).
+ *
+ * Reference:
+ * <p>
+ * J.C. Gower<br/>
+ * A comparison of some methods of cluster analysis<br/>
+ * Biometrics (1967): 623-637.
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@Reference(authors = "J. C. Gower", title = "A comparison of some methods of cluster analysis", booktitle = "Biometrics (1967)", url = "http://www.jstor.org/stable/10.2307/2528417")
+@Alias({ "wpgmc", "WPGMC", "weighted-centroid" })
+public class MedianLinkageMethod implements LinkageMethod {
+ /**
+ * Static instance of class.
+ */
+ public static final MedianLinkageMethod STATIC = new MedianLinkageMethod();
+
+ /**
+ * Constructor.
+ *
+ * @deprecated use the static instance {@link #STATIC} instead.
+ */
+ @Deprecated
+ public MedianLinkageMethod() {
+ super();
+ }
+
+ @Override
+ public double combine(int sizex, double dx, int sizey, double dy, int sizej, double dxy) {
+ return .5 * (dx + dy) - .25 * dxy;
+ }
+
+ /**
+ * Class parameterizer.
+ *
+ * Returns the static instance.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected MedianLinkageMethod makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/NaiveAgglomerativeHierarchicalClustering.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/NaiveAgglomerativeHierarchicalClustering.java
new file mode 100644
index 00000000..ee3052a4
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/NaiveAgglomerativeHierarchicalClustering.java
@@ -0,0 +1,303 @@
+package de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm;
+import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
+import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.database.Database;
+import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory;
+import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
+import de.lmu.ifi.dbs.elki.database.datastore.WritableDBIDDataStore;
+import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDistanceDataStore;
+import de.lmu.ifi.dbs.elki.database.datastore.WritableIntegerDataStore;
+import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDArrayIter;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SquaredEuclideanDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
+
+/**
+ * This tutorial will step you through implementing a well known clustering
+ * algorithm, agglomerative hierarchical clustering, in multiple steps.
+ *
+ * This is the third step, where we add support for different linkage
+ * strategies.
+ *
+ * This is the naive O(n^3) algorithm. See {@link SLINK} for a much faster
+ * algorithm (however, only for single-linkage).
+ *
+ * Reference for the unified concept:
+ * <p>
+ * G. N. Lance and W. T. Williams<br />
+ * A general theory of classificatory sorting strategies 1. Hierarchical systems
+ * <br/>
+ * The computer journal 9.4 (1967): 373-380.
+ * </p>
+ *
+ * See also:
+ * <p>
+ * A Review of Classification<br />
+ * R. M. Cormack<br />
+ * Journal of the Royal Statistical Society. Series A, Vol. 134, No. 3
+ * </p>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.composedOf LinkageMethod
+ *
+ * @param <O> Object type
+ */
+@Reference(authors = "G. N. Lance and W. T. Williams", title = "A general theory of classificatory sorting strategies 1. Hierarchical systems", booktitle = "The computer journal 9.4", url = "http://dx.doi.org/ 10.1093/comjnl/9.4.373")
+public class NaiveAgglomerativeHierarchicalClustering<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBasedAlgorithm<O, D, PointerHierarchyRepresentationResult<DoubleDistance>> implements HierarchicalClusteringAlgorithm<DoubleDistance> {
+ /**
+ * Class logger
+ */
+ private static final Logging LOG = Logging.getLogger(NaiveAgglomerativeHierarchicalClustering.class);
+
+ /**
+ * Current linkage method in use.
+ */
+ LinkageMethod linkage = WardLinkageMethod.STATIC;
+
+ /**
+ * Constructor.
+ *
+ * @param distanceFunction Distance function to use
+ * @param linkage Linkage method
+ */
+ public NaiveAgglomerativeHierarchicalClustering(DistanceFunction<? super O, D> distanceFunction, LinkageMethod linkage) {
+ super(distanceFunction);
+ this.linkage = linkage;
+ }
+
+ /**
+ * Run the algorithm
+ *
+ * @param db Database
+ * @param relation Relation
+ * @return Clustering hierarchy
+ */
+ public PointerHierarchyRepresentationResult<DoubleDistance> run(Database db, Relation<O> relation) {
+ DistanceQuery<O, D> dq = db.getDistanceQuery(relation, getDistanceFunction());
+ ArrayDBIDs ids = DBIDUtil.ensureArray(relation.getDBIDs());
+ final int size = ids.size();
+
+ if (size > 0x10000) {
+ throw new AbortException("This implementation does not scale to data sets larger than " + 0x10000 + " instances (~17 GB RAM), which results in an integer overflow.");
+ }
+ if (SingleLinkageMethod.class.isInstance(linkage)) {
+ LOG.verbose("Notice: SLINK is a much faster algorithm for single-linkage clustering!");
+ }
+
+ // Compute the initial (lower triangular) distance matrix.
+ double[] scratch = new double[triangleSize(size)];
+ DBIDArrayIter ix = ids.iter(), iy = ids.iter(), ij = ids.iter();
+ // Position counter - must agree with computeOffset!
+ int pos = 0;
+ boolean square = WardLinkageMethod.class.isInstance(linkage) && !(SquaredEuclideanDistanceFunction.class.isInstance(getDistanceFunction()));
+ for (ix.seek(0); ix.valid(); ix.advance()) {
+ for (iy.seek(0); iy.getOffset() < ix.getOffset(); iy.advance()) {
+ scratch[pos] = dq.distance(ix, iy).doubleValue();
+ // Ward uses variances -- i.e. squared values
+ if (square) {
+ scratch[pos] *= scratch[pos];
+ }
+ pos++;
+ }
+ }
+
+ // Initialize space for result:
+ WritableDBIDDataStore pi = DataStoreUtil.makeDBIDStorage(ids, DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_STATIC);
+ WritableDoubleDistanceDataStore lambda = DataStoreUtil.makeDoubleDistanceStorage(ids, DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_STATIC);
+ WritableIntegerDataStore csize = DataStoreUtil.makeIntegerStorage(ids, DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP);
+ for (DBIDIter it = ids.iter(); it.valid(); it.advance()) {
+ pi.put(it, it);
+ lambda.put(it, Double.POSITIVE_INFINITY);
+ csize.put(it, 1);
+ }
+
+ // Repeat until everything merged into 1 cluster
+ FiniteProgress prog = LOG.isVerbose() ? new FiniteProgress("Agglomerative clustering", size - 1, LOG) : null;
+ for (int i = 1; i < size; i++) {
+ double mindist = Double.POSITIVE_INFINITY;
+ int x = -1, y = -1;
+ for (ix.seek(0); ix.valid(); ix.advance()) {
+ if (lambda.doubleValue(ix) < Double.POSITIVE_INFINITY) {
+ continue;
+ }
+ final int xbase = triangleSize(ix.getOffset());
+ for (iy.seek(0); iy.getOffset() < ix.getOffset(); iy.advance()) {
+ if (lambda.doubleValue(iy) < Double.POSITIVE_INFINITY) {
+ continue;
+ }
+ final int idx = xbase + iy.getOffset();
+ if (scratch[idx] <= mindist) {
+ mindist = scratch[idx];
+ x = ix.getOffset();
+ y = iy.getOffset();
+ }
+ }
+ }
+ assert (x >= 0 && y >= 0);
+ // Avoid allocating memory, by reusing existing iterators:
+ ix.seek(x);
+ iy.seek(y);
+ if (LOG.isDebuggingFine()) {
+ LOG.debugFine("Merging: " + DBIDUtil.toString(ix) + " -> " + DBIDUtil.toString(iy));
+ }
+ // Perform merge in data structure: x -> y
+ // Since y < x, prefer keeping y, dropping x.
+ lambda.put(ix, mindist);
+ pi.put(ix, iy);
+ // Merge into cluster
+ int sizex = csize.intValue(ix), sizey = csize.intValue(iy);
+ csize.put(iy, sizex + sizey);
+
+ // Update distance matrix. Note: miny < minx
+
+ // Implementation note: most will not need sizej, and could save the
+ // hashmap lookup.
+ final int xbase = triangleSize(x), ybase = triangleSize(y);
+
+ ij.seek(0);
+ // Write to (y, j), with j < y
+ for (; ij.getOffset() < y; ij.advance()) {
+ if (lambda.doubleValue(ij) < Double.POSITIVE_INFINITY) {
+ continue;
+ }
+ final int sizej = csize.intValue(ij);
+ scratch[ybase + ij.getOffset()] = linkage.combine(sizex, scratch[xbase + ij.getOffset()], sizey, scratch[ybase + ij.getOffset()], sizej, mindist);
+ }
+ ij.advance(); // Skip y
+ // Write to (j, y), with y < j < x
+ for (; ij.getOffset() < x; ij.advance()) {
+ if (lambda.doubleValue(ij) < Double.POSITIVE_INFINITY) {
+ continue;
+ }
+ final int jbase = triangleSize(ij.getOffset());
+ final int sizej = csize.intValue(ij);
+ scratch[jbase + y] = linkage.combine(sizex, scratch[xbase + ij.getOffset()], sizey, scratch[jbase + y], sizej, mindist);
+ }
+ ij.advance(); // Skip x
+ // Write to (j, y), with y < x < j
+ for (; ij.valid(); ij.advance()) {
+ if (lambda.doubleValue(ij) < Double.POSITIVE_INFINITY) {
+ continue;
+ }
+ final int sizej = csize.intValue(ij);
+ final int jbase = triangleSize(ij.getOffset());
+ scratch[jbase + y] = linkage.combine(sizex, scratch[jbase + x], sizey, scratch[jbase + y], sizej, mindist);
+ }
+ if (prog != null) {
+ prog.incrementProcessed(LOG);
+ }
+ }
+ if (prog != null) {
+ prog.ensureCompleted(LOG);
+ }
+
+ return new PointerHierarchyRepresentationResult<>(ids, pi, lambda);
+ }
+
+ /**
+ * Compute the size of a complete x by x triangle (minus diagonal)
+ *
+ * @param x Offset
+ * @return Size of complete triangle
+ */
+ protected static int triangleSize(int x) {
+ return (x * (x - 1)) >>> 1;
+ }
+
+ @Override
+ public DoubleDistance getDistanceFactory() {
+ return DoubleDistance.FACTORY;
+ }
+
+ @Override
+ public TypeInformation[] getInputTypeRestriction() {
+ // The input relation must match our distance function:
+ return TypeUtil.array(getDistanceFunction().getInputTypeRestriction());
+ }
+
+ @Override
+ protected Logging getLogger() {
+ return LOG;
+ }
+
+ /**
+ * Parameterization class
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ *
+ * @param <O> Object type
+ * @param <D> Distance type
+ */
+ public static class Parameterizer<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBasedAlgorithm.Parameterizer<O, D> {
+ /**
+ * Option ID for linkage parameter.
+ */
+ public static final OptionID LINKAGE_ID = new OptionID("hierarchical.linkage", "Linkage method to use (e.g. Ward, Single-Link)");
+
+ /**
+ * Current linkage in use.
+ */
+ protected LinkageMethod linkage;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ // We don't call super, because we want a different default distance.
+ ObjectParameter<DistanceFunction<O, D>> distanceFunctionP = makeParameterDistanceFunction(SquaredEuclideanDistanceFunction.class, DistanceFunction.class);
+ if (config.grab(distanceFunctionP)) {
+ distanceFunction = distanceFunctionP.instantiateClass(config);
+ }
+
+ ObjectParameter<LinkageMethod> linkageP = new ObjectParameter<>(LINKAGE_ID, LinkageMethod.class);
+ linkageP.setDefaultValue(WardLinkageMethod.class);
+ if (config.grab(linkageP)) {
+ linkage = linkageP.instantiateClass(config);
+ }
+ }
+
+ @Override
+ protected NaiveAgglomerativeHierarchicalClustering<O, D> makeInstance() {
+ return new NaiveAgglomerativeHierarchicalClustering<>(distanceFunction, linkage);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/PointerHierarchyRepresentationResult.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/PointerHierarchyRepresentationResult.java
new file mode 100644
index 00000000..c339fb09
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/PointerHierarchyRepresentationResult.java
@@ -0,0 +1,97 @@
+package de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.database.datastore.DBIDDataStore;
+import de.lmu.ifi.dbs.elki.database.datastore.DataStore;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.result.BasicResult;
+
+/**
+ * The pointer representation of a hierarchical clustering. Each object is
+ * represented by a parent object and the distance at which it joins the parent
+ * objects cluster.
+ *
+ * @author Erich Schubert
+ *
+ * @param <D> Distance type
+ */
+public class PointerHierarchyRepresentationResult<D extends Distance<D>> extends BasicResult {
+ /**
+ * The DBIDs in this result.
+ */
+ DBIDs ids;
+
+ /**
+ * The parent DBID relation.
+ */
+ DBIDDataStore parent;
+
+ /**
+ * Distance to the parent object.
+ */
+ DataStore<D> parentDistance;
+
+ /**
+ * Constructor.
+ *
+ * @param ids IDs processed.
+ * @param parent Parent pointer.
+ * @param parentDistance Distance to parent.
+ */
+ public PointerHierarchyRepresentationResult(DBIDs ids, DBIDDataStore parent, DataStore<D> parentDistance) {
+ super("Pointer Representation", "pointer-representation");
+ this.ids = ids;
+ this.parent = parent;
+ this.parentDistance = parentDistance;
+ }
+
+ /**
+ * Get the clustered DBIDs.
+ *
+ * @return DBIDs
+ */
+ public DBIDs getDBIDs() {
+ return ids;
+ }
+
+ /**
+ * Get the parent DBID relation.
+ *
+ * @return Parent relation.
+ */
+ public DBIDDataStore getParentStore() {
+ return parent;
+ }
+
+ /**
+ * Get the distance to the parent.
+ *
+ * @return Parent distance.
+ */
+ public DataStore<D> getParentDistanceStore() {
+ return parentDistance;
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/SLINK.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/SLINK.java
new file mode 100644
index 00000000..f1b58868
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/SLINK.java
@@ -0,0 +1,368 @@
+package de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm;
+import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
+import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.database.Database;
+import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory;
+import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
+import de.lmu.ifi.dbs.elki.database.datastore.WritableDBIDDataStore;
+import de.lmu.ifi.dbs.elki.database.datastore.WritableDataStore;
+import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDistanceDataStore;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDVar;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.DistanceUtil;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Description;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
+
+/**
+ * Implementation of the efficient Single-Link Algorithm SLINK of R. Sibson.
+ *
+ * <p>
+ * Reference:<br />
+ * R. Sibson: SLINK: An optimally efficient algorithm for the single-link
+ * cluster method. <br/>
+ * In: The Computer Journal 16 (1973), No. 1, p. 30-34.
+ * </p>
+ *
+ * @author Elke Achtert
+ * @author Erich Schubert
+ *
+ * @apiviz.has SingleLinkageMethod
+ *
+ * @param <O> the type of DatabaseObject the algorithm is applied on
+ * @param <D> the type of Distance used
+ */
+@Title("SLINK: Single Link Clustering")
+@Description("Hierarchical clustering algorithm based on single-link connectivity.")
+@Reference(authors = "R. Sibson", title = "SLINK: An optimally efficient algorithm for the single-link cluster method", booktitle = "The Computer Journal 16 (1973), No. 1, p. 30-34.", url = "http://dx.doi.org/10.1093/comjnl/16.1.30")
+@Alias(value = { "de.lmu.ifi.dbs.elki.algorithm.clustering.SLINK", "clustering.SLINK", "SLINK", "single-link", "single-linkage" })
+public class SLINK<O, D extends Distance<D>> extends AbstractDistanceBasedAlgorithm<O, D, PointerHierarchyRepresentationResult<D>> implements HierarchicalClusteringAlgorithm<D> {
+ /**
+ * The logger for this class.
+ */
+ private static final Logging LOG = Logging.getLogger(SLINK.class);
+
+ /**
+ * Constructor.
+ *
+ * @param distanceFunction Distance function
+ */
+ public SLINK(DistanceFunction<? super O, D> distanceFunction) {
+ super(distanceFunction);
+ }
+
+ /**
+ * Performs the SLINK algorithm on the given database.
+ */
+ public PointerHierarchyRepresentationResult<D> run(Database database, Relation<O> relation) {
+ DBIDs ids = relation.getDBIDs();
+ DistanceQuery<O, D> distQuery = database.getDistanceQuery(relation, getDistanceFunction());
+ @SuppressWarnings("unchecked")
+ Class<D> distCls = (Class<D>) getDistanceFunction().getDistanceFactory().getClass();
+ WritableDBIDDataStore pi = DataStoreUtil.makeDBIDStorage(ids, DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_STATIC);
+ WritableDataStore<D> lambda = DataStoreUtil.makeStorage(ids, DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_STATIC, distCls);
+ // Temporary storage for m.
+ WritableDataStore<D> m = DataStoreUtil.makeStorage(ids, DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP, distCls);
+
+ FiniteProgress progress = LOG.isVerbose() ? new FiniteProgress("Running SLINK", ids.size(), LOG) : null;
+ // has to be an array for monotonicity reasons!
+ ModifiableDBIDs processedIDs = DBIDUtil.newArray(ids.size());
+
+ // Optimized code path for double distances
+ if (getDistanceFunction() instanceof PrimitiveDoubleDistanceFunction && lambda instanceof WritableDoubleDistanceDataStore && m instanceof WritableDoubleDistanceDataStore) {
+ @SuppressWarnings("unchecked")
+ PrimitiveDoubleDistanceFunction<? super O> dist = (PrimitiveDoubleDistanceFunction<? super O>) getDistanceFunction();
+ WritableDoubleDistanceDataStore lambdad = (WritableDoubleDistanceDataStore) lambda;
+ WritableDoubleDistanceDataStore md = (WritableDoubleDistanceDataStore) m;
+ // apply the algorithm
+ for (DBIDIter id = ids.iter(); id.valid(); id.advance()) {
+ step1double(id, pi, lambdad);
+ step2double(id, processedIDs, distQuery.getRelation(), dist, md);
+ step3double(id, pi, lambdad, processedIDs, md);
+ step4double(id, pi, lambdad, processedIDs);
+
+ processedIDs.add(id);
+
+ if (progress != null) {
+ progress.incrementProcessed(LOG);
+ }
+ }
+ } else {
+ // apply the algorithm
+ for (DBIDIter id = ids.iter(); id.valid(); id.advance()) {
+ step1(id, pi, lambda);
+ step2(id, processedIDs, distQuery, m);
+ step3(id, pi, lambda, processedIDs, m);
+ step4(id, pi, lambda, processedIDs);
+
+ processedIDs.add(id);
+
+ if (progress != null) {
+ progress.incrementProcessed(LOG);
+ }
+ }
+ }
+
+ if (progress != null) {
+ progress.ensureCompleted(LOG);
+ }
+ // We don't need m anymore.
+ m.destroy();
+ m = null;
+
+ return new PointerHierarchyRepresentationResult<>(ids, pi, lambda);
+ }
+
+ /**
+ * First step: Initialize P(id) = id, L(id) = infinity.
+ *
+ * @param id the id of the object to be inserted into the pointer
+ * representation
+ * @param pi Pi data store
+ * @param lambda Lambda data store
+ */
+ private void step1(DBIDRef id, WritableDBIDDataStore pi, WritableDataStore<D> lambda) {
+ // P(n+1) = n+1:
+ pi.put(id, id);
+ // L(n+1) = infinity
+ lambda.put(id, getDistanceFunction().getDistanceFactory().infiniteDistance());
+ }
+
+ /**
+ * Second step: Determine the pairwise distances from all objects in the
+ * pointer representation to the new object with the specified id.
+ *
+ * @param id the id of the object to be inserted into the pointer
+ * representation
+ * @param processedIDs the already processed ids
+ * @param m Data store
+ * @param distFunc Distance function to use
+ */
+ private void step2(DBIDRef id, DBIDs processedIDs, DistanceQuery<O, D> distFunc, WritableDataStore<D> m) {
+ O newObj = distFunc.getRelation().get(id);
+ for (DBIDIter it = processedIDs.iter(); it.valid(); it.advance()) {
+ // M(i) = dist(i, n+1)
+ m.put(it, distFunc.distance(it, newObj));
+ }
+ }
+
+ /**
+ * Third step: Determine the values for P and L
+ *
+ * @param id the id of the object to be inserted into the pointer
+ * representation
+ * @param pi Pi data store
+ * @param lambda Lambda data store
+ * @param processedIDs the already processed ids
+ * @param m Data store
+ */
+ private void step3(DBIDRef id, WritableDBIDDataStore pi, WritableDataStore<D> lambda, DBIDs processedIDs, WritableDataStore<D> m) {
+ DBIDVar p_i = DBIDUtil.newVar();
+ // for i = 1..n
+ for (DBIDIter it = processedIDs.iter(); it.valid(); it.advance()) {
+ D l_i = lambda.get(it);
+ D m_i = m.get(it);
+ pi.assignVar(it, p_i); // p_i = pi(it)
+ D mp_i = m.get(p_i);
+
+ // if L(i) >= M(i)
+ if (l_i.compareTo(m_i) >= 0) {
+ // M(P(i)) = min { M(P(i)), L(i) }
+ m.put(p_i, DistanceUtil.min(mp_i, l_i));
+
+ // L(i) = M(i)
+ lambda.put(it, m_i);
+
+ // P(i) = n+1;
+ pi.put(it, id);
+ } else {
+ // M(P(i)) = min { M(P(i)), M(i) }
+ m.put(p_i, DistanceUtil.min(mp_i, m_i));
+ }
+ }
+ }
+
+ /**
+ * Fourth step: Actualize the clusters if necessary
+ *
+ * @param id the id of the current object
+ * @param pi Pi data store
+ * @param lambda Lambda data store
+ * @param processedIDs the already processed ids
+ */
+ private void step4(DBIDRef id, WritableDBIDDataStore pi, WritableDataStore<D> lambda, DBIDs processedIDs) {
+ DBIDVar p_i = DBIDUtil.newVar();
+ // for i = 1..n
+ for (DBIDIter it = processedIDs.iter(); it.valid(); it.advance()) {
+ D l_i = lambda.get(it);
+ pi.assignVar(it, p_i); // p_i = pi(it)
+ D lp_i = lambda.get(p_i);
+
+ // if L(i) >= L(P(i))
+ if (l_i.compareTo(lp_i) >= 0) {
+ // P(i) = n+1
+ pi.put(it, id);
+ }
+ }
+ }
+
+ /**
+ * First step: Initialize P(id) = id, L(id) = infinity.
+ *
+ * @param id the id of the object to be inserted into the pointer
+ * representation
+ * @param pi Pi data store
+ * @param lambda Lambda data store
+ */
+ private void step1double(DBIDRef id, WritableDBIDDataStore pi, WritableDoubleDistanceDataStore lambda) {
+ // P(n+1) = n+1:
+ pi.put(id, id);
+ // L(n+1) = infinity
+ lambda.putDouble(id, Double.POSITIVE_INFINITY);
+ }
+
+ /**
+ * Second step: Determine the pairwise distances from all objects in the
+ * pointer representation to the new object with the specified id.
+ *
+ * @param id the id of the object to be inserted into the pointer
+ * representation
+ * @param processedIDs the already processed ids
+ * @param m Data store
+ * @param relation Data relation
+ * @param distFunc Distance function to use
+ */
+ private void step2double(DBIDRef id, DBIDs processedIDs, Relation<? extends O> relation, PrimitiveDoubleDistanceFunction<? super O> distFunc, WritableDoubleDistanceDataStore m) {
+ O newObj = relation.get(id);
+ for (DBIDIter it = processedIDs.iter(); it.valid(); it.advance()) {
+ // M(i) = dist(i, n+1)
+ m.putDouble(it, distFunc.doubleDistance(relation.get(it), newObj));
+ }
+ }
+
+ /**
+ * Third step: Determine the values for P and L
+ *
+ * @param id the id of the object to be inserted into the pointer
+ * representation
+ * @param pi Pi data store
+ * @param lambda Lambda data store
+ * @param processedIDs the already processed ids
+ * @param m Data store
+ */
+ private void step3double(DBIDRef id, WritableDBIDDataStore pi, WritableDoubleDistanceDataStore lambda, DBIDs processedIDs, WritableDoubleDistanceDataStore m) {
+ DBIDVar p_i = DBIDUtil.newVar();
+ // for i = 1..n
+ for (DBIDIter it = processedIDs.iter(); it.valid(); it.advance()) {
+ double l_i = lambda.doubleValue(it);
+ double m_i = m.doubleValue(it);
+ pi.assignVar(it, p_i); // p_i = pi(it)
+ double mp_i = m.doubleValue(p_i);
+
+ // if L(i) >= M(i)
+ if (l_i >= m_i) {
+ // M(P(i)) = min { M(P(i)), L(i) }
+ m.putDouble(p_i, Math.min(mp_i, l_i));
+
+ // L(i) = M(i)
+ lambda.putDouble(it, m_i);
+
+ // P(i) = n+1;
+ pi.put(it, id);
+ } else {
+ // M(P(i)) = min { M(P(i)), M(i) }
+ m.putDouble(p_i, Math.min(mp_i, m_i));
+ }
+ }
+ }
+
+ /**
+ * Fourth step: Actualize the clusters if necessary
+ *
+ * @param id the id of the current object
+ * @param pi Pi data store
+ * @param lambda Lambda data store
+ * @param processedIDs the already processed ids
+ */
+ private void step4double(DBIDRef id, WritableDBIDDataStore pi, WritableDoubleDistanceDataStore lambda, DBIDs processedIDs) {
+ DBIDVar p_i = DBIDUtil.newVar();
+ // for i = 1..n
+ for (DBIDIter it = processedIDs.iter(); it.valid(); it.advance()) {
+ double l_i = lambda.doubleValue(it);
+ pi.assignVar(it, p_i); // p_i = pi(it)
+ double lp_i = lambda.doubleValue(p_i);
+
+ // if L(i) >= L(P(i))
+ if (l_i >= lp_i) {
+ // P(i) = n+1
+ pi.put(it, id);
+ }
+ }
+ }
+
+ @Override
+ public D getDistanceFactory() {
+ return getDistanceFunction().getDistanceFactory();
+ }
+
+ @Override
+ public TypeInformation[] getInputTypeRestriction() {
+ return TypeUtil.array(getDistanceFunction().getInputTypeRestriction());
+ }
+
+ @Override
+ protected Logging getLogger() {
+ return LOG;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer<O, D extends Distance<D>> extends AbstractDistanceBasedAlgorithm.Parameterizer<O, D> {
+ @Override
+ protected SLINK<O, D> makeInstance() {
+ return new SLINK<>(distanceFunction);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/SingleLinkageMethod.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/SingleLinkageMethod.java
new file mode 100644
index 00000000..7ef81692
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/SingleLinkageMethod.java
@@ -0,0 +1,80 @@
+package de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.utilities.Alias;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Single-linkage clustering method.
+ *
+ * Reference:
+ * <p>
+ * K. Florek and J. Łukaszewicz and J. Perkal and H. Steinhaus and S. Zubrzycki<br/>
+ * Sur la liaison et la division des points d'un ensemble fini<br />
+ * In Colloquium Mathematicae (Vol. 2, No. 3-4)
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@Reference(authors = "K. Florek and J. Łukaszewicz and J. Perkal and H. Steinhaus and S. Zubrzycki", title = "Sur la liaison et la division des points d'un ensemble fini", booktitle = "Colloquium Mathematicae (Vol. 2, No. 3-4)")
+@Alias({ "single-link", "single", "slink", "nearest", "nearest-neighbor" })
+public class SingleLinkageMethod implements LinkageMethod {
+ /**
+ * Static instance of class.
+ */
+ public static final SingleLinkageMethod STATIC = new SingleLinkageMethod();
+
+ /**
+ * Constructor.
+ *
+ * @deprecated use the static instance {@link #STATIC} instead.
+ */
+ @Deprecated
+ public SingleLinkageMethod() {
+ super();
+ }
+
+ @Override
+ public double combine(int sizex, double dx, int sizey, double dy, int sizej, double dxy) {
+ return Math.min(dx, dy);
+ }
+
+ /**
+ * Class parameterizer.
+ *
+ * Returns the static instance.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected SingleLinkageMethod makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/WardLinkageMethod.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/WardLinkageMethod.java
new file mode 100644
index 00000000..488f011c
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/WardLinkageMethod.java
@@ -0,0 +1,86 @@
+package de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+
+/**
+ * Ward's method clustering method.
+ *
+ * This criterion minimizes variances, and makes most sense when used with
+ * squared Euclidean distance, see
+ * {@link de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SquaredEuclideanDistanceFunction}
+ *
+ * Reference:
+ * <p>
+ * Ward Jr, Joe H.<br />
+ * Hierarchical grouping to optimize an objective function<br />
+ * Journal of the American statistical association 58.301 (1963): 236-244.
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@Reference(authors = "J. H. Ward Jr", title = "Hierarchical grouping to optimize an objective function", booktitle = "Journal of the American statistical association 58.301", url = "http://dx.doi.org/10.1080/01621459.1963.10500845")
+@Alias({ "ward", "variance" })
+public class WardLinkageMethod implements LinkageMethod {
+ /**
+ * Static instance of class.
+ */
+ public static final WardLinkageMethod STATIC = new WardLinkageMethod();
+
+ /**
+ * Constructor.
+ *
+ * @deprecated use the static instance {@link #STATIC} instead.
+ */
+ @Deprecated
+ public WardLinkageMethod() {
+ super();
+ }
+
+ @Override
+ public double combine(int sizex, double dx, int sizey, double dy, int sizej, double dxy) {
+ final double wx = (sizex + sizej) / (double) (sizex + sizey + sizej);
+ final double wy = (sizey + sizej) / (double) (sizex + sizey + sizej);
+ final double beta = sizej / (double) (sizex + sizey + sizej);
+ return wx * dx + wy * dy - beta * dxy;
+ }
+
+ /**
+ * Class parameterizer.
+ *
+ * Returns the static instance.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected WardLinkageMethod makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/WeightedAverageLinkageMethod.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/WeightedAverageLinkageMethod.java
new file mode 100644
index 00000000..ac0b17f5
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/WeightedAverageLinkageMethod.java
@@ -0,0 +1,84 @@
+package de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.utilities.Alias;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Weighted average linkage clustering method.
+ *
+ * This is somewhat a misnomer, as it actually ignores that the clusters should
+ * likely be weighted differently according to their size when computing the
+ * average linkage. See {@link GroupAverageLinkageMethod} for the UPGMA method
+ * that uses the group size to weight the objects the same way.
+ *
+ * Reference:
+ * <p>
+ * A. K. Jain and R. C. Dubes<br />
+ * Algorithms for Clustering Data<br />
+ * Prentice-Hall
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@Reference(authors = "A. K. Jain and R. C. Dubes", title = "Algorithms for Clustering Data", booktitle = "Algorithms for Clustering Data, Prentice-Hall")
+@Alias({ "wpgma", "WPGMA" })
+public class WeightedAverageLinkageMethod implements LinkageMethod {
+ /**
+ * Static instance of class.
+ */
+ public static final WeightedAverageLinkageMethod STATIC = new WeightedAverageLinkageMethod();
+
+ /**
+ * Constructor.
+ *
+ * @deprecated use the static instance {@link #STATIC} instead.
+ */
+ @Deprecated
+ public WeightedAverageLinkageMethod() {
+ super();
+ }
+
+ @Override
+ public double combine(int sizex, double dx, int sizey, double dy, int sizej, double dxy) {
+ return .5 * (dx + dy);
+ }
+
+ /**
+ * Class parameterizer.
+ *
+ * Returns the static instance.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected WeightedAverageLinkageMethod makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/AbstractKMeans.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/AbstractKMeans.java
index 47855aad..dc1fa47c 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/AbstractKMeans.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/AbstractKMeans.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -43,9 +43,17 @@ import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SquaredEuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
import de.lmu.ifi.dbs.elki.utilities.datastructures.QuickSelect;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterEqualConstraint;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
/**
* Abstract base class for k-means implementations.
@@ -59,7 +67,7 @@ import de.lmu.ifi.dbs.elki.utilities.datastructures.QuickSelect;
* @param <D> Distance type
* @param <M> Cluster model type
*/
-public abstract class AbstractKMeans<V extends NumberVector<?>, D extends Distance<D>, M extends MeanModel<V>> extends AbstractPrimitiveDistanceBasedAlgorithm<NumberVector<?>, D, Clustering<M>> implements KMeans, ClusteringAlgorithm<Clustering<M>> {
+public abstract class AbstractKMeans<V extends NumberVector<?>, D extends Distance<D>, M extends MeanModel<V>> extends AbstractPrimitiveDistanceBasedAlgorithm<NumberVector<?>, D, Clustering<M>> implements KMeans<V, D, M>, ClusteringAlgorithm<Clustering<M>> {
/**
* Holds the value of {@link #K_ID}.
*/
@@ -102,54 +110,53 @@ public abstract class AbstractKMeans<V extends NumberVector<?>, D extends Distan
protected boolean assignToNearestCluster(Relation<V> relation, List<? extends NumberVector<?>> means, List<? extends ModifiableDBIDs> clusters) {
boolean changed = false;
- if(getDistanceFunction() instanceof PrimitiveDoubleDistanceFunction) {
+ if (getDistanceFunction() instanceof PrimitiveDoubleDistanceFunction) {
@SuppressWarnings("unchecked")
final PrimitiveDoubleDistanceFunction<? super NumberVector<?>> df = (PrimitiveDoubleDistanceFunction<? super NumberVector<?>>) getDistanceFunction();
- for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
+ for (DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
double mindist = Double.POSITIVE_INFINITY;
V fv = relation.get(iditer);
int minIndex = 0;
- for(int i = 0; i < k; i++) {
+ for (int i = 0; i < k; i++) {
double dist = df.doubleDistance(fv, means.get(i));
- if(dist < mindist) {
+ if (dist < mindist) {
minIndex = i;
mindist = dist;
}
}
- if(clusters.get(minIndex).add(iditer)) {
+ if (clusters.get(minIndex).add(iditer)) {
changed = true;
// Remove from previous cluster
// TODO: keep a list of cluster assignments to save this search?
- for(int i = 0; i < k; i++) {
- if(i != minIndex) {
- if(clusters.get(i).remove(iditer)) {
+ for (int i = 0; i < k; i++) {
+ if (i != minIndex) {
+ if (clusters.get(i).remove(iditer)) {
break;
}
}
}
}
}
- }
- else {
+ } else {
final PrimitiveDistanceFunction<? super NumberVector<?>, D> df = getDistanceFunction();
- for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
+ for (DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
D mindist = df.getDistanceFactory().infiniteDistance();
V fv = relation.get(iditer);
int minIndex = 0;
- for(int i = 0; i < k; i++) {
+ for (int i = 0; i < k; i++) {
D dist = df.distance(fv, means.get(i));
- if(dist.compareTo(mindist) < 0) {
+ if (dist.compareTo(mindist) < 0) {
minIndex = i;
mindist = dist;
}
}
- if(clusters.get(minIndex).add(iditer)) {
+ if (clusters.get(minIndex).add(iditer)) {
changed = true;
// Remove from previous cluster
// TODO: keep a list of cluster assignments to save this search?
- for(int i = 0; i < k; i++) {
- if(i != minIndex) {
- if(clusters.get(i).remove(iditer)) {
+ for (int i = 0; i < k; i++) {
+ if (i != minIndex) {
+ if (clusters.get(i).remove(iditer)) {
break;
}
}
@@ -174,21 +181,24 @@ public abstract class AbstractKMeans<V extends NumberVector<?>, D extends Distan
* @return the mean vectors of the given clusters in the given database
*/
protected List<Vector> means(List<? extends ModifiableDBIDs> clusters, List<? extends NumberVector<?>> means, Relation<V> database) {
- List<Vector> newMeans = new ArrayList<Vector>(k);
- for(int i = 0; i < k; i++) {
+ List<Vector> newMeans = new ArrayList<>(k);
+ for (int i = 0; i < k; i++) {
ModifiableDBIDs list = clusters.get(i);
Vector mean = null;
- if(list.size() > 0) {
+ if (list.size() > 0) {
double s = 1.0 / list.size();
DBIDIter iter = list.iter();
assert (iter.valid());
mean = database.get(iter).getColumnVector().timesEquals(s);
+ double[] raw = mean.getArrayRef();
iter.advance();
- for(; iter.valid(); iter.advance()) {
- mean.plusTimesEquals(database.get(iter).getColumnVector(), s);
+ for (; iter.valid(); iter.advance()) {
+ NumberVector<?> vec = database.get(iter);
+ for (int j = 0; j < mean.getDimensionality(); j++) {
+ raw[j] += s * vec.doubleValue(j);
+ }
}
- }
- else {
+ } else {
mean = means.get(i).getColumnVector();
}
newMeans.add(mean);
@@ -207,19 +217,18 @@ public abstract class AbstractKMeans<V extends NumberVector<?>, D extends Distan
protected List<NumberVector<?>> medians(List<? extends ModifiableDBIDs> clusters, List<? extends NumberVector<?>> medians, Relation<V> database) {
final int dim = medians.get(0).getDimensionality();
final SortDBIDsBySingleDimension sorter = new SortDBIDsBySingleDimension(database);
- List<NumberVector<?>> newMedians = new ArrayList<NumberVector<?>>(k);
- for(int i = 0; i < k; i++) {
+ List<NumberVector<?>> newMedians = new ArrayList<>(k);
+ for (int i = 0; i < k; i++) {
ArrayModifiableDBIDs list = DBIDUtil.newArray(clusters.get(i));
- if(list.size() > 0) {
+ if (list.size() > 0) {
Vector mean = new Vector(dim);
- for(int d = 0; d < dim; d++) {
+ for (int d = 0; d < dim; d++) {
sorter.setDimension(d);
DBID id = QuickSelect.median(list, sorter);
mean.set(d, database.get(id).doubleValue(d));
}
newMedians.add(mean);
- }
- else {
+ } else {
newMedians.add((NumberVector<?>) medians.get(i));
}
}
@@ -235,7 +244,7 @@ public abstract class AbstractKMeans<V extends NumberVector<?>, D extends Distan
* @param op Cluster size change / Weight change
*/
protected void incrementalUpdateMean(Vector mean, V vec, int newsize, double op) {
- if(newsize == 0) {
+ if (newsize == 0) {
return; // Keep old mean
}
Vector delta = vec.getColumnVector();
@@ -256,65 +265,62 @@ public abstract class AbstractKMeans<V extends NumberVector<?>, D extends Distan
protected boolean macQueenIterate(Relation<V> relation, List<Vector> means, List<ModifiableDBIDs> clusters) {
boolean changed = false;
- if(getDistanceFunction() instanceof PrimitiveDoubleDistanceFunction) {
+ if (getDistanceFunction() instanceof PrimitiveDoubleDistanceFunction) {
// Raw distance function
@SuppressWarnings("unchecked")
final PrimitiveDoubleDistanceFunction<? super NumberVector<?>> df = (PrimitiveDoubleDistanceFunction<? super NumberVector<?>>) getDistanceFunction();
// Incremental update
- for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
+ for (DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
double mindist = Double.POSITIVE_INFINITY;
V fv = relation.get(iditer);
int minIndex = 0;
- for(int i = 0; i < k; i++) {
+ for (int i = 0; i < k; i++) {
double dist = df.doubleDistance(fv, means.get(i));
- if(dist < mindist) {
+ if (dist < mindist) {
minIndex = i;
mindist = dist;
}
}
// Update the cluster mean incrementally:
- for(int i = 0; i < k; i++) {
+ for (int i = 0; i < k; i++) {
ModifiableDBIDs ci = clusters.get(i);
- if(i == minIndex) {
- if(ci.add(iditer)) {
+ if (i == minIndex) {
+ if (ci.add(iditer)) {
incrementalUpdateMean(means.get(i), fv, ci.size(), +1);
changed = true;
}
- }
- else if(ci.remove(iditer)) {
+ } else if (ci.remove(iditer)) {
incrementalUpdateMean(means.get(i), fv, ci.size() + 1, -1);
changed = true;
}
}
}
- }
- else {
+ } else {
// Raw distance function
final PrimitiveDistanceFunction<? super NumberVector<?>, D> df = getDistanceFunction();
// Incremental update
- for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
+ for (DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
D mindist = df.getDistanceFactory().infiniteDistance();
V fv = relation.get(iditer);
int minIndex = 0;
- for(int i = 0; i < k; i++) {
+ for (int i = 0; i < k; i++) {
D dist = df.distance(fv, means.get(i));
- if(dist.compareTo(mindist) < 0) {
+ if (dist.compareTo(mindist) < 0) {
minIndex = i;
mindist = dist;
}
}
// Update the cluster mean incrementally:
- for(int i = 0; i < k; i++) {
+ for (int i = 0; i < k; i++) {
ModifiableDBIDs ci = clusters.get(i);
- if(i == minIndex) {
- if(ci.add(iditer)) {
+ if (i == minIndex) {
+ if (ci.add(iditer)) {
incrementalUpdateMean(means.get(i), fv, ci.size(), +1);
changed = true;
}
- }
- else if(ci.remove(iditer)) {
+ } else if (ci.remove(iditer)) {
incrementalUpdateMean(means.get(i), fv, ci.size() + 1, -1);
changed = true;
}
@@ -323,4 +329,76 @@ public abstract class AbstractKMeans<V extends NumberVector<?>, D extends Distan
}
return changed;
}
+
+ @Override
+ public void setK(int k) {
+ this.k = k;
+ }
+
+ @Override
+ public void setDistanceFunction(PrimitiveDistanceFunction<? super NumberVector<?>, D> distanceFunction) {
+ this.distanceFunction = distanceFunction;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public abstract static class Parameterizer<V extends NumberVector<?>, D extends Distance<D>> extends AbstractPrimitiveDistanceBasedAlgorithm.Parameterizer<NumberVector<?>, D> {
+ /**
+ * k Parameter.
+ */
+ protected int k;
+
+ /**
+ * Maximum number of iterations.
+ */
+ protected int maxiter;
+
+ /**
+ * Initialization method.
+ */
+ protected KMeansInitialization<V> initializer;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ ObjectParameter<PrimitiveDistanceFunction<NumberVector<?>, D>> distanceFunctionP = makeParameterDistanceFunction(SquaredEuclideanDistanceFunction.class, PrimitiveDistanceFunction.class);
+ if (config.grab(distanceFunctionP)) {
+ distanceFunction = distanceFunctionP.instantiateClass(config);
+ if (!(distanceFunction instanceof EuclideanDistanceFunction) && !(distanceFunction instanceof SquaredEuclideanDistanceFunction)) {
+ getLogger().warning("k-means optimizes the sum of squares - it should be used with squared euclidean distance and may stop converging otherwise!");
+ }
+ }
+
+ IntParameter kP = new IntParameter(K_ID);
+ kP.addConstraint(new GreaterConstraint(0));
+ if (config.grab(kP)) {
+ k = kP.getValue();
+ }
+
+ ObjectParameter<KMeansInitialization<V>> initialP = new ObjectParameter<>(INIT_ID, KMeansInitialization.class, RandomlyChosenInitialMeans.class);
+ if (config.grab(initialP)) {
+ initializer = initialP.instantiateClass(config);
+ }
+
+ IntParameter maxiterP = new IntParameter(MAXITER_ID, 0);
+ maxiterP.addConstraint(new GreaterEqualConstraint(0));
+ if (config.grab(maxiterP)) {
+ maxiter = maxiterP.getValue();
+ }
+ }
+
+ /**
+ * Get class logger.
+ *
+ * @return Logger
+ */
+ abstract protected Logging getLogger();
+
+ @Override
+ abstract protected AbstractKMeans<V, D, ?> makeInstance();
+ }
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/AbstractKMeansInitialization.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/AbstractKMeansInitialization.java
index 3a69c806..9e3eb478 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/AbstractKMeansInitialization.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/AbstractKMeansInitialization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/BestOfMultipleKMeans.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/BestOfMultipleKMeans.java
new file mode 100644
index 00000000..30bb640c
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/BestOfMultipleKMeans.java
@@ -0,0 +1,219 @@
+package de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans;
+
+/*
+ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.algorithm.AbstractAlgorithm;
+import de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.quality.KMeansQualityMeasure;
+import de.lmu.ifi.dbs.elki.data.Clustering;
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.model.MeanModel;
+import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
+import de.lmu.ifi.dbs.elki.database.Database;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterEqualConstraint;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
+
+/**
+ * Run K-Means multiple times, and keep the best run.
+ *
+ * @author Stephan Baier
+ * @author Erich Schubert
+ *
+ * @param <V> Vector type
+ * @param <D> Distance type
+ * @param <M> Model type
+ */
+public class BestOfMultipleKMeans<V extends NumberVector<?>, D extends Distance<?>, M extends MeanModel<V>> extends AbstractAlgorithm<Clustering<M>> implements KMeans<V, D, M> {
+ /**
+ * The logger for this class.
+ */
+ private static final Logging LOG = Logging.getLogger(BestOfMultipleKMeans.class);
+
+ /**
+ * Number of trials to do.
+ */
+ private int trials;
+
+ /**
+ * Variant of kMeans for the bisecting step.
+ */
+ private KMeans<V, D, M> innerkMeans;
+
+ /**
+ * Quality measure which should be used.
+ */
+ private KMeansQualityMeasure<? super V, ? super D> qualityMeasure;
+
+ /**
+ * Constructor.
+ *
+ * @param trials Number of trials to do.
+ * @param innerkMeans K-Means variant to actually use.
+ * @param qualityMeasure Quality measure
+ */
+ public BestOfMultipleKMeans(int trials, KMeans<V, D, M> innerkMeans, KMeansQualityMeasure<? super V, ? super D> qualityMeasure) {
+ super();
+ this.trials = trials;
+ this.innerkMeans = innerkMeans;
+ this.qualityMeasure = qualityMeasure;
+ }
+
+ @Override
+ public Clustering<M> run(Database database, Relation<V> relation) {
+ if (!(innerkMeans.getDistanceFunction() instanceof PrimitiveDistanceFunction)) {
+ throw new AbortException("K-Means results can only be evaluated for primitive distance functions, got: " + innerkMeans.getDistanceFunction().getClass());
+ }
+ final PrimitiveDistanceFunction<? super V, D> df = (PrimitiveDistanceFunction<? super V, D>) innerkMeans.getDistanceFunction();
+ Clustering<M> bestResult = null;
+ if (trials > 1) {
+ double bestCost = Double.POSITIVE_INFINITY;
+ FiniteProgress prog = LOG.isVerbose() ? new FiniteProgress("K-means iterations", trials, LOG) : null;
+ for (int i = 0; i < trials; i++) {
+ Clustering<M> currentCandidate = innerkMeans.run(database, relation);
+ double currentCost = qualityMeasure.calculateCost(currentCandidate, df, relation);
+
+ if (LOG.isVerbose()) {
+ LOG.verbose("Cost of candidate " + i + ": " + currentCost);
+ }
+
+ if (currentCost < bestCost) {
+ bestResult = currentCandidate;
+ bestCost = currentCost;
+ }
+ if (prog != null) {
+ prog.incrementProcessed(LOG);
+ }
+ }
+ if (prog != null) {
+ prog.ensureCompleted(LOG);
+ }
+ } else {
+ bestResult = innerkMeans.run(database);
+ }
+
+ return bestResult;
+ }
+
+ @Override
+ public TypeInformation[] getInputTypeRestriction() {
+ return innerkMeans.getInputTypeRestriction();
+ }
+
+ @Override
+ public DistanceFunction<? super V, D> getDistanceFunction() {
+ return innerkMeans.getDistanceFunction();
+ }
+
+ @Override
+ public void setK(int k) {
+ innerkMeans.setK(k);
+ }
+
+ @Override
+ public void setDistanceFunction(PrimitiveDistanceFunction<? super NumberVector<?>, D> distanceFunction) {
+ innerkMeans.setDistanceFunction(distanceFunction);
+ }
+
+ @Override
+ protected Logging getLogger() {
+ return LOG;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Stephan Baier
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ *
+ * @param <V> Vector type
+ * @param <D> Distance type
+ * @param <M> Model type
+ */
+ public static class Parameterizer<V extends NumberVector<?>, D extends Distance<D>, M extends MeanModel<V>> extends AbstractParameterizer {
+ /**
+ * Parameter to specify the iterations of the bisecting step.
+ */
+ public static final OptionID TRIALS_ID = new OptionID("kmeans.trials", "The number of trials to run.");
+
+ /**
+ * Parameter to specify the kMeans variant.
+ */
+ public static final OptionID KMEANS_ID = new OptionID("kmeans.algorithm", "KMeans variant to run multiple times.");
+
+ /**
+ * Parameter to specify the variant of quality measure.
+ */
+ public static final OptionID QUALITYMEASURE_ID = new OptionID("kmeans.qualitymeasure", "Quality measure variant for deciding which run to keep.");
+
+ /**
+ * Number of trials to perform.
+ */
+ protected int trials;
+
+ /**
+ * Variant of kMeans to use.
+ */
+ protected KMeans<V, D, M> kMeansVariant;
+
+ /**
+ * Quality measure.
+ */
+ protected KMeansQualityMeasure<? super V, ? super D> qualityMeasure;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ IntParameter trialsP = new IntParameter(TRIALS_ID);
+ trialsP.addConstraint(new GreaterEqualConstraint(1));
+ if (config.grab(trialsP)) {
+ trials = trialsP.intValue();
+ }
+
+ ObjectParameter<KMeans<V, D, M>> kMeansVariantP = new ObjectParameter<>(KMEANS_ID, KMeans.class);
+ if (config.grab(kMeansVariantP)) {
+ kMeansVariant = kMeansVariantP.instantiateClass(config);
+ }
+
+ ObjectParameter<KMeansQualityMeasure<V, ? super D>> qualityMeasureP = new ObjectParameter<>(QUALITYMEASURE_ID, KMeansQualityMeasure.class);
+ if (config.grab(qualityMeasureP)) {
+ qualityMeasure = qualityMeasureP.instantiateClass(config);
+ }
+ }
+
+ @Override
+ protected BestOfMultipleKMeans<V, D, M> makeInstance() {
+ return new BestOfMultipleKMeans<>(trials, kMeansVariant, qualityMeasure);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/FarthestPointsInitialMeans.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/FarthestPointsInitialMeans.java
new file mode 100644
index 00000000..a018c04b
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/FarthestPointsInitialMeans.java
@@ -0,0 +1,186 @@
+package de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.database.Database;
+import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDVar;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
+import de.lmu.ifi.dbs.elki.utilities.RandomFactory;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Flag;
+
+/**
+ * K-Means initialization by repeatedly choosing the farthest point.
+ *
+ * Note: this is less random than other initializations, so running multiple
+ * times will be more likely to return the same local minima.
+ *
+ * @author Erich Schubert
+ *
+ * @param <V> Vector type
+ * @param <D> Distance type
+ */
+public class FarthestPointsInitialMeans<V, D extends NumberDistance<D, ?>> extends AbstractKMeansInitialization<V> implements KMedoidsInitialization<V> {
+ /**
+ * Discard the first vector.
+ */
+ boolean dropfirst = true;
+
+ /**
+ * Constructor.
+ *
+ * @param rnd Random generator.
+ * @param dropfirst Flag to discard the first vector.
+ */
+ public FarthestPointsInitialMeans(RandomFactory rnd, boolean dropfirst) {
+ super(rnd);
+ this.dropfirst = dropfirst;
+ }
+
+ @Override
+ public List<V> chooseInitialMeans(Database database, Relation<V> relation, int k, PrimitiveDistanceFunction<? super NumberVector<?>, ?> distanceFunction) {
+ // Get a distance query
+ if (!(distanceFunction.getDistanceFactory() instanceof NumberDistance)) {
+ throw new AbortException("Farthest points K-Means initialization can only be used with numerical distances.");
+ }
+ @SuppressWarnings("unchecked")
+ final PrimitiveDistanceFunction<? super V, D> distF = (PrimitiveDistanceFunction<? super V, D>) distanceFunction;
+ DistanceQuery<V, D> distQ = database.getDistanceQuery(relation, distF);
+
+ // Chose first mean
+ List<V> means = new ArrayList<>(k);
+
+ Random random = rnd.getRandom();
+ DBIDIter first = DBIDUtil.randomSample(relation.getDBIDs(), 1, new Random(random.nextLong())).iter();
+ means.add(relation.get(first));
+
+ DBIDVar best = DBIDUtil.newVar(first);
+ for (int i = (dropfirst ? 0 : 1); i < k; i++) {
+ // Find farthest object:
+ double maxdist = Double.NEGATIVE_INFINITY;
+ for (DBIDIter it = relation.iterDBIDs(); it.valid(); it.advance()) {
+ double dsum = 0.;
+ for (V ex : means) {
+ dsum += distQ.distance(ex, it).doubleValue();
+ }
+ if (dsum > maxdist) {
+ maxdist = dsum;
+ best.set(it);
+ }
+ }
+ // Add new mean:
+ if (k == 0) {
+ means.clear(); // Remove temporary first element.
+ }
+ means.add(relation.get(best));
+ }
+
+ return means;
+ }
+
+ @Override
+ public DBIDs chooseInitialMedoids(int k, DistanceQuery<? super V, ?> distQ2) {
+ if (!(distQ2.getDistanceFactory() instanceof NumberDistance)) {
+ throw new AbortException("Farthest points K-Means initialization can only be used with numerical distances.");
+ }
+ @SuppressWarnings("unchecked")
+ DistanceQuery<? super V, D> distQ = (DistanceQuery<? super V, D>) distQ2;
+ final Relation<?> relation = distQ.getRelation();
+ // Chose first mean
+ ArrayModifiableDBIDs means = DBIDUtil.newArray(k);
+
+ Random random = rnd.getRandom();
+ DBIDIter first = DBIDUtil.randomSample(relation.getDBIDs(), 1, new Random(random.nextLong())).iter();
+ means.add(first);
+
+ DBIDVar best = DBIDUtil.newVar(first);
+ for (int i = (dropfirst ? 0 : 1); i < k; i++) {
+ // Find farthest object:
+ double maxdist = Double.NEGATIVE_INFINITY;
+ for (DBIDIter it = relation.iterDBIDs(); it.valid(); it.advance()) {
+ double dsum = 0.;
+ for (DBIDIter ex = means.iter(); ex.valid(); ex.advance()) {
+ dsum += distQ.distance(ex, it).doubleValue();
+ }
+ if (dsum > maxdist) {
+ maxdist = dsum;
+ best.set(it);
+ }
+ }
+ // Add new mean:
+ if (k == 0) {
+ means.clear(); // Remove temporary first element.
+ }
+ means.add(best);
+ }
+
+ return means;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer<V, D extends NumberDistance<D, ?>> extends AbstractKMeansInitialization.Parameterizer<V> {
+ /**
+ * Option ID to control the handling of the first object chosen.
+ */
+ public static final OptionID DROPFIRST_ID = new OptionID("farthest.dropfirst", "Drop the first object chosen (which is chosen randomly) for the farthest points heuristic.");
+
+ /**
+ * Flag for discarding the first object chosen.
+ */
+ protected boolean dropfirst = true;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ Flag dropfirstP = new Flag(DROPFIRST_ID);
+ if (config.grab(dropfirstP)) {
+ dropfirst = dropfirstP.isTrue();
+ }
+ }
+
+ @Override
+ protected FarthestPointsInitialMeans<V, D> makeInstance() {
+ return new FarthestPointsInitialMeans<>(rnd, dropfirst);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/FirstKInitialMeans.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/FirstKInitialMeans.java
index 1e51f4d6..08e2f116 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/FirstKInitialMeans.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/FirstKInitialMeans.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,6 +26,7 @@ import java.util.ArrayList;
import java.util.List;
import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
@@ -51,9 +52,9 @@ public class FirstKInitialMeans<V> implements KMeansInitialization<V>, KMedoidsI
}
@Override
- public List<V> chooseInitialMeans(Relation<V> relation, int k, PrimitiveDistanceFunction<? super V, ?> distanceFunction) {
+ public List<V> chooseInitialMeans(Database database, Relation<V> relation, int k, PrimitiveDistanceFunction<? super NumberVector<?>, ?> distanceFunction) {
DBIDIter iter = relation.iterDBIDs();
- List<V> means = new ArrayList<V>(k);
+ List<V> means = new ArrayList<>(k);
for(int i = 0; i < k && iter.valid(); i++, iter.advance()) {
means.add(relation.get(iter));
}
@@ -80,7 +81,7 @@ public class FirstKInitialMeans<V> implements KMeansInitialization<V>, KMedoidsI
public static class Parameterizer<V extends NumberVector<?>> extends AbstractParameterizer {
@Override
protected FirstKInitialMeans<V> makeInstance() {
- return new FirstKInitialMeans<V>();
+ return new FirstKInitialMeans<>();
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeans.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeans.java
index 68fc4e48..29c0a5c8 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeans.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeans.java
@@ -1,12 +1,10 @@
package de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
-
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,12 +23,27 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import de.lmu.ifi.dbs.elki.algorithm.DistanceBasedAlgorithm;
+import de.lmu.ifi.dbs.elki.algorithm.clustering.ClusteringAlgorithm;
+import de.lmu.ifi.dbs.elki.data.Clustering;
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.model.MeanModel;
+import de.lmu.ifi.dbs.elki.database.Database;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+
/**
* Some constants and options shared among kmeans family algorithms.
*
* @author Erich Schubert
+ *
+ * @param <V> Number vector type
+ * @param <D> Distance type
+ * @param <M> Actual model type
*/
-public interface KMeans {
+public interface KMeans<V extends NumberVector<?>, D extends Distance<?>, M extends MeanModel<V>> extends ClusteringAlgorithm<Clustering<M>>, DistanceBasedAlgorithm<V, D> {
/**
* Parameter to specify the initialization method
*/
@@ -52,4 +65,27 @@ public interface KMeans {
* Parameter to specify the random generator seed.
*/
public static final OptionID SEED_ID = new OptionID("kmeans.seed", "The random number generator seed.");
-} \ No newline at end of file
+
+ /**
+ * Run the clustering algorithm.
+ *
+ * @param database Database to run on.
+ * @param rel Relation to process.
+ * @return Clustering result
+ */
+ Clustering<M> run(Database database, Relation<V> rel);
+
+ /**
+ * Set the value of k. Needed for some types of nested k-means.
+ *
+ * @param k K parameter
+ */
+ void setK(int k);
+
+ /**
+ * Set the distance function to use.
+ *
+ * @param distanceFunction Distance function.
+ */
+ void setDistanceFunction(PrimitiveDistanceFunction<? super NumberVector<?>, D> distanceFunction);
+}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeansBisecting.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeansBisecting.java
new file mode 100644
index 00000000..37071d36
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeansBisecting.java
@@ -0,0 +1,231 @@
+package de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans;
+
+/*
+ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.LinkedList;
+
+import de.lmu.ifi.dbs.elki.algorithm.AbstractAlgorithm;
+import de.lmu.ifi.dbs.elki.data.Cluster;
+import de.lmu.ifi.dbs.elki.data.Clustering;
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.model.MeanModel;
+import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
+import de.lmu.ifi.dbs.elki.database.Database;
+import de.lmu.ifi.dbs.elki.database.ProxyDatabase;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.ChainedParameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.ListParameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
+
+/**
+ * The bisecting k-means algorithm works by starting with an initial
+ * partitioning into two clusters, then repeated splitting of the largest
+ * cluster to get additional clusters.
+ *
+ * Reference:<br>
+ * <p>
+ * M. Steinbach, G. Karypis, V. Kumar:<br />
+ * A Comparison of Document Clustering Techniques<br />
+ * KDD workshop on text mining. Vol. 400. No. 1
+ * </p>
+ *
+ * @author Stephan Baier
+ *
+ * @param <V> Vector type
+ * @param <D> Distance type
+ * @param <M> Model type
+ */
+@Reference(authors = "M. Steinbach, G. Karypis, V. Kumar", title = "A Comparison of Document Clustering Techniques", booktitle = "KDD workshop on text mining. Vol. 400. No. 1")
+public class KMeansBisecting<V extends NumberVector<?>, D extends Distance<?>, M extends MeanModel<V>> extends AbstractAlgorithm<Clustering<M>> implements KMeans<V, D, M> {
+ /**
+ * The logger for this class.
+ */
+ private static final Logging LOG = Logging.getLogger(KMeansBisecting.class);
+
+ /**
+ * Variant of kMeans for the bisecting step.
+ */
+ private KMeans<V, D, M> innerkMeans;
+
+ /**
+ * Desired value of k.
+ */
+ private int k;
+
+ /**
+ * Constructor.
+ *
+ * @param k k parameter - number of result clusters
+ * @param innerkMeans KMeans variant parameter - for bisecting step
+ */
+ public KMeansBisecting(int k, KMeans<V, D, M> innerkMeans) {
+ super();
+ this.k = k;
+ this.innerkMeans = innerkMeans;
+ }
+
+ @Override
+ public Clustering<M> run(Database database, Relation<V> relation) {
+ ProxyDatabase proxyDB = new ProxyDatabase(relation.getDBIDs(), database);
+
+ // Linked list is preferrable for scratch, as we will A) not need that many
+ // clusters and B) be doing random removals of the largest cluster (often at
+ // the head)
+ LinkedList<Cluster<M>> currentClusterList = new LinkedList<>();
+
+ FiniteProgress prog = LOG.isVerbose() ? new FiniteProgress("Bisecting k-means", k - 1, LOG) : null;
+
+ for (int j = 0; j < this.k - 1; j++) {
+ // Choose a cluster to split and project database to cluster
+ if (currentClusterList.size() == 0) {
+ proxyDB = new ProxyDatabase(relation.getDBIDs(), database);
+ } else {
+ Cluster<M> largestCluster = null;
+ for (Cluster<M> cluster : currentClusterList) {
+ if (largestCluster == null || cluster.size() > largestCluster.size()) {
+ largestCluster = cluster;
+ }
+ }
+ currentClusterList.remove(largestCluster);
+ proxyDB.setDBIDs(largestCluster.getIDs());
+ }
+
+ // Run the inner k-means algorithm:
+ // FIXME: ensure we run on the correct relation in a multirelational
+ // setting!
+ Clustering<M> innerResult = innerkMeans.run(proxyDB);
+ // Add resulting clusters to current result.
+ currentClusterList.addAll(innerResult.getAllClusters());
+
+ if (prog != null) {
+ prog.incrementProcessed(LOG);
+ }
+ if (LOG.isVerbose()) {
+ LOG.verbose("Iteration " + j);
+ }
+ }
+ if (prog != null) {
+ prog.ensureCompleted(LOG);
+ }
+
+ // add all current clusters to the result
+ Clustering<M> result = new Clustering<>("Bisecting k-Means Result", "Bisecting-k-means");
+ for (Cluster<M> cluster : currentClusterList) {
+ result.addToplevelCluster(cluster);
+ }
+ return result;
+ }
+
+ @Override
+ public TypeInformation[] getInputTypeRestriction() {
+ return innerkMeans.getInputTypeRestriction();
+ }
+
+ @Override
+ public DistanceFunction<? super V, D> getDistanceFunction() {
+ return innerkMeans.getDistanceFunction();
+ }
+
+ @Override
+ public void setK(int k) {
+ this.k = k;
+ }
+
+ @Override
+ public void setDistanceFunction(PrimitiveDistanceFunction<? super NumberVector<?>, D> distanceFunction) {
+ innerkMeans.setDistanceFunction(distanceFunction);
+ }
+
+ @Override
+ protected Logging getLogger() {
+ return LOG;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Stephan Baier
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ *
+ * @param <V> Vector type
+ * @param <D> Distance type
+ * @param <M> Model type
+ */
+ public static class Parameterizer<V extends NumberVector<?>, D extends Distance<?>, M extends MeanModel<V>> extends AbstractParameterizer {
+ /**
+ * Parameter to specify the kMeans variant.
+ */
+ public static final OptionID KMEANS_ID = new OptionID("bisecting.kmeansvariant", "KMeans variant");
+
+ /**
+ * Variant of kMeans
+ */
+ protected KMeans<V, D, M> kMeansVariant;
+
+ /**
+ * Desired number of clusters.
+ */
+ protected int k;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+
+ IntParameter kP = new IntParameter(KMeans.K_ID);
+ kP.addConstraint(new GreaterConstraint(1));
+ if (config.grab(kP)) {
+ k = kP.intValue();
+ }
+
+ ObjectParameter<KMeans<V, D, M>> kMeansVariantP = new ObjectParameter<>(KMEANS_ID, KMeans.class, BestOfMultipleKMeans.class);
+ if (config.grab(kMeansVariantP)) {
+ ListParameterization kMeansVariantParameters = new ListParameterization();
+
+ // We will always invoke this with k=2!
+ kMeansVariantParameters.addParameter(KMeans.K_ID, 2);
+
+ ChainedParameterization combinedConfig = new ChainedParameterization(kMeansVariantParameters, config);
+ combinedConfig.errorsTo(config);
+ kMeansVariant = kMeansVariantP.instantiateClass(combinedConfig);
+ }
+ }
+
+ @Override
+ protected KMeansBisecting<V, D, M> makeInstance() {
+ return new KMeansBisecting<>(k, kMeansVariant);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeansInitialization.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeansInitialization.java
index 54b3a2ce..06fb10c1 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeansInitialization.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeansInitialization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,6 +24,8 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans;
*/
import java.util.List;
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction;
@@ -31,7 +33,7 @@ import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction;
* Interface for initializing K-Means
*
* @author Erich Schubert
- *
+ *
* @apiviz.landmark
*
* @param <V> Object type
@@ -40,10 +42,12 @@ public interface KMeansInitialization<V> {
/**
* Choose initial means
*
+ * @param database Database context
* @param relation Relation
* @param k Parameter k
- * @param distanceFunction Distance function
+ * @param distanceFunction Distance function
+ *
* @return List of chosen means for k-means
*/
- public abstract List<V> chooseInitialMeans(Relation<V> relation, int k, PrimitiveDistanceFunction<? super V, ?> distanceFunction);
+ public abstract List<V> chooseInitialMeans(Database database, Relation<V> relation, int k, PrimitiveDistanceFunction<? super NumberVector<?>, ?> distanceFunction);
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeansLloyd.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeansLloyd.java
index f43c2277..e692293c 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeansLloyd.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeansLloyd.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,7 +26,6 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans;
import java.util.ArrayList;
import java.util.List;
-import de.lmu.ifi.dbs.elki.algorithm.AbstractPrimitiveDistanceBasedAlgorithm;
import de.lmu.ifi.dbs.elki.data.Cluster;
import de.lmu.ifi.dbs.elki.data.Clustering;
import de.lmu.ifi.dbs.elki.data.NumberVector;
@@ -36,19 +35,13 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.database.relation.RelationUtil;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.SquaredEuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.progress.IndefiniteProgress;
import de.lmu.ifi.dbs.elki.utilities.documentation.Description;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterEqualConstraint;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
/**
* Provides the k-means algorithm, using Lloyd-style bulk iterations.
@@ -90,28 +83,23 @@ public class KMeansLloyd<V extends NumberVector<?>, D extends Distance<D>> exten
super(distanceFunction, k, maxiter, initializer);
}
- /**
- * Run k-means.
- *
- * @param database Database
- * @param relation relation to use
- * @return result
- */
+ @Override
public Clustering<KMeansModel<V>> run(Database database, Relation<V> relation) {
if (relation.size() <= 0) {
- return new Clustering<KMeansModel<V>>("k-Means Clustering", "kmeans-clustering");
+ return new Clustering<>("k-Means Clustering", "kmeans-clustering");
}
// Choose initial means
- List<? extends NumberVector<?>> means = initializer.chooseInitialMeans(relation, k, getDistanceFunction());
+ List<? extends NumberVector<?>> means = initializer.chooseInitialMeans(database, relation, k, getDistanceFunction());
// Setup cluster assignment store
- List<ModifiableDBIDs> clusters = new ArrayList<ModifiableDBIDs>();
+ List<ModifiableDBIDs> clusters = new ArrayList<>();
for (int i = 0; i < k; i++) {
clusters.add(DBIDUtil.newHashSet(relation.size() / k));
}
+ IndefiniteProgress prog = LOG.isVerbose() ? new IndefiniteProgress("K-Means iteration", LOG) : null;
for (int iteration = 0; maxiter <= 0 || iteration < maxiter; iteration++) {
- if (LOG.isVerbose()) {
- LOG.verbose("K-Means iteration " + (iteration + 1));
+ if (prog != null) {
+ prog.incrementProcessed(LOG);
}
boolean changed = assignToNearestCluster(relation, means, clusters);
// Stop if no cluster assignment changed.
@@ -121,12 +109,16 @@ public class KMeansLloyd<V extends NumberVector<?>, D extends Distance<D>> exten
// Recompute means.
means = means(clusters, means, relation);
}
+ if (prog != null) {
+ prog.setCompleted(LOG);
+ }
+
// Wrap result
final NumberVector.Factory<V, ?> factory = RelationUtil.getNumberVectorFactory(relation);
- Clustering<KMeansModel<V>> result = new Clustering<KMeansModel<V>>("k-Means Clustering", "kmeans-clustering");
+ Clustering<KMeansModel<V>> result = new Clustering<>("k-Means Clustering", "kmeans-clustering");
for (int i = 0; i < clusters.size(); i++) {
- KMeansModel<V> model = new KMeansModel<V>(factory.newNumberVector(means.get(i).getColumnVector().getArrayRef()));
- result.addCluster(new Cluster<KMeansModel<V>>(clusters.get(i), model));
+ KMeansModel<V> model = new KMeansModel<>(factory.newNumberVector(means.get(i).getColumnVector().getArrayRef()));
+ result.addToplevelCluster(new Cluster<>(clusters.get(i), model));
}
return result;
}
@@ -143,53 +135,15 @@ public class KMeansLloyd<V extends NumberVector<?>, D extends Distance<D>> exten
*
* @apiviz.exclude
*/
- public static class Parameterizer<V extends NumberVector<?>, D extends Distance<D>> extends AbstractPrimitiveDistanceBasedAlgorithm.Parameterizer<NumberVector<?>, D> {
- /**
- * k Parameter.
- */
- protected int k;
-
- /**
- * Number of iterations.
- */
- protected int maxiter;
-
- /**
- * Initialization method.
- */
- protected KMeansInitialization<V> initializer;
-
+ public static class Parameterizer<V extends NumberVector<?>, D extends Distance<D>> extends AbstractKMeans.Parameterizer<V, D> {
@Override
- protected void makeOptions(Parameterization config) {
- ObjectParameter<PrimitiveDistanceFunction<NumberVector<?>, D>> distanceFunctionP = makeParameterDistanceFunction(SquaredEuclideanDistanceFunction.class, PrimitiveDistanceFunction.class);
- if(config.grab(distanceFunctionP)) {
- distanceFunction = distanceFunctionP.instantiateClass(config);
- if (!(distanceFunction instanceof EuclideanDistanceFunction) && !(distanceFunction instanceof SquaredEuclideanDistanceFunction)) {
- LOG.warning("k-means optimizes the sum of squares - it should be used with squared euclidean distance and may stop converging otherwise!");
- }
- }
-
- IntParameter kP = new IntParameter(K_ID);
- kP.addConstraint(new GreaterConstraint(0));
- if (config.grab(kP)) {
- k = kP.getValue();
- }
-
- ObjectParameter<KMeansInitialization<V>> initialP = new ObjectParameter<KMeansInitialization<V>>(INIT_ID, KMeansInitialization.class, RandomlyGeneratedInitialMeans.class);
- if (config.grab(initialP)) {
- initializer = initialP.instantiateClass(config);
- }
-
- IntParameter maxiterP = new IntParameter(MAXITER_ID, 0);
- maxiterP.addConstraint(new GreaterEqualConstraint(0));
- if (config.grab(maxiterP)) {
- maxiter = maxiterP.intValue();
- }
+ protected Logging getLogger() {
+ return LOG;
}
@Override
protected KMeansLloyd<V, D> makeInstance() {
- return new KMeansLloyd<V, D>(distanceFunction, k, maxiter, initializer);
+ return new KMeansLloyd<>(distanceFunction, k, maxiter, initializer);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeansMacQueen.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeansMacQueen.java
index 0cc7c363..bb689bd3 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeansMacQueen.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeansMacQueen.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,7 +26,6 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans;
import java.util.ArrayList;
import java.util.List;
-import de.lmu.ifi.dbs.elki.algorithm.AbstractPrimitiveDistanceBasedAlgorithm;
import de.lmu.ifi.dbs.elki.data.Cluster;
import de.lmu.ifi.dbs.elki.data.Clustering;
import de.lmu.ifi.dbs.elki.data.NumberVector;
@@ -37,20 +36,14 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.database.relation.RelationUtil;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.SquaredEuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.progress.IndefiniteProgress;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
import de.lmu.ifi.dbs.elki.utilities.documentation.Description;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterEqualConstraint;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
/**
* Provides the k-means algorithm, using MacQueen style incremental updates.
@@ -89,24 +82,18 @@ public class KMeansMacQueen<V extends NumberVector<?>, D extends Distance<D>> ex
super(distanceFunction, k, maxiter, initializer);
}
- /**
- * Run k-means.
- *
- * @param database Database
- * @param relation relation to use
- * @return Clustering result
- */
+ @Override
public Clustering<KMeansModel<V>> run(Database database, Relation<V> relation) {
if (relation.size() <= 0) {
- return new Clustering<KMeansModel<V>>("k-Means Clustering", "kmeans-clustering");
+ return new Clustering<>("k-Means Clustering", "kmeans-clustering");
}
// Choose initial means
- List<Vector> means = new ArrayList<Vector>(k);
- for (NumberVector<?> nv : initializer.chooseInitialMeans(relation, k, getDistanceFunction())) {
+ List<Vector> means = new ArrayList<>(k);
+ for (NumberVector<?> nv : initializer.chooseInitialMeans(database, relation, k, getDistanceFunction())) {
means.add(nv.getColumnVector());
}
// Initialize cluster and assign objects
- List<ModifiableDBIDs> clusters = new ArrayList<ModifiableDBIDs>();
+ List<ModifiableDBIDs> clusters = new ArrayList<>();
for (int i = 0; i < k; i++) {
clusters.add(DBIDUtil.newHashSet(relation.size() / k));
}
@@ -114,22 +101,27 @@ public class KMeansMacQueen<V extends NumberVector<?>, D extends Distance<D>> ex
// Initial recomputation of the means.
means = means(clusters, means, relation);
+ IndefiniteProgress prog = LOG.isVerbose() ? new IndefiniteProgress("K-Means iteration", LOG) : null;
// Refine result
for (int iteration = 0; maxiter <= 0 || iteration < maxiter; iteration++) {
- if (LOG.isVerbose()) {
- LOG.verbose("K-Means iteration " + (iteration + 1));
+ if (prog != null) {
+ prog.incrementProcessed(LOG);
}
boolean changed = macQueenIterate(relation, means, clusters);
if (!changed) {
break;
}
}
+ if (prog != null) {
+ prog.setCompleted(LOG);
+ }
+
final NumberVector.Factory<V, ?> factory = RelationUtil.getNumberVectorFactory(relation);
- Clustering<KMeansModel<V>> result = new Clustering<KMeansModel<V>>("k-Means Clustering", "kmeans-clustering");
+ Clustering<KMeansModel<V>> result = new Clustering<>("k-Means Clustering", "kmeans-clustering");
for (int i = 0; i < clusters.size(); i++) {
DBIDs ids = clusters.get(i);
- KMeansModel<V> model = new KMeansModel<V>(factory.newNumberVector(means.get(i).getArrayRef()));
- result.addCluster(new Cluster<KMeansModel<V>>(ids, model));
+ KMeansModel<V> model = new KMeansModel<>(factory.newNumberVector(means.get(i).getArrayRef()));
+ result.addToplevelCluster(new Cluster<>(ids, model));
}
return result;
}
@@ -146,53 +138,15 @@ public class KMeansMacQueen<V extends NumberVector<?>, D extends Distance<D>> ex
*
* @apiviz.exclude
*/
- public static class Parameterizer<V extends NumberVector<?>, D extends Distance<D>> extends AbstractPrimitiveDistanceBasedAlgorithm.Parameterizer<NumberVector<?>, D> {
- /**
- * k Parameter.
- */
- protected int k;
-
- /**
- * Maximum number of iterations.
- */
- protected int maxiter;
-
- /**
- * Initialization method.
- */
- protected KMeansInitialization<V> initializer;
-
+ public static class Parameterizer<V extends NumberVector<?>, D extends Distance<D>> extends AbstractKMeans.Parameterizer<V, D> {
@Override
- protected void makeOptions(Parameterization config) {
- ObjectParameter<PrimitiveDistanceFunction<NumberVector<?>, D>> distanceFunctionP = makeParameterDistanceFunction(SquaredEuclideanDistanceFunction.class, PrimitiveDistanceFunction.class);
- if (config.grab(distanceFunctionP)) {
- distanceFunction = distanceFunctionP.instantiateClass(config);
- if (!(distanceFunction instanceof EuclideanDistanceFunction) && !(distanceFunction instanceof SquaredEuclideanDistanceFunction)) {
- LOG.warning("k-means optimizes the sum of squares - it should be used with squared euclidean distance and may stop converging otherwise!");
- }
- }
-
- IntParameter kP = new IntParameter(K_ID);
- kP.addConstraint(new GreaterConstraint(0));
- if (config.grab(kP)) {
- k = kP.getValue();
- }
-
- ObjectParameter<KMeansInitialization<V>> initialP = new ObjectParameter<KMeansInitialization<V>>(INIT_ID, KMeansInitialization.class, RandomlyGeneratedInitialMeans.class);
- if (config.grab(initialP)) {
- initializer = initialP.instantiateClass(config);
- }
-
- IntParameter maxiterP = new IntParameter(MAXITER_ID, 0);
- maxiterP.addConstraint(new GreaterEqualConstraint(0));
- if (config.grab(maxiterP)) {
- maxiter = maxiterP.getValue();
- }
+ protected Logging getLogger() {
+ return LOG;
}
@Override
protected KMeansMacQueen<V, D> makeInstance() {
- return new KMeansMacQueen<V, D>(distanceFunction, k, maxiter, initializer);
+ return new KMeansMacQueen<>(distanceFunction, k, maxiter, initializer);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeansPlusPlusInitialMeans.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeansPlusPlusInitialMeans.java
index a07953da..302ca86b 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeansPlusPlusInitialMeans.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeansPlusPlusInitialMeans.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,6 +26,8 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Random;
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
@@ -70,17 +72,17 @@ public class KMeansPlusPlusInitialMeans<V, D extends NumberDistance<D, ?>> exten
}
@Override
- public List<V> chooseInitialMeans(Relation<V> relation, int k, PrimitiveDistanceFunction<? super V, ?> distanceFunction) {
+ public List<V> chooseInitialMeans(Database database, Relation<V> relation, int k, PrimitiveDistanceFunction<? super NumberVector<?>, ?> distanceFunction) {
// Get a distance query
if(!(distanceFunction.getDistanceFactory() instanceof NumberDistance)) {
throw new AbortException("K-Means++ initialization can only be used with numerical distances.");
}
@SuppressWarnings("unchecked")
final PrimitiveDistanceFunction<? super V, D> distF = (PrimitiveDistanceFunction<? super V, D>) distanceFunction;
- DistanceQuery<V, D> distQ = relation.getDatabase().getDistanceQuery(relation, distF);
+ DistanceQuery<V, D> distQ = database.getDistanceQuery(relation, distF);
// Chose first mean
- List<V> means = new ArrayList<V>(k);
+ List<V> means = new ArrayList<>(k);
Random random = rnd.getRandom();
DBID first = DBIDUtil.deref(DBIDUtil.randomSample(relation.getDBIDs(), 1, new Random(random.nextLong())).iter());
@@ -99,7 +101,7 @@ public class KMeansPlusPlusInitialMeans<V, D extends NumberDistance<D, ?>> exten
}
double r = random.nextDouble() * weightsum;
int pos = 0;
- while(r > 0 && pos < weights.length) {
+ while(r > 0 && pos < weights.length - 1) {
r -= weights[pos];
pos++;
}
@@ -125,7 +127,7 @@ public class KMeansPlusPlusInitialMeans<V, D extends NumberDistance<D, ?>> exten
@Override
public DBIDs chooseInitialMedoids(int k, DistanceQuery<? super V, ?> distQ2) {
if(!(distQ2.getDistanceFactory() instanceof NumberDistance)) {
- throw new AbortException("PAM initialization can only be used with numerical distances.");
+ throw new AbortException("K-Means++ initialization initialization can only be used with numerical distances.");
}
@SuppressWarnings("unchecked")
DistanceQuery<? super V, D> distQ = (DistanceQuery<? super V, D>) distQ2;
@@ -244,7 +246,7 @@ public class KMeansPlusPlusInitialMeans<V, D extends NumberDistance<D, ?>> exten
public static class Parameterizer<V, D extends NumberDistance<D, ?>> extends AbstractKMeansInitialization.Parameterizer<V> {
@Override
protected KMeansPlusPlusInitialMeans<V, D> makeInstance() {
- return new KMeansPlusPlusInitialMeans<V, D>(rnd);
+ return new KMeansPlusPlusInitialMeans<>(rnd);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMediansLloyd.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMediansLloyd.java
index 9917337e..cc7aaa9e 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMediansLloyd.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMediansLloyd.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,7 +26,6 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans;
import java.util.ArrayList;
import java.util.List;
-import de.lmu.ifi.dbs.elki.algorithm.AbstractPrimitiveDistanceBasedAlgorithm;
import de.lmu.ifi.dbs.elki.data.Cluster;
import de.lmu.ifi.dbs.elki.data.Clustering;
import de.lmu.ifi.dbs.elki.data.NumberVector;
@@ -39,13 +38,9 @@ import de.lmu.ifi.dbs.elki.database.relation.RelationUtil;
import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.progress.IndefiniteProgress;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterEqualConstraint;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
/**
* Provides the k-medians clustering algorithm, using Lloyd-style bulk
@@ -83,28 +78,23 @@ public class KMediansLloyd<V extends NumberVector<?>, D extends Distance<D>> ext
super(distanceFunction, k, maxiter, initializer);
}
- /**
- * Run k-medians.
- *
- * @param database Database
- * @param relation relation to use
- * @return result
- */
+ @Override
public Clustering<MeanModel<V>> run(Database database, Relation<V> relation) {
if (relation.size() <= 0) {
- return new Clustering<MeanModel<V>>("k-Medians Clustering", "kmedians-clustering");
+ return new Clustering<>("k-Medians Clustering", "kmedians-clustering");
}
// Choose initial medians
- List<? extends NumberVector<?>> medians = initializer.chooseInitialMeans(relation, k, getDistanceFunction());
+ List<? extends NumberVector<?>> medians = initializer.chooseInitialMeans(database, relation, k, getDistanceFunction());
// Setup cluster assignment store
- List<ModifiableDBIDs> clusters = new ArrayList<ModifiableDBIDs>();
+ List<ModifiableDBIDs> clusters = new ArrayList<>();
for (int i = 0; i < k; i++) {
clusters.add(DBIDUtil.newHashSet(relation.size() / k));
}
+ IndefiniteProgress prog = LOG.isVerbose() ? new IndefiniteProgress("K-Medians iteration", LOG) : null;
for (int iteration = 0; maxiter <= 0 || iteration < maxiter; iteration++) {
- if (LOG.isVerbose()) {
- LOG.verbose("K-Medians iteration " + (iteration + 1));
+ if (prog != null) {
+ prog.incrementProcessed(LOG);
}
boolean changed = assignToNearestCluster(relation, medians, clusters);
// Stop if no cluster assignment changed.
@@ -114,12 +104,15 @@ public class KMediansLloyd<V extends NumberVector<?>, D extends Distance<D>> ext
// Recompute medians.
medians = medians(clusters, medians, relation);
}
+ if (prog != null) {
+ prog.setCompleted(LOG);
+ }
// Wrap result
final NumberVector.Factory<V, ?> factory = RelationUtil.getNumberVectorFactory(relation);
- Clustering<MeanModel<V>> result = new Clustering<MeanModel<V>>("k-Medians Clustering", "kmedians-clustering");
+ Clustering<MeanModel<V>> result = new Clustering<>("k-Medians Clustering", "kmedians-clustering");
for (int i = 0; i < clusters.size(); i++) {
- MeanModel<V> model = new MeanModel<V>(factory.newNumberVector(medians.get(i).getColumnVector().getArrayRef()));
- result.addCluster(new Cluster<MeanModel<V>>(clusters.get(i), model));
+ MeanModel<V> model = new MeanModel<>(factory.newNumberVector(medians.get(i).getColumnVector().getArrayRef()));
+ result.addToplevelCluster(new Cluster<>(clusters.get(i), model));
}
return result;
}
@@ -136,46 +129,15 @@ public class KMediansLloyd<V extends NumberVector<?>, D extends Distance<D>> ext
*
* @apiviz.exclude
*/
- public static class Parameterizer<V extends NumberVector<?>, D extends Distance<D>> extends AbstractPrimitiveDistanceBasedAlgorithm.Parameterizer<NumberVector<?>, D> {
- /**
- * k Parameter.
- */
- protected int k;
-
- /**
- * Maximum number of iterations.
- */
- protected int maxiter;
-
- /**
- * Initialization method.
- */
- protected KMeansInitialization<V> initializer;
-
+ public static class Parameterizer<V extends NumberVector<?>, D extends Distance<D>> extends AbstractKMeans.Parameterizer<V, D> {
@Override
- protected void makeOptions(Parameterization config) {
- super.makeOptions(config);
- IntParameter kP = new IntParameter(K_ID);
- kP.addConstraint(new GreaterConstraint(0));
- if (config.grab(kP)) {
- k = kP.intValue();
- }
-
- ObjectParameter<KMeansInitialization<V>> initialP = new ObjectParameter<KMeansInitialization<V>>(INIT_ID, KMeansInitialization.class, RandomlyGeneratedInitialMeans.class);
- if (config.grab(initialP)) {
- initializer = initialP.instantiateClass(config);
- }
-
- IntParameter maxiterP = new IntParameter(MAXITER_ID, 0);
- maxiterP.addConstraint(new GreaterEqualConstraint(0));
- if (config.grab(maxiterP)) {
- maxiter = maxiterP.intValue();
- }
+ protected Logging getLogger() {
+ return LOG;
}
@Override
protected KMediansLloyd<V, D> makeInstance() {
- return new KMediansLloyd<V, D>(distanceFunction, k, maxiter, initializer);
+ return new KMediansLloyd<>(distanceFunction, k, maxiter, initializer);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMedoidsEM.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMedoidsEM.java
index f4398458..87a0c7ae 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMedoidsEM.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMedoidsEM.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -46,6 +46,7 @@ import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.progress.IndefiniteProgress;
import de.lmu.ifi.dbs.elki.math.Mean;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterEqualConstraint;
@@ -119,13 +120,13 @@ public class KMedoidsEM<V, D extends NumberDistance<D, ?>> extends AbstractDista
*/
public Clustering<MedoidModel> run(Database database, Relation<V> relation) {
if (relation.size() <= 0) {
- return new Clustering<MedoidModel>("k-Medoids Clustering", "kmedoids-clustering");
+ return new Clustering<>("k-Medoids Clustering", "kmedoids-clustering");
}
DistanceQuery<V, D> distQ = database.getDistanceQuery(relation, getDistanceFunction());
// Choose initial medoids
ArrayModifiableDBIDs medoids = DBIDUtil.newArray(initializer.chooseInitialMedoids(k, distQ));
// Setup cluster assignment store
- List<ModifiableDBIDs> clusters = new ArrayList<ModifiableDBIDs>();
+ List<ModifiableDBIDs> clusters = new ArrayList<>();
for (int i = 0; i < k; i++) {
clusters.add(DBIDUtil.newHashSet(relation.size() / k));
}
@@ -135,9 +136,13 @@ public class KMedoidsEM<V, D extends NumberDistance<D, ?>> extends AbstractDista
// TODO: reuse this information, from the build phase, when possible?
assignToNearestCluster(medoids, mdists, clusters, distQ);
+ IndefiniteProgress prog = LOG.isVerbose() ? new IndefiniteProgress("K-Medoids iteration", LOG) : null;
// Swap phase
boolean changed = true;
while (changed) {
+ if (prog != null) {
+ prog.incrementProcessed(LOG);
+ }
changed = false;
// Try to swap the medoid with a better cluster member:
int i = 0;
@@ -168,12 +173,15 @@ public class KMedoidsEM<V, D extends NumberDistance<D, ?>> extends AbstractDista
assignToNearestCluster(medoids, mdists, clusters, distQ);
}
}
+ if (prog != null) {
+ prog.setCompleted(LOG);
+ }
// Wrap result
- Clustering<MedoidModel> result = new Clustering<MedoidModel>("k-Medoids Clustering", "kmedoids-clustering");
+ Clustering<MedoidModel> result = new Clustering<>("k-Medoids Clustering", "kmedoids-clustering");
for (int i = 0; i < clusters.size(); i++) {
MedoidModel model = new MedoidModel(medoids.get(i));
- result.addCluster(new Cluster<MedoidModel>(clusters.get(i), model));
+ result.addToplevelCluster(new Cluster<>(clusters.get(i), model));
}
return result;
}
@@ -256,7 +264,7 @@ public class KMedoidsEM<V, D extends NumberDistance<D, ?>> extends AbstractDista
k = kP.intValue();
}
- ObjectParameter<KMedoidsInitialization<V>> initialP = new ObjectParameter<KMedoidsInitialization<V>>(KMeans.INIT_ID, KMedoidsInitialization.class, PAMInitialMeans.class);
+ ObjectParameter<KMedoidsInitialization<V>> initialP = new ObjectParameter<>(KMeans.INIT_ID, KMedoidsInitialization.class, PAMInitialMeans.class);
if (config.grab(initialP)) {
initializer = initialP.instantiateClass(config);
}
@@ -270,7 +278,7 @@ public class KMedoidsEM<V, D extends NumberDistance<D, ?>> extends AbstractDista
@Override
protected KMedoidsEM<V, D> makeInstance() {
- return new KMedoidsEM<V, D>(distanceFunction, k, maxiter, initializer);
+ return new KMedoidsEM<>(distanceFunction, k, maxiter, initializer);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMedoidsInitialization.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMedoidsInitialization.java
index 269e7e9e..136a4129 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMedoidsInitialization.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMedoidsInitialization.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMedoidsPAM.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMedoidsPAM.java
index 906501e4..1feda867 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMedoidsPAM.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMedoidsPAM.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -50,6 +50,7 @@ import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.progress.IndefiniteProgress;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
@@ -124,14 +125,14 @@ public class KMedoidsPAM<V, D extends NumberDistance<D, ?>> extends AbstractDist
*/
public Clustering<MedoidModel> run(Database database, Relation<V> relation) {
if (relation.size() <= 0) {
- return new Clustering<MedoidModel>("k-Medoids Clustering", "kmedoids-clustering");
+ return new Clustering<>("k-Medoids Clustering", "kmedoids-clustering");
}
DistanceQuery<V, D> distQ = database.getDistanceQuery(relation, getDistanceFunction());
DBIDs ids = relation.getDBIDs();
// Choose initial medoids
ArrayModifiableDBIDs medoids = DBIDUtil.newArray(initializer.chooseInitialMedoids(k, distQ));
// Setup cluster assignment store
- List<ModifiableDBIDs> clusters = new ArrayList<ModifiableDBIDs>();
+ List<ModifiableDBIDs> clusters = new ArrayList<>();
for (int i = 0; i < k; i++) {
clusters.add(DBIDUtil.newHashSet(relation.size() / k));
}
@@ -141,9 +142,13 @@ public class KMedoidsPAM<V, D extends NumberDistance<D, ?>> extends AbstractDist
// TODO: reuse this information, from the build phase, when possible?
assignToNearestCluster(medoids, ids, second, clusters, distQ);
+ IndefiniteProgress prog = LOG.isVerbose() ? new IndefiniteProgress("PAM iteration", LOG) : null;
// Swap phase
boolean changed = true;
while (changed) {
+ if (prog != null) {
+ prog.incrementProcessed(LOG);
+ }
changed = false;
// Try to swap the medoid with a better cluster member:
double best = 0;
@@ -189,6 +194,9 @@ public class KMedoidsPAM<V, D extends NumberDistance<D, ?>> extends AbstractDist
}
}
}
+ if (prog != null) {
+ prog.setCompleted(LOG);
+ }
if (LOG.isDebugging()) {
LOG.debug("Best cost: " + best);
}
@@ -204,10 +212,10 @@ public class KMedoidsPAM<V, D extends NumberDistance<D, ?>> extends AbstractDist
}
// Wrap result
- Clustering<MedoidModel> result = new Clustering<MedoidModel>("k-Medoids Clustering", "kmedoids-clustering");
+ Clustering<MedoidModel> result = new Clustering<>("k-Medoids Clustering", "kmedoids-clustering");
for (int i = 0; i < clusters.size(); i++) {
MedoidModel model = new MedoidModel(medoids.get(i));
- result.addCluster(new Cluster<MedoidModel>(clusters.get(i), model));
+ result.addToplevelCluster(new Cluster<>(clusters.get(i), model));
}
return result;
}
@@ -293,7 +301,7 @@ public class KMedoidsPAM<V, D extends NumberDistance<D, ?>> extends AbstractDist
k = kP.intValue();
}
- ObjectParameter<KMedoidsInitialization<V>> initialP = new ObjectParameter<KMedoidsInitialization<V>>(KMeans.INIT_ID, KMedoidsInitialization.class, PAMInitialMeans.class);
+ ObjectParameter<KMedoidsInitialization<V>> initialP = new ObjectParameter<>(KMeans.INIT_ID, KMedoidsInitialization.class, PAMInitialMeans.class);
if (config.grab(initialP)) {
initializer = initialP.instantiateClass(config);
}
@@ -307,7 +315,7 @@ public class KMedoidsPAM<V, D extends NumberDistance<D, ?>> extends AbstractDist
@Override
protected KMedoidsPAM<V, D> makeInstance() {
- return new KMedoidsPAM<V, D>(distanceFunction, k, maxiter, initializer);
+ return new KMedoidsPAM<>(distanceFunction, k, maxiter, initializer);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/PAMInitialMeans.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/PAMInitialMeans.java
index 1fc7160e..c7e1751f 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/PAMInitialMeans.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/PAMInitialMeans.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,6 +25,8 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans;
import java.util.ArrayList;
import java.util.List;
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
@@ -69,16 +71,16 @@ public class PAMInitialMeans<V, D extends NumberDistance<D, ?>> implements KMean
}
@Override
- public List<V> chooseInitialMeans(Relation<V> relation, int k, PrimitiveDistanceFunction<? super V, ?> distanceFunction) {
+ public List<V> chooseInitialMeans(Database database, Relation<V> relation, int k, PrimitiveDistanceFunction<? super NumberVector<?>, ?> distanceFunction) {
// Get a distance query
if(!(distanceFunction.getDistanceFactory() instanceof NumberDistance)) {
throw new AbortException("PAM initialization can only be used with numerical distances.");
}
@SuppressWarnings("unchecked")
final PrimitiveDistanceFunction<? super V, D> distF = (PrimitiveDistanceFunction<? super V, D>) distanceFunction;
- final DistanceQuery<V, D> distQ = relation.getDatabase().getDistanceQuery(relation, distF);
+ final DistanceQuery<V, D> distQ = database.getDistanceQuery(relation, distF);
DBIDs medids = chooseInitialMedoids(k, distQ);
- List<V> medoids = new ArrayList<V>(k);
+ List<V> medoids = new ArrayList<>(k);
for(DBIDIter iter = medids.iter(); iter.valid(); iter.advance()) {
medoids.add(relation.get(iter));
}
@@ -179,7 +181,7 @@ public class PAMInitialMeans<V, D extends NumberDistance<D, ?>> implements KMean
public static class Parameterizer<V, D extends NumberDistance<D, ?>> extends AbstractParameterizer {
@Override
protected PAMInitialMeans<V, D> makeInstance() {
- return new PAMInitialMeans<V, D>();
+ return new PAMInitialMeans<>();
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/RandomlyChosenInitialMeans.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/RandomlyChosenInitialMeans.java
index 78e59be7..214f4ce6 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/RandomlyChosenInitialMeans.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/RandomlyChosenInitialMeans.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,6 +25,8 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans;
import java.util.ArrayList;
import java.util.List;
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
@@ -52,9 +54,9 @@ public class RandomlyChosenInitialMeans<V> extends AbstractKMeansInitialization<
}
@Override
- public List<V> chooseInitialMeans(Relation<V> relation, int k, PrimitiveDistanceFunction<? super V, ?> distanceFunction) {
+ public List<V> chooseInitialMeans(Database database, Relation<V> relation, int k, PrimitiveDistanceFunction<? super NumberVector<?>, ?> distanceFunction) {
DBIDs ids = DBIDUtil.randomSample(relation.getDBIDs(), k, rnd);
- List<V> means = new ArrayList<V>(k);
+ List<V> means = new ArrayList<>(k);
for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
means.add(relation.get(iter));
}
@@ -74,10 +76,9 @@ public class RandomlyChosenInitialMeans<V> extends AbstractKMeansInitialization<
* @apiviz.exclude
*/
public static class Parameterizer<V> extends AbstractKMeansInitialization.Parameterizer<V> {
-
@Override
protected RandomlyChosenInitialMeans<V> makeInstance() {
- return new RandomlyChosenInitialMeans<V>(rnd);
+ return new RandomlyChosenInitialMeans<>(rnd);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/RandomlyGeneratedInitialMeans.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/RandomlyGeneratedInitialMeans.java
index 300f5cb0..ee90e0dc 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/RandomlyGeneratedInitialMeans.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/RandomlyGeneratedInitialMeans.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,6 +27,7 @@ import java.util.List;
import java.util.Random;
import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.database.relation.RelationUtil;
import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction;
@@ -54,11 +55,11 @@ public class RandomlyGeneratedInitialMeans<V extends NumberVector<?>> extends Ab
}
@Override
- public List<V> chooseInitialMeans(Relation<V> relation, int k, PrimitiveDistanceFunction<? super V, ?> distanceFunction) {
+ public List<V> chooseInitialMeans(Database database, Relation<V> relation, int k, PrimitiveDistanceFunction<? super NumberVector<?>, ?> distanceFunction) {
final int dim = RelationUtil.dimensionality(relation);
NumberVector.Factory<V, ?> factory = RelationUtil.getNumberVectorFactory(relation);
Pair<V, V> minmax = DatabaseUtil.computeMinMax(relation);
- List<V> means = new ArrayList<V>(k);
+ List<V> means = new ArrayList<>(k);
final Random random = rnd.getRandom();
for(int i = 0; i < k; i++) {
double[] r = MathUtil.randomDoubleArray(dim, random);
@@ -81,7 +82,7 @@ public class RandomlyGeneratedInitialMeans<V extends NumberVector<?>> extends Ab
public static class Parameterizer<V extends NumberVector<?>> extends AbstractKMeansInitialization.Parameterizer<V> {
@Override
protected RandomlyGeneratedInitialMeans<V> makeInstance() {
- return new RandomlyGeneratedInitialMeans<V>(rnd);
+ return new RandomlyGeneratedInitialMeans<>(rnd);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/SampleKMeansInitialization.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/SampleKMeansInitialization.java
new file mode 100644
index 00000000..9f0a1923
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/SampleKMeansInitialization.java
@@ -0,0 +1,160 @@
+package de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+import de.lmu.ifi.dbs.elki.data.Cluster;
+import de.lmu.ifi.dbs.elki.data.Clustering;
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.model.MeanModel;
+import de.lmu.ifi.dbs.elki.database.Database;
+import de.lmu.ifi.dbs.elki.database.ProxyDatabase;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.relation.ProxyView;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SquaredEuclideanDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.utilities.RandomFactory;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.ChainedParameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.ListParameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleParameter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
+
+/**
+ * Initialize k-means by running k-means on a sample of the data set only.
+ *
+ * @author Erich Schubert
+ *
+ * @param <V> Vector type
+ */
+public class SampleKMeansInitialization<V extends NumberVector<?>, D extends Distance<?>> extends AbstractKMeansInitialization<V> {
+ /**
+ * Variant of kMeans for the bisecting step.
+ */
+ private KMeans<V, D, ?> innerkMeans;
+
+ /**
+ * Sample size.
+ */
+ private double rate;
+
+ /**
+ * Constructor.
+ *
+ * @param rnd Random generator.
+ * @param innerkMeans Inner k-means algorithm.
+ * @param rate Sampling rate.
+ */
+ public SampleKMeansInitialization(RandomFactory rnd, KMeans<V, D, ?> innerkMeans, double rate) {
+ super(rnd);
+ this.innerkMeans = innerkMeans;
+ this.rate = rate;
+ }
+
+ @Override
+ public List<V> chooseInitialMeans(Database database, Relation<V> relation, int k, PrimitiveDistanceFunction<? super NumberVector<?>, ?> distanceFunction) {
+ final int samplesize = (int) Math.ceil(rate * relation.size());
+ final DBIDs sample = DBIDUtil.randomSample(relation.getDBIDs(), samplesize, rnd);
+
+ ProxyView<V> proxyv = new ProxyView<>(database, sample, relation);
+ ProxyDatabase proxydb = new ProxyDatabase(sample, proxyv);
+
+ innerkMeans.setK(k);
+ @SuppressWarnings("unchecked")
+ PrimitiveDistanceFunction<? super NumberVector<?>, D> df = (PrimitiveDistanceFunction<? super NumberVector<?>, D>) distanceFunction;
+ innerkMeans.setDistanceFunction(df);
+ Clustering<? extends MeanModel<V>> clusters = innerkMeans.run(proxydb, proxyv);
+ List<V> means = new ArrayList<>();
+ for (Cluster<? extends MeanModel<V>> cluster : clusters.getAllClusters()) {
+ means.add((V) cluster.getModel().getMean());
+ }
+
+ return means;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ *
+ * @param <V> Vector type
+ * @param <D> Distance type
+ */
+ public static class Parameterizer<V extends NumberVector<?>, D extends Distance<?>> extends AbstractKMeansInitialization.Parameterizer<V> {
+ /**
+ * Parameter to specify the kMeans variant.
+ */
+ public static final OptionID KMEANS_ID = new OptionID("kmeans.algorithm", "KMeans variant to run multiple times.");
+
+ /**
+ * Parameter to specify the sampling rate.
+ */
+ public static final OptionID SAMPLE_ID = new OptionID("kmeans.samplesize", "Sample set size (if > 1) or sampling rante (if < 1).");
+
+ /**
+ * Inner k-means algorithm to use.
+ */
+ protected KMeans<V, D, ?> innerkMeans;
+
+ /**
+ * Sampling rate.
+ */
+ protected double rate;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ ObjectParameter<KMeans<V, D, ?>> kMeansVariantP = new ObjectParameter<>(KMEANS_ID, KMeans.class);
+ if (config.grab(kMeansVariantP)) {
+ ListParameterization kMeansVariantParameters = new ListParameterization();
+
+ // We will always invoke this with k as requested from outside!
+ kMeansVariantParameters.addParameter(KMeans.K_ID, 13);
+ kMeansVariantParameters.addParameter(KMeans.DISTANCE_FUNCTION_ID, SquaredEuclideanDistanceFunction.class);
+
+ ChainedParameterization combinedConfig = new ChainedParameterization(kMeansVariantParameters, config);
+ combinedConfig.errorsTo(config);
+ innerkMeans = kMeansVariantP.instantiateClass(combinedConfig);
+ }
+
+ DoubleParameter sampleP = new DoubleParameter(SAMPLE_ID);
+ if (config.grab(sampleP)) {
+ rate = sampleP.doubleValue();
+ }
+ }
+
+ @Override
+ protected SampleKMeansInitialization<V, D> makeInstance() {
+ return new SampleKMeansInitialization<>(rnd, innerkMeans, rate);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/package-info.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/package-info.java
index 2ce625b0..aa4c3e24 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/quality/KMeansQualityMeasure.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/quality/KMeansQualityMeasure.java
new file mode 100644
index 00000000..f2de7846
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/quality/KMeansQualityMeasure.java
@@ -0,0 +1,54 @@
+package de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.quality;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.data.Clustering;
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.model.MeanModel;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+
+/**
+ * Interface for computing the quality of a K-Means clustering.
+ *
+ * @author Erich Schubert
+ *
+ * @param <O> Input Object restriction type
+ * @param <D> Distance restriction type
+ */
+public interface KMeansQualityMeasure<O extends NumberVector<?>, D extends Distance<?>> {
+ /**
+ * Calculates and returns the quality measure.
+ *
+ * @param clustering Clustering to analyze
+ * @param distanceFunction Distance function to use (usually Euclidean or
+ * squared Euclidean!)
+ * @param relation Relation for accessing objects
+ * @param <V> Actual vector type (could be a subtype of O!)
+ *
+ * @return quality measure
+ */
+ <V extends O> double calculateCost(Clustering<? extends MeanModel<V>> clustering, PrimitiveDistanceFunction<? super V, ? extends D> distanceFunction, Relation<V> relation);
+}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/quality/WithinClusterMeanDistanceQualityMeasure.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/quality/WithinClusterMeanDistanceQualityMeasure.java
new file mode 100644
index 00000000..e0ddfff0
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/quality/WithinClusterMeanDistanceQualityMeasure.java
@@ -0,0 +1,89 @@
+package de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.quality;
+
+/*
+ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.List;
+
+import de.lmu.ifi.dbs.elki.data.Cluster;
+import de.lmu.ifi.dbs.elki.data.Clustering;
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.model.MeanModel;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
+
+/**
+ * Class for computing the average overall distance.
+ *
+ * The average of all average pairwise distances in a cluster.
+ *
+ * @author Stephan Baier
+ */
+public class WithinClusterMeanDistanceQualityMeasure implements KMeansQualityMeasure<NumberVector<?>, NumberDistance<?, ?>> {
+ @Override
+ public <V extends NumberVector<?>> double calculateCost(Clustering<? extends MeanModel<V>> clustering, PrimitiveDistanceFunction<? super V, ? extends NumberDistance<?, ?>> distanceFunction, Relation<V> relation) {
+ @SuppressWarnings("unchecked")
+ final List<Cluster<MeanModel<V>>> clusterList = (List<Cluster<MeanModel<V>>>) (List<?>) clustering.getAllClusters();
+
+ if (distanceFunction instanceof PrimitiveDoubleDistanceFunction) {
+ @SuppressWarnings("unchecked")
+ PrimitiveDoubleDistanceFunction<? super V> df = (PrimitiveDoubleDistanceFunction<? super V>) distanceFunction;
+ double clusterDistanceSum = 0;
+ for (Cluster<MeanModel<V>> cluster : clusterList) {
+ DBIDs ids = cluster.getIDs();
+
+ // Compute sum of pairwise distances:
+ double clusterPairwiseDistanceSum = 0;
+ for (DBIDIter iter1 = ids.iter(); iter1.valid(); iter1.advance()) {
+ V obj1 = relation.get(iter1);
+ for (DBIDIter iter2 = ids.iter(); iter2.valid(); iter2.advance()) {
+ clusterPairwiseDistanceSum += df.doubleDistance(obj1, relation.get(iter2));
+ }
+ }
+ clusterDistanceSum += clusterPairwiseDistanceSum / (ids.size() * ids.size());
+ }
+
+ return clusterDistanceSum / clusterList.size();
+ } else {
+ double clusterDistanceSum = 0;
+ for (Cluster<MeanModel<V>> cluster : clusterList) {
+ DBIDs ids = cluster.getIDs();
+
+ // Compute sum of pairwise distances:
+ double clusterPairwiseDistanceSum = 0;
+ for (DBIDIter iter1 = ids.iter(); iter1.valid(); iter1.advance()) {
+ V obj1 = relation.get(iter1);
+ for (DBIDIter iter2 = ids.iter(); iter2.valid(); iter2.advance()) {
+ clusterPairwiseDistanceSum += distanceFunction.distance(obj1, relation.get(iter2)).doubleValue();
+ }
+ }
+ clusterDistanceSum += clusterPairwiseDistanceSum / (ids.size() * ids.size());
+ }
+
+ return clusterDistanceSum / clusterList.size();
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/quality/WithinClusterVarianceQualityMeasure.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/quality/WithinClusterVarianceQualityMeasure.java
new file mode 100644
index 00000000..32ad5210
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/quality/WithinClusterVarianceQualityMeasure.java
@@ -0,0 +1,83 @@
+package de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.quality;
+
+/*
+ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.List;
+
+import de.lmu.ifi.dbs.elki.data.Cluster;
+import de.lmu.ifi.dbs.elki.data.Clustering;
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.model.MeanModel;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SquaredEuclideanDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
+
+/**
+ * Class for computing the variance in a clustering result (sum-of-squares).
+ *
+ * @author Stephan Baier
+ */
+public class WithinClusterVarianceQualityMeasure implements KMeansQualityMeasure<NumberVector<?>, NumberDistance<?, ?>> {
+ @Override
+ public <V extends NumberVector<?>> double calculateCost(Clustering<? extends MeanModel<V>> clustering, PrimitiveDistanceFunction<? super V, ? extends NumberDistance<?, ?>> distanceFunction, Relation<V> relation) {
+ @SuppressWarnings("unchecked")
+ final List<Cluster<MeanModel<V>>> clusterList = (List<Cluster<MeanModel<V>>>) (List<?>) clustering.getAllClusters();
+
+ boolean squared = (distanceFunction instanceof SquaredEuclideanDistanceFunction);
+ if (distanceFunction instanceof PrimitiveDoubleDistanceFunction) {
+ @SuppressWarnings("unchecked")
+ PrimitiveDoubleDistanceFunction<? super V> df = (PrimitiveDoubleDistanceFunction<? super V>) distanceFunction;
+ double variance = 0.0;
+ for (Cluster<MeanModel<V>> cluster : clusterList) {
+ DBIDs ids = cluster.getIDs();
+ V mean = cluster.getModel().getMean();
+
+ for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
+ double dist = df.doubleDistance(relation.get(iter), mean);
+ if (squared) {
+ variance += dist;
+ } else {
+ variance += dist * dist;
+ }
+ }
+ }
+ return variance;
+ } else {
+ double variance = 0.0;
+ for (Cluster<MeanModel<V>> cluster : clusterList) {
+ DBIDs ids = cluster.getIDs();
+ V mean = cluster.getModel().getMean();
+
+ for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
+ double dist = distanceFunction.distance(relation.get(iter), mean).doubleValue();
+ variance += dist * dist;
+ }
+ }
+ return variance;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/quality/package-info.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/quality/package-info.java
new file mode 100644
index 00000000..ed9a528d
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/quality/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Quality measures for k-Means results.
+ */
+package de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.quality; \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/package-info.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/package-info.java
index 4ba1ce09..26fb3024 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/package-info.java
@@ -19,7 +19,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/CLIQUE.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/CLIQUE.java
index 37b3eb57..db026e93 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/CLIQUE.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/CLIQUE.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.subspace;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -172,7 +172,7 @@ public class CLIQUE<V extends NumberVector<?>> extends AbstractAlgorithm<Cluster
if(LOG.isVerbose()) {
LOG.verbose("*** 1. Identification of subspaces that contain clusters ***");
}
- SortedMap<Integer, List<CLIQUESubspace<V>>> dimensionToDenseSubspaces = new TreeMap<Integer, List<CLIQUESubspace<V>>>();
+ SortedMap<Integer, List<CLIQUESubspace<V>>> dimensionToDenseSubspaces = new TreeMap<>();
List<CLIQUESubspace<V>> denseSubspaces = findOneDimensionalDenseSubspaces(relation);
dimensionToDenseSubspaces.put(Integer.valueOf(0), denseSubspaces);
if(LOG.isVerbose()) {
@@ -204,7 +204,7 @@ public class CLIQUE<V extends NumberVector<?>> extends AbstractAlgorithm<Cluster
}
// build result
int numClusters = 1;
- Clustering<SubspaceModel<V>> result = new Clustering<SubspaceModel<V>>("CLIQUE clustering", "clique-clustering");
+ Clustering<SubspaceModel<V>> result = new Clustering<>("CLIQUE clustering", "clique-clustering");
for(Integer dim : dimensionToDenseSubspaces.keySet()) {
List<CLIQUESubspace<V>> subspaces = dimensionToDenseSubspaces.get(dim);
List<Pair<Subspace, ModifiableDBIDs>> modelsAndClusters = determineClusters(subspaces);
@@ -214,10 +214,10 @@ public class CLIQUE<V extends NumberVector<?>> extends AbstractAlgorithm<Cluster
}
for(Pair<Subspace, ModifiableDBIDs> modelAndCluster : modelsAndClusters) {
- Cluster<SubspaceModel<V>> newCluster = new Cluster<SubspaceModel<V>>(modelAndCluster.second);
- newCluster.setModel(new SubspaceModel<V>(modelAndCluster.first, Centroid.make(relation, modelAndCluster.second).toVector(relation)));
+ Cluster<SubspaceModel<V>> newCluster = new Cluster<>(modelAndCluster.second);
+ newCluster.setModel(new SubspaceModel<>(modelAndCluster.first, Centroid.make(relation, modelAndCluster.second).toVector(relation)));
newCluster.setName("cluster_" + numClusters++);
- result.addCluster(newCluster);
+ result.addToplevelCluster(newCluster);
}
}
@@ -233,7 +233,7 @@ public class CLIQUE<V extends NumberVector<?>> extends AbstractAlgorithm<Cluster
* cluster models
*/
private List<Pair<Subspace, ModifiableDBIDs>> determineClusters(List<CLIQUESubspace<V>> denseSubspaces) {
- List<Pair<Subspace, ModifiableDBIDs>> clusters = new ArrayList<Pair<Subspace, ModifiableDBIDs>>();
+ List<Pair<Subspace, ModifiableDBIDs>> clusters = new ArrayList<>();
for(CLIQUESubspace<V> subspace : denseSubspaces) {
List<Pair<Subspace, ModifiableDBIDs>> clustersInSubspace = subspace.determineClusters();
@@ -339,7 +339,7 @@ public class CLIQUE<V extends NumberVector<?>> extends AbstractAlgorithm<Cluster
}
// build the 1 dimensional units
- List<CLIQUEUnit<V>> units = new ArrayList<CLIQUEUnit<V>>((xsi * dimensionality));
+ List<CLIQUEUnit<V>> units = new ArrayList<>((xsi * dimensionality));
for(int x = 0; x < xsi; x++) {
for(int d = 0; d < dimensionality; d++) {
units.add(new CLIQUEUnit<V>(new Interval(d, unit_bounds[x][d], unit_bounds[x + 1][d])));
@@ -396,8 +396,8 @@ public class CLIQUE<V extends NumberVector<?>> extends AbstractAlgorithm<Cluster
}
}
- Collection<CLIQUEUnit<V>> denseUnits = new ArrayList<CLIQUEUnit<V>>();
- Map<Integer, CLIQUESubspace<V>> denseSubspaces = new HashMap<Integer, CLIQUESubspace<V>>();
+ Collection<CLIQUEUnit<V>> denseUnits = new ArrayList<>();
+ Map<Integer, CLIQUESubspace<V>> denseSubspaces = new HashMap<>();
for(CLIQUEUnit<V> unit : units) {
// unit is a dense unit
if(unit.selectivity(total) >= tau) {
@@ -406,7 +406,7 @@ public class CLIQUE<V extends NumberVector<?>> extends AbstractAlgorithm<Cluster
int dim = unit.getIntervals().iterator().next().getDimension();
CLIQUESubspace<V> subspace_d = denseSubspaces.get(Integer.valueOf(dim));
if(subspace_d == null) {
- subspace_d = new CLIQUESubspace<V>(dim);
+ subspace_d = new CLIQUESubspace<>(dim);
denseSubspaces.put(Integer.valueOf(dim), subspace_d);
}
subspace_d.addDenseUnit(unit);
@@ -420,7 +420,7 @@ public class CLIQUE<V extends NumberVector<?>> extends AbstractAlgorithm<Cluster
LOG.debugFine(msg.toString());
}
- List<CLIQUESubspace<V>> subspaceCandidates = new ArrayList<CLIQUESubspace<V>>(denseSubspaces.values());
+ List<CLIQUESubspace<V>> subspaceCandidates = new ArrayList<>(denseSubspaces.values());
Collections.sort(subspaceCandidates, new CLIQUESubspace.CoverageComparator());
return subspaceCandidates;
}
@@ -436,12 +436,12 @@ public class CLIQUE<V extends NumberVector<?>> extends AbstractAlgorithm<Cluster
*/
private List<CLIQUESubspace<V>> findDenseSubspaceCandidates(Relation<V> database, List<CLIQUESubspace<V>> denseSubspaces) {
// sort (k-1)-dimensional dense subspace according to their dimensions
- List<CLIQUESubspace<V>> denseSubspacesByDimensions = new ArrayList<CLIQUESubspace<V>>(denseSubspaces);
+ List<CLIQUESubspace<V>> denseSubspacesByDimensions = new ArrayList<>(denseSubspaces);
Collections.sort(denseSubspacesByDimensions, new Subspace.DimensionComparator());
// determine k-dimensional dense subspace candidates
double all = database.size();
- List<CLIQUESubspace<V>> denseSubspaceCandidates = new ArrayList<CLIQUESubspace<V>>();
+ List<CLIQUESubspace<V>> denseSubspaceCandidates = new ArrayList<>();
while(!denseSubspacesByDimensions.isEmpty()) {
CLIQUESubspace<V> s1 = denseSubspacesByDimensions.remove(0);
@@ -614,7 +614,7 @@ public class CLIQUE<V extends NumberVector<?>> extends AbstractAlgorithm<Cluster
@Override
protected CLIQUE<V> makeInstance() {
- return new CLIQUE<V>(xsi, tau, prune);
+ return new CLIQUE<>(xsi, tau, prune);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/DiSH.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/DiSH.java
index a3496a0e..b17ebebb 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/DiSH.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/DiSH.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.subspace;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -62,7 +62,8 @@ import de.lmu.ifi.dbs.elki.result.optics.ClusterOrderEntry;
import de.lmu.ifi.dbs.elki.result.optics.ClusterOrderResult;
import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
import de.lmu.ifi.dbs.elki.utilities.FormatUtil;
-import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.HierarchyReferenceLists;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.Hierarchy;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.Hierarchy.Iter;
import de.lmu.ifi.dbs.elki.utilities.documentation.Description;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
@@ -238,29 +239,29 @@ public class DiSH<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
}
// build the hierarchy
- buildHierarchy(database, distFunc, clusters, dimensionality);
+ Clustering<SubspaceModel<V>> clustering = new Clustering<>("DiSH clustering", "dish-clustering");
+ buildHierarchy(database, distFunc, clustering, clusters, dimensionality);
if (LOG.isVerbose()) {
StringBuilder msg = new StringBuilder("Step 4: build hierarchy");
for (Cluster<SubspaceModel<V>> c : clusters) {
msg.append('\n').append(FormatUtil.format(dimensionality, c.getModel().getDimensions())).append(" ids ").append(c.size());
- for (Cluster<SubspaceModel<V>> cluster : c.getParents()) {
- msg.append("\n parent ").append(cluster);
+ for (Iter<Cluster<SubspaceModel<V>>> iter = clustering.getClusterHierarchy().iterParents(c); iter.valid(); iter.advance()) {
+ msg.append("\n parent ").append(iter.get());
}
- for (Cluster<SubspaceModel<V>> cluster : c.getChildren()) {
- msg.append("\n child ").append(cluster);
+ for (Iter<Cluster<SubspaceModel<V>>> iter = clustering.getClusterHierarchy().iterChildren(c); iter.valid(); iter.advance()) {
+ msg.append("\n child ").append(iter.get());
}
}
LOG.verbose(msg.toString());
}
// build result
- Clustering<SubspaceModel<V>> result = new Clustering<SubspaceModel<V>>("DiSH clustering", "dish-clustering");
for (Cluster<SubspaceModel<V>> c : clusters) {
- if (c.getParents() == null || c.getParents().isEmpty()) {
- result.addCluster(c);
+ if (clustering.getClusterHierarchy().numParents(c) == 0) {
+ clustering.addToplevelCluster(c);
}
}
- return result;
+ return clustering;
}
/**
@@ -274,9 +275,9 @@ public class DiSH<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
private Map<BitSet, List<Pair<BitSet, ArrayModifiableDBIDs>>> extractClusters(Relation<V> database, DiSHDistanceFunction.Instance<V> distFunc, ClusterOrderResult<PreferenceVectorBasedCorrelationDistance> clusterOrder) {
FiniteProgress progress = LOG.isVerbose() ? new FiniteProgress("Extract Clusters", database.size(), LOG) : null;
int processed = 0;
- Map<BitSet, List<Pair<BitSet, ArrayModifiableDBIDs>>> clustersMap = new HashMap<BitSet, List<Pair<BitSet, ArrayModifiableDBIDs>>>();
- Map<DBID, ClusterOrderEntry<PreferenceVectorBasedCorrelationDistance>> entryMap = new HashMap<DBID, ClusterOrderEntry<PreferenceVectorBasedCorrelationDistance>>();
- Map<DBID, Pair<BitSet, ArrayModifiableDBIDs>> entryToClusterMap = new HashMap<DBID, Pair<BitSet, ArrayModifiableDBIDs>>();
+ Map<BitSet, List<Pair<BitSet, ArrayModifiableDBIDs>>> clustersMap = new HashMap<>();
+ Map<DBID, ClusterOrderEntry<PreferenceVectorBasedCorrelationDistance>> entryMap = new HashMap<>();
+ Map<DBID, Pair<BitSet, ArrayModifiableDBIDs>> entryToClusterMap = new HashMap<>();
for (Iterator<ClusterOrderEntry<PreferenceVectorBasedCorrelationDistance>> it = clusterOrder.iterator(); it.hasNext();) {
ClusterOrderEntry<PreferenceVectorBasedCorrelationDistance> entry = it.next();
entryMap.put(entry.getID(), entry);
@@ -287,7 +288,7 @@ public class DiSH<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
// get the list of (parallel) clusters for the preference vector
List<Pair<BitSet, ArrayModifiableDBIDs>> parallelClusters = clustersMap.get(preferenceVector);
if (parallelClusters == null) {
- parallelClusters = new ArrayList<Pair<BitSet, ArrayModifiableDBIDs>>();
+ parallelClusters = new ArrayList<>();
clustersMap.put(preferenceVector, parallelClusters);
}
@@ -305,7 +306,7 @@ public class DiSH<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
}
}
if (cluster == null) {
- cluster = new Pair<BitSet, ArrayModifiableDBIDs>(preferenceVector, DBIDUtil.newArray());
+ cluster = new Pair<>(preferenceVector, DBIDUtil.newArray());
parallelClusters.add(cluster);
}
cluster.second.add(entry.getID());
@@ -373,15 +374,13 @@ public class DiSH<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
private List<Cluster<SubspaceModel<V>>> sortClusters(Relation<V> database, Map<BitSet, List<Pair<BitSet, ArrayModifiableDBIDs>>> clustersMap) {
final int db_dim = RelationUtil.dimensionality(database);
// int num = 1;
- List<Cluster<SubspaceModel<V>>> clusters = new ArrayList<Cluster<SubspaceModel<V>>>();
+ List<Cluster<SubspaceModel<V>>> clusters = new ArrayList<>();
for (BitSet pv : clustersMap.keySet()) {
List<Pair<BitSet, ArrayModifiableDBIDs>> parallelClusters = clustersMap.get(pv);
for (int i = 0; i < parallelClusters.size(); i++) {
Pair<BitSet, ArrayModifiableDBIDs> c = parallelClusters.get(i);
- Cluster<SubspaceModel<V>> cluster = new Cluster<SubspaceModel<V>>(c.second);
- cluster.setModel(new SubspaceModel<V>(new Subspace(c.first), Centroid.make(database, c.second).toVector(database)));
- cluster.setHierarchy(new HierarchyReferenceLists<Cluster<SubspaceModel<V>>>(cluster, new ArrayList<Cluster<SubspaceModel<V>>>(), new ArrayList<Cluster<SubspaceModel<V>>>()));
- // cluster.setName("Cluster_" + num++);
+ Cluster<SubspaceModel<V>> cluster = new Cluster<>(c.second);
+ cluster.setModel(new SubspaceModel<>(new Subspace(c.first), Centroid.make(database, c.second).toVector(database)));
String subspace = FormatUtil.format(cluster.getModel().getSubspace().getDimensions(), db_dim, "");
if (parallelClusters.size() > 1) {
cluster.setName("Cluster_" + subspace + "_" + i);
@@ -415,9 +414,9 @@ public class DiSH<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
private void checkClusters(Relation<V> database, DiSHDistanceFunction.Instance<V> distFunc, Map<BitSet, List<Pair<BitSet, ArrayModifiableDBIDs>>> clustersMap, int minpts) {
// check if there are clusters < minpts
// and add them to not assigned
- List<Pair<BitSet, ArrayModifiableDBIDs>> notAssigned = new ArrayList<Pair<BitSet, ArrayModifiableDBIDs>>();
- Map<BitSet, List<Pair<BitSet, ArrayModifiableDBIDs>>> newClustersMap = new HashMap<BitSet, List<Pair<BitSet, ArrayModifiableDBIDs>>>();
- Pair<BitSet, ArrayModifiableDBIDs> noise = new Pair<BitSet, ArrayModifiableDBIDs>(new BitSet(), DBIDUtil.newArray());
+ List<Pair<BitSet, ArrayModifiableDBIDs>> notAssigned = new ArrayList<>();
+ Map<BitSet, List<Pair<BitSet, ArrayModifiableDBIDs>>> newClustersMap = new HashMap<>();
+ Pair<BitSet, ArrayModifiableDBIDs> noise = new Pair<>(new BitSet(), DBIDUtil.newArray());
for (BitSet pv : clustersMap.keySet()) {
// noise
if (pv.cardinality() == 0) {
@@ -429,7 +428,7 @@ public class DiSH<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
// clusters
else {
List<Pair<BitSet, ArrayModifiableDBIDs>> parallelClusters = clustersMap.get(pv);
- List<Pair<BitSet, ArrayModifiableDBIDs>> newParallelClusters = new ArrayList<Pair<BitSet, ArrayModifiableDBIDs>>(parallelClusters.size());
+ List<Pair<BitSet, ArrayModifiableDBIDs>> newParallelClusters = new ArrayList<>(parallelClusters.size());
for (Pair<BitSet, ArrayModifiableDBIDs> c : parallelClusters) {
if (!pv.equals(new BitSet()) && c.second.size() < minpts) {
notAssigned.add(c);
@@ -456,7 +455,7 @@ public class DiSH<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
}
}
- List<Pair<BitSet, ArrayModifiableDBIDs>> noiseList = new ArrayList<Pair<BitSet, ArrayModifiableDBIDs>>(1);
+ List<Pair<BitSet, ArrayModifiableDBIDs>> noiseList = new ArrayList<>(1);
noiseList.add(noise);
clustersMap.put(noise.first, noiseList);
}
@@ -510,13 +509,15 @@ public class DiSH<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
* Builds the cluster hierarchy.
*
* @param distFunc the distance function
+ * @param clustering Clustering we process
* @param clusters the sorted list of clusters
* @param dimensionality the dimensionality of the data
* @param database the database containing the data objects
*/
- private void buildHierarchy(Relation<V> database, DiSHDistanceFunction.Instance<V> distFunc, List<Cluster<SubspaceModel<V>>> clusters, int dimensionality) {
+ private void buildHierarchy(Relation<V> database, DiSHDistanceFunction.Instance<V> distFunc, Clustering<SubspaceModel<V>> clustering, List<Cluster<SubspaceModel<V>>> clusters, int dimensionality) {
StringBuilder msg = new StringBuilder();
final int db_dim = RelationUtil.dimensionality(database);
+ Hierarchy<Cluster<SubspaceModel<V>>> hier = clustering.getClusterHierarchy();
for (int i = 0; i < clusters.size() - 1; i++) {
Cluster<SubspaceModel<V>> c_i = clusters.get(i);
@@ -536,9 +537,8 @@ public class DiSH<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
// noise level reached
if (c_j.getModel().getSubspace().dimensionality() == 0) {
// no parents exists -> parent is noise
- if (c_i.getParents().isEmpty()) {
- c_j.getChildren().add(c_i);
- c_i.getParents().add(c_j);
+ if (hier.numParents(c_i) == 0) {
+ clustering.addChildCluster(c_j, c_i);
if (LOG.isDebugging()) {
msg.append("\n [").append(FormatUtil.format(db_dim, c_j.getModel().getSubspace().getDimensions()));
msg.append("] is parent of [").append(FormatUtil.format(db_dim, c_i.getModel().getSubspace().getDimensions()));
@@ -560,9 +560,8 @@ public class DiSH<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
if (d <= 2 * epsilon) {
// no parent exists or c_j is not a parent of the already
// existing parents
- if (c_i.getParents().isEmpty() || !isParent(database, distFunc, c_j, c_i.getParents())) {
- c_j.getChildren().add(c_i);
- c_i.getParents().add(c_j);
+ if (hier.numParents(c_i) == 0 || !isParent(database, distFunc, c_j, hier.iterParents(c_i))) {
+ clustering.addChildCluster(c_j, c_i);
if (LOG.isDebugging()) {
msg.append("\n [").append(FormatUtil.format(db_dim, c_j.getModel().getSubspace().getDimensions()));
msg.append("] is parent of [");
@@ -591,16 +590,17 @@ public class DiSH<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
* @param distFunc the distance function for distance computation between the
* clusters
* @param parent the parent to be tested
- * @param children the list of children to be tested
+ * @param iter the list of children to be tested
* @return true, if the specified parent cluster is a parent of one child of
* the children clusters, false otherwise
*/
- private boolean isParent(Relation<V> database, DiSHDistanceFunction.Instance<V> distFunc, Cluster<SubspaceModel<V>> parent, List<Cluster<SubspaceModel<V>>> children) {
+ private boolean isParent(Relation<V> database, DiSHDistanceFunction.Instance<V> distFunc, Cluster<SubspaceModel<V>> parent, Iter<Cluster<SubspaceModel<V>>> iter) {
V parent_centroid = ProjectedCentroid.make(parent.getModel().getDimensions(), database, parent.getIDs()).toVector(database);
int dimensionality = RelationUtil.dimensionality(database);
int subspaceDim_parent = dimensionality - parent.getModel().getSubspace().dimensionality();
- for (Cluster<SubspaceModel<V>> child : children) {
+ for (; iter.valid(); iter.advance()) {
+ Cluster<SubspaceModel<V>> child = iter.get();
V child_centroid = ProjectedCentroid.make(child.getModel().getDimensions(), database, child.getIDs()).toVector(database);
PreferenceVectorBasedCorrelationDistance distance = distFunc.correlationDistance(parent_centroid, child_centroid, parent.getModel().getSubspace().getDimensions(), child.getModel().getSubspace().getDimensions());
if (distance.getCorrelationValue() == subspaceDim_parent) {
@@ -699,7 +699,7 @@ public class DiSH<V extends NumberVector<?>> extends AbstractAlgorithm<Clusterin
@Override
protected DiSH<V> makeInstance() {
- return new DiSH<V>(epsilon, dishDistance, opticsO);
+ return new DiSH<>(epsilon, dishDistance, opticsO);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/HiSC.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/HiSC.java
index 58f3acef..9ac7c072 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/HiSC.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/HiSC.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.subspace;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -119,7 +119,7 @@ public class HiSC<V extends NumberVector<?>> extends OPTICS<V, PreferenceVectorB
@Override
protected HiSC<V> makeInstance() {
- return new HiSC<V>(distanceFunction);
+ return new HiSC<>(distanceFunction);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/PROCLUS.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/PROCLUS.java
index ef49ff10..92158734 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/PROCLUS.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/PROCLUS.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.subspace;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -49,13 +49,13 @@ import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
-import de.lmu.ifi.dbs.elki.database.ids.DistanceDBIDPair;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDPair;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.database.relation.RelationUtil;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultUtil;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.logging.Logging;
@@ -150,13 +150,13 @@ public class PROCLUS<V extends NumberVector<?>> extends AbstractProjectedCluster
RangeQuery<V, DoubleDistance> rangeQuery = database.getRangeQuery(distFunc);
final Random random = rnd.getRandom();
- if(RelationUtil.dimensionality(relation) < l) {
+ if (RelationUtil.dimensionality(relation) < l) {
throw new IllegalStateException("Dimensionality of data < parameter l! " + "(" + RelationUtil.dimensionality(relation) + " < " + l + ")");
}
// TODO: use a StepProgress!
// initialization phase
- if(LOG.isVerbose()) {
+ if (LOG.isVerbose()) {
LOG.verbose("1. Initialization phase...");
}
int sampleSize = Math.min(relation.size(), k_i * k);
@@ -165,7 +165,7 @@ public class PROCLUS<V extends NumberVector<?>> extends AbstractProjectedCluster
int medoidSize = Math.min(relation.size(), m_i * k);
DBIDs medoids = greedy(distFunc, sampleSet, medoidSize, random);
- if(LOG.isDebugging()) {
+ if (LOG.isDebugging()) {
StringBuilder msg = new StringBuilder();
msg.append('\n');
msg.append("sampleSize ").append(sampleSize).append('\n');
@@ -176,7 +176,7 @@ public class PROCLUS<V extends NumberVector<?>> extends AbstractProjectedCluster
}
// iterative phase
- if(LOG.isVerbose()) {
+ if (LOG.isVerbose()) {
LOG.verbose("2. Iterative phase...");
}
double bestObjective = Double.POSITIVE_INFINITY;
@@ -184,7 +184,7 @@ public class PROCLUS<V extends NumberVector<?>> extends AbstractProjectedCluster
ModifiableDBIDs m_bad = null;
ModifiableDBIDs m_current = initialSet(medoids, k, random);
- if(LOG.isDebugging()) {
+ if (LOG.isDebugging()) {
StringBuilder msg = new StringBuilder();
msg.append('\n');
msg.append("m_c ").append(m_current).append('\n');
@@ -196,12 +196,12 @@ public class PROCLUS<V extends NumberVector<?>> extends AbstractProjectedCluster
// TODO: Use DataStore and Trove for performance
Map<DBID, PROCLUSCluster> clusters = null;
int loops = 0;
- while(loops < 10) {
+ while (loops < 10) {
Map<DBID, TIntSet> dimensions = findDimensions(m_current, relation, distFunc, rangeQuery);
clusters = assignPoints(dimensions, relation);
double objectiveFunction = evaluateClusters(clusters, dimensions, relation);
- if(objectiveFunction < bestObjective) {
+ if (objectiveFunction < bestObjective) {
// restart counting loops
loops = 0;
bestObjective = objectiveFunction;
@@ -211,32 +211,32 @@ public class PROCLUS<V extends NumberVector<?>> extends AbstractProjectedCluster
m_current = computeM_current(medoids, m_best, m_bad, random);
loops++;
- if(cprogress != null) {
+ if (cprogress != null) {
cprogress.setProcessed(clusters.size(), LOG);
}
}
- if(cprogress != null) {
+ if (cprogress != null) {
cprogress.setCompleted(LOG);
}
// refinement phase
- if(LOG.isVerbose()) {
+ if (LOG.isVerbose()) {
LOG.verbose("3. Refinement phase...");
}
- List<Pair<V, TIntSet>> dimensions = findDimensions(new ArrayList<PROCLUSCluster>(clusters.values()), relation);
+ List<Pair<V, TIntSet>> dimensions = findDimensions(new ArrayList<>(clusters.values()), relation);
List<PROCLUSCluster> finalClusters = finalAssignment(dimensions, relation);
// build result
int numClusters = 1;
- Clustering<SubspaceModel<V>> result = new Clustering<SubspaceModel<V>>("ProClus clustering", "proclus-clustering");
- for(PROCLUSCluster c : finalClusters) {
- Cluster<SubspaceModel<V>> cluster = new Cluster<SubspaceModel<V>>(c.objectIDs);
- cluster.setModel(new SubspaceModel<V>(new Subspace(c.getDimensions()), c.centroid));
+ Clustering<SubspaceModel<V>> result = new Clustering<>("ProClus clustering", "proclus-clustering");
+ for (PROCLUSCluster c : finalClusters) {
+ Cluster<SubspaceModel<V>> cluster = new Cluster<>(c.objectIDs);
+ cluster.setModel(new SubspaceModel<>(new Subspace(c.getDimensions()), c.centroid));
cluster.setName("cluster_" + numClusters++);
- result.addCluster(cluster);
+ result.addToplevelCluster(cluster);
}
return result;
}
@@ -257,22 +257,22 @@ public class PROCLUS<V extends NumberVector<?>> extends AbstractProjectedCluster
// m_1 is random point of S
DBID m_i = s.remove(random.nextInt(s.size()));
medoids.add(m_i);
- if(LOG.isDebugging()) {
+ if (LOG.isDebugging()) {
LOG.debugFiner("medoids " + medoids);
}
// compute distances between each point in S and m_i
// FIXME: don't use maps, so we can work with DBIDRef
- Map<DBID, DistanceDBIDPair<DoubleDistance>> distances = new HashMap<DBID, DistanceDBIDPair<DoubleDistance>>();
- for(DBIDIter iter = s.iter(); iter.valid(); iter.advance()) {
+ Map<DBID, DistanceDBIDPair<DoubleDistance>> distances = new HashMap<>();
+ for (DBIDIter iter = s.iter(); iter.valid(); iter.advance()) {
DBID id = DBIDUtil.deref(iter);
DoubleDistance dist = distFunc.distance(id, m_i);
distances.put(id, DBIDUtil.newDistancePair(dist, id));
}
- for(int i = 1; i < m; i++) {
- // choose medoid m_i to be far from prevois medoids
- List<DistanceDBIDPair<DoubleDistance>> d = new ArrayList<DistanceDBIDPair<DoubleDistance>>(distances.values());
+ for (int i = 1; i < m; i++) {
+ // choose medoid m_i to be far from previous medoids
+ List<DistanceDBIDPair<DoubleDistance>> d = new ArrayList<>(distances.values());
DistanceDBIDResultUtil.sortByDistance(d);
m_i = DBIDUtil.deref(d.get(d.size() - 1));
@@ -281,7 +281,7 @@ public class PROCLUS<V extends NumberVector<?>> extends AbstractProjectedCluster
distances.remove(m_i);
// compute distances of each point to closest medoid
- for(DBIDIter iter = s.iter(); iter.valid(); iter.advance()) {
+ for (DBIDIter iter = s.iter(); iter.valid(); iter.advance()) {
DBID id = DBIDUtil.deref(iter);
DoubleDistance dist_new = distFunc.distance(id, m_i);
DoubleDistance dist_old = distances.get(id).getDistance();
@@ -290,7 +290,7 @@ public class PROCLUS<V extends NumberVector<?>> extends AbstractProjectedCluster
distances.put(id, DBIDUtil.newDistancePair(dist, id));
}
- if(LOG.isDebugging()) {
+ if (LOG.isDebugging()) {
LOG.debugFiner("medoids " + medoids);
}
}
@@ -309,7 +309,7 @@ public class PROCLUS<V extends NumberVector<?>> extends AbstractProjectedCluster
private ModifiableDBIDs initialSet(DBIDs sampleSet, int k, Random random) {
ArrayModifiableDBIDs s = DBIDUtil.newArray(sampleSet);
ModifiableDBIDs initialSet = DBIDUtil.newHashSet();
- while(initialSet.size() < k) {
+ while (initialSet.size() < k) {
DBID next = s.remove(random.nextInt(s.size()));
initialSet.add(next);
}
@@ -330,16 +330,15 @@ public class PROCLUS<V extends NumberVector<?>> extends AbstractProjectedCluster
m_list.removeDBIDs(m_best);
ModifiableDBIDs m_current = DBIDUtil.newHashSet();
- for(DBIDIter iter = m_best.iter(); iter.valid(); iter.advance()) {
+ for (DBIDIter iter = m_best.iter(); iter.valid(); iter.advance()) {
DBID m_i = DBIDUtil.deref(iter);
- if(m_bad.contains(m_i)) {
+ if (m_bad.contains(m_i)) {
int currentSize = m_current.size();
- while(m_current.size() == currentSize) {
+ while (m_current.size() == currentSize) {
DBID next = m_list.remove(random.nextInt(m_list.size()));
m_current.add(next);
}
- }
- else {
+ } else {
m_current.add(m_i);
}
}
@@ -358,28 +357,28 @@ public class PROCLUS<V extends NumberVector<?>> extends AbstractProjectedCluster
* @param distFunc the distance function
* @return a mapping of the medoid's id to its locality
*/
- private Map<DBID, DistanceDBIDResult<DoubleDistance>> getLocalities(DBIDs medoids, Relation<V> database, DistanceQuery<V, DoubleDistance> distFunc, RangeQuery<V, DoubleDistance> rangeQuery) {
- Map<DBID, DistanceDBIDResult<DoubleDistance>> result = new HashMap<DBID, DistanceDBIDResult<DoubleDistance>>();
+ private Map<DBID, DistanceDBIDList<DoubleDistance>> getLocalities(DBIDs medoids, Relation<V> database, DistanceQuery<V, DoubleDistance> distFunc, RangeQuery<V, DoubleDistance> rangeQuery) {
+ Map<DBID, DistanceDBIDList<DoubleDistance>> result = new HashMap<>();
- for(DBIDIter iter = medoids.iter(); iter.valid(); iter.advance()) {
+ for (DBIDIter iter = medoids.iter(); iter.valid(); iter.advance()) {
DBID m = DBIDUtil.deref(iter);
// determine minimum distance between current medoid m and any other
// medoid m_i
DoubleDistance minDist = null;
- for(DBIDIter iter2 = medoids.iter(); iter2.valid(); iter2.advance()) {
+ for (DBIDIter iter2 = medoids.iter(); iter2.valid(); iter2.advance()) {
DBID m_i = DBIDUtil.deref(iter2);
- if(DBIDUtil.equal(m_i, m)) {
+ if (DBIDUtil.equal(m_i, m)) {
continue;
}
DoubleDistance currentDist = distFunc.distance(m, m_i);
- if(minDist == null || currentDist.compareTo(minDist) < 0) {
+ if (minDist == null || currentDist.compareTo(minDist) < 0) {
minDist = currentDist;
}
}
// determine points in sphere centered at m with radius minDist
assert minDist != null;
- DistanceDBIDResult<DoubleDistance> qr = rangeQuery.getRangeForDBID(m, minDist);
+ DistanceDBIDList<DoubleDistance> qr = rangeQuery.getRangeForDBID(m, minDist);
result.put(m, qr);
}
@@ -398,32 +397,32 @@ public class PROCLUS<V extends NumberVector<?>> extends AbstractProjectedCluster
*/
private Map<DBID, TIntSet> findDimensions(DBIDs medoids, Relation<V> database, DistanceQuery<V, DoubleDistance> distFunc, RangeQuery<V, DoubleDistance> rangeQuery) {
// get localities
- Map<DBID, DistanceDBIDResult<DoubleDistance>> localities = getLocalities(medoids, database, distFunc, rangeQuery);
+ Map<DBID, DistanceDBIDList<DoubleDistance>> localities = getLocalities(medoids, database, distFunc, rangeQuery);
// compute x_ij = avg distance from points in l_i to medoid m_i
int dim = RelationUtil.dimensionality(database);
- Map<DBID, double[]> averageDistances = new HashMap<DBID, double[]>();
+ Map<DBID, double[]> averageDistances = new HashMap<>();
- for(DBIDIter iter = medoids.iter(); iter.valid(); iter.advance()) {
+ for (DBIDIter iter = medoids.iter(); iter.valid(); iter.advance()) {
DBID m_i = DBIDUtil.deref(iter);
V medoid_i = database.get(m_i);
- DistanceDBIDResult<DoubleDistance> l_i = localities.get(m_i);
+ DistanceDBIDList<DoubleDistance> l_i = localities.get(m_i);
double[] x_i = new double[dim];
- for(DBIDIter qr = l_i.iter(); qr.valid(); qr.advance()) {
+ for (DBIDIter qr = l_i.iter(); qr.valid(); qr.advance()) {
V o = database.get(qr);
- for(int d = 0; d < dim; d++) {
+ for (int d = 0; d < dim; d++) {
x_i[d] += Math.abs(medoid_i.doubleValue(d) - o.doubleValue(d));
}
}
- for(int d = 0; d < dim; d++) {
+ for (int d = 0; d < dim; d++) {
x_i[d] /= l_i.size();
}
averageDistances.put(m_i, x_i);
}
- Map<DBID, TIntSet> dimensionMap = new HashMap<DBID, TIntSet>();
- List<CTriple<Double, DBID, Integer>> z_ijs = new ArrayList<CTriple<Double, DBID, Integer>>();
- for(DBIDIter iter = medoids.iter(); iter.valid(); iter.advance()) {
+ Map<DBID, TIntSet> dimensionMap = new HashMap<>();
+ List<CTriple<Double, DBID, Integer>> z_ijs = new ArrayList<>();
+ for (DBIDIter iter = medoids.iter(); iter.valid(); iter.advance()) {
DBID m_i = DBIDUtil.deref(iter);
TIntSet dims_i = new TIntHashSet();
dimensionMap.put(m_i, dims_i);
@@ -431,33 +430,33 @@ public class PROCLUS<V extends NumberVector<?>> extends AbstractProjectedCluster
double[] x_i = averageDistances.get(m_i);
// y_i
double y_i = 0;
- for(int j = 0; j < dim; j++) {
+ for (int j = 0; j < dim; j++) {
y_i += x_i[j];
}
y_i /= dim;
// sigma_i
double sigma_i = 0;
- for(int j = 0; j < dim; j++) {
+ for (int j = 0; j < dim; j++) {
double diff = x_i[j] - y_i;
sigma_i += diff * diff;
}
sigma_i /= (dim - 1);
sigma_i = Math.sqrt(sigma_i);
- for(int j = 0; j < dim; j++) {
- z_ijs.add(new CTriple<Double, DBID, Integer>((x_i[j] - y_i) / sigma_i, m_i, j));
+ for (int j = 0; j < dim; j++) {
+ z_ijs.add(new CTriple<>((x_i[j] - y_i) / sigma_i, m_i, j));
}
}
Collections.sort(z_ijs);
int max = Math.max(k * l, 2);
- for(int m = 0; m < max; m++) {
+ for (int m = 0; m < max; m++) {
CTriple<Double, DBID, Integer> z_ij = z_ijs.get(m);
TIntSet dims_i = dimensionMap.get(z_ij.getSecond());
dims_i.add(z_ij.getThird());
- if(LOG.isDebugging()) {
+ if (LOG.isDebugging()) {
StringBuilder msg = new StringBuilder();
msg.append('\n');
msg.append("z_ij ").append(z_ij).append('\n');
@@ -480,61 +479,61 @@ public class PROCLUS<V extends NumberVector<?>> extends AbstractProjectedCluster
private List<Pair<V, TIntSet>> findDimensions(List<PROCLUSCluster> clusters, Relation<V> database) {
// compute x_ij = avg distance from points in c_i to c_i.centroid
int dim = RelationUtil.dimensionality(database);
- Map<Integer, double[]> averageDistances = new HashMap<Integer, double[]>();
+ Map<Integer, double[]> averageDistances = new HashMap<>();
- for(int i = 0; i < clusters.size(); i++) {
+ for (int i = 0; i < clusters.size(); i++) {
PROCLUSCluster c_i = clusters.get(i);
double[] x_i = new double[dim];
- for(DBIDIter iter = c_i.objectIDs.iter(); iter.valid(); iter.advance()) {
+ for (DBIDIter iter = c_i.objectIDs.iter(); iter.valid(); iter.advance()) {
V o = database.get(iter);
- for(int d = 0; d < dim; d++) {
+ for (int d = 0; d < dim; d++) {
x_i[d] += Math.abs(c_i.centroid.doubleValue(d) - o.doubleValue(d));
}
}
- for(int d = 0; d < dim; d++) {
+ for (int d = 0; d < dim; d++) {
x_i[d] /= c_i.objectIDs.size();
}
averageDistances.put(i, x_i);
}
- List<CTriple<Double, Integer, Integer>> z_ijs = new ArrayList<CTriple<Double, Integer, Integer>>();
- for(int i = 0; i < clusters.size(); i++) {
+ List<CTriple<Double, Integer, Integer>> z_ijs = new ArrayList<>();
+ for (int i = 0; i < clusters.size(); i++) {
double[] x_i = averageDistances.get(i);
// y_i
double y_i = 0;
- for(int j = 0; j < dim; j++) {
+ for (int j = 0; j < dim; j++) {
y_i += x_i[j];
}
y_i /= dim;
// sigma_i
double sigma_i = 0;
- for(int j = 0; j < dim; j++) {
+ for (int j = 0; j < dim; j++) {
double diff = x_i[j] - y_i;
sigma_i += diff * diff;
}
sigma_i /= (dim - 1);
sigma_i = Math.sqrt(sigma_i);
- for(int j = 0; j < dim; j++) {
- z_ijs.add(new CTriple<Double, Integer, Integer>((x_i[j] - y_i) / sigma_i, i, j));
+ for (int j = 0; j < dim; j++) {
+ z_ijs.add(new CTriple<>((x_i[j] - y_i) / sigma_i, i, j));
}
}
Collections.sort(z_ijs);
// mapping cluster index -> dimensions
- Map<Integer, TIntSet> dimensionMap = new HashMap<Integer, TIntSet>();
+ Map<Integer, TIntSet> dimensionMap = new HashMap<>();
int max = Math.max(k * l, 2);
- for(int m = 0; m < max; m++) {
+ for (int m = 0; m < max; m++) {
CTriple<Double, Integer, Integer> z_ij = z_ijs.get(m);
TIntSet dims_i = dimensionMap.get(z_ij.getSecond());
- if(dims_i == null) {
+ if (dims_i == null) {
dims_i = new TIntHashSet();
dimensionMap.put(z_ij.getSecond(), dims_i);
}
dims_i.add(z_ij.getThird());
- if(LOG.isDebugging()) {
+ if (LOG.isDebugging()) {
StringBuilder msg = new StringBuilder();
msg.append('\n');
msg.append("z_ij ").append(z_ij).append('\n');
@@ -544,11 +543,11 @@ public class PROCLUS<V extends NumberVector<?>> extends AbstractProjectedCluster
}
// mapping cluster -> dimensions
- List<Pair<V, TIntSet>> result = new ArrayList<Pair<V, TIntSet>>();
- for(int i : dimensionMap.keySet()) {
+ List<Pair<V, TIntSet>> result = new ArrayList<>();
+ for (int i : dimensionMap.keySet()) {
TIntSet dims_i = dimensionMap.get(i);
PROCLUSCluster c_i = clusters.get(i);
- result.add(new Pair<V, TIntSet>(c_i.centroid, dims_i));
+ result.add(new Pair<>(c_i.centroid, dims_i));
}
return result;
}
@@ -562,19 +561,19 @@ public class PROCLUS<V extends NumberVector<?>> extends AbstractProjectedCluster
* @return the assignments of the object to the clusters
*/
private Map<DBID, PROCLUSCluster> assignPoints(Map<DBID, TIntSet> dimensions, Relation<V> database) {
- Map<DBID, ModifiableDBIDs> clusterIDs = new HashMap<DBID, ModifiableDBIDs>();
- for(DBID m_i : dimensions.keySet()) {
+ Map<DBID, ModifiableDBIDs> clusterIDs = new HashMap<>();
+ for (DBID m_i : dimensions.keySet()) {
clusterIDs.put(m_i, DBIDUtil.newHashSet());
}
- for(DBIDIter it = database.iterDBIDs(); it.valid(); it.advance()) {
+ for (DBIDIter it = database.iterDBIDs(); it.valid(); it.advance()) {
DBID p_id = DBIDUtil.deref(it);
V p = database.get(p_id);
DistanceDBIDPair<DoubleDistance> minDist = null;
- for(DBID m_i : dimensions.keySet()) {
+ for (DBID m_i : dimensions.keySet()) {
V m = database.get(m_i);
DistanceDBIDPair<DoubleDistance> currentDist = DBIDUtil.newDistancePair(manhattanSegmentalDistance(p, m, dimensions.get(m_i)), m_i);
- if(minDist == null || currentDist.compareByDistance(minDist) < 0) {
+ if (minDist == null || currentDist.compareByDistance(minDist) < 0) {
minDist = currentDist;
}
}
@@ -584,17 +583,17 @@ public class PROCLUS<V extends NumberVector<?>> extends AbstractProjectedCluster
ids.add(p_id);
}
- Map<DBID, PROCLUSCluster> clusters = new HashMap<DBID, PROCLUSCluster>();
- for(DBID m_i : dimensions.keySet()) {
+ Map<DBID, PROCLUSCluster> clusters = new HashMap<>();
+ for (DBID m_i : dimensions.keySet()) {
ModifiableDBIDs objectIDs = clusterIDs.get(m_i);
- if(!objectIDs.isEmpty()) {
+ if (!objectIDs.isEmpty()) {
TIntSet clusterDimensions = dimensions.get(m_i);
V centroid = Centroid.make(database, objectIDs).toVector(database);
clusters.put(m_i, new PROCLUSCluster(objectIDs, clusterDimensions, centroid));
}
}
- if(LOG.isDebugging()) {
+ if (LOG.isDebugging()) {
StringBuilder msg = new StringBuilder();
msg.append('\n');
msg.append("clusters ").append(clusters).append('\n');
@@ -612,22 +611,22 @@ public class PROCLUS<V extends NumberVector<?>> extends AbstractProjectedCluster
* @return the assignments of the object to the clusters
*/
private List<PROCLUSCluster> finalAssignment(List<Pair<V, TIntSet>> dimensions, Relation<V> database) {
- Map<Integer, ModifiableDBIDs> clusterIDs = new HashMap<Integer, ModifiableDBIDs>();
- for(int i = 0; i < dimensions.size(); i++) {
+ Map<Integer, ModifiableDBIDs> clusterIDs = new HashMap<>();
+ for (int i = 0; i < dimensions.size(); i++) {
clusterIDs.put(i, DBIDUtil.newHashSet());
}
- for(DBIDIter it = database.iterDBIDs(); it.valid(); it.advance()) {
+ for (DBIDIter it = database.iterDBIDs(); it.valid(); it.advance()) {
DBID p_id = DBIDUtil.deref(it);
V p = database.get(p_id);
Pair<DoubleDistance, Integer> minDist = null;
- for(int i = 0; i < dimensions.size(); i++) {
+ for (int i = 0; i < dimensions.size(); i++) {
Pair<V, TIntSet> pair_i = dimensions.get(i);
V c_i = pair_i.first;
TIntSet dimensions_i = pair_i.second;
DoubleDistance currentDist = manhattanSegmentalDistance(p, c_i, dimensions_i);
- if(minDist == null || currentDist.compareTo(minDist.first) < 0) {
- minDist = new Pair<DoubleDistance, Integer>(currentDist, i);
+ if (minDist == null || currentDist.compareTo(minDist.first) < 0) {
+ minDist = new Pair<>(currentDist, i);
}
}
// add p to cluster with mindist
@@ -636,17 +635,17 @@ public class PROCLUS<V extends NumberVector<?>> extends AbstractProjectedCluster
ids.add(p_id);
}
- List<PROCLUSCluster> clusters = new ArrayList<PROCLUSCluster>();
- for(int i = 0; i < dimensions.size(); i++) {
+ List<PROCLUSCluster> clusters = new ArrayList<>();
+ for (int i = 0; i < dimensions.size(); i++) {
ModifiableDBIDs objectIDs = clusterIDs.get(i);
- if(!objectIDs.isEmpty()) {
+ if (!objectIDs.isEmpty()) {
TIntSet clusterDimensions = dimensions.get(i).second;
V centroid = Centroid.make(database, objectIDs).toVector(database);
clusters.add(new PROCLUSCluster(objectIDs, clusterDimensions, centroid));
}
}
- if(LOG.isDebugging()) {
+ if (LOG.isDebugging()) {
StringBuilder msg = new StringBuilder();
msg.append('\n');
msg.append("clusters ").append(clusters).append('\n');
@@ -667,7 +666,7 @@ public class PROCLUS<V extends NumberVector<?>> extends AbstractProjectedCluster
*/
private DoubleDistance manhattanSegmentalDistance(V o1, V o2, TIntSet dimensions) {
double result = 0;
- for (TIntIterator iter = dimensions.iterator(); iter.hasNext(); ) {
+ for (TIntIterator iter = dimensions.iterator(); iter.hasNext();) {
final int d = iter.next();
result += Math.abs(o1.doubleValue(d) - o2.doubleValue(d));
}
@@ -685,13 +684,13 @@ public class PROCLUS<V extends NumberVector<?>> extends AbstractProjectedCluster
*/
private double evaluateClusters(Map<DBID, PROCLUSCluster> clusters, Map<DBID, TIntSet> dimensions, Relation<V> database) {
double result = 0;
- for(DBID m_i : clusters.keySet()) {
+ for (DBID m_i : clusters.keySet()) {
PROCLUSCluster c_i = clusters.get(m_i);
V centroid_i = c_i.centroid;
TIntSet dims_i = dimensions.get(m_i);
double w_i = 0;
- for (TIntIterator iter = dims_i.iterator(); iter.hasNext(); ) {
+ for (TIntIterator iter = dims_i.iterator(); iter.hasNext();) {
final int j = iter.next();
w_i += avgDistance(centroid_i, c_i.objectIDs, database, j);
}
@@ -716,7 +715,7 @@ public class PROCLUS<V extends NumberVector<?>> extends AbstractProjectedCluster
*/
private double avgDistance(V centroid, DBIDs objectIDs, Relation<V> database, int dimension) {
Mean avg = new Mean();
- for(DBIDIter iter = objectIDs.iter(); iter.valid(); iter.advance()) {
+ for (DBIDIter iter = objectIDs.iter(); iter.valid(); iter.advance()) {
V o = database.get(iter);
avg.put(Math.abs(centroid.doubleValue(dimension) - o.doubleValue(dimension)));
}
@@ -733,9 +732,9 @@ public class PROCLUS<V extends NumberVector<?>> extends AbstractProjectedCluster
*/
private ModifiableDBIDs computeBadMedoids(Map<DBID, PROCLUSCluster> clusters, int threshold) {
ModifiableDBIDs badMedoids = DBIDUtil.newHashSet();
- for(DBID m_i : clusters.keySet()) {
+ for (DBID m_i : clusters.keySet()) {
PROCLUSCluster c_i = clusters.get(m_i);
- if(c_i.objectIDs.size() < threshold) {
+ if (c_i.objectIDs.size() < threshold) {
badMedoids.add(m_i);
}
}
@@ -791,11 +790,10 @@ public class PROCLUS<V extends NumberVector<?>> extends AbstractProjectedCluster
StringBuilder result = new StringBuilder();
result.append("Dimensions: [");
boolean notFirst = false;
- for(TIntIterator iter = dimensions.iterator(); iter.hasNext(); ) {
- if(notFirst) {
+ for (TIntIterator iter = dimensions.iterator(); iter.hasNext();) {
+ if (notFirst) {
result.append(',');
- }
- else {
+ } else {
notFirst = true;
}
result.append(iter.next());
@@ -813,7 +811,7 @@ public class PROCLUS<V extends NumberVector<?>> extends AbstractProjectedCluster
*/
public BitSet getDimensions() {
BitSet result = new BitSet();
- for(TIntIterator iter = dimensions.iterator(); iter.hasNext(); ) {
+ for (TIntIterator iter = dimensions.iterator(); iter.hasNext();) {
result.set(iter.next());
}
return result;
@@ -847,19 +845,19 @@ public class PROCLUS<V extends NumberVector<?>> extends AbstractProjectedCluster
IntParameter m_iP = new IntParameter(M_I_ID, 10);
m_iP.addConstraint(new GreaterConstraint(0));
- if(config.grab(m_iP)) {
+ if (config.grab(m_iP)) {
m_i = m_iP.getValue();
}
RandomParameter rndP = new RandomParameter(SEED_ID);
- if(config.grab(rndP)) {
+ if (config.grab(rndP)) {
rnd = rndP.getValue();
}
}
@Override
protected PROCLUS<V> makeInstance() {
- return new PROCLUS<V>(k, k_i, l, m_i, rnd);
+ return new PROCLUS<>(k, k_i, l, m_i, rnd);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/PreDeCon.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/PreDeCon.java
index fc3228eb..4e670974 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/PreDeCon.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/PreDeCon.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.subspace;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -111,7 +111,7 @@ public class PreDeCon<V extends NumberVector<?>> extends AbstractProjectedDBSCAN
@Override
protected PreDeCon<V> makeInstance() {
- return new PreDeCon<V>(epsilon, minpts, outerdist, lambda);
+ return new PreDeCon<>(epsilon, minpts, outerdist, lambda);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/SUBCLU.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/SUBCLU.java
index 46c5f0b8..c8d0833e 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/SUBCLU.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/SUBCLU.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.subspace;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -43,7 +43,7 @@ import de.lmu.ifi.dbs.elki.database.ProxyDatabase;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.database.relation.RelationUtil;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.AbstractDimensionsSelectingDoubleDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.DimensionSelectingSubspaceDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.SubspaceEuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.logging.Logging;
@@ -105,7 +105,7 @@ public class SUBCLU<V extends NumberVector<?>> extends AbstractAlgorithm<Cluster
/**
* Parameter to specify the maximum radius of the neighborhood to be
* considered, must be suitable to
- * {@link AbstractDimensionsSelectingDoubleDistanceFunction}.
+ * {@link DimensionSelectingSubspaceDistanceFunction}.
* <p>
* Key: {@code -subclu.epsilon}
* </p>
@@ -125,7 +125,7 @@ public class SUBCLU<V extends NumberVector<?>> extends AbstractAlgorithm<Cluster
* Holds the instance of the distance function specified by
* {@link #DISTANCE_FUNCTION_ID}.
*/
- private AbstractDimensionsSelectingDoubleDistanceFunction<V> distanceFunction;
+ private DimensionSelectingSubspaceDistanceFunction<V, DoubleDistance> distanceFunction;
/**
* Holds the value of {@link #EPSILON_ID}.
@@ -149,7 +149,7 @@ public class SUBCLU<V extends NumberVector<?>> extends AbstractAlgorithm<Cluster
* @param epsilon Epsilon value
* @param minpts Minpts value
*/
- public SUBCLU(AbstractDimensionsSelectingDoubleDistanceFunction<V> distanceFunction, DoubleDistance epsilon, int minpts) {
+ public SUBCLU(DimensionSelectingSubspaceDistanceFunction<V, DoubleDistance> distanceFunction, DoubleDistance epsilon, int minpts) {
super();
this.distanceFunction = distanceFunction;
this.epsilon = epsilon;
@@ -168,49 +168,49 @@ public class SUBCLU<V extends NumberVector<?>> extends AbstractAlgorithm<Cluster
StepProgress stepprog = LOG.isVerbose() ? new StepProgress(dimensionality) : null;
// Generate all 1-dimensional clusters
- if(stepprog != null) {
+ if (stepprog != null) {
stepprog.beginStep(1, "Generate all 1-dimensional clusters.", LOG);
}
// mapping of dimensionality to set of subspaces
- HashMap<Integer, List<Subspace>> subspaceMap = new HashMap<Integer, List<Subspace>>();
+ HashMap<Integer, List<Subspace>> subspaceMap = new HashMap<>();
// list of 1-dimensional subspaces containing clusters
- List<Subspace> s_1 = new ArrayList<Subspace>();
+ List<Subspace> s_1 = new ArrayList<>();
subspaceMap.put(0, s_1);
// mapping of subspaces to list of clusters
- TreeMap<Subspace, List<Cluster<Model>>> clusterMap = new TreeMap<Subspace, List<Cluster<Model>>>(new Subspace.DimensionComparator());
+ TreeMap<Subspace, List<Cluster<Model>>> clusterMap = new TreeMap<>(new Subspace.DimensionComparator());
- for(int d = 0; d < dimensionality; d++) {
+ for (int d = 0; d < dimensionality; d++) {
Subspace currentSubspace = new Subspace(d);
List<Cluster<Model>> clusters = runDBSCAN(relation, null, currentSubspace);
- if(LOG.isDebuggingFiner()) {
+ if (LOG.isDebuggingFiner()) {
StringBuilder msg = new StringBuilder();
msg.append('\n').append(clusters.size()).append(" clusters in subspace ").append(currentSubspace.dimensonsToString()).append(": \n");
- for(Cluster<Model> cluster : clusters) {
+ for (Cluster<Model> cluster : clusters) {
msg.append(" " + cluster.getIDs() + "\n");
}
LOG.debugFiner(msg.toString());
}
- if(!clusters.isEmpty()) {
+ if (!clusters.isEmpty()) {
s_1.add(currentSubspace);
clusterMap.put(currentSubspace, clusters);
}
}
// Generate (d+1)-dimensional clusters from d-dimensional clusters
- for(int d = 0; d < dimensionality - 1; d++) {
- if(stepprog != null) {
+ for (int d = 0; d < dimensionality - 1; d++) {
+ if (stepprog != null) {
stepprog.beginStep(d + 2, "Generate " + (d + 2) + "-dimensional clusters from " + (d + 1) + "-dimensional clusters.", LOG);
}
List<Subspace> subspaces = subspaceMap.get(d);
- if(subspaces == null || subspaces.isEmpty()) {
- if(stepprog != null) {
- for(int dim = d + 1; dim < dimensionality - 1; dim++) {
+ if (subspaces == null || subspaces.isEmpty()) {
+ if (stepprog != null) {
+ for (int dim = d + 1; dim < dimensionality - 1; dim++) {
stepprog.beginStep(dim + 2, "Generation of" + (dim + 2) + "-dimensional clusters not applicable, because no more " + (d + 2) + "-dimensional subspaces found.", LOG);
}
}
@@ -218,57 +218,57 @@ public class SUBCLU<V extends NumberVector<?>> extends AbstractAlgorithm<Cluster
}
List<Subspace> candidates = generateSubspaceCandidates(subspaces);
- List<Subspace> s_d = new ArrayList<Subspace>();
+ List<Subspace> s_d = new ArrayList<>();
- for(Subspace candidate : candidates) {
+ for (Subspace candidate : candidates) {
Subspace bestSubspace = bestSubspace(subspaces, candidate, clusterMap);
- if(LOG.isDebuggingFine()) {
+ if (LOG.isDebuggingFine()) {
LOG.debugFine("best subspace of " + candidate.dimensonsToString() + ": " + bestSubspace.dimensonsToString());
}
List<Cluster<Model>> bestSubspaceClusters = clusterMap.get(bestSubspace);
- List<Cluster<Model>> clusters = new ArrayList<Cluster<Model>>();
- for(Cluster<Model> cluster : bestSubspaceClusters) {
+ List<Cluster<Model>> clusters = new ArrayList<>();
+ for (Cluster<Model> cluster : bestSubspaceClusters) {
List<Cluster<Model>> candidateClusters = runDBSCAN(relation, cluster.getIDs(), candidate);
- if(!candidateClusters.isEmpty()) {
+ if (!candidateClusters.isEmpty()) {
clusters.addAll(candidateClusters);
}
}
- if(LOG.isDebuggingFine()) {
+ if (LOG.isDebuggingFine()) {
StringBuilder msg = new StringBuilder();
msg.append(clusters.size() + " cluster(s) in subspace " + candidate + ": \n");
- for(Cluster<Model> c : clusters) {
+ for (Cluster<Model> c : clusters) {
msg.append(" " + c.getIDs() + "\n");
}
LOG.debugFine(msg.toString());
}
- if(!clusters.isEmpty()) {
+ if (!clusters.isEmpty()) {
s_d.add(candidate);
clusterMap.put(candidate, clusters);
}
}
- if(!s_d.isEmpty()) {
+ if (!s_d.isEmpty()) {
subspaceMap.put(d + 1, s_d);
}
}
// build result
int numClusters = 1;
- result = new Clustering<SubspaceModel<V>>("SUBCLU clustering", "subclu-clustering");
- for(Subspace subspace : clusterMap.descendingKeySet()) {
+ result = new Clustering<>("SUBCLU clustering", "subclu-clustering");
+ for (Subspace subspace : clusterMap.descendingKeySet()) {
List<Cluster<Model>> clusters = clusterMap.get(subspace);
- for(Cluster<Model> cluster : clusters) {
- Cluster<SubspaceModel<V>> newCluster = new Cluster<SubspaceModel<V>>(cluster.getIDs());
- newCluster.setModel(new SubspaceModel<V>(subspace, Centroid.make(relation, cluster.getIDs()).toVector(relation)));
+ for (Cluster<Model> cluster : clusters) {
+ Cluster<SubspaceModel<V>> newCluster = new Cluster<>(cluster.getIDs());
+ newCluster.setModel(new SubspaceModel<>(subspace, Centroid.make(relation, cluster.getIDs()).toVector(relation)));
newCluster.setName("cluster_" + numClusters++);
- result.addCluster(newCluster);
+ result.addToplevelCluster(newCluster);
}
}
- if(stepprog != null) {
+ if (stepprog != null) {
stepprog.setCompleted(LOG);
}
return result;
@@ -300,7 +300,7 @@ public class SUBCLU<V extends NumberVector<?>> extends AbstractAlgorithm<Cluster
distanceFunction.setSelectedDimensions(subspace.getDimensions());
ProxyDatabase proxy;
- if(ids == null) {
+ if (ids == null) {
// TODO: in this case, we might want to use an index - the proxy below
// will prevent this!
ids = relation.getDBIDs();
@@ -308,18 +308,18 @@ public class SUBCLU<V extends NumberVector<?>> extends AbstractAlgorithm<Cluster
proxy = new ProxyDatabase(ids, relation);
- DBSCAN<V, DoubleDistance> dbscan = new DBSCAN<V, DoubleDistance>(distanceFunction, epsilon, minpts);
+ DBSCAN<V, DoubleDistance> dbscan = new DBSCAN<>(distanceFunction, epsilon, minpts);
// run DBSCAN
- if(LOG.isVerbose()) {
+ if (LOG.isVerbose()) {
LOG.verbose("\nRun DBSCAN on subspace " + subspace.dimensonsToString());
}
Clustering<Model> dbsres = dbscan.run(proxy);
// separate cluster and noise
List<Cluster<Model>> clusterAndNoise = dbsres.getAllClusters();
- List<Cluster<Model>> clusters = new ArrayList<Cluster<Model>>();
- for(Cluster<Model> c : clusterAndNoise) {
- if(!c.isNoise()) {
+ List<Cluster<Model>> clusters = new ArrayList<>();
+ for (Cluster<Model> c : clusterAndNoise) {
+ if (!c.isNoise()) {
clusters.add(c);
}
}
@@ -334,9 +334,9 @@ public class SUBCLU<V extends NumberVector<?>> extends AbstractAlgorithm<Cluster
* @return the {@code d+1}-dimensional subspace candidates
*/
private List<Subspace> generateSubspaceCandidates(List<Subspace> subspaces) {
- List<Subspace> candidates = new ArrayList<Subspace>();
+ List<Subspace> candidates = new ArrayList<>();
- if(subspaces.isEmpty()) {
+ if (subspaces.isEmpty()) {
return candidates;
}
@@ -344,46 +344,46 @@ public class SUBCLU<V extends NumberVector<?>> extends AbstractAlgorithm<Cluster
int d = subspaces.get(0).dimensionality();
StringBuilder msgFine = new StringBuilder("\n");
- if(LOG.isDebuggingFiner()) {
+ if (LOG.isDebuggingFiner()) {
msgFine.append("subspaces ").append(subspaces).append('\n');
}
- for(int i = 0; i < subspaces.size(); i++) {
+ for (int i = 0; i < subspaces.size(); i++) {
Subspace s1 = subspaces.get(i);
- for(int j = i + 1; j < subspaces.size(); j++) {
+ for (int j = i + 1; j < subspaces.size(); j++) {
Subspace s2 = subspaces.get(j);
Subspace candidate = s1.join(s2);
- if(candidate != null) {
- if(LOG.isDebuggingFiner()) {
+ if (candidate != null) {
+ if (LOG.isDebuggingFiner()) {
msgFine.append("candidate: ").append(candidate.dimensonsToString()).append('\n');
}
// prune irrelevant candidate subspaces
List<Subspace> lowerSubspaces = lowerSubspaces(candidate);
- if(LOG.isDebuggingFiner()) {
+ if (LOG.isDebuggingFiner()) {
msgFine.append("lowerSubspaces: ").append(lowerSubspaces).append('\n');
}
boolean irrelevantCandidate = false;
- for(Subspace s : lowerSubspaces) {
- if(!subspaces.contains(s)) {
+ for (Subspace s : lowerSubspaces) {
+ if (!subspaces.contains(s)) {
irrelevantCandidate = true;
break;
}
}
- if(!irrelevantCandidate) {
+ if (!irrelevantCandidate) {
candidates.add(candidate);
}
}
}
}
- if(LOG.isDebuggingFiner()) {
+ if (LOG.isDebuggingFiner()) {
LOG.debugFiner(msgFine.toString());
}
- if(LOG.isDebugging()) {
+ if (LOG.isDebugging()) {
StringBuilder msg = new StringBuilder();
msg.append(d + 1).append("-dimensional candidate subspaces: ");
- for(Subspace candidate : candidates) {
+ for (Subspace candidate : candidates) {
msg.append(candidate.dimensonsToString()).append(' ');
}
LOG.debug(msg.toString());
@@ -401,14 +401,14 @@ public class SUBCLU<V extends NumberVector<?>> extends AbstractAlgorithm<Cluster
*/
private List<Subspace> lowerSubspaces(Subspace subspace) {
int dimensionality = subspace.dimensionality();
- if(dimensionality <= 1) {
+ if (dimensionality <= 1) {
return null;
}
// order result according to the dimensions
- List<Subspace> result = new ArrayList<Subspace>();
+ List<Subspace> result = new ArrayList<>();
BitSet dimensions = subspace.getDimensions();
- for(int dim = dimensions.nextSetBit(0); dim >= 0; dim = dimensions.nextSetBit(dim + 1)) {
+ for (int dim = dimensions.nextSetBit(0); dim >= 0; dim = dimensions.nextSetBit(dim + 1)) {
BitSet newDimensions = (BitSet) dimensions.clone();
newDimensions.set(dim, false);
result.add(new Subspace(newDimensions));
@@ -432,14 +432,14 @@ public class SUBCLU<V extends NumberVector<?>> extends AbstractAlgorithm<Cluster
private Subspace bestSubspace(List<Subspace> subspaces, Subspace candidate, TreeMap<Subspace, List<Cluster<Model>>> clusterMap) {
Subspace bestSubspace = null;
- for(Subspace subspace : subspaces) {
+ for (Subspace subspace : subspaces) {
int min = Integer.MAX_VALUE;
- if(subspace.isSubspace(candidate)) {
+ if (subspace.isSubspace(candidate)) {
List<Cluster<Model>> clusters = clusterMap.get(subspace);
- for(Cluster<Model> cluster : clusters) {
+ for (Cluster<Model> cluster : clusters) {
int clusterSize = cluster.size();
- if(clusterSize < min) {
+ if (clusterSize < min) {
min = clusterSize;
bestSubspace = subspace;
}
@@ -472,31 +472,31 @@ public class SUBCLU<V extends NumberVector<?>> extends AbstractAlgorithm<Cluster
protected DoubleDistance epsilon = null;
- protected AbstractDimensionsSelectingDoubleDistanceFunction<V> distance = null;
+ protected DimensionSelectingSubspaceDistanceFunction<V, DoubleDistance> distance = null;
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- ObjectParameter<AbstractDimensionsSelectingDoubleDistanceFunction<V>> param = new ObjectParameter<AbstractDimensionsSelectingDoubleDistanceFunction<V>>(DISTANCE_FUNCTION_ID, AbstractDimensionsSelectingDoubleDistanceFunction.class, SubspaceEuclideanDistanceFunction.class);
- if(config.grab(param)) {
+ ObjectParameter<DimensionSelectingSubspaceDistanceFunction<V, DoubleDistance>> param = new ObjectParameter<>(DISTANCE_FUNCTION_ID, DimensionSelectingSubspaceDistanceFunction.class, SubspaceEuclideanDistanceFunction.class);
+ if (config.grab(param)) {
distance = param.instantiateClass(config);
}
- DistanceParameter<DoubleDistance> epsilonP = new DistanceParameter<DoubleDistance>(EPSILON_ID, distance);
- if(config.grab(epsilonP)) {
+ DistanceParameter<DoubleDistance> epsilonP = new DistanceParameter<>(EPSILON_ID, distance);
+ if (config.grab(epsilonP)) {
epsilon = epsilonP.getValue();
}
IntParameter minptsP = new IntParameter(MINPTS_ID);
minptsP.addConstraint(new GreaterConstraint(0));
- if(config.grab(minptsP)) {
+ if (config.grab(minptsP)) {
minpts = minptsP.getValue();
}
}
@Override
protected SUBCLU<V> makeInstance() {
- return new SUBCLU<V>(distance, epsilon, minpts);
+ return new SUBCLU<>(distance, epsilon, minpts);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/SubspaceClusteringAlgorithm.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/SubspaceClusteringAlgorithm.java
index 17eb3c19..561816bd 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/SubspaceClusteringAlgorithm.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/SubspaceClusteringAlgorithm.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.subspace;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/clique/CLIQUESubspace.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/clique/CLIQUESubspace.java
index 6b22b233..50e3fcd5 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/clique/CLIQUESubspace.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/clique/CLIQUESubspace.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.subspace.clique;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -65,7 +65,7 @@ public class CLIQUESubspace<V extends NumberVector<?>> extends Subspace {
*/
public CLIQUESubspace(int dimension) {
super(dimension);
- denseUnits = new ArrayList<CLIQUEUnit<V>>();
+ denseUnits = new ArrayList<>();
coverage = 0;
}
@@ -76,7 +76,7 @@ public class CLIQUESubspace<V extends NumberVector<?>> extends Subspace {
*/
public CLIQUESubspace(BitSet dimensions) {
super(dimensions);
- denseUnits = new ArrayList<CLIQUEUnit<V>>();
+ denseUnits = new ArrayList<>();
coverage = 0;
}
@@ -104,12 +104,12 @@ public class CLIQUESubspace<V extends NumberVector<?>> extends Subspace {
* @return the clusters in this subspace and the corresponding cluster models
*/
public List<Pair<Subspace, ModifiableDBIDs>> determineClusters() {
- List<Pair<Subspace, ModifiableDBIDs>> clusters = new ArrayList<Pair<Subspace, ModifiableDBIDs>>();
+ List<Pair<Subspace, ModifiableDBIDs>> clusters = new ArrayList<>();
for(CLIQUEUnit<V> unit : getDenseUnits()) {
if(!unit.isAssigned()) {
ModifiableDBIDs cluster = DBIDUtil.newHashSet();
- CLIQUESubspace<V> model = new CLIQUESubspace<V>(getDimensions());
+ CLIQUESubspace<V> model = new CLIQUESubspace<>(getDimensions());
clusters.add(new Pair<Subspace, ModifiableDBIDs>(model, cluster));
dfs(unit, cluster, model);
}
@@ -217,7 +217,7 @@ public class CLIQUESubspace<V extends NumberVector<?>> extends Subspace {
return null;
}
- CLIQUESubspace<V> s = new CLIQUESubspace<V>(dimensions);
+ CLIQUESubspace<V> s = new CLIQUESubspace<>(dimensions);
for(CLIQUEUnit<V> u1 : this.getDenseUnits()) {
for(CLIQUEUnit<V> u2 : other.getDenseUnits()) {
CLIQUEUnit<V> u = u1.join(u2, all, tau);
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/clique/CLIQUEUnit.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/clique/CLIQUEUnit.java
index 70f251c9..a71b2b67 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/clique/CLIQUEUnit.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/clique/CLIQUEUnit.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.subspace.clique;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -77,7 +77,7 @@ public class CLIQUEUnit<V extends NumberVector<?>> {
public CLIQUEUnit(SortedSet<Interval> intervals, ModifiableDBIDs ids) {
this.intervals = intervals;
- dimensionToInterval = new TIntObjectHashMap<Interval>();
+ dimensionToInterval = new TIntObjectHashMap<>();
for(Interval interval : intervals) {
dimensionToInterval.put(interval.getDimension(), interval);
}
@@ -93,10 +93,10 @@ public class CLIQUEUnit<V extends NumberVector<?>> {
* @param interval the interval belonging to this unit
*/
public CLIQUEUnit(Interval interval) {
- intervals = new TreeSet<Interval>();
+ intervals = new TreeSet<>();
intervals.add(interval);
- dimensionToInterval = new TIntObjectHashMap<Interval>();
+ dimensionToInterval = new TIntObjectHashMap<>();
dimensionToInterval.put(interval.getDimension(), interval);
ids = DBIDUtil.newHashSet();
@@ -254,7 +254,7 @@ public class CLIQUEUnit<V extends NumberVector<?>> {
Iterator<Interval> it1 = this.intervals.iterator();
Iterator<Interval> it2 = other.intervals.iterator();
- SortedSet<Interval> resultIntervals = new TreeSet<Interval>();
+ SortedSet<Interval> resultIntervals = new TreeSet<>();
for(int i = 0; i < this.intervals.size() - 1; i++) {
i1 = it1.next();
i2 = it2.next();
@@ -270,7 +270,7 @@ public class CLIQUEUnit<V extends NumberVector<?>> {
resultIDs.retainAll(other.ids);
if(resultIDs.size() / all >= tau) {
- return new CLIQUEUnit<V>(resultIntervals, resultIDs);
+ return new CLIQUEUnit<>(resultIntervals, resultIDs);
}
return null;
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/clique/package-info.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/clique/package-info.java
index 7a686190..7acd7572 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/clique/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/clique/package-info.java
@@ -7,7 +7,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/package-info.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/package-info.java
index 2a1eb930..2efa038d 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/package-info.java
@@ -10,7 +10,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/ByLabelClustering.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/ByLabelClustering.java
index af8fb1ea..3b5d0ec2 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/ByLabelClustering.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/ByLabelClustering.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.trivial;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -144,7 +144,7 @@ public class ByLabelClustering extends AbstractAlgorithm<Clustering<Model>> impl
HashMap<String, DBIDs> labelMap = multiple ? multipleAssignment(relation) : singleAssignment(relation);
ModifiableDBIDs noiseids = DBIDUtil.newArray();
- Clustering<Model> result = new Clustering<Model>("By Label Clustering", "bylabel-clustering");
+ Clustering<Model> result = new Clustering<>("By Label Clustering", "bylabel-clustering");
for(Entry<String, DBIDs> entry : labelMap.entrySet()) {
DBIDs ids = entry.getValue();
if(ids.size() <= 1) {
@@ -156,13 +156,13 @@ public class ByLabelClustering extends AbstractAlgorithm<Clustering<Model>> impl
if(noisepattern != null && noisepattern.matcher(entry.getKey()).find()) {
c.setNoise(true);
}
- result.addCluster(c);
+ result.addToplevelCluster(c);
}
// Collected noise IDs.
if(noiseids.size() > 0) {
Cluster<Model> c = new Cluster<Model>("Noise", noiseids, ClusterModel.CLUSTER);
c.setNoise(true);
- result.addCluster(c);
+ result.addToplevelCluster(c);
}
return result;
}
@@ -175,7 +175,7 @@ public class ByLabelClustering extends AbstractAlgorithm<Clustering<Model>> impl
* @return a mapping of labels to ids
*/
private HashMap<String, DBIDs> singleAssignment(Relation<?> data) {
- HashMap<String, DBIDs> labelMap = new HashMap<String, DBIDs>();
+ HashMap<String, DBIDs> labelMap = new HashMap<>();
for(DBIDIter iditer = data.iterDBIDs(); iditer.valid(); iditer.advance()) {
final Object val = data.get(iditer);
@@ -193,7 +193,7 @@ public class ByLabelClustering extends AbstractAlgorithm<Clustering<Model>> impl
* @return a mapping of labels to ids
*/
private HashMap<String, DBIDs> multipleAssignment(Relation<?> data) {
- HashMap<String, DBIDs> labelMap = new HashMap<String, DBIDs>();
+ HashMap<String, DBIDs> labelMap = new HashMap<>();
for(DBIDIter iditer = data.iterDBIDs(); iditer.valid(); iditer.advance()) {
String[] labels = data.get(iditer).toString().split(" ");
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/ByLabelHierarchicalClustering.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/ByLabelHierarchicalClustering.java
index dfb7d37f..33101221 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/ByLabelHierarchicalClustering.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/ByLabelHierarchicalClustering.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.trivial;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -88,8 +88,7 @@ public class ByLabelHierarchicalClustering extends AbstractAlgorithm<Clustering<
try {
Relation<ClassLabel> relation = database.getRelation(TypeUtil.CLASSLABEL);
return run(relation);
- }
- catch(NoSupportedDataTypeException e) {
+ } catch (NoSupportedDataTypeException e) {
// Otherwise, try any labellike.
return run(database.getRelation(getInputTypeRestriction()[0]));
}
@@ -101,12 +100,13 @@ public class ByLabelHierarchicalClustering extends AbstractAlgorithm<Clustering<
* @param relation The data input to use
*/
public Clustering<Model> run(Relation<?> relation) {
- HashMap<String, DBIDs> labelmap = new HashMap<String, DBIDs>();
+ HashMap<String, DBIDs> labelmap = new HashMap<>();
ModifiableDBIDs noiseids = DBIDUtil.newArray();
+ Clustering<Model> clustering = new Clustering<>("By Label Hierarchical Clustering", "bylabel-clustering");
- for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
+ for (DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
final Object val = relation.get(iditer);
- if(val == null) {
+ if (val == null) {
noiseids.add(iditer);
continue;
}
@@ -115,44 +115,41 @@ public class ByLabelHierarchicalClustering extends AbstractAlgorithm<Clustering<
assign(labelmap, label, iditer);
}
- ArrayList<Cluster<Model>> clusters = new ArrayList<Cluster<Model>>(labelmap.size());
- for(Entry<String, DBIDs> entry : labelmap.entrySet()) {
+ ArrayList<Cluster<Model>> clusters = new ArrayList<>(labelmap.size());
+ for (Entry<String, DBIDs> entry : labelmap.entrySet()) {
DBIDs ids = entry.getValue();
- if(ids instanceof DBID) {
+ if (ids instanceof DBID) {
noiseids.add((DBID) ids);
continue;
}
- Cluster<Model> clus = new Cluster<Model>(entry.getKey(), ids, ClusterModel.CLUSTER, new ArrayList<Cluster<Model>>(), new ArrayList<Cluster<Model>>());
+ Cluster<Model> clus = new Cluster<Model>(entry.getKey(), ids, ClusterModel.CLUSTER);
clusters.add(clus);
}
- for(Cluster<Model> cur : clusters) {
- for(Cluster<Model> oth : clusters) {
- if(oth != cur) {
- if(oth.getName().startsWith(cur.getName())) {
- oth.getParents().add(cur);
- cur.getChildren().add(oth);
- // System.err.println(oth.getLabel() + " is a child of " +
- // cur.getLabel());
+ for (Cluster<Model> cur : clusters) {
+ boolean isrootcluster = true;
+ for (Cluster<Model> oth : clusters) {
+ if (oth != cur) {
+ if (oth.getName().startsWith(cur.getName())) {
+ clustering.addChildCluster(oth, cur);
+ if (LOG.isDebuggingFiner()) {
+ LOG.debugFiner(oth.getName() + " is a child of " + cur.getName());
+ }
+ isrootcluster = false;
}
}
}
- }
- ArrayList<Cluster<Model>> rootclusters = new ArrayList<Cluster<Model>>();
- for(Cluster<Model> cur : clusters) {
- if(cur.getParents().size() == 0) {
- rootclusters.add(cur);
+ if (isrootcluster) {
+ clustering.addToplevelCluster(cur);
}
}
// Collected noise IDs.
- if(noiseids.size() > 0) {
+ if (noiseids.size() > 0) {
Cluster<Model> c = new Cluster<Model>("Noise", noiseids, ClusterModel.CLUSTER);
c.setNoise(true);
- rootclusters.add(c);
+ clustering.addToplevelCluster(c);
}
- assert (rootclusters.size() > 0) : "No clusters found by bylabel clustering. Empty database?";
-
- return new Clustering<Model>("By Label Hierarchical Clustering", "bylabel-clustering", rootclusters);
+ return clustering;
}
/**
@@ -163,21 +160,19 @@ public class ByLabelHierarchicalClustering extends AbstractAlgorithm<Clustering<
* @param id the id of the object to be assigned
*/
private void assign(HashMap<String, DBIDs> labelMap, String label, DBIDRef id) {
- if(labelMap.containsKey(label)) {
+ if (labelMap.containsKey(label)) {
DBIDs exist = labelMap.get(label);
- if(exist instanceof DBID) {
+ if (exist instanceof DBID) {
ModifiableDBIDs n = DBIDUtil.newHashSet();
n.add((DBID) exist);
n.add(id);
labelMap.put(label, n);
- }
- else {
+ } else {
assert (exist instanceof HashSetModifiableDBIDs);
assert (exist.size() > 1);
((ModifiableDBIDs) exist).add(id);
}
- }
- else {
+ } else {
labelMap.put(label, DBIDUtil.deref(id));
}
}
@@ -191,4 +186,4 @@ public class ByLabelHierarchicalClustering extends AbstractAlgorithm<Clustering<
protected Logging getLogger() {
return LOG;
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/ByLabelOrAllInOneClustering.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/ByLabelOrAllInOneClustering.java
index f082db9c..76b024a2 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/ByLabelOrAllInOneClustering.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/ByLabelOrAllInOneClustering.java
@@ -15,7 +15,7 @@ import de.lmu.ifi.dbs.elki.database.relation.Relation;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -66,9 +66,9 @@ public class ByLabelOrAllInOneClustering extends ByLabelClustering {
// Ignore.
}
final DBIDs ids = database.getRelation(TypeUtil.ANY).getDBIDs();
- Clustering<Model> result = new Clustering<Model>("All-in-one trivial Clustering", "allinone-clustering");
+ Clustering<Model> result = new Clustering<>("All-in-one trivial Clustering", "allinone-clustering");
Cluster<Model> c = new Cluster<Model>(ids, ClusterModel.CLUSTER);
- result.addCluster(c);
+ result.addToplevelCluster(c);
return result;
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/ByModelClustering.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/ByModelClustering.java
index 2114ac16..73ad9880 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/ByModelClustering.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/ByModelClustering.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.trivial;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -101,7 +101,7 @@ public class ByModelClustering extends AbstractAlgorithm<Clustering<Model>> impl
*/
public Clustering<Model> run(Relation<Model> relation) {
// Build model mapping
- HashMap<Model, ModifiableDBIDs> modelMap = new HashMap<Model, ModifiableDBIDs>();
+ HashMap<Model, ModifiableDBIDs> modelMap = new HashMap<>();
for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
Model model = relation.get(iditer);
ModifiableDBIDs modelids = modelMap.get(model);
@@ -112,16 +112,16 @@ public class ByModelClustering extends AbstractAlgorithm<Clustering<Model>> impl
modelids.add(iditer);
}
- Clustering<Model> result = new Clustering<Model>("By Model Clustering", "bymodel-clustering");
+ Clustering<Model> result = new Clustering<>("By Model Clustering", "bymodel-clustering");
for(Entry<Model, ModifiableDBIDs> entry : modelMap.entrySet()) {
final Model model = entry.getKey();
final ModifiableDBIDs ids = entry.getValue();
final String name = (model instanceof GeneratorInterface) ? ((GeneratorInterface) model).getName() : model.toString();
- Cluster<Model> c = new Cluster<Model>(name, ids, model);
+ Cluster<Model> c = new Cluster<>(name, ids, model);
if(noisepattern != null && noisepattern.matcher(name).find()) {
c.setNoise(true);
}
- result.addCluster(c);
+ result.addToplevelCluster(c);
}
return result;
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/TrivialAllInOne.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/TrivialAllInOne.java
index eaa5d2b2..dae50c25 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/TrivialAllInOne.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/TrivialAllInOne.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.trivial;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -63,9 +63,9 @@ public class TrivialAllInOne extends AbstractAlgorithm<Clustering<Model>> implem
public Clustering<Model> run(Relation<?> relation) {
final DBIDs ids = relation.getDBIDs();
- Clustering<Model> result = new Clustering<Model>("All-in-one trivial Clustering", "allinone-clustering");
+ Clustering<Model> result = new Clustering<>("All-in-one trivial Clustering", "allinone-clustering");
Cluster<Model> c = new Cluster<Model>(ids, ClusterModel.CLUSTER);
- result.addCluster(c);
+ result.addToplevelCluster(c);
return result;
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/TrivialAllNoise.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/TrivialAllNoise.java
index dd0f94a5..ecc7dbec 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/TrivialAllNoise.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/TrivialAllNoise.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.trivial;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -62,9 +62,9 @@ public class TrivialAllNoise extends AbstractAlgorithm<Clustering<Model>> implem
public Clustering<Model> run(Relation<?> relation) {
final DBIDs ids = relation.getDBIDs();
- Clustering<Model> result = new Clustering<Model>("All-in-noise trivial Clustering", "allinnoise-clustering");
+ Clustering<Model> result = new Clustering<>("All-in-noise trivial Clustering", "allinnoise-clustering");
Cluster<Model> c = new Cluster<Model>(ids, true, ClusterModel.CLUSTER);
- result.addCluster(c);
+ result.addToplevelCluster(c);
return result;
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/package-info.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/package-info.java
index 5870a736..6b7b50f5 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/package-info.java
@@ -7,7 +7,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/ABOD.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/ABOD.java
index d52a81fd..ad0b8175 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/ABOD.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/ABOD.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,7 +23,6 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.Collections;
import java.util.HashMap;
import de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm;
@@ -34,19 +33,21 @@ import de.lmu.ifi.dbs.elki.database.QueryUtil;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
+import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDRange;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDPair;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.distance.similarityfunction.PrimitiveSimilarityFunction;
import de.lmu.ifi.dbs.elki.distance.similarityfunction.kernel.KernelMatrix;
@@ -58,13 +59,13 @@ import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
import de.lmu.ifi.dbs.elki.result.outlier.InvertedOutlierScoreMeta;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierScoreMeta;
-import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.Heap;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.ComparableMaxHeap;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.ComparableMinHeap;
import de.lmu.ifi.dbs.elki.utilities.documentation.Description;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterEqualConstraint;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
@@ -139,7 +140,7 @@ public class ABOD<V extends NumberVector<?>> extends AbstractDistanceBasedAlgori
/**
* Static DBID map.
*/
- private ArrayModifiableDBIDs staticids = null;
+ private ArrayDBIDs staticids = null;
/**
* Actual constructor, with parameters. Fast mode (sampling).
@@ -178,11 +179,15 @@ public class ABOD<V extends NumberVector<?>> extends AbstractDistanceBasedAlgori
*/
public OutlierResult getRanking(Relation<V> relation) {
// Fix a static set of IDs
- staticids = DBIDUtil.newArray(relation.getDBIDs());
- staticids.sort();
+ if (relation.getDBIDs() instanceof DBIDRange) {
+ staticids = (DBIDRange) relation.getDBIDs();
+ } else {
+ staticids = DBIDUtil.newArray(relation.getDBIDs());
+ ((ArrayModifiableDBIDs) staticids).sort();
+ }
KernelMatrix kernelMatrix = new KernelMatrix(primitiveKernelFunction, relation, staticids);
- Heap<DoubleDBIDPair> pq = new Heap<DoubleDBIDPair>(relation.size(), Collections.reverseOrder());
+ ComparableMaxHeap<DoubleDBIDPair> pq = new ComparableMaxHeap<>(relation.size());
// preprocess kNN neighborhoods
KNNQuery<V, DoubleDistance> knnQuery = QueryUtil.getKNNQuery(relation, getDistanceFunction(), k);
@@ -191,7 +196,7 @@ public class ABOD<V extends NumberVector<?>> extends AbstractDistanceBasedAlgori
for (DBIDIter objKey = relation.iterDBIDs(); objKey.valid(); objKey.advance()) {
s.reset();
- KNNResult<DoubleDistance> neighbors = knnQuery.getKNNForDBID(objKey, k);
+ KNNList<DoubleDistance> neighbors = knnQuery.getKNNForDBID(objKey, k);
for (DBIDIter key1 = neighbors.iter(); key1.valid(); key1.advance()) {
for (DBIDIter key2 = neighbors.iter(); key2.valid(); key2.advance()) {
if (DBIDUtil.equal(key2, key1) || DBIDUtil.equal(key1, objKey) || DBIDUtil.equal(key2, objKey)) {
@@ -214,12 +219,13 @@ public class ABOD<V extends NumberVector<?>> extends AbstractDistanceBasedAlgori
DoubleMinMax minmaxabod = new DoubleMinMax();
WritableDoubleDataStore abodvalues = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC);
- for (DoubleDBIDPair pair : pq) {
+ while (!pq.isEmpty()) {
+ DoubleDBIDPair pair = pq.poll();
abodvalues.putDouble(pair, pair.doubleValue());
minmaxabod.put(pair.doubleValue());
}
// Build result representation.
- Relation<Double> scoreResult = new MaterializedRelation<Double>("Angle-based Outlier Degree", "abod-outlier", TypeUtil.DOUBLE, abodvalues, relation.getDBIDs());
+ Relation<Double> scoreResult = new MaterializedRelation<>("Angle-based Outlier Degree", "abod-outlier", TypeUtil.DOUBLE, abodvalues, relation.getDBIDs());
OutlierScoreMeta scoreMeta = new InvertedOutlierScoreMeta(minmaxabod.getMin(), minmaxabod.getMax(), 0.0, Double.POSITIVE_INFINITY);
return new OutlierResult(scoreMeta, scoreResult);
}
@@ -234,17 +240,21 @@ public class ABOD<V extends NumberVector<?>> extends AbstractDistanceBasedAlgori
final DBIDs ids = relation.getDBIDs();
// Fix a static set of IDs
// TODO: add a DBIDUtil.ensureSorted?
- staticids = DBIDUtil.newArray(ids);
- staticids.sort();
+ if (relation.getDBIDs() instanceof DBIDRange) {
+ staticids = (DBIDRange) relation.getDBIDs();
+ } else {
+ staticids = DBIDUtil.newArray(relation.getDBIDs());
+ ((ArrayModifiableDBIDs) staticids).sort();
+ }
KernelMatrix kernelMatrix = new KernelMatrix(primitiveKernelFunction, relation, staticids);
- Heap<DoubleDBIDPair> pq = new Heap<DoubleDBIDPair>(relation.size(), Collections.reverseOrder());
+ ComparableMaxHeap<DoubleDBIDPair> pq = new ComparableMaxHeap<>(relation.size());
// get Candidate Ranking
for (DBIDIter aKey = relation.iterDBIDs(); aKey.valid(); aKey.advance()) {
WritableDoubleDataStore dists = DataStoreUtil.makeDoubleStorage(ids, DataStoreFactory.HINT_TEMP | DataStoreFactory.HINT_HOT);
// determine kNearestNeighbors and pairwise distances
- Heap<DoubleDBIDPair> nn;
+ ComparableMinHeap<DoubleDBIDPair> nn;
if (!USE_RND_SAMPLE) {
nn = calcDistsandNN(relation, kernelMatrix, sampleSize, aKey, dists);
} else {
@@ -264,7 +274,7 @@ public class ABOD<V extends NumberVector<?>> extends AbstractDistanceBasedAlgori
pq.add(DBIDUtil.newPair(var, aKey));
}
// refine Candidates
- Heap<DoubleDBIDPair> resqueue = new Heap<DoubleDBIDPair>(k);
+ ComparableMinHeap<DoubleDBIDPair> resqueue = new ComparableMinHeap<>(k);
MeanVariance s = new MeanVariance();
while (!pq.isEmpty()) {
if (resqueue.size() == k && pq.peek().doubleValue() > resqueue.peek().doubleValue()) {
@@ -302,12 +312,13 @@ public class ABOD<V extends NumberVector<?>> extends AbstractDistanceBasedAlgori
}
DoubleMinMax minmaxabod = new DoubleMinMax();
WritableDoubleDataStore abodvalues = DataStoreUtil.makeDoubleStorage(ids, DataStoreFactory.HINT_STATIC);
- for (DoubleDBIDPair pair : pq) {
+ while (!pq.isEmpty()) {
+ DoubleDBIDPair pair = pq.poll();
abodvalues.putDouble(pair, pair.doubleValue());
minmaxabod.put(pair.doubleValue());
}
// Build result representation.
- Relation<Double> scoreResult = new MaterializedRelation<Double>("Angle-based Outlier Detection", "abod-outlier", TypeUtil.DOUBLE, abodvalues, ids);
+ Relation<Double> scoreResult = new MaterializedRelation<>("Angle-based Outlier Detection", "abod-outlier", TypeUtil.DOUBLE, abodvalues, ids);
OutlierScoreMeta scoreMeta = new InvertedOutlierScoreMeta(minmaxabod.getMin(), minmaxabod.getMax(), 0.0, Double.POSITIVE_INFINITY);
return new OutlierResult(scoreMeta, scoreResult);
}
@@ -404,8 +415,8 @@ public class ABOD<V extends NumberVector<?>> extends AbstractDistanceBasedAlgori
return (kernelMatrix.getDistance(ai, ai) + kernelMatrix.getDistance(bi, ci) - kernelMatrix.getDistance(ai, ci) - kernelMatrix.getDistance(ai, bi));
}
- private Heap<DoubleDBIDPair> calcDistsandNN(Relation<V> data, KernelMatrix kernelMatrix, int sampleSize, DBIDRef aKey, WritableDoubleDataStore dists) {
- Heap<DoubleDBIDPair> nn = new Heap<DoubleDBIDPair>(sampleSize);
+ private ComparableMinHeap<DoubleDBIDPair> calcDistsandNN(Relation<V> data, KernelMatrix kernelMatrix, int sampleSize, DBIDRef aKey, WritableDoubleDataStore dists) {
+ ComparableMinHeap<DoubleDBIDPair> nn = new ComparableMinHeap<>(sampleSize);
for (DBIDIter bKey = data.iterDBIDs(); bKey.valid(); bKey.advance()) {
double val = calcCos(kernelMatrix, aKey, bKey);
dists.putDouble(bKey, val);
@@ -420,8 +431,8 @@ public class ABOD<V extends NumberVector<?>> extends AbstractDistanceBasedAlgori
return nn;
}
- private Heap<DoubleDBIDPair> calcDistsandRNDSample(Relation<V> data, KernelMatrix kernelMatrix, int sampleSize, DBIDRef aKey, WritableDoubleDataStore dists) {
- Heap<DoubleDBIDPair> nn = new Heap<DoubleDBIDPair>(sampleSize);
+ private ComparableMinHeap<DoubleDBIDPair> calcDistsandRNDSample(Relation<V> data, KernelMatrix kernelMatrix, int sampleSize, DBIDRef aKey, WritableDoubleDataStore dists) {
+ ComparableMinHeap<DoubleDBIDPair> nn = new ComparableMinHeap<>(sampleSize);
int step = (int) ((double) data.size() / (double) sampleSize);
int counter = 0;
for (DBIDIter bKey = data.iterDBIDs(); bKey.valid(); bKey.advance()) {
@@ -445,14 +456,14 @@ public class ABOD<V extends NumberVector<?>> extends AbstractDistanceBasedAlgori
public String getExplanations(Relation<V> data) {
KernelMatrix kernelMatrix = new KernelMatrix(primitiveKernelFunction, data, staticids);
// PQ for Outlier Ranking
- Heap<DoubleDBIDPair> pq = new Heap<DoubleDBIDPair>(data.size(), Collections.reverseOrder());
- HashMap<DBID, DBIDs> explaintab = new HashMap<DBID, DBIDs>();
+ ComparableMaxHeap<DoubleDBIDPair> pq = new ComparableMaxHeap<>(data.size());
+ HashMap<DBID, DBIDs> explaintab = new HashMap<>();
// test all objects
MeanVariance s = new MeanVariance(), s2 = new MeanVariance();
for (DBIDIter objKey = data.iterDBIDs(); objKey.valid(); objKey.advance()) {
s.reset();
// Queue for the best explanation
- Heap<DoubleDBIDPair> explain = new Heap<DoubleDBIDPair>();
+ ComparableMinHeap<DoubleDBIDPair> explain = new ComparableMinHeap<>();
// determine Object
// for each pair of other objects
for (DBIDIter key1 = data.iterDBIDs(); key1.valid(); key1.advance()) {
@@ -591,7 +602,7 @@ public class ABOD<V extends NumberVector<?>> extends AbstractDistanceBasedAlgori
if (config.grab(sampleSizeP)) {
sampleSize = sampleSizeP.getValue();
}
- final ObjectParameter<PrimitiveSimilarityFunction<V, DoubleDistance>> param = new ObjectParameter<PrimitiveSimilarityFunction<V, DoubleDistance>>(KERNEL_FUNCTION_ID, PrimitiveSimilarityFunction.class, PolynomialKernelFunction.class);
+ final ObjectParameter<PrimitiveSimilarityFunction<V, DoubleDistance>> param = new ObjectParameter<>(KERNEL_FUNCTION_ID, PrimitiveSimilarityFunction.class, PolynomialKernelFunction.class);
if (config.grab(param)) {
primitiveKernelFunction = param.instantiateClass(config);
}
@@ -599,7 +610,7 @@ public class ABOD<V extends NumberVector<?>> extends AbstractDistanceBasedAlgori
@Override
protected ABOD<V> makeInstance() {
- return new ABOD<V>(k, sampleSize, primitiveKernelFunction, distanceFunction);
+ return new ABOD<>(k, sampleSize, primitiveKernelFunction, distanceFunction);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/AbstractAggarwalYuOutlier.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/AbstractAggarwalYuOutlier.java
index 2a4885dc..99356aef 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/AbstractAggarwalYuOutlier.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/AbstractAggarwalYuOutlier.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -109,12 +109,12 @@ public abstract class AbstractAggarwalYuOutlier<V extends NumberVector<?>> exten
final int dim = RelationUtil.dimensionality(relation);
final int size = relation.size();
final DBIDs allids = relation.getDBIDs();
- final ArrayList<ArrayList<DBIDs>> ranges = new ArrayList<ArrayList<DBIDs>>();
+ final ArrayList<ArrayList<DBIDs>> ranges = new ArrayList<>();
// Temporary projection storage of the database
- final ArrayList<ArrayList<DoubleDBIDPair>> dbAxis = new ArrayList<ArrayList<DoubleDBIDPair>>(dim);
+ final ArrayList<ArrayList<DoubleDBIDPair>> dbAxis = new ArrayList<>(dim);
for(int i = 0; i < dim; i++) {
- ArrayList<DoubleDBIDPair> axis = new ArrayList<DoubleDBIDPair>(size);
+ ArrayList<DoubleDBIDPair> axis = new ArrayList<>(size);
dbAxis.add(i, axis);
}
// Project
@@ -129,7 +129,7 @@ public abstract class AbstractAggarwalYuOutlier<V extends NumberVector<?>> exten
for(int d = 0; d < dim; d++) {
ArrayList<DoubleDBIDPair> axis = dbAxis.get(d);
Collections.sort(axis);
- ArrayList<DBIDs> dimranges = new ArrayList<DBIDs>(phi + 1);
+ ArrayList<DBIDs> dimranges = new ArrayList<>(phi + 1);
dimranges.add(allids);
int start = 0;
for(int r = 0; r < phi; r++) {
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/AbstractDBOutlier.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/AbstractDBOutlier.java
index 0e6f502a..5cafe04d 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/AbstractDBOutlier.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/AbstractDBOutlier.java
@@ -86,7 +86,7 @@ public abstract class AbstractDBOutlier<O, D extends Distance<D>> extends Abstra
DoubleDataStore dbodscore = computeOutlierScores(database, relation, d);
// Build result representation.
- Relation<Double> scoreResult = new MaterializedRelation<Double>("Density-Based Outlier Detection", "db-outlier", TypeUtil.DOUBLE, dbodscore, relation.getDBIDs());
+ Relation<Double> scoreResult = new MaterializedRelation<>("Density-Based Outlier Detection", "db-outlier", TypeUtil.DOUBLE, dbodscore, relation.getDBIDs());
OutlierScoreMeta scoreMeta = new ProbabilisticOutlierScore();
return new OutlierResult(scoreMeta, scoreResult);
}
@@ -132,7 +132,7 @@ public abstract class AbstractDBOutlier<O, D extends Distance<D>> extends Abstra
*/
protected void configD(Parameterization config, DistanceFunction<?, D> distanceFunction) {
final D distanceFactory = (distanceFunction != null) ? distanceFunction.getDistanceFactory() : null;
- final DistanceParameter<D> param = new DistanceParameter<D>(D_ID, distanceFactory);
+ final DistanceParameter<D> param = new DistanceParameter<>(D_ID, distanceFactory);
if(config.grab(param)) {
d = param.getValue();
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/AggarwalYuEvolutionary.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/AggarwalYuEvolutionary.java
index c263cdfa..89be0e66 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/AggarwalYuEvolutionary.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/AggarwalYuEvolutionary.java
@@ -49,6 +49,7 @@ import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierScoreMeta;
import de.lmu.ifi.dbs.elki.utilities.FormatUtil;
import de.lmu.ifi.dbs.elki.utilities.RandomFactory;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.Heap;
import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.TopBoundedHeap;
import de.lmu.ifi.dbs.elki.utilities.documentation.Description;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
@@ -131,30 +132,30 @@ public class AggarwalYuEvolutionary<V extends NumberVector<?>> extends AbstractA
final int dbsize = relation.size();
ArrayList<ArrayList<DBIDs>> ranges = buildRanges(relation);
- Iterable<Individuum> individuums = (new EvolutionarySearch(relation, ranges, m, rnd.getRandom())).run();
+ Heap<Individuum>.UnorderedIter individuums = (new EvolutionarySearch(relation, ranges, m, rnd.getRandom())).run();
WritableDoubleDataStore outlierScore = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_STATIC);
- for(Individuum ind : individuums) {
- DBIDs ids = computeSubspaceForGene(ind.getGene(), ranges);
+ for (; individuums.valid(); individuums.advance()) {
+ DBIDs ids = computeSubspaceForGene(individuums.get().getGene(), ranges);
double sparsityC = sparsity(ids.size(), dbsize, k, phi);
for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
double prev = outlierScore.doubleValue(iter);
- if(Double.isNaN(prev) || sparsityC < prev) {
+ if (Double.isNaN(prev) || sparsityC < prev) {
outlierScore.putDouble(iter, sparsityC);
}
}
}
DoubleMinMax minmax = new DoubleMinMax();
- for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
+ for (DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
double val = outlierScore.doubleValue(iditer);
- if(Double.isNaN(val)) {
+ if (Double.isNaN(val)) {
outlierScore.putDouble(iditer, 0.0);
val = 0.0;
}
minmax.put(val);
}
- Relation<Double> scoreResult = new MaterializedRelation<Double>("AggarwalYuEvolutionary", "aggarwal-yu-outlier", TypeUtil.DOUBLE, outlierScore, relation.getDBIDs());
+ Relation<Double> scoreResult = new MaterializedRelation<>("AggarwalYuEvolutionary", "aggarwal-yu-outlier", TypeUtil.DOUBLE, outlierScore, relation.getDBIDs());
OutlierScoreMeta meta = new InvertedOutlierScoreMeta(minmax.getMin(), minmax.getMax(), Double.NEGATIVE_INFINITY, 0.0);
return new OutlierResult(meta, scoreResult);
}
@@ -214,16 +215,16 @@ public class AggarwalYuEvolutionary<V extends NumberVector<?>> extends AbstractA
this.random = random;
}
- public Iterable<Individuum> run() {
+ public Heap<Individuum>.UnorderedIter run() {
ArrayList<Individuum> pop = initialPopulation(m);
// best Population
- TopBoundedHeap<Individuum> bestSol = new TopBoundedHeap<Individuum>(m, Collections.reverseOrder());
+ TopBoundedHeap<Individuum> bestSol = new TopBoundedHeap<>(m, Collections.reverseOrder());
for (Individuum ind : pop) {
bestSol.add(ind);
}
int iterations = 0;
- while(!checkConvergence(pop)) {
+ while (!checkConvergence(pop)) {
Collections.sort(pop);
pop = rouletteRankSelection(pop);
// Crossover
@@ -231,33 +232,33 @@ public class AggarwalYuEvolutionary<V extends NumberVector<?>> extends AbstractA
// Mutation with probability 0.25 , 0.25
pop = mutation(pop, 0.5, 0.5);
// Avoid duplicates
- ind: for(Individuum ind : pop) {
- for (Individuum b : bestSol) {
- if (b.equals(ind)) {
+ ind: for (Individuum ind : pop) {
+ for (Heap<Individuum>.UnorderedIter it = bestSol.unorderedIter(); it.valid(); it.advance()) {
+ if (it.get().equals(ind)) {
continue ind;
}
}
bestSol.add(ind);
}
- if(LOG.isDebuggingFinest()) {
+ if (LOG.isDebuggingFinest()) {
StringBuilder buf = new StringBuilder();
buf.append("Top solutions:\n");
- for(Individuum ind : bestSol) {
- buf.append(ind.toString()).append('\n');
+ for (Heap<Individuum>.UnorderedIter it = bestSol.unorderedIter(); it.valid(); it.advance()) {
+ buf.append(it.get().toString()).append('\n');
}
buf.append("Population:\n");
- for(Individuum ind : pop) {
+ for (Individuum ind : pop) {
buf.append(ind.toString()).append('\n');
}
LOG.debugFinest(buf.toString());
}
iterations++;
- if(iterations > MAX_ITERATIONS) {
+ if (iterations > MAX_ITERATIONS) {
LOG.warning("Maximum iterations reached.");
break;
}
}
- return bestSol;
+ return bestSol.unorderedIter();
}
/**
@@ -267,18 +268,18 @@ public class AggarwalYuEvolutionary<V extends NumberVector<?>> extends AbstractA
* @return Convergence
*/
private boolean checkConvergence(Collection<Individuum> pop) {
- if(pop.size() == 0) {
+ if (pop.size() == 0) {
return true;
}
// Gene occurrence counter
int[][] occur = new int[dim][phi + 1];
// Count gene occurrences
- for(Individuum ind : pop) {
+ for (Individuum ind : pop) {
int[] gene = ind.getGene();
- for(int d = 0; d < dim; d++) {
+ for (int d = 0; d < dim; d++) {
int val = gene[d] + DONT_CARE;
- if(val < 0 || val >= phi + 1) {
+ if (val < 0 || val >= phi + 1) {
LOG.warning("Invalid gene value encountered: " + val + " in " + ind.toString());
continue;
}
@@ -287,20 +288,20 @@ public class AggarwalYuEvolutionary<V extends NumberVector<?>> extends AbstractA
}
int conv = (int) (pop.size() * 0.95);
- if(LOG.isDebuggingFine()) {
+ if (LOG.isDebuggingFine()) {
LOG.debugFine("Convergence at " + conv + " of " + pop.size() + " individuums.");
}
- for(int d = 0; d < dim; d++) {
+ for (int d = 0; d < dim; d++) {
boolean converged = false;
- for(int val = 0; val < phi + 1; val++) {
- if(occur[d][val] >= conv) {
+ for (int val = 0; val < phi + 1; val++) {
+ if (occur[d][val] >= conv) {
converged = true;
break;
}
}
// A single failure to converge is sufficient to continue.
- if(!converged) {
+ if (!converged) {
return false;
}
}
@@ -315,21 +316,21 @@ public class AggarwalYuEvolutionary<V extends NumberVector<?>> extends AbstractA
*/
private ArrayList<Individuum> initialPopulation(int popsize) {
// Initial Population
- ArrayList<Individuum> population = new ArrayList<Individuum>(popsize);
+ ArrayList<Individuum> population = new ArrayList<>(popsize);
// fill population
- for(int i = 0; i < popsize; i++) {
+ for (int i = 0; i < popsize; i++) {
// Random Individual
int[] gene = new int[dim];
// fill don't care ( any dimension == don't care)
- for(int j = 0; j < dim; j++) {
+ for (int j = 0; j < dim; j++) {
gene[j] = DONT_CARE;
}
// count of don't care positions
int countDim = k;
// fill non don't care positions of the Individual
- while(countDim > 0) {
+ while (countDim > 0) {
int z = random.nextInt(dim);
- if(gene[z] == DONT_CARE) {
+ if (gene[z] == DONT_CARE) {
gene[z] = random.nextInt(phi) + 1;
countDim--;
}
@@ -357,24 +358,23 @@ public class AggarwalYuEvolutionary<V extends NumberVector<?>> extends AbstractA
// Relative weight := popsize - position => sum(1..popsize)
int totalweight = (popsize * (popsize + 1)) >> 1;
// Survivors
- ArrayList<Individuum> survivors = new ArrayList<Individuum>(popsize);
+ ArrayList<Individuum> survivors = new ArrayList<>(popsize);
// position of selection
- for(int i = 0; i < popsize; i++) {
+ for (int i = 0; i < popsize; i++) {
int z = random.nextInt(totalweight);
- for(int j = 0; j < popsize; j++) {
- if(z < popsize - j) {
+ for (int j = 0; j < popsize; j++) {
+ if (z < popsize - j) {
// TODO: need clone?
survivors.add(population.get(j));
break;
- }
- else {
+ } else {
// decrement
z -= (popsize - j);
}
}
}
- if(survivors.size() != popsize) {
+ if (survivors.size() != popsize) {
throw new AbortException("Selection step failed - implementation error?");
}
// Don't sort, to avoid biasing the crossover!
@@ -387,31 +387,30 @@ public class AggarwalYuEvolutionary<V extends NumberVector<?>> extends AbstractA
*/
private ArrayList<Individuum> mutation(ArrayList<Individuum> population, double perc1, double perc2) {
// the Mutations
- ArrayList<Individuum> mutations = new ArrayList<Individuum>();
+ ArrayList<Individuum> mutations = new ArrayList<>();
// Set of Positions which are don't care in the String
- TreeSet<Integer> Q = new TreeSet<Integer>();
+ TreeSet<Integer> Q = new TreeSet<>();
// Set of Positions which are not don't care in the String
- TreeSet<Integer> R = new TreeSet<Integer>();
+ TreeSet<Integer> R = new TreeSet<>();
// for each individuum
- for(int j = 0; j < population.size(); j++) {
+ for (int j = 0; j < population.size(); j++) {
// clear the Sets
Q.clear();
R.clear();
// Fill the Sets with the Positions
- for(int i = 0; i < dim; i++) {
- if(population.get(j).getGene()[i] == DONT_CARE) {
+ for (int i = 0; i < dim; i++) {
+ if (population.get(j).getGene()[i] == DONT_CARE) {
Q.add(i);
- }
- else {
+ } else {
R.add(i);
}
}
//
double r1 = random.nextDouble();
- if(Q.size() != 0) {
+ if (Q.size() != 0) {
// Mutation Variant 1
- if(r1 <= perc1) {
+ if (r1 <= perc1) {
// calc Mutation Spot
Integer[] pos = new Integer[Q.size()];
pos = Q.toArray(pos);
@@ -436,7 +435,7 @@ public class AggarwalYuEvolutionary<V extends NumberVector<?>> extends AbstractA
}
r1 = random.nextDouble();
// Mutation Variant 2
- if(r1 <= perc2) {
+ if (r1 <= perc2) {
// calc Mutation Spot
Integer[] pos = new Integer[R.size()];
pos = R.toArray(pos);
@@ -470,16 +469,16 @@ public class AggarwalYuEvolutionary<V extends NumberVector<?>> extends AbstractA
*/
private ArrayList<Individuum> crossoverOptimized(ArrayList<Individuum> population) {
// Crossover Set of population Set
- ArrayList<Individuum> crossover = new ArrayList<Individuum>();
+ ArrayList<Individuum> crossover = new ArrayList<>();
- for(int i = 0; i < population.size() - 1; i += 2) {
+ for (int i = 0; i < population.size() - 1; i += 2) {
Pair<Individuum, Individuum> recombine = recombineOptimized(population.get(i), population.get(i + 1));
// add the Solutions to the new Set
crossover.add(recombine.getFirst());
crossover.add(recombine.getSecond());
}
// if the set contains an odd number of Subspaces, retain the last one
- if(population.size() % 2 == 1) {
+ if (population.size() % 2 == 1) {
crossover.add(population.get(population.size() - 1));
}
// Collections.sort(crossover);
@@ -496,18 +495,18 @@ public class AggarwalYuEvolutionary<V extends NumberVector<?>> extends AbstractA
private Pair<Individuum, Individuum> recombineOptimized(Individuum parent1, Individuum parent2) {
Pair<Individuum, Individuum> recombinePair;
// Set of Positions in which either s1 or s2 are don't care
- ArrayList<Integer> Q = new ArrayList<Integer>(dim);
+ ArrayList<Integer> Q = new ArrayList<>(dim);
// Set of Positions in which neither s1 or s2 is don't care
- ArrayList<Integer> R = new ArrayList<Integer>(dim);
+ ArrayList<Integer> R = new ArrayList<>(dim);
- for(int i = 0; i < dim; i++) {
- if((parent1.getGene()[i] == DONT_CARE) && (parent2.getGene()[i] != DONT_CARE)) {
+ for (int i = 0; i < dim; i++) {
+ if ((parent1.getGene()[i] == DONT_CARE) && (parent2.getGene()[i] != DONT_CARE)) {
Q.add(i);
}
- if((parent1.getGene()[i] != DONT_CARE) && (parent2.getGene()[i] == DONT_CARE)) {
+ if ((parent1.getGene()[i] != DONT_CARE) && (parent2.getGene()[i] == DONT_CARE)) {
Q.add(i);
}
- if((parent1.getGene()[i] != DONT_CARE) && (parent2.getGene()[i] != DONT_CARE)) {
+ if ((parent1.getGene()[i] != DONT_CARE) && (parent2.getGene()[i] != DONT_CARE)) {
R.add(i);
}
}
@@ -519,11 +518,11 @@ public class AggarwalYuEvolutionary<V extends NumberVector<?>> extends AbstractA
int count = k - R.size();
Iterator<Integer> q = Q.iterator();
- while(count > 0) {
+ while (count > 0) {
int[] l1 = b.clone();
int[] l2 = b.clone();
- while(q.hasNext()) {
+ while (q.hasNext()) {
int next = q.next();
// pos = next;
@@ -537,15 +536,14 @@ public class AggarwalYuEvolutionary<V extends NumberVector<?>> extends AbstractA
final double sparsityL1 = sparsity(computeSubspaceForGene(l1, ranges).size(), dbsize, k, phi);
final double sparsityL2 = sparsity(computeSubspaceForGene(l2, ranges).size(), dbsize, k, phi);
- if(sparsityL1 <= sparsityL2) {
+ if (sparsityL1 <= sparsityL2) {
b = l1.clone();
- if(s1Null) {
+ if (s1Null) {
count--;
}
- }
- else {
+ } else {
b = l2.clone();
- if(s2Null) {
+ if (s2Null) {
count--;
}
}
@@ -557,17 +555,16 @@ public class AggarwalYuEvolutionary<V extends NumberVector<?>> extends AbstractA
// create the complementary String
int[] comp = new int[dim];
- for(int i = 0; i < dim; i++) {
- if(b[i] == parent1.getGene()[i]) {
+ for (int i = 0; i < dim; i++) {
+ if (b[i] == parent1.getGene()[i]) {
comp[i] = parent2.getGene()[i];
- }
- else {
+ } else {
comp[i] = parent2.getGene()[i];
}
}
final Individuum i1 = makeIndividuum(b);
final Individuum i2 = makeIndividuum(comp);
- recombinePair = new Pair<Individuum, Individuum>(i1, i2);
+ recombinePair = new Pair<>(i1, i2);
return recombinePair;
}
@@ -584,7 +581,7 @@ public class AggarwalYuEvolutionary<V extends NumberVector<?>> extends AbstractA
* @return best gene combination
*/
private Individuum combineRecursive(ArrayList<Integer> r, int i, int[] current, Individuum parent1, Individuum parent2) {
- if(i == r.size()) {
+ if (i == r.size()) {
return makeIndividuum(current);
}
// Position to modify
@@ -597,10 +594,9 @@ public class AggarwalYuEvolutionary<V extends NumberVector<?>> extends AbstractA
Individuum i1 = combineRecursive(r, i + 1, gene1, parent1, parent2);
Individuum i2 = combineRecursive(r, i + 1, gene2, parent1, parent2);
// Return the better result.
- if(i1.getFitness() < i2.getFitness()) {
+ if (i1.getFitness() < i2.getFitness()) {
return i1;
- }
- else {
+ } else {
return i2;
}
}
@@ -610,8 +606,8 @@ public class AggarwalYuEvolutionary<V extends NumberVector<?>> extends AbstractA
* Individuum for the evolutionary search.
*
* @author Erich Schubert
- *
- * @apiviz.exclude de.lmu.ifi.dbs.elki.utilities.pairs.FCPair
+ *
+ * @apiviz.exclude de.lmu.ifi.dbs.elki.utilities.pairs.FCPair
*/
private static class Individuum extends FCPair<Double, int[]> {
/**
@@ -661,15 +657,15 @@ public class AggarwalYuEvolutionary<V extends NumberVector<?>> extends AbstractA
@Override
public boolean equals(Object obj) {
- if(!(obj instanceof Individuum)) {
+ if (!(obj instanceof Individuum)) {
return false;
}
Individuum other = (Individuum) obj;
- if(other.second.length != this.second.length) {
+ if (other.second.length != this.second.length) {
return false;
}
- for(int i = 0; i < this.second.length; i++) {
- if(other.second[i] != this.second[i]) {
+ for (int i = 0; i < this.second.length; i++) {
+ if (other.second[i] != this.second[i]) {
return false;
}
}
@@ -708,18 +704,18 @@ public class AggarwalYuEvolutionary<V extends NumberVector<?>> extends AbstractA
super.makeOptions(config);
final IntParameter mP = new IntParameter(M_ID);
mP.addConstraint(new GreaterEqualConstraint(2));
- if(config.grab(mP)) {
+ if (config.grab(mP)) {
m = mP.getValue();
}
final RandomParameter rndP = new RandomParameter(SEED_ID);
- if(config.grab(rndP)) {
+ if (config.grab(rndP)) {
rnd = rndP.getValue();
}
}
@Override
protected AggarwalYuEvolutionary<V> makeInstance() {
- return new AggarwalYuEvolutionary<V>(k, phi, m, rnd);
+ return new AggarwalYuEvolutionary<>(k, phi, m, rnd);
}
}
-}
+}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/AggarwalYuNaive.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/AggarwalYuNaive.java
index 9cd7d79f..1816c3a3 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/AggarwalYuNaive.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/AggarwalYuNaive.java
@@ -102,15 +102,15 @@ public class AggarwalYuNaive<V extends NumberVector<?>> extends AbstractAggarwal
// Build a list of all subspaces
{
// R1 initial one-dimensional subspaces.
- Rk = new ArrayList<ArrayList<IntIntPair>>();
+ Rk = new ArrayList<>();
// Set of all dim*phi ranges
- ArrayList<IntIntPair> q = new ArrayList<IntIntPair>();
+ ArrayList<IntIntPair> q = new ArrayList<>();
for(int i = 0; i < dimensionality; i++) {
for(int j = 1; j <= phi; j++) {
IntIntPair s = new IntIntPair(i, j);
q.add(s);
// Add to first Rk
- ArrayList<IntIntPair> v = new ArrayList<IntIntPair>();
+ ArrayList<IntIntPair> v = new ArrayList<>();
v.add(s);
Rk.add(v);
}
@@ -118,7 +118,7 @@ public class AggarwalYuNaive<V extends NumberVector<?>> extends AbstractAggarwal
// build Ri
for(int i = 2; i <= k; i++) {
- ArrayList<ArrayList<IntIntPair>> Rnew = new ArrayList<ArrayList<IntIntPair>>();
+ ArrayList<ArrayList<IntIntPair>> Rnew = new ArrayList<>();
for(int j = 0; j < Rk.size(); j++) {
ArrayList<IntIntPair> c = Rk.get(j);
@@ -131,7 +131,7 @@ public class AggarwalYuNaive<V extends NumberVector<?>> extends AbstractAggarwal
}
}
if(!invalid) {
- ArrayList<IntIntPair> neu = new ArrayList<IntIntPair>(c);
+ ArrayList<IntIntPair> neu = new ArrayList<>(c);
neu.add(pair);
Rnew.add(neu);
}
@@ -165,7 +165,7 @@ public class AggarwalYuNaive<V extends NumberVector<?>> extends AbstractAggarwal
}
minmax.put(val);
}
- Relation<Double> scoreResult = new MaterializedRelation<Double>("AggarwalYuNaive", "aggarwal-yu-outlier", TypeUtil.DOUBLE, sparsity, relation.getDBIDs());
+ Relation<Double> scoreResult = new MaterializedRelation<>("AggarwalYuNaive", "aggarwal-yu-outlier", TypeUtil.DOUBLE, sparsity, relation.getDBIDs());
OutlierScoreMeta meta = new InvertedOutlierScoreMeta(minmax.getMin(), minmax.getMax(), Double.NEGATIVE_INFINITY, 0.0);
return new OutlierResult(meta, scoreResult);
}
@@ -185,7 +185,7 @@ public class AggarwalYuNaive<V extends NumberVector<?>> extends AbstractAggarwal
public static class Parameterizer<V extends NumberVector<?>> extends AbstractAggarwalYuOutlier.Parameterizer {
@Override
protected AggarwalYuNaive<V> makeInstance() {
- return new AggarwalYuNaive<V>(k, phi);
+ return new AggarwalYuNaive<>(k, phi);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/COP.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/COP.java
index ac544b7f..06168c5a 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/COP.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/COP.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -39,12 +39,12 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.database.relation.RelationUtil;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
@@ -54,10 +54,11 @@ import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
import de.lmu.ifi.dbs.elki.math.linearalgebra.pca.PCAResult;
import de.lmu.ifi.dbs.elki.math.linearalgebra.pca.PCARunner;
import de.lmu.ifi.dbs.elki.math.statistics.distribution.ChiSquaredDistribution;
-import de.lmu.ifi.dbs.elki.math.statistics.distribution.GammaDistribution;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.GammaChoiWetteEstimator;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierScoreMeta;
import de.lmu.ifi.dbs.elki.result.outlier.ProbabilisticOutlierScore;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
@@ -108,6 +109,53 @@ public class COP<V extends NumberVector<?>, D extends NumberDistance<D, ?>> exte
public static final String COP_ERRORVEC = "cop-errorvec";
/**
+ * A clone of
+ * {@link de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.DoubleArrayAdapter}
+ * that only uses the first 85% of the array!
+ */
+ private static final NumberArrayAdapter<Double, double[]> SHORTENED_ARRAY = new NumberArrayAdapter<Double, double[]>() {
+ @Override
+ public int size(double[] array) {
+ return (int) (.85 * array.length);
+ }
+
+ @Override
+ public Double get(double[] array, int off) throws IndexOutOfBoundsException {
+ return Double.valueOf(array[off]);
+ }
+
+ @Override
+ public double getDouble(double[] array, int off) throws IndexOutOfBoundsException {
+ return array[off];
+ }
+
+ @Override
+ public float getFloat(double[] array, int off) throws IndexOutOfBoundsException {
+ return (float) array[off];
+ }
+
+ @Override
+ public int getInteger(double[] array, int off) throws IndexOutOfBoundsException {
+ return (int) array[off];
+ }
+
+ @Override
+ public short getShort(double[] array, int off) throws IndexOutOfBoundsException {
+ return (short) array[off];
+ }
+
+ @Override
+ public long getLong(double[] array, int off) throws IndexOutOfBoundsException {
+ return (long) array[off];
+ }
+
+ @Override
+ public byte getByte(double[] array, int off) throws IndexOutOfBoundsException {
+ return (byte) array[off];
+ }
+ };
+
+ /**
* Number of neighbors to be considered.
*/
int k;
@@ -184,7 +232,7 @@ public class COP<V extends NumberVector<?>, D extends NumberDistance<D, ?>> exte
FiniteProgress prog = LOG.isVerbose() ? new FiniteProgress("Correlation Outlier Probabilities", relation.size(), LOG) : null;
for (DBIDIter id = ids.iter(); id.valid(); id.advance()) {
- KNNResult<D> neighbors = knnQuery.getKNNForDBID(id, k + 1);
+ KNNList<D> neighbors = knnQuery.getKNNForDBID(id, k + 1);
ModifiableDBIDs nids = DBIDUtil.newHashSet(neighbors);
nids.remove(id); // Do not use query object
@@ -241,7 +289,7 @@ public class COP<V extends NumberVector<?>, D extends NumberDistance<D, ?>> exte
// Sort, so we can trim the top 15% below.
Arrays.sort(dists[d]);
// Evaluate
- double score = 1 - GammaDistribution.estimate(dists[d], (int) (.85 * dists[d].length)).cdf(sqdevs);
+ double score = 1 - GammaChoiWetteEstimator.STATIC.estimate(dists[d], SHORTENED_ARRAY).cdf(sqdevs);
if (score < min) {
min = score;
vdim = d + 1;
@@ -271,11 +319,11 @@ public class COP<V extends NumberVector<?>, D extends NumberDistance<D, ?>> exte
}
// combine results.
- Relation<Double> scoreResult = new MaterializedRelation<Double>("Correlation Outlier Probabilities", COP_SCORES, TypeUtil.DOUBLE, cop_score, ids);
+ Relation<Double> scoreResult = new MaterializedRelation<>("Correlation Outlier Probabilities", COP_SCORES, TypeUtil.DOUBLE, cop_score, ids);
OutlierScoreMeta scoreMeta = new ProbabilisticOutlierScore();
OutlierResult result = new OutlierResult(scoreMeta, scoreResult);
- result.addChildResult(new MaterializedRelation<Integer>("Local Dimensionality", COP_DIM, TypeUtil.INTEGER, cop_dim, ids));
- result.addChildResult(new MaterializedRelation<Vector>("Error vectors", COP_ERRORVEC, TypeUtil.VECTOR, cop_err_v, ids));
+ result.addChildResult(new MaterializedRelation<>("Local Dimensionality", COP_DIM, TypeUtil.INTEGER, cop_dim, ids));
+ result.addChildResult(new MaterializedRelation<>("Error vectors", COP_ERRORVEC, TypeUtil.VECTOR, cop_err_v, ids));
return result;
}
@@ -361,7 +409,7 @@ public class COP<V extends NumberVector<?>, D extends NumberDistance<D, ?>> exte
if (config.grab(kP)) {
k = kP.intValue();
}
- EnumParameter<DistanceDist> distP = new EnumParameter<DistanceDist>(DIST_ID, DistanceDist.class, DistanceDist.GAMMA);
+ EnumParameter<DistanceDist> distP = new EnumParameter<>(DIST_ID, DistanceDist.class, DistanceDist.GAMMA);
if (config.grab(distP)) {
dist = distP.getValue();
}
@@ -371,7 +419,7 @@ public class COP<V extends NumberVector<?>, D extends NumberDistance<D, ?>> exte
if (config.grab(expectP)) {
expect = expectP.doubleValue();
}
- ObjectParameter<PCARunner<V>> pcaP = new ObjectParameter<PCARunner<V>>(PCARUNNER_ID, PCARunner.class, PCARunner.class);
+ ObjectParameter<PCARunner<V>> pcaP = new ObjectParameter<>(PCARUNNER_ID, PCARunner.class, PCARunner.class);
if (config.grab(pcaP)) {
pca = pcaP.instantiateClass(config);
}
@@ -379,7 +427,7 @@ public class COP<V extends NumberVector<?>, D extends NumberDistance<D, ?>> exte
@Override
protected COP<V, D> makeInstance() {
- return new COP<V, D>(distanceFunction, k, pca, expect, dist);
+ return new COP<>(distanceFunction, k, pca, expect, dist);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/DBOutlierDetection.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/DBOutlierDetection.java
index ba1fd841..4f4d12bf 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/DBOutlierDetection.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/DBOutlierDetection.java
@@ -29,12 +29,12 @@ import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
import de.lmu.ifi.dbs.elki.database.datastore.DoubleDataStore;
import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
@@ -117,7 +117,7 @@ public class DBOutlierDetection<O, D extends Distance<D>> extends AbstractDBOutl
if(knnQuery != null) {
for(DBIDIter iditer = distFunc.getRelation().iterDBIDs(); iditer.valid(); iditer.advance()) {
counter++;
- final KNNResult<D> knns = knnQuery.getKNNForDBID(iditer, m);
+ final KNNList<D> knns = knnQuery.getKNNForDBID(iditer, m);
if(LOG.isDebugging()) {
LOG.debugFine("distance to mth nearest neighbour" + knns.toString());
}
@@ -184,7 +184,7 @@ public class DBOutlierDetection<O, D extends Distance<D>> extends AbstractDBOutl
@Override
protected DBOutlierDetection<O, D> makeInstance() {
- return new DBOutlierDetection<O, D>(distanceFunction, d, p);
+ return new DBOutlierDetection<>(distanceFunction, d, p);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/DBOutlierScore.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/DBOutlierScore.java
index a2d39130..d6528682 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/DBOutlierScore.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/DBOutlierScore.java
@@ -103,7 +103,7 @@ public class DBOutlierScore<O, D extends Distance<D>> extends AbstractDBOutlier<
public static class Parameterizer<O, D extends Distance<D>> extends AbstractDBOutlier.Parameterizer<O, D> {
@Override
protected DBOutlierScore<O, D> makeInstance() {
- return new DBOutlierScore<O, D>(distanceFunction, d);
+ return new DBOutlierScore<>(distanceFunction, d);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/EMOutlier.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/EMOutlier.java
index 2d2a4466..f8fd686f 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/EMOutlier.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/EMOutlier.java
@@ -104,7 +104,7 @@ public class EMOutlier<V extends NumberVector<?>> extends AbstractAlgorithm<Outl
emo_score.putDouble(iditer, maxProb);
globmax = Math.max(maxProb, globmax);
}
- Relation<Double> scoreres = new MaterializedRelation<Double>("EM outlier scores", "em-outlier", TypeUtil.DOUBLE, emo_score, relation.getDBIDs());
+ Relation<Double> scoreres = new MaterializedRelation<>("EM outlier scores", "em-outlier", TypeUtil.DOUBLE, emo_score, relation.getDBIDs());
OutlierScoreMeta meta = new ProbabilisticOutlierScore(0.0, globmax);
// combine results.
OutlierResult result = new OutlierResult(meta, scoreres);
@@ -142,7 +142,7 @@ public class EMOutlier<V extends NumberVector<?>> extends AbstractAlgorithm<Outl
@Override
protected EMOutlier<V> makeInstance() {
- return new EMOutlier<V>(em);
+ return new EMOutlier<>(em);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/GaussianModel.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/GaussianModel.java
index 6aed60fe..c9e6a634 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/GaussianModel.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/GaussianModel.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -136,7 +136,7 @@ public class GaussianModel<V extends NumberVector<?>> extends AbstractAlgorithm<
else {
meta = new InvertedOutlierScoreMeta(mm.getMin(), mm.getMax(), 0.0, Double.POSITIVE_INFINITY);
}
- Relation<Double> res = new MaterializedRelation<Double>("Gaussian Model Outlier Score", "gaussian-model-outlier", TypeUtil.DOUBLE, oscores, relation.getDBIDs());
+ Relation<Double> res = new MaterializedRelation<>("Gaussian Model Outlier Score", "gaussian-model-outlier", TypeUtil.DOUBLE, oscores, relation.getDBIDs());
return new OutlierResult(meta, res);
}
@@ -171,7 +171,7 @@ public class GaussianModel<V extends NumberVector<?>> extends AbstractAlgorithm<
@Override
protected GaussianModel<V> makeInstance() {
- return new GaussianModel<V>(invert);
+ return new GaussianModel<>(invert);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/GaussianUniformMixture.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/GaussianUniformMixture.java
index db53a3ef..294592e8 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/GaussianUniformMixture.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/GaussianUniformMixture.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -184,7 +184,7 @@ public class GaussianUniformMixture<V extends NumberVector<?>> extends AbstractA
}
OutlierScoreMeta meta = new BasicOutlierScoreMeta(minmax.getMin(), minmax.getMax(), Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 0.0);
- Relation<Double> res = new MaterializedRelation<Double>("Gaussian Mixture Outlier Score", "gaussian-mixture-outlier", TypeUtil.DOUBLE, oscores, relation.getDBIDs());
+ Relation<Double> res = new MaterializedRelation<>("Gaussian Mixture Outlier Score", "gaussian-mixture-outlier", TypeUtil.DOUBLE, oscores, relation.getDBIDs());
return new OutlierResult(meta, res);
}
@@ -267,7 +267,7 @@ public class GaussianUniformMixture<V extends NumberVector<?>> extends AbstractA
@Override
protected GaussianUniformMixture<V> makeInstance() {
- return new GaussianUniformMixture<V>(l, c);
+ return new GaussianUniformMixture<>(l, c);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/HilOut.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/HilOut.java
index 15f6cbf3..e0cdd0c5 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/HilOut.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/HilOut.java
@@ -1,28 +1,28 @@
package de.lmu.ifi.dbs.elki.algorithm.outlier;
-/*
- This file is part of ELKI:
+
+/*
+ This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-
- Copyright (C) 2012
- Ludwig-Maximilians-Universität München
- Lehr- und Forschungseinheit für Datenbanksysteme
+
+ Copyright (C) 2012
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-import java.util.Collections;
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
import java.util.Comparator;
import java.util.HashSet;
import java.util.Set;
@@ -39,14 +39,16 @@ import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDFactory;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
-import de.lmu.ifi.dbs.elki.database.ids.DoubleDistanceDBIDPair;
import de.lmu.ifi.dbs.elki.database.ids.HashSetModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPair;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.database.relation.RelationUtil;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.LPNormDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.LPNormDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultUtil;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
@@ -57,7 +59,9 @@ import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierScoreMeta;
import de.lmu.ifi.dbs.elki.utilities.BitsUtil;
import de.lmu.ifi.dbs.elki.utilities.DatabaseUtil;
-import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.Heap;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.ComparatorMaxHeap;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.ComparatorMinHeap;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.ObjectHeap;
import de.lmu.ifi.dbs.elki.utilities.documentation.Description;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
@@ -139,6 +143,13 @@ public class HilOut<O extends NumberVector<?>> extends AbstractDistanceBasedAlgo
*/
private double omega_star;
+ // public int distcomp = 1;
+
+ /**
+ * Comparator for sorting the heaps.
+ */
+ private static final Comparator<? super DistanceDBIDPair<?>> COMPARATOR = DistanceDBIDResultUtil.distanceComparator();
+
/**
* Type of output: all scores (upper bounds) or top n only
*
@@ -182,18 +193,18 @@ public class HilOut<O extends NumberVector<?>> extends AbstractDistanceBasedAlgo
Pair<O, O> hbbs = DatabaseUtil.computeMinMax(relation);
min = new double[d];
double[] max = new double[d];
- for(int i = 0; i < d; i++) {
+ for (int i = 0; i < d; i++) {
min[i] = hbbs.first.doubleValue(i);
max[i] = hbbs.second.doubleValue(i);
diameter = Math.max(diameter, max[i] - min[i]);
}
// Enlarge bounding box to have equal lengths.
- for(int i = 0; i < d; i++) {
+ for (int i = 0; i < d; i++) {
double diff = (diameter - (max[i] - min[i])) * .5;
min[i] -= diff;
max[i] += diff;
}
- if(LOG.isVerbose()) {
+ if (LOG.isVerbose()) {
LOG.verbose("Rescaling dataset by " + (1 / diameter) + " to fit the unit cube.");
}
}
@@ -205,7 +216,7 @@ public class HilOut<O extends NumberVector<?>> extends AbstractDistanceBasedAlgo
FiniteProgress progressHilOut = LOG.isVerbose() ? new FiniteProgress("HilOut iterations", d + 1, LOG) : null;
FiniteProgress progressTrueOut = LOG.isVerbose() ? new FiniteProgress("True outliers found", n, LOG) : null;
// Main part: 1. Phase max. d+1 loops
- for(int j = 0; j <= d && n_star < n; j++) {
+ for (int j = 0; j <= d && n_star < n; j++) {
// initialize (clear) out and wlb - not 100% clear in the paper
h.out.clear();
h.wlb.clear();
@@ -215,61 +226,64 @@ public class HilOut<O extends NumberVector<?>> extends AbstractDistanceBasedAlgo
scan(h, (int) (k * capital_n / (double) capital_n_star));
// determine the true outliers (n_star)
trueOutliers(h);
- if(progressTrueOut != null) {
+ if (progressTrueOut != null) {
progressTrueOut.setProcessed(n_star, LOG);
}
// Build the top Set as out + wlb
h.top.clear();
HashSetModifiableDBIDs top_keys = DBIDUtil.newHashSet(h.out.size());
- for(HilFeature entry : h.out) {
+ for (ObjectHeap.UnsortedIter<HilFeature> iter = h.out.unsortedIter(); iter.valid(); iter.advance()) {
+ HilFeature entry = iter.get();
top_keys.add(entry.id);
h.top.add(entry);
}
- for(HilFeature entry : h.wlb) {
- if(!top_keys.contains(entry.id)) {
+ for (ObjectHeap.UnsortedIter<HilFeature> iter = h.wlb.unsortedIter(); iter.valid(); iter.advance()) {
+ HilFeature entry = iter.get();
+ if (!top_keys.contains(entry.id)) {
// No need to update top_keys - discarded
h.top.add(entry);
}
}
- if(progressHilOut != null) {
+ if (progressHilOut != null) {
progressHilOut.incrementProcessed(LOG);
}
}
// 2. Phase: Additional Scan if less than n true outliers determined
- if(n_star < n) {
+ if (n_star < n) {
h.out.clear();
h.wlb.clear();
// TODO: reinitialize shift to 0?
scan(h, capital_n);
}
- if(progressHilOut != null) {
+ if (progressHilOut != null) {
progressHilOut.setProcessed(d, LOG);
progressHilOut.ensureCompleted(LOG);
}
- if(progressTrueOut != null) {
+ if (progressTrueOut != null) {
progressTrueOut.setProcessed(n, LOG);
progressTrueOut.ensureCompleted(LOG);
}
DoubleMinMax minmax = new DoubleMinMax();
// Return weights in out
- if(tn == ScoreType.TopN) {
+ if (tn == ScoreType.TopN) {
minmax.put(0.0);
- for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
+ for (DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
hilout_weight.putDouble(iditer, 0.0);
}
- for(HilFeature ent : h.out) {
+ for (ObjectHeap.UnsortedIter<HilFeature> iter = h.out.unsortedIter(); iter.valid(); iter.advance()) {
+ HilFeature ent = iter.get();
minmax.put(ent.ubound);
hilout_weight.putDouble(ent.id, ent.ubound);
}
}
// Return all weights in pf
else {
- for(HilFeature ent : h.pf) {
+ for (HilFeature ent : h.pf) {
minmax.put(ent.ubound);
hilout_weight.putDouble(ent.id, ent.ubound);
}
}
- Relation<Double> scoreResult = new MaterializedRelation<Double>("HilOut weight", "hilout-weight", TypeUtil.DOUBLE, hilout_weight, relation.getDBIDs());
+ Relation<Double> scoreResult = new MaterializedRelation<>("HilOut weight", "hilout-weight", TypeUtil.DOUBLE, hilout_weight, relation.getDBIDs());
OutlierScoreMeta scoreMeta = new BasicOutlierScoreMeta(minmax.getMin(), minmax.getMax(), 0.0, Double.POSITIVE_INFINITY);
OutlierResult result = new OutlierResult(scoreMeta, scoreResult);
return result;
@@ -283,37 +297,35 @@ public class HilOut<O extends NumberVector<?>> extends AbstractDistanceBasedAlgo
*/
private void scan(HilbertFeatures hf, int k0) {
final int mink0 = Math.min(2 * k0, capital_n - 1);
- if(LOG.isDebuggingFine()) {
+ if (LOG.isDebuggingFine()) {
LOG.debugFine("Scanning with k0=" + k0 + " (" + mink0 + ")" + " N*=" + capital_n_star);
}
- for(int i = 0; i < hf.pf.length; i++) {
- if(hf.pf[i].ubound < omega_star) {
+ for (int i = 0; i < hf.pf.length; i++) {
+ if (hf.pf[i].ubound < omega_star) {
continue;
}
- if(hf.pf[i].lbound < hf.pf[i].ubound) {
+ if (hf.pf[i].lbound < hf.pf[i].ubound) {
double omega = hf.fastUpperBound(i);
- if(omega < omega_star) {
+ if (omega < omega_star) {
hf.pf[i].ubound = omega;
- }
- else {
+ } else {
int maxcount;
// capital_n-1 instead of capital_n: all, except self
- if(hf.top.contains(hf.pf[i])) {
+ if (hf.top.contains(hf.pf[i])) {
maxcount = capital_n - 1;
- }
- else {
+ } else {
maxcount = mink0;
}
innerScan(hf, i, maxcount);
}
}
- if(hf.pf[i].ubound > 0) {
+ if (hf.pf[i].ubound > 0) {
hf.updateOUT(i);
}
- if(hf.pf[i].lbound > 0) {
+ if (hf.pf[i].lbound > 0) {
hf.updateWLB(i);
}
- if(hf.wlb.size() >= n) {
+ if (hf.wlb.size() >= n) {
omega_star = Math.max(omega_star, hf.wlb.peek().lbound);
}
}
@@ -332,43 +344,40 @@ public class HilOut<O extends NumberVector<?>> extends AbstractDistanceBasedAlgo
int a = i, b = i;
int level = h, levela = h, levelb = h;
// Explore up to "maxcount" neighbors in this pass
- for(int count = 0; count < maxcount; count++) {
+ for (int count = 0; count < maxcount; count++) {
final int c; // Neighbor to explore
- if(a == 0) { // At left end, explore right
+ if (a == 0) { // At left end, explore right
// assert (b < capital_n - 1);
levelb = Math.min(levelb, hf.pf[b].level);
b++;
c = b;
- }
- else if(b >= capital_n - 1) { // At right end, explore left
+ } else if (b >= capital_n - 1) { // At right end, explore left
// assert (a > 0);
a--;
levela = Math.min(levela, hf.pf[a].level);
c = a;
- }
- else if(hf.pf[a - 1].level >= hf.pf[b].level) { // Prefer higher level
+ } else if (hf.pf[a - 1].level >= hf.pf[b].level) { // Prefer higher level
a--;
levela = Math.min(levela, hf.pf[a].level);
c = a;
- }
- else {
+ } else {
// assert (b < capital_n - 1);
levelb = Math.min(levelb, hf.pf[b].level);
b++;
c = b;
}
- if(!hf.pf[i].nn_keys.contains(hf.pf[c].id)) {
+ if (!hf.pf[i].nn_keys.contains(hf.pf[c].id)) {
// hf.distcomp ++;
hf.pf[i].insert(hf.pf[c].id, distq.distance(p, hf.pf[c].id).doubleValue(), k);
- if(hf.pf[i].nn.size() == k) {
- if(hf.pf[i].sum_nn < omega_star) {
+ if (hf.pf[i].nn.size() == k) {
+ if (hf.pf[i].sum_nn < omega_star) {
break; // stop = true
}
final int mlevel = Math.max(levela, levelb);
- if(mlevel < level) {
+ if (mlevel < level) {
level = mlevel;
final double delta = hf.minDistLevel(hf.pf[i].id, level);
- if(delta >= hf.pf[i].nn.peek().doubleDistance()) {
+ if (delta >= hf.pf[i].nn.peek().doubleDistance()) {
break; // stop = true
}
}
@@ -378,16 +387,17 @@ public class HilOut<O extends NumberVector<?>> extends AbstractDistanceBasedAlgo
double br = hf.boxRadius(i, a - 1, b + 1);
double newlb = 0.0;
double newub = 0.0;
- for(DoubleDistanceDBIDPair entry : hf.pf[i].nn) {
+ for (ObjectHeap.UnsortedIter<DoubleDistanceDBIDPair> iter = hf.pf[i].nn.unsortedIter(); iter.valid(); iter.advance()) {
+ DoubleDistanceDBIDPair entry = iter.get();
newub += entry.doubleDistance();
- if(entry.doubleDistance() <= br) {
+ if (entry.doubleDistance() <= br) {
newlb += entry.doubleDistance();
}
}
- if(newlb > hf.pf[i].lbound) {
+ if (newlb > hf.pf[i].lbound) {
hf.pf[i].lbound = newlb;
}
- if(newub < hf.pf[i].ubound) {
+ if (newub < hf.pf[i].ubound) {
hf.pf[i].ubound = newub;
}
}
@@ -401,8 +411,9 @@ public class HilOut<O extends NumberVector<?>> extends AbstractDistanceBasedAlgo
private void trueOutliers(HilbertFeatures h) {
n_star = 0;
- for(HilFeature entry : h.out) {
- if(entry.ubound >= omega_star && (entry.ubound - entry.lbound < 1E-10)) {
+ for (ObjectHeap.UnsortedIter<HilFeature> iter = h.out.unsortedIter(); iter.valid(); iter.advance()) {
+ HilFeature entry = iter.get();
+ if (entry.ubound >= omega_star && (entry.ubound - entry.lbound < 1E-10)) {
n_star++;
}
}
@@ -461,12 +472,12 @@ public class HilOut<O extends NumberVector<?>> extends AbstractDistanceBasedAlgo
/**
* "OUT"
*/
- private Heap<HilFeature> out;
+ private ObjectHeap<HilFeature> out;
/**
* "WLB"
*/
- private Heap<HilFeature> wlb;
+ private ObjectHeap<HilFeature> wlb;
/**
* Constructor.
@@ -483,22 +494,22 @@ public class HilOut<O extends NumberVector<?>> extends AbstractDistanceBasedAlgo
this.pf = new HilFeature[relation.size()];
int pos = 0;
- for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
- pf[pos++] = new HilFeature(DBIDUtil.deref(iditer), new Heap<DoubleDistanceDBIDPair>(k, Collections.reverseOrder()));
+ for (DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
+ pf[pos++] = new HilFeature(DBIDUtil.deref(iditer), new ComparatorMaxHeap<DoubleDistanceDBIDPair>(k, COMPARATOR));
}
- this.out = new Heap<HilFeature>(n, new Comparator<HilFeature>() {
+ this.out = new ComparatorMinHeap<>(n, new Comparator<HilFeature>() {
@Override
public int compare(HilFeature o1, HilFeature o2) {
return Double.compare(o1.ubound, o2.ubound);
}
});
- this.wlb = new Heap<HilFeature>(n, new Comparator<HilFeature>() {
+ this.wlb = new ComparatorMinHeap<>(n, new Comparator<HilFeature>() {
@Override
public int compare(HilFeature o1, HilFeature o2) {
return Double.compare(o1.lbound, o2.lbound);
}
});
- this.top = new HashSet<HilFeature>(2 * n);
+ this.top = new HashSet<>(2 * n);
}
/**
@@ -512,45 +523,42 @@ public class HilOut<O extends NumberVector<?>> extends AbstractDistanceBasedAlgo
// FIXME: 64 bit mode untested - sign bit is tricky to handle correctly
// with the rescaling. 63 bit should be fine. The sign bit probably needs
// to be handled differently, or at least needs careful testing of the API
- if(h >= 32) { // 32 to 63 bit
+ if (h >= 32) { // 32 to 63 bit
final long scale = Long.MAX_VALUE; // = 63 bits
- for(int i = 0; i < pf.length; i++) {
+ for (int i = 0; i < pf.length; i++) {
NumberVector<?> obj = relation.get(pf[i].id);
long[] coord = new long[d];
- for(int dim = 0; dim < d; dim++) {
+ for (int dim = 0; dim < d; dim++) {
coord[dim] = (long) (getDimForObject(obj, dim) * .5 * scale);
}
pf[i].hilbert = HilbertSpatialSorter.coordinatesToHilbert(coord, h, 1);
}
- }
- else if(h >= 16) { // 16-31 bit
+ } else if (h >= 16) { // 16-31 bit
final int scale = ~1 >>> 1;
- for(int i = 0; i < pf.length; i++) {
+ for (int i = 0; i < pf.length; i++) {
NumberVector<?> obj = relation.get(pf[i].id);
int[] coord = new int[d];
- for(int dim = 0; dim < d; dim++) {
+ for (int dim = 0; dim < d; dim++) {
coord[dim] = (int) (getDimForObject(obj, dim) * .5 * scale);
}
pf[i].hilbert = HilbertSpatialSorter.coordinatesToHilbert(coord, h, 1);
}
- }
- else if(h >= 8) { // 8-15 bit
+ } else if (h >= 8) { // 8-15 bit
final int scale = ~1 >>> 16;
- for(int i = 0; i < pf.length; i++) {
+ for (int i = 0; i < pf.length; i++) {
NumberVector<?> obj = relation.get(pf[i].id);
short[] coord = new short[d];
- for(int dim = 0; dim < d; dim++) {
+ for (int dim = 0; dim < d; dim++) {
coord[dim] = (short) (getDimForObject(obj, dim) * .5 * scale);
}
pf[i].hilbert = HilbertSpatialSorter.coordinatesToHilbert(coord, h, 16);
}
- }
- else { // 1-7 bit
+ } else { // 1-7 bit
final int scale = ~1 >>> 8;
- for(int i = 0; i < pf.length; i++) {
+ for (int i = 0; i < pf.length; i++) {
NumberVector<?> obj = relation.get(pf[i].id);
byte[] coord = new byte[d];
- for(int dim = 0; dim < d; dim++) {
+ for (int dim = 0; dim < d; dim++) {
coord[dim] = (byte) (getDimForObject(obj, dim) * .5 * scale);
}
pf[i].hilbert = HilbertSpatialSorter.coordinatesToHilbert(coord, h, 24);
@@ -558,13 +566,13 @@ public class HilOut<O extends NumberVector<?>> extends AbstractDistanceBasedAlgo
}
java.util.Arrays.sort(pf);
// Update levels
- for(int i = 0; i < pf.length - 1; i++) {
+ for (int i = 0; i < pf.length - 1; i++) {
pf[i].level = minRegLevel(i, i + 1);
}
// Count candidates
capital_n_star = 0;
- for(int i = 0; i < pf.length; i++) {
- if(pf[i].ubound >= omega_star) {
+ for (int i = 0; i < pf.length; i++) {
+ if (pf[i].ubound >= omega_star) {
capital_n_star++;
}
}
@@ -576,12 +584,11 @@ public class HilOut<O extends NumberVector<?>> extends AbstractDistanceBasedAlgo
* @param i position in pf of the feature to be inserted
*/
private void updateOUT(int i) {
- if(out.size() < n) {
+ if (out.size() < n) {
out.add(pf[i]);
- }
- else {
+ } else {
HilFeature head = out.peek();
- if(pf[i].ubound > head.ubound) {
+ if (pf[i].ubound > head.ubound) {
// replace smallest
out.replaceTopElement(pf[i]);
}
@@ -594,12 +601,11 @@ public class HilOut<O extends NumberVector<?>> extends AbstractDistanceBasedAlgo
* @param i position in pf of the feature to be inserted
*/
private void updateWLB(int i) {
- if(wlb.size() < n) {
+ if (wlb.size() < n) {
wlb.add(pf[i]);
- }
- else {
+ } else {
HilFeature head = wlb.peek();
- if(pf[i].lbound > head.lbound) {
+ if (pf[i].lbound > head.lbound) {
// replace smallest
wlb.replaceTopElement(pf[i]);
}
@@ -616,13 +622,12 @@ public class HilOut<O extends NumberVector<?>> extends AbstractDistanceBasedAlgo
private double fastUpperBound(int i) {
int pre = i;
int post = i;
- while(post - pre < k) {
+ while (post - pre < k) {
int pre_level = (pre - 1 >= 0) ? pf[pre - 1].level : -2;
int post_level = (post < capital_n - 1) ? pf[post].level : -2;
- if(post_level >= pre_level) {
+ if (post_level >= pre_level) {
post++;
- }
- else {
+ } else {
pre--;
}
}
@@ -642,7 +647,7 @@ public class HilOut<O extends NumberVector<?>> extends AbstractDistanceBasedAlgo
// 2 ^ - (level - 1)
final double r = 1.0 / (1 << (level - 1));
double dist = Double.POSITIVE_INFINITY;
- for(int dim = 0; dim < d; dim++) {
+ for (int dim = 0; dim < d; dim++) {
final double p_m_r = getDimForObject(obj, dim) % r;
dist = Math.min(dist, Math.min(p_m_r, r - p_m_r));
}
@@ -661,35 +666,32 @@ public class HilOut<O extends NumberVector<?>> extends AbstractDistanceBasedAlgo
// level 1 is supposed to have r=1 as in the original publication
final double r = 1.0 / (1 << (level - 1));
double dist;
- if(t == 1.0) {
+ if (t == 1.0) {
dist = 0.0;
- for(int dim = 0; dim < d; dim++) {
+ for (int dim = 0; dim < d; dim++) {
final double p_m_r = getDimForObject(obj, dim) % r;
// assert (p_m_r >= 0);
dist += Math.max(p_m_r, r - p_m_r);
}
- }
- else if(t == 2.0) {
+ } else if (t == 2.0) {
dist = 0.0;
- for(int dim = 0; dim < d; dim++) {
+ for (int dim = 0; dim < d; dim++) {
final double p_m_r = getDimForObject(obj, dim) % r;
// assert (p_m_r >= 0);
double a = Math.max(p_m_r, r - p_m_r);
dist += a * a;
}
dist = Math.sqrt(dist);
- }
- else if(!Double.isInfinite(t)) {
+ } else if (!Double.isInfinite(t)) {
dist = 0.0;
- for(int dim = 0; dim < d; dim++) {
+ for (int dim = 0; dim < d; dim++) {
final double p_m_r = getDimForObject(obj, dim) % r;
dist += Math.pow(Math.max(p_m_r, r - p_m_r), t);
}
dist = Math.pow(dist, 1.0 / t);
- }
- else {
+ } else {
dist = Double.NEGATIVE_INFINITY;
- for(int dim = 0; dim < d; dim++) {
+ for (int dim = 0; dim < d; dim++) {
final double p_m_r = getDimForObject(obj, dim) % r;
dist = Math.max(dist, Math.max(p_m_r, r - p_m_r));
}
@@ -705,9 +707,9 @@ public class HilOut<O extends NumberVector<?>> extends AbstractDistanceBasedAlgo
* @return Number of level shared
*/
private int numberSharedLevels(long[] a, long[] b) {
- for(int i = 0, j = a.length - 1; i < a.length; i++, j--) {
+ for (int i = 0, j = a.length - 1; i < a.length; i++, j--) {
final long diff = a[j] ^ b[j];
- if(diff != 0) {
+ if (diff != 0) {
// expected unused = available - used
final int expected = (a.length * Long.SIZE) - (d * h);
return ((BitsUtil.numberOfLeadingZeros(diff) + i * Long.SIZE) - expected) / d;
@@ -756,16 +758,14 @@ public class HilOut<O extends NumberVector<?>> extends AbstractDistanceBasedAlgo
private double boxRadius(int i, int a, int b) {
// level are inversely ordered to box sizes. min -> max
final int level;
- if(a < 0) {
- if(b >= pf.length) {
+ if (a < 0) {
+ if (b >= pf.length) {
return Double.POSITIVE_INFINITY;
}
level = maxRegLevel(i, b);
- }
- else if(b >= pf.length) {
+ } else if (b >= pf.length) {
level = maxRegLevel(i, a);
- }
- else {
+ } else {
level = Math.max(maxRegLevel(i, a), maxRegLevel(i, b));
}
return minDistLevel(pf[i].id, level);
@@ -822,7 +822,7 @@ public class HilOut<O extends NumberVector<?>> extends AbstractDistanceBasedAlgo
/**
* Heap with the nearest known neighbors
*/
- public Heap<DoubleDistanceDBIDPair> nn;
+ public ObjectHeap<DoubleDistanceDBIDPair> nn;
/**
* Set representation of the nearest neighbors for faster lookups
@@ -840,7 +840,7 @@ public class HilOut<O extends NumberVector<?>> extends AbstractDistanceBasedAlgo
* @param id Object ID
* @param nn Heap for neighbors
*/
- public HilFeature(DBID id, Heap<DoubleDistanceDBIDPair> nn) {
+ public HilFeature(DBID id, ObjectHeap<DoubleDistanceDBIDPair> nn) {
super();
this.id = id;
this.nn = nn;
@@ -861,15 +861,14 @@ public class HilOut<O extends NumberVector<?>> extends AbstractDistanceBasedAlgo
*/
protected void insert(DBID id, double dt, int k) {
// assert (!nn_keys.contains(id));
- if(nn.size() < k) {
+ if (nn.size() < k) {
DoubleDistanceDBIDPair entry = DBIDFactory.FACTORY.newDistancePair(dt, id);
nn.add(entry);
nn_keys.add(id);
sum_nn += dt;
- }
- else {
+ } else {
DoubleDistanceDBIDPair head = nn.peek();
- if(dt < head.doubleDistance()) {
+ if (dt < head.doubleDistance()) {
head = nn.poll(); // Remove worst
sum_nn -= head.doubleDistance();
nn_keys.remove(head);
@@ -891,7 +890,7 @@ public class HilOut<O extends NumberVector<?>> extends AbstractDistanceBasedAlgo
* @author Jonathan von Brünken
*
* @apiviz.exclude
- *
+ *
* @param <O> Vector type
*/
public static class Parameterizer<O extends NumberVector<?>> extends AbstractParameterizer {
@@ -952,34 +951,34 @@ public class HilOut<O extends NumberVector<?>> extends AbstractDistanceBasedAlgo
super.makeOptions(config);
final IntParameter kP = new IntParameter(K_ID, 5);
- if(config.grab(kP)) {
+ if (config.grab(kP)) {
k = kP.getValue();
}
final IntParameter nP = new IntParameter(N_ID, 10);
- if(config.grab(nP)) {
+ if (config.grab(nP)) {
n = nP.getValue();
}
final IntParameter hP = new IntParameter(H_ID, 32);
- if(config.grab(hP)) {
+ if (config.grab(hP)) {
h = hP.getValue();
}
-
+
ObjectParameter<LPNormDistanceFunction> distP = AbstractDistanceBasedAlgorithm.makeParameterDistanceFunction(EuclideanDistanceFunction.class, LPNormDistanceFunction.class);
if (config.grab(distP)) {
distfunc = distP.instantiateClass(config);
}
- final EnumParameter<ScoreType> tnP = new EnumParameter<ScoreType>(TN_ID, ScoreType.class, ScoreType.TopN);
- if(config.grab(tnP)) {
+ final EnumParameter<ScoreType> tnP = new EnumParameter<>(TN_ID, ScoreType.class, ScoreType.TopN);
+ if (config.grab(tnP)) {
tn = tnP.getValue();
}
}
@Override
protected HilOut<O> makeInstance() {
- return new HilOut<O>(distfunc, k, n, h, tn);
+ return new HilOut<>(distfunc, k, n, h, tn);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/KNNOutlier.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/KNNOutlier.java
index 4c4873dd..503487c8 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/KNNOutlier.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/KNNOutlier.java
@@ -31,13 +31,13 @@ import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceKNNList;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
@@ -53,10 +53,8 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameteriz
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
/**
- * <p>
* Outlier Detection based on the distance of an object to its k nearest
* neighbor.
- * </p>
*
* <p>
* Reference:<br>
@@ -119,7 +117,7 @@ public class KNNOutlier<O, D extends NumberDistance<D, ?>> extends AbstractDista
// compute distance to the k nearest neighbor.
for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
// distance to the kth nearest neighbor
- final KNNResult<D> knns = knnQuery.getKNNForDBID(iditer, k);
+ final KNNList<D> knns = knnQuery.getKNNForDBID(iditer, k);
final double dkn;
if(knns instanceof DoubleDistanceKNNList) {
dkn = ((DoubleDistanceKNNList) knns).doubleKNNDistance();
@@ -138,7 +136,7 @@ public class KNNOutlier<O, D extends NumberDistance<D, ?>> extends AbstractDista
if(progressKNNDistance != null) {
progressKNNDistance.ensureCompleted(LOG);
}
- Relation<Double> scoreres = new MaterializedRelation<Double>("kNN Outlier Score", "knn-outlier", TypeUtil.DOUBLE, knno_score, relation.getDBIDs());
+ Relation<Double> scoreres = new MaterializedRelation<>("kNN Outlier Score", "knn-outlier", TypeUtil.DOUBLE, knno_score, relation.getDBIDs());
OutlierScoreMeta meta = new BasicOutlierScoreMeta(minmax.getMin(), minmax.getMax(), 0.0, Double.POSITIVE_INFINITY, 0.0);
return new OutlierResult(meta, scoreres);
}
@@ -174,7 +172,7 @@ public class KNNOutlier<O, D extends NumberDistance<D, ?>> extends AbstractDista
@Override
protected KNNOutlier<O, D> makeInstance() {
- return new KNNOutlier<O, D>(distanceFunction, k);
+ return new KNNOutlier<>(distanceFunction, k);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/KNNWeightOutlier.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/KNNWeightOutlier.java
index e7eeeb9c..88603f09 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/KNNWeightOutlier.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/KNNWeightOutlier.java
@@ -31,15 +31,15 @@ import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultIter;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceDBIDResultIter;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceKNNList;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
@@ -124,15 +124,15 @@ public class KNNWeightOutlier<O, D extends NumberDistance<D, ?>> extends Abstrac
for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
// compute sum of the distances to the k nearest neighbors
- final KNNResult<D> knn = knnQuery.getKNNForDBID(iditer, k);
+ final KNNList<D> knn = knnQuery.getKNNForDBID(iditer, k);
double skn = 0;
if(knn instanceof DoubleDistanceKNNList) {
- for(DoubleDistanceDBIDResultIter neighbor = ((DoubleDistanceKNNList) knn).iter(); neighbor.valid(); neighbor.advance()) {
+ for(DoubleDistanceDBIDListIter neighbor = ((DoubleDistanceKNNList) knn).iter(); neighbor.valid(); neighbor.advance()) {
skn += neighbor.doubleDistance();
}
}
else {
- for(DistanceDBIDResultIter<D> neighbor = knn.iter(); neighbor.valid(); neighbor.advance()) {
+ for(DistanceDBIDListIter<D> neighbor = knn.iter(); neighbor.valid(); neighbor.advance()) {
skn += neighbor.getDistance().doubleValue();
}
}
@@ -147,7 +147,7 @@ public class KNNWeightOutlier<O, D extends NumberDistance<D, ?>> extends Abstrac
progressKNNWeight.ensureCompleted(LOG);
}
- Relation<Double> res = new MaterializedRelation<Double>("Weighted kNN Outlier Score", "knnw-outlier", TypeUtil.DOUBLE, knnw_score, relation.getDBIDs());
+ Relation<Double> res = new MaterializedRelation<>("Weighted kNN Outlier Score", "knnw-outlier", TypeUtil.DOUBLE, knnw_score, relation.getDBIDs());
OutlierScoreMeta meta = new BasicOutlierScoreMeta(minmax.getMin(), minmax.getMax(), 0.0, Double.POSITIVE_INFINITY, 0.0);
return new OutlierResult(meta, res);
}
@@ -183,7 +183,7 @@ public class KNNWeightOutlier<O, D extends NumberDistance<D, ?>> extends Abstrac
@Override
protected KNNWeightOutlier<O, D> makeInstance() {
- return new KNNWeightOutlier<O, D>(distanceFunction, k);
+ return new KNNWeightOutlier<>(distanceFunction, k);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/ODIN.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/ODIN.java
new file mode 100644
index 00000000..f22cdeb7
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/ODIN.java
@@ -0,0 +1,192 @@
+package de.lmu.ifi.dbs.elki.algorithm.outlier;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm;
+import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
+import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.database.Database;
+import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory;
+import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
+import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
+import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
+import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
+import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.result.outlier.InvertedOutlierScoreMeta;
+import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
+import de.lmu.ifi.dbs.elki.result.outlier.OutlierScoreMeta;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
+
+/**
+ * Outlier detection based on the in-degree of the kNN graph.
+ *
+ * This is a curried version: instead of using a threshold T to obtain a binary
+ * decision, we use the computed value as outlier score; normalized by k to make
+ * the numbers more comparable across different parameterizations.
+ *
+ * Reference:
+ * <p>
+ * V. Hautamäki and I. Kärkkäinen and P Fränti<br />
+ * Outlier detection using k-nearest neighbour graph<br />
+ * Proc. 17th Int. Conf. Pattern Recognition, ICPR 2004 <br />
+ * </p>
+ *
+ * @author Erich Schubert
+ *
+ * @param <O> Object type
+ * @param <D> Distance type
+ */
+@Reference(authors = "V. Hautamäki and I. Kärkkäinen and P Fränti", title = "Outlier detection using k-nearest neighbour graph", booktitle = "Proc. 17th Int. Conf. Pattern Recognition, ICPR 2004", url = "http://dx.doi.org/10.1109/ICPR.2004.1334558")
+public class ODIN<O, D extends Distance<D>> extends AbstractDistanceBasedAlgorithm<O, D, OutlierResult> implements OutlierAlgorithm {
+ /**
+ * Class logger.
+ */
+ private static final Logging LOG = Logging.getLogger(ODIN.class);
+
+ /**
+ * Number of neighbors for kNN graph.
+ */
+ int k;
+
+ /**
+ * Constructor.
+ *
+ * @param distanceFunction Distance function
+ * @param k k parameter
+ */
+ public ODIN(DistanceFunction<? super O, D> distanceFunction, int k) {
+ super(distanceFunction);
+ this.k = k;
+ }
+
+ /**
+ * Run the ODIN algorithm
+ *
+ * @param database Database to run on.
+ * @param relation Relation to process.
+ * @return ODIN outlier result.
+ */
+ public OutlierResult run(Database database, Relation<O> relation) {
+ // Get the query functions:
+ DistanceQuery<O, D> dq = database.getDistanceQuery(relation, getDistanceFunction());
+ KNNQuery<O, D> knnq = database.getKNNQuery(dq, k);
+
+ // Get the objects to process, and a data storage for counting and output:
+ DBIDs ids = relation.getDBIDs();
+ WritableDoubleDataStore scores = DataStoreUtil.makeDoubleStorage(ids, DataStoreFactory.HINT_DB, 0.);
+
+ double inc = 1. / (k - 1);
+ double min = Double.POSITIVE_INFINITY, max = 0.0;
+ // Process all objects
+ for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
+ // Find the nearest neighbors (using an index, if available!)
+ KNNList<D> neighbors = knnq.getKNNForDBID(iter, k);
+ // For each neighbor, except ourselves, increase the in-degree:
+ for (DBIDIter nei = neighbors.iter(); nei.valid(); nei.advance()) {
+ if (DBIDUtil.equal(iter, nei)) {
+ continue;
+ }
+ final double value = scores.doubleValue(nei) + inc;
+ if (value < min) {
+ min = value;
+ }
+ if (value > max) {
+ max = value;
+ }
+ scores.put(nei, value);
+ }
+ }
+
+ // Wrap the result and add metadata.
+ OutlierScoreMeta meta = new InvertedOutlierScoreMeta(min, max, 0., inc * (ids.size() - 1), 1);
+ Relation<Double> rel = new MaterializedRelation<>("ODIN In-Degree", "odin", TypeUtil.DOUBLE, scores, ids);
+ return new OutlierResult(meta, rel);
+ }
+
+ @Override
+ public TypeInformation[] getInputTypeRestriction() {
+ return TypeUtil.array(getDistanceFunction().getInputTypeRestriction());
+ }
+
+ @Override
+ protected Logging getLogger() {
+ return LOG;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ *
+ * @param <O> Object type
+ * @param <D> Distance type
+ */
+ public static class Parameterizer<O, D extends Distance<D>> extends AbstractDistanceBasedAlgorithm.Parameterizer<O, D> {
+ /**
+ * Parameter for the number of nearest neighbors:
+ *
+ * <pre>
+ * -odin.k &lt;int&gt;
+ * </pre>
+ */
+ public static final OptionID K_ID = new OptionID("odin.k", "Number of neighbors to use for kNN graph.");
+
+ /**
+ * Number of nearest neighbors to use.
+ */
+ int k;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+
+ IntParameter param = new IntParameter(K_ID);
+ // Since in a database context, the 1 nearest neighbor
+ // will usually be the query object itself, we require
+ // this value to be at least 2.
+ param.addConstraint(new GreaterConstraint(1));
+ if (config.grab(param)) {
+ k = param.intValue();
+ }
+ }
+
+ @Override
+ protected ODIN<O, D> makeInstance() {
+ return new ODIN<>(distanceFunction, k);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/OPTICSOF.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/OPTICSOF.java
index bed27a33..f6d46f57 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/OPTICSOF.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/OPTICSOF.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -37,14 +37,14 @@ import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.datastore.WritableIntegerDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery;
import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultIter;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
@@ -115,7 +115,7 @@ public class OPTICSOF<O, D extends NumberDistance<D, ?>> extends AbstractDistanc
DBIDs ids = relation.getDBIDs();
// FIXME: implicit preprocessor.
- WritableDataStore<KNNResult<D>> nMinPts = DataStoreUtil.makeStorage(ids, DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP, KNNResult.class);
+ WritableDataStore<KNNList<D>> nMinPts = DataStoreUtil.makeStorage(ids, DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP, KNNList.class);
WritableDoubleDataStore coreDistance = DataStoreUtil.makeDoubleStorage(ids, DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP);
WritableIntegerDataStore minPtsNeighborhoodSize = DataStoreUtil.makeIntegerStorage(ids, DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP, -1);
@@ -123,7 +123,7 @@ public class OPTICSOF<O, D extends NumberDistance<D, ?>> extends AbstractDistanc
// N_minpts(id) and core-distance(id)
for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
- KNNResult<D> minptsNeighbours = knnQuery.getKNNForDBID(iditer, minpts);
+ KNNList<D> minptsNeighbours = knnQuery.getKNNForDBID(iditer, minpts);
D d = minptsNeighbours.getKNNDistance();
nMinPts.put(iditer, minptsNeighbours);
coreDistance.putDouble(iditer, d.doubleValue());
@@ -134,10 +134,10 @@ public class OPTICSOF<O, D extends NumberDistance<D, ?>> extends AbstractDistanc
WritableDataStore<List<Double>> reachDistance = DataStoreUtil.makeStorage(ids, DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP, List.class);
WritableDoubleDataStore lrds = DataStoreUtil.makeDoubleStorage(ids, DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP);
for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
- List<Double> core = new ArrayList<Double>();
+ List<Double> core = new ArrayList<>();
double lrd = 0;
// TODO: optimize for double distances
- for (DistanceDBIDResultIter<D> neighbor = nMinPts.get(iditer).iter(); neighbor.valid(); neighbor.advance()) {
+ for (DistanceDBIDListIter<D> neighbor = nMinPts.get(iditer).iter(); neighbor.valid(); neighbor.advance()) {
double coreDist = coreDistance.doubleValue(neighbor);
double dist = distQuery.distance(iditer, neighbor).doubleValue();
double rd = Math.max(coreDist, dist);
@@ -165,7 +165,7 @@ public class OPTICSOF<O, D extends NumberDistance<D, ?>> extends AbstractDistanc
ofminmax.put(of);
}
// Build result representation.
- Relation<Double> scoreResult = new MaterializedRelation<Double>("OPTICS Outlier Scores", "optics-outlier", TypeUtil.DOUBLE, ofs, relation.getDBIDs());
+ Relation<Double> scoreResult = new MaterializedRelation<>("OPTICS Outlier Scores", "optics-outlier", TypeUtil.DOUBLE, ofs, relation.getDBIDs());
OutlierScoreMeta scoreMeta = new QuotientOutlierScoreMeta(ofminmax.getMin(), ofminmax.getMax(), 0.0, Double.POSITIVE_INFINITY, 1.0);
return new OutlierResult(scoreMeta, scoreResult);
}
@@ -202,7 +202,7 @@ public class OPTICSOF<O, D extends NumberDistance<D, ?>> extends AbstractDistanc
@Override
protected OPTICSOF<O, D> makeInstance() {
- return new OPTICSOF<O, D>(distanceFunction, minpts);
+ return new OPTICSOF<>(distanceFunction, minpts);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/OutlierAlgorithm.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/OutlierAlgorithm.java
index 00c4a8ec..f3ef5ab5 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/OutlierAlgorithm.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/OutlierAlgorithm.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -33,7 +33,7 @@ import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
* @author Erich Schubert
*
* @apiviz.landmark
- *
+ * @apiviz.excludeSubtypes
* @apiviz.has OutlierResult
*/
public interface OutlierAlgorithm extends Algorithm {
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/ReferenceBasedOutlierDetection.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/ReferenceBasedOutlierDetection.java
index 93eca7db..092bbc45 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/ReferenceBasedOutlierDetection.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/ReferenceBasedOutlierDetection.java
@@ -31,18 +31,19 @@ import de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
-import de.lmu.ifi.dbs.elki.database.ids.DistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.generic.GenericDistanceDBIDList;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.GenericDistanceDBIDList;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.math.Mean;
@@ -136,11 +137,12 @@ public class ReferenceBasedOutlierDetection<V extends NumberVector<?>, D extends
/**
* Run the algorithm on the given relation.
*
+ * @param database Database
* @param relation Relation to process
* @return Outlier result
*/
- public OutlierResult run(Relation<V> relation) {
- DistanceQuery<V, D> distFunc = relation.getDatabase().getDistanceQuery(relation, distanceFunction);
+ public OutlierResult run(Database database, Relation<V> relation) {
+ DistanceQuery<V, D> distFunc = database.getDistanceQuery(relation, distanceFunction);
Collection<V> refPoints = refp.getReferencePoints(relation);
DBIDs ids = relation.getDBIDs();
@@ -158,7 +160,7 @@ public class ReferenceBasedOutlierDetection<V extends NumberVector<?>, D extends
}
V firstRef = iter.next();
// compute distance vector for the first reference point
- DistanceDBIDResult<D> firstReferenceDists = computeDistanceVector(firstRef, relation, distFunc);
+ DistanceDBIDList<D> firstReferenceDists = computeDistanceVector(firstRef, relation, distFunc);
for(int l = 0; l < firstReferenceDists.size(); l++) {
double density = computeDensity(firstReferenceDists, l);
// Initial value
@@ -167,7 +169,7 @@ public class ReferenceBasedOutlierDetection<V extends NumberVector<?>, D extends
// compute density values for all remaining reference points
while(iter.hasNext()) {
V refPoint = iter.next();
- DistanceDBIDResult<D> referenceDists = computeDistanceVector(refPoint, relation, distFunc);
+ DistanceDBIDList<D> referenceDists = computeDistanceVector(refPoint, relation, distFunc);
// compute density value for each object
for(int l = 0; l < referenceDists.size(); l++) {
double density = computeDensity(referenceDists, l);
@@ -194,9 +196,9 @@ public class ReferenceBasedOutlierDetection<V extends NumberVector<?>, D extends
// adds reference points to the result. header information for the
// visualizer to find the reference points in the result
- ReferencePointsResult<V> refp = new ReferencePointsResult<V>("Reference points", "reference-points", refPoints);
+ ReferencePointsResult<V> refp = new ReferencePointsResult<>("Reference points", "reference-points", refPoints);
- Relation<Double> scoreResult = new MaterializedRelation<Double>("Reference-points Outlier Scores", "reference-outlier", TypeUtil.DOUBLE, rbod_score, relation.getDBIDs());
+ Relation<Double> scoreResult = new MaterializedRelation<>("Reference-points Outlier Scores", "reference-outlier", TypeUtil.DOUBLE, rbod_score, relation.getDBIDs());
OutlierScoreMeta scoreMeta = new BasicOutlierScoreMeta(0.0, 1.0, 0.0, 1.0, 0.0);
OutlierResult result = new OutlierResult(scoreMeta, scoreResult);
result.addChildResult(refp);
@@ -213,9 +215,9 @@ public class ReferenceBasedOutlierDetection<V extends NumberVector<?>, D extends
* @return array containing the distance to one reference point for each
* database object and the object id
*/
- protected DistanceDBIDResult<D> computeDistanceVector(V refPoint, Relation<V> database, DistanceQuery<V, D> distFunc) {
+ protected DistanceDBIDList<D> computeDistanceVector(V refPoint, Relation<V> database, DistanceQuery<V, D> distFunc) {
// TODO: optimize for double distances?
- GenericDistanceDBIDList<D> referenceDists = new GenericDistanceDBIDList<D>(database.size());
+ GenericDistanceDBIDList<D> referenceDists = new GenericDistanceDBIDList<>(database.size());
for(DBIDIter iditer = database.iterDBIDs(); iditer.valid(); iditer.advance()) {
referenceDists.add(distFunc.distance(iditer, refPoint), iditer);
}
@@ -235,7 +237,7 @@ public class ReferenceBasedOutlierDetection<V extends NumberVector<?>, D extends
* @param index index of the current object
* @return density for one object and reference point
*/
- protected double computeDensity(DistanceDBIDResult<D> referenceDists, int index) {
+ protected double computeDensity(DistanceDBIDList<D> referenceDists, int index) {
final DistanceDBIDPair<D> x = referenceDists.get(index);
final double xDist = x.getDistance().doubleValue();
@@ -321,7 +323,7 @@ public class ReferenceBasedOutlierDetection<V extends NumberVector<?>, D extends
if(config.grab(pK)) {
k = pK.getValue();
}
- final ObjectParameter<ReferencePointsHeuristic<V>> refpP = new ObjectParameter<ReferencePointsHeuristic<V>>(REFP_ID, ReferencePointsHeuristic.class, GridBasedReferencePoints.class);
+ final ObjectParameter<ReferencePointsHeuristic<V>> refpP = new ObjectParameter<>(REFP_ID, ReferencePointsHeuristic.class, GridBasedReferencePoints.class);
if(config.grab(refpP)) {
refp = refpP.instantiateClass(config);
}
@@ -329,7 +331,7 @@ public class ReferenceBasedOutlierDetection<V extends NumberVector<?>, D extends
@Override
protected ReferenceBasedOutlierDetection<V, D> makeInstance() {
- return new ReferenceBasedOutlierDetection<V, D>(k, distanceFunction, refp);
+ return new ReferenceBasedOutlierDetection<>(k, distanceFunction, refp);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/SimpleCOP.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/SimpleCOP.java
index e8077819..38820ab7 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/SimpleCOP.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/SimpleCOP.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -41,11 +41,11 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
@@ -107,7 +107,7 @@ public class SimpleCOP<V extends NumberVector<?>, D extends NumberDistance<D, ?>
public SimpleCOP(DistanceFunction<? super V, D> distanceFunction, int k, PCAFilteredRunner<V> pca) {
super(distanceFunction);
this.k = k;
- this.dependencyDerivator = new DependencyDerivator<V, D>(null, FormatUtil.NF8, pca, 0, false);
+ this.dependencyDerivator = new DependencyDerivator<>(null, FormatUtil.NF, pca, 0, false);
}
public OutlierResult run(Database database, Relation<V> data) throws IllegalStateException {
@@ -124,7 +124,7 @@ public class SimpleCOP<V extends NumberVector<?>, D extends NumberDistance<D, ?>
FiniteProgress progressLocalPCA = LOG.isVerbose() ? new FiniteProgress("Correlation Outlier Probabilities", data.size(), LOG) : null;
double sqrt2 = Math.sqrt(2.0);
for (DBIDIter id = data.iterDBIDs(); id.valid(); id.advance()) {
- KNNResult<D> neighbors = knnQuery.getKNNForDBID(id, k + 1);
+ KNNList<D> neighbors = knnQuery.getKNNForDBID(id, k + 1);
ModifiableDBIDs nids = DBIDUtil.newArray(neighbors);
nids.remove(id);
@@ -156,14 +156,14 @@ public class SimpleCOP<V extends NumberVector<?>, D extends NumberDistance<D, ?>
}
}
// combine results.
- Relation<Double> scoreResult = new MaterializedRelation<Double>("Original Correlation Outlier Probabilities", "origcop-outlier", TypeUtil.DOUBLE, cop_score, ids);
+ Relation<Double> scoreResult = new MaterializedRelation<>("Original Correlation Outlier Probabilities", "origcop-outlier", TypeUtil.DOUBLE, cop_score, ids);
OutlierScoreMeta scoreMeta = new ProbabilisticOutlierScore();
OutlierResult result = new OutlierResult(scoreMeta, scoreResult);
// extra results
- result.addChildResult(new MaterializedRelation<Integer>("Local Dimensionality", COP.COP_DIM, TypeUtil.INTEGER, cop_dim, ids));
- result.addChildResult(new MaterializedRelation<Vector>("Error vectors", COP.COP_ERRORVEC, TypeUtil.VECTOR, cop_err_v, ids));
- result.addChildResult(new MaterializedRelation<Matrix>("Data vectors", "cop-datavec", TypeUtil.MATRIX, cop_datav, ids));
- result.addChildResult(new MaterializedRelation<CorrelationAnalysisSolution<?>>("Correlation analysis", "cop-sol", new SimpleTypeInformation<CorrelationAnalysisSolution<?>>(CorrelationAnalysisSolution.class), cop_sol, ids));
+ result.addChildResult(new MaterializedRelation<>("Local Dimensionality", COP.COP_DIM, TypeUtil.INTEGER, cop_dim, ids));
+ result.addChildResult(new MaterializedRelation<>("Error vectors", COP.COP_ERRORVEC, TypeUtil.VECTOR, cop_err_v, ids));
+ result.addChildResult(new MaterializedRelation<>("Data vectors", "cop-datavec", TypeUtil.MATRIX, cop_datav, ids));
+ result.addChildResult(new MaterializedRelation<>("Correlation analysis", "cop-sol", new SimpleTypeInformation<CorrelationAnalysisSolution<?>>(CorrelationAnalysisSolution.class), cop_sol, ids));
return result;
}
@@ -222,7 +222,7 @@ public class SimpleCOP<V extends NumberVector<?>, D extends NumberDistance<D, ?>
if (config.grab(kP)) {
k = kP.intValue();
}
- ObjectParameter<PCAFilteredRunner<V>> pcaP = new ObjectParameter<PCAFilteredRunner<V>>(PCARUNNER_ID, PCAFilteredRunner.class, PCAFilteredRunner.class);
+ ObjectParameter<PCAFilteredRunner<V>> pcaP = new ObjectParameter<>(PCARUNNER_ID, PCAFilteredRunner.class, PCAFilteredRunner.class);
if (config.grab(pcaP)) {
pca = pcaP.instantiateClass(config);
}
@@ -230,7 +230,7 @@ public class SimpleCOP<V extends NumberVector<?>, D extends NumberDistance<D, ?>
@Override
protected SimpleCOP<V, D> makeInstance() {
- return new SimpleCOP<V, D>(distanceFunction, k, pca);
+ return new SimpleCOP<>(distanceFunction, k, pca);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/ALOCI.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/ALOCI.java
index 41da687f..d48679a9 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/ALOCI.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/ALOCI.java
@@ -1,4 +1,4 @@
-package de.lmu.ifi.dbs.elki.algorithm.outlier;
+package de.lmu.ifi.dbs.elki.algorithm.outlier.lof;
/*
This file is part of ELKI:
@@ -28,6 +28,7 @@ import java.util.List;
import java.util.Random;
import de.lmu.ifi.dbs.elki.algorithm.AbstractAlgorithm;
+import de.lmu.ifi.dbs.elki.algorithm.outlier.OutlierAlgorithm;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
@@ -42,8 +43,8 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.database.relation.RelationUtil;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancefunction.NumberVectorDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
@@ -163,7 +164,7 @@ public class ALOCI<O extends NumberVector<?>, D extends NumberDistance<D, ?>> ex
}
}
- List<ALOCIQuadTree> qts = new ArrayList<ALOCIQuadTree>(g);
+ List<ALOCIQuadTree> qts = new ArrayList<>(g);
double[] nshift = new double[dim];
ALOCIQuadTree qt = new ALOCIQuadTree(min, max, nshift, nmin, relation);
@@ -251,7 +252,7 @@ public class ALOCI<O extends NumberVector<?>, D extends NumberDistance<D, ?>> ex
if(progressLOCI != null) {
progressLOCI.ensureCompleted(LOG);
}
- Relation<Double> scoreResult = new MaterializedRelation<Double>("aLOCI normalized MDEF", "aloci-mdef-outlier", TypeUtil.DOUBLE, mdef_norm, relation.getDBIDs());
+ Relation<Double> scoreResult = new MaterializedRelation<>("aLOCI normalized MDEF", "aloci-mdef-outlier", TypeUtil.DOUBLE, mdef_norm, relation.getDBIDs());
OutlierScoreMeta scoreMeta = new QuotientOutlierScoreMeta(minmax.getMin(), minmax.getMax(), 0.0, Double.POSITIVE_INFINITY);
OutlierResult result = new OutlierResult(scoreMeta, scoreResult);
return result;
@@ -370,7 +371,7 @@ public class ALOCI<O extends NumberVector<?>, D extends NumberDistance<D, ?>> ex
}
this.relation = relation;
ArrayModifiableDBIDs ids = DBIDUtil.newArray(relation.getDBIDs());
- List<Node> children = new ArrayList<Node>();
+ List<Node> children = new ArrayList<>();
bulkLoad(min.clone(), max.clone(), children, ids, 0, ids.size(), 0, 0, 0);
this.root = new Node(0, new Vector(center), ids.size(), -1, children);
}
@@ -432,7 +433,7 @@ public class ALOCI<O extends NumberVector<?>, D extends NumberDistance<D, ?>> ex
return;
}
else {
- List<Node> newchildren = new ArrayList<Node>();
+ List<Node> newchildren = new ArrayList<>();
bulkLoad(lmin, lmax, newchildren, ids, start, end, 0, level + 1, 0);
children.add(new Node(code, new Vector(center), end - start, level, newchildren));
return;
@@ -730,7 +731,7 @@ public class ALOCI<O extends NumberVector<?>, D extends NumberDistance<D, ?>> ex
@Override
protected ALOCI<O, D> makeInstance() {
- return new ALOCI<O, D>(distanceFunction, nmin, alpha, g, rnd);
+ return new ALOCI<>(distanceFunction, nmin, alpha, g, rnd);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/LOF.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/FlexibleLOF.java
index 66bed47a..80f60e8b 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/LOF.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/FlexibleLOF.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.algorithm.outlier;
+package de.lmu.ifi.dbs.elki.algorithm.outlier.lof;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,9 +25,11 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier;
import de.lmu.ifi.dbs.elki.algorithm.AbstractAlgorithm;
import de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm;
+import de.lmu.ifi.dbs.elki.algorithm.outlier.OutlierAlgorithm;
import de.lmu.ifi.dbs.elki.data.type.CombinedTypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.database.QueryUtil;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
@@ -36,6 +38,10 @@ import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
@@ -44,10 +50,6 @@ import de.lmu.ifi.dbs.elki.database.query.rknn.RKNNQuery;
import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultIter;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceDBIDResultIter;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceKNNList;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNPreprocessor;
import de.lmu.ifi.dbs.elki.logging.Logging;
@@ -70,8 +72,7 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
/**
* <p>
- * Algorithm to compute density-based local outlier factors in a database based
- * on a specified parameter {@link #K_ID} ({@code -lof.k}).
+ * Flexible variant of the "Local Outlier Factor" algorithm.
* </p>
*
* <p>
@@ -85,14 +86,15 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
* The k nearest neighbors are determined using the parameter
* {@link de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm#DISTANCE_FUNCTION_ID}
* , while the reference set used in reachability distance computation is
- * configured using {@link #REACHABILITY_DISTANCE_FUNCTION_ID}.
+ * configured using {@link Parameterizer#REACHABILITY_DISTANCE_FUNCTION_ID}.
* </p>
*
* <p>
- * The original LOF parameter was called &quot;minPts&quot;. Since kNN queries
- * in ELKI have slightly different semantics - exactly k neighbors are returned
- * - we chose to rename the parameter to {@link #K_ID} ({@code -lof.k}) to
- * reflect this difference.
+ * The original LOF parameter was called &quot;minPts&quot;. For consistency
+ * with the name "kNN query", we chose to rename the parameter to {@code k}.
+ * Flexible LOF allows you to set the two values different, which yields the
+ * parameters {@link Parameterizer#KREF_ID} ({@code -lof.krefer}) and
+ * {@link Parameterizer#KREACH_ID} ({@code -lof.kreach})
* </p>
*
* <p>
@@ -116,33 +118,26 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
@Title("LOF: Local Outlier Factor")
@Description("Algorithm to compute density-based local outlier factors in a database based on the neighborhood size parameter 'k'")
@Reference(authors = "M. M. Breunig, H.-P. Kriegel, R. Ng, and J. Sander", title = "LOF: Identifying Density-Based Local Outliers", booktitle = "Proc. 2nd ACM SIGMOD Int. Conf. on Management of Data (SIGMOD '00), Dallas, TX, 2000", url = "http://dx.doi.org/10.1145/342009.335388")
-public class LOF<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<OutlierResult> implements OutlierAlgorithm {
+public class FlexibleLOF<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<OutlierResult> implements OutlierAlgorithm {
/**
* The logger for this class.
*/
- private static final Logging LOG = Logging.getLogger(LOF.class);
+ private static final Logging LOG = Logging.getLogger(FlexibleLOF.class);
/**
- * The distance function to determine the reachability distance between
- * database objects.
+ * Number of neighbors in comparison set.
*/
- public static final OptionID REACHABILITY_DISTANCE_FUNCTION_ID = new OptionID("lof.reachdistfunction", "Distance function to determine the reachability distance between database objects.");
+ protected int krefer = 2;
/**
- * Parameter to specify the number of nearest neighbors of an object to be
- * considered for computing its LOF_SCORE, must be an integer greater than 1.
+ * Number of neighbors used for reachability distance.
*/
- public static final OptionID K_ID = new OptionID("lof.k", "The number of nearest neighbors of an object to be considered for computing its LOF_SCORE.");
-
- /**
- * Holds the value of {@link #K_ID}.
- */
- protected int k = 2;
+ protected int kreach = 2;
/**
* Neighborhood distance function.
*/
- protected DistanceFunction<? super O, D> neighborhoodDistanceFunction;
+ protected DistanceFunction<? super O, D> referenceDistanceFunction;
/**
* Reachability distance function.
@@ -160,42 +155,30 @@ public class LOF<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<Ou
/**
* Constructor.
*
- * @param k the value of k
+ * @param krefer The number of neighbors for reference
+ * @param kreach The number of neighbors for reachability distance
* @param neighborhoodDistanceFunction the neighborhood distance function
* @param reachabilityDistanceFunction the reachability distance function
*/
- public LOF(int k, DistanceFunction<? super O, D> neighborhoodDistanceFunction, DistanceFunction<? super O, D> reachabilityDistanceFunction) {
+ public FlexibleLOF(int krefer, int kreach, DistanceFunction<? super O, D> neighborhoodDistanceFunction, DistanceFunction<? super O, D> reachabilityDistanceFunction) {
super();
- this.k = k + (objectIsInKNN ? 0 : 1);
- this.neighborhoodDistanceFunction = neighborhoodDistanceFunction;
+ this.krefer = krefer + (objectIsInKNN ? 0 : 1);
+ this.kreach = kreach + (objectIsInKNN ? 0 : 1);
+ this.referenceDistanceFunction = neighborhoodDistanceFunction;
this.reachabilityDistanceFunction = reachabilityDistanceFunction;
}
/**
- * Constructor.
- *
- * @param k the value of k
- * @param distanceFunction the distance function
- *
- * Uses the same distance function for neighborhood computation and
- * reachability distance (standard as in the original publication),
- * same as {@link #LOF(int, DistanceFunction, DistanceFunction)
- * LOF(int, distanceFunction, distanceFunction)}.
- */
- public LOF(int k, DistanceFunction<? super O, D> distanceFunction) {
- this(k, distanceFunction, distanceFunction);
- }
-
- /**
- * Performs the Generalized LOF_SCORE algorithm on the given database by
- * calling {@link #doRunInTime}.
+ * Performs the Generalized LOF algorithm on the given database by calling
+ * {@link #doRunInTime}.
*
+ * @param database Database to query
* @param relation Data to process
* @return LOF outlier result
*/
- public OutlierResult run(Relation<O> relation) {
+ public OutlierResult run(Database database, Relation<O> relation) {
StepProgress stepprog = LOG.isVerbose() ? new StepProgress("LOF", 3) : null;
- Pair<KNNQuery<O, D>, KNNQuery<O, D>> pair = getKNNQueries(relation, stepprog);
+ Pair<KNNQuery<O, D>, KNNQuery<O, D>> pair = getKNNQueries(database, relation, stepprog);
KNNQuery<O, D> kNNRefer = pair.getFirst();
KNNQuery<O, D> kNNReach = pair.getSecond();
return doRunInTime(relation.getDBIDs(), kNNRefer, kNNReach, stepprog).getResult();
@@ -208,40 +191,41 @@ public class LOF<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<Ou
* @param stepprog the progress logger
* @return the kNN queries for the algorithm
*/
- private Pair<KNNQuery<O, D>, KNNQuery<O, D>> getKNNQueries(Relation<O> relation, StepProgress stepprog) {
+ private Pair<KNNQuery<O, D>, KNNQuery<O, D>> getKNNQueries(Database database, Relation<O> relation, StepProgress stepprog) {
// "HEAVY" flag for knnReach since it is used more than once
- KNNQuery<O, D> knnReach = QueryUtil.getKNNQuery(relation, reachabilityDistanceFunction, k, DatabaseQuery.HINT_HEAVY_USE, DatabaseQuery.HINT_OPTIMIZED_ONLY, DatabaseQuery.HINT_NO_CACHE);
+ KNNQuery<O, D> knnReach = QueryUtil.getKNNQuery(relation, reachabilityDistanceFunction, kreach, DatabaseQuery.HINT_HEAVY_USE, DatabaseQuery.HINT_OPTIMIZED_ONLY, DatabaseQuery.HINT_NO_CACHE);
// No optimized kNN query - use a preprocessor!
if (!(knnReach instanceof PreprocessorKNNQuery)) {
if (stepprog != null) {
- if (neighborhoodDistanceFunction.equals(reachabilityDistanceFunction)) {
+ if (referenceDistanceFunction.equals(reachabilityDistanceFunction)) {
stepprog.beginStep(1, "Materializing neighborhoods w.r.t. reference neighborhood distance function.", LOG);
} else {
stepprog.beginStep(1, "Not materializing neighborhoods w.r.t. reference neighborhood distance function, but materializing neighborhoods w.r.t. reachability distance function.", LOG);
}
}
- MaterializeKNNPreprocessor<O, D> preproc = new MaterializeKNNPreprocessor<O, D>(relation, reachabilityDistanceFunction, k);
- relation.getDatabase().addIndex(preproc);
- DistanceQuery<O, D> rdq = relation.getDatabase().getDistanceQuery(relation, reachabilityDistanceFunction);
- knnReach = preproc.getKNNQuery(rdq, k);
+ int kpreproc = (referenceDistanceFunction.equals(reachabilityDistanceFunction)) ? Math.max(kreach, krefer) : kreach;
+ MaterializeKNNPreprocessor<O, D> preproc = new MaterializeKNNPreprocessor<>(relation, reachabilityDistanceFunction, kpreproc);
+ database.addIndex(preproc);
+ DistanceQuery<O, D> rdq = database.getDistanceQuery(relation, reachabilityDistanceFunction);
+ knnReach = preproc.getKNNQuery(rdq, kreach);
}
// knnReach is only used once
KNNQuery<O, D> knnRefer;
- if (neighborhoodDistanceFunction == reachabilityDistanceFunction || neighborhoodDistanceFunction.equals(reachabilityDistanceFunction)) {
+ if (referenceDistanceFunction == reachabilityDistanceFunction || referenceDistanceFunction.equals(reachabilityDistanceFunction)) {
knnRefer = knnReach;
} else {
// do not materialize the first neighborhood, since it is used only once
- knnRefer = QueryUtil.getKNNQuery(relation, neighborhoodDistanceFunction, k);
+ knnRefer = QueryUtil.getKNNQuery(relation, referenceDistanceFunction, krefer);
}
- return new Pair<KNNQuery<O, D>, KNNQuery<O, D>>(knnRefer, knnReach);
+ return new Pair<>(knnRefer, knnReach);
}
/**
* Performs the Generalized LOF_SCORE algorithm on the given database and
- * returns a {@link LOF.LOFResult} encapsulating information that may be
- * needed by an OnlineLOF algorithm.
+ * returns a {@link FlexibleLOF.LOFResult} encapsulating information that may
+ * be needed by an OnlineLOF algorithm.
*
* @param ids Object ids
* @param kNNRefer the kNN query w.r.t. reference neighborhood distance
@@ -279,11 +263,11 @@ public class LOF<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<Ou
}
// Build result representation.
- Relation<Double> scoreResult = new MaterializedRelation<Double>("Local Outlier Factor", "lof-outlier", TypeUtil.DOUBLE, lofs, ids);
+ Relation<Double> scoreResult = new MaterializedRelation<>("Local Outlier Factor", "lof-outlier", TypeUtil.DOUBLE, lofs, ids);
OutlierScoreMeta scoreMeta = new QuotientOutlierScoreMeta(lofminmax.getMin(), lofminmax.getMax(), 0.0, Double.POSITIVE_INFINITY, 1.0);
OutlierResult result = new OutlierResult(scoreMeta, scoreResult);
- return new LOFResult<O, D>(result, kNNRefer, kNNReach, lrds, lofs);
+ return new LOFResult<>(result, kNNRefer, kNNReach, lrds, lofs);
}
/**
@@ -298,14 +282,14 @@ public class LOF<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<Ou
WritableDoubleDataStore lrds = DataStoreUtil.makeDoubleStorage(ids, DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP);
FiniteProgress lrdsProgress = LOG.isVerbose() ? new FiniteProgress("LRD", ids.size(), LOG) : null;
for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
- final KNNResult<D> neighbors = knnReach.getKNNForDBID(iter, k);
+ final KNNList<D> neighbors = knnReach.getKNNForDBID(iter, kreach);
double sum = 0.0;
int count = 0;
if (neighbors instanceof DoubleDistanceKNNList) {
// Fast version for double distances
- for (DoubleDistanceDBIDResultIter neighbor = ((DoubleDistanceKNNList) neighbors).iter(); neighbor.valid(); neighbor.advance()) {
+ for (DoubleDistanceDBIDListIter neighbor = ((DoubleDistanceKNNList) neighbors).iter(); neighbor.valid(); neighbor.advance()) {
if (objectIsInKNN || !DBIDUtil.equal(neighbor, iter)) {
- KNNResult<D> neighborsNeighbors = knnReach.getKNNForDBID(neighbor, k);
+ KNNList<D> neighborsNeighbors = knnReach.getKNNForDBID(neighbor, kreach);
final double nkdist;
if (neighborsNeighbors instanceof DoubleDistanceKNNList) {
nkdist = ((DoubleDistanceKNNList) neighborsNeighbors).doubleKNNDistance();
@@ -317,16 +301,16 @@ public class LOF<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<Ou
}
}
} else {
- for (DistanceDBIDResultIter<D> neighbor = neighbors.iter(); neighbor.valid(); neighbor.advance()) {
+ for (DistanceDBIDListIter<D> neighbor = neighbors.iter(); neighbor.valid(); neighbor.advance()) {
if (objectIsInKNN || !DBIDUtil.equal(neighbor, iter)) {
- KNNResult<D> neighborsNeighbors = knnReach.getKNNForDBID(neighbor, k);
+ KNNList<D> neighborsNeighbors = knnReach.getKNNForDBID(neighbor, kreach);
sum += Math.max(neighbor.getDistance().doubleValue(), neighborsNeighbors.getKNNDistance().doubleValue());
count++;
}
}
}
// Avoid division by 0
- final double lrd = (sum > 0) ? (count / sum) : 0;
+ final double lrd = (sum > 0) ? (count / sum) : Double.POSITIVE_INFINITY;
lrds.putDouble(iter, lrd);
if (lrdsProgress != null) {
lrdsProgress.incrementProcessed(LOG);
@@ -356,8 +340,8 @@ public class LOF<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<Ou
for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
final double lrdp = lrds.doubleValue(iter);
final double lof;
- if (lrdp > 0) {
- final KNNResult<D> neighbors = knnRefer.getKNNForDBID(iter, k);
+ if (lrdp > 0 && !Double.isInfinite(lrdp)) {
+ final KNNList<D> neighbors = knnRefer.getKNNForDBID(iter, krefer);
double sum = 0.0;
int count = 0;
for (DBIDIter neighbor = neighbors.iter(); neighbor.valid(); neighbor.advance()) {
@@ -373,7 +357,9 @@ public class LOF<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<Ou
}
lofs.putDouble(iter, lof);
// update minimum and maximum
- lofminmax.put(lof);
+ if (!Double.isInfinite(lof)) {
+ lofminmax.put(lof);
+ }
if (progressLOFs != null) {
progressLOFs.incrementProcessed(LOG);
@@ -382,16 +368,16 @@ public class LOF<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<Ou
if (progressLOFs != null) {
progressLOFs.ensureCompleted(LOG);
}
- return new Pair<WritableDoubleDataStore, DoubleMinMax>(lofs, lofminmax);
+ return new Pair<>(lofs, lofminmax);
}
@Override
public TypeInformation[] getInputTypeRestriction() {
final TypeInformation type;
- if (reachabilityDistanceFunction.equals(neighborhoodDistanceFunction)) {
+ if (reachabilityDistanceFunction.equals(referenceDistanceFunction)) {
type = reachabilityDistanceFunction.getInputTypeRestriction();
} else {
- type = new CombinedTypeInformation(neighborhoodDistanceFunction.getInputTypeRestriction(), reachabilityDistanceFunction.getInputTypeRestriction());
+ type = new CombinedTypeInformation(referenceDistanceFunction.getInputTypeRestriction(), reachabilityDistanceFunction.getInputTypeRestriction());
}
return TypeUtil.array(type);
}
@@ -403,11 +389,13 @@ public class LOF<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<Ou
/**
* Encapsulates information like the neighborhood, the LRD and LOF values of
- * the objects during a run of the {@link LOF} algorithm.
+ * the objects during a run of the {@link FlexibleLOF} algorithm.
+ *
+ * @author Elke Achtert
*/
public static class LOFResult<O, D extends NumberDistance<D, ?>> {
/**
- * The result of the run of the {@link LOF} algorithm.
+ * The result of the run of the {@link FlexibleLOF} algorithm.
*/
private OutlierResult result;
@@ -442,10 +430,10 @@ public class LOF<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<Ou
private final WritableDoubleDataStore lofs;
/**
- * Encapsulates information generated during a run of the {@link LOF}
- * algorithm.
+ * Encapsulates information generated during a run of the
+ * {@link FlexibleLOF} algorithm.
*
- * @param result the result of the run of the {@link LOF} algorithm
+ * @param result the result of the run of the {@link FlexibleLOF} algorithm
* @param kNNRefer the kNN query w.r.t. the reference neighborhood distance
* @param kNNReach the kNN query w.r.t. the reachability distance
* @param lrds the LRD values of the objects
@@ -498,7 +486,7 @@ public class LOF<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<Ou
/**
* Get the outlier result.
*
- * @return the result of the run of the {@link LOF} algorithm
+ * @return the result of the run of the {@link FlexibleLOF} algorithm
*/
public OutlierResult getResult() {
return result;
@@ -550,9 +538,33 @@ public class LOF<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<Ou
*/
public static class Parameterizer<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBasedAlgorithm.Parameterizer<O, D> {
/**
- * The neighborhood size to use.
+ * The distance function to determine the reachability distance between
+ * database objects.
+ */
+ public static final OptionID REACHABILITY_DISTANCE_FUNCTION_ID = new OptionID("lof.reachdistfunction", "Distance function to determine the reachability distance between database objects.");
+
+ /**
+ * Parameter to specify the number of nearest neighbors of an object to be
+ * considered for computing its LOF_SCORE, must be an integer greater than
+ * 1.
+ */
+ public static final OptionID KREF_ID = new OptionID("lof.krefer", "The number of nearest neighbors of an object to be considered for computing its LOF_SCORE.");
+
+ /**
+ * Parameter to specify the number of nearest neighbors of an object to be
+ * considered for computing its reachability distance.
+ */
+ public static final OptionID KREACH_ID = new OptionID("lof.kreach", "The number of nearest neighbors of an object to be considered for computing its LOF_SCORE.");
+
+ /**
+ * The reference set size to use.
*/
- protected int k = 2;
+ protected int krefer = 2;
+
+ /**
+ * The set size to use for reachability distance.
+ */
+ protected int kreach = 2;
/**
* Neighborhood distance function.
@@ -568,23 +580,33 @@ public class LOF<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<Ou
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- final IntParameter pK = new IntParameter(K_ID);
+ final IntParameter pK = new IntParameter(KREF_ID);
pK.addConstraint(new GreaterConstraint(1));
if (config.grab(pK)) {
- k = pK.getValue();
+ krefer = pK.intValue();
}
- final ObjectParameter<DistanceFunction<O, D>> reachDistP = new ObjectParameter<DistanceFunction<O, D>>(REACHABILITY_DISTANCE_FUNCTION_ID, DistanceFunction.class, true);
+ final IntParameter pK2 = new IntParameter(KREACH_ID);
+ pK2.setOptional(true);
+ pK2.addConstraint(new GreaterConstraint(1));
+ if (config.grab(pK2)) {
+ kreach = pK2.intValue();
+ } else {
+ kreach = krefer;
+ }
+
+ final ObjectParameter<DistanceFunction<O, D>> reachDistP = new ObjectParameter<>(REACHABILITY_DISTANCE_FUNCTION_ID, DistanceFunction.class);
+ reachDistP.setOptional(true);
if (config.grab(reachDistP)) {
reachabilityDistanceFunction = reachDistP.instantiateClass(config);
+ } else {
+ reachabilityDistanceFunction = distanceFunction;
}
}
@Override
- protected LOF<O, D> makeInstance() {
- // Default is to re-use the same distance
- DistanceFunction<O, D> rdist = (reachabilityDistanceFunction != null) ? reachabilityDistanceFunction : distanceFunction;
- return new LOF<O, D>(k, distanceFunction, rdist);
+ protected FlexibleLOF<O, D> makeInstance() {
+ return new FlexibleLOF<>(kreach, krefer, distanceFunction, reachabilityDistanceFunction);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/INFLO.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/INFLO.java
index 655a0910..ae297a3c 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/INFLO.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/INFLO.java
@@ -1,4 +1,4 @@
-package de.lmu.ifi.dbs.elki.algorithm.outlier;
+package de.lmu.ifi.dbs.elki.algorithm.outlier.lof;
/*
This file is part of ELKI:
@@ -24,6 +24,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier;
*/
import de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm;
+import de.lmu.ifi.dbs.elki.algorithm.outlier.OutlierAlgorithm;
import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
import de.lmu.ifi.dbs.elki.database.Database;
@@ -34,13 +35,13 @@ import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
@@ -154,7 +155,7 @@ public class INFLO<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBa
int count = rnns.get(id).size();
if (!processedIDs.contains(id)) {
// TODO: use exactly k neighbors?
- KNNResult<D> list = knnQuery.getKNNForDBID(id, k);
+ KNNList<D> list = knnQuery.getKNNForDBID(id, k);
knns.get(id).addDBIDs(list);
processedIDs.add(id);
density.putDouble(id, 1 / list.getKNNDistance().doubleValue());
@@ -164,7 +165,7 @@ public class INFLO<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBa
for (DBIDIter q = knns.get(id).iter(); q.valid(); q.advance()) {
if (!processedIDs.contains(q)) {
// TODO: use exactly k neighbors?
- KNNResult<D> listQ = knnQuery.getKNNForDBID(q, k);
+ KNNList<D> listQ = knnQuery.getKNNForDBID(q, k);
knns.get(q).addDBIDs(listQ);
density.putDouble(q, 1 / listQ.getKNNDistance().doubleValue());
processedIDs.add(q);
@@ -209,7 +210,7 @@ public class INFLO<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBa
}
// Build result representation.
- Relation<Double> scoreResult = new MaterializedRelation<Double>("Influence Outlier Score", "inflo-outlier", TypeUtil.DOUBLE, inflos, relation.getDBIDs());
+ Relation<Double> scoreResult = new MaterializedRelation<>("Influence Outlier Score", "inflo-outlier", TypeUtil.DOUBLE, inflos, relation.getDBIDs());
OutlierScoreMeta scoreMeta = new QuotientOutlierScoreMeta(inflominmax.getMin(), inflominmax.getMax(), 0.0, Double.POSITIVE_INFINITY, 1.0);
return new OutlierResult(scoreMeta, scoreResult);
}
@@ -254,7 +255,7 @@ public class INFLO<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBa
@Override
protected INFLO<O, D> makeInstance() {
- return new INFLO<O, D>(distanceFunction, m, k);
+ return new INFLO<>(distanceFunction, m, k);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/LDF.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/LDF.java
index 4ce0313e..4a86e93d 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/LDF.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/LDF.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.algorithm.outlier;
+package de.lmu.ifi.dbs.elki.algorithm.outlier.lof;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,10 +24,12 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier;
*/
import de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm;
+import de.lmu.ifi.dbs.elki.algorithm.outlier.OutlierAlgorithm;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.data.type.CombinedTypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.database.QueryUtil;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
@@ -35,6 +37,10 @@ import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
@@ -43,18 +49,14 @@ import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.database.relation.RelationUtil;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultIter;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceDBIDResultIter;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceKNNList;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNPreprocessor;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
import de.lmu.ifi.dbs.elki.logging.progress.StepProgress;
import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
-import de.lmu.ifi.dbs.elki.math.statistics.GaussianKernelDensityFunction;
-import de.lmu.ifi.dbs.elki.math.statistics.KernelDensityFunction;
+import de.lmu.ifi.dbs.elki.math.statistics.kernelfunctions.GaussianKernelDensityFunction;
+import de.lmu.ifi.dbs.elki.math.statistics.kernelfunctions.KernelDensityFunction;
import de.lmu.ifi.dbs.elki.result.outlier.BasicOutlierScoreMeta;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierScoreMeta;
@@ -133,10 +135,11 @@ public class LDF<O extends NumberVector<?>, D extends NumberDistance<D, ?>> exte
/**
* Run the naive kernel density LOF algorithm.
*
+ * @param database Database to query
* @param relation Data to process
* @return LOF outlier result
*/
- public OutlierResult run(Relation<O> relation) {
+ public OutlierResult run(Database database, Relation<O> relation) {
StepProgress stepprog = LOG.isVerbose() ? new StepProgress("LDF", 3) : null;
final int dim = RelationUtil.dimensionality(relation);
@@ -150,43 +153,54 @@ public class LDF<O extends NumberVector<?>, D extends NumberDistance<D, ?>> exte
if (stepprog != null) {
stepprog.beginStep(1, "Materializing neighborhoods w.r.t. distance function.", LOG);
}
- MaterializeKNNPreprocessor<O, D> preproc = new MaterializeKNNPreprocessor<O, D>(relation, getDistanceFunction(), k);
- relation.getDatabase().addIndex(preproc);
- DistanceQuery<O, D> rdq = relation.getDatabase().getDistanceQuery(relation, getDistanceFunction());
+ MaterializeKNNPreprocessor<O, D> preproc = new MaterializeKNNPreprocessor<>(relation, getDistanceFunction(), k);
+ database.addIndex(preproc);
+ DistanceQuery<O, D> rdq = database.getDistanceQuery(relation, getDistanceFunction());
knnq = preproc.getKNNQuery(rdq, k);
}
- // Compute LRDs
+ // Compute LDEs
if (stepprog != null) {
stepprog.beginStep(2, "Computing LDEs.", LOG);
}
WritableDoubleDataStore ldes = DataStoreUtil.makeDoubleStorage(ids, DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP);
FiniteProgress densProgress = LOG.isVerbose() ? new FiniteProgress("Densities", ids.size(), LOG) : null;
for (DBIDIter it = ids.iter(); it.valid(); it.advance()) {
- final KNNResult<D> neighbors = knnq.getKNNForDBID(it, k);
+ final KNNList<D> neighbors = knnq.getKNNForDBID(it, k);
double sum = 0.0;
int count = 0;
if (neighbors instanceof DoubleDistanceKNNList) {
// Fast version for double distances
- for (DoubleDistanceDBIDResultIter neighbor = ((DoubleDistanceKNNList) neighbors).iter(); neighbor.valid(); neighbor.advance()) {
+ for (DoubleDistanceDBIDListIter neighbor = ((DoubleDistanceKNNList) neighbors).iter(); neighbor.valid(); neighbor.advance()) {
if (DBIDUtil.equal(neighbor, it)) {
continue;
}
- double nkdist = ((DoubleDistanceKNNList) knnq.getKNNForDBID(neighbor, k)).doubleKNNDistance();
-
- final double v = Math.max(nkdist, neighbor.doubleDistance()) / (h * nkdist);
- sum += kernel.density(v) / Math.pow(h * nkdist, dim);
- count++;
+ final double nkdist = ((DoubleDistanceKNNList) knnq.getKNNForDBID(neighbor, k)).doubleKNNDistance();
+ if (nkdist > 0.) {
+ final double v = Math.max(nkdist, neighbor.doubleDistance()) / (h * nkdist);
+ sum += kernel.density(v) / Math.pow(h * nkdist, dim);
+ count++;
+ } else {
+ sum = Double.POSITIVE_INFINITY;
+ count++;
+ break;
+ }
}
} else {
- for (DistanceDBIDResultIter<D> neighbor = neighbors.iter(); neighbor.valid(); neighbor.advance()) {
+ for (DistanceDBIDListIter<D> neighbor = neighbors.iter(); neighbor.valid(); neighbor.advance()) {
if (DBIDUtil.equal(neighbor, it)) {
continue;
}
- double nkdist = knnq.getKNNForDBID(neighbor, k).getKNNDistance().doubleValue();
- final double v = Math.max(nkdist, neighbor.getDistance().doubleValue()) / (h * nkdist);
- sum += kernel.density(v) / Math.pow(h * nkdist, dim);
- count++;
+ final double nkdist = knnq.getKNNForDBID(neighbor, k).getKNNDistance().doubleValue();
+ if (nkdist > 0.) {
+ final double v = Math.max(nkdist, neighbor.getDistance().doubleValue()) / (h * nkdist);
+ sum += kernel.density(v) / Math.pow(h * nkdist, dim);
+ count++;
+ } else {
+ sum = Double.POSITIVE_INFINITY;
+ count++;
+ break;
+ }
}
}
ldes.putDouble(it, sum / count);
@@ -209,7 +223,7 @@ public class LDF<O extends NumberVector<?>, D extends NumberDistance<D, ?>> exte
FiniteProgress progressLOFs = LOG.isVerbose() ? new FiniteProgress("Local Density Factors", ids.size(), LOG) : null;
for (DBIDIter it = ids.iter(); it.valid(); it.advance()) {
final double lrdp = ldes.doubleValue(it);
- final KNNResult<D> neighbors = knnq.getKNNForDBID(it, k);
+ final KNNList<D> neighbors = knnq.getKNNForDBID(it, k);
double sum = 0.0;
int count = 0;
for (DBIDIter neighbor = neighbors.iter(); neighbor.valid(); neighbor.advance()) {
@@ -240,7 +254,7 @@ public class LDF<O extends NumberVector<?>, D extends NumberDistance<D, ?>> exte
}
// Build result representation.
- Relation<Double> scoreResult = new MaterializedRelation<Double>("Local Density Factor", "ldf-outlier", TypeUtil.DOUBLE, ldfs, ids);
+ Relation<Double> scoreResult = new MaterializedRelation<>("Local Density Factor", "ldf-outlier", TypeUtil.DOUBLE, ldfs, ids);
OutlierScoreMeta scoreMeta = new BasicOutlierScoreMeta(lofminmax.getMin(), lofminmax.getMax(), 0.0, 1. / c, 1 / (1 + c));
OutlierResult result = new OutlierResult(scoreMeta, scoreResult);
@@ -318,7 +332,7 @@ public class LDF<O extends NumberVector<?>, D extends NumberDistance<D, ?>> exte
k = pK.getValue();
}
- ObjectParameter<KernelDensityFunction> kernelP = new ObjectParameter<KernelDensityFunction>(KERNEL_ID, KernelDensityFunction.class, GaussianKernelDensityFunction.class);
+ ObjectParameter<KernelDensityFunction> kernelP = new ObjectParameter<>(KERNEL_ID, KernelDensityFunction.class, GaussianKernelDensityFunction.class);
if (config.grab(kernelP)) {
kernel = kernelP.instantiateClass(config);
}
@@ -336,7 +350,7 @@ public class LDF<O extends NumberVector<?>, D extends NumberDistance<D, ?>> exte
@Override
protected LDF<O, D> makeInstance() {
- return new LDF<O, D>(k, distanceFunction, kernel, h, c);
+ return new LDF<>(k, distanceFunction, kernel, h, c);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/LDOF.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/LDOF.java
index fbbfe484..80ed3f68 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/LDOF.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/LDOF.java
@@ -1,4 +1,4 @@
-package de.lmu.ifi.dbs.elki.algorithm.outlier;
+package de.lmu.ifi.dbs.elki.algorithm.outlier.lof;
/*
This file is part of ELKI:
@@ -24,6 +24,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier;
*/
import de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm;
+import de.lmu.ifi.dbs.elki.algorithm.outlier.OutlierAlgorithm;
import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
import de.lmu.ifi.dbs.elki.database.Database;
@@ -32,13 +33,13 @@ import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultIter;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
@@ -47,6 +48,7 @@ import de.lmu.ifi.dbs.elki.math.Mean;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierScoreMeta;
import de.lmu.ifi.dbs.elki.result.outlier.QuotientOutlierScoreMeta;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
import de.lmu.ifi.dbs.elki.utilities.documentation.Description;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
@@ -78,6 +80,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
@Title("LDOF: Local Distance-Based Outlier Factor")
@Description("Local outlier detection appraoch suitable for scattered data by averaging the kNN distance over all k nearest neighbors")
@Reference(authors = "K. Zhang, M. Hutter, H. Jin", title = "A New Local Distance-Based Outlier Detection Approach for Scattered Real-World Data", booktitle = "Proc. 13th Pacific-Asia Conference on Advances in Knowledge Discovery and Data Mining (PAKDD 2009), Bangkok, Thailand, 2009", url = "http://dx.doi.org/10.1007/978-3-642-01307-2_84")
+@Alias({"de.lmu.ifi.dbs.elki.algorithm.outlier.LDOF"})
public class LDOF<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBasedAlgorithm<O, D, OutlierResult> implements OutlierAlgorithm {
/**
* The logger for this class.
@@ -136,14 +139,14 @@ public class LDOF<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBas
Mean dxp = new Mean(), Dxp = new Mean();
for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
- KNNResult<D> neighbors = knnQuery.getKNNForDBID(iditer, k);
+ KNNList<D> neighbors = knnQuery.getKNNForDBID(iditer, k);
// skip the point itself
dxp.reset(); Dxp.reset();
// TODO: optimize for double distances
- for (DistanceDBIDResultIter<D> neighbor1 = neighbors.iter(); neighbor1.valid(); neighbor1.advance()) {
+ for (DistanceDBIDListIter<D> neighbor1 = neighbors.iter(); neighbor1.valid(); neighbor1.advance()) {
if(!DBIDUtil.equal(neighbor1, iditer)) {
dxp.put(neighbor1.getDistance().doubleValue());
- for (DistanceDBIDResultIter<D> neighbor2 = neighbors.iter(); neighbor2.valid(); neighbor2.advance()) {
+ for (DistanceDBIDListIter<D> neighbor2 = neighbors.iter(); neighbor2.valid(); neighbor2.advance()) {
if(!DBIDUtil.equal(neighbor1, neighbor2) && !DBIDUtil.equal(neighbor2, iditer)) {
Dxp.put(distFunc.distance(neighbor1, neighbor2).doubleValue());
}
@@ -167,7 +170,7 @@ public class LDOF<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBas
}
// Build result representation.
- Relation<Double> scoreResult = new MaterializedRelation<Double>("LDOF Outlier Score", "ldof-outlier", TypeUtil.DOUBLE, ldofs, relation.getDBIDs());
+ Relation<Double> scoreResult = new MaterializedRelation<>("LDOF Outlier Score", "ldof-outlier", TypeUtil.DOUBLE, ldofs, relation.getDBIDs());
OutlierScoreMeta scoreMeta = new QuotientOutlierScoreMeta(ldofminmax.getMin(), ldofminmax.getMax(), 0.0, Double.POSITIVE_INFINITY, LDOF_BASELINE);
return new OutlierResult(scoreMeta, scoreResult);
}
@@ -204,7 +207,7 @@ public class LDOF<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBas
@Override
protected LDOF<O, D> makeInstance() {
- return new LDOF<O, D>(distanceFunction, k);
+ return new LDOF<>(distanceFunction, k);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/LOCI.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/LOCI.java
index ba9ad20e..e76c6034 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/LOCI.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/LOCI.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.algorithm.outlier;
+package de.lmu.ifi.dbs.elki.algorithm.outlier.lof;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,6 +28,7 @@ import java.util.Collections;
import java.util.List;
import de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm;
+import de.lmu.ifi.dbs.elki.algorithm.outlier.OutlierAlgorithm;
import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
import de.lmu.ifi.dbs.elki.database.Database;
@@ -36,14 +37,14 @@ import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
import de.lmu.ifi.dbs.elki.database.datastore.WritableDataStore;
import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
-import de.lmu.ifi.dbs.elki.database.ids.DistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery;
import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultIter;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
@@ -52,6 +53,7 @@ import de.lmu.ifi.dbs.elki.math.MeanVariance;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierScoreMeta;
import de.lmu.ifi.dbs.elki.result.outlier.QuotientOutlierScoreMeta;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
import de.lmu.ifi.dbs.elki.utilities.documentation.Description;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
@@ -83,6 +85,7 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleIntPair;
@Title("LOCI: Fast Outlier Detection Using the Local Correlation Integral")
@Description("Algorithm to compute outliers based on the Local Correlation Integral")
@Reference(authors = "S. Papadimitriou, H. Kitagawa, P. B. Gibbons, C. Faloutsos", title = "LOCI: Fast Outlier Detection Using the Local Correlation Integral", booktitle = "Proc. 19th IEEE Int. Conf. on Data Engineering (ICDE '03), Bangalore, India, 2003", url = "http://dx.doi.org/10.1109/ICDE.2003.1260802")
+@Alias({"de.lmu.ifi.dbs.elki.algorithm.outlier.LOCI"})
public class LOCI<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBasedAlgorithm<O, D, OutlierResult> implements OutlierAlgorithm {
/**
* The logger for this class.
@@ -150,9 +153,9 @@ public class LOCI<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBas
// LOCI preprocessing step
WritableDataStore<ArrayList<DoubleIntPair>> interestingDistances = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_TEMP | DataStoreFactory.HINT_SORTED, ArrayList.class);
for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
- DistanceDBIDResult<D> neighbors = rangeQuery.getRangeForDBID(iditer, rmax);
+ DistanceDBIDList<D> neighbors = rangeQuery.getRangeForDBID(iditer, rmax);
// build list of critical distances
- ArrayList<DoubleIntPair> cdist = new ArrayList<DoubleIntPair>(neighbors.size() << 1);
+ ArrayList<DoubleIntPair> cdist = new ArrayList<>(neighbors.size() << 1);
{
for(int i = 0; i < neighbors.size(); i++) {
DistanceDBIDPair<D> r = neighbors.get(i);
@@ -203,7 +206,7 @@ public class LOCI<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBas
if(maxneig >= nmin) {
D range = distFunc.getDistanceFactory().fromDouble(maxdist);
// Compute the largest neighborhood we will need.
- DistanceDBIDResult<D> maxneighbors = rangeQuery.getRangeForDBID(iditer, range);
+ DistanceDBIDList<D> maxneighbors = rangeQuery.getRangeForDBID(iditer, range);
// TODO: Ensure the set is sorted. Should be a no-op with most indexes.
// For any critical distance, compute the normalized MDEF score.
for(DoubleIntPair c : cdist) {
@@ -218,7 +221,7 @@ public class LOCI<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBas
// compute \hat{n}(p_i, r, \alpha) and the corresponding \simga_{MDEF}
MeanVariance mv_n_r_alpha = new MeanVariance();
// TODO: optimize for double distances
- for (DistanceDBIDResultIter<D> neighbor = maxneighbors.iter(); neighbor.valid(); neighbor.advance()) {
+ for (DistanceDBIDListIter<D> neighbor = maxneighbors.iter(); neighbor.valid(); neighbor.advance()) {
// Stop at radius r
if(neighbor.getDistance().doubleValue() > r) {
break;
@@ -256,10 +259,10 @@ public class LOCI<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBas
if(progressLOCI != null) {
progressLOCI.ensureCompleted(LOG);
}
- Relation<Double> scoreResult = new MaterializedRelation<Double>("LOCI normalized MDEF", "loci-mdef-outlier", TypeUtil.DOUBLE, mdef_norm, relation.getDBIDs());
+ Relation<Double> scoreResult = new MaterializedRelation<>("LOCI normalized MDEF", "loci-mdef-outlier", TypeUtil.DOUBLE, mdef_norm, relation.getDBIDs());
OutlierScoreMeta scoreMeta = new QuotientOutlierScoreMeta(minmax.getMin(), minmax.getMax(), 0.0, Double.POSITIVE_INFINITY, 0.0);
OutlierResult result = new OutlierResult(scoreMeta, scoreResult);
- result.addChildResult(new MaterializedRelation<Double>("LOCI MDEF Radius", "loci-critical-radius", TypeUtil.DOUBLE, mdef_radius, relation.getDBIDs()));
+ result.addChildResult(new MaterializedRelation<>("LOCI MDEF Radius", "loci-critical-radius", TypeUtil.DOUBLE, mdef_radius, relation.getDBIDs()));
return result;
}
@@ -313,7 +316,7 @@ public class LOCI<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBas
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
final D distanceFactory = (distanceFunction != null) ? distanceFunction.getDistanceFactory() : null;
- final DistanceParameter<D> rmaxP = new DistanceParameter<D>(RMAX_ID, distanceFactory);
+ final DistanceParameter<D> rmaxP = new DistanceParameter<>(RMAX_ID, distanceFactory);
if(config.grab(rmaxP)) {
rmax = rmaxP.getValue();
}
@@ -331,7 +334,7 @@ public class LOCI<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBas
@Override
protected LOCI<O, D> makeInstance() {
- return new LOCI<O, D>(distanceFunction, rmax, nmin, alpha);
+ return new LOCI<>(distanceFunction, rmax, nmin, alpha);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/LOF.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/LOF.java
new file mode 100644
index 00000000..302dafe6
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/LOF.java
@@ -0,0 +1,293 @@
+package de.lmu.ifi.dbs.elki.algorithm.outlier.lof;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm;
+import de.lmu.ifi.dbs.elki.algorithm.outlier.OutlierAlgorithm;
+import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
+import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.database.Database;
+import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory;
+import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
+import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
+import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery;
+import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
+import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
+import de.lmu.ifi.dbs.elki.database.query.knn.PreprocessorKNNQuery;
+import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
+import de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNPreprocessor;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
+import de.lmu.ifi.dbs.elki.logging.progress.StepProgress;
+import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
+import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
+import de.lmu.ifi.dbs.elki.result.outlier.OutlierScoreMeta;
+import de.lmu.ifi.dbs.elki.result.outlier.QuotientOutlierScoreMeta;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Description;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
+
+/**
+ * <p>
+ * Algorithm to compute density-based local outlier factors in a database based
+ * on a specified parameter {@link Parameterizer#K_ID} ({@code -lof.k}).
+ * </p>
+ *
+ * <p>
+ * The original LOF parameter was called &quot;minPts&quot;, but for consistency
+ * within ELKI we have renamed this parameter to &quot;k&quot;.
+ * </p>
+ *
+ * <p>
+ * Reference: <br>
+ * M. M. Breunig, H.-P. Kriegel, R. Ng, J. Sander: LOF: Identifying
+ * Density-Based Local Outliers. <br>
+ * In: Proc. 2nd ACM SIGMOD Int. Conf. on Management of Data (SIGMOD'00),
+ * Dallas, TX, 2000.
+ * </p>
+ *
+ * @author Erich Schubert
+ * @author Elke Achtert
+ *
+ * @apiviz.has KNNQuery
+ *
+ * @param <O> the type of DatabaseObjects handled by this Algorithm
+ * @param <D> Distance type
+ */
+@Title("LOF: Local Outlier Factor")
+@Description("Algorithm to compute density-based local outlier factors in a database based on the neighborhood size parameter 'k'")
+@Reference(authors = "M. M. Breunig, H.-P. Kriegel, R. Ng, and J. Sander", title = "LOF: Identifying Density-Based Local Outliers", booktitle = "Proc. 2nd ACM SIGMOD Int. Conf. on Management of Data (SIGMOD '00), Dallas, TX, 2000", url = "http://dx.doi.org/10.1145/342009.335388")
+@Alias({ "de.lmu.ifi.dbs.elki.algorithm.outlier.LOF", "outlier.LOF", "LOF" })
+public class LOF<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBasedAlgorithm<O, D, OutlierResult> implements OutlierAlgorithm {
+ /**
+ * The logger for this class.
+ */
+ private static final Logging LOG = Logging.getLogger(LOF.class);
+
+ /**
+ * Holds the value of {@link Parameterizer#K_ID}.
+ */
+ protected int k = 2;
+
+ /**
+ * Constructor.
+ *
+ * @param k the value of k
+ * @param distanceFunction the neighborhood distance function
+ */
+ public LOF(int k, DistanceFunction<? super O, D> distanceFunction) {
+ super(distanceFunction);
+ this.k = k + 1;
+ }
+
+ /**
+ * Performs the Generalized LOF_SCORE algorithm on the given database.
+ *
+ * @param database Database to query
+ * @param relation Data to process
+ * @return LOF outlier result
+ */
+ public OutlierResult run(Database database, Relation<O> relation) {
+ StepProgress stepprog = LOG.isVerbose() ? new StepProgress("LOF", 3) : null;
+ DistanceQuery<O, D> dq = database.getDistanceQuery(relation, getDistanceFunction());
+ // "HEAVY" flag for knn query since it is used more than once
+ KNNQuery<O, D> knnq = database.getKNNQuery(dq, k, DatabaseQuery.HINT_HEAVY_USE, DatabaseQuery.HINT_OPTIMIZED_ONLY, DatabaseQuery.HINT_NO_CACHE);
+ // No optimized kNN query - use a preprocessor!
+ if (!(knnq instanceof PreprocessorKNNQuery)) {
+ if (stepprog != null) {
+ stepprog.beginStep(1, "Materializing LOF neighborhoods.", LOG);
+ }
+ MaterializeKNNPreprocessor<O, D> preproc = new MaterializeKNNPreprocessor<>(relation, getDistanceFunction(), k);
+ knnq = preproc.getKNNQuery(dq, k);
+ }
+ DBIDs ids = relation.getDBIDs();
+
+ // Compute LRDs
+ if (stepprog != null) {
+ stepprog.beginStep(2, "Computing LRDs.", LOG);
+ }
+ WritableDoubleDataStore lrds = DataStoreUtil.makeDoubleStorage(ids, DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP);
+ {
+ FiniteProgress lrdsProgress = LOG.isVerbose() ? new FiniteProgress("LRD", ids.size(), LOG) : null;
+ for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
+ final KNNList<D> neighbors = knnq.getKNNForDBID(iter, k);
+ double sum = 0.0;
+ int count = 0;
+ if (neighbors instanceof DoubleDistanceKNNList) {
+ // Fast version for double distances
+ for (DoubleDistanceDBIDListIter neighbor = ((DoubleDistanceKNNList) neighbors).iter(); neighbor.valid(); neighbor.advance()) {
+ if (DBIDUtil.equal(neighbor, iter)) {
+ continue;
+ }
+ KNNList<D> neighborsNeighbors = knnq.getKNNForDBID(neighbor, k);
+ final double nkdist;
+ if (neighborsNeighbors instanceof DoubleDistanceKNNList) {
+ nkdist = ((DoubleDistanceKNNList) neighborsNeighbors).doubleKNNDistance();
+ } else {
+ nkdist = neighborsNeighbors.getKNNDistance().doubleValue();
+ }
+ sum += Math.max(neighbor.doubleDistance(), nkdist);
+ count++;
+ }
+ } else {
+ for (DistanceDBIDListIter<D> neighbor = neighbors.iter(); neighbor.valid(); neighbor.advance()) {
+ if (DBIDUtil.equal(neighbor, iter)) {
+ continue;
+ }
+ KNNList<D> neighborsNeighbors = knnq.getKNNForDBID(neighbor, k);
+ sum += Math.max(neighbor.getDistance().doubleValue(), neighborsNeighbors.getKNNDistance().doubleValue());
+ count++;
+ }
+ }
+ // Avoid division by 0
+ final double lrd = (sum > 0) ? (count / sum) : Double.POSITIVE_INFINITY;
+ lrds.putDouble(iter, lrd);
+ if (lrdsProgress != null) {
+ lrdsProgress.incrementProcessed(LOG);
+ }
+ }
+ if (lrdsProgress != null) {
+ lrdsProgress.ensureCompleted(LOG);
+ }
+ }
+
+ // compute LOF_SCORE of each db object
+ if (stepprog != null) {
+ stepprog.beginStep(3, "Computing LOFs.", LOG);
+ }
+ WritableDoubleDataStore lofs = DataStoreUtil.makeDoubleStorage(ids, DataStoreFactory.HINT_STATIC);
+ // track the maximum value for normalization.
+ DoubleMinMax lofminmax = new DoubleMinMax();
+ {
+ FiniteProgress progressLOFs = LOG.isVerbose() ? new FiniteProgress("LOF_SCORE for objects", ids.size(), LOG) : null;
+ for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
+ final double lof;
+ final double lrdp = lrds.doubleValue(iter);
+ final KNNList<D> neighbors = knnq.getKNNForDBID(iter, k);
+ if (!Double.isInfinite(lrdp)) {
+ double sum = 0.0;
+ int count = 0;
+ for (DBIDIter neighbor = neighbors.iter(); neighbor.valid(); neighbor.advance()) {
+ // skip the point itself
+ if (DBIDUtil.equal(neighbor, iter)) {
+ continue;
+ }
+ final double val = lrds.doubleValue(neighbor);
+ sum += val;
+ count++;
+ if (Double.isInfinite(val)) {
+ break;
+ }
+ }
+ lof = sum / (lrdp * count);
+ } else {
+ lof = 1.0;
+ }
+ lofs.putDouble(iter, lof);
+ // update minimum and maximum
+ lofminmax.put(lof);
+
+ if (progressLOFs != null) {
+ progressLOFs.incrementProcessed(LOG);
+ }
+ }
+ if (progressLOFs != null) {
+ progressLOFs.ensureCompleted(LOG);
+ }
+ }
+
+ if (stepprog != null) {
+ stepprog.setCompleted(LOG);
+ }
+
+ // Build result representation.
+ Relation<Double> scoreResult = new MaterializedRelation<>("Local Outlier Factor", "lof-outlier", TypeUtil.DOUBLE, lofs, ids);
+ OutlierScoreMeta scoreMeta = new QuotientOutlierScoreMeta(lofminmax.getMin(), lofminmax.getMax(), 0.0, Double.POSITIVE_INFINITY, 1.0);
+ OutlierResult result = new OutlierResult(scoreMeta, scoreResult);
+
+ return result;
+ }
+
+ @Override
+ public TypeInformation[] getInputTypeRestriction() {
+ return TypeUtil.array(getDistanceFunction().getInputTypeRestriction());
+ }
+
+ @Override
+ protected Logging getLogger() {
+ return LOG;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBasedAlgorithm.Parameterizer<O, D> {
+ /**
+ * Parameter to specify the number of nearest neighbors of an object to be
+ * considered for computing its LOF_SCORE, must be an integer greater than
+ * 1.
+ */
+ public static final OptionID K_ID = new OptionID("lof.k", "The number of nearest neighbors of an object to be considered for computing its LOF_SCORE.");
+
+ /**
+ * The neighborhood size to use.
+ */
+ protected int k = 2;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+
+ final IntParameter pK = new IntParameter(K_ID);
+ pK.addConstraint(new GreaterConstraint(1));
+ if (config.grab(pK)) {
+ k = pK.getValue();
+ }
+ }
+
+ @Override
+ protected LOF<O, D> makeInstance() {
+ return new LOF<>(k, distanceFunction);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/LoOP.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/LoOP.java
index 5da06983..15ff690a 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/LoOP.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/LoOP.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.algorithm.outlier;
+package de.lmu.ifi.dbs.elki.algorithm.outlier.lof;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,6 +24,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier;
*/
import de.lmu.ifi.dbs.elki.algorithm.AbstractAlgorithm;
+import de.lmu.ifi.dbs.elki.algorithm.outlier.OutlierAlgorithm;
import de.lmu.ifi.dbs.elki.data.type.CombinedTypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
@@ -34,17 +35,17 @@ import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultIter;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceDBIDResultIter;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceKNNList;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNPreprocessor;
import de.lmu.ifi.dbs.elki.logging.Logging;
@@ -56,6 +57,7 @@ import de.lmu.ifi.dbs.elki.math.statistics.distribution.NormalDistribution;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierScoreMeta;
import de.lmu.ifi.dbs.elki.result.outlier.ProbabilisticOutlierScore;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
import de.lmu.ifi.dbs.elki.utilities.documentation.Description;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
@@ -85,6 +87,7 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
@Title("LoOP: Local Outlier Probabilities")
@Description("Variant of the LOF algorithm normalized using statistical values.")
@Reference(authors = "H.-P. Kriegel, P. Kröger, E. Schubert, A. Zimek", title = "LoOP: Local Outlier Probabilities", booktitle = "Proceedings of the 18th International Conference on Information and Knowledge Management (CIKM), Hong Kong, China, 2009", url = "http://dx.doi.org/10.1145/1645953.1646195")
+@Alias({ "de.lmu.ifi.dbs.elki.algorithm.outlier.LoOP", "LoOP", "outlier.LoOP" })
public class LoOP<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<OutlierResult> implements OutlierAlgorithm {
/**
* The logger for this class.
@@ -188,7 +191,7 @@ public class LoOP<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<O
if (stepprog != null) {
stepprog.beginStep(1, "Materializing neighborhoods with respect to reference neighborhood distance function.", LOG);
}
- MaterializeKNNPreprocessor<O, D> preproc = new MaterializeKNNPreprocessor<O, D>(relation, comparisonDistanceFunction, kcomp);
+ MaterializeKNNPreprocessor<O, D> preproc = new MaterializeKNNPreprocessor<>(relation, comparisonDistanceFunction, kcomp);
database.addIndex(preproc);
DistanceQuery<O, D> cdq = database.getDistanceQuery(relation, comparisonDistanceFunction);
knnComp = preproc.getKNNQuery(cdq, kreach, DatabaseQuery.HINT_HEAVY_USE);
@@ -205,7 +208,7 @@ public class LoOP<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<O
knnComp = QueryUtil.getKNNQuery(relation, comparisonDistanceFunction, kreach);
knnReach = QueryUtil.getKNNQuery(relation, reachabilityDistanceFunction, kcomp);
}
- return new Pair<KNNQuery<O, D>, KNNQuery<O, D>>(knnComp, knnReach);
+ return new Pair<>(knnComp, knnReach);
}
/**
@@ -241,13 +244,13 @@ public class LoOP<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<O
}
FiniteProgress prdsProgress = LOG.isVerbose() ? new FiniteProgress("pdists", relation.size(), LOG) : null;
for (DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
- final KNNResult<D> neighbors = knnReach.getKNNForDBID(iditer, kreach);
+ final KNNList<D> neighbors = knnReach.getKNNForDBID(iditer, kreach);
mean.reset();
// use first kref neighbors as reference set
int ks = 0;
// TODO: optimize for double distances
if (neighbors instanceof DoubleDistanceKNNList) {
- for (DoubleDistanceDBIDResultIter neighbor = ((DoubleDistanceKNNList) neighbors).iter(); neighbor.valid(); neighbor.advance()) {
+ for (DoubleDistanceDBIDListIter neighbor = ((DoubleDistanceKNNList) neighbors).iter(); neighbor.valid(); neighbor.advance()) {
if (objectIsInKNN || !DBIDUtil.equal(neighbor, iditer)) {
final double d = neighbor.doubleDistance();
mean.put(d * d);
@@ -258,7 +261,7 @@ public class LoOP<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<O
}
}
} else {
- for (DistanceDBIDResultIter<D> neighbor = neighbors.iter(); neighbor.valid(); neighbor.advance()) {
+ for (DistanceDBIDListIter<D> neighbor = neighbors.iter(); neighbor.valid(); neighbor.advance()) {
if (objectIsInKNN || !DBIDUtil.equal(neighbor, iditer)) {
double d = neighbor.getDistance().doubleValue();
mean.put(d * d);
@@ -287,7 +290,7 @@ public class LoOP<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<O
FiniteProgress progressPLOFs = LOG.isVerbose() ? new FiniteProgress("PLOFs for objects", relation.size(), LOG) : null;
MeanVariance mv = new MeanVariance();
for (DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
- final KNNResult<D> neighbors = knnComp.getKNNForDBID(iditer, kcomp);
+ final KNNList<D> neighbors = knnComp.getKNNForDBID(iditer, kcomp);
mv.reset();
// use first kref neighbors as comparison set.
int ks = 0;
@@ -340,7 +343,7 @@ public class LoOP<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<O
}
// Build result representation.
- Relation<Double> scoreResult = new MaterializedRelation<Double>("Local Outlier Probabilities", "loop-outlier", TypeUtil.DOUBLE, loops, relation.getDBIDs());
+ Relation<Double> scoreResult = new MaterializedRelation<>("Local Outlier Probabilities", "loop-outlier", TypeUtil.DOUBLE, loops, relation.getDBIDs());
OutlierScoreMeta scoreMeta = new ProbabilisticOutlierScore();
return new OutlierResult(scoreMeta, scoreResult);
}
@@ -403,7 +406,7 @@ public class LoOP<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<O
kcomp = kcompP.intValue();
}
- final ObjectParameter<DistanceFunction<O, D>> compDistP = new ObjectParameter<DistanceFunction<O, D>>(COMPARISON_DISTANCE_FUNCTION_ID, DistanceFunction.class, EuclideanDistanceFunction.class);
+ final ObjectParameter<DistanceFunction<O, D>> compDistP = new ObjectParameter<>(COMPARISON_DISTANCE_FUNCTION_ID, DistanceFunction.class, EuclideanDistanceFunction.class);
if (config.grab(compDistP)) {
comparisonDistanceFunction = compDistP.instantiateClass(config);
}
@@ -417,7 +420,7 @@ public class LoOP<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<O
kreach = kcomp;
}
- final ObjectParameter<DistanceFunction<O, D>> reachDistP = new ObjectParameter<DistanceFunction<O, D>>(REACHABILITY_DISTANCE_FUNCTION_ID, DistanceFunction.class, true);
+ final ObjectParameter<DistanceFunction<O, D>> reachDistP = new ObjectParameter<>(REACHABILITY_DISTANCE_FUNCTION_ID, DistanceFunction.class, true);
if (config.grab(reachDistP)) {
reachabilityDistanceFunction = reachDistP.instantiateClass(config);
}
@@ -433,7 +436,7 @@ public class LoOP<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<O
@Override
protected LoOP<O, D> makeInstance() {
DistanceFunction<O, D> realreach = (reachabilityDistanceFunction != null) ? reachabilityDistanceFunction : comparisonDistanceFunction;
- return new LoOP<O, D>(kreach, kcomp, realreach, comparisonDistanceFunction, lambda);
+ return new LoOP<>(kreach, kcomp, realreach, comparisonDistanceFunction, lambda);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/OnlineLOF.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/OnlineLOF.java
index bac5db36..c01c914f 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/OnlineLOF.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/OnlineLOF.java
@@ -1,30 +1,31 @@
-package de.lmu.ifi.dbs.elki.algorithm.outlier;
-/*
-This file is part of ELKI:
-Environment for Developing KDD-Applications Supported by Index-Structures
-
-Copyright (C) 2012
-Ludwig-Maximilians-Universität München
-Lehr- und Forschungseinheit für Datenbanksysteme
-ELKI Development Team
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
+package de.lmu.ifi.dbs.elki.algorithm.outlier.lof;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
import java.util.List;
-import de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm;
+import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.database.QueryUtil;
import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs;
@@ -33,6 +34,8 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
@@ -40,8 +43,6 @@ import de.lmu.ifi.dbs.elki.database.query.knn.PreprocessorKNNQuery;
import de.lmu.ifi.dbs.elki.database.query.rknn.RKNNQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.preprocessed.knn.AbstractMaterializeKNNPreprocessor;
import de.lmu.ifi.dbs.elki.index.preprocessed.knn.KNNChangeEvent;
@@ -53,11 +54,7 @@ import de.lmu.ifi.dbs.elki.logging.progress.StepProgress;
import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
import de.lmu.ifi.dbs.elki.result.outlier.BasicOutlierScoreMeta;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.ListParameterization;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
/**
@@ -66,10 +63,10 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
*
* @author Elke Achtert
*
- * @apiviz.has LOF.LOFResult oneway - - updates
+ * @apiviz.has FlexibleLOF.LOFResult oneway - - updates
*/
-// TODO: related to publication?
-public class OnlineLOF<O, D extends NumberDistance<D, ?>> extends LOF<O, D> {
+// TODO: related to publication?
+public class OnlineLOF<O, D extends NumberDistance<D, ?>> extends FlexibleLOF<O, D> {
/**
* The logger for this class.
*/
@@ -78,12 +75,13 @@ public class OnlineLOF<O, D extends NumberDistance<D, ?>> extends LOF<O, D> {
/**
* Constructor.
*
- * @param k the value of k
+ * @param krefer The number of neighbors for reference
+ * @param kreach The number of neighbors for reachability distance
* @param neighborhoodDistanceFunction the neighborhood distance function
* @param reachabilityDistanceFunction the reachability distance function
*/
- public OnlineLOF(int k, DistanceFunction<? super O, D> neighborhoodDistanceFunction, DistanceFunction<? super O, D> reachabilityDistanceFunction) {
- super(k, neighborhoodDistanceFunction, reachabilityDistanceFunction);
+ public OnlineLOF(int krefer, int kreach, DistanceFunction<? super O, D> neighborhoodDistanceFunction, DistanceFunction<? super O, D> reachabilityDistanceFunction) {
+ super(krefer, kreach, neighborhoodDistanceFunction, reachabilityDistanceFunction);
}
/**
@@ -92,10 +90,10 @@ public class OnlineLOF<O, D extends NumberDistance<D, ?>> extends LOF<O, D> {
* the preprocessors.
*/
@Override
- public OutlierResult run(Relation<O> relation) {
+ public OutlierResult run(Database database, Relation<O> relation) {
StepProgress stepprog = LOG.isVerbose() ? new StepProgress("OnlineLOF", 3) : null;
- Pair<Pair<KNNQuery<O, D>, KNNQuery<O, D>>, Pair<RKNNQuery<O, D>, RKNNQuery<O, D>>> queries = getKNNAndRkNNQueries(relation, stepprog);
+ Pair<Pair<KNNQuery<O, D>, KNNQuery<O, D>>, Pair<RKNNQuery<O, D>, RKNNQuery<O, D>>> queries = getKNNAndRkNNQueries(database, relation, stepprog);
KNNQuery<O, D> kNNRefer = queries.getFirst().getFirst();
KNNQuery<O, D> kNNReach = queries.getFirst().getSecond();
RKNNQuery<O, D> rkNNRefer = queries.getSecond().getFirst();
@@ -107,8 +105,8 @@ public class OnlineLOF<O, D extends NumberDistance<D, ?>> extends LOF<O, D> {
// add listener
KNNListener l = new LOFKNNListener(lofResult);
- ((MaterializeKNNPreprocessor<O, D>)((PreprocessorKNNQuery<O, D, ? extends KNNResult<D>>) lofResult.getKNNRefer()).getPreprocessor()).addKNNListener(l);
- ((MaterializeKNNPreprocessor<O, D>)((PreprocessorKNNQuery<O, D, ? extends KNNResult<D>>) lofResult.getKNNReach()).getPreprocessor()).addKNNListener(l);
+ ((MaterializeKNNPreprocessor<O, D>) ((PreprocessorKNNQuery<O, D, ? extends KNNList<D>>) lofResult.getKNNRefer()).getPreprocessor()).addKNNListener(l);
+ ((MaterializeKNNPreprocessor<O, D>) ((PreprocessorKNNQuery<O, D, ? extends KNNList<D>>) lofResult.getKNNReach()).getPreprocessor()).addKNNListener(l);
return lofResult.getResult();
}
@@ -120,50 +118,49 @@ public class OnlineLOF<O, D extends NumberDistance<D, ?>> extends LOF<O, D> {
* @param stepprog Progress logger
* @return the kNN and rkNN queries
*/
- private Pair<Pair<KNNQuery<O, D>, KNNQuery<O, D>>, Pair<RKNNQuery<O, D>, RKNNQuery<O, D>>> getKNNAndRkNNQueries(Relation<O> relation, StepProgress stepprog) {
+ private Pair<Pair<KNNQuery<O, D>, KNNQuery<O, D>>, Pair<RKNNQuery<O, D>, RKNNQuery<O, D>>> getKNNAndRkNNQueries(Database database, Relation<O> relation, StepProgress stepprog) {
// Use "HEAVY" flag, since this is an online algorithm
- KNNQuery<O, D> kNNRefer = QueryUtil.getKNNQuery(relation, neighborhoodDistanceFunction, k, DatabaseQuery.HINT_HEAVY_USE, DatabaseQuery.HINT_OPTIMIZED_ONLY, DatabaseQuery.HINT_NO_CACHE);
- RKNNQuery<O, D> rkNNRefer = QueryUtil.getRKNNQuery(relation, neighborhoodDistanceFunction, DatabaseQuery.HINT_HEAVY_USE, DatabaseQuery.HINT_OPTIMIZED_ONLY, DatabaseQuery.HINT_NO_CACHE);
+ KNNQuery<O, D> kNNRefer = QueryUtil.getKNNQuery(relation, referenceDistanceFunction, krefer, DatabaseQuery.HINT_HEAVY_USE, DatabaseQuery.HINT_OPTIMIZED_ONLY, DatabaseQuery.HINT_NO_CACHE);
+ RKNNQuery<O, D> rkNNRefer = QueryUtil.getRKNNQuery(relation, referenceDistanceFunction, DatabaseQuery.HINT_HEAVY_USE, DatabaseQuery.HINT_OPTIMIZED_ONLY, DatabaseQuery.HINT_NO_CACHE);
// No optimized kNN query or RkNN query - use a preprocessor!
- if(kNNRefer == null || rkNNRefer == null) {
- if(stepprog != null) {
+ if (kNNRefer == null || rkNNRefer == null) {
+ if (stepprog != null) {
stepprog.beginStep(1, "Materializing neighborhood w.r.t. reference neighborhood distance function.", LOG);
}
- MaterializeKNNAndRKNNPreprocessor<O, D> preproc = new MaterializeKNNAndRKNNPreprocessor<O, D>(relation, neighborhoodDistanceFunction, k);
- DistanceQuery<O, D> ndq = relation.getDatabase().getDistanceQuery(relation, neighborhoodDistanceFunction);
- kNNRefer = preproc.getKNNQuery(ndq, k, DatabaseQuery.HINT_HEAVY_USE);
- rkNNRefer = preproc.getRKNNQuery(ndq, k, DatabaseQuery.HINT_HEAVY_USE);
+ MaterializeKNNAndRKNNPreprocessor<O, D> preproc = new MaterializeKNNAndRKNNPreprocessor<>(relation, referenceDistanceFunction, krefer);
+ DistanceQuery<O, D> ndq = database.getDistanceQuery(relation, referenceDistanceFunction);
+ kNNRefer = preproc.getKNNQuery(ndq, krefer, DatabaseQuery.HINT_HEAVY_USE);
+ rkNNRefer = preproc.getRKNNQuery(ndq, krefer, DatabaseQuery.HINT_HEAVY_USE);
// add as index
relation.getDatabase().addIndex(preproc);
- }
- else {
- if(stepprog != null) {
+ } else {
+ if (stepprog != null) {
stepprog.beginStep(1, "Optimized neighborhood w.r.t. reference neighborhood distance function provided by database.", LOG);
}
}
- KNNQuery<O, D> kNNReach = QueryUtil.getKNNQuery(relation, reachabilityDistanceFunction, k, DatabaseQuery.HINT_HEAVY_USE, DatabaseQuery.HINT_OPTIMIZED_ONLY, DatabaseQuery.HINT_NO_CACHE);
+ KNNQuery<O, D> kNNReach = QueryUtil.getKNNQuery(relation, reachabilityDistanceFunction, kreach, DatabaseQuery.HINT_HEAVY_USE, DatabaseQuery.HINT_OPTIMIZED_ONLY, DatabaseQuery.HINT_NO_CACHE);
RKNNQuery<O, D> rkNNReach = QueryUtil.getRKNNQuery(relation, reachabilityDistanceFunction, DatabaseQuery.HINT_HEAVY_USE, DatabaseQuery.HINT_OPTIMIZED_ONLY, DatabaseQuery.HINT_NO_CACHE);
- if(kNNReach == null || rkNNReach == null) {
- if(stepprog != null) {
+ if (kNNReach == null || rkNNReach == null) {
+ if (stepprog != null) {
stepprog.beginStep(2, "Materializing neighborhood w.r.t. reachability distance function.", LOG);
}
ListParameterization config = new ListParameterization();
config.addParameter(AbstractMaterializeKNNPreprocessor.Factory.DISTANCE_FUNCTION_ID, reachabilityDistanceFunction);
- config.addParameter(AbstractMaterializeKNNPreprocessor.Factory.K_ID, k);
- MaterializeKNNAndRKNNPreprocessor<O, D> preproc = new MaterializeKNNAndRKNNPreprocessor<O, D>(relation, reachabilityDistanceFunction, k);
- DistanceQuery<O, D> rdq = relation.getDatabase().getDistanceQuery(relation, reachabilityDistanceFunction);
- kNNReach = preproc.getKNNQuery(rdq, k, DatabaseQuery.HINT_HEAVY_USE);
- rkNNReach = preproc.getRKNNQuery(rdq, k, DatabaseQuery.HINT_HEAVY_USE);
+ config.addParameter(AbstractMaterializeKNNPreprocessor.Factory.K_ID, kreach);
+ MaterializeKNNAndRKNNPreprocessor<O, D> preproc = new MaterializeKNNAndRKNNPreprocessor<>(relation, reachabilityDistanceFunction, kreach);
+ DistanceQuery<O, D> rdq = database.getDistanceQuery(relation, reachabilityDistanceFunction);
+ kNNReach = preproc.getKNNQuery(rdq, kreach, DatabaseQuery.HINT_HEAVY_USE);
+ rkNNReach = preproc.getRKNNQuery(rdq, kreach, DatabaseQuery.HINT_HEAVY_USE);
// add as index
relation.getDatabase().addIndex(preproc);
}
- Pair<KNNQuery<O, D>, KNNQuery<O, D>> kNNPair = new Pair<KNNQuery<O, D>, KNNQuery<O, D>>(kNNRefer, kNNReach);
- Pair<RKNNQuery<O, D>, RKNNQuery<O, D>> rkNNPair = new Pair<RKNNQuery<O, D>, RKNNQuery<O, D>>(rkNNRefer, rkNNReach);
+ Pair<KNNQuery<O, D>, KNNQuery<O, D>> kNNPair = new Pair<>(kNNRefer, kNNReach);
+ Pair<RKNNQuery<O, D>, RKNNQuery<O, D>> rkNNPair = new Pair<>(rkNNRefer, rkNNReach);
- return new Pair<Pair<KNNQuery<O, D>, KNNQuery<O, D>>, Pair<RKNNQuery<O, D>, RKNNQuery<O, D>>>(kNNPair, rkNNPair);
+ return new Pair<>(kNNPair, rkNNPair);
}
/**
@@ -201,24 +198,20 @@ public class OnlineLOF<O, D extends NumberDistance<D, ?>> extends LOF<O, D> {
AbstractMaterializeKNNPreprocessor<O, D, ?> p1 = ((PreprocessorKNNQuery<O, D, ?>) lofResult.getKNNRefer()).getPreprocessor();
AbstractMaterializeKNNPreprocessor<O, D, ?> p2 = ((PreprocessorKNNQuery<O, D, ?>) lofResult.getKNNReach()).getPreprocessor();
- if(firstEventReceived == null) {
- if(e.getSource().equals(p1) && e.getSource().equals(p2)) {
+ if (firstEventReceived == null) {
+ if (e.getSource().equals(p1) && e.getSource().equals(p2)) {
kNNsChanged(e, e);
- }
- else {
+ } else {
firstEventReceived = e;
}
- }
- else {
- if(e.getSource().equals(p1) && firstEventReceived.getSource().equals(p2)) {
+ } else {
+ if (e.getSource().equals(p1) && firstEventReceived.getSource().equals(p2)) {
kNNsChanged(e, firstEventReceived);
firstEventReceived = null;
- }
- else if(e.getSource().equals(p2) && firstEventReceived.getSource().equals(p1)) {
+ } else if (e.getSource().equals(p2) && firstEventReceived.getSource().equals(p1)) {
kNNsChanged(firstEventReceived, e);
firstEventReceived = null;
- }
- else {
+ } else {
throw new UnsupportedOperationException("Event sources do not fit!");
}
}
@@ -232,20 +225,18 @@ public class OnlineLOF<O, D extends NumberDistance<D, ?>> extends LOF<O, D> {
* @param e2 the change event of the second preprocessor
*/
private void kNNsChanged(KNNChangeEvent e1, KNNChangeEvent e2) {
- if(!e1.getType().equals(e2.getType())) {
+ if (!e1.getType().equals(e2.getType())) {
throw new UnsupportedOperationException("Event types do not fit: " + e1.getType() + " != " + e2.getType());
}
- if(!e1.getObjects().equals(e2.getObjects())) {
+ if (!e1.getObjects().equals(e2.getObjects())) {
throw new UnsupportedOperationException("Objects do not fit: " + e1.getObjects() + " != " + e2.getObjects());
}
- if(e1.getType().equals(KNNChangeEvent.Type.DELETE)) {
+ if (e1.getType().equals(KNNChangeEvent.Type.DELETE)) {
kNNsRemoved(e1.getObjects(), e1.getUpdates(), e2.getUpdates(), lofResult);
- }
- else if(e1.getType().equals(KNNChangeEvent.Type.INSERT)) {
+ } else if (e1.getType().equals(KNNChangeEvent.Type.INSERT)) {
kNNsInserted(e1.getObjects(), e1.getUpdates(), e2.getUpdates(), lofResult);
- }
- else {
+ } else {
throw new UnsupportedOperationException("Unsupported event type: " + e1.getType());
}
}
@@ -264,38 +255,38 @@ public class OnlineLOF<O, D extends NumberDistance<D, ?>> extends LOF<O, D> {
StepProgress stepprog = LOG.isVerbose() ? new StepProgress(3) : null;
// recompute lrds
- if(stepprog != null) {
+ if (stepprog != null) {
stepprog.beginStep(1, "Recompute LRDs.", LOG);
}
ArrayDBIDs lrd_ids = DBIDUtil.ensureArray(DBIDUtil.union(insertions, updates2));
- List<? extends DistanceDBIDResult<D>> reachDistRKNNs = lofResult.getRkNNReach().getRKNNForBulkDBIDs(lrd_ids, k);
+ List<? extends DistanceDBIDList<D>> reachDistRKNNs = lofResult.getRkNNReach().getRKNNForBulkDBIDs(lrd_ids, kreach);
ArrayDBIDs affected_lrd_id_candidates = mergeIDs(reachDistRKNNs, lrd_ids);
ArrayModifiableDBIDs affected_lrd_ids = DBIDUtil.newArray(affected_lrd_id_candidates.size());
WritableDoubleDataStore new_lrds = computeLRDs(affected_lrd_id_candidates, lofResult.getKNNReach());
for (DBIDIter iter = affected_lrd_id_candidates.iter(); iter.valid(); iter.advance()) {
double new_lrd = new_lrds.doubleValue(iter);
double old_lrd = lofResult.getLrds().doubleValue(iter);
- if(Double.isNaN(old_lrd) || old_lrd != new_lrd) {
+ if (Double.isNaN(old_lrd) || old_lrd != new_lrd) {
lofResult.getLrds().putDouble(iter, new_lrd);
affected_lrd_ids.add(iter);
}
}
// recompute lofs
- if(stepprog != null) {
+ if (stepprog != null) {
stepprog.beginStep(2, "Recompute LOFS.", LOG);
}
- List<? extends DistanceDBIDResult<D>> primDistRKNNs = lofResult.getRkNNRefer().getRKNNForBulkDBIDs(affected_lrd_ids, k);
+ List<? extends DistanceDBIDList<D>> primDistRKNNs = lofResult.getRkNNRefer().getRKNNForBulkDBIDs(affected_lrd_ids, krefer);
ArrayDBIDs affected_lof_ids = mergeIDs(primDistRKNNs, affected_lrd_ids, insertions, updates1);
recomputeLOFs(affected_lof_ids, lofResult);
// fire result changed
- if(stepprog != null) {
+ if (stepprog != null) {
stepprog.beginStep(3, "Inform listeners.", LOG);
}
lofResult.getResult().getHierarchy().resultChanged(lofResult.getResult());
- if(stepprog != null) {
+ if (stepprog != null) {
stepprog.setCompleted(LOG);
}
}
@@ -314,7 +305,7 @@ public class OnlineLOF<O, D extends NumberDistance<D, ?>> extends LOF<O, D> {
StepProgress stepprog = LOG.isVerbose() ? new StepProgress(4) : null;
// delete lrds and lofs
- if(stepprog != null) {
+ if (stepprog != null) {
stepprog.beginStep(1, "Delete old LRDs and LOFs.", LOG);
}
for (DBIDIter iter = deletions.iter(); iter.valid(); iter.advance()) {
@@ -323,38 +314,38 @@ public class OnlineLOF<O, D extends NumberDistance<D, ?>> extends LOF<O, D> {
}
// recompute lrds
- if(stepprog != null) {
+ if (stepprog != null) {
stepprog.beginStep(2, "Recompute LRDs.", LOG);
}
ArrayDBIDs lrd_ids = DBIDUtil.ensureArray(updates2);
- List<? extends DistanceDBIDResult<D>> reachDistRKNNs = lofResult.getRkNNReach().getRKNNForBulkDBIDs(lrd_ids, k);
+ List<? extends DistanceDBIDList<D>> reachDistRKNNs = lofResult.getRkNNReach().getRKNNForBulkDBIDs(lrd_ids, kreach);
ArrayDBIDs affected_lrd_id_candidates = mergeIDs(reachDistRKNNs, lrd_ids);
ArrayModifiableDBIDs affected_lrd_ids = DBIDUtil.newArray(affected_lrd_id_candidates.size());
WritableDoubleDataStore new_lrds = computeLRDs(affected_lrd_id_candidates, lofResult.getKNNReach());
for (DBIDIter iter = affected_lrd_id_candidates.iter(); iter.valid(); iter.advance()) {
double new_lrd = new_lrds.doubleValue(iter);
double old_lrd = lofResult.getLrds().doubleValue(iter);
- if(old_lrd != new_lrd) {
+ if (old_lrd != new_lrd) {
lofResult.getLrds().putDouble(iter, new_lrd);
affected_lrd_ids.add(iter);
}
}
// recompute lofs
- if(stepprog != null) {
+ if (stepprog != null) {
stepprog.beginStep(3, "Recompute LOFS.", LOG);
}
- List<? extends DistanceDBIDResult<D>> primDistRKNNs = lofResult.getRkNNRefer().getRKNNForBulkDBIDs(affected_lrd_ids, k);
+ List<? extends DistanceDBIDList<D>> primDistRKNNs = lofResult.getRkNNRefer().getRKNNForBulkDBIDs(affected_lrd_ids, krefer);
ArrayDBIDs affected_lof_ids = mergeIDs(primDistRKNNs, affected_lrd_ids, updates1);
recomputeLOFs(affected_lof_ids, lofResult);
// fire result changed
- if(stepprog != null) {
+ if (stepprog != null) {
stepprog.beginStep(4, "Inform listeners.", LOG);
}
lofResult.getResult().getHierarchy().resultChanged(lofResult.getResult());
- if(stepprog != null) {
+ if (stepprog != null) {
stepprog.setCompleted(LOG);
}
}
@@ -367,12 +358,12 @@ public class OnlineLOF<O, D extends NumberDistance<D, ?>> extends LOF<O, D> {
* @return a set containing the ids of the query result and the specified
* ids
*/
- private ArrayModifiableDBIDs mergeIDs(List<? extends DistanceDBIDResult<D>> queryResults, DBIDs... ids) {
+ private ArrayModifiableDBIDs mergeIDs(List<? extends DistanceDBIDList<D>> queryResults, DBIDs... ids) {
ModifiableDBIDs result = DBIDUtil.newHashSet();
- for(DBIDs dbids : ids) {
+ for (DBIDs dbids : ids) {
result.addDBIDs(dbids);
}
- for(DistanceDBIDResult<D> queryResult : queryResults) {
+ for (DistanceDBIDList<D> queryResult : queryResults) {
result.addDBIDs(queryResult);
}
return DBIDUtil.newArray(result);
@@ -394,12 +385,12 @@ public class OnlineLOF<O, D extends NumberDistance<D, ?>> extends LOF<O, D> {
DoubleMinMax new_lofminmax = lofsAndMax.getSecond();
// Actualize meta info
- if(new_lofminmax.isValid() && lofResult.getResult().getOutlierMeta().getActualMaximum() < new_lofminmax.getMax()) {
+ if (new_lofminmax.isValid() && lofResult.getResult().getOutlierMeta().getActualMaximum() < new_lofminmax.getMax()) {
BasicOutlierScoreMeta scoreMeta = (BasicOutlierScoreMeta) lofResult.getResult().getOutlierMeta();
scoreMeta.setActualMaximum(new_lofminmax.getMax());
}
- if(new_lofminmax.isValid() && lofResult.getResult().getOutlierMeta().getActualMinimum() > new_lofminmax.getMin()) {
+ if (new_lofminmax.isValid() && lofResult.getResult().getOutlierMeta().getActualMinimum() > new_lofminmax.getMin()) {
BasicOutlierScoreMeta scoreMeta = (BasicOutlierScoreMeta) lofResult.getResult().getOutlierMeta();
scoreMeta.setActualMinimum(new_lofminmax.getMin());
}
@@ -412,49 +403,16 @@ public class OnlineLOF<O, D extends NumberDistance<D, ?>> extends LOF<O, D> {
}
/**
- * Parameterization class.
- *
- * @author Erich Schubert
- *
- * @apiviz.exclude
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
*/
- public static class Parameterizer<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBasedAlgorithm.Parameterizer<O, D> {
- /**
- * The neighborhood size to use
- */
- protected int k = 2;
-
- /**
- * Neighborhood distance function.
- */
- protected DistanceFunction<O, D> neighborhoodDistanceFunction = null;
-
- /**
- * Reachability distance function.
- */
- protected DistanceFunction<O, D> reachabilityDistanceFunction = null;
-
- @Override
- protected void makeOptions(Parameterization config) {
- super.makeOptions(config);
-
- final IntParameter pK = new IntParameter(K_ID);
- pK.addConstraint(new GreaterConstraint(1));
- if(config.grab(pK)) {
- k = pK.getValue();
- }
-
- final ObjectParameter<DistanceFunction<O, D>> reachDistP = new ObjectParameter<DistanceFunction<O, D>>(REACHABILITY_DISTANCE_FUNCTION_ID, DistanceFunction.class, true);
- if(config.grab(reachDistP)) {
- reachabilityDistanceFunction = reachDistP.instantiateClass(config);
- }
- }
-
+ public static class Parameterizer<O, D extends NumberDistance<D, ?>> extends FlexibleLOF.Parameterizer<O, D> {
@Override
protected OnlineLOF<O, D> makeInstance() {
- // Default is to re-use the same distance
- DistanceFunction<O, D> rdist = (reachabilityDistanceFunction != null) ? reachabilityDistanceFunction : distanceFunction;
- return new OnlineLOF<O, D>(k, distanceFunction, rdist);
+ return new OnlineLOF<>(kreach, krefer, distanceFunction, reachabilityDistanceFunction);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/SimpleKernelDensityLOF.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/SimpleKernelDensityLOF.java
index 1c104c08..2ff7534a 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/SimpleKernelDensityLOF.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/SimpleKernelDensityLOF.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.algorithm.outlier;
+package de.lmu.ifi.dbs.elki.algorithm.outlier.lof;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,10 +24,12 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier;
*/
import de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm;
+import de.lmu.ifi.dbs.elki.algorithm.outlier.OutlierAlgorithm;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.data.type.CombinedTypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.database.QueryUtil;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
@@ -35,6 +37,10 @@ import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
@@ -43,18 +49,14 @@ import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.database.relation.RelationUtil;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultIter;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceDBIDResultIter;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceKNNList;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNPreprocessor;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
import de.lmu.ifi.dbs.elki.logging.progress.StepProgress;
import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
-import de.lmu.ifi.dbs.elki.math.statistics.EpanechnikovKernelDensityFunction;
-import de.lmu.ifi.dbs.elki.math.statistics.KernelDensityFunction;
+import de.lmu.ifi.dbs.elki.math.statistics.kernelfunctions.EpanechnikovKernelDensityFunction;
+import de.lmu.ifi.dbs.elki.math.statistics.kernelfunctions.KernelDensityFunction;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierScoreMeta;
import de.lmu.ifi.dbs.elki.result.outlier.QuotientOutlierScoreMeta;
@@ -107,10 +109,11 @@ public class SimpleKernelDensityLOF<O extends NumberVector<?>, D extends NumberD
/**
* Run the naive kernel density LOF algorithm.
*
+ * @param database Database to query
* @param relation Data to process
* @return LOF outlier result
*/
- public OutlierResult run(Relation<O> relation) {
+ public OutlierResult run(Database database, Relation<O> relation) {
StepProgress stepprog = LOG.isVerbose() ? new StepProgress("KernelDensityLOF", 3) : null;
final int dim = RelationUtil.dimensionality(relation);
@@ -124,9 +127,9 @@ public class SimpleKernelDensityLOF<O extends NumberVector<?>, D extends NumberD
if (stepprog != null) {
stepprog.beginStep(1, "Materializing neighborhoods w.r.t. distance function.", LOG);
}
- MaterializeKNNPreprocessor<O, D> preproc = new MaterializeKNNPreprocessor<O, D>(relation, getDistanceFunction(), k);
- relation.getDatabase().addIndex(preproc);
- DistanceQuery<O, D> rdq = relation.getDatabase().getDistanceQuery(relation, getDistanceFunction());
+ MaterializeKNNPreprocessor<O, D> preproc = new MaterializeKNNPreprocessor<>(relation, getDistanceFunction(), k);
+ database.addIndex(preproc);
+ DistanceQuery<O, D> rdq = database.getDistanceQuery(relation, getDistanceFunction());
knnq = preproc.getKNNQuery(rdq, k);
}
@@ -137,12 +140,12 @@ public class SimpleKernelDensityLOF<O extends NumberVector<?>, D extends NumberD
WritableDoubleDataStore dens = DataStoreUtil.makeDoubleStorage(ids, DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP);
FiniteProgress densProgress = LOG.isVerbose() ? new FiniteProgress("Densities", ids.size(), LOG) : null;
for (DBIDIter it = ids.iter(); it.valid(); it.advance()) {
- final KNNResult<D> neighbors = knnq.getKNNForDBID(it, k);
+ final KNNList<D> neighbors = knnq.getKNNForDBID(it, k);
int count = 0;
double sum = 0.0;
if (neighbors instanceof DoubleDistanceKNNList) {
// Fast version for double distances
- for (DoubleDistanceDBIDResultIter neighbor = ((DoubleDistanceKNNList) neighbors).iter(); neighbor.valid(); neighbor.advance()) {
+ for (DoubleDistanceDBIDListIter neighbor = ((DoubleDistanceKNNList) neighbors).iter(); neighbor.valid(); neighbor.advance()) {
if (DBIDUtil.equal(neighbor, it)) {
continue;
}
@@ -152,7 +155,7 @@ public class SimpleKernelDensityLOF<O extends NumberVector<?>, D extends NumberD
count++;
}
} else {
- for (DistanceDBIDResultIter<D> neighbor = neighbors.iter(); neighbor.valid(); neighbor.advance()) {
+ for (DistanceDBIDListIter<D> neighbor = neighbors.iter(); neighbor.valid(); neighbor.advance()) {
if (DBIDUtil.equal(neighbor, it)) {
continue;
}
@@ -185,7 +188,7 @@ public class SimpleKernelDensityLOF<O extends NumberVector<?>, D extends NumberD
final double lrdp = dens.doubleValue(it);
final double lof;
if (lrdp > 0) {
- final KNNResult<D> neighbors = knnq.getKNNForDBID(it, k);
+ final KNNList<D> neighbors = knnq.getKNNForDBID(it, k);
double sum = 0.0;
int count = 0;
for (DBIDIter neighbor = neighbors.iter(); neighbor.valid(); neighbor.advance()) {
@@ -217,7 +220,7 @@ public class SimpleKernelDensityLOF<O extends NumberVector<?>, D extends NumberD
}
// Build result representation.
- Relation<Double> scoreResult = new MaterializedRelation<Double>("Kernel Density Local Outlier Factor", "kernel-density-slof-outlier", TypeUtil.DOUBLE, lofs, ids);
+ Relation<Double> scoreResult = new MaterializedRelation<>("Kernel Density Local Outlier Factor", "kernel-density-slof-outlier", TypeUtil.DOUBLE, lofs, ids);
OutlierScoreMeta scoreMeta = new QuotientOutlierScoreMeta(lofminmax.getMin(), lofminmax.getMax(), 0.0, Double.POSITIVE_INFINITY, 1.0);
OutlierResult result = new OutlierResult(scoreMeta, scoreResult);
@@ -264,13 +267,13 @@ public class SimpleKernelDensityLOF<O extends NumberVector<?>, D extends NumberD
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- final IntParameter pK = new IntParameter(LOF.K_ID);
+ final IntParameter pK = new IntParameter(LOF.Parameterizer.K_ID);
pK.addConstraint(new GreaterConstraint(1));
if (config.grab(pK)) {
k = pK.getValue();
}
- ObjectParameter<KernelDensityFunction> kernelP = new ObjectParameter<KernelDensityFunction>(KERNEL_ID, KernelDensityFunction.class, EpanechnikovKernelDensityFunction.class);
+ ObjectParameter<KernelDensityFunction> kernelP = new ObjectParameter<>(KERNEL_ID, KernelDensityFunction.class, EpanechnikovKernelDensityFunction.class);
if (config.grab(kernelP)) {
kernel = kernelP.instantiateClass(config);
}
@@ -278,7 +281,7 @@ public class SimpleKernelDensityLOF<O extends NumberVector<?>, D extends NumberD
@Override
protected SimpleKernelDensityLOF<O, D> makeInstance() {
- return new SimpleKernelDensityLOF<O, D>(k, distanceFunction, kernel);
+ return new SimpleKernelDensityLOF<>(k, distanceFunction, kernel);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/SimpleLOF.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/SimplifiedLOF.java
index 48505ed5..413eaca1 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/SimpleLOF.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/SimplifiedLOF.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.algorithm.outlier;
+package de.lmu.ifi.dbs.elki.algorithm.outlier.lof;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,8 +24,10 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier;
*/
import de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm;
+import de.lmu.ifi.dbs.elki.algorithm.outlier.OutlierAlgorithm;
import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.database.QueryUtil;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
@@ -33,6 +35,10 @@ import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
@@ -40,10 +46,6 @@ import de.lmu.ifi.dbs.elki.database.query.knn.PreprocessorKNNQuery;
import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultIter;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceDBIDResultIter;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceKNNList;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNPreprocessor;
import de.lmu.ifi.dbs.elki.logging.Logging;
@@ -53,6 +55,8 @@ import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierScoreMeta;
import de.lmu.ifi.dbs.elki.result.outlier.QuotientOutlierScoreMeta;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
@@ -61,6 +65,14 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
* A simplified version of the original LOF algorithm, which does not use the
* reachability distance, yielding less stable results on inliers.
*
+ * Reference:
+ * <p>
+ * Erich Schubert, Arthur Zimek, Hans-Peter Kriegel<br />
+ * Local outlier detection reconsidered: a generalized view on locality with
+ * applications to spatial, video, and network outlier detection<br />
+ * In: Data Mining and Knowledge Discovery
+ * </p>
+ *
* @author Erich Schubert
*
* @apiviz.has KNNQuery
@@ -68,11 +80,13 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
* @param <O> the type of DatabaseObjects handled by this Algorithm
* @param <D> Distance type
*/
-public class SimpleLOF<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBasedAlgorithm<O, D, OutlierResult> implements OutlierAlgorithm {
+@Reference(authors = "Erich Schubert, Arthur Zimek, Hans-Peter Kriegel", title = "Local outlier detection reconsidered: a generalized view on locality with applications to spatial, video, and network outlier detection", booktitle = "Data Mining and Knowledge Discovery", url = "http://dx.doi.org/10.1007/s10618-012-0300-z")
+@Alias({ "SimpleLOF", "outlier.SimpleLOF", "de.lmu.ifi.dbs.elki.algorithm.outlier.SimpleLOF" })
+public class SimplifiedLOF<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBasedAlgorithm<O, D, OutlierResult> implements OutlierAlgorithm {
/**
* The logger for this class.
*/
- private static final Logging LOG = Logging.getLogger(SimpleLOF.class);
+ private static final Logging LOG = Logging.getLogger(SimplifiedLOF.class);
/**
* Parameter k.
@@ -84,7 +98,7 @@ public class SimpleLOF<O, D extends NumberDistance<D, ?>> extends AbstractDistan
*
* @param k the value of k
*/
- public SimpleLOF(int k, DistanceFunction<? super O, D> distance) {
+ public SimplifiedLOF(int k, DistanceFunction<? super O, D> distance) {
super(distance);
this.k = k + 1;
}
@@ -92,10 +106,11 @@ public class SimpleLOF<O, D extends NumberDistance<D, ?>> extends AbstractDistan
/**
* Run the Simple LOF algorithm.
*
+ * @param database Database to query
* @param relation Data to process
* @return LOF outlier result
*/
- public OutlierResult run(Relation<O> relation) {
+ public OutlierResult run(Database database, Relation<O> relation) {
StepProgress stepprog = LOG.isVerbose() ? new StepProgress("SimpleLOF", 3) : null;
DBIDs ids = relation.getDBIDs();
@@ -107,9 +122,9 @@ public class SimpleLOF<O, D extends NumberDistance<D, ?>> extends AbstractDistan
if (stepprog != null) {
stepprog.beginStep(1, "Materializing neighborhoods w.r.t. distance function.", LOG);
}
- MaterializeKNNPreprocessor<O, D> preproc = new MaterializeKNNPreprocessor<O, D>(relation, getDistanceFunction(), k);
- relation.getDatabase().addIndex(preproc);
- DistanceQuery<O, D> rdq = relation.getDatabase().getDistanceQuery(relation, getDistanceFunction());
+ MaterializeKNNPreprocessor<O, D> preproc = new MaterializeKNNPreprocessor<>(relation, getDistanceFunction(), k);
+ database.addIndex(preproc);
+ DistanceQuery<O, D> rdq = database.getDistanceQuery(relation, getDistanceFunction());
knnq = preproc.getKNNQuery(rdq, k);
}
@@ -120,12 +135,12 @@ public class SimpleLOF<O, D extends NumberDistance<D, ?>> extends AbstractDistan
WritableDoubleDataStore dens = DataStoreUtil.makeDoubleStorage(ids, DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP);
FiniteProgress densProgress = LOG.isVerbose() ? new FiniteProgress("Densities", ids.size(), LOG) : null;
for (DBIDIter it = ids.iter(); it.valid(); it.advance()) {
- final KNNResult<D> neighbors = knnq.getKNNForDBID(it, k);
+ final KNNList<D> neighbors = knnq.getKNNForDBID(it, k);
double sum = 0.0;
int count = 0;
if (neighbors instanceof DoubleDistanceKNNList) {
// Fast version for double distances
- for (DoubleDistanceDBIDResultIter neighbor = ((DoubleDistanceKNNList) neighbors).iter(); neighbor.valid(); neighbor.advance()) {
+ for (DoubleDistanceDBIDListIter neighbor = ((DoubleDistanceKNNList) neighbors).iter(); neighbor.valid(); neighbor.advance()) {
if (DBIDUtil.equal(neighbor, it)) {
continue;
}
@@ -133,7 +148,7 @@ public class SimpleLOF<O, D extends NumberDistance<D, ?>> extends AbstractDistan
count++;
}
} else {
- for (DistanceDBIDResultIter<D> neighbor = neighbors.iter(); neighbor.valid(); neighbor.advance()) {
+ for (DistanceDBIDListIter<D> neighbor = neighbors.iter(); neighbor.valid(); neighbor.advance()) {
if (DBIDUtil.equal(neighbor, it)) {
continue;
}
@@ -165,7 +180,7 @@ public class SimpleLOF<O, D extends NumberDistance<D, ?>> extends AbstractDistan
final double lrdp = dens.doubleValue(it);
final double lof;
if (lrdp > 0) {
- final KNNResult<D> neighbors = knnq.getKNNForDBID(it, k);
+ final KNNList<D> neighbors = knnq.getKNNForDBID(it, k);
double sum = 0.0;
int count = 0;
for (DBIDIter neighbor = neighbors.iter(); neighbor.valid(); neighbor.advance()) {
@@ -197,7 +212,7 @@ public class SimpleLOF<O, D extends NumberDistance<D, ?>> extends AbstractDistan
}
// Build result representation.
- Relation<Double> scoreResult = new MaterializedRelation<Double>("Simple Local Outlier Factor", "simple-lof-outlier", TypeUtil.DOUBLE, lofs, ids);
+ Relation<Double> scoreResult = new MaterializedRelation<>("Simple Local Outlier Factor", "simple-lof-outlier", TypeUtil.DOUBLE, lofs, ids);
OutlierScoreMeta scoreMeta = new QuotientOutlierScoreMeta(lofminmax.getMin(), lofminmax.getMax(), 0.0, Double.POSITIVE_INFINITY, 1.0);
OutlierResult result = new OutlierResult(scoreMeta, scoreResult);
@@ -234,7 +249,7 @@ public class SimpleLOF<O, D extends NumberDistance<D, ?>> extends AbstractDistan
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- final IntParameter pK = new IntParameter(LOF.K_ID);
+ final IntParameter pK = new IntParameter(LOF.Parameterizer.K_ID);
pK.addConstraint(new GreaterConstraint(1));
if (config.grab(pK)) {
k = pK.getValue();
@@ -242,8 +257,8 @@ public class SimpleLOF<O, D extends NumberDistance<D, ?>> extends AbstractDistan
}
@Override
- protected SimpleLOF<O, D> makeInstance() {
- return new SimpleLOF<O, D>(k, distanceFunction);
+ protected SimplifiedLOF<O, D> makeInstance() {
+ return new SimplifiedLOF<>(k, distanceFunction);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/package-info.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/package-info.java
new file mode 100644
index 00000000..48d4b16a
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/package-info.java
@@ -0,0 +1,27 @@
+/**
+ * <p>LOF family of outlier detection algorithms.</p>
+ */
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package de.lmu.ifi.dbs.elki.algorithm.outlier.lof;
+
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/ExternalDoubleOutlierScore.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/ExternalDoubleOutlierScore.java
index f230fd3b..0d0f7303 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/ExternalDoubleOutlierScore.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/ExternalDoubleOutlierScore.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier.meta;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -202,7 +202,7 @@ public class ExternalDoubleOutlierScore extends AbstractAlgorithm<OutlierResult>
else {
meta = new BasicOutlierScoreMeta(minmax.getMin(), minmax.getMax());
}
- Relation<Double> scoresult = new MaterializedRelation<Double>("External Outlier", "external-outlier", TypeUtil.DOUBLE, scores, relation.getDBIDs());
+ Relation<Double> scoresult = new MaterializedRelation<>("External Outlier", "external-outlier", TypeUtil.DOUBLE, scores, relation.getDBIDs());
OutlierResult or = new OutlierResult(meta, scoresult);
// Apply scaling
@@ -327,7 +327,7 @@ public class ExternalDoubleOutlierScore extends AbstractAlgorithm<OutlierResult>
inverted = inverstedF.getValue();
}
- ObjectParameter<ScalingFunction> scalingP = new ObjectParameter<ScalingFunction>(SCALING_ID, ScalingFunction.class, IdentityScaling.class);
+ ObjectParameter<ScalingFunction> scalingP = new ObjectParameter<>(SCALING_ID, ScalingFunction.class, IdentityScaling.class);
if(config.grab(scalingP)) {
scaling = scalingP.instantiateClass(config);
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/FeatureBagging.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/FeatureBagging.java
index b53a0942..22c20fc3 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/FeatureBagging.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/FeatureBagging.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier.meta;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,11 +28,12 @@ import java.util.BitSet;
import java.util.Random;
import de.lmu.ifi.dbs.elki.algorithm.AbstractAlgorithm;
-import de.lmu.ifi.dbs.elki.algorithm.outlier.LOF;
import de.lmu.ifi.dbs.elki.algorithm.outlier.OutlierAlgorithm;
+import de.lmu.ifi.dbs.elki.algorithm.outlier.lof.LOF;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
@@ -127,25 +128,26 @@ public class FeatureBagging extends AbstractAlgorithm<OutlierResult> implements
/**
* Run the algorithm on a data set.
*
+ * @param database Database context
* @param relation Relation to use
* @return Outlier detection result
*/
- public OutlierResult run(Relation<NumberVector<?>> relation) {
+ public OutlierResult run(Database database, Relation<NumberVector<?>> relation) {
final int dbdim = RelationUtil.dimensionality(relation);
final int mindim = dbdim >> 1;
final int maxdim = dbdim - 1;
final Random rand = rnd.getRandom();
- ArrayList<OutlierResult> results = new ArrayList<OutlierResult>(num);
+ ArrayList<OutlierResult> results = new ArrayList<>(num);
{
FiniteProgress prog = LOG.isVerbose() ? new FiniteProgress("LOF iterations", num, LOG) : null;
for (int i = 0; i < num; i++) {
BitSet dimset = randomSubspace(dbdim, mindim, maxdim, rand);
SubspaceEuclideanDistanceFunction df = new SubspaceEuclideanDistanceFunction(dimset);
- LOF<NumberVector<?>, DoubleDistance> lof = new LOF<NumberVector<?>, DoubleDistance>(k, df);
+ LOF<NumberVector<?>, DoubleDistance> lof = new LOF<>(k, df);
// run LOF and collect the result
- OutlierResult result = lof.run(relation);
+ OutlierResult result = lof.run(database, relation);
results.add(result);
if (prog != null) {
prog.incrementProcessed(LOG);
@@ -219,7 +221,7 @@ public class FeatureBagging extends AbstractAlgorithm<OutlierResult> implements
}
}
OutlierScoreMeta meta = new BasicOutlierScoreMeta(minmax.getMin(), minmax.getMax());
- Relation<Double> scoreres = new MaterializedRelation<Double>("Feature bagging", "fb-outlier", TypeUtil.DOUBLE, scores, relation.getDBIDs());
+ Relation<Double> scoreres = new MaterializedRelation<>("Feature bagging", "fb-outlier", TypeUtil.DOUBLE, scores, relation.getDBIDs());
return new OutlierResult(meta, scoreres);
}
@@ -314,7 +316,7 @@ public class FeatureBagging extends AbstractAlgorithm<OutlierResult> implements
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- final IntParameter pK = new IntParameter(LOF.K_ID);
+ final IntParameter pK = new IntParameter(LOF.Parameterizer.K_ID);
pK.addConstraint(new GreaterConstraint(1));
if (config.grab(pK)) {
k = pK.getValue();
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/HiCS.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/HiCS.java
index 15b94322..69608293 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/HiCS.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/HiCS.java
@@ -33,13 +33,12 @@ import java.util.Set;
import java.util.TreeSet;
import de.lmu.ifi.dbs.elki.algorithm.AbstractAlgorithm;
-import de.lmu.ifi.dbs.elki.algorithm.outlier.LOF;
import de.lmu.ifi.dbs.elki.algorithm.outlier.OutlierAlgorithm;
+import de.lmu.ifi.dbs.elki.algorithm.outlier.lof.LOF;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.data.VectorUtil;
import de.lmu.ifi.dbs.elki.data.VectorUtil.SortDBIDsBySingleDimension;
import de.lmu.ifi.dbs.elki.data.projection.NumericalFeatureSelection;
-import de.lmu.ifi.dbs.elki.data.projection.Projection;
import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
import de.lmu.ifi.dbs.elki.database.ProxyDatabase;
@@ -66,6 +65,7 @@ import de.lmu.ifi.dbs.elki.result.outlier.BasicOutlierScoreMeta;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierScoreMeta;
import de.lmu.ifi.dbs.elki.utilities.RandomFactory;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.Heap;
import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.TopBoundedHeap;
import de.lmu.ifi.dbs.elki.utilities.documentation.Description;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
@@ -172,7 +172,6 @@ public class HiCS<V extends NumberVector<?>> extends AbstractAlgorithm<OutlierRe
*/
public OutlierResult run(Relation<V> relation) {
final DBIDs ids = relation.getDBIDs();
- final NumberVector.Factory<V, ?> factory = RelationUtil.getNumberVectorFactory(relation);
ArrayList<ArrayDBIDs> subspaceIndex = buildOneDimIndexes(relation);
Set<HiCSSubspace> subspaces = calculateSubspaces(relation, subspaceIndex, rnd.getRandom());
@@ -180,7 +179,7 @@ public class HiCS<V extends NumberVector<?>> extends AbstractAlgorithm<OutlierRe
if (LOG.isVerbose()) {
LOG.verbose("Number of high-contrast subspaces: " + subspaces.size());
}
- List<Relation<Double>> results = new ArrayList<Relation<Double>>();
+ List<Relation<Double>> results = new ArrayList<>();
FiniteProgress prog = LOG.isVerbose() ? new FiniteProgress("Calculating Outlier scores for high Contrast subspaces", subspaces.size(), LOG) : null;
// run outlier detection and collect the result
@@ -192,8 +191,7 @@ public class HiCS<V extends NumberVector<?>> extends AbstractAlgorithm<OutlierRe
}
ProxyDatabase pdb = new ProxyDatabase(ids);
- Projection<V, V> proj = new NumericalFeatureSelection<V>(dimset, factory);
- pdb.addRelation(new ProjectedView<V, V>(relation, proj));
+ pdb.addRelation(new ProjectedView<>(relation, new NumericalFeatureSelection<V>(dimset)));
// run LOF and collect the result
OutlierResult result = outlierAlgorithm.run(pdb);
@@ -221,7 +219,7 @@ public class HiCS<V extends NumberVector<?>> extends AbstractAlgorithm<OutlierRe
minmax.put(sum);
}
OutlierScoreMeta meta = new BasicOutlierScoreMeta(minmax.getMin(), minmax.getMax());
- Relation<Double> scoreres = new MaterializedRelation<Double>("HiCS", "HiCS-outlier", TypeUtil.DOUBLE, scores, relation.getDBIDs());
+ Relation<Double> scoreres = new MaterializedRelation<>("HiCS", "HiCS-outlier", TypeUtil.DOUBLE, scores, relation.getDBIDs());
return new OutlierResult(meta, scoreres);
}
@@ -236,7 +234,7 @@ public class HiCS<V extends NumberVector<?>> extends AbstractAlgorithm<OutlierRe
*/
private ArrayList<ArrayDBIDs> buildOneDimIndexes(Relation<? extends NumberVector<?>> relation) {
final int dim = RelationUtil.dimensionality(relation);
- ArrayList<ArrayDBIDs> subspaceIndex = new ArrayList<ArrayDBIDs>(dim + 1);
+ ArrayList<ArrayDBIDs> subspaceIndex = new ArrayList<>(dim + 1);
SortDBIDsBySingleDimension comp = new VectorUtil.SortDBIDsBySingleDimension(relation);
for (int i = 0; i < dim; i++) {
@@ -264,8 +262,8 @@ public class HiCS<V extends NumberVector<?>> extends AbstractAlgorithm<OutlierRe
dprog.setProcessed(2, LOG);
}
- TreeSet<HiCSSubspace> subspaceList = new TreeSet<HiCSSubspace>(HiCSSubspace.SORT_BY_SUBSPACE);
- TopBoundedHeap<HiCSSubspace> dDimensionalList = new TopBoundedHeap<HiCSSubspace>(cutoff, HiCSSubspace.SORT_BY_CONTRAST_ASC);
+ TreeSet<HiCSSubspace> subspaceList = new TreeSet<>(HiCSSubspace.SORT_BY_SUBSPACE);
+ TopBoundedHeap<HiCSSubspace> dDimensionalList = new TopBoundedHeap<>(cutoff, HiCSSubspace.SORT_BY_CONTRAST_ASC);
FiniteProgress prog = LOG.isVerbose() ? new FiniteProgress("Generating two-element subsets", (dbdim * (dbdim - 1)) >> 1, LOG) : null;
// compute two-element sets of subspaces
for (int i = 0; i < dbdim; i++) {
@@ -291,10 +289,10 @@ public class HiCS<V extends NumberVector<?>> extends AbstractAlgorithm<OutlierRe
}
// result now contains all d-dimensional sets of subspaces
- ArrayList<HiCSSubspace> candidateList = new ArrayList<HiCSSubspace>(dDimensionalList.size());
- for (HiCSSubspace sub : dDimensionalList) {
- subspaceList.add(sub);
- candidateList.add(sub);
+ ArrayList<HiCSSubspace> candidateList = new ArrayList<>(dDimensionalList.size());
+ for (Heap<HiCSSubspace>.UnorderedIter it = dDimensionalList.unorderedIter(); it.valid(); it.advance()) {
+ subspaceList.add(it.get());
+ candidateList.add(it.get());
}
dDimensionalList.clear();
// candidateList now contains the *m* best d-dimensional sets
@@ -322,8 +320,8 @@ public class HiCS<V extends NumberVector<?>> extends AbstractAlgorithm<OutlierRe
}
// Prune
for (HiCSSubspace cand : candidateList) {
- for (HiCSSubspace nextSet : dDimensionalList) {
- if (nextSet.contrast > cand.contrast) {
+ for (Heap<HiCSSubspace>.UnorderedIter it = dDimensionalList.unorderedIter(); it.valid(); it.advance()) {
+ if (it.get().contrast > cand.contrast) {
subspaceList.remove(cand);
break;
}
@@ -610,12 +608,12 @@ public class HiCS<V extends NumberVector<?>> extends AbstractAlgorithm<OutlierRe
alpha = alphaP.doubleValue();
}
- final ObjectParameter<OutlierAlgorithm> algoP = new ObjectParameter<OutlierAlgorithm>(ALGO_ID, OutlierAlgorithm.class, LOF.class);
+ final ObjectParameter<OutlierAlgorithm> algoP = new ObjectParameter<>(ALGO_ID, OutlierAlgorithm.class, LOF.class);
if (config.grab(algoP)) {
outlierAlgorithm = algoP.instantiateClass(config);
}
- final ObjectParameter<GoodnessOfFitTest> testP = new ObjectParameter<GoodnessOfFitTest>(TEST_ID, GoodnessOfFitTest.class, KolmogorovSmirnovTest.class);
+ final ObjectParameter<GoodnessOfFitTest> testP = new ObjectParameter<>(TEST_ID, GoodnessOfFitTest.class, KolmogorovSmirnovTest.class);
if (config.grab(testP)) {
statTest = testP.instantiateClass(config);
}
@@ -634,7 +632,7 @@ public class HiCS<V extends NumberVector<?>> extends AbstractAlgorithm<OutlierRe
@Override
protected HiCS<V> makeInstance() {
- return new HiCS<V>(m, alpha, outlierAlgorithm, statTest, cutoff, rnd);
+ return new HiCS<>(m, alpha, outlierAlgorithm, statTest, cutoff, rnd);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/RescaleMetaOutlierAlgorithm.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/RescaleMetaOutlierAlgorithm.java
index 387041da..8ebdc27a 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/RescaleMetaOutlierAlgorithm.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/RescaleMetaOutlierAlgorithm.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier.meta;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -50,6 +50,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameteriz
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
import de.lmu.ifi.dbs.elki.utilities.scaling.ScalingFunction;
import de.lmu.ifi.dbs.elki.utilities.scaling.outlier.OutlierScalingFunction;
+import de.lmu.ifi.dbs.elki.workflow.AlgorithmStep;
/**
* Scale another outlier score using the given scaling function.
@@ -114,7 +115,7 @@ public class RescaleMetaOutlierAlgorithm extends AbstractAlgorithm<OutlierResult
}
OutlierScoreMeta meta = new BasicOutlierScoreMeta(minmax.getMin(), minmax.getMax(), scaling.getMin(), scaling.getMax());
- Relation<Double> scoresult = new MaterializedRelation<Double>("Scaled Outlier", "scaled-outlier", TypeUtil.DOUBLE, scaledscores, scores.getDBIDs());
+ Relation<Double> scoresult = new MaterializedRelation<>("Scaled Outlier", "scaled-outlier", TypeUtil.DOUBLE, scaledscores, scores.getDBIDs());
OutlierResult result = new OutlierResult(meta, scoresult);
result.addChildResult(innerresult);
@@ -167,12 +168,12 @@ public class RescaleMetaOutlierAlgorithm extends AbstractAlgorithm<OutlierResult
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- ObjectParameter<Algorithm> algP = new ObjectParameter<Algorithm>(OptionID.ALGORITHM, OutlierAlgorithm.class);
+ ObjectParameter<Algorithm> algP = new ObjectParameter<>(AlgorithmStep.Parameterizer.ALGORITHM_ID, OutlierAlgorithm.class);
if(config.grab(algP)) {
algorithm = algP.instantiateClass(config);
}
- ObjectParameter<ScalingFunction> scalingP = new ObjectParameter<ScalingFunction>(SCALING_ID, ScalingFunction.class);
+ ObjectParameter<ScalingFunction> scalingP = new ObjectParameter<>(SCALING_ID, ScalingFunction.class);
if(config.grab(scalingP)) {
scaling = scalingP.instantiateClass(config);
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/SimpleOutlierEnsemble.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/SimpleOutlierEnsemble.java
index b7791fc4..d40af384 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/SimpleOutlierEnsemble.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/SimpleOutlierEnsemble.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier.meta;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -58,6 +58,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.ListParamet
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectListParameter;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
+import de.lmu.ifi.dbs.elki.workflow.AlgorithmStep;
/**
* Simple outlier ensemble method.
@@ -100,7 +101,7 @@ public class SimpleOutlierEnsemble extends AbstractAlgorithm<OutlierResult> impl
int num = algorithms.size();
// Run inner outlier algorithms
ModifiableDBIDs ids = DBIDUtil.newHashSet();
- ArrayList<OutlierResult> results = new ArrayList<OutlierResult>(num);
+ ArrayList<OutlierResult> results = new ArrayList<>(num);
{
FiniteProgress prog = LOG.isVerbose() ? new FiniteProgress("Inner outlier algorithms", num, LOG) : null;
for (Algorithm alg : algorithms) {
@@ -155,7 +156,7 @@ public class SimpleOutlierEnsemble extends AbstractAlgorithm<OutlierResult> impl
}
}
OutlierScoreMeta meta = new BasicOutlierScoreMeta(minmax.getMin(), minmax.getMax());
- Relation<Double> scores = new MaterializedRelation<Double>("Simple Outlier Ensemble", "ensemble-outlier", TypeUtil.DOUBLE, sumscore, ids);
+ Relation<Double> scores = new MaterializedRelation<>("Simple Outlier Ensemble", "ensemble-outlier", TypeUtil.DOUBLE, sumscore, ids);
return new OutlierResult(meta, scores);
}
@@ -200,7 +201,7 @@ public class SimpleOutlierEnsemble extends AbstractAlgorithm<OutlierResult> impl
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- ObjectListParameter<OutlierAlgorithm> algP = new ObjectListParameter<OutlierAlgorithm>(OptionID.ALGORITHM, OutlierAlgorithm.class);
+ ObjectListParameter<OutlierAlgorithm> algP = new ObjectListParameter<>(AlgorithmStep.Parameterizer.ALGORITHM_ID, OutlierAlgorithm.class);
if (config.grab(algP)) {
ListParameterization subconfig = new ListParameterization();
ChainedParameterization chain = new ChainedParameterization(subconfig, config);
@@ -208,7 +209,7 @@ public class SimpleOutlierEnsemble extends AbstractAlgorithm<OutlierResult> impl
algorithms = algP.instantiateClasses(chain);
subconfig.logAndClearReportedErrors();
}
- ObjectParameter<EnsembleVoting> votingP = new ObjectParameter<EnsembleVoting>(VOTING_ID, EnsembleVoting.class);
+ ObjectParameter<EnsembleVoting> votingP = new ObjectParameter<>(VOTING_ID, EnsembleVoting.class);
if (config.grab(votingP)) {
voting = votingP.instantiateClass(config);
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/package-info.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/package-info.java
index 7c5dd8b0..f28f8db3 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/package-info.java
@@ -8,7 +8,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/package-info.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/package-info.java
index eca0d876..0ce6f9b5 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/package-info.java
@@ -14,7 +14,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/AbstractDistanceBasedSpatialOutlier.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/AbstractDistanceBasedSpatialOutlier.java
index f37ee182..e059c16c 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/AbstractDistanceBasedSpatialOutlier.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/AbstractDistanceBasedSpatialOutlier.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier.spatial;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,8 +25,8 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier.spatial;
import de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.neighborhood.NeighborSetPredicate;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/AbstractNeighborhoodOutlier.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/AbstractNeighborhoodOutlier.java
index d3770504..3b3e71b3 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/AbstractNeighborhoodOutlier.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/AbstractNeighborhoodOutlier.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier.spatial;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -88,7 +88,7 @@ public abstract class AbstractNeighborhoodOutlier<O> extends AbstractAlgorithm<O
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- final ObjectParameter<NeighborSetPredicate.Factory<O>> param = new ObjectParameter<NeighborSetPredicate.Factory<O>>(NEIGHBORHOOD_ID, NeighborSetPredicate.Factory.class);
+ final ObjectParameter<NeighborSetPredicate.Factory<O>> param = new ObjectParameter<>(NEIGHBORHOOD_ID, NeighborSetPredicate.Factory.class);
if(config.grab(param)) {
npredf = param.instantiateClass(config);
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuGLSBackwardSearchAlgorithm.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuGLSBackwardSearchAlgorithm.java
index cd5670f7..5035cf6f 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuGLSBackwardSearchAlgorithm.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuGLSBackwardSearchAlgorithm.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier.spatial;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,22 +28,23 @@ import de.lmu.ifi.dbs.elki.algorithm.outlier.OutlierAlgorithm;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.database.QueryUtil;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs;
-import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDVar;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
import de.lmu.ifi.dbs.elki.database.relation.ProxyView;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.database.relation.RelationUtil;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
@@ -116,23 +117,24 @@ public class CTLuGLSBackwardSearchAlgorithm<V extends NumberVector<?>, D extends
/**
* Run the algorithm
*
+ * @param database Database to process
* @param relationx Spatial relation
* @param relationy Attribute relation
* @return Algorithm result
*/
- public OutlierResult run(Relation<V> relationx, Relation<? extends NumberVector<?>> relationy) {
+ public OutlierResult run(Database database, Relation<V> relationx, Relation<? extends NumberVector<?>> relationy) {
WritableDoubleDataStore scores = DataStoreUtil.makeDoubleStorage(relationx.getDBIDs(), DataStoreFactory.HINT_STATIC);
DoubleMinMax mm = new DoubleMinMax(0.0, 0.0);
// Outlier detection loop
{
ModifiableDBIDs idview = DBIDUtil.newHashSet(relationx.getDBIDs());
- ProxyView<V> proxy = new ProxyView<V>(relationx.getDatabase(), idview, relationx);
+ ProxyView<V> proxy = new ProxyView<>(database, idview, relationx);
double phialpha = NormalDistribution.standardNormalQuantile(1.0 - alpha *.5);
// Detect outliers while significant.
while(true) {
- Pair<DBID, Double> candidate = singleIteration(proxy, relationy);
+ Pair<DBIDVar, Double> candidate = singleIteration(proxy, relationy);
if(candidate.second < phialpha) {
break;
}
@@ -149,7 +151,7 @@ public class CTLuGLSBackwardSearchAlgorithm<V extends NumberVector<?>, D extends
}
}
- Relation<Double> scoreResult = new MaterializedRelation<Double>("GLSSODBackward", "GLSSODbackward-outlier", TypeUtil.DOUBLE, scores, relationx.getDBIDs());
+ Relation<Double> scoreResult = new MaterializedRelation<>("GLSSODBackward", "GLSSODbackward-outlier", TypeUtil.DOUBLE, scores, relationx.getDBIDs());
OutlierScoreMeta scoreMeta = new BasicOutlierScoreMeta(mm.getMin(), mm.getMax(), 0, Double.POSITIVE_INFINITY, 0);
return new OutlierResult(scoreMeta, scoreResult);
}
@@ -161,7 +163,7 @@ public class CTLuGLSBackwardSearchAlgorithm<V extends NumberVector<?>, D extends
* @param relationy Attribute relation
* @return Top outlier and associated score
*/
- private Pair<DBID, Double> singleIteration(Relation<V> relationx, Relation<? extends NumberVector<?>> relationy) {
+ private Pair<DBIDVar, Double> singleIteration(Relation<V> relationx, Relation<? extends NumberVector<?>> relationy) {
final int dim = RelationUtil.dimensionality(relationx);
final int dimy = RelationUtil.dimensionality(relationy);
assert (dim == 2);
@@ -203,7 +205,7 @@ public class CTLuGLSBackwardSearchAlgorithm<V extends NumberVector<?>, D extends
// Fill the neighborhood matrix F:
{
- KNNResult<D> neighbors = knnQuery.getKNNForDBID(id, k + 1);
+ KNNList<D> neighbors = knnQuery.getKNNForDBID(id, k + 1);
ModifiableDBIDs neighborhood = DBIDUtil.newArray(neighbors.size());
for(DBIDIter neighbor = neighbors.iter(); neighbor.valid(); neighbor.advance()) {
if(DBIDUtil.equal(id, neighbor)) {
@@ -237,7 +239,7 @@ public class CTLuGLSBackwardSearchAlgorithm<V extends NumberVector<?>, D extends
// calculate the absolute values of standard residuals
Matrix E = F.times(Y.minus(X.times(b))).timesEquals(norm);
- DBID worstid = null;
+ DBIDVar worstid = DBIDUtil.newVar();
double worstscore = Double.NEGATIVE_INFINITY;
int i = 0;
for(DBIDIter id = ids.iter(); id.valid(); id.advance(), i++) {
@@ -245,11 +247,11 @@ public class CTLuGLSBackwardSearchAlgorithm<V extends NumberVector<?>, D extends
// double err = Math.abs(E.get(i, 0));
if(err > worstscore) {
worstscore = err;
- worstid = DBIDUtil.deref(id);
+ worstid.set(id);
}
}
- return new Pair<DBID, Double>(worstid, worstscore);
+ return new Pair<>(worstid, worstscore);
}
@Override
@@ -302,7 +304,7 @@ public class CTLuGLSBackwardSearchAlgorithm<V extends NumberVector<?>, D extends
@Override
protected CTLuGLSBackwardSearchAlgorithm<V, D> makeInstance() {
- return new CTLuGLSBackwardSearchAlgorithm<V, D>(distanceFunction, k, alpha);
+ return new CTLuGLSBackwardSearchAlgorithm<>(distanceFunction, k, alpha);
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuMeanMultipleAttributes.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuMeanMultipleAttributes.java
index 2caee128..1712dd4f 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuMeanMultipleAttributes.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuMeanMultipleAttributes.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier.spatial;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -124,7 +124,7 @@ public class CTLuMeanMultipleAttributes<N, O extends NumberVector<?>> extends Ab
scores.putDouble(iditer, score);
}
- Relation<Double> scoreResult = new MaterializedRelation<Double>("mean multiple attributes spatial outlier", "mean-multipleattributes-outlier", TypeUtil.DOUBLE, scores, attributes.getDBIDs());
+ Relation<Double> scoreResult = new MaterializedRelation<>("mean multiple attributes spatial outlier", "mean-multipleattributes-outlier", TypeUtil.DOUBLE, scores, attributes.getDBIDs());
OutlierScoreMeta scoreMeta = new BasicOutlierScoreMeta(minmax.getMin(), minmax.getMax(), 0.0, Double.POSITIVE_INFINITY, 0);
OutlierResult or = new OutlierResult(scoreMeta, scoreResult);
or.addChildResult(npred);
@@ -149,7 +149,7 @@ public class CTLuMeanMultipleAttributes<N, O extends NumberVector<?>> extends Ab
public static class Parameterizer<N, O extends NumberVector<?>> extends AbstractNeighborhoodOutlier.Parameterizer<N> {
@Override
protected CTLuMeanMultipleAttributes<N, O> makeInstance() {
- return new CTLuMeanMultipleAttributes<N, O>(npredf);
+ return new CTLuMeanMultipleAttributes<>(npredf);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuMedianAlgorithm.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuMedianAlgorithm.java
index 7755a459..9848d664 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuMedianAlgorithm.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuMedianAlgorithm.java
@@ -132,7 +132,7 @@ public class CTLuMedianAlgorithm<N> extends AbstractNeighborhoodOutlier<N> {
scores.putDouble(iditer, score);
}
- Relation<Double> scoreResult = new MaterializedRelation<Double>("MO", "Median-outlier", TypeUtil.DOUBLE, scores, relation.getDBIDs());
+ Relation<Double> scoreResult = new MaterializedRelation<>("MO", "Median-outlier", TypeUtil.DOUBLE, scores, relation.getDBIDs());
OutlierScoreMeta scoreMeta = new BasicOutlierScoreMeta(minmax.getMin(), minmax.getMax(), 0.0, Double.POSITIVE_INFINITY, 0);
OutlierResult or = new OutlierResult(scoreMeta, scoreResult);
or.addChildResult(npred);
@@ -161,7 +161,7 @@ public class CTLuMedianAlgorithm<N> extends AbstractNeighborhoodOutlier<N> {
public static class Parameterizer<N> extends AbstractNeighborhoodOutlier.Parameterizer<N> {
@Override
protected CTLuMedianAlgorithm<N> makeInstance() {
- return new CTLuMedianAlgorithm<N>(npredf);
+ return new CTLuMedianAlgorithm<>(npredf);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuMedianMultipleAttributes.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuMedianMultipleAttributes.java
index 0d515ac7..583958fe 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuMedianMultipleAttributes.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuMedianMultipleAttributes.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier.spatial;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -150,7 +150,7 @@ public class CTLuMedianMultipleAttributes<N, O extends NumberVector<?>> extends
scores.putDouble(iditer, score);
}
- Relation<Double> scoreResult = new MaterializedRelation<Double>("Median multiple attributes outlier", "median-outlier", TypeUtil.DOUBLE, scores, attributes.getDBIDs());
+ Relation<Double> scoreResult = new MaterializedRelation<>("Median multiple attributes outlier", "median-outlier", TypeUtil.DOUBLE, scores, attributes.getDBIDs());
OutlierScoreMeta scoreMeta = new BasicOutlierScoreMeta(minmax.getMin(), minmax.getMax(), 0.0, Double.POSITIVE_INFINITY, 0);
OutlierResult or = new OutlierResult(scoreMeta, scoreResult);
or.addChildResult(npred);
@@ -175,7 +175,7 @@ public class CTLuMedianMultipleAttributes<N, O extends NumberVector<?>> extends
public static class Parameterizer<N, O extends NumberVector<?>> extends AbstractNeighborhoodOutlier.Parameterizer<N> {
@Override
protected CTLuMedianMultipleAttributes<N, O> makeInstance() {
- return new CTLuMedianMultipleAttributes<N, O>(npredf);
+ return new CTLuMedianMultipleAttributes<>(npredf);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuMoranScatterplotOutlier.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuMoranScatterplotOutlier.java
index 3b876bba..da527af0 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuMoranScatterplotOutlier.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuMoranScatterplotOutlier.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier.spatial;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -136,7 +136,7 @@ public class CTLuMoranScatterplotOutlier<N> extends AbstractNeighborhoodOutlier<
scores.putDouble(iditer, score);
}
- Relation<Double> scoreResult = new MaterializedRelation<Double>("MoranOutlier", "Moran Scatterplot Outlier", TypeUtil.DOUBLE, scores, relation.getDBIDs());
+ Relation<Double> scoreResult = new MaterializedRelation<>("MoranOutlier", "Moran Scatterplot Outlier", TypeUtil.DOUBLE, scores, relation.getDBIDs());
OutlierScoreMeta scoreMeta = new BasicOutlierScoreMeta(minmax.getMin(), minmax.getMax(), Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 0);
OutlierResult or = new OutlierResult(scoreMeta, scoreResult);
or.addChildResult(npred);
@@ -165,7 +165,7 @@ public class CTLuMoranScatterplotOutlier<N> extends AbstractNeighborhoodOutlier<
public static class Parameterizer<N> extends AbstractNeighborhoodOutlier.Parameterizer<N> {
@Override
protected CTLuMoranScatterplotOutlier<N> makeInstance() {
- return new CTLuMoranScatterplotOutlier<N>(npredf);
+ return new CTLuMoranScatterplotOutlier<>(npredf);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuRandomWalkEC.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuRandomWalkEC.java
index ec92afd7..c8efe4da 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuRandomWalkEC.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuRandomWalkEC.java
@@ -38,12 +38,11 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNHeap;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNHeap;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNUtil;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
@@ -137,7 +136,7 @@ public class CTLuRandomWalkEC<N, D extends NumberDistance<D, ?>> extends Abstrac
// construct the relation Matrix of the ec-graph
Matrix E = new Matrix(ids.size(), ids.size());
- KNNHeap<D> heap = KNNUtil.newHeap(distFunc.getDistanceFactory(), k);
+ KNNHeap<D> heap = DBIDUtil.newHeap(distFunc.getDistanceFactory(), k);
{
int i = 0;
for(DBIDIter id = ids.iter(); id.valid(); id.advance(), i++) {
@@ -226,7 +225,7 @@ public class CTLuRandomWalkEC<N, D extends NumberDistance<D, ?>> extends Abstrac
scores.putDouble(id, score);
}
- Relation<Double> scoreResult = new MaterializedRelation<Double>("randomwalkec", "RandomWalkEC", TypeUtil.DOUBLE, scores, relation.getDBIDs());
+ Relation<Double> scoreResult = new MaterializedRelation<>("randomwalkec", "RandomWalkEC", TypeUtil.DOUBLE, scores, relation.getDBIDs());
OutlierScoreMeta scoreMeta = new BasicOutlierScoreMeta(minmax.getMin(), minmax.getMax(), 0.0, Double.POSITIVE_INFINITY, 0.0);
return new OutlierResult(scoreMeta, scoreResult);
}
@@ -329,7 +328,7 @@ public class CTLuRandomWalkEC<N, D extends NumberDistance<D, ?>> extends Abstrac
@Override
protected CTLuRandomWalkEC<N, D> makeInstance() {
- return new CTLuRandomWalkEC<N, D>(distanceFunction, alpha, c, k);
+ return new CTLuRandomWalkEC<>(distanceFunction, alpha, c, k);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuScatterplotOutlier.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuScatterplotOutlier.java
index 295c7414..bcbbfd2a 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuScatterplotOutlier.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuScatterplotOutlier.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier.spatial;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -160,7 +160,7 @@ public class CTLuScatterplotOutlier<N> extends AbstractNeighborhoodOutlier<N> {
}
}
// build representation
- Relation<Double> scoreResult = new MaterializedRelation<Double>("SPO", "Scatterplot-Outlier", TypeUtil.DOUBLE, scores, relation.getDBIDs());
+ Relation<Double> scoreResult = new MaterializedRelation<>("SPO", "Scatterplot-Outlier", TypeUtil.DOUBLE, scores, relation.getDBIDs());
OutlierScoreMeta scoreMeta = new BasicOutlierScoreMeta(minmax.getMin(), minmax.getMax(), 0.0, Double.POSITIVE_INFINITY, 0);
OutlierResult or = new OutlierResult(scoreMeta, scoreResult);
or.addChildResult(npred);
@@ -189,7 +189,7 @@ public class CTLuScatterplotOutlier<N> extends AbstractNeighborhoodOutlier<N> {
public static class Parameterizer<N> extends AbstractNeighborhoodOutlier.Parameterizer<N> {
@Override
protected CTLuScatterplotOutlier<N> makeInstance() {
- return new CTLuScatterplotOutlier<N>(npredf);
+ return new CTLuScatterplotOutlier<>(npredf);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuZTestOutlier.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuZTestOutlier.java
index 02573a06..d6cb5a50 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuZTestOutlier.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuZTestOutlier.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier.spatial;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -133,7 +133,7 @@ public class CTLuZTestOutlier<N> extends AbstractNeighborhoodOutlier<N> {
}
// Wrap result
- Relation<Double> scoreResult = new MaterializedRelation<Double>("ZTest", "Z Test score", TypeUtil.DOUBLE, scores, relation.getDBIDs());
+ Relation<Double> scoreResult = new MaterializedRelation<>("ZTest", "Z Test score", TypeUtil.DOUBLE, scores, relation.getDBIDs());
OutlierScoreMeta scoreMeta = new BasicOutlierScoreMeta(minmax.getMin(), minmax.getMax(), 0.0, Double.POSITIVE_INFINITY, 0);
OutlierResult or = new OutlierResult(scoreMeta, scoreResult);
or.addChildResult(npred);
@@ -162,7 +162,7 @@ public class CTLuZTestOutlier<N> extends AbstractNeighborhoodOutlier<N> {
public static class Parameterizer<N> extends AbstractNeighborhoodOutlier.Parameterizer<N> {
@Override
protected CTLuZTestOutlier<N> makeInstance() {
- return new CTLuZTestOutlier<N>(npredf);
+ return new CTLuZTestOutlier<>(npredf);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/SLOM.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/SLOM.java
index 720fa39f..08c3e29b 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/SLOM.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/SLOM.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier.spatial;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -187,7 +187,7 @@ public class SLOM<N, O, D extends NumberDistance<D, ?>> extends AbstractDistance
slomminmax.put(slom);
}
- Relation<Double> scoreResult = new MaterializedRelation<Double>("SLOM", "slom-outlier", TypeUtil.DOUBLE, sloms, relation.getDBIDs());
+ Relation<Double> scoreResult = new MaterializedRelation<>("SLOM", "slom-outlier", TypeUtil.DOUBLE, sloms, relation.getDBIDs());
OutlierScoreMeta scoreMeta = new BasicOutlierScoreMeta(slomminmax.getMin(), slomminmax.getMax(), 0.0, Double.POSITIVE_INFINITY);
OutlierResult or = new OutlierResult(scoreMeta, scoreResult);
or.addChildResult(npred);
@@ -218,7 +218,7 @@ public class SLOM<N, O, D extends NumberDistance<D, ?>> extends AbstractDistance
public static class Parameterizer<N, O, D extends NumberDistance<D, ?>> extends AbstractDistanceBasedSpatialOutlier.Parameterizer<N, O, D> {
@Override
protected SLOM<N, O, D> makeInstance() {
- return new SLOM<N, O, D>(npredf, distanceFunction);
+ return new SLOM<>(npredf, distanceFunction);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/SOF.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/SOF.java
index a6f39a60..a2605f39 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/SOF.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/SOF.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier.spatial;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -46,7 +46,7 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
/**
* The Spatial Outlier Factor (SOF) is a spatial
- * {@link de.lmu.ifi.dbs.elki.algorithm.outlier.LOF LOF} variation.
+ * {@link de.lmu.ifi.dbs.elki.algorithm.outlier.lof.LOF LOF} variation.
*
* Since the "reachability distance" of LOF cannot be used canonically in the
* bichromatic case, this part of LOF is dropped and the exact distance is used
@@ -138,7 +138,7 @@ public class SOF<N, O, D extends NumberDistance<D, ?>> extends AbstractDistanceB
}
// Build result representation.
- Relation<Double> scoreResult = new MaterializedRelation<Double>("Spatial Outlier Factor", "sof-outlier", TypeUtil.DOUBLE, lofs, relation.getDBIDs());
+ Relation<Double> scoreResult = new MaterializedRelation<>("Spatial Outlier Factor", "sof-outlier", TypeUtil.DOUBLE, lofs, relation.getDBIDs());
OutlierScoreMeta scoreMeta = new QuotientOutlierScoreMeta(lofminmax.getMin(), lofminmax.getMax(), 0.0, Double.POSITIVE_INFINITY, 1.0);
OutlierResult or = new OutlierResult(scoreMeta, scoreResult);
or.addChildResult(npred);
@@ -164,7 +164,7 @@ public class SOF<N, O, D extends NumberDistance<D, ?>> extends AbstractDistanceB
public static class Parameterizer<N, O, D extends NumberDistance<D, ?>> extends AbstractDistanceBasedSpatialOutlier.Parameterizer<N, O, D> {
@Override
protected SOF<N, O, D> makeInstance() {
- return new SOF<N, O, D>(npredf, distanceFunction);
+ return new SOF<>(npredf, distanceFunction);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/TrimmedMeanApproach.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/TrimmedMeanApproach.java
index 9aa21b66..e07ce480 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/TrimmedMeanApproach.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/TrimmedMeanApproach.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier.spatial;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -186,7 +186,7 @@ public class TrimmedMeanApproach<N> extends AbstractNeighborhoodOutlier<N> {
minmax.put(score);
}
//
- Relation<Double> scoreResult = new MaterializedRelation<Double>("TrimmedMean", "Trimmed Mean Score", TypeUtil.DOUBLE, scores, relation.getDBIDs());
+ Relation<Double> scoreResult = new MaterializedRelation<>("TrimmedMean", "Trimmed Mean Score", TypeUtil.DOUBLE, scores, relation.getDBIDs());
OutlierScoreMeta scoreMeta = new BasicOutlierScoreMeta(minmax.getMin(), minmax.getMax(), 0.0, Double.POSITIVE_INFINITY, 0);
OutlierResult or = new OutlierResult(scoreMeta, scoreResult);
or.addChildResult(npred);
@@ -237,7 +237,7 @@ public class TrimmedMeanApproach<N> extends AbstractNeighborhoodOutlier<N> {
@Override
protected TrimmedMeanApproach<N> makeInstance() {
- return new TrimmedMeanApproach<N>(npredf, p);
+ return new TrimmedMeanApproach<>(npredf, p);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/AbstractPrecomputedNeighborhood.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/AbstractPrecomputedNeighborhood.java
index 2c706ce0..ef237928 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/AbstractPrecomputedNeighborhood.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/AbstractPrecomputedNeighborhood.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.neighborhood;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/ExtendedNeighborhood.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/ExtendedNeighborhood.java
index 4aa96b25..c4fc4407 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/ExtendedNeighborhood.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/ExtendedNeighborhood.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.neighborhood;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -202,7 +202,7 @@ public class ExtendedNeighborhood extends AbstractPrecomputedNeighborhood {
* @return Inner neighborhood.
*/
protected static <O> NeighborSetPredicate.Factory<O> getParameterInnerNeighborhood(Parameterization config) {
- final ObjectParameter<NeighborSetPredicate.Factory<O>> param = new ObjectParameter<NeighborSetPredicate.Factory<O>>(NEIGHBORHOOD_ID, NeighborSetPredicate.Factory.class);
+ final ObjectParameter<NeighborSetPredicate.Factory<O>> param = new ObjectParameter<>(NEIGHBORHOOD_ID, NeighborSetPredicate.Factory.class);
if(config.grab(param)) {
return param.instantiateClass(config);
}
@@ -233,7 +233,7 @@ public class ExtendedNeighborhood extends AbstractPrecomputedNeighborhood {
@Override
protected ExtendedNeighborhood.Factory<O> makeInstance() {
- return new ExtendedNeighborhood.Factory<O>(inner, steps);
+ return new ExtendedNeighborhood.Factory<>(inner, steps);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/ExternalNeighborhood.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/ExternalNeighborhood.java
index 01052c1f..96896bd8 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/ExternalNeighborhood.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/ExternalNeighborhood.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.neighborhood;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -36,6 +36,7 @@ import de.lmu.ifi.dbs.elki.data.ExternalID;
import de.lmu.ifi.dbs.elki.data.LabelList;
import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.database.datastore.DataStore;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
@@ -119,8 +120,8 @@ public class ExternalNeighborhood extends AbstractPrecomputedNeighborhood {
}
@Override
- public NeighborSetPredicate instantiate(Relation<?> database) {
- DataStore<DBIDs> store = loadNeighbors(database);
+ public NeighborSetPredicate instantiate(Relation<?> relation) {
+ DataStore<DBIDs> store = loadNeighbors(relation.getDatabase(), relation);
ExternalNeighborhood neighborhood = new ExternalNeighborhood(store);
return neighborhood;
}
@@ -133,8 +134,8 @@ public class ExternalNeighborhood extends AbstractPrecomputedNeighborhood {
/**
* Method to load the external neighbors.
*/
- private DataStore<DBIDs> loadNeighbors(Relation<?> database) {
- final WritableDataStore<DBIDs> store = DataStoreUtil.makeStorage(database.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_STATIC | DataStoreFactory.HINT_TEMP, DBIDs.class);
+ private DataStore<DBIDs> loadNeighbors(Database database, Relation<?> relation) {
+ final WritableDataStore<DBIDs> store = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_STATIC | DataStoreFactory.HINT_TEMP, DBIDs.class);
if(LOG.isVerbose()) {
LOG.verbose("Loading external neighborhoods.");
@@ -146,11 +147,11 @@ public class ExternalNeighborhood extends AbstractPrecomputedNeighborhood {
// Build a map label/ExternalId -> DBID
// (i.e. a reverse index!)
// TODO: move this into the database layer to share?
- Map<String, DBID> lblmap = new HashMap<String, DBID>(database.size() << 1);
+ Map<String, DBID> lblmap = new HashMap<>(relation.size() << 1);
{
- Relation<LabelList> olq = database.getDatabase().getRelation(TypeUtil.LABELLIST);
- Relation<ExternalID> eidq = database.getDatabase().getRelation(TypeUtil.EXTERNALID);
- for(DBIDIter iditer = database.iterDBIDs(); iditer.valid(); iditer.advance()) {
+ Relation<LabelList> olq = database.getRelation(TypeUtil.LABELLIST);
+ Relation<ExternalID> eidq = database.getRelation(TypeUtil.EXTERNALID);
+ for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
if(eidq != null) {
ExternalID eid = eidq.get(iditer);
if(eid != null) {
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/NeighborSetPredicate.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/NeighborSetPredicate.java
index b52f8e91..25283d5c 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/NeighborSetPredicate.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/NeighborSetPredicate.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.neighborhood;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/PrecomputedKNearestNeighborNeighborhood.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/PrecomputedKNearestNeighborNeighborhood.java
index f6000ef0..c43ebba7 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/PrecomputedKNearestNeighborNeighborhood.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/PrecomputedKNearestNeighborNeighborhood.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.neighborhood;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -32,10 +32,10 @@ import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
@@ -119,7 +119,7 @@ public class PrecomputedKNearestNeighborNeighborhood<D extends Distance<D>> exte
// TODO: use bulk?
WritableDataStore<DBIDs> s = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_STATIC, DBIDs.class);
for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
- KNNResult<D> neighbors = knnQuery.getKNNForDBID(iditer, k);
+ KNNList<D> neighbors = knnQuery.getKNNForDBID(iditer, k);
ArrayModifiableDBIDs neighbours = DBIDUtil.newArray(neighbors.size());
for (DBIDIter neighbor = neighbors.iter(); neighbor.valid(); neighbor.advance()) {
neighbours.add(neighbor);
@@ -172,7 +172,7 @@ public class PrecomputedKNearestNeighborNeighborhood<D extends Distance<D>> exte
if(config.grab(kP)) {
k = kP.getValue();
}
- final ObjectParameter<DistanceFunction<? super O, D>> distP = new ObjectParameter<DistanceFunction<? super O, D>>(DISTANCEFUNCTION_ID, DistanceFunction.class);
+ final ObjectParameter<DistanceFunction<? super O, D>> distP = new ObjectParameter<>(DISTANCEFUNCTION_ID, DistanceFunction.class);
if(config.grab(distP)) {
distFunc = distP.instantiateClass(config);
}
@@ -180,7 +180,7 @@ public class PrecomputedKNearestNeighborNeighborhood<D extends Distance<D>> exte
@Override
protected PrecomputedKNearestNeighborNeighborhood.Factory<O, D> makeInstance() {
- return new PrecomputedKNearestNeighborNeighborhood.Factory<O, D>(k, distFunc);
+ return new PrecomputedKNearestNeighborNeighborhood.Factory<>(k, distFunc);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/package-info.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/package-info.java
index 47ca5ad2..fd51ca22 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/weighted/LinearWeightedExtendedNeighborhood.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/weighted/LinearWeightedExtendedNeighborhood.java
index f1c68577..05bf2f18 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/weighted/LinearWeightedExtendedNeighborhood.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/weighted/LinearWeightedExtendedNeighborhood.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.neighborhood.weighted;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -89,7 +89,7 @@ public class LinearWeightedExtendedNeighborhood implements WeightedNeighborSetPr
@Override
public Collection<DoubleDBIDPair> getWeightedNeighbors(DBIDRef reference) {
ModifiableDBIDs seen = DBIDUtil.newHashSet();
- List<DoubleDBIDPair> result = new ArrayList<DoubleDBIDPair>();
+ List<DoubleDBIDPair> result = new ArrayList<>();
// Add starting object
result.add(DBIDUtil.newPair(computeWeight(0), reference));
@@ -194,7 +194,7 @@ public class LinearWeightedExtendedNeighborhood implements WeightedNeighborSetPr
* @return Inner neighborhood.
*/
protected static <O> NeighborSetPredicate.Factory<O> getParameterInnerNeighborhood(Parameterization config) {
- final ObjectParameter<NeighborSetPredicate.Factory<O>> param = new ObjectParameter<NeighborSetPredicate.Factory<O>>(NEIGHBORHOOD_ID, NeighborSetPredicate.Factory.class);
+ final ObjectParameter<NeighborSetPredicate.Factory<O>> param = new ObjectParameter<>(NEIGHBORHOOD_ID, NeighborSetPredicate.Factory.class);
if(config.grab(param)) {
return param.instantiateClass(config);
}
@@ -225,7 +225,7 @@ public class LinearWeightedExtendedNeighborhood implements WeightedNeighborSetPr
@Override
protected LinearWeightedExtendedNeighborhood.Factory<O> makeInstance() {
- return new LinearWeightedExtendedNeighborhood.Factory<O>(inner, steps);
+ return new LinearWeightedExtendedNeighborhood.Factory<>(inner, steps);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/weighted/UnweightedNeighborhoodAdapter.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/weighted/UnweightedNeighborhoodAdapter.java
index c179d81f..9bdb7d51 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/weighted/UnweightedNeighborhoodAdapter.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/weighted/UnweightedNeighborhoodAdapter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.neighborhood.weighted;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -64,7 +64,7 @@ public class UnweightedNeighborhoodAdapter implements WeightedNeighborSetPredica
@Override
public Collection<DoubleDBIDPair> getWeightedNeighbors(DBIDRef reference) {
DBIDs neighbors = inner.getNeighborDBIDs(reference);
- ArrayList<DoubleDBIDPair> adapted = new ArrayList<DoubleDBIDPair>(neighbors.size());
+ ArrayList<DoubleDBIDPair> adapted = new ArrayList<>(neighbors.size());
for(DBIDIter iter = neighbors.iter(); iter.valid(); iter.advance()) {
adapted.add(DBIDUtil.newPair(1.0, iter));
}
@@ -130,7 +130,7 @@ public class UnweightedNeighborhoodAdapter implements WeightedNeighborSetPredica
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- ObjectParameter<NeighborSetPredicate.Factory<O>> innerP = new ObjectParameter<NeighborSetPredicate.Factory<O>>(INNER_ID, NeighborSetPredicate.Factory.class);
+ ObjectParameter<NeighborSetPredicate.Factory<O>> innerP = new ObjectParameter<>(INNER_ID, NeighborSetPredicate.Factory.class);
if(config.grab(innerP)) {
inner = innerP.instantiateClass(config);
}
@@ -138,7 +138,7 @@ public class UnweightedNeighborhoodAdapter implements WeightedNeighborSetPredica
@Override
protected UnweightedNeighborhoodAdapter.Factory<O> makeInstance() {
- return new UnweightedNeighborhoodAdapter.Factory<O>(inner);
+ return new UnweightedNeighborhoodAdapter.Factory<>(inner);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/weighted/WeightedNeighborSetPredicate.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/weighted/WeightedNeighborSetPredicate.java
index 16d37587..ca0fa620 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/weighted/WeightedNeighborSetPredicate.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/weighted/WeightedNeighborSetPredicate.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.neighborhood.weighted;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/weighted/package-info.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/weighted/package-info.java
index 39165cfd..d7c7a797 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/weighted/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/weighted/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/package-info.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/package-info.java
index 13bf3f25..5a65d8c1 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/subspace/OUTRES.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/subspace/OUTRES.java
index 1965914d..ae04fef4 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/subspace/OUTRES.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/subspace/OUTRES.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier.subspace;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -37,26 +37,28 @@ import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
-import de.lmu.ifi.dbs.elki.database.ids.DistanceDBIDPair;
-import de.lmu.ifi.dbs.elki.database.ids.DoubleDistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPairList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.ModifiableDoubleDistanceDBIDList;
import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery;
import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.database.relation.RelationUtil;
import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.SubspaceEuclideanDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultIter;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceDBIDList;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceDBIDResultIter;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
import de.lmu.ifi.dbs.elki.math.MeanVariance;
-import de.lmu.ifi.dbs.elki.math.statistics.EpanechnikovKernelDensityFunction;
-import de.lmu.ifi.dbs.elki.math.statistics.KernelDensityFunction;
import de.lmu.ifi.dbs.elki.math.statistics.distribution.GammaDistribution;
+import de.lmu.ifi.dbs.elki.math.statistics.kernelfunctions.EpanechnikovKernelDensityFunction;
+import de.lmu.ifi.dbs.elki.math.statistics.kernelfunctions.KernelDensityFunction;
import de.lmu.ifi.dbs.elki.result.outlier.InvertedOutlierScoreMeta;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierScoreMeta;
@@ -145,7 +147,7 @@ public class OUTRES<V extends NumberVector<?>> extends AbstractAlgorithm<Outlier
}
OutlierScoreMeta meta = new InvertedOutlierScoreMeta(minmax.getMin(), minmax.getMax(), 0., 1., 1.);
- OutlierResult outresResult = new OutlierResult(meta, new MaterializedRelation<Double>("OUTRES", "outres-score", TypeUtil.DOUBLE, ranks, relation.getDBIDs()));
+ OutlierResult outresResult = new OutlierResult(meta, new MaterializedRelation<>("OUTRES", "outres-score", TypeUtil.DOUBLE, ranks, relation.getDBIDs()));
return outresResult;
}
@@ -175,7 +177,7 @@ public class OUTRES<V extends NumberVector<?>> extends AbstractAlgorithm<Outlier
final DoubleDistance range = new DoubleDistance(adjustedEps * 2.);
RangeQuery<V, DoubleDistance> rq = QueryUtil.getRangeQuery(kernel.relation, df, range);
- DistanceDBIDResult<DoubleDistance> neighc = rq.getRangeForDBID(id, range);
+ DistanceDBIDList<DoubleDistance> neighc = rq.getRangeForDBID(id, range);
DoubleDistanceDBIDList neigh = refineRange(neighc, adjustedEps);
if(neigh.size() > 2) {
// Relevance test
@@ -183,7 +185,7 @@ public class OUTRES<V extends NumberVector<?>> extends AbstractAlgorithm<Outlier
final double density = kernel.subspaceDensity(subspace, neigh);
// Compute mean and standard deviation for densities of neighbors.
meanv.reset();
- for (DoubleDistanceDBIDResultIter neighbor = neigh.iter(); neighbor.valid(); neighbor.advance()) {
+ for (DoubleDistanceDBIDListIter neighbor = neigh.iter(); neighbor.valid(); neighbor.advance()) {
DoubleDistanceDBIDList n2 = subsetNeighborhoodQuery(neighc, neighbor, df, adjustedEps, kernel);
meanv.put(kernel.subspaceDensity(subspace, n2));
}
@@ -208,10 +210,10 @@ public class OUTRES<V extends NumberVector<?>> extends AbstractAlgorithm<Outlier
* @param adjustedEps New epsilon
* @return refined list
*/
- private DoubleDistanceDBIDList refineRange(DistanceDBIDResult<DoubleDistance> neighc, double adjustedEps) {
- DoubleDistanceDBIDList n = new DoubleDistanceDBIDList(neighc.size());
+ private DoubleDistanceDBIDList refineRange(DistanceDBIDList<DoubleDistance> neighc, double adjustedEps) {
+ ModifiableDoubleDistanceDBIDList n = new DoubleDistanceDBIDPairList(neighc.size());
// We don't have a guarantee for this list to be sorted
- for (DistanceDBIDResultIter<DoubleDistance> neighbor = neighc.iter(); neighbor.valid(); neighbor.advance()) {
+ for (DistanceDBIDListIter<DoubleDistance> neighbor = neighc.iter(); neighbor.valid(); neighbor.advance()) {
DistanceDBIDPair<DoubleDistance> p = neighbor.getDistancePair();
if(p instanceof DoubleDistanceDBIDPair) {
if(((DoubleDistanceDBIDPair) p).doubleDistance() <= adjustedEps) {
@@ -238,10 +240,10 @@ public class OUTRES<V extends NumberVector<?>> extends AbstractAlgorithm<Outlier
* @param kernel Kernel
* @return Neighbors of neighbor object
*/
- private DoubleDistanceDBIDList subsetNeighborhoodQuery(DistanceDBIDResult<DoubleDistance> neighc, DBIDRef dbid, PrimitiveDoubleDistanceFunction<? super V> df, double adjustedEps, KernelDensityEstimator kernel) {
- DoubleDistanceDBIDList n = new DoubleDistanceDBIDList(neighc.size());
+ private DoubleDistanceDBIDList subsetNeighborhoodQuery(DistanceDBIDList<DoubleDistance> neighc, DBIDRef dbid, PrimitiveDoubleDistanceFunction<? super V> df, double adjustedEps, KernelDensityEstimator kernel) {
+ ModifiableDoubleDistanceDBIDList n = new DoubleDistanceDBIDPairList(neighc.size());
V query = kernel.relation.get(dbid);
- for (DistanceDBIDResultIter<DoubleDistance> neighbor = neighc.iter(); neighbor.valid(); neighbor.advance()) {
+ for (DistanceDBIDListIter<DoubleDistance> neighbor = neighc.iter(); neighbor.valid(); neighbor.advance()) {
DistanceDBIDPair<DoubleDistance> p = neighbor.getDistancePair();
double dist = df.doubleDistance(query, kernel.relation.get(p));
if(dist <= adjustedEps) {
@@ -348,7 +350,7 @@ public class OUTRES<V extends NumberVector<?>> extends AbstractAlgorithm<Outlier
final double bandwidth = optimalBandwidth(subspace.cardinality());
double density = 0;
- for (DoubleDistanceDBIDResultIter neighbor = neighbors.iter(); neighbor.valid(); neighbor.advance()) {
+ for (DoubleDistanceDBIDListIter neighbor = neighbors.iter(); neighbor.valid(); neighbor.advance()) {
double v = neighbor.doubleDistance() / bandwidth;
if(v < 1) {
density += 1 - (v * v);
@@ -426,7 +428,7 @@ public class OUTRES<V extends NumberVector<?>> extends AbstractAlgorithm<Outlier
@Override
protected OUTRES<O> makeInstance() {
- return new OUTRES<O>(eps);
+ return new OUTRES<>(eps);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/subspace/OutRankS1.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/subspace/OutRankS1.java
index 79243213..96c8875f 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/subspace/OutRankS1.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/subspace/OutRankS1.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier.subspace;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -133,7 +133,7 @@ public class OutRankS1 extends AbstractAlgorithm<OutlierResult> implements Outli
}
}
- Relation<Double> scoreResult = new MaterializedRelation<Double>("OutRank-S1", "OUTRANK_S1", TypeUtil.DOUBLE, score, ids);
+ Relation<Double> scoreResult = new MaterializedRelation<>("OutRank-S1", "OUTRANK_S1", TypeUtil.DOUBLE, score, ids);
OutlierScoreMeta meta = new InvertedOutlierScoreMeta(minmax.getMin(), minmax.getMax(), 0, Double.POSITIVE_INFINITY);
OutlierResult res = new OutlierResult(meta, scoreResult);
res.addChildResult(clustering);
@@ -181,7 +181,7 @@ public class OutRankS1 extends AbstractAlgorithm<OutlierResult> implements Outli
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- ObjectParameter<SubspaceClusteringAlgorithm<? extends SubspaceModel<?>>> algP = new ObjectParameter<SubspaceClusteringAlgorithm<? extends SubspaceModel<?>>>(ALGORITHM_ID, SubspaceClusteringAlgorithm.class);
+ ObjectParameter<SubspaceClusteringAlgorithm<? extends SubspaceModel<?>>> algP = new ObjectParameter<>(ALGORITHM_ID, SubspaceClusteringAlgorithm.class);
if (config.grab(algP)) {
algorithm = algP.instantiateClass(config);
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/subspace/SOD.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/subspace/SOD.java
index 35a780cd..b2255e67 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/subspace/SOD.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/subspace/SOD.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier.subspace;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -164,7 +164,7 @@ public class SOD<V extends NumberVector<?>, D extends NumberDistance<D, ?>> exte
progress.incrementProcessed(LOG);
}
DBIDs knnList = getNearestNeighbors(relation, snnInstance, iter);
- SODModel<V> model = new SODModel<V>(relation, knnList, alpha, relation.get(iter));
+ SODModel<V> model = new SODModel<>(relation, knnList, alpha, relation.get(iter));
sod_models.put(iter, model);
minmax.put(model.getSod());
}
@@ -172,7 +172,7 @@ public class SOD<V extends NumberVector<?>, D extends NumberDistance<D, ?>> exte
progress.ensureCompleted(LOG);
}
// combine results.
- Relation<SODModel<?>> models = new MaterializedRelation<SODModel<?>>("Subspace Outlier Model", "sod-outlier", new SimpleTypeInformation<SODModel<?>>(SODModel.class), sod_models, relation.getDBIDs());
+ Relation<SODModel<?>> models = new MaterializedRelation<>("Subspace Outlier Model", "sod-outlier", new SimpleTypeInformation<SODModel<?>>(SODModel.class), sod_models, relation.getDBIDs());
OutlierScoreMeta meta = new BasicOutlierScoreMeta(minmax.getMin(), minmax.getMax());
OutlierResult sodResult = new OutlierResult(meta, new SODProxyScoreResult(models, relation.getDBIDs()));
// also add the models.
@@ -194,7 +194,7 @@ public class SOD<V extends NumberVector<?>, D extends NumberDistance<D, ?>> exte
*/
private DBIDs getNearestNeighbors(Relation<V> relation, SimilarityQuery<V, D> simQ, DBIDRef queryObject) {
// similarityFunction.getPreprocessor().getParameters();
- Heap<DoubleDBIDPair> nearestNeighbors = new TiedTopBoundedHeap<DoubleDBIDPair>(knn);
+ Heap<DoubleDBIDPair> nearestNeighbors = new TiedTopBoundedHeap<>(knn);
for (DBIDIter iter = relation.iterDBIDs(); iter.valid(); iter.advance()) {
if (!DBIDUtil.equal(iter, queryObject)) {
double sim = simQ.similarity(queryObject, iter).doubleValue();
@@ -454,7 +454,7 @@ public class SOD<V extends NumberVector<?>, D extends NumberDistance<D, ?>> exte
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- final ObjectParameter<SimilarityFunction<V, D>> simP = new ObjectParameter<SimilarityFunction<V, D>>(SIM_ID, SimilarityFunction.class, SharedNearestNeighborSimilarityFunction.class);
+ final ObjectParameter<SimilarityFunction<V, D>> simP = new ObjectParameter<>(SIM_ID, SimilarityFunction.class, SharedNearestNeighborSimilarityFunction.class);
if (config.grab(simP)) {
similarityFunction = simP.instantiateClass(config);
}
@@ -474,7 +474,7 @@ public class SOD<V extends NumberVector<?>, D extends NumberDistance<D, ?>> exte
@Override
protected SOD<V, D> makeInstance() {
- return new SOD<V, D>(knn, alpha, similarityFunction);
+ return new SOD<>(knn, alpha, similarityFunction);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/subspace/package-info.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/subspace/package-info.java
index 8b1c80df..c3951821 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/subspace/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/subspace/package-info.java
@@ -7,7 +7,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/ByLabelOutlier.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/ByLabelOutlier.java
index ae95abfa..d10eaef8 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/ByLabelOutlier.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/ByLabelOutlier.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier.trivial;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -117,7 +117,7 @@ public class ByLabelOutlier extends AbstractAlgorithm<OutlierResult> implements
final double score = (pattern.matcher(label).matches()) ? 1 : 0;
scores.putDouble(iditer, score);
}
- Relation<Double> scoreres = new MaterializedRelation<Double>("By label outlier scores", "label-outlier", TypeUtil.DOUBLE, scores, relation.getDBIDs());
+ Relation<Double> scoreres = new MaterializedRelation<>("By label outlier scores", "label-outlier", TypeUtil.DOUBLE, scores, relation.getDBIDs());
OutlierScoreMeta meta = new ProbabilisticOutlierScore();
return new OutlierResult(meta, scoreres);
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/TrivialAllOutlier.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/TrivialAllOutlier.java
index 35a85d51..44a7975f 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/TrivialAllOutlier.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/TrivialAllOutlier.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier.trivial;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -73,7 +73,7 @@ public class TrivialAllOutlier extends AbstractAlgorithm<OutlierResult> implemen
for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
scores.putDouble(iditer, 1.0);
}
- Relation<Double> scoreres = new MaterializedRelation<Double>("Trivial all-outlier score", "all-outlier", TypeUtil.DOUBLE, scores, relation.getDBIDs());
+ Relation<Double> scoreres = new MaterializedRelation<>("Trivial all-outlier score", "all-outlier", TypeUtil.DOUBLE, scores, relation.getDBIDs());
OutlierScoreMeta meta = new ProbabilisticOutlierScore();
return new OutlierResult(meta, scoreres);
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/TrivialAverageCoordinateOutlier.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/TrivialAverageCoordinateOutlier.java
new file mode 100644
index 00000000..84e3ad41
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/TrivialAverageCoordinateOutlier.java
@@ -0,0 +1,98 @@
+package de.lmu.ifi.dbs.elki.algorithm.outlier.trivial;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2012
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.algorithm.AbstractAlgorithm;
+import de.lmu.ifi.dbs.elki.algorithm.outlier.OutlierAlgorithm;
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
+import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory;
+import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
+import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
+import de.lmu.ifi.dbs.elki.math.Mean;
+import de.lmu.ifi.dbs.elki.result.outlier.BasicOutlierScoreMeta;
+import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
+import de.lmu.ifi.dbs.elki.result.outlier.OutlierScoreMeta;
+
+/**
+ * Trivial method that takes the average of all dimensions (for one-dimensional
+ * data that is just the actual value!) as outlier score. Mostly useful to
+ * convert a 1d data set into a score, e.g. in geodata.
+ *
+ * @author Erich Schubert
+ */
+public class TrivialAverageCoordinateOutlier extends AbstractAlgorithm<OutlierResult> implements OutlierAlgorithm {
+ /**
+ * Our logger.
+ */
+ private static final Logging logger = Logging.getLogger(TrivialAverageCoordinateOutlier.class);
+
+ /**
+ * Constructor.
+ */
+ public TrivialAverageCoordinateOutlier() {
+ super();
+ }
+
+ @Override
+ public TypeInformation[] getInputTypeRestriction() {
+ return TypeUtil.array(TypeUtil.NUMBER_VECTOR_VARIABLE_LENGTH);
+ }
+
+ /**
+ * Run the actual algorithm.
+ *
+ * @param relation Relation
+ * @return Result
+ */
+ public OutlierResult run(Relation<? extends NumberVector<?>> relation) {
+ WritableDoubleDataStore scores = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT);
+ DoubleMinMax minmax = new DoubleMinMax();
+ Mean m = new Mean();
+ for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
+ m.reset();
+ NumberVector<?> nv = relation.get(iditer);
+ for (int i = 0; i < nv.getDimensionality(); i++) {
+ m.put(nv.doubleValue(i + 1));
+ }
+ final double score = m.getMean();
+ scores.putDouble(iditer, score);
+ minmax.put(score);
+ }
+ Relation<Double> scoreres = new MaterializedRelation<Double>("Trivial mean score", "mean-outlier", TypeUtil.DOUBLE, scores, relation.getDBIDs());
+ OutlierScoreMeta meta = new BasicOutlierScoreMeta(minmax.getMin(), minmax.getMax());
+ return new OutlierResult(meta, scoreres);
+ }
+
+ @Override
+ protected Logging getLogger() {
+ return logger;
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/TrivialGeneratedOutlier.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/TrivialGeneratedOutlier.java
index e4c3861f..285b00df 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/TrivialGeneratedOutlier.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/TrivialGeneratedOutlier.java
@@ -1,9 +1,10 @@
package de.lmu.ifi.dbs.elki.algorithm.outlier.trivial;
+
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -48,8 +49,11 @@ import de.lmu.ifi.dbs.elki.math.statistics.distribution.NormalDistribution;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierScoreMeta;
import de.lmu.ifi.dbs.elki.result.outlier.ProbabilisticOutlierScore;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.LessEqualConstraint;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleParameter;
@@ -68,11 +72,6 @@ public class TrivialGeneratedOutlier extends AbstractAlgorithm<OutlierResult> im
private static final Logging LOG = Logging.getLogger(TrivialGeneratedOutlier.class);
/**
- * Expected share of outliers
- */
- public static final OptionID EXPECT_ID = new OptionID("modeloutlier.expect", "Expected amount of outliers, for making the scores more intuitive.");
-
- /**
* Expected share of outliers.
*/
double expect = 0.01;
@@ -96,19 +95,18 @@ public class TrivialGeneratedOutlier extends AbstractAlgorithm<OutlierResult> im
@Override
public TypeInformation[] getInputTypeRestriction() {
- return TypeUtil.array(TypeUtil.NUMBER_VECTOR_FIELD, new SimpleTypeInformation<Model>(Model.class), TypeUtil.GUESSED_LABEL);
+ return TypeUtil.array(TypeUtil.NUMBER_VECTOR_FIELD, new SimpleTypeInformation<>(Model.class), TypeUtil.GUESSED_LABEL);
}
@Override
public OutlierResult run(Database database) {
Relation<NumberVector<?>> vecs = database.getRelation(TypeUtil.NUMBER_VECTOR_FIELD);
- Relation<Model> models = database.getRelation(new SimpleTypeInformation<Model>(Model.class));
+ Relation<Model> models = database.getRelation(new SimpleTypeInformation<>(Model.class));
// Prefer a true class label
try {
Relation<?> relation = database.getRelation(TypeUtil.CLASSLABEL);
return run(models, vecs, relation);
- }
- catch(NoSupportedDataTypeException e) {
+ } catch (NoSupportedDataTypeException e) {
// Otherwise, try any labellike.
return run(models, vecs, database.getRelation(TypeUtil.GUESSED_LABEL));
}
@@ -125,54 +123,62 @@ public class TrivialGeneratedOutlier extends AbstractAlgorithm<OutlierResult> im
public OutlierResult run(Relation<Model> models, Relation<NumberVector<?>> vecs, Relation<?> labels) {
WritableDoubleDataStore scores = DataStoreUtil.makeDoubleStorage(models.getDBIDs(), DataStoreFactory.HINT_HOT);
- // Adjustment constant
- final double minscore = expect / (expect + 1);
-
- HashSet<GeneratorSingleCluster> generators = new HashSet<GeneratorSingleCluster>();
- for(DBIDIter iditer = models.iterDBIDs(); iditer.valid(); iditer.advance()) {
+ HashSet<GeneratorSingleCluster> generators = new HashSet<>();
+ for (DBIDIter iditer = models.iterDBIDs(); iditer.valid(); iditer.advance()) {
Model model = models.get(iditer);
- if(model instanceof GeneratorSingleCluster) {
+ if (model instanceof GeneratorSingleCluster) {
generators.add((GeneratorSingleCluster) model);
}
}
- if(generators.size() == 0) {
+ if (generators.size() == 0) {
LOG.warning("No generator models found for dataset - all points will be considered outliers.");
}
+ for (GeneratorSingleCluster gen : generators) {
+ for (int i = 0; i < gen.getDim(); i++) {
+ Distribution dist = gen.getDistribution(i);
+ if (!(dist instanceof NormalDistribution)) {
+ throw new AbortException("TrivialGeneratedOutlier currently only supports normal distributions, got: " + dist);
+ }
+ }
+ }
- for(DBIDIter iditer = models.iterDBIDs(); iditer.valid(); iditer.advance()) {
- double score = 0.0;
+ for (DBIDIter iditer = models.iterDBIDs(); iditer.valid(); iditer.advance()) {
+ double score = 1.;
// Convert to a math vector
Vector v = vecs.get(iditer).getColumnVector();
- for(GeneratorSingleCluster gen : generators) {
+ for (GeneratorSingleCluster gen : generators) {
Vector tv = v;
// Transform backwards
- if(gen.getTransformation() != null) {
+ if (gen.getTransformation() != null) {
tv = gen.getTransformation().applyInverse(v);
}
final int dim = tv.getDimensionality();
double lensq = 0.0;
int norm = 0;
- for(int i = 0; i < dim; i++) {
+ for (int i = 0; i < dim; i++) {
Distribution dist = gen.getDistribution(i);
- if(dist instanceof NormalDistribution) {
+ if (dist instanceof NormalDistribution) {
NormalDistribution d = (NormalDistribution) dist;
double delta = (tv.get(i) - d.getMean()) / d.getStddev();
lensq += delta * delta;
norm += 1;
+ } else {
+ throw new AbortException("TrivialGeneratedOutlier currently only supports normal distributions, got: " + dist);
}
}
- if(norm > 0) {
+ if (norm > 0.) {
// The squared distances are ChiSquared distributed
- score = Math.max(score, 1 - ChiSquaredDistribution.cdf(lensq, norm));
+ score = Math.min(score, ChiSquaredDistribution.cdf(lensq, norm));
+ } else {
+ score = 0.;
}
}
- // score inversion.
- score = expect / (expect + score);
- // adjust to 0 to 1 range:
- score = (score - minscore) / (1 - minscore);
+ if (expect < 1) {
+ score = expect * score / (1 - score + expect);
+ }
scores.putDouble(iditer, score);
}
- Relation<Double> scoreres = new MaterializedRelation<Double>("Model outlier scores", "model-outlier", TypeUtil.DOUBLE, scores, models.getDBIDs());
+ Relation<Double> scoreres = new MaterializedRelation<>("Model outlier scores", "model-outlier", TypeUtil.DOUBLE, scores, models.getDBIDs());
OutlierScoreMeta meta = new ProbabilisticOutlierScore(0., 1.);
return new OutlierResult(meta, scoreres);
}
@@ -193,13 +199,20 @@ public class TrivialGeneratedOutlier extends AbstractAlgorithm<OutlierResult> im
/**
* Expected share of outliers
*/
+ public static final OptionID EXPECT_ID = new OptionID("modeloutlier.expect", "Expected amount of outliers, for making the scores more intuitive. When the value is 1, the CDF will be given instead.");
+
+ /**
+ * Expected share of outliers
+ */
double expect;
-
+
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
DoubleParameter expectP = new DoubleParameter(EXPECT_ID, 0.01);
- if(config.grab(expectP)) {
+ expectP.addConstraint(new GreaterConstraint(0.0));
+ expectP.addConstraint(new LessEqualConstraint(1.0));
+ if (config.grab(expectP)) {
expect = expectP.getValue();
}
}
@@ -209,4 +222,4 @@ public class TrivialGeneratedOutlier extends AbstractAlgorithm<OutlierResult> im
return new TrivialGeneratedOutlier(expect);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/TrivialNoOutlier.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/TrivialNoOutlier.java
index 695ff112..ff3d0296 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/TrivialNoOutlier.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/TrivialNoOutlier.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier.trivial;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -73,7 +73,7 @@ public class TrivialNoOutlier extends AbstractAlgorithm<OutlierResult> implement
for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
scores.putDouble(iditer, 0.0);
}
- Relation<Double> scoreres = new MaterializedRelation<Double>("Trivial no-outlier score", "no-outlier", TypeUtil.DOUBLE, scores, relation.getDBIDs());
+ Relation<Double> scoreres = new MaterializedRelation<>("Trivial no-outlier score", "no-outlier", TypeUtil.DOUBLE, scores, relation.getDBIDs());
OutlierScoreMeta meta = new ProbabilisticOutlierScore();
return new OutlierResult(meta, scoreres);
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/package-info.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/package-info.java
index d49d3565..c927cae4 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/package-info.java
@@ -7,7 +7,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/package-info.java b/src/de/lmu/ifi/dbs/elki/algorithm/package-info.java
index 44eb2aba..ba8a7b56 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/package-info.java
@@ -13,7 +13,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/statistics/AddSingleScale.java b/src/de/lmu/ifi/dbs/elki/algorithm/statistics/AddSingleScale.java
index 159fb691..cbae17ca 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/statistics/AddSingleScale.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/statistics/AddSingleScale.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.statistics;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/statistics/AveragePrecisionAtK.java b/src/de/lmu/ifi/dbs/elki/algorithm/statistics/AveragePrecisionAtK.java
index e8165afc..1b87a015 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/statistics/AveragePrecisionAtK.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/statistics/AveragePrecisionAtK.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.statistics;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,6 +27,7 @@ import java.util.ArrayList;
import java.util.Collection;
import de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm;
+import de.lmu.ifi.dbs.elki.data.ClassLabel;
import de.lmu.ifi.dbs.elki.data.DoubleVector;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
@@ -35,23 +36,23 @@ import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
import de.lmu.ifi.dbs.elki.math.MeanVariance;
import de.lmu.ifi.dbs.elki.result.CollectionResult;
-import de.lmu.ifi.dbs.elki.result.HistogramResult;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterEqualConstraint;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.LessEqualConstraint;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleParameter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Flag;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.LongParameter;
@@ -60,6 +61,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.LongParameter;
* at k, when ranking the objects by distance.
*
* @author Erich Schubert
+ *
* @param <V> Vector type
* @param <D> Distance type
*/
@@ -73,38 +75,51 @@ public class AveragePrecisionAtK<V extends Object, D extends NumberDistance<D, ?
* The parameter k - the number of neighbors to retrieve.
*/
private int k;
-
+
/**
* Relative number of object to use in sampling.
*/
private double sampling = 1.0;
-
+
/**
* Random sampling seed.
*/
private Long seed = null;
/**
+ * Include query object in evaluation.
+ */
+ private boolean includeSelf;
+
+ /**
* Constructor.
*
* @param distanceFunction Distance function
* @param k K parameter
* @param sampling Sampling rate
* @param seed Random sampling seed (may be null)
+ * @param includeSelf Include query object in evaluation
*/
- public AveragePrecisionAtK(DistanceFunction<? super V, D> distanceFunction, int k, double sampling, Long seed) {
+ public AveragePrecisionAtK(DistanceFunction<? super V, D> distanceFunction, int k, double sampling, Long seed, boolean includeSelf) {
super(distanceFunction);
this.k = k;
this.sampling = sampling;
this.seed = seed;
+ this.includeSelf = includeSelf;
}
- @Override
- public HistogramResult<DoubleVector> run(Database database) {
- final Relation<V> relation = database.getRelation(getInputTypeRestriction()[0]);
- final Relation<Object> lrelation = database.getRelation(getInputTypeRestriction()[1]);
+ /**
+ * Run the algorithm
+ *
+ * @param database Database to run on (for kNN queries)
+ * @param relation Relation for distance computations
+ * @param lrelation Relation for class label comparison
+ * @return Vectors containing mean and standard deviation.
+ */
+ public CollectionResult<DoubleVector> run(Database database, Relation<V> relation, Relation<ClassLabel> lrelation) {
final DistanceQuery<V, D> distQuery = database.getDistanceQuery(relation, getDistanceFunction());
- final KNNQuery<V, D> knnQuery = database.getKNNQuery(distQuery, k);
+ final int qk = k + (includeSelf ? 0 : 1);
+ final KNNQuery<V, D> knnQuery = database.getKNNQuery(distQuery, qk);
MeanVariance[] mvs = MeanVariance.newArray(k);
@@ -115,53 +130,56 @@ public class AveragePrecisionAtK<V extends Object, D extends NumberDistance<D, ?
} else {
ids = relation.getDBIDs();
}
-
- if(LOG.isVerbose()) {
+
+ if (LOG.isVerbose()) {
LOG.verbose("Processing points...");
}
FiniteProgress objloop = LOG.isVerbose() ? new FiniteProgress("Computing nearest neighbors", ids.size(), LOG) : null;
// sort neighbors
- for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
- KNNResult<D> knn = knnQuery.getKNNForDBID(iter, k);
+ for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
+ KNNList<D> knn = knnQuery.getKNNForDBID(iter, qk);
Object label = lrelation.get(iter);
int positive = 0, i = 0;
- for (DBIDIter ri = knn.iter(); i < k && ri.valid(); ri.advance(), i++) {
+ for (DBIDIter ri = knn.iter(); i < k && ri.valid(); ri.advance()) {
+ if (!includeSelf && DBIDUtil.equal(iter, ri)) {
+ continue;
+ }
Object olabel = lrelation.get(ri);
- if(label == null) {
- if(olabel == null) {
+ if (label == null) {
+ if (olabel == null) {
positive += 1;
}
- }
- else {
- if(label.equals(olabel)) {
+ } else {
+ if (label.equals(olabel)) {
positive += 1;
}
}
final double precision = positive / (double) (i + 1);
mvs[i].put(precision);
+ i++;
}
- if(objloop != null) {
+ if (objloop != null) {
objloop.incrementProcessed(LOG);
}
}
- if(objloop != null) {
+ if (objloop != null) {
objloop.ensureCompleted(LOG);
}
// Collections.sort(results);
// Transform Histogram into a Double Vector array.
- Collection<DoubleVector> res = new ArrayList<DoubleVector>(k);
- for(int i = 0; i < k; i++) {
+ Collection<DoubleVector> res = new ArrayList<>(k);
+ for (int i = 0; i < k; i++) {
DoubleVector row = new DoubleVector(new double[] { mvs[i].getMean(), mvs[i].getSampleStddev() });
res.add(row);
}
- return new HistogramResult<DoubleVector>("Average Precision", "average-precision", res);
+ return new CollectionResult<>("Average Precision", "average-precision", res);
}
@Override
public TypeInformation[] getInputTypeRestriction() {
- return TypeUtil.array(getDistanceFunction().getInputTypeRestriction(), TypeUtil.GUESSED_LABEL);
+ return TypeUtil.array(getDistanceFunction().getInputTypeRestriction(), TypeUtil.CLASSLABEL);
}
@Override
@@ -193,26 +211,36 @@ public class AveragePrecisionAtK<V extends Object, D extends NumberDistance<D, ?
public static final OptionID SEED_ID = new OptionID("avep.sampling-seed", "Random seed for deterministic sampling.");
/**
+ * Parameter to include the query object.
+ */
+ public static final OptionID INCLUDESELF_ID = new OptionID("avep.includeself", "Include the query object in the evaluation.");
+
+ /**
* Neighborhood size.
*/
protected int k = 20;
-
+
/**
* Relative amount of data to sample.
*/
protected double sampling = 1.0;
-
+
/**
* Random sampling seed.
*/
protected Long seed = null;
+ /**
+ * Include query object in evaluation.
+ */
+ protected boolean includeSelf;
+
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
final IntParameter kP = new IntParameter(K_ID);
kP.addConstraint(new GreaterEqualConstraint(2));
- if(config.grab(kP)) {
+ if (config.grab(kP)) {
k = kP.getValue();
}
final DoubleParameter samplingP = new DoubleParameter(SAMPLING_ID);
@@ -227,11 +255,15 @@ public class AveragePrecisionAtK<V extends Object, D extends NumberDistance<D, ?
if (config.grab(rndP)) {
seed = rndP.getValue();
}
+ final Flag includeP = new Flag(INCLUDESELF_ID);
+ if (config.grab(includeP)) {
+ includeSelf = includeP.isTrue();
+ }
}
@Override
protected AveragePrecisionAtK<V, D> makeInstance() {
- return new AveragePrecisionAtK<V, D>(distanceFunction, k, sampling, seed);
+ return new AveragePrecisionAtK<>(distanceFunction, k, sampling, seed, includeSelf);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/statistics/DistanceStatisticsWithClasses.java b/src/de/lmu/ifi/dbs/elki/algorithm/statistics/DistanceStatisticsWithClasses.java
index ebf588b6..3c8e1635 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/statistics/DistanceStatisticsWithClasses.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/statistics/DistanceStatisticsWithClasses.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.statistics;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -284,7 +284,7 @@ public class DistanceStatisticsWithClasses<O, D extends NumberDistance<D, ?>> ex
}
long bnum = inum + onum;
- Collection<DoubleVector> binstat = new ArrayList<DoubleVector>(numbin);
+ Collection<DoubleVector> binstat = new ArrayList<>(numbin);
for (ObjHistogram.Iter<long[]> iter = histogram.iter(); iter.valid(); iter.advance()) {
final long[] value = iter.getValue();
final double icof = (inum == 0) ? 0 : ((double) value[0]) / inum / histogram.getBinsize();
@@ -294,7 +294,7 @@ public class DistanceStatisticsWithClasses<O, D extends NumberDistance<D, ?>> ex
DoubleVector row = new DoubleVector(new double[] { iter.getCenter(), icof, icaf, ocof, ocaf });
binstat.add(row);
}
- HistogramResult<DoubleVector> result = new HistogramResult<DoubleVector>("Distance Histogram", "distance-histogram", binstat);
+ HistogramResult<DoubleVector> result = new HistogramResult<>("Distance Histogram", "distance-histogram", binstat);
result.addHeader("Absolute minimum distance (abs): " + gminmax.getMin());
result.addHeader("Absolute maximum distance (abs): " + gminmax.getMax());
@@ -319,8 +319,8 @@ public class DistanceStatisticsWithClasses<O, D extends NumberDistance<D, ?>> ex
Random rnd = new Random();
// estimate minimum and maximum.
int k = (int) Math.max(25, Math.pow(relation.size(), 0.2));
- TreeSet<DoubleDBIDPair> minhotset = new TreeSet<DoubleDBIDPair>();
- TreeSet<DoubleDBIDPair> maxhotset = new TreeSet<DoubleDBIDPair>(Collections.reverseOrder());
+ TreeSet<DoubleDBIDPair> minhotset = new TreeSet<>();
+ TreeSet<DoubleDBIDPair> maxhotset = new TreeSet<>(Collections.reverseOrder());
int randomsize = (int) Math.max(25, Math.pow(relation.size(), 0.2));
double rprob = ((double) randomsize) / size;
@@ -336,7 +336,7 @@ public class DistanceStatisticsWithClasses<O, D extends NumberDistance<D, ?>> ex
maxhotset.add(DBIDUtil.newPair(Double.MIN_VALUE, firstid));
for (; iter.valid(); iter.advance()) {
// generate candidates for min distance.
- ArrayList<DoubleDBIDPair> np = new ArrayList<DoubleDBIDPair>(k * 2 + randomsize * 2);
+ ArrayList<DoubleDBIDPair> np = new ArrayList<>(k * 2 + randomsize * 2);
for (DoubleDBIDPair pair : minhotset) {
// skip the object itself
if (DBIDUtil.equal(iter, pair)) {
@@ -355,7 +355,7 @@ public class DistanceStatisticsWithClasses<O, D extends NumberDistance<D, ?>> ex
shrinkHeap(minhotset, k);
// generate candidates for max distance.
- ArrayList<DoubleDBIDPair> np2 = new ArrayList<DoubleDBIDPair>(k * 2 + randomsize * 2);
+ ArrayList<DoubleDBIDPair> np2 = new ArrayList<>(k * 2 + randomsize * 2);
for (DoubleDBIDPair pair : minhotset) {
// skip the object itself
if (DBIDUtil.equal(iter, pair)) {
@@ -479,7 +479,7 @@ public class DistanceStatisticsWithClasses<O, D extends NumberDistance<D, ?>> ex
sampling = samplingF.getValue();
}
- ArrayList<Parameter<?>> exclusive = new ArrayList<Parameter<?>>();
+ ArrayList<Parameter<?>> exclusive = new ArrayList<>();
exclusive.add(exactF);
exclusive.add(samplingF);
config.checkConstraint(new OnlyOneIsAllowedToBeSetGlobalConstraint(exclusive));
@@ -487,7 +487,7 @@ public class DistanceStatisticsWithClasses<O, D extends NumberDistance<D, ?>> ex
@Override
protected DistanceStatisticsWithClasses<O, D> makeInstance() {
- return new DistanceStatisticsWithClasses<O, D>(distanceFunction, numbin, exact, sampling);
+ return new DistanceStatisticsWithClasses<>(distanceFunction, numbin, exact, sampling);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/statistics/EvaluateRankingQuality.java b/src/de/lmu/ifi/dbs/elki/algorithm/statistics/EvaluateRankingQuality.java
index 1643d378..76e5ef66 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/statistics/EvaluateRankingQuality.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/statistics/EvaluateRankingQuality.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.statistics;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -41,22 +41,24 @@ import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.evaluation.roc.ROC;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
import de.lmu.ifi.dbs.elki.math.MathUtil;
+import de.lmu.ifi.dbs.elki.math.MeanVariance;
import de.lmu.ifi.dbs.elki.math.linearalgebra.CovarianceMatrix;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Matrix;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
import de.lmu.ifi.dbs.elki.result.CollectionResult;
import de.lmu.ifi.dbs.elki.result.HistogramResult;
import de.lmu.ifi.dbs.elki.utilities.datastructures.histogram.MeanVarianceStaticHistogram;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.histogram.ObjHistogram;
import de.lmu.ifi.dbs.elki.utilities.documentation.Description;
import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
@@ -126,8 +128,8 @@ public class EvaluateRankingQuality<V extends NumberVector<?>, D extends NumberD
Collection<Cluster<Model>> split = (new ByLabelOrAllInOneClustering()).run(database).getAllClusters();
// Compute cluster averages and covariance matrix
- HashMap<Cluster<?>, Vector> averages = new HashMap<Cluster<?>, Vector>(split.size());
- HashMap<Cluster<?>, Matrix> covmats = new HashMap<Cluster<?>, Matrix>(split.size());
+ HashMap<Cluster<?>, Vector> averages = new HashMap<>(split.size());
+ HashMap<Cluster<?>, Matrix> covmats = new HashMap<>(split.size());
for (Cluster<?> clus : split) {
CovarianceMatrix covmat = CovarianceMatrix.make(relation, clus.getIDs());
averages.put(clus, covmat.getMeanVector());
@@ -143,7 +145,7 @@ public class EvaluateRankingQuality<V extends NumberVector<?>, D extends NumberD
// sort neighbors
for (Cluster<?> clus : split) {
- ArrayList<DoubleDBIDPair> cmem = new ArrayList<DoubleDBIDPair>(clus.size());
+ ArrayList<DoubleDBIDPair> cmem = new ArrayList<>(clus.size());
Vector av = averages.get(clus);
Matrix covm = covmats.get(clus);
@@ -154,7 +156,7 @@ public class EvaluateRankingQuality<V extends NumberVector<?>, D extends NumberD
Collections.sort(cmem);
for (int ind = 0; ind < cmem.size(); ind++) {
- KNNResult<D> knn = knnQuery.getKNNForDBID(cmem.get(ind), relation.size());
+ KNNList<D> knn = knnQuery.getKNNForDBID(cmem.get(ind), relation.size());
double result = ROC.computeROCAUCDistanceResult(relation.size(), clus, knn);
hist.put(((double) ind) / clus.size(), result);
@@ -170,12 +172,12 @@ public class EvaluateRankingQuality<V extends NumberVector<?>, D extends NumberD
// Collections.sort(results);
// Transform Histogram into a Double Vector array.
- Collection<DoubleVector> res = new ArrayList<DoubleVector>(relation.size());
- for (MeanVarianceStaticHistogram.Iter iter = hist.iter(); iter.valid(); iter.advance()) {
+ Collection<DoubleVector> res = new ArrayList<>(relation.size());
+ for (ObjHistogram.Iter<MeanVariance> iter = hist.iter(); iter.valid(); iter.advance()) {
DoubleVector row = new DoubleVector(new double[] { iter.getCenter(), iter.getValue().getCount(), iter.getValue().getMean(), iter.getValue().getSampleVariance() });
res.add(row);
}
- return new HistogramResult<DoubleVector>("Ranking Quality Histogram", "ranking-histogram", res);
+ return new HistogramResult<>("Ranking Quality Histogram", "ranking-histogram", res);
}
@Override
@@ -213,7 +215,7 @@ public class EvaluateRankingQuality<V extends NumberVector<?>, D extends NumberD
@Override
protected EvaluateRankingQuality<V, D> makeInstance() {
- return new EvaluateRankingQuality<V, D>(distanceFunction, numbins);
+ return new EvaluateRankingQuality<>(distanceFunction, numbins);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/statistics/RankingQualityHistogram.java b/src/de/lmu/ifi/dbs/elki/algorithm/statistics/RankingQualityHistogram.java
index 6d8167a5..58018029 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/statistics/RankingQualityHistogram.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/statistics/RankingQualityHistogram.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.statistics;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -35,11 +35,11 @@ import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.evaluation.roc.ROC;
import de.lmu.ifi.dbs.elki.logging.Logging;
@@ -126,7 +126,7 @@ public class RankingQualityHistogram<O, D extends NumberDistance<D, ?>> extends
// sort neighbors
for (Cluster<?> clus : split) {
for (DBIDIter iter = clus.getIDs().iter(); iter.valid(); iter.advance()) {
- KNNResult<D> knn = knnQuery.getKNNForDBID(iter, relation.size());
+ KNNList<D> knn = knnQuery.getKNNForDBID(iter, relation.size());
double result = ROC.computeROCAUCDistanceResult(relation.size(), clus, knn);
mv.put(result);
@@ -142,12 +142,12 @@ public class RankingQualityHistogram<O, D extends NumberDistance<D, ?>> extends
}
// Transform Histogram into a Double Vector array.
- Collection<DoubleVector> res = new ArrayList<DoubleVector>(relation.size());
+ Collection<DoubleVector> res = new ArrayList<>(relation.size());
for (DoubleStaticHistogram.Iter iter = hist.iter(); iter.valid(); iter.advance()) {
DoubleVector row = new DoubleVector(new double[] { iter.getCenter(), iter.getValue() });
res.add(row);
}
- HistogramResult<DoubleVector> result = new HistogramResult<DoubleVector>("Ranking Quality Histogram", "ranking-histogram", res);
+ HistogramResult<DoubleVector> result = new HistogramResult<>("Ranking Quality Histogram", "ranking-histogram", res);
result.addHeader("Mean: " + mv.getMean() + " Variance: " + mv.getSampleVariance());
return result;
}
@@ -187,7 +187,7 @@ public class RankingQualityHistogram<O, D extends NumberDistance<D, ?>> extends
@Override
protected RankingQualityHistogram<O, D> makeInstance() {
- return new RankingQualityHistogram<O, D>(distanceFunction, numbins);
+ return new RankingQualityHistogram<>(distanceFunction, numbins);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/statistics/package-info.java b/src/de/lmu/ifi/dbs/elki/algorithm/statistics/package-info.java
index e706d586..8e566101 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/statistics/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/statistics/package-info.java
@@ -8,7 +8,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/application/AbstractApplication.java b/src/de/lmu/ifi/dbs/elki/application/AbstractApplication.java
index c0c166bc..db97b4bb 100644
--- a/src/de/lmu/ifi/dbs/elki/application/AbstractApplication.java
+++ b/src/de/lmu/ifi/dbs/elki/application/AbstractApplication.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.application;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,6 +27,7 @@ import java.io.File;
import java.util.Collection;
import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.Logging.Level;
import de.lmu.ifi.dbs.elki.logging.LoggingConfiguration;
import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
@@ -60,6 +61,7 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
* @author Erich Schubert
*
* @apiviz.uses LoggingConfiguration oneway
+ * @apiviz.excludeSubtypes
*/
public abstract class AbstractApplication implements Parameterizable {
/**
@@ -93,10 +95,11 @@ public abstract class AbstractApplication implements Parameterizable {
* @param args the arguments to run this application with
*/
public static void runCLIApplication(Class<?> cls, String[] args) {
- final Flag helpF = new Flag(OptionID.HELP);
- final Flag helpLongF = new Flag(OptionID.HELP_LONG);
- final ClassParameter<Object> descriptionP = new ClassParameter<Object>(OptionID.DESCRIPTION, Object.class, true);
- final StringParameter debugP = new StringParameter(OptionID.DEBUG);
+ final Flag helpF = new Flag(Parameterizer.HELP_ID);
+ final Flag helpLongF = new Flag(Parameterizer.HELP_LONG_ID);
+ final ClassParameter<Object> descriptionP = new ClassParameter<>(Parameterizer.DESCRIPTION_ID, Object.class, true);
+ final StringParameter debugP = new StringParameter(Parameterizer.DEBUG_ID);
+ final Flag verboseF = new Flag(Parameterizer.VERBOSE_ID);
debugP.setOptional(true);
SerializedParameterization params = new SerializedParameterization(args);
@@ -124,21 +127,31 @@ public abstract class AbstractApplication implements Parameterizable {
}
try {
TrackParameters config = new TrackParameters(params);
+ if (config.grab(verboseF) && verboseF.isTrue()) {
+ // Extra verbosity by repeating the flag:
+ final Flag verbose2F = new Flag(Parameterizer.VERBOSE_ID);
+ if (config.grab(verbose2F) && verbose2F.isTrue()) {
+ LoggingConfiguration.setVerbose(Level.VERYVERBOSE);
+ } else {
+ LoggingConfiguration.setVerbose(Level.VERBOSE);
+ }
+ }
AbstractApplication task = ClassGenericsUtil.tryInstantiate(AbstractApplication.class, cls, config);
if ((helpF.isDefined() && helpF.getValue()) || (helpLongF.isDefined() && helpLongF.getValue())) {
- LoggingConfiguration.setVerbose(true);
+ LoggingConfiguration.setVerbose(Level.VERBOSE);
LOG.verbose(usage(config.getAllParameters()));
} else {
params.logUnusedParameters();
if (params.getErrors().size() > 0) {
- LoggingConfiguration.setVerbose(true);
+ LoggingConfiguration.setVerbose(Level.VERBOSE);
LOG.verbose("The following configuration errors prevented execution:\n");
for (ParameterException e : params.getErrors()) {
LOG.verbose(e.getMessage());
}
LOG.verbose("\n");
LOG.verbose("Stopping execution because of configuration errors.");
+ System.exit(1);
} else {
task.run();
}
@@ -174,7 +187,7 @@ public abstract class AbstractApplication implements Parameterizable {
protected static void printErrorMessage(Exception e) {
if (e instanceof AbortException) {
// ensure we actually show the message:
- LoggingConfiguration.setVerbose(true);
+ LoggingConfiguration.setVerbose(Level.VERBOSE);
LOG.verbose(e.getMessage());
} else if (e instanceof UnspecifiedParameterException) {
LOG.error(e.getMessage());
@@ -190,7 +203,7 @@ public abstract class AbstractApplication implements Parameterizable {
*/
private static void printDescription(Class<?> descriptionClass) {
if (descriptionClass != null) {
- LoggingConfiguration.setVerbose(true);
+ LoggingConfiguration.setVerbose(Level.VERBOSE);
LOG.verbose(OptionUtil.describeParameterizable(new StringBuilder(), descriptionClass, FormatUtil.getConsoleWidth(), " ").toString());
}
}
@@ -227,25 +240,45 @@ public abstract class AbstractApplication implements Parameterizable {
*/
public static final OptionID INPUT_ID = new OptionID("app.in", "");
- @Override
- protected void makeOptions(Parameterization config) {
- super.makeOptions(config);
- configVerbose(config);
- // Note: we do not run the other methods by default.
- // Only verbose will always be present!
- }
+ /**
+ * Flag to obtain help-message.
+ * <p>
+ * Key: {@code -h}
+ * </p>
+ */
+ public static final OptionID HELP_ID = new OptionID("h", "Request a help-message, either for the main-routine or for any specified algorithm. " + "Causes immediate stop of the program.");
/**
- * Get the verbose parameter.
- *
- * @param config Parameterization
+ * Flag to obtain help-message.
+ * <p>
+ * Key: {@code -help}
+ * </p>
*/
- protected void configVerbose(Parameterization config) {
- final Flag verboseF = new Flag(OptionID.VERBOSE_FLAG);
- if (config.grab(verboseF)) {
- LoggingConfiguration.setVerbose(verboseF.isTrue());
- }
- }
+ public static final OptionID HELP_LONG_ID = new OptionID("help", "Request a help-message, either for the main-routine or for any specified algorithm. " + "Causes immediate stop of the program.");
+
+ /**
+ * Optional Parameter to specify a class to obtain a description for.
+ * <p>
+ * Key: {@code -description}
+ * </p>
+ */
+ public static final OptionID DESCRIPTION_ID = new OptionID("description", "Class to obtain a description of. " + "Causes immediate stop of the program.");
+
+ /**
+ * Optional Parameter to specify a class to enable debugging for.
+ * <p>
+ * Key: {@code -enableDebug}
+ * </p>
+ */
+ public static final OptionID DEBUG_ID = new OptionID("enableDebug", "Parameter to enable debugging for particular packages.");
+
+ /**
+ * Flag to allow verbose messages while running the application.
+ * <p>
+ * Key: {@code -verbose}
+ * </p>
+ */
+ public static final OptionID VERBOSE_ID = new OptionID("verbose", "Enable verbose messages.");
/**
* Get the output file parameter.
diff --git a/src/de/lmu/ifi/dbs/elki/application/ComputeSingleColorHistogram.java b/src/de/lmu/ifi/dbs/elki/application/ComputeSingleColorHistogram.java
index 4ef544ab..b2c8afff 100644
--- a/src/de/lmu/ifi/dbs/elki/application/ComputeSingleColorHistogram.java
+++ b/src/de/lmu/ifi/dbs/elki/application/ComputeSingleColorHistogram.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.application;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -135,7 +135,7 @@ public class ComputeSingleColorHistogram extends AbstractApplication {
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- final ObjectParameter<ComputeColorHistogram> colorhistP = new ObjectParameter<ComputeColorHistogram>(COLORHIST_ID, ComputeColorHistogram.class, ComputeNaiveRGBColorHistogram.class);
+ final ObjectParameter<ComputeColorHistogram> colorhistP = new ObjectParameter<>(COLORHIST_ID, ComputeColorHistogram.class, ComputeNaiveRGBColorHistogram.class);
if(config.grab(colorhistP)) {
histogrammaker = colorhistP.instantiateClass(config);
}
diff --git a/src/de/lmu/ifi/dbs/elki/application/ConvertToBundleApplication.java b/src/de/lmu/ifi/dbs/elki/application/ConvertToBundleApplication.java
index 451fc572..99320838 100644
--- a/src/de/lmu/ifi/dbs/elki/application/ConvertToBundleApplication.java
+++ b/src/de/lmu/ifi/dbs/elki/application/ConvertToBundleApplication.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.application;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,6 +28,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
+import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.datasource.DatabaseConnection;
import de.lmu.ifi.dbs.elki.datasource.FileBasedDatabaseConnection;
import de.lmu.ifi.dbs.elki.datasource.bundle.BundleWriter;
@@ -35,7 +36,6 @@ import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle;
import de.lmu.ifi.dbs.elki.datasource.bundle.StreamFromBundle;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.utilities.exceptions.UnableToComplyException;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
@@ -115,7 +115,7 @@ public class ConvertToBundleApplication extends AbstractApplication {
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- ObjectParameter<DatabaseConnection> inputP = new ObjectParameter<DatabaseConnection>(OptionID.DATABASE_CONNECTION, DatabaseConnection.class, FileBasedDatabaseConnection.class);
+ ObjectParameter<DatabaseConnection> inputP = new ObjectParameter<>(Database.DATABASE_CONNECTION_ID, DatabaseConnection.class, FileBasedDatabaseConnection.class);
if (config.grab(inputP)) {
input = inputP.instantiateClass(config);
}
diff --git a/src/de/lmu/ifi/dbs/elki/application/ELKILauncher.java b/src/de/lmu/ifi/dbs/elki/application/ELKILauncher.java
index 2cc84b2b..b8d000a3 100644
--- a/src/de/lmu/ifi/dbs/elki/application/ELKILauncher.java
+++ b/src/de/lmu/ifi/dbs/elki/application/ELKILauncher.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.application;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,6 +28,8 @@ import java.util.Arrays;
import de.lmu.ifi.dbs.elki.gui.minigui.MiniGUI;
import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
+import de.lmu.ifi.dbs.elki.utilities.InspectionUtil;
/**
* Class to launch ELKI.
@@ -48,19 +50,14 @@ public class ELKILauncher {
public static void main(String[] args) {
if (args.length > 0 && args[0].charAt(0) != '-') {
try {
- Class<?> cls = Class.forName(args[0]);
+ Class<?> cls = findMainClass(args[0]);
Method m = cls.getMethod("main", String[].class);
Object a = Arrays.copyOfRange(args, 1, args.length);
- m.invoke(null, a);
- return;
- } catch (Exception e) {
- // Ignore
- }
- try {
- Class<?> cls = Class.forName(AbstractApplication.class.getPackage().getName() + '.' + args[0]);
- Method m = cls.getMethod("main", String[].class);
- Object a = Arrays.copyOfRange(args, 1, args.length);
- m.invoke(null, a);
+ try {
+ m.invoke(null, a);
+ } catch (Exception e) {
+ LoggingUtil.exception(e);
+ }
return;
} catch (Exception e) {
// Ignore
@@ -73,4 +70,35 @@ public class ELKILauncher {
LoggingUtil.exception(e);
}
}
+
+ /**
+ * Find a class for the given name.
+ *
+ * @param name Class name
+ * @return Class
+ * @throws ClassNotFoundException
+ */
+ private static Class<?> findMainClass(String name) throws ClassNotFoundException {
+ try {
+ return Class.forName(name);
+ } catch (ClassNotFoundException e) {
+ // pass
+ }
+ try {
+ return Class.forName(AbstractApplication.class.getPackage().getName() + '.' + name);
+ } catch (ClassNotFoundException e) {
+ // pass
+ }
+ for (Class<?> c : InspectionUtil.cachedFindAllImplementations(AbstractApplication.class)) {
+ if (c.isAnnotationPresent(Alias.class)) {
+ Alias aliases = c.getAnnotation(Alias.class);
+ for (String alias : aliases.value()) {
+ if (alias.equalsIgnoreCase(name)) {
+ return c;
+ }
+ }
+ }
+ }
+ throw new ClassNotFoundException(name);
+ }
}
diff --git a/src/de/lmu/ifi/dbs/elki/application/GeneratorXMLSpec.java b/src/de/lmu/ifi/dbs/elki/application/GeneratorXMLSpec.java
index ecb7ed4c..50f97d87 100644
--- a/src/de/lmu/ifi/dbs/elki/application/GeneratorXMLSpec.java
+++ b/src/de/lmu/ifi/dbs/elki/application/GeneratorXMLSpec.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.application;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -44,7 +44,7 @@ import de.lmu.ifi.dbs.elki.datasource.GeneratorXMLDatabaseConnection;
import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
-import de.lmu.ifi.dbs.elki.math.statistics.distribution.DistributionWithRandom;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.Distribution;
import de.lmu.ifi.dbs.elki.utilities.FormatUtil;
import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
import de.lmu.ifi.dbs.elki.utilities.exceptions.UnableToComplyException;
@@ -143,8 +143,8 @@ public class GeneratorXMLSpec extends AbstractApplication {
if(modelcol < 0) {
throw new AbortException("No model column found in bundle.");
}
- ArrayList<Model> models = new ArrayList<Model>();
- Map<Model, TIntList> modelMap = new HashMap<Model, TIntList>();
+ ArrayList<Model> models = new ArrayList<>();
+ Map<Model, TIntList> modelMap = new HashMap<>();
{ // Build a map from model to the actual objects
for(int i = 0; i < data.dataLength(); i++) {
Model model = (Model) data.data(i, modelcol);
@@ -185,7 +185,7 @@ public class GeneratorXMLSpec extends AbstractApplication {
outStream.write("## Density correction factor: " + cursclus.getDensityCorrection() + LINE_SEPARATOR);
outStream.write("## Generators:" + LINE_SEPARATOR);
for(int i = 0; i < cursclus.getDim(); i++) {
- DistributionWithRandom gen = cursclus.getDistribution(i);
+ Distribution gen = cursclus.getDistribution(i);
outStream.write("## " + gen.toString() + LINE_SEPARATOR);
}
if(cursclus.getTransformation() != null && cursclus.getTransformation().getTransformation() != null) {
diff --git a/src/de/lmu/ifi/dbs/elki/application/KDDCLIApplication.java b/src/de/lmu/ifi/dbs/elki/application/KDDCLIApplication.java
index 5e0e0ef1..7e072989 100644
--- a/src/de/lmu/ifi/dbs/elki/application/KDDCLIApplication.java
+++ b/src/de/lmu/ifi/dbs/elki/application/KDDCLIApplication.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.application;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,20 +25,21 @@ package de.lmu.ifi.dbs.elki.application;
import de.lmu.ifi.dbs.elki.KDDTask;
import de.lmu.ifi.dbs.elki.algorithm.Algorithm;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
import de.lmu.ifi.dbs.elki.workflow.OutputStep;
/**
* Provides a KDDCLIApplication that can be used to perform any algorithm
* implementing {@link Algorithm Algorithm} using any DatabaseConnection
- * implementing
- * {@link de.lmu.ifi.dbs.elki.datasource.DatabaseConnection
+ * implementing {@link de.lmu.ifi.dbs.elki.datasource.DatabaseConnection
* DatabaseConnection}.
*
* @author Arthur Zimek
*
* @apiviz.composedOf KDDTask
*/
+@Alias({ "cli", "kddtask" })
public class KDDCLIApplication extends AbstractApplication {
/**
* The KDD Task to perform.
@@ -94,4 +95,4 @@ public class KDDCLIApplication extends AbstractApplication {
OutputStep.setDefaultHandlerWriter();
runCLIApplication(KDDCLIApplication.class, args);
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/application/cache/CacheDoubleDistanceInOnDiskMatrix.java b/src/de/lmu/ifi/dbs/elki/application/cache/CacheDoubleDistanceInOnDiskMatrix.java
index 07907313..6a28282c 100644
--- a/src/de/lmu/ifi/dbs/elki/application/cache/CacheDoubleDistanceInOnDiskMatrix.java
+++ b/src/de/lmu/ifi/dbs/elki/application/cache/CacheDoubleDistanceInOnDiskMatrix.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.application.cache;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,7 +28,6 @@ import java.io.IOException;
import de.lmu.ifi.dbs.elki.application.AbstractApplication;
import de.lmu.ifi.dbs.elki.database.Database;
-import de.lmu.ifi.dbs.elki.database.StaticArrayDatabase;
import de.lmu.ifi.dbs.elki.database.ids.DBIDFactory;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
@@ -44,10 +43,10 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.FileParameter;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
+import de.lmu.ifi.dbs.elki.workflow.InputStep;
/**
- * Wrapper to convert a traditional text-serialized result into a on-disk matrix
- * for random access.
+ * Precompute an on-disk distance matrix, using double precision.
*
* @author Erich Schubert
*
@@ -64,30 +63,14 @@ public class CacheDoubleDistanceInOnDiskMatrix<O, D extends NumberDistance<D, ?>
private static final Logging LOG = Logging.getLogger(CacheDoubleDistanceInOnDiskMatrix.class);
/**
- * Parameter that specifies the name of the directory to be re-parsed.
- * <p>
- * Key: {@code -loader.diskcache}
- * </p>
- */
- public static final OptionID CACHE_ID = new OptionID("loader.diskcache", "File name of the disk cache to create.");
-
- /**
- * Parameter that specifies the name of the directory to be re-parsed.
- * <p>
- * Key: {@code -loader.distance}
- * </p>
- */
- public static final OptionID DISTANCE_ID = new OptionID("loader.distance", "Distance function to cache.");
-
- /**
* Debug flag, to double-check all write operations.
*/
private static final boolean debugExtraCheckSymmetry = false;
/**
- * Holds the database connection to have the algorithm run with.
+ * Data source to process.
*/
- private Database database;
+ private InputStep input;
/**
* Distance function that is to be cached.
@@ -102,28 +85,28 @@ public class CacheDoubleDistanceInOnDiskMatrix<O, D extends NumberDistance<D, ?>
/**
* Constructor.
*
- * @param database Database
+ * @param input Data source
* @param distance Distance function
* @param out Matrix output file
*/
- public CacheDoubleDistanceInOnDiskMatrix(Database database, DistanceFunction<O, D> distance, File out) {
+ public CacheDoubleDistanceInOnDiskMatrix(InputStep input, DistanceFunction<O, D> distance, File out) {
super();
- this.database = database;
+ this.input = input;
this.distance = distance;
this.out = out;
}
@Override
public void run() {
- database.initialize();
+ Database database = input.getDatabase();
Relation<O> relation = database.getRelation(distance.getInputTypeRestriction());
DistanceQuery<O, D> distanceQuery = database.getDistanceQuery(relation, distance);
int matrixsize = 0;
- for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
+ for (DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
int intid = DBIDUtil.asInteger(iditer);
matrixsize = Math.max(matrixsize, intid + 1);
- if(intid < 0) {
+ if (intid < 0) {
throw new AbortException("OnDiskMatrixCache does not allow negative DBIDs.");
}
}
@@ -131,25 +114,23 @@ public class CacheDoubleDistanceInOnDiskMatrix<O, D extends NumberDistance<D, ?>
OnDiskUpperTriangleMatrix matrix;
try {
matrix = new OnDiskUpperTriangleMatrix(out, DiskCacheBasedDoubleDistanceFunction.DOUBLE_CACHE_MAGIC, 0, 8, matrixsize);
- }
- catch(IOException e) {
+ } catch (IOException e) {
throw new AbortException("Error creating output matrix.", e);
}
- for(DBIDIter id1 = relation.iterDBIDs(); id1.valid(); id1.advance()) {
- for(DBIDIter id2 = relation.iterDBIDs(); id2.valid(); id2.advance()) {
- if(DBIDUtil.asInteger(id2) >= DBIDUtil.asInteger(id1)) {
+ for (DBIDIter id1 = relation.iterDBIDs(); id1.valid(); id1.advance()) {
+ for (DBIDIter id2 = relation.iterDBIDs(); id2.valid(); id2.advance()) {
+ if (DBIDUtil.asInteger(id2) >= DBIDUtil.asInteger(id1)) {
double d = distanceQuery.distance(id1, id2).doubleValue();
- if(debugExtraCheckSymmetry) {
+ if (debugExtraCheckSymmetry) {
double d2 = distanceQuery.distance(id2, id1).doubleValue();
- if(Math.abs(d - d2) > 0.0000001) {
+ if (Math.abs(d - d2) > 0.0000001) {
LOG.warning("Distance function doesn't appear to be symmetric!");
}
}
try {
matrix.getRecordBuffer(DBIDUtil.asInteger(id1), DBIDUtil.asInteger(id2)).putDouble(d);
- }
- catch(IOException e) {
+ } catch (IOException e) {
throw new AbortException("Error writing distance record " + DBIDFactory.FACTORY.toString(id1) + "," + DBIDFactory.FACTORY.toString(id2) + " to matrix.", e);
}
}
@@ -166,9 +147,25 @@ public class CacheDoubleDistanceInOnDiskMatrix<O, D extends NumberDistance<D, ?>
*/
public static class Parameterizer<O, D extends NumberDistance<D, ?>> extends AbstractApplication.Parameterizer {
/**
- * Holds the database connection to have the algorithm run with.
+ * Parameter that specifies the name of the directory to be re-parsed.
+ * <p>
+ * Key: {@code -loader.diskcache}
+ * </p>
*/
- private Database database = null;
+ public static final OptionID CACHE_ID = new OptionID("loader.diskcache", "File name of the disk cache to create.");
+
+ /**
+ * Parameter that specifies the name of the directory to be re-parsed.
+ * <p>
+ * Key: {@code -loader.distance}
+ * </p>
+ */
+ public static final OptionID DISTANCE_ID = new OptionID("loader.distance", "Distance function to cache.");
+
+ /**
+ * Data source to process.
+ */
+ private InputStep input = null;
/**
* Distance function that is to be cached.
@@ -183,27 +180,22 @@ public class CacheDoubleDistanceInOnDiskMatrix<O, D extends NumberDistance<D, ?>
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- // Database connection parameter
- final ObjectParameter<Database> dbpar = new ObjectParameter<Database>(OptionID.DATABASE_CONNECTION, Database.class, StaticArrayDatabase.class);
- if(config.grab(dbpar)) {
- database = dbpar.instantiateClass(config);
- }
+ input = config.tryInstantiate(InputStep.class);
// Distance function parameter
- final ObjectParameter<DistanceFunction<O, D>> dpar = new ObjectParameter<DistanceFunction<O, D>>(DISTANCE_ID, DistanceFunction.class);
- if(config.grab(dpar)) {
+ final ObjectParameter<DistanceFunction<O, D>> dpar = new ObjectParameter<>(DISTANCE_ID, DistanceFunction.class);
+ if (config.grab(dpar)) {
distance = dpar.instantiateClass(config);
}
// Output file parameter
final FileParameter cpar = new FileParameter(CACHE_ID, FileParameter.FileType.OUTPUT_FILE);
- if(config.grab(cpar)) {
+ if (config.grab(cpar)) {
out = cpar.getValue();
}
-
}
@Override
protected CacheDoubleDistanceInOnDiskMatrix<O, D> makeInstance() {
- return new CacheDoubleDistanceInOnDiskMatrix<O, D>(database, distance, out);
+ return new CacheDoubleDistanceInOnDiskMatrix<>(input, distance, out);
}
}
@@ -215,4 +207,4 @@ public class CacheDoubleDistanceInOnDiskMatrix<O, D extends NumberDistance<D, ?>
public static void main(String[] args) {
runCLIApplication(CacheDoubleDistanceInOnDiskMatrix.class, args);
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/application/cache/CacheDoubleDistanceKNNLists.java b/src/de/lmu/ifi/dbs/elki/application/cache/CacheDoubleDistanceKNNLists.java
new file mode 100644
index 00000000..e9bd4480
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/application/cache/CacheDoubleDistanceKNNLists.java
@@ -0,0 +1,272 @@
+package de.lmu.ifi.dbs.elki.application.cache;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+
+import de.lmu.ifi.dbs.elki.application.AbstractApplication;
+import de.lmu.ifi.dbs.elki.database.Database;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
+import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery;
+import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
+import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
+import de.lmu.ifi.dbs.elki.persistent.ByteArrayUtil;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterEqualConstraint;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.FileParameter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
+import de.lmu.ifi.dbs.elki.workflow.InputStep;
+
+/**
+ * Precompute the k nearest neighbors in a disk cache.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has DistanceFunction
+ *
+ * @param <O> Object type
+ * @param <D> Distance type
+ */
+public class CacheDoubleDistanceKNNLists<O, D extends NumberDistance<D, ?>> extends AbstractApplication {
+ /**
+ * The logger for this class.
+ */
+ private static final Logging LOG = Logging.getLogger(CacheDoubleDistanceKNNLists.class);
+
+ /**
+ * Data source to process.
+ */
+ private InputStep input;
+
+ /**
+ * Distance function that is to be cached.
+ */
+ private DistanceFunction<O, D> distance;
+
+ /**
+ * Number of neighbors to precompute.
+ */
+ private int k;
+
+ /**
+ * Output file.
+ */
+ private File out;
+
+ /**
+ * Magic number to identify files.
+ *
+ * Note, when cloning this class, and performing any incompatible change to
+ * the file format, you should also change this magic ID!
+ */
+ public static final int KNN_CACHE_MAGIC = 0xCAC43D1C;
+
+ /**
+ * Constructor.
+ *
+ * @param input Data source
+ * @param distance Distance function
+ * @param k Number of nearest neighbors
+ * @param out Matrix output file
+ */
+ public CacheDoubleDistanceKNNLists(InputStep input, DistanceFunction<O, D> distance, int k, File out) {
+ super();
+ this.input = input;
+ this.distance = distance;
+ this.k = k;
+ this.out = out;
+ }
+
+ @Override
+ public void run() {
+ Database database = input.getDatabase();
+ Relation<O> relation = database.getRelation(distance.getInputTypeRestriction());
+ DistanceQuery<O, D> distanceQuery = database.getDistanceQuery(relation, distance);
+ KNNQuery<O, D> knnQ = database.getKNNQuery(distanceQuery, DatabaseQuery.HINT_HEAVY_USE);
+
+ // open file.
+ try (RandomAccessFile file = new RandomAccessFile(out, "rw");
+ FileChannel channel = file.getChannel();
+ // and acquire a file write lock
+ FileLock lock = channel.lock()) {
+ // write magic header
+ file.writeInt(KNN_CACHE_MAGIC);
+
+ int bufsize = k * 12 * 2 + 10; // Initial size, enough for 2 kNN.
+ ByteBuffer buffer = ByteBuffer.allocateDirect(bufsize);
+
+ FiniteProgress prog = LOG.isVerbose() ? new FiniteProgress("Computing kNN", relation.size(), LOG) : null;
+
+ for (DBIDIter it = relation.iterDBIDs(); it.valid(); it.advance()) {
+ final KNNList<D> nn = knnQ.getKNNForDBID(it, k);
+ final int nnsize = nn.size();
+
+ // Grow the buffer when needed:
+ if (nnsize * 12 + 10 > bufsize) {
+ while (nnsize * 12 + 10 > bufsize) {
+ bufsize <<= 1;
+ }
+ buffer = ByteBuffer.allocateDirect(bufsize);
+ }
+
+ buffer.clear();
+ ByteArrayUtil.writeUnsignedVarint(buffer, it.internalGetIndex());
+ ByteArrayUtil.writeUnsignedVarint(buffer, nnsize);
+ int c = 0;
+ if (nn instanceof DoubleDistanceDBIDList) {
+ for (DoubleDistanceDBIDListIter ni = ((DoubleDistanceDBIDList) nn).iter(); ni.valid(); ni.advance(), c++) {
+ ByteArrayUtil.writeUnsignedVarint(buffer, ni.internalGetIndex());
+ buffer.putDouble(ni.doubleDistance());
+ }
+ } else {
+ for (DistanceDBIDListIter<D> ni = nn.iter(); ni.valid(); ni.advance(), c++) {
+ ByteArrayUtil.writeUnsignedVarint(buffer, ni.internalGetIndex());
+ buffer.putDouble(ni.getDistance().doubleValue());
+ }
+ }
+ if (c != nn.size()) {
+ throw new AbortException("Sizes did not agree. Cache is invalid.");
+ }
+
+ buffer.flip();
+ channel.write(buffer);
+ if (prog != null) {
+ prog.incrementProcessed(LOG);
+ }
+ }
+ if (prog != null) {
+ prog.ensureCompleted(LOG);
+ }
+ lock.release();
+ } catch (IOException e) {
+ LOG.exception(e);
+ }
+ // FIXME: close!
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer<O, D extends NumberDistance<D, ?>> extends AbstractApplication.Parameterizer {
+ /**
+ * Parameter that specifies the name of the directory to be re-parsed.
+ * <p>
+ * Key: {@code -loader.diskcache}
+ * </p>
+ */
+ public static final OptionID CACHE_ID = new OptionID("loader.diskcache", "File name of the disk cache to create.");
+
+ /**
+ * Parameter that specifies the name of the directory to be re-parsed.
+ * <p>
+ * Key: {@code -loader.distance}
+ * </p>
+ */
+ public static final OptionID DISTANCE_ID = new OptionID("loader.distance", "Distance function to cache.");
+
+ /**
+ * Parameter that specifies the number of neighbors to precompute.
+ * <p>
+ * Key: {@code -loader.k}
+ * </p>
+ */
+ public static final OptionID K_ID = new OptionID("loader.k", "Number of nearest neighbors to precompute.");
+
+ /**
+ * Data source to process.
+ */
+ private InputStep input = null;
+
+ /**
+ * Distance function that is to be cached.
+ */
+ private DistanceFunction<O, D> distance = null;
+
+ /**
+ * Number of neighbors to precompute.
+ */
+ private int k;
+
+ /**
+ * Output file.
+ */
+ private File out = null;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ input = config.tryInstantiate(InputStep.class);
+ // Distance function parameter
+ final ObjectParameter<DistanceFunction<O, D>> dpar = new ObjectParameter<>(DISTANCE_ID, DistanceFunction.class);
+ if (config.grab(dpar)) {
+ distance = dpar.instantiateClass(config);
+ }
+ final IntParameter kpar = new IntParameter(K_ID);
+ kpar.addConstraint(new GreaterEqualConstraint(1));
+ if (config.grab(kpar)) {
+ k = kpar.intValue();
+ }
+ // Output file parameter
+ final FileParameter cpar = new FileParameter(CACHE_ID, FileParameter.FileType.OUTPUT_FILE);
+ if (config.grab(cpar)) {
+ out = cpar.getValue();
+ }
+ }
+
+ @Override
+ protected CacheDoubleDistanceKNNLists<O, D> makeInstance() {
+ return new CacheDoubleDistanceKNNLists<>(input, distance, k, out);
+ }
+ }
+
+ /**
+ * Main method, delegate to super class.
+ *
+ * @param args Command line arguments
+ */
+ public static void main(String[] args) {
+ runCLIApplication(CacheDoubleDistanceKNNLists.class, args);
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/application/cache/CacheDoubleDistanceRangeQueries.java b/src/de/lmu/ifi/dbs/elki/application/cache/CacheDoubleDistanceRangeQueries.java
new file mode 100644
index 00000000..f9434820
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/application/cache/CacheDoubleDistanceRangeQueries.java
@@ -0,0 +1,277 @@
+package de.lmu.ifi.dbs.elki.application.cache;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+
+import de.lmu.ifi.dbs.elki.application.AbstractApplication;
+import de.lmu.ifi.dbs.elki.database.Database;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery;
+import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
+import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
+import de.lmu.ifi.dbs.elki.persistent.ByteArrayUtil;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterEqualConstraint;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleParameter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.FileParameter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
+import de.lmu.ifi.dbs.elki.workflow.InputStep;
+
+/**
+ * Precompute the k nearest neighbors in a disk cache.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has DistanceFunction
+ *
+ * @param <O> Object type
+ */
+public class CacheDoubleDistanceRangeQueries<O> extends AbstractApplication {
+ /**
+ * The logger for this class.
+ */
+ private static final Logging LOG = Logging.getLogger(CacheDoubleDistanceRangeQueries.class);
+
+ /**
+ * Data source to process.
+ */
+ private InputStep input;
+
+ /**
+ * Distance function that is to be cached.
+ */
+ private DistanceFunction<O, DoubleDistance> distance;
+
+ /**
+ * Query radius.
+ */
+ private double radius;
+
+ /**
+ * Output file.
+ */
+ private File out;
+
+ /**
+ * Magic number to identify files.
+ *
+ * Note, when cloning this class, and performing any incompatible change to
+ * the file format, you should also change this magic ID!
+ */
+ public static final int RANGE_CACHE_MAGIC = 0xCAC43333;
+
+ /**
+ * Constructor.
+ *
+ * @param input Data source
+ * @param distance Distance function
+ * @param radius Query radius
+ * @param out Matrix output file
+ */
+ public CacheDoubleDistanceRangeQueries(InputStep input, DistanceFunction<O, DoubleDistance> distance, double radius, File out) {
+ super();
+ this.input = input;
+ this.distance = distance;
+ this.radius = radius;
+ this.out = out;
+ }
+
+ @Override
+ public void run() {
+ Database database = input.getDatabase();
+ Relation<O> relation = database.getRelation(distance.getInputTypeRestriction());
+ DistanceQuery<O, DoubleDistance> distanceQuery = database.getDistanceQuery(relation, distance);
+ DoubleDistance rad = new DoubleDistance(radius);
+ RangeQuery<O, DoubleDistance> rangeQ = database.getRangeQuery(distanceQuery, rad, DatabaseQuery.HINT_HEAVY_USE);
+
+ LOG.verbose("Performing range queries with radius " + rad);
+
+ // open file.
+ try (RandomAccessFile file = new RandomAccessFile(out, "rw");
+ FileChannel channel = file.getChannel();
+ // and acquire a file write lock
+ FileLock lock = channel.lock()) {
+ // write magic header
+ file.writeInt(RANGE_CACHE_MAGIC);
+ // write the query radius.
+ file.writeDouble(radius);
+
+ int bufsize = 100 * 12 * 2 + 10; // Initial size, enough for 100.
+ ByteBuffer buffer = ByteBuffer.allocateDirect(bufsize);
+
+ FiniteProgress prog = LOG.isVerbose() ? new FiniteProgress("Computing range queries", relation.size(), LOG) : null;
+
+ for (DBIDIter it = relation.iterDBIDs(); it.valid(); it.advance()) {
+ final DistanceDBIDList<DoubleDistance> nn = rangeQ.getRangeForDBID(it, rad);
+ final int nnsize = nn.size();
+
+ // Grow the buffer when needed:
+ if (nnsize * 12 + 10 > bufsize) {
+ while (nnsize * 12 + 10 > bufsize) {
+ bufsize <<= 1;
+ }
+ LOG.verbose("Resizing buffer to "+bufsize+" to store "+nnsize+" results:");
+ buffer = ByteBuffer.allocateDirect(bufsize);
+ }
+
+ buffer.clear();
+ ByteArrayUtil.writeUnsignedVarint(buffer, it.internalGetIndex());
+ ByteArrayUtil.writeUnsignedVarint(buffer, nnsize);
+ int c = 0;
+ if (nn instanceof DoubleDistanceDBIDList) {
+ for (DoubleDistanceDBIDListIter ni = ((DoubleDistanceDBIDList) nn).iter(); ni.valid(); ni.advance(), c++) {
+ ByteArrayUtil.writeUnsignedVarint(buffer, ni.internalGetIndex());
+ buffer.putDouble(ni.doubleDistance());
+ }
+ } else {
+ for (DistanceDBIDListIter<DoubleDistance> ni = nn.iter(); ni.valid(); ni.advance(), c++) {
+ ByteArrayUtil.writeUnsignedVarint(buffer, ni.internalGetIndex());
+ buffer.putDouble(ni.getDistance().doubleValue());
+ }
+ }
+ if (c != nn.size()) {
+ throw new AbortException("Sizes did not agree. Cache is invalid.");
+ }
+
+ buffer.flip();
+ channel.write(buffer);
+ if (prog != null) {
+ prog.incrementProcessed(LOG);
+ }
+ }
+ if (prog != null) {
+ prog.ensureCompleted(LOG);
+ }
+ lock.release();
+ } catch (IOException e) {
+ LOG.exception(e);
+ }
+ // FIXME: close!
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer<O> extends AbstractApplication.Parameterizer {
+ /**
+ * Parameter that specifies the name of the directory to be re-parsed.
+ * <p>
+ * Key: {@code -loader.diskcache}
+ * </p>
+ */
+ public static final OptionID CACHE_ID = new OptionID("loader.diskcache", "File name of the disk cache to create.");
+
+ /**
+ * Parameter that specifies the name of the directory to be re-parsed.
+ * <p>
+ * Key: {@code -loader.distance}
+ * </p>
+ */
+ public static final OptionID DISTANCE_ID = new OptionID("loader.distance", "Distance function to cache.");
+
+ /**
+ * Parameter that specifies the query radius to precompute.
+ * <p>
+ * Key: {@code -loader.radius}
+ * </p>
+ */
+ public static final OptionID RADIUS_ID = new OptionID("loader.radius", "Query radius for precomputation.");
+
+ /**
+ * Data source to process.
+ */
+ private InputStep input = null;
+
+ /**
+ * Distance function that is to be cached.
+ */
+ private DistanceFunction<O, DoubleDistance> distance = null;
+
+ /**
+ * Number of neighbors to precompute.
+ */
+ private double radius;
+
+ /**
+ * Output file.
+ */
+ private File out = null;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ input = config.tryInstantiate(InputStep.class);
+ // Distance function parameter
+ final ObjectParameter<DistanceFunction<O, DoubleDistance>> dpar = new ObjectParameter<>(DISTANCE_ID, DistanceFunction.class);
+ if (config.grab(dpar)) {
+ distance = dpar.instantiateClass(config);
+ }
+ final DoubleParameter kpar = new DoubleParameter(RADIUS_ID);
+ kpar.addConstraint(new GreaterEqualConstraint(0.));
+ if (config.grab(kpar)) {
+ radius = kpar.doubleValue();
+ }
+ // Output file parameter
+ final FileParameter cpar = new FileParameter(CACHE_ID, FileParameter.FileType.OUTPUT_FILE);
+ if (config.grab(cpar)) {
+ out = cpar.getValue();
+ }
+ }
+
+ @Override
+ protected CacheDoubleDistanceRangeQueries<O> makeInstance() {
+ return new CacheDoubleDistanceRangeQueries<>(input, distance, radius, out);
+ }
+ }
+
+ /**
+ * Main method, delegate to super class.
+ *
+ * @param args Command line arguments
+ */
+ public static void main(String[] args) {
+ runCLIApplication(CacheDoubleDistanceRangeQueries.class, args);
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/application/cache/CacheFloatDistanceInOnDiskMatrix.java b/src/de/lmu/ifi/dbs/elki/application/cache/CacheFloatDistanceInOnDiskMatrix.java
index 144b4b70..5499415b 100644
--- a/src/de/lmu/ifi/dbs/elki/application/cache/CacheFloatDistanceInOnDiskMatrix.java
+++ b/src/de/lmu/ifi/dbs/elki/application/cache/CacheFloatDistanceInOnDiskMatrix.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.application.cache;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,7 +28,6 @@ import java.io.IOException;
import de.lmu.ifi.dbs.elki.application.AbstractApplication;
import de.lmu.ifi.dbs.elki.database.Database;
-import de.lmu.ifi.dbs.elki.database.StaticArrayDatabase;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
@@ -39,14 +38,13 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.persistent.OnDiskUpperTriangleMatrix;
import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.FileParameter;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
+import de.lmu.ifi.dbs.elki.workflow.InputStep;
/**
- * Wrapper to convert a traditional text-serialized result into a on-disk matrix
- * for random access.
+ * Precompute an on-disk distance matrix, using double precision.
*
* @author Erich Schubert
*
@@ -63,22 +61,6 @@ public class CacheFloatDistanceInOnDiskMatrix<O, D extends NumberDistance<D, ?>>
private static final Logging LOG = Logging.getLogger(CacheFloatDistanceInOnDiskMatrix.class);
/**
- * Parameter that specifies the name of the directory to be re-parsed.
- * <p>
- * Key: {@code -loader.diskcache}
- * </p>
- */
- public static final OptionID CACHE_ID = new OptionID("loader.diskcache", "File name of the disk cache to create.");
-
- /**
- * Parameter that specifies the name of the directory to be re-parsed.
- * <p>
- * Key: {@code -loader.distance}
- * </p>
- */
- public static final OptionID DISTANCE_ID = new OptionID("loader.distance", "Distance function to cache.");
-
- /**
* Debug flag, to double-check all write operations.
*/
private static final boolean debugExtraCheckSymmetry = false;
@@ -89,9 +71,9 @@ public class CacheFloatDistanceInOnDiskMatrix<O, D extends NumberDistance<D, ?>>
private static final int FLOAT_SIZE = 4;
/**
- * Holds the database connection to have the algorithm run with.
+ * Data source to process.
*/
- private Database database;
+ private InputStep input;
/**
* Distance function that is to be cached.
@@ -106,28 +88,28 @@ public class CacheFloatDistanceInOnDiskMatrix<O, D extends NumberDistance<D, ?>>
/**
* Constructor.
*
- * @param database Database
+ * @param input Data source
* @param distance Distance function
* @param out Matrix output file
*/
- public CacheFloatDistanceInOnDiskMatrix(Database database, DistanceFunction<O, D> distance, File out) {
+ public CacheFloatDistanceInOnDiskMatrix(InputStep input, DistanceFunction<O, D> distance, File out) {
super();
- this.database = database;
+ this.input = input;
this.distance = distance;
this.out = out;
}
@Override
public void run() {
- database.initialize();
+ Database database = input.getDatabase();
Relation<O> relation = database.getRelation(distance.getInputTypeRestriction());
DistanceQuery<O, D> distanceQuery = database.getDistanceQuery(relation, distance);
int matrixsize = 0;
- for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
+ for (DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
final int intid = DBIDUtil.asInteger(iditer);
matrixsize = Math.max(matrixsize, intid + 1);
- if(intid < 0) {
+ if (intid < 0) {
throw new AbortException("OnDiskMatrixCache does not allow negative DBIDs.");
}
}
@@ -135,25 +117,23 @@ public class CacheFloatDistanceInOnDiskMatrix<O, D extends NumberDistance<D, ?>>
OnDiskUpperTriangleMatrix matrix;
try {
matrix = new OnDiskUpperTriangleMatrix(out, DiskCacheBasedFloatDistanceFunction.FLOAT_CACHE_MAGIC, 0, FLOAT_SIZE, matrixsize);
- }
- catch(IOException e) {
+ } catch (IOException e) {
throw new AbortException("Error creating output matrix.", e);
}
- for(DBIDIter id1 = relation.iterDBIDs(); id1.valid(); id1.advance()) {
- for(DBIDIter id2 = relation.iterDBIDs(); id2.valid(); id2.advance()) {
- if(DBIDUtil.asInteger(id2) >= DBIDUtil.asInteger(id1)) {
+ for (DBIDIter id1 = relation.iterDBIDs(); id1.valid(); id1.advance()) {
+ for (DBIDIter id2 = relation.iterDBIDs(); id2.valid(); id2.advance()) {
+ if (DBIDUtil.asInteger(id2) >= DBIDUtil.asInteger(id1)) {
float d = distanceQuery.distance(id1, id2).floatValue();
- if(debugExtraCheckSymmetry) {
+ if (debugExtraCheckSymmetry) {
float d2 = distanceQuery.distance(id2, id1).floatValue();
- if(Math.abs(d - d2) > 0.0000001) {
+ if (Math.abs(d - d2) > 0.0000001) {
LOG.warning("Distance function doesn't appear to be symmetric!");
}
}
try {
matrix.getRecordBuffer(DBIDUtil.asInteger(id1), DBIDUtil.asInteger(id2)).putFloat(d);
- }
- catch(IOException e) {
+ } catch (IOException e) {
throw new AbortException("Error writing distance record " + id1 + "," + id2 + " to matrix.", e);
}
}
@@ -170,9 +150,9 @@ public class CacheFloatDistanceInOnDiskMatrix<O, D extends NumberDistance<D, ?>>
*/
public static class Parameterizer<O, D extends NumberDistance<D, ?>> extends AbstractApplication.Parameterizer {
/**
- * Holds the database connection to have the algorithm run with.
+ * Data source to process.
*/
- private Database database = null;
+ private InputStep input = null;
/**
* Distance function that is to be cached.
@@ -187,27 +167,22 @@ public class CacheFloatDistanceInOnDiskMatrix<O, D extends NumberDistance<D, ?>>
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- // Database connection parameter
- final ObjectParameter<Database> dbpar = new ObjectParameter<Database>(OptionID.DATABASE_CONNECTION, Database.class, StaticArrayDatabase.class);
- if(config.grab(dbpar)) {
- database = dbpar.instantiateClass(config);
- }
+ input = config.tryInstantiate(InputStep.class);
// Distance function parameter
- final ObjectParameter<DistanceFunction<O, D>> dpar = new ObjectParameter<DistanceFunction<O, D>>(DISTANCE_ID, DistanceFunction.class);
- if(config.grab(dpar)) {
+ final ObjectParameter<DistanceFunction<O, D>> dpar = new ObjectParameter<>(CacheDoubleDistanceInOnDiskMatrix.Parameterizer.DISTANCE_ID, DistanceFunction.class);
+ if (config.grab(dpar)) {
distance = dpar.instantiateClass(config);
}
// Output file parameter
- final FileParameter cpar = new FileParameter(CACHE_ID, FileParameter.FileType.OUTPUT_FILE);
- if(config.grab(cpar)) {
+ final FileParameter cpar = new FileParameter(CacheDoubleDistanceInOnDiskMatrix.Parameterizer.CACHE_ID, FileParameter.FileType.OUTPUT_FILE);
+ if (config.grab(cpar)) {
out = cpar.getValue();
}
-
}
@Override
protected CacheFloatDistanceInOnDiskMatrix<O, D> makeInstance() {
- return new CacheFloatDistanceInOnDiskMatrix<O, D>(database, distance, out);
+ return new CacheFloatDistanceInOnDiskMatrix<>(input, distance, out);
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/application/cache/package-info.java b/src/de/lmu/ifi/dbs/elki/application/cache/package-info.java
index 5ed7ec1c..78a93a07 100644
--- a/src/de/lmu/ifi/dbs/elki/application/cache/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/application/cache/package-info.java
@@ -11,7 +11,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/application/geo/VisualizeGeodesicDistances.java b/src/de/lmu/ifi/dbs/elki/application/geo/VisualizeGeodesicDistances.java
index bdc0f39a..75770ba7 100644
--- a/src/de/lmu/ifi/dbs/elki/application/geo/VisualizeGeodesicDistances.java
+++ b/src/de/lmu/ifi/dbs/elki/application/geo/VisualizeGeodesicDistances.java
@@ -32,20 +32,20 @@ import de.lmu.ifi.dbs.elki.application.AbstractApplication;
import de.lmu.ifi.dbs.elki.data.DoubleVector;
import de.lmu.ifi.dbs.elki.data.ModifiableHyperBoundingBox;
import de.lmu.ifi.dbs.elki.logging.Logging;
-import de.lmu.ifi.dbs.elki.math.GeoUtil;
-import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
+import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
+import de.lmu.ifi.dbs.elki.math.geodesy.EarthModel;
+import de.lmu.ifi.dbs.elki.math.geodesy.SphereUtil;
+import de.lmu.ifi.dbs.elki.math.geodesy.SphericalVincentyEarthModel;
import de.lmu.ifi.dbs.elki.utilities.exceptions.UnableToComplyException;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterEqualConstraint;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.EnumParameter;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
/**
* Visualization function for Cross-track distance function
*
- * TODO: make resolution configurable.
- *
* TODO: make origin point / rectangle configurable.
*
* @author Niels Dörre
@@ -66,7 +66,7 @@ public class VisualizeGeodesicDistances extends AbstractApplication {
*/
public static enum Mode {
/** Cross track distance */
- CTD,
+ XTD,
/** Along track distance */
ATD,
/** Mindist */
@@ -81,7 +81,7 @@ public class VisualizeGeodesicDistances extends AbstractApplication {
/**
* Image size.
*/
- final int width = 2000, height = 1000;
+ protected int width = 2000, height = 1000;
/**
* Number of steps for shades.
@@ -89,9 +89,14 @@ public class VisualizeGeodesicDistances extends AbstractApplication {
protected int steps = 10;
/**
- * Visualization mode
+ * Visualization mode.
+ */
+ protected Mode mode = Mode.XTD;
+
+ /**
+ * Earth model.
*/
- private Mode mode = Mode.CTD;
+ protected EarthModel model;
/**
* Constructor.
@@ -99,12 +104,16 @@ public class VisualizeGeodesicDistances extends AbstractApplication {
* @param out Output filename
* @param steps Number of steps in the color map
* @param mode Visualization mode
+ * @param model Earth model
*/
- public VisualizeGeodesicDistances(File out, int steps, Mode mode) {
+ public VisualizeGeodesicDistances(File out, int resolution, int steps, Mode mode, EarthModel model) {
super();
+ this.width = resolution;
+ this.height = resolution >> 1;
this.out = out;
this.steps = steps;
this.mode = mode;
+ this.model = model;
}
@Override
@@ -125,34 +134,20 @@ public class VisualizeGeodesicDistances extends AbstractApplication {
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
- final double max;
- switch(mode) {
- case ATD:
- // Currently half the circumference - we're missing the sign
- max = GeoUtil.EARTH_RADIUS * Math.PI;
- break;
- case CTD:
- // Quarter (!) the circumference is the maximum CTD!
- max = .5 * GeoUtil.EARTH_RADIUS * Math.PI;
- break;
- case MINDIST:
- // Half the circumference
- max = GeoUtil.EARTH_RADIUS * Math.PI;
- break;
- default:
- throw new AbortException("Invalid mode: " + mode);
- }
+ final double max = model.getEquatorialRadius() * Math.PI;
+
// Red: left off-course, green: right off-course
int red = 0xffff0000;
int green = 0xff00ff00;
+ FiniteProgress prog = LOG.isVerbose() ? new FiniteProgress("columns", width, LOG) : null;
for (int x = 0; x < width; x++) {
final double lon = x * 360. / width - 180.;
for (int y = 0; y < height; y++) {
final double lat = y * -180. / height + 90.;
switch(mode) {
case ATD: {
- final double atd = GeoUtil.alongTrackDistance(stap.doubleValue(0), stap.doubleValue(1), endp.doubleValue(0), endp.doubleValue(1), lat, lon);
+ final double atd = model.getEquatorialRadius() * SphereUtil.alongTrackDistanceDeg(stap.doubleValue(0), stap.doubleValue(1), endp.doubleValue(0), endp.doubleValue(1), lat, lon);
if (atd < 0) {
img.setRGB(x, y, colorMultiply(red, -atd / max, false));
} else {
@@ -160,8 +155,8 @@ public class VisualizeGeodesicDistances extends AbstractApplication {
}
break;
}
- case CTD: {
- final double ctd = GeoUtil.crossTrackDistance(stap.doubleValue(0), stap.doubleValue(1), endp.doubleValue(0), endp.doubleValue(1), lat, lon);
+ case XTD: {
+ final double ctd = model.getEquatorialRadius() * SphereUtil.crossTrackDistanceDeg(stap.doubleValue(0), stap.doubleValue(1), endp.doubleValue(0), endp.doubleValue(1), lat, lon);
if (ctd < 0) {
img.setRGB(x, y, colorMultiply(red, -ctd / max, false));
} else {
@@ -170,7 +165,7 @@ public class VisualizeGeodesicDistances extends AbstractApplication {
break;
}
case MINDIST: {
- final double dist = GeoUtil.latlngMinDistDeg(lat, lon, bb.getMin(0), bb.getMin(1), bb.getMax(0), bb.getMax(1));
+ final double dist = model.minDistDeg(lat, lon, bb.getMin(0), bb.getMin(1), bb.getMax(0), bb.getMax(1));
if (dist < 0) {
img.setRGB(x, y, colorMultiply(red, -dist / max, true));
} else {
@@ -180,6 +175,12 @@ public class VisualizeGeodesicDistances extends AbstractApplication {
}
}
}
+ if (prog != null) {
+ prog.incrementProcessed(LOG);
+ }
+ }
+ if (prog != null) {
+ prog.ensureCompleted(LOG);
}
try {
@@ -192,10 +193,24 @@ public class VisualizeGeodesicDistances extends AbstractApplication {
private int colorMultiply(int col, double reldist, boolean ceil) {
if (steps > 0) {
if (!ceil) {
- reldist = Math.round(reldist * steps) * 1. / steps;
+ reldist = Math.round(reldist * steps) / steps;
} else {
reldist = Math.ceil(reldist * steps) / steps;
}
+ } else if (steps < 0 && reldist > 0.) {
+ double s = reldist * -steps;
+ double off = Math.abs(s - Math.round(s));
+ double factor = -steps * 1. / 1000; // height;
+ if (off < factor) { // Blend with black:
+ factor = (off / factor);
+ int a = (col >> 24) & 0xFF;
+ a = (int) (a * Math.sqrt(reldist)) & 0xFF;
+ a = (int) ((1 - factor) * 0xFF + factor * a);
+ int r = (int) (factor * ((col >> 16) & 0xFF));
+ int g = (int) (factor * ((col >> 8) & 0xFF));
+ int b = (int) (factor * (col & 0xFF));
+ return a << 24 | r << 16 | g << 8 | b;
+ }
}
int a = (col >> 24) & 0xFF, r = (col >> 16) & 0xFF, g = (col >> 8) & 0xFF, b = (col) & 0xFF;
a = (int) (a * Math.sqrt(reldist)) & 0xFF;
@@ -208,7 +223,7 @@ public class VisualizeGeodesicDistances extends AbstractApplication {
* @param args Parameters
*/
public static void main(String[] args) {
- VisualizeGeodesicDistances.runCLIApplication(VisualizeGeodesicDistances.class, args);
+ runCLIApplication(VisualizeGeodesicDistances.class, args);
}
/**
@@ -222,12 +237,17 @@ public class VisualizeGeodesicDistances extends AbstractApplication {
/**
* Number of steps in the distance map.
*/
- public static final OptionID STEPS_ID = new OptionID("ctdvis.steps", "Number of steps for the distance map.");
+ public static final OptionID STEPS_ID = new OptionID("geodistvis.steps", "Number of steps for the distance map. Use negative numbers to get contour lines.");
+
+ /**
+ * Image resolution.
+ */
+ public static final OptionID RESOLUTION_ID = new OptionID("geodistvis.resolution", "Horizontal resolution for the image map (vertical resolution is horizonal / 2).");
/**
* Visualization mode.
*/
- public static final OptionID MODE_ID = new OptionID("ctdvis.mode", "Visualization mode.");
+ public static final OptionID MODE_ID = new OptionID("geodistvis.mode", "Visualization mode.");
/**
* Holds the file to print results to.
@@ -235,34 +255,51 @@ public class VisualizeGeodesicDistances extends AbstractApplication {
protected File out = null;
/**
- * Number of steps in the color map
+ * Number of steps in the color map.
*/
protected int steps = 0;
/**
- * Visualization mode
+ * Horizontal resolution.
+ */
+ protected int resolution = 2000;
+
+ /**
+ * Visualization mode.
*/
- protected Mode mode = Mode.CTD;
+ protected Mode mode = Mode.XTD;
+
+ /**
+ * Earth model to use.
+ */
+ protected EarthModel model;
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- out = super.getParameterOutputFile(config, "Output image file");
+ out = super.getParameterOutputFile(config, "Output image file name.");
IntParameter stepsP = new IntParameter(STEPS_ID);
stepsP.setOptional(true);
- stepsP.addConstraint(new GreaterEqualConstraint(0));
if (config.grab(stepsP)) {
steps = stepsP.intValue();
}
- EnumParameter<Mode> modeP = new EnumParameter<Mode>(MODE_ID, Mode.class, Mode.CTD);
+ IntParameter resolutionP = new IntParameter(RESOLUTION_ID, 2000);
+ if (config.grab(resolutionP)) {
+ resolution = resolutionP.intValue();
+ }
+ EnumParameter<Mode> modeP = new EnumParameter<>(MODE_ID, Mode.class, Mode.XTD);
if (config.grab(modeP)) {
mode = modeP.getValue();
}
+ ObjectParameter<EarthModel> modelP = new ObjectParameter<>(EarthModel.MODEL_ID, EarthModel.class, SphericalVincentyEarthModel.class);
+ if (config.grab(modelP)) {
+ model = modelP.instantiateClass(config);
+ }
}
@Override
protected VisualizeGeodesicDistances makeInstance() {
- return new VisualizeGeodesicDistances(out, steps, mode);
+ return new VisualizeGeodesicDistances(out, resolution, steps, mode, model);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/application/geo/package-info.java b/src/de/lmu/ifi/dbs/elki/application/geo/package-info.java
index 5937fc7d..3c60474d 100644
--- a/src/de/lmu/ifi/dbs/elki/application/geo/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/application/geo/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/application/greedyensemble/ComputeKNNOutlierScores.java b/src/de/lmu/ifi/dbs/elki/application/greedyensemble/ComputeKNNOutlierScores.java
index 5f5074a2..9dd9ddae 100644
--- a/src/de/lmu/ifi/dbs/elki/application/greedyensemble/ComputeKNNOutlierScores.java
+++ b/src/de/lmu/ifi/dbs/elki/application/greedyensemble/ComputeKNNOutlierScores.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.application.greedyensemble;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -33,14 +33,17 @@ import de.lmu.ifi.dbs.elki.algorithm.AbstractAlgorithm;
import de.lmu.ifi.dbs.elki.algorithm.outlier.ABOD;
import de.lmu.ifi.dbs.elki.algorithm.outlier.KNNOutlier;
import de.lmu.ifi.dbs.elki.algorithm.outlier.KNNWeightOutlier;
-import de.lmu.ifi.dbs.elki.algorithm.outlier.LDOF;
-import de.lmu.ifi.dbs.elki.algorithm.outlier.LOF;
-import de.lmu.ifi.dbs.elki.algorithm.outlier.LoOP;
+import de.lmu.ifi.dbs.elki.algorithm.outlier.lof.LDF;
+import de.lmu.ifi.dbs.elki.algorithm.outlier.lof.LDOF;
+import de.lmu.ifi.dbs.elki.algorithm.outlier.lof.LOF;
+import de.lmu.ifi.dbs.elki.algorithm.outlier.lof.LoOP;
+import de.lmu.ifi.dbs.elki.algorithm.outlier.lof.SimplifiedLOF;
import de.lmu.ifi.dbs.elki.algorithm.outlier.trivial.ByLabelOutlier;
import de.lmu.ifi.dbs.elki.algorithm.outlier.trivial.TrivialAllOutlier;
import de.lmu.ifi.dbs.elki.algorithm.outlier.trivial.TrivialNoOutlier;
import de.lmu.ifi.dbs.elki.application.AbstractApplication;
import de.lmu.ifi.dbs.elki.data.DoubleVector;
+import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.database.QueryUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
@@ -50,14 +53,13 @@ import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.PreprocessorKNNQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.distance.similarityfunction.kernel.PolynomialKernelFunction;
import de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNPreprocessor;
import de.lmu.ifi.dbs.elki.logging.Logging;
-import de.lmu.ifi.dbs.elki.result.Result;
-import de.lmu.ifi.dbs.elki.result.ResultHierarchy;
+import de.lmu.ifi.dbs.elki.math.statistics.kernelfunctions.GaussianKernelDensityFunction;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
import de.lmu.ifi.dbs.elki.utilities.Base64;
import de.lmu.ifi.dbs.elki.utilities.FormatUtil;
@@ -70,8 +72,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
import de.lmu.ifi.dbs.elki.utilities.scaling.IdentityScaling;
import de.lmu.ifi.dbs.elki.utilities.scaling.ScalingFunction;
-import de.lmu.ifi.dbs.elki.utilities.scaling.outlier.MinusLogStandardDeviationScaling;
-import de.lmu.ifi.dbs.elki.utilities.scaling.outlier.StandardDeviationScaling;
+import de.lmu.ifi.dbs.elki.utilities.scaling.outlier.OutlierScalingFunction;
import de.lmu.ifi.dbs.elki.workflow.InputStep;
/**
@@ -90,7 +91,7 @@ import de.lmu.ifi.dbs.elki.workflow.InputStep;
* @author Erich Schubert
*/
@Reference(authors = "E. Schubert, R. Wojdanowski, A. Zimek, H.-P. Kriegel", title = "On Evaluation of Outlier Rankings and Outlier Scores", booktitle = "Proc. 12th SIAM International Conference on Data Mining (SDM), Anaheim, CA, 2012.")
-public class ComputeKNNOutlierScores<O, D extends NumberDistance<D, ?>> extends AbstractApplication {
+public class ComputeKNNOutlierScores<O extends NumberVector<?>, D extends NumberDistance<D, ?>> extends AbstractApplication {
/**
* Our logger class.
*/
@@ -137,6 +138,11 @@ public class ComputeKNNOutlierScores<O, D extends NumberDistance<D, ?>> extends
boolean runabod = false;
/**
+ * Scaling function.
+ */
+ ScalingFunction scaling;
+
+ /**
* Constructor.
*
* @param inputstep Input step
@@ -146,8 +152,9 @@ public class ComputeKNNOutlierScores<O, D extends NumberDistance<D, ?>> extends
* @param maxk Maximum k value
* @param bylabel By label outlier (reference)
* @param outfile Output file
+ * @param scaling Scaling function
*/
- public ComputeKNNOutlierScores(InputStep inputstep, DistanceFunction<? super O, D> distf, int startk, int stepk, int maxk, ByLabelOutlier bylabel, File outfile) {
+ public ComputeKNNOutlierScores(InputStep inputstep, DistanceFunction<? super O, D> distf, int startk, int stepk, int maxk, ByLabelOutlier bylabel, File outfile, ScalingFunction scaling) {
super();
this.distf = distf;
this.startk = startk;
@@ -156,19 +163,25 @@ public class ComputeKNNOutlierScores<O, D extends NumberDistance<D, ?>> extends
this.inputstep = inputstep;
this.bylabel = bylabel;
this.outfile = outfile;
+ this.scaling = scaling;
}
@Override
public void run() {
final Database database = inputstep.getDatabase();
final Relation<O> relation = database.getRelation(distf.getInputTypeRestriction());
- LOG.verbose("Running preprocessor ...");
- MaterializeKNNPreprocessor<O, D> preproc = new MaterializeKNNPreprocessor<O, D>(relation, distf, maxk + 2);
- database.addIndex(preproc);
- // Test that we did get a proper index query
- KNNQuery<O, D> knnq = QueryUtil.getKNNQuery(relation, distf);
- if(!(knnq instanceof PreprocessorKNNQuery)) {
+ // If there is no kNN preprocessor already, then precompute.
+ KNNQuery<O, D> knnq = QueryUtil.getKNNQuery(relation, distf, maxk + 2);
+ if (!(knnq instanceof PreprocessorKNNQuery)) {
+ LOG.verbose("Running preprocessor ...");
+ MaterializeKNNPreprocessor<O, D> preproc = new MaterializeKNNPreprocessor<>(relation, distf, maxk + 2);
+ database.addIndex(preproc);
+ }
+
+ // Test that we now get a proper index query
+ knnq = QueryUtil.getKNNQuery(relation, distf, maxk + 2);
+ if (!(knnq instanceof PreprocessorKNNQuery)) {
LOG.warning("Not using preprocessor knn query -- KNN queries using class: " + knnq.getClass());
}
@@ -177,8 +190,7 @@ public class ComputeKNNOutlierScores<O, D extends NumberDistance<D, ?>> extends
final PrintStream fout;
try {
fout = new PrintStream(outfile);
- }
- catch(FileNotFoundException e) {
+ } catch (FileNotFoundException e) {
throw new AbortException("Cannot create output file.", e);
}
// Control: print the DBIDs in case we are seeing an odd iteration
@@ -186,14 +198,13 @@ public class ComputeKNNOutlierScores<O, D extends NumberDistance<D, ?>> extends
try {
MessageDigest md = MessageDigest.getInstance("MD5");
for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
- md.update(" ".getBytes());
+ md.update((byte) ' ');
md.update(DBIDUtil.toString(iter).getBytes());
}
fout.append("# DBID-series MD5:");
fout.append(Base64.encodeBase64(md.digest()));
fout.append(FormatUtil.NEWLINE);
- }
- catch(NoSuchAlgorithmException e) {
+ } catch (NoSuchAlgorithmException e) {
throw new AbortException("MD5 not found.");
}
}
@@ -204,7 +215,8 @@ public class ComputeKNNOutlierScores<O, D extends NumberDistance<D, ?>> extends
writeResult(fout, ids, bylabelresult, new IdentityScaling(), "bylabel");
}
// No/all outliers "results"
- {
+ boolean withdummy = false;
+ if (withdummy) {
OutlierResult noresult = (new TrivialNoOutlier()).run(database);
writeResult(fout, ids, noresult, new IdentityScaling(), "no-outliers");
OutlierResult allresult = (new TrivialAllOutlier()).run(database);
@@ -216,13 +228,10 @@ public class ComputeKNNOutlierScores<O, D extends NumberDistance<D, ?>> extends
runForEachK(new AlgRunner() {
@Override
public void run(int k, String kstr) {
- KNNOutlier<O, D> knn = new KNNOutlier<O, D>(distf, k);
+ KNNOutlier<O, D> knn = new KNNOutlier<>(distf, k);
OutlierResult knnresult = knn.run(database, relation);
- // Setup scaling
- StandardDeviationScaling scaling = new StandardDeviationScaling();
- scaling.prepare(knnresult);
writeResult(fout, ids, knnresult, scaling, "KNN-" + kstr);
- detachResult(database, knnresult);
+ database.getHierarchy().removeSubtree(knnresult);
}
});
// KNN Weight
@@ -230,13 +239,10 @@ public class ComputeKNNOutlierScores<O, D extends NumberDistance<D, ?>> extends
runForEachK(new AlgRunner() {
@Override
public void run(int k, String kstr) {
- KNNWeightOutlier<O, D> knnw = new KNNWeightOutlier<O, D>(distf, k);
+ KNNWeightOutlier<O, D> knnw = new KNNWeightOutlier<>(distf, k);
OutlierResult knnresult = knnw.run(database, relation);
- // Setup scaling
- StandardDeviationScaling scaling = new StandardDeviationScaling();
- scaling.prepare(knnresult);
writeResult(fout, ids, knnresult, scaling, "KNNW-" + kstr);
- detachResult(database, knnresult);
+ database.getHierarchy().removeSubtree(knnresult);
}
});
// Run LOF
@@ -244,13 +250,21 @@ public class ComputeKNNOutlierScores<O, D extends NumberDistance<D, ?>> extends
runForEachK(new AlgRunner() {
@Override
public void run(int k, String kstr) {
- LOF<O, D> lof = new LOF<O, D>(k, distf, distf);
- OutlierResult lofresult = lof.run(relation);
- // Setup scaling
- StandardDeviationScaling scaling = new StandardDeviationScaling(1.0, 1.0);
- scaling.prepare(lofresult);
+ LOF<O, D> lof = new LOF<>(k, distf);
+ OutlierResult lofresult = lof.run(database, relation);
writeResult(fout, ids, lofresult, scaling, "LOF-" + kstr);
- detachResult(database, lofresult);
+ database.getHierarchy().removeSubtree(lofresult);
+ }
+ });
+ // Run Simplified-LOF
+ LOG.verbose("Running Simplified-LOF");
+ runForEachK(new AlgRunner() {
+ @Override
+ public void run(int k, String kstr) {
+ SimplifiedLOF<O, D> lof = new SimplifiedLOF<>(k, distf);
+ OutlierResult lofresult = lof.run(database, relation);
+ writeResult(fout, ids, lofresult, scaling, "Simplified-LOF-" + kstr);
+ database.getHierarchy().removeSubtree(lofresult);
}
});
// LoOP
@@ -258,28 +272,38 @@ public class ComputeKNNOutlierScores<O, D extends NumberDistance<D, ?>> extends
runForEachK(new AlgRunner() {
@Override
public void run(int k, String kstr) {
- LoOP<O, D> loop = new LoOP<O, D>(k, k, distf, distf, 1.0);
+ LoOP<O, D> loop = new LoOP<>(k, k, distf, distf, 1.0);
OutlierResult loopresult = loop.run(database, relation);
- writeResult(fout, ids, loopresult, new IdentityScaling(), "LOOP-" + kstr);
- detachResult(database, loopresult);
+ writeResult(fout, ids, loopresult, scaling, "LOOP-" + kstr);
+ database.getHierarchy().removeSubtree(loopresult);
}
});
// LDOF
+ boolean runldof = false;
+ if (runldof) {
LOG.verbose("Running LDOF");
runForEachK(new AlgRunner() {
@Override
public void run(int k, String kstr) {
- LDOF<O, D> ldof = new LDOF<O, D>(distf, k);
+ LDOF<O, D> ldof = new LDOF<>(distf, k + 1);
OutlierResult ldofresult = ldof.run(database, relation);
- // Setup scaling
- StandardDeviationScaling scaling = new StandardDeviationScaling(1.0, 1.0);
- scaling.prepare(ldofresult);
writeResult(fout, ids, ldofresult, scaling, "LDOF-" + kstr);
- detachResult(database, ldofresult);
+ database.getHierarchy().removeSubtree(ldofresult);
+ }
+ });}
+ // Run LDF
+ LOG.verbose("Running LDF");
+ runForEachK(new AlgRunner() {
+ @Override
+ public void run(int k, String kstr) {
+ LDF<O, D> ldf = new LDF<>(k, distf, GaussianKernelDensityFunction.KERNEL, 2, .1);
+ OutlierResult ldfresult = ldf.run(database, relation);
+ writeResult(fout, ids, ldfresult, scaling, "LDF-" + kstr);
+ database.getHierarchy().removeSubtree(ldfresult);
}
});
// ABOD
- if(runabod && relation.size() < 10000) {
+ if (runabod && relation.size() < 10000) {
try {
final PolynomialKernelFunction poly = new PolynomialKernelFunction(PolynomialKernelFunction.DEFAULT_DEGREE);
@SuppressWarnings("unchecked")
@@ -288,17 +312,13 @@ public class ComputeKNNOutlierScores<O, D extends NumberDistance<D, ?>> extends
runForEachK(new AlgRunner() {
@Override
public void run(int k, String kstr) {
- ABOD<DoubleVector> abod = new ABOD<DoubleVector>(k, poly, df);
+ ABOD<DoubleVector> abod = new ABOD<>(k, poly, df);
OutlierResult abodresult = abod.run(database);
- // Setup scaling
- StandardDeviationScaling scaling = new MinusLogStandardDeviationScaling(null, 1.0);
- scaling.prepare(abodresult);
writeResult(fout, ids, abodresult, scaling, "ABOD-" + kstr);
- detachResult(database, abodresult);
+ database.getHierarchy().removeSubtree(abodresult);
}
});
- }
- catch(ClassCastException e) {
+ } catch (ClassCastException e) {
// ABOD might just be not appropriate.
LOG.warning("Running ABOD failed - probably not appropriate to this data type / distance?", e);
}
@@ -306,33 +326,26 @@ public class ComputeKNNOutlierScores<O, D extends NumberDistance<D, ?>> extends
}
/**
- * Avoid that (future changes?) keep a reference to the result.
- *
- * @param database Database
- * @param discardresult Result to discard.
- */
- void detachResult(Database database, OutlierResult discardresult) {
- final ResultHierarchy hier = database.getHierarchy();
- for(Result parent : hier.getParents(discardresult)) {
- hier.remove(parent, discardresult);
- }
- }
-
- /**
* Write a single output line.
*
* @param out Output stream
* @param ids DBIDs
* @param result Outlier result
- * @param scaling Scaling function.
+ * @param scaling Scaling function
* @param label Identification label
*/
void writeResult(PrintStream out, DBIDs ids, OutlierResult result, ScalingFunction scaling, String label) {
+ if (scaling instanceof OutlierScalingFunction) {
+ ((OutlierScalingFunction) scaling).prepare(result);
+ }
out.append(label);
Relation<Double> scores = result.getScores();
for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
- final double value = scaling.getScaled(scores.get(iter));
- out.append(" ").append(FormatUtil.format(value, FormatUtil.NF8));
+ double value = scores.get(iter);
+ if (scaling != null) {
+ value = scaling.getScaled(value);
+ }
+ out.append(' ').append(FormatUtil.NF.format(value));
}
out.append(FormatUtil.NEWLINE);
}
@@ -345,7 +358,7 @@ public class ComputeKNNOutlierScores<O, D extends NumberDistance<D, ?>> extends
private void runForEachK(AlgRunner runner) {
final int digits = (int) Math.ceil(Math.log10(maxk));
final int startk = (this.startk > 0) ? this.startk : this.stepk;
- for(int k = startk; k <= maxk; k += stepk) {
+ for (int k = startk; k <= maxk; k += stepk) {
String kstr = String.format("%0" + digits + "d", k);
runner.run(k, kstr);
}
@@ -369,7 +382,7 @@ public class ComputeKNNOutlierScores<O, D extends NumberDistance<D, ?>> extends
*
* @apiviz.exclude
*/
- public static class Parameterizer<O, D extends NumberDistance<D, ?>> extends AbstractApplication.Parameterizer {
+ public static class Parameterizer<O extends NumberVector<?>, D extends NumberDistance<D, ?>> extends AbstractApplication.Parameterizer {
/**
* Option ID for k step size.
*/
@@ -386,6 +399,11 @@ public class ComputeKNNOutlierScores<O, D extends NumberDistance<D, ?>> extends
public static final OptionID MAXK_ID = new OptionID("maxk", "Maximum value for k.");
/**
+ * Option ID for scaling class
+ */
+ public static final OptionID SCALING_ID = new OptionID("scaling", "Scaling function.");
+
+ /**
* k step size
*/
int stepk;
@@ -416,6 +434,11 @@ public class ComputeKNNOutlierScores<O, D extends NumberDistance<D, ?>> extends
ByLabelOutlier bylabel;
/**
+ * Scaling function.
+ */
+ ScalingFunction scaling = null;
+
+ /**
* Output destination file
*/
File outfile;
@@ -427,36 +450,41 @@ public class ComputeKNNOutlierScores<O, D extends NumberDistance<D, ?>> extends
inputstep = config.tryInstantiate(InputStep.class);
// Distance function
ObjectParameter<DistanceFunction<? super O, D>> distP = AbstractAlgorithm.makeParameterDistanceFunction(EuclideanDistanceFunction.class, DistanceFunction.class);
- if(config.grab(distP)) {
+ if (config.grab(distP)) {
distf = distP.instantiateClass(config);
}
// k parameters
IntParameter stepkP = new IntParameter(STEPK_ID);
stepkP.addConstraint(new GreaterConstraint(0));
- if(config.grab(stepkP)) {
+ if (config.grab(stepkP)) {
stepk = stepkP.getValue();
}
IntParameter startkP = new IntParameter(STARTK_ID);
startkP.setOptional(true);
- if(config.grab(startkP)) {
+ if (config.grab(startkP)) {
startk = startkP.getValue();
- }
- else {
+ } else {
startk = stepk;
}
IntParameter maxkP = new IntParameter(MAXK_ID);
maxkP.addConstraint(new GreaterConstraint(0));
- if(config.grab(maxkP)) {
+ if (config.grab(maxkP)) {
maxk = maxkP.getValue();
}
bylabel = config.tryInstantiate(ByLabelOutlier.class);
// Output
outfile = super.getParameterOutputFile(config, "File to output the resulting score vectors to.");
+
+ ObjectParameter<ScalingFunction> scalingP = new ObjectParameter<>(SCALING_ID, ScalingFunction.class);
+ scalingP.setOptional(true);
+ if (config.grab(scalingP)) {
+ scaling = scalingP.instantiateClass(config);
+ }
}
@Override
- protected AbstractApplication makeInstance() {
- return new ComputeKNNOutlierScores<O, D>(inputstep, distf, startk, stepk, maxk, bylabel, outfile);
+ protected ComputeKNNOutlierScores<O, D> makeInstance() {
+ return new ComputeKNNOutlierScores<>(inputstep, distf, startk, stepk, maxk, bylabel, outfile, scaling);
}
}
@@ -466,6 +494,6 @@ public class ComputeKNNOutlierScores<O, D extends NumberDistance<D, ?>> extends
* @param args Command line parameters.
*/
public static void main(String[] args) {
- ComputeKNNOutlierScores.runCLIApplication(ComputeKNNOutlierScores.class, args);
+ runCLIApplication(ComputeKNNOutlierScores.class, args);
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/application/greedyensemble/GreedyEnsembleExperiment.java b/src/de/lmu/ifi/dbs/elki/application/greedyensemble/GreedyEnsembleExperiment.java
index f3f9c101..ab4bf001 100644
--- a/src/de/lmu/ifi/dbs/elki/application/greedyensemble/GreedyEnsembleExperiment.java
+++ b/src/de/lmu/ifi/dbs/elki/application/greedyensemble/GreedyEnsembleExperiment.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.application.greedyensemble;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,15 +23,17 @@ package de.lmu.ifi.dbs.elki.application.greedyensemble;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
-import java.util.Set;
-import java.util.TreeSet;
import de.lmu.ifi.dbs.elki.application.AbstractApplication;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
import de.lmu.ifi.dbs.elki.database.Database;
+import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory;
+import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
+import de.lmu.ifi.dbs.elki.database.datastore.WritableDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
@@ -40,21 +42,33 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDPair;
import de.lmu.ifi.dbs.elki.database.ids.HashSetModifiableDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.database.relation.RelationUtil;
import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.WeightedPearsonCorrelationDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.WeightedEuclideanDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.WeightedManhattanDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.WeightedSquaredEuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.evaluation.roc.ROC;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.math.MeanVariance;
import de.lmu.ifi.dbs.elki.math.geometry.XYCurve;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
import de.lmu.ifi.dbs.elki.utilities.DatabaseUtil;
-import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.TiedTopBoundedHeap;
-import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.TopBoundedHeap;
+import de.lmu.ifi.dbs.elki.utilities.FormatUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayLikeUtil;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.ensemble.EnsembleVoting;
+import de.lmu.ifi.dbs.elki.utilities.ensemble.EnsembleVotingMean;
import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
-import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleIntPair;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleParameter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.EnumParameter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
+import de.lmu.ifi.dbs.elki.utilities.scaling.ScalingFunction;
+import de.lmu.ifi.dbs.elki.utilities.scaling.outlier.OutlierScalingFunction;
import de.lmu.ifi.dbs.elki.workflow.InputStep;
/**
@@ -101,71 +115,124 @@ public class GreedyEnsembleExperiment extends AbstractApplication {
boolean refine_truth = false;
/**
+ * Ensemble voting method.
+ */
+ EnsembleVoting voting;
+
+ /**
+ * Outlier scaling to apply during preprocessing.
+ */
+ ScalingFunction prescaling;
+
+ /**
+ * Outlier scaling to apply to constructed ensembles.
+ */
+ ScalingFunction scaling;
+
+ /**
+ * Expected rate of outliers.
+ */
+ double rate;
+
+ /**
+ * Minimum votes.
+ */
+ int minvote = 1;
+
+ /**
+ * Distance modes.
+ *
+ * @apiviz.exclude
+ */
+ public static enum Distance {
+ PEARSON, //
+ SQEUCLIDEAN, //
+ EUCLIDEAN, //
+ MANHATTAN, //
+ }
+
+ /**
+ * Distance in use.
+ */
+ Distance distance = Distance.PEARSON;
+
+ /**
* Constructor.
*
* @param inputstep Input step
+ * @param voting Ensemble voting
+ * @param distance Distance function
+ * @param prescaling Scaling to apply to input data
+ * @param scaling Scaling to apply to ensemble members
+ * @param rate Expected rate of outliers
*/
- public GreedyEnsembleExperiment(InputStep inputstep) {
+ public GreedyEnsembleExperiment(InputStep inputstep, EnsembleVoting voting, Distance distance, ScalingFunction prescaling, ScalingFunction scaling, double rate) {
super();
this.inputstep = inputstep;
+ this.voting = voting;
+ this.distance = distance;
+ this.prescaling = prescaling;
+ this.scaling = scaling;
+ this.rate = rate;
}
@Override
public void run() {
- // Note: the database contains the *result vectors*, not the original data
- // points.
+ // Note: the database contains the *result vectors*, not the original data.
final Database database = inputstep.getDatabase();
- final Relation<NumberVector<?>> relation = database.getRelation(TypeUtil.NUMBER_VECTOR_FIELD);
+ Relation<NumberVector<?>> relation = database.getRelation(TypeUtil.NUMBER_VECTOR_FIELD);
final NumberVector.Factory<NumberVector<?>, ?> factory = RelationUtil.getNumberVectorFactory(relation);
final Relation<String> labels = DatabaseUtil.guessLabelRepresentation(database);
final DBID firstid = DBIDUtil.deref(labels.iterDBIDs());
final String firstlabel = labels.get(firstid);
- if(!firstlabel.matches("bylabel")) {
+ if (!firstlabel.matches("bylabel")) {
throw new AbortException("No 'by label' reference outlier found, which is needed for weighting!");
}
+ relation = applyPrescaling(prescaling, relation, firstid);
+ final int numcand = relation.size() - 1;
// Dimensionality and reference vector
final int dim = RelationUtil.dimensionality(relation);
final NumberVector<?> refvec = relation.get(firstid);
// Build the positive index set for ROC AUC.
- Set<Integer> positive = new TreeSet<Integer>();
- for(int d = 0; d < dim; d++) {
- if(refvec.doubleValue(d) > 0) {
- positive.add(d);
- }
- }
+ ROC.Predicate<ROC.DecreasingVectorIter> positive = new ROC.VectorNonZero(refvec);
- final int estimated_outliers = (int) (0.005 * dim);
+ final int desired_outliers = (int) (rate * dim);
int union_outliers = 0;
final int[] outliers_seen = new int[dim];
- // Find the top-k for each ensemble member
+ // Merge the top-k for each ensemble member, until we have enough
+ // candidates.
{
- for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
+ int k = 0;
+ ArrayList<ROC.DecreasingVectorIter> iters = new ArrayList<>(numcand);
+ if (minvote >= numcand) {
+ minvote = Math.max(1, numcand - 1);
+ }
+ for (DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
// Skip "by label", obviously
- if(DBIDUtil.equal(firstid, iditer)) {
+ if (DBIDUtil.equal(firstid, iditer)) {
continue;
}
- final NumberVector<?> vec = relation.get(iditer);
- TiedTopBoundedHeap<DoubleIntPair> heap = new TiedTopBoundedHeap<DoubleIntPair>(estimated_outliers, Collections.reverseOrder());
- for(int i = 0; i < dim; i++) {
- heap.add(new DoubleIntPair(vec.doubleValue(i), i));
- }
- if(heap.size() >= 2 * estimated_outliers) {
- LOG.warning("Too many ties. Expected: " + estimated_outliers + " got: " + heap.size());
- }
- for(DoubleIntPair pair : heap) {
- if(outliers_seen[pair.second] == 0) {
- outliers_seen[pair.second] = 1;
- union_outliers += 1;
+ iters.add(new ROC.DecreasingVectorIter(relation.get(iditer)));
+ }
+ loop: while (union_outliers < desired_outliers) {
+ for (ROC.DecreasingVectorIter iter : iters) {
+ if (!iter.valid()) {
+ LOG.warning("Union_outliers=" + union_outliers + " < desired_outliers=" + desired_outliers + " minvote=" + minvote);
+ break loop;
}
- else {
- outliers_seen[pair.second] += 1;
+ int cur = iter.dim();
+ outliers_seen[cur] += 1;
+ if (outliers_seen[cur] == minvote) {
+ union_outliers += 1;
}
+ iter.advance();
}
+ k++;
}
+ LOG.verbose("Merged top " + k + " outliers to: " + union_outliers + " outliers (desired: at least " + desired_outliers + ")");
}
- LOG.verbose("Merged top " + estimated_outliers + " outliers to: " + union_outliers + " outliers");
// Build the final weight vector.
final double[] estimated_weights = new double[dim];
final double[] estimated_truth = new double[dim];
@@ -178,18 +245,22 @@ public class GreedyEnsembleExperiment extends AbstractApplication {
// Build the naive ensemble:
final double[] naiveensemble = new double[dim];
{
- for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
- if(DBIDUtil.equal(firstid, iditer)) {
- continue;
+ double[] buf = new double[numcand];
+ for (int d = 0; d < dim; d++) {
+ int i = 0;
+ for (DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
+ if (DBIDUtil.equal(firstid, iditer)) {
+ continue;
+ }
+ final NumberVector<?> vec = relation.get(iditer);
+ buf[i] = vec.doubleValue(d);
+ i++;
}
- final NumberVector<?> vec = relation.get(iditer);
- for(int d = 0; d < dim; d++) {
- naiveensemble[d] += vec.doubleValue(d);
+ naiveensemble[d] = voting.combine(buf, i);
+ if (Double.isNaN(naiveensemble[d])) {
+ LOG.warning("NaN after combining: " + FormatUtil.format(buf) + " i=" + i + " " + voting.toString());
}
}
- for(int d = 0; d < dim; d++) {
- naiveensemble[d] /= (relation.size() - 1);
- }
}
NumberVector<?> naivevec = factory.newNumberVector(naiveensemble);
@@ -202,26 +273,29 @@ public class GreedyEnsembleExperiment extends AbstractApplication {
DBID bestid = null;
double bestest = Double.POSITIVE_INFINITY;
{
+ final double[] greedyensemble = new double[dim];
// Compute individual scores
- for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
- if(DBIDUtil.equal(firstid, iditer)) {
+ for (DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
+ if (DBIDUtil.equal(firstid, iditer)) {
continue;
}
// fout.append(labels.get(id));
final NumberVector<?> vec = relation.get(iditer);
- double auc = computeROCAUC(vec, positive, dim);
- double estimated = wdist.doubleDistance(vec, estimated_truth_vec);
- double cost = tdist.doubleDistance(vec, refvec);
+ singleEnsemble(greedyensemble, vec);
+ final Vector v2 = new Vector(greedyensemble);
+ double auc = XYCurve.areaUnderCurve(ROC.materializeROC(positive, new ROC.DecreasingVectorIter(v2)));
+ double estimated = wdist.doubleDistance(v2, estimated_truth_vec);
+ double cost = tdist.doubleDistance(v2, refvec);
LOG.verbose("ROC AUC: " + auc + " estimated " + estimated + " cost " + cost + " " + labels.get(iditer));
- if(auc > bestauc) {
+ if (auc > bestauc) {
bestauc = auc;
bestaucstr = labels.get(iditer);
}
- if(cost < bestcost) {
+ if (cost < bestcost) {
bestcost = cost;
bestcoststr = labels.get(iditer);
}
- if(estimated < bestest) {
+ if (estimated < bestest || bestid == null) {
bestest = estimated;
bestid = DBIDUtil.deref(iditer);
}
@@ -229,75 +303,107 @@ public class GreedyEnsembleExperiment extends AbstractApplication {
}
// Initialize ensemble with "best" method
+ if (prescaling != null) {
+ LOG.verbose("Input prescaling: " + prescaling);
+ }
LOG.verbose("Distance function: " + wdist);
+ LOG.verbose("Ensemble voting: " + voting);
+ if (scaling != null) {
+ LOG.verbose("Ensemble rescaling: " + scaling);
+ }
LOG.verbose("Initial estimation of outliers: " + union_outliers);
LOG.verbose("Initializing ensemble with: " + labels.get(bestid));
ModifiableDBIDs ensemble = DBIDUtil.newArray(bestid);
ModifiableDBIDs enscands = DBIDUtil.newHashSet(relation.getDBIDs());
+ ModifiableDBIDs dropped = DBIDUtil.newHashSet(relation.size());
+ dropped.add(firstid);
enscands.remove(bestid);
enscands.remove(firstid);
final double[] greedyensemble = new double[dim];
- {
- final NumberVector<?> vec = relation.get(bestid);
- for(int i = 0; i < dim; i++) {
- greedyensemble[i] = vec.doubleValue(i);
- }
- }
+ singleEnsemble(greedyensemble, relation.get(bestid));
// Greedily grow the ensemble
final double[] testensemble = new double[dim];
- while(enscands.size() > 0) {
+ while (enscands.size() > 0) {
NumberVector<?> greedyvec = factory.newNumberVector(greedyensemble);
-
- // Weighting factors for combining:
- double s1 = ensemble.size() / (ensemble.size() + 1.);
- double s2 = 1. / (ensemble.size() + 1.);
+ final double oldd = wdist.doubleDistance(estimated_truth_vec, greedyvec);
final int heapsize = enscands.size();
- TopBoundedHeap<DoubleDBIDPair> heap = new TopBoundedHeap<DoubleDBIDPair>(heapsize, Collections.reverseOrder());
+ ArrayList<DoubleDBIDPair> heap = new ArrayList<>(heapsize);
+ double[] tmp = new double[dim];
for (DBIDIter iter = enscands.iter(); iter.valid(); iter.advance()) {
final NumberVector<?> vec = relation.get(iter);
- double diversity = wdist.doubleDistance(vec, greedyvec);
+ singleEnsemble(tmp, vec);
+ final Vector v2 = new Vector(greedyensemble);
+ double diversity = wdist.doubleDistance(v2, greedyvec);
heap.add(DBIDUtil.newPair(diversity, iter));
}
- while(heap.size() > 0) {
- DBIDRef bestadd = heap.poll();
+ Collections.sort(heap); // , Collections.reverseOrder());
+ while (heap.size() > 0) {
+ DBIDRef bestadd = heap.remove(heap.size() - 1);
enscands.remove(bestadd);
- // Update ensemble:
final NumberVector<?> vec = relation.get(bestadd);
- for(int i = 0; i < dim; i++) {
- testensemble[i] = greedyensemble[i] * s1 + vec.doubleValue(i) * s2;
+ // Build combined ensemble.
+ {
+ double buf[] = new double[ensemble.size() + 1];
+ for (int i = 0; i < dim; i++) {
+ int j = 0;
+ for (DBIDIter iter = ensemble.iter(); iter.valid(); iter.advance()) {
+ buf[j] = relation.get(iter).doubleValue(i);
+ j++;
+ }
+ buf[j] = vec.doubleValue(i);
+ testensemble[i] = voting.combine(buf, j + 1);
+ }
}
+ applyScaling(testensemble, scaling);
NumberVector<?> testvec = factory.newNumberVector(testensemble);
- double oldd = wdist.doubleDistance(estimated_truth_vec, greedyvec);
double newd = wdist.doubleDistance(estimated_truth_vec, testvec);
- // logger.verbose("Distances: " + oldd + " vs. " + newd);
- if(newd < oldd) {
+ // LOG.verbose("Distances: " + oldd + " vs. " + newd + " " +
+ // labels.get(bestadd));
+ if (newd < oldd) {
System.arraycopy(testensemble, 0, greedyensemble, 0, dim);
ensemble.add(bestadd);
// logger.verbose("Growing ensemble with: " + labels.get(bestadd));
break; // Recompute heap
- }
- else {
+ } else {
+ dropped.add(bestadd);
// logger.verbose("Discarding: " + labels.get(bestadd));
- if(refine_truth) {
- boolean refresh = false;
+ if (refine_truth) {
// Update target vectors and weights
- TiedTopBoundedHeap<DoubleIntPair> oheap = new TiedTopBoundedHeap<DoubleIntPair>(estimated_outliers, Collections.reverseOrder());
- for(int i = 0; i < dim; i++) {
- oheap.add(new DoubleIntPair(vec.doubleValue(i), i));
- }
- for(DoubleIntPair pair : oheap) {
- assert (outliers_seen[pair.second] > 0);
- outliers_seen[pair.second] -= 1;
- if(outliers_seen[pair.second] == 0) {
- union_outliers -= 1;
- refresh = true;
+ ArrayList<ROC.DecreasingVectorIter> iters = new ArrayList<>(numcand);
+ for (DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
+ // Skip "by label", obviously
+ if (DBIDUtil.equal(firstid, iditer) || dropped.contains(iditer)) {
+ continue;
}
+ iters.add(new ROC.DecreasingVectorIter(relation.get(iditer)));
}
- if(refresh) {
- updateEstimations(outliers_seen, union_outliers, estimated_weights, estimated_truth);
- estimated_truth_vec = factory.newNumberVector(estimated_truth);
+ if (minvote >= iters.size()) {
+ minvote = iters.size() - 1;
}
+
+ union_outliers = 0;
+ Arrays.fill(outliers_seen, 0);
+ while (union_outliers < desired_outliers) {
+ for (ROC.DecreasingVectorIter iter : iters) {
+ if (!iter.valid()) {
+ break;
+ }
+ int cur = iter.dim();
+ if (outliers_seen[cur] == 0) {
+ outliers_seen[cur] = 1;
+ } else {
+ outliers_seen[cur] += 1;
+ }
+ if (outliers_seen[cur] == minvote) {
+ union_outliers += 1;
+ }
+ iter.advance();
+ }
+ }
+ LOG.warning("New num outliers: " + union_outliers);
+ updateEstimations(outliers_seen, union_outliers, estimated_weights, estimated_truth);
+ estimated_truth_vec = factory.newNumberVector(estimated_truth);
}
}
}
@@ -306,29 +412,31 @@ public class GreedyEnsembleExperiment extends AbstractApplication {
StringBuilder greedylbl = new StringBuilder();
{
for (DBIDIter iter = ensemble.iter(); iter.valid(); iter.advance()) {
- if(greedylbl.length() > 0) {
- greedylbl.append(" ");
+ if (greedylbl.length() > 0) {
+ greedylbl.append(' ');
}
greedylbl.append(labels.get(iter));
}
}
NumberVector<?> greedyvec = factory.newNumberVector(greedyensemble);
- LOG.verbose("Estimated outliers remaining: " + union_outliers);
- LOG.verbose("Greedy ensemble: " + greedylbl.toString());
+ if (refine_truth) {
+ LOG.verbose("Estimated outliers remaining: " + union_outliers);
+ }
+ LOG.verbose("Greedy ensemble (" + ensemble.size() + "): " + greedylbl.toString());
LOG.verbose("Best single ROC AUC: " + bestauc + " (" + bestaucstr + ")");
LOG.verbose("Best single cost: " + bestcost + " (" + bestcoststr + ")");
// Evaluate the naive ensemble and the "shrunk" ensemble
double naiveauc, naivecost;
{
- naiveauc = computeROCAUC(naivevec, positive, dim);
+ naiveauc = XYCurve.areaUnderCurve(ROC.materializeROC(positive, new ROC.DecreasingVectorIter(naivevec)));
naivecost = tdist.doubleDistance(naivevec, refvec);
LOG.verbose("Naive ensemble AUC: " + naiveauc + " cost: " + naivecost);
LOG.verbose("Naive ensemble Gain: " + gain(naiveauc, bestauc, 1) + " cost gain: " + gain(naivecost, bestcost, 0));
}
double greedyauc, greedycost;
{
- greedyauc = computeROCAUC(greedyvec, positive, dim);
+ greedyauc = XYCurve.areaUnderCurve(ROC.materializeROC(positive, new ROC.DecreasingVectorIter(greedyvec)));
greedycost = tdist.doubleDistance(greedyvec, refvec);
LOG.verbose("Greedy ensemble AUC: " + greedyauc + " cost: " + greedycost);
LOG.verbose("Greedy ensemble Gain to best: " + gain(greedyauc, bestauc, 1) + " cost gain: " + gain(greedycost, bestcost, 0));
@@ -339,25 +447,26 @@ public class GreedyEnsembleExperiment extends AbstractApplication {
MeanVariance meancost = new MeanVariance();
HashSetModifiableDBIDs candidates = DBIDUtil.newHashSet(relation.getDBIDs());
candidates.remove(firstid);
- for(int i = 0; i < 5000; i++) {
+ for (int i = 0; i < 1000; i++) {
// Build the improved ensemble:
final double[] randomensemble = new double[dim];
{
- DBIDs random = DBIDUtil.randomSample(candidates, ensemble.size(), (long)i);
- for (DBIDIter iter = random.iter(); iter.valid(); iter.advance()) {
- assert (!DBIDUtil.equal(firstid, iter));
- // logger.verbose("Using: "+labels.get(id));
- final NumberVector<?> vec = relation.get(iter);
- for(int d = 0; d < dim; d++) {
- randomensemble[d] += vec.doubleValue(d);
+ DBIDs random = DBIDUtil.randomSample(candidates, ensemble.size(), (long) i);
+ double[] buf = new double[random.size()];
+ for (int d = 0; d < dim; d++) {
+ int j = 0;
+ for (DBIDIter iter = random.iter(); iter.valid(); iter.advance()) {
+ assert (!DBIDUtil.equal(firstid, iter));
+ final NumberVector<?> vec = relation.get(iter);
+ buf[j] = vec.doubleValue(d);
+ j++;
}
- }
- for(int d = 0; d < dim; d++) {
- randomensemble[d] /= ensemble.size();
+ randomensemble[d] = voting.combine(buf, j);
}
}
+ applyScaling(randomensemble, scaling);
NumberVector<?> randomvec = factory.newNumberVector(randomensemble);
- double auc = computeROCAUC(randomvec, positive, dim);
+ double auc = XYCurve.areaUnderCurve(ROC.materializeROC(positive, new ROC.DecreasingVectorIter(randomvec)));
meanauc.put(auc);
double cost = tdist.doubleDistance(randomvec, refvec);
meancost.put(cost);
@@ -374,32 +483,97 @@ public class GreedyEnsembleExperiment extends AbstractApplication {
}
}
- protected void updateEstimations(final int[] outliers_seen, int union_outliers, final double[] estimated_weights, final double[] estimated_truth) {
- for(int i = 0; i < outliers_seen.length; i++) {
- if(outliers_seen[i] > 0) {
- estimated_weights[i] = 0.5 / union_outliers;
- estimated_truth[i] = 1.0;
+ /**
+ * Build a single-element "ensemble".
+ *
+ * @param ensemble
+ * @param vec
+ */
+ protected void singleEnsemble(final double[] ensemble, final NumberVector<?> vec) {
+ double buf[] = new double[1];
+ for (int i = 0; i < ensemble.length; i++) {
+ buf[0] = vec.doubleValue(i);
+ ensemble[i] = voting.combine(buf, 1);
+ if (Double.isNaN(ensemble[i])) {
+ LOG.warning("NaN after combining: " + FormatUtil.format(buf) + " " + voting.toString());
+ }
+ }
+ applyScaling(ensemble, scaling);
+ }
+
+ /**
+ * Prescale each vector (except when in {@code skip}) with the given scaling
+ * function.
+ *
+ * @param scaling Scaling function
+ * @param relation Relation to read
+ * @param skip DBIDs to pass unmodified
+ * @return New relation
+ */
+ public static Relation<NumberVector<?>> applyPrescaling(ScalingFunction scaling, Relation<NumberVector<?>> relation, DBIDs skip) {
+ if (scaling == null) {
+ return relation;
+ }
+ NumberVector.Factory<NumberVector<?>, ?> factory = (NumberVector.Factory<NumberVector<?>, ?>) RelationUtil.assumeVectorField(relation).getFactory();
+ DBIDs ids = relation.getDBIDs();
+ WritableDataStore<NumberVector<?>> contents = DataStoreUtil.makeStorage(ids, DataStoreFactory.HINT_HOT, NumberVector.class);
+ for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
+ NumberVector<?> v = relation.get(iter);
+ double[] raw = v.getColumnVector().getArrayRef();
+ if (!skip.contains(iter)) {
+ applyScaling(raw, scaling);
}
- else {
- estimated_weights[i] = 0.5 / (outliers_seen.length - union_outliers);
- estimated_truth[i] = 0.0;
+ contents.put(iter, factory.newNumberVector(raw, ArrayLikeUtil.DOUBLEARRAYADAPTER));
+ }
+ return new MaterializedRelation<>(relation.getDatabase(), relation.getDataTypeInformation(), ids, "rescaled", contents);
+ }
+
+ private static void applyScaling(double[] raw, ScalingFunction scaling) {
+ if (scaling == null) {
+ return;
+ }
+ if (scaling instanceof OutlierScalingFunction) {
+ ((OutlierScalingFunction) scaling).prepare(raw, ArrayLikeUtil.DOUBLEARRAYADAPTER);
+ }
+ for (int i = 0; i < raw.length; i++) {
+ final double newval = scaling.getScaled(raw[i]);
+ if (Double.isNaN(newval)) {
+ LOG.warning("NaN after prescaling: " + raw[i] + " " + scaling.toString() + " -> " + newval);
}
+ raw[i] = newval;
}
}
- private PrimitiveDoubleDistanceFunction<NumberVector<?>> getDistanceFunction(double[] estimated_weights) {
- // return new WeightedSquaredEuclideanDistanceFunction(estimated_weights);
- // return new WeightedLPNormDistanceFunction(1.0, estimated_weights);
- return new WeightedPearsonCorrelationDistanceFunction(estimated_weights);
+ protected void updateEstimations(final int[] outliers, int numoutliers, final double[] weights, final double[] truth) {
+ final double oweight = .5 / numoutliers;
+ final double iweight = .5 / (outliers.length - numoutliers);
+ // final double orate = union_outliers * 1.0 / (outliers_seen.length);
+ final double oscore = 1.; // .5 - .5 * orate;
+ final double iscore = 0.; // 1 - .5 * orate;
+ for (int i = 0; i < outliers.length; i++) {
+ if (outliers[i] >= minvote) {
+ weights[i] = oweight;
+ truth[i] = oscore;
+ } else {
+ weights[i] = iweight;
+ truth[i] = iscore;
+ }
+ }
}
- private double computeROCAUC(NumberVector<?> vec, Set<Integer> positive, int dim) {
- final DoubleIntPair[] scores = new DoubleIntPair[dim];
- for(int d = 0; d < dim; d++) {
- scores[d] = new DoubleIntPair(vec.doubleValue(d), d);
+ private PrimitiveDoubleDistanceFunction<NumberVector<?>> getDistanceFunction(double[] estimated_weights) {
+ switch(distance) {
+ case SQEUCLIDEAN:
+ return new WeightedSquaredEuclideanDistanceFunction(estimated_weights);
+ case EUCLIDEAN:
+ return new WeightedEuclideanDistanceFunction(estimated_weights);
+ case MANHATTAN:
+ return new WeightedManhattanDistanceFunction(estimated_weights);
+ case PEARSON:
+ return new WeightedPearsonCorrelationDistanceFunction(estimated_weights);
+ default:
+ throw new AbortException("Unsupported distance mode: " + distance);
}
- Arrays.sort(scores, Collections.reverseOrder(DoubleIntPair.BYFIRST_COMPARATOR));
- return XYCurve.areaUnderCurve(ROC.materializeROC(dim, positive, Arrays.asList(scores).iterator()));
}
/**
@@ -423,20 +597,97 @@ public class GreedyEnsembleExperiment extends AbstractApplication {
*/
public static class Parameterizer extends AbstractApplication.Parameterizer {
/**
+ * Expected rate of outliers
+ */
+ public static final OptionID RATE_ID = new OptionID("greedy.rate", "Expected rate of outliers.");
+
+ /**
+ * Ensemble voting function.
+ */
+ public static final OptionID VOTING_ID = new OptionID("ensemble.voting", "Ensemble voting function.");
+
+ /**
+ * Scaling to apply to input scores.
+ */
+ public static final OptionID PRESCALING_ID = new OptionID("ensemble.prescaling", "Prescaling to apply to input scores.");
+
+ /**
+ * Scaling to apply to ensemble scores.
+ */
+ public static final OptionID SCALING_ID = new OptionID("ensemble.scaling", "Scaling to apply to ensemble.");
+
+ /**
+ * Similarity measure
+ */
+ public static final OptionID DISTANCE_ID = new OptionID("ensemble.measure", "Similarity measure.");
+
+ /**
* Data source.
*/
InputStep inputstep;
+ /**
+ * Ensemble voting method.
+ */
+ EnsembleVoting voting;
+
+ /**
+ * Distance in use.
+ */
+ Distance distance = Distance.PEARSON;
+
+ /**
+ * Outlier scaling to apply during preprocessing.
+ */
+ ScalingFunction prescaling;
+
+ /**
+ * Outlier scaling to apply to constructed ensembles.
+ */
+ ScalingFunction scaling;
+
+ /**
+ * Expected rate of outliers
+ */
+ double rate = 0.01;
+
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
// Data input
inputstep = config.tryInstantiate(InputStep.class);
+ // Voting method
+ ObjectParameter<EnsembleVoting> votingP = new ObjectParameter<>(VOTING_ID, EnsembleVoting.class, EnsembleVotingMean.class);
+ if (config.grab(votingP)) {
+ voting = votingP.instantiateClass(config);
+ }
+ // Similarity measure
+ EnumParameter<Distance> distanceP = new EnumParameter<>(DISTANCE_ID, Distance.class);
+ if (config.grab(distanceP)) {
+ distance = distanceP.getValue();
+ }
+ // Prescaling
+ ObjectParameter<ScalingFunction> prescalingP = new ObjectParameter<>(PRESCALING_ID, ScalingFunction.class);
+ prescalingP.setOptional(true);
+ if (config.grab(prescalingP)) {
+ prescaling = prescalingP.instantiateClass(config);
+ }
+ // Ensemble scaling
+ ObjectParameter<ScalingFunction> scalingP = new ObjectParameter<>(SCALING_ID, ScalingFunction.class);
+ scalingP.setOptional(true);
+ if (config.grab(scalingP)) {
+ scaling = scalingP.instantiateClass(config);
+ }
+ // Expected rate of outliers
+ DoubleParameter rateP = new DoubleParameter(RATE_ID, 0.01);
+ if (config.grab(rateP)) {
+ rate = rateP.doubleValue();
+ }
}
@Override
- protected AbstractApplication makeInstance() {
- return new GreedyEnsembleExperiment(inputstep);
+ protected GreedyEnsembleExperiment makeInstance() {
+ return new GreedyEnsembleExperiment(inputstep, voting, distance, prescaling, scaling, rate);
}
}
@@ -446,6 +697,6 @@ public class GreedyEnsembleExperiment extends AbstractApplication {
* @param args Command line parameters.
*/
public static void main(String[] args) {
- GreedyEnsembleExperiment.runCLIApplication(GreedyEnsembleExperiment.class, args);
+ runCLIApplication(GreedyEnsembleExperiment.class, args);
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/application/greedyensemble/VisualizePairwiseGainMatrix.java b/src/de/lmu/ifi/dbs/elki/application/greedyensemble/VisualizePairwiseGainMatrix.java
index afb9c122..3ef30c10 100644
--- a/src/de/lmu/ifi/dbs/elki/application/greedyensemble/VisualizePairwiseGainMatrix.java
+++ b/src/de/lmu/ifi/dbs/elki/application/greedyensemble/VisualizePairwiseGainMatrix.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.application.greedyensemble;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,11 +24,7 @@ package de.lmu.ifi.dbs.elki.application.greedyensemble;
*/
import java.awt.image.BufferedImage;
-import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
-import java.util.Set;
-import java.util.TreeSet;
import org.apache.batik.util.SVGConstants;
@@ -47,15 +43,20 @@ import de.lmu.ifi.dbs.elki.evaluation.roc.ROC;
import de.lmu.ifi.dbs.elki.evaluation.similaritymatrix.ComputeSimilarityMatrixImage;
import de.lmu.ifi.dbs.elki.evaluation.similaritymatrix.ComputeSimilarityMatrixImage.SimilarityMatrix;
import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
import de.lmu.ifi.dbs.elki.math.geometry.XYCurve;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
import de.lmu.ifi.dbs.elki.result.ResultUtil;
import de.lmu.ifi.dbs.elki.utilities.DatabaseUtil;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.ensemble.EnsembleVoting;
+import de.lmu.ifi.dbs.elki.utilities.ensemble.EnsembleVotingMean;
import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
-import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleIntPair;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
import de.lmu.ifi.dbs.elki.utilities.scaling.LinearScaling;
+import de.lmu.ifi.dbs.elki.utilities.scaling.ScalingFunction;
import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
import de.lmu.ifi.dbs.elki.visualization.VisualizerContext;
import de.lmu.ifi.dbs.elki.visualization.VisualizerParameterizer;
@@ -105,88 +106,102 @@ public class VisualizePairwiseGainMatrix extends AbstractApplication {
private VisualizerParameterizer vispar;
/**
+ * Outlier scaling to apply during preprocessing.
+ */
+ private ScalingFunction prescaling;
+
+ /**
+ * Ensemble voting function.
+ */
+ private EnsembleVoting voting;
+
+ /**
* Constructor.
*
* @param inputstep Input step
+ * @param prescaling Scaling function for input scores.
+ * @param voting Voting function
* @param vispar Visualizer parameterizer
*/
- public VisualizePairwiseGainMatrix(InputStep inputstep, VisualizerParameterizer vispar) {
+ public VisualizePairwiseGainMatrix(InputStep inputstep, ScalingFunction prescaling, EnsembleVoting voting, VisualizerParameterizer vispar) {
super();
this.inputstep = inputstep;
+ this.prescaling = prescaling;
+ this.voting = voting;
this.vispar = vispar;
}
@Override
public void run() {
final Database database = inputstep.getDatabase();
- final Relation<NumberVector<?>> relation = database.getRelation(TypeUtil.NUMBER_VECTOR_FIELD);
+ Relation<NumberVector<?>> relation = database.getRelation(TypeUtil.NUMBER_VECTOR_FIELD);
final Relation<String> labels = DatabaseUtil.guessLabelRepresentation(database);
final DBID firstid = DBIDUtil.deref(labels.iterDBIDs());
final String firstlabel = labels.get(firstid);
- if(!firstlabel.matches("bylabel")) {
+ if (!firstlabel.matches(".*by.?label.*")) {
throw new AbortException("No 'by label' reference outlier found, which is needed for weighting!");
}
+ relation = GreedyEnsembleExperiment.applyPrescaling(prescaling, relation, firstid);
// Dimensionality and reference vector
final int dim = RelationUtil.dimensionality(relation);
final NumberVector<?> refvec = relation.get(firstid);
// Build the truth vector
- Set<Integer> pos = new TreeSet<Integer>();
- final DoubleIntPair[] combined = new DoubleIntPair[dim];
- {
- for(int d = 0; d < dim; d++) {
- combined[d] = new DoubleIntPair(0, d);
- if(refvec.doubleValue(d) > 0) {
- pos.add(d);
- }
- }
- }
+ ROC.VectorNonZero pos = new ROC.VectorNonZero(refvec);
ArrayModifiableDBIDs ids = DBIDUtil.newArray(relation.getDBIDs());
ids.remove(firstid);
+ ids.sort();
final int size = ids.size();
double[][] data = new double[size][size];
- DoubleMinMax minmax = new DoubleMinMax();
+ DoubleMinMax minmax = new DoubleMinMax(), commax = new DoubleMinMax();
{
+ FiniteProgress prog = LOG.isVerbose() ? new FiniteProgress("Computing ensemble gain.", size * (size + 1) >> 1, LOG) : null;
+ double[] buf = new double[2]; // Vote combination buffer.
int a = 0;
- for(DBIDIter id = ids.iter(); id.valid(); id.advance(), a++) {
+ for (DBIDIter id = ids.iter(); id.valid(); id.advance(), a++) {
final NumberVector<?> veca = relation.get(id);
// Direct AUC score:
{
- for(int d = 0; d < dim; d++) {
- combined[d].first = veca.doubleValue(d);
- combined[d].second = d;
- }
- Arrays.sort(combined, Collections.reverseOrder(DoubleIntPair.BYFIRST_COMPARATOR));
- double auc = XYCurve.areaUnderCurve(ROC.materializeROC(dim, pos, Arrays.asList(combined).iterator()));
+ double auc = XYCurve.areaUnderCurve(ROC.materializeROC(pos, new ROC.DecreasingVectorIter(veca)));
data[a][a] = auc;
// minmax.put(auc);
- // logger.verbose(auc + " " + labels.get(ids.get(a)));
+ if (prog != null) {
+ prog.incrementProcessed(LOG);
+ }
}
// Compare to others, exploiting symmetry
DBIDArrayIter id2 = ids.iter();
id2.seek(a + 1);
- for(int b = a + 1; b < size; b++, id2.advance()) {
+ for (int b = a + 1; b < size; b++, id2.advance()) {
final NumberVector<?> vecb = relation.get(id2);
- for(int d = 0; d < dim; d++) {
- combined[d].first = veca.doubleValue(d) + vecb.doubleValue(d);
- combined[d].second = d;
+ double[] combined = new double[dim];
+ for (int d = 0; d < dim; d++) {
+ buf[0] = veca.doubleValue(d);
+ buf[1] = vecb.doubleValue(d);
+ combined[d] = voting.combine(buf);
}
- Arrays.sort(combined, Collections.reverseOrder(DoubleIntPair.BYFIRST_COMPARATOR));
- double auc = XYCurve.areaUnderCurve(ROC.materializeROC(dim, pos, Arrays.asList(combined).iterator()));
+ double auc = XYCurve.areaUnderCurve(ROC.materializeROC(pos, new ROC.DecreasingVectorIter(new Vector(combined))));
// logger.verbose(auc + " " + labels.get(ids.get(a)) + " " +
// labels.get(ids.get(b)));
data[a][b] = auc;
data[b][a] = auc;
+ commax.put(data[a][b]);
// minmax.put(auc);
+ if (prog != null) {
+ prog.incrementProcessed(LOG);
+ }
}
}
+ if (prog != null) {
+ prog.ensureCompleted(LOG);
+ }
}
- for(int a = 0; a < size; a++) {
- for(int b = a + 1; b < size; b++) {
+ for (int a = 0; a < size; a++) {
+ for (int b = a + 1; b < size; b++) {
double ref = Math.max(data[a][a], data[b][b]);
data[a][b] = (data[a][b] - ref) / (1 - ref);
data[b][a] = (data[b][a] - ref) / (1 - ref);
@@ -195,42 +210,35 @@ public class VisualizePairwiseGainMatrix extends AbstractApplication {
minmax.put(data[a][b]);
}
}
- for(int a = 0; a < size; a++) {
+ for (int a = 0; a < size; a++) {
data[a][a] = 0;
}
- LOG.verbose(minmax.toString());
+ LOG.verbose("Gain: " + minmax.toString() + " AUC: " + commax.toString());
boolean hasneg = (minmax.getMin() < -1E-3);
LinearScaling scale;
- if(!hasneg) {
- scale = new LinearScaling(minmax);
- }
- else {
+ if (!hasneg) {
+ scale = LinearScaling.fromMinMax(0., minmax.getMax());
+ } else {
scale = LinearScaling.fromMinMax(0.0, Math.max(minmax.getMax(), -minmax.getMin()));
}
+ scale = LinearScaling.fromMinMax(0., .5);
BufferedImage img = new BufferedImage(size, size, BufferedImage.TYPE_INT_RGB);
- for(int x = 0; x < size; x++) {
- for(int y = x; y < size; y++) {
+ for (int x = 0; x < size; x++) {
+ for (int y = x; y < size; y++) {
double val = data[x][y];
- val = scale.getScaled(val);
+ val = Math.max(-1, Math.min(1., scale.getScaled(val)));
// Compute color:
final int col;
{
- if(!hasneg) {
- int ival = 0xFF & (int) (255 * Math.max(0, val));
- col = 0xff000000 | (ival << 16) | (ival << 8) | ival;
- }
- else {
- if(val >= 0) {
- int ival = 0xFF & (int) (255 * val);
- col = 0xff000000 | (ival << 8);
- }
- else {
- int ival = 0xFF & (int) (255 * -val);
- col = 0xff000000 | (ival << 16);
- }
+ if (val >= 0) {
+ int ival = 0xFF & (int) (255 * val);
+ col = 0xff000000 | (ival << 8);
+ } else {
+ int ival = 0xFF & (int) (255 * -val);
+ col = 0xff000000 | (ival << 16);
}
}
img.setRGB(x, y, col);
@@ -247,8 +255,8 @@ public class VisualizePairwiseGainMatrix extends AbstractApplication {
factory.processNewResult(database, database);
List<VisualizationTask> tasks = ResultUtil.filterResults(database, VisualizationTask.class);
- for(VisualizationTask task : tasks) {
- if(task.getFactory() == factory) {
+ for (VisualizationTask task : tasks) {
+ if (task.getFactory() == factory) {
showVisualization(context, factory, task);
}
}
@@ -284,13 +292,23 @@ public class VisualizePairwiseGainMatrix extends AbstractApplication {
/**
* Data source.
*/
- InputStep inputstep;
+ private InputStep inputstep;
/**
* Parameterizer for visualizers.
*/
private VisualizerParameterizer vispar;
+ /**
+ * Outlier scaling to apply during preprocessing.
+ */
+ private ScalingFunction prescaling;
+
+ /**
+ * Voring function.
+ */
+ private EnsembleVoting voting;
+
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
@@ -298,11 +316,23 @@ public class VisualizePairwiseGainMatrix extends AbstractApplication {
inputstep = config.tryInstantiate(InputStep.class);
// Visualization options
vispar = config.tryInstantiate(VisualizerParameterizer.class);
+
+ // Prescaling
+ ObjectParameter<ScalingFunction> prescalingP = new ObjectParameter<>(GreedyEnsembleExperiment.Parameterizer.PRESCALING_ID, ScalingFunction.class);
+ prescalingP.setOptional(true);
+ if (config.grab(prescalingP)) {
+ prescaling = prescalingP.instantiateClass(config);
+ }
+
+ ObjectParameter<EnsembleVoting> votingP = new ObjectParameter<>(GreedyEnsembleExperiment.Parameterizer.VOTING_ID, EnsembleVoting.class, EnsembleVotingMean.class);
+ if (config.grab(votingP)) {
+ voting = votingP.instantiateClass(config);
+ }
}
@Override
- protected AbstractApplication makeInstance() {
- return new VisualizePairwiseGainMatrix(inputstep, vispar);
+ protected VisualizePairwiseGainMatrix makeInstance() {
+ return new VisualizePairwiseGainMatrix(inputstep, prescaling, voting, vispar);
}
}
@@ -312,6 +342,6 @@ public class VisualizePairwiseGainMatrix extends AbstractApplication {
* @param args Command line parameters.
*/
public static void main(String[] args) {
- VisualizePairwiseGainMatrix.runCLIApplication(VisualizePairwiseGainMatrix.class, args);
+ runCLIApplication(VisualizePairwiseGainMatrix.class, args);
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/application/greedyensemble/package-info.java b/src/de/lmu/ifi/dbs/elki/application/greedyensemble/package-info.java
index 29b34e96..f8e8f705 100644
--- a/src/de/lmu/ifi/dbs/elki/application/greedyensemble/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/application/greedyensemble/package-info.java
@@ -11,7 +11,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/application/internal/CheckELKIServices.java b/src/de/lmu/ifi/dbs/elki/application/internal/CheckELKIServices.java
index cfa57c80..7dca7f37 100644
--- a/src/de/lmu/ifi/dbs/elki/application/internal/CheckELKIServices.java
+++ b/src/de/lmu/ifi/dbs/elki/application/internal/CheckELKIServices.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.application.internal;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -67,7 +67,7 @@ public class CheckELKIServices {
/**
* Package to skip matches in - unreleased code.
*/
- private String[] skippackages = { "experimentalcode." };
+ private String[] skippackages = { "experimentalcode.", "project." };
/**
* Main method.
@@ -126,11 +126,11 @@ public class CheckELKIServices {
cls = Class.forName(prop);
}
catch(ClassNotFoundException e) {
- LOG.warning("Property is not a class name: " + prop);
+ LOG.warning("Service file name is not a class name: " + prop);
return;
}
List<Class<?>> impls = InspectionUtil.findAllImplementations(cls, false);
- HashSet<String> names = new HashSet<String>();
+ HashSet<String> names = new HashSet<>();
for(Class<?> c2 : impls) {
boolean skip = false;
for(String pkg : skippackages) {
@@ -176,7 +176,7 @@ public class CheckELKIServices {
}
if(names.size() > 0) {
// format for copy & paste to properties file:
- ArrayList<String> sorted = new ArrayList<String>(names);
+ ArrayList<String> sorted = new ArrayList<>(names);
// TODO: sort by package, then classname
Collections.sort(sorted);
if(!update) {
diff --git a/src/de/lmu/ifi/dbs/elki/application/internal/CheckParameterizables.java b/src/de/lmu/ifi/dbs/elki/application/internal/CheckParameterizables.java
index 2e990bc8..68a4b127 100644
--- a/src/de/lmu/ifi/dbs/elki/application/internal/CheckParameterizables.java
+++ b/src/de/lmu/ifi/dbs/elki/application/internal/CheckParameterizables.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.application.internal;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,6 +29,7 @@ import java.lang.reflect.Modifier;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.LoggingConfiguration;
+import de.lmu.ifi.dbs.elki.logging.Logging.Level;
import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
import de.lmu.ifi.dbs.elki.utilities.InspectionUtil;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
@@ -56,7 +57,7 @@ public class CheckParameterizables {
* methods)
*/
public void checkParameterizables() {
- LoggingConfiguration.setVerbose(true);
+ LoggingConfiguration.setVerbose(Level.VERBOSE);
for(final Class<?> cls : InspectionUtil.findAllImplementations(Object.class, false)) {
final Constructor<?> constructor;
try {
diff --git a/src/de/lmu/ifi/dbs/elki/application/internal/DocumentParameters.java b/src/de/lmu/ifi/dbs/elki/application/internal/DocumentParameters.java
index f4e06c02..b9a8ae43 100644
--- a/src/de/lmu/ifi/dbs/elki/application/internal/DocumentParameters.java
+++ b/src/de/lmu/ifi/dbs/elki/application/internal/DocumentParameters.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.application.internal;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,12 +29,15 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
+import java.io.PrintStream;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
@@ -50,13 +53,14 @@ import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
+import de.lmu.ifi.dbs.elki.KDDTask;
import de.lmu.ifi.dbs.elki.application.AbstractApplication;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.LoggingConfiguration;
+import de.lmu.ifi.dbs.elki.logging.Logging.Level;
import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
import de.lmu.ifi.dbs.elki.utilities.ELKIServiceLoader;
import de.lmu.ifi.dbs.elki.utilities.InspectionUtil;
-import de.lmu.ifi.dbs.elki.utilities.datastructures.HashMapList;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizer;
@@ -102,31 +106,46 @@ public class DocumentParameters {
private static final String HEADER_KNOWN_IMPLEMENTATIONS = "Known implementations: ";
/**
+ * Enable the full wiki output. Currently not sensible, as there is a size
+ * restriction on wiki pages, so we would need to split this somehow!
+ */
+ private static final boolean FULL_WIKI_OUTPUT = false;
+
+ /**
* @param args Command line arguments
*/
public static void main(String[] args) {
- LoggingConfiguration.setVerbose(true);
- if(args.length != 2) {
- LOG.warning("I need exactly two file names to operate!");
+ LoggingConfiguration.setVerbose(Level.VERBOSE);
+ if (args.length != 2 && args.length != 4) {
+ LOG.warning("I need exactly two or four file names to operate!");
System.exit(1);
}
- if(!args[0].endsWith(".html")) {
+ if (!args[0].endsWith(".html")) {
LOG.warning("First file name doesn't end with .html!");
System.exit(1);
}
- if(!args[1].endsWith(".html")) {
+ if (!args[1].endsWith(".html")) {
LOG.warning("Second file name doesn't end with .html!");
System.exit(1);
}
+ if (args.length > 2 && !args[2].endsWith(".wiki")) {
+ LOG.warning("Third file name doesn't end with .wiki!");
+ System.exit(1);
+ }
+ if (args.length > 3 && !args[3].endsWith(".wiki")) {
+ LOG.warning("Fourth file name doesn't end with .wiki!");
+ System.exit(1);
+ }
File byclsname = new File(args[0]);
File byoptname = new File(args[1]);
+ File byclsnamew = args.length >= 3 ? new File(args[2]) : null;
+ File byoptnamew = args.length >= 4 ? new File(args[3]) : null;
- HashMapList<Class<?>, Parameter<?>> byclass = new HashMapList<Class<?>, Parameter<?>>();
- HashMapList<OptionID, Pair<Parameter<?>, Class<?>>> byopt = new HashMapList<OptionID, Pair<Parameter<?>, Class<?>>>();
+ Map<Class<?>, List<Parameter<?>>> byclass = new HashMap<>();
+ Map<OptionID, List<Pair<Parameter<?>, Class<?>>>> byopt = new HashMap<>();
try {
buildParameterIndex(byclass, byopt);
- }
- catch(Exception e) {
+ } catch (Exception e) {
LOG.exception(e);
System.exit(1);
}
@@ -135,20 +154,37 @@ public class DocumentParameters {
FileOutputStream byclassfo;
try {
byclassfo = new FileOutputStream(byclsname);
- }
- catch(FileNotFoundException e) {
+ } catch (FileNotFoundException e) {
LOG.exception("Can't create output stream!", e);
throw new RuntimeException(e);
}
OutputStream byclassstream = new BufferedOutputStream(byclassfo);
- Document byclassdoc = makeByClassOverview(byclass);
+ Document byclassdoc = makeByClassOverviewHTML(byclass);
try {
HTMLUtil.writeXHTML(byclassdoc, byclassstream);
byclassstream.flush();
byclassstream.close();
byclassfo.close();
+ } catch (IOException e) {
+ LOG.exception("IO Exception writing output.", e);
+ throw new RuntimeException(e);
}
- catch(IOException e) {
+ }
+ if (byclsnamew != null) {
+ FileOutputStream byclassfo;
+ try {
+ byclassfo = new FileOutputStream(byclsnamew);
+ } catch (FileNotFoundException e) {
+ LOG.exception("Can't create output stream!", e);
+ throw new RuntimeException(e);
+ }
+ try {
+ PrintStream byclassstream = new PrintStream(new BufferedOutputStream(byclassfo));
+ makeByClassOverviewWiki(byclass, new WikiStream(byclassstream));
+ byclassstream.flush();
+ byclassstream.close();
+ byclassfo.close();
+ } catch (IOException e) {
LOG.exception("IO Exception writing output.", e);
throw new RuntimeException(e);
}
@@ -158,20 +194,38 @@ public class DocumentParameters {
FileOutputStream byoptfo;
try {
byoptfo = new FileOutputStream(byoptname);
- }
- catch(FileNotFoundException e) {
+ } catch (FileNotFoundException e) {
LOG.exception("Can't create output stream!", e);
throw new RuntimeException(e);
}
OutputStream byoptstream = new BufferedOutputStream(byoptfo);
- Document byoptdoc = makeByOptOverview(byopt);
+ Document byoptdoc = makeByOptOverviewHTML(byopt);
try {
HTMLUtil.writeXHTML(byoptdoc, byoptfo);
byoptstream.flush();
byoptstream.close();
byoptfo.close();
+ } catch (IOException e) {
+ LOG.exception("IO Exception writing output.", e);
+ throw new RuntimeException(e);
}
- catch(IOException e) {
+ }
+
+ if (byoptnamew != null) {
+ FileOutputStream byoptfo;
+ try {
+ byoptfo = new FileOutputStream(byoptnamew);
+ } catch (FileNotFoundException e) {
+ LOG.exception("Can't create output stream!", e);
+ throw new RuntimeException(e);
+ }
+ try {
+ PrintStream byoptstream = new PrintStream(new BufferedOutputStream(byoptfo));
+ makeByOptOverviewWiki(byopt, new WikiStream(byoptstream));
+ byoptstream.flush();
+ byoptstream.close();
+ byoptfo.close();
+ } catch (IOException e) {
LOG.exception("IO Exception writing output.", e);
throw new RuntimeException(e);
}
@@ -180,59 +234,53 @@ public class DocumentParameters {
System.exit(0);
}
- private static void buildParameterIndex(HashMapList<Class<?>, Parameter<?>> byclass, HashMapList<OptionID, Pair<Parameter<?>, Class<?>>> byopt) {
- final ArrayList<Pair<Object, Parameter<?>>> options = new ArrayList<Pair<Object, Parameter<?>>>();
+ private static void buildParameterIndex(Map<Class<?>, List<Parameter<?>>> byclass, Map<OptionID, List<Pair<Parameter<?>, Class<?>>>> byopt) {
+ final ArrayList<Pair<Object, Parameter<?>>> options = new ArrayList<>();
ExecutorService es = Executors.newSingleThreadExecutor();
- for(final Class<?> cls : InspectionUtil.findAllImplementations(Parameterizable.class, false)) {
+ for (final Class<?> cls : InspectionUtil.findAllImplementations(Parameterizable.class, false)) {
// Doesn't have a proper name?
- if(cls.getCanonicalName() == null) {
+ if (cls.getCanonicalName() == null) {
continue;
}
// Some of the "applications" do currently not have appropriate
// constructors / parameterizers and may start AWT threads - skip them.
- if(AbstractApplication.class.isAssignableFrom(cls)) {
+ if (AbstractApplication.class.isAssignableFrom(cls)) {
continue;
}
UnParameterization config = new UnParameterization();
final TrackParameters track = new TrackParameters(config);
// LoggingUtil.warning("Instantiating " + cls.getName());
- FutureTask<?> instantiator = new FutureTask<Object>(new Runnable() {
+ FutureTask<?> instantiator = new FutureTask<>(new Runnable() {
@Override
public void run() {
// Try a V3 style parameterizer first.
Parameterizer par = ClassGenericsUtil.getParameterizer(cls);
- if(par != null) {
+ if (par != null) {
par.configure(track);
- }
- else {
+ } else {
try {
ClassGenericsUtil.tryInstantiate(Object.class, cls, track);
- }
- catch(java.lang.NoSuchMethodException e) {
+ } catch (java.lang.NoSuchMethodException e) {
LOG.warning("Could not instantiate class " + cls.getName() + " - no appropriate constructor or parameterizer found.");
- }
- catch(java.lang.reflect.InvocationTargetException e) {
- if(e.getCause() instanceof RuntimeException) {
+ } catch (java.lang.reflect.InvocationTargetException e) {
+ if (e.getCause() instanceof RuntimeException) {
throw (RuntimeException) e.getCause();
}
- if(e.getCause() instanceof Error) {
+ if (e.getCause() instanceof Error) {
throw (Error) e.getCause();
}
throw new RuntimeException(e.getCause());
- }
- catch(RuntimeException e) {
+ } catch (RuntimeException e) {
throw e;
- }
- catch(Exception e) {
+ } catch (Exception e) {
throw new RuntimeException(e);
- }
- catch(java.lang.Error e) {
+ } catch (java.lang.Error e) {
throw new RuntimeException(e);
}
}
- for(Pair<Object, Parameter<?>> pair : track.getAllParameters()) {
- if(pair.first == null) {
+ for (Pair<Object, Parameter<?>> pair : track.getAllParameters()) {
+ if (pair.first == null) {
pair.first = cls;
}
options.add(pair);
@@ -243,18 +291,15 @@ public class DocumentParameters {
try {
// Wait up to one second.
instantiator.get(1L, TimeUnit.SECONDS);
- }
- catch(TimeoutException e) {
+ } catch (TimeoutException e) {
LOG.warning("Timeout on instantiating " + cls.getName());
es.shutdownNow();
throw new RuntimeException(e);
- }
- catch(java.util.concurrent.ExecutionException e) {
+ } catch (java.util.concurrent.ExecutionException e) {
// Do full reporting only on release branch.
- if(cls.getName().startsWith("de.lmu.ifi.dbs.elki")) {
+ if (cls.getName().startsWith("de.lmu.ifi.dbs.elki")) {
LOG.warning("Error instantiating " + cls.getName(), e.getCause());
- }
- else {
+ } else {
LOG.warning("Error instantiating " + cls.getName());
}
// es.shutdownNow();
@@ -263,13 +308,11 @@ public class DocumentParameters {
// }
// throw new RuntimeException(e.getCause());
continue;
- }
- catch(Exception e) {
+ } catch (Exception e) {
// Do full reporting only on release branch.
- if(cls.getName().startsWith("de.lmu.ifi.dbs.elki")) {
+ if (cls.getName().startsWith("de.lmu.ifi.dbs.elki")) {
LOG.warning("Error instantiating " + cls.getName(), e.getCause());
- }
- else {
+ } else {
LOG.warning("Error instantiating " + cls.getName());
}
// es.shutdownNow();
@@ -278,16 +321,15 @@ public class DocumentParameters {
}
}
LOG.debug("Documenting " + options.size() + " parameter instances.");
- for(Pair<Object, Parameter<?>> pp : options) {
- if(pp.first == null || pp.second == null) {
+ for (Pair<Object, Parameter<?>> pp : options) {
+ if (pp.first == null || pp.second == null) {
LOG.debugFiner("Null: " + pp.first + " " + pp.second);
continue;
}
Class<?> c;
- if(pp.first instanceof Class) {
+ if (pp.first instanceof Class) {
c = (Class<?>) pp.first;
- }
- else {
+ } else {
c = pp.first.getClass();
}
Parameter<?> o = pp.second;
@@ -296,31 +338,41 @@ public class DocumentParameters {
{
List<Parameter<?>> byc = byclass.get(c);
boolean inlist = false;
- if(byc != null) {
- for(Parameter<?> par : byc) {
- if(par.getOptionID() == o.getOptionID()) {
+ if (byc != null) {
+ for (Parameter<?> par : byc) {
+ if (par.getOptionID() == o.getOptionID()) {
inlist = true;
break;
}
}
}
- if(!inlist) {
- byclass.add(c, o);
+ if (!inlist) {
+ List<Parameter<?>> ex = byclass.get(c);
+ if (ex == null) {
+ ex = new ArrayList<>();
+ byclass.put(c, ex);
+ }
+ ex.add(o);
}
}
{
List<Pair<Parameter<?>, Class<?>>> byo = byopt.get(o.getOptionID());
boolean inlist = false;
- if(byo != null) {
- for(Pair<Parameter<?>, Class<?>> pair : byo) {
- if(pair.second.equals(c)) {
+ if (byo != null) {
+ for (Pair<Parameter<?>, Class<?>> pair : byo) {
+ if (pair.second.equals(c)) {
inlist = true;
break;
}
}
}
- if(!inlist) {
- byopt.add(o.getOptionID(), new Pair<Parameter<?>, Class<?>>(o, c));
+ if (!inlist) {
+ List<Pair<Parameter<?>, Class<?>>> ex = byopt.get(o.getOptionID());
+ if (ex == null) {
+ ex = new ArrayList<>();
+ byopt.put(o.getOptionID(), ex);
+ }
+ ex.add(new Pair<Parameter<?>, Class<?>>(o, c));
}
}
}
@@ -330,31 +382,26 @@ public class DocumentParameters {
protected static Constructor<?> getConstructor(final Class<?> cls) {
try {
return cls.getConstructor(Parameterization.class);
- }
- catch(java.lang.NoClassDefFoundError e) {
+ } catch (java.lang.NoClassDefFoundError e) {
// Class not actually found
- }
- catch(RuntimeException e) {
+ } catch (RuntimeException e) {
// Not parameterizable, usually not even found ...
LOG.warning("RuntimeException: ", e);
- }
- catch(Exception e) {
+ } catch (Exception e) {
// Not parameterizable.
- }
- catch(java.lang.Error e) {
+ } catch (java.lang.Error e) {
// Not parameterizable.
LOG.warning("Error: ", e);
}
return null;
}
- private static Document makeByClassOverview(HashMapList<Class<?>, Parameter<?>> byclass) {
+ private static Document makeByClassOverviewHTML(Map<Class<?>, List<Parameter<?>>> byclass) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder;
try {
builder = factory.newDocumentBuilder();
- }
- catch(ParserConfigurationException e1) {
+ } catch (ParserConfigurationException e1) {
throw new RuntimeException(e1);
}
DOMImplementation impl = builder.getDOMImplementation();
@@ -404,10 +451,10 @@ public class DocumentParameters {
Element maindl = htmldoc.createElement(HTMLUtil.HTML_DL_TAG);
body.appendChild(maindl);
- List<Class<?>> classes = new ArrayList<Class<?>>(byclass.keySet());
+ List<Class<?>> classes = new ArrayList<>(byclass.keySet());
Collections.sort(classes, new InspectionUtil.ClassSorter());
- for(Class<?> cls : classes) {
+ for (Class<?> cls : classes) {
// DT = definition term
Element classdt = htmldoc.createElement(HTMLUtil.HTML_DT_TAG);
// Anchor for references
@@ -430,7 +477,7 @@ public class DocumentParameters {
// nested definition list for options
Element classdl = htmldoc.createElement(HTMLUtil.HTML_DL_TAG);
classdd.appendChild(classdl);
- for(Parameter<?> opt : byclass.get(cls)) {
+ for (Parameter<?> opt : byclass.get(cls)) {
// DT definition term: option name, in TT for typewriter optics
Element elemdt = htmldoc.createElement(HTMLUtil.HTML_DT_TAG);
{
@@ -442,18 +489,18 @@ public class DocumentParameters {
// DD definition description - put the option description here.
Element elemdd = htmldoc.createElement(HTMLUtil.HTML_DD_TAG);
Element elemp = htmldoc.createElement(HTMLUtil.HTML_P_TAG);
- if(opt.getShortDescription() != null) {
+ if (opt.getShortDescription() != null) {
HTMLUtil.appendMultilineText(htmldoc, elemp, opt.getShortDescription());
}
elemdd.appendChild(elemp);
// class restriction?
- if(opt instanceof ClassParameter<?>) {
+ if (opt instanceof ClassParameter<?>) {
appendClassRestriction(htmldoc, ((ClassParameter<?>) opt).getRestrictionClass(), elemdd);
}
// default value? completions?
appendDefaultValueIfSet(htmldoc, opt, elemdd);
// known values?
- if(opt instanceof ClassParameter<?>) {
+ if (opt instanceof ClassParameter<?>) {
appendKnownImplementationsIfNonempty(htmldoc, (ClassParameter<?>) opt, elemdd);
}
classdl.appendChild(elemdd);
@@ -462,13 +509,134 @@ public class DocumentParameters {
return htmldoc;
}
- private static Document makeByOptOverview(HashMapList<OptionID, Pair<Parameter<?>, Class<?>>> byopt) {
+ /**
+ * Write to a Wiki format.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ private static class WikiStream {
+ PrintStream out;
+
+ public int indent = 0;
+
+ // Newline mode.
+ int newline = 0;
+
+ WikiStream(PrintStream out) {
+ this.out = out;
+ this.newline = -1;
+ }
+
+ void print(String p) {
+ insertNewline();
+ out.print(p);
+ }
+
+ private void insertNewline() {
+ if (newline == 2) {
+ out.print("[[br]]");
+ }
+ if (newline != 0) {
+ printIndent();
+ newline = 0;
+ }
+ }
+
+ private void printIndent() {
+ if (newline > 0) {
+ out.println();
+ }
+ for (int i = indent; i > 0; i--) {
+ out.print(' ');
+ }
+ }
+
+ void println(String p) {
+ insertNewline();
+ out.print(p);
+ newline = 2;
+ }
+
+ void println() {
+ newline = 2;
+ }
+
+ void printitem(String item) {
+ printIndent();
+ newline = 0;
+ print(item);
+ }
+
+ void javadocLink(Class<?> cls, Class<?> base) {
+ insertNewline();
+ out.print("[[javadoc(");
+ out.print(cls.getCanonicalName());
+ if (base != null) {
+ out.print(",");
+ out.print(ClassParameter.canonicalClassName(cls, base));
+ }
+ out.print(")]]");
+ }
+ }
+
+ private static void makeByClassOverviewWiki(Map<Class<?>, List<Parameter<?>>> byclass, WikiStream out) {
+ List<Class<?>> classes = new ArrayList<>(byclass.keySet());
+ Collections.sort(classes, new InspectionUtil.ClassSorter());
+
+ for (Class<?> cls : classes) {
+ out.indent = 0;
+ out.printitem("'''");
+ out.javadocLink(cls, KDDTask.class);
+ out.println("''':");
+ out.indent = 1;
+ out.newline = 1; // No BR needed, we increase the indent.
+ for (Parameter<?> opt : byclass.get(cls)) {
+ out.printitem("* ");
+ out.print("{{{"); // typewriter
+ out.print(SerializedParameterization.OPTION_PREFIX);
+ out.print(opt.getName());
+ out.print(" ");
+ out.print(opt.getSyntax());
+ out.println("}}}");
+ if (opt.getShortDescription() != null) {
+ appendMultilineTextWiki(out, opt.getShortDescription());
+ }
+ // class restriction?
+ if (opt instanceof ClassParameter<?>) {
+ appendClassRestrictionWiki(out, ((ClassParameter<?>) opt).getRestrictionClass());
+ }
+ // default value?
+ if (opt.hasDefaultValue()) {
+ appendDefaultValueWiki(out, opt);
+ }
+ // known values?
+ if (FULL_WIKI_OUTPUT) {
+ if (opt instanceof ClassParameter<?>) {
+ if (((ClassParameter<?>) opt).getKnownImplementations().size() > 0) {
+ appendKnownImplementationsWiki(out, (ClassParameter<?>) opt);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private static int appendMultilineTextWiki(WikiStream out, String text) {
+ final String[] lines = text.split("\n");
+ for (int i = 0; i < lines.length; i++) {
+ out.println(lines[i]);
+ }
+ return lines.length;
+ }
+
+ private static Document makeByOptOverviewHTML(Map<OptionID, List<Pair<Parameter<?>, Class<?>>>> byopt) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder;
try {
builder = factory.newDocumentBuilder();
- }
- catch(ParserConfigurationException e1) {
+ } catch (ParserConfigurationException e1) {
throw new RuntimeException(e1);
}
DOMImplementation impl = builder.getDOMImplementation();
@@ -518,10 +686,10 @@ public class DocumentParameters {
Element maindl = htmldoc.createElement(HTMLUtil.HTML_DL_TAG);
body.appendChild(maindl);
- List<OptionID> opts = new ArrayList<OptionID>(byopt.keySet());
+ List<OptionID> opts = new ArrayList<>(byopt.keySet());
Collections.sort(opts, new SortByOption());
- for(OptionID oid : opts) {
+ for (OptionID oid : opts) {
final Parameter<?> firstopt = byopt.get(oid).get(0).getFirst();
// DT = definition term
Element optdt = htmldoc.createElement(HTMLUtil.HTML_DT_TAG);
@@ -547,12 +715,12 @@ public class DocumentParameters {
}
// class restriction?
Class<?> superclass = null;
- if(firstopt instanceof ClassParameter<?>) {
+ if (firstopt instanceof ClassParameter<?>) {
// Find superclass heuristically
superclass = ((ClassParameter<?>) firstopt).getRestrictionClass();
- for(Pair<Parameter<?>, Class<?>> clinst : byopt.get(oid)) {
+ for (Pair<Parameter<?>, Class<?>> clinst : byopt.get(oid)) {
ClassParameter<?> cls = (ClassParameter<?>) clinst.getFirst();
- if(!cls.getRestrictionClass().equals(superclass) && cls.getRestrictionClass().isAssignableFrom(superclass)) {
+ if (!cls.getRestrictionClass().equals(superclass) && cls.getRestrictionClass().isAssignableFrom(superclass)) {
superclass = cls.getRestrictionClass();
}
}
@@ -561,7 +729,7 @@ public class DocumentParameters {
// default value?
appendDefaultValueIfSet(htmldoc, firstopt, optdd);
// known values?
- if(firstopt instanceof ClassParameter<?>) {
+ if (firstopt instanceof ClassParameter<?>) {
appendKnownImplementationsIfNonempty(htmldoc, (ClassParameter<?>) firstopt, optdd);
}
maindl.appendChild(optdd);
@@ -573,7 +741,7 @@ public class DocumentParameters {
optdd.appendChild(p);
}
optdd.appendChild(classesul);
- for(Pair<Parameter<?>, Class<?>> clinst : byopt.get(oid)) {
+ for (Pair<Parameter<?>, Class<?>> clinst : byopt.get(oid)) {
// DT definition term: option name, in TT for typewriter optics
Element classli = htmldoc.createElement(HTMLUtil.HTML_LI_TAG);
@@ -584,26 +752,24 @@ public class DocumentParameters {
classa.setTextContent(clinst.getSecond().getName());
classli.appendChild(classa);
}
- if(clinst.getFirst() instanceof ClassParameter<?> && firstopt instanceof ClassParameter<?>) {
+ if (clinst.getFirst() instanceof ClassParameter<?> && firstopt instanceof ClassParameter<?>) {
ClassParameter<?> cls = (ClassParameter<?>) clinst.getFirst();
- if(cls.getRestrictionClass() != null) {
+ if (cls.getRestrictionClass() != null) {
// TODO: if it is null, it could still be different!
- if(!cls.getRestrictionClass().equals(superclass)) {
+ if (!cls.getRestrictionClass().equals(superclass)) {
appendClassRestriction(htmldoc, cls.getRestrictionClass(), classli);
}
- }
- else {
+ } else {
appendNoClassRestriction(htmldoc, classli);
}
}
Parameter<?> param = clinst.getFirst();
- if(param.getDefaultValue() != null) {
- if(!param.getDefaultValue().equals(firstopt.getDefaultValue())) {
+ if (param.getDefaultValue() != null) {
+ if (!param.getDefaultValue().equals(firstopt.getDefaultValue())) {
appendDefaultValueIfSet(htmldoc, param, classli);
}
- }
- else {
- if(firstopt.getDefaultValue() != null) {
+ } else {
+ if (firstopt.getDefaultValue() != null) {
appendNoDefaultValue(htmldoc, classli);
}
}
@@ -614,6 +780,82 @@ public class DocumentParameters {
return htmldoc;
}
+ private static void makeByOptOverviewWiki(Map<OptionID, List<Pair<Parameter<?>, Class<?>>>> byopt, WikiStream out) {
+ List<OptionID> opts = new ArrayList<>(byopt.keySet());
+ Collections.sort(opts, new SortByOption());
+
+ for (OptionID oid : opts) {
+ final Parameter<?> firstopt = byopt.get(oid).get(0).getFirst();
+ out.indent = 1;
+ out.printitem("");
+ out.print("{{{");
+ out.print(SerializedParameterization.OPTION_PREFIX);
+ out.print(firstopt.getName());
+ out.print(" ");
+ out.print(firstopt.getSyntax());
+ out.println("}}}:: ");
+ out.newline = 1; // No BR needed, we increase the indent.
+ out.indent = 2;
+
+ appendMultilineTextWiki(out, firstopt.getShortDescription());
+ // class restriction?
+ Class<?> superclass = null;
+ if (firstopt instanceof ClassParameter<?>) {
+ // Find superclass heuristically
+ superclass = ((ClassParameter<?>) firstopt).getRestrictionClass();
+ for (Pair<Parameter<?>, Class<?>> clinst : byopt.get(oid)) {
+ ClassParameter<?> cls = (ClassParameter<?>) clinst.getFirst();
+ if (!cls.getRestrictionClass().equals(superclass) && cls.getRestrictionClass().isAssignableFrom(superclass)) {
+ superclass = cls.getRestrictionClass();
+ }
+ }
+ appendClassRestrictionWiki(out, superclass);
+ }
+ // default value?
+ if (firstopt.hasDefaultValue()) {
+ appendDefaultValueWiki(out, firstopt);
+ }
+ if (FULL_WIKI_OUTPUT) {
+ // known values?
+ if (firstopt instanceof ClassParameter<?>) {
+ if (((ClassParameter<?>) firstopt).getKnownImplementations().size() > 0) {
+ appendKnownImplementationsWiki(out, (ClassParameter<?>) firstopt);
+ }
+ }
+ // List of classes that use this parameter
+ out.println("Used by:");
+ for (Pair<Parameter<?>, Class<?>> clinst : byopt.get(oid)) {
+ out.indent = 3;
+ out.printitem("* ");
+ out.javadocLink(clinst.getSecond(), null);
+ out.println();
+ if (clinst.getFirst() instanceof ClassParameter<?> && firstopt instanceof ClassParameter<?>) {
+ ClassParameter<?> cls = (ClassParameter<?>) clinst.getFirst();
+ if (cls.getRestrictionClass() != null) {
+ // TODO: if it is null, it could still be different!
+ if (!cls.getRestrictionClass().equals(superclass)) {
+ appendClassRestrictionWiki(out, cls.getRestrictionClass());
+ }
+ } else {
+ appendNoClassRestrictionWiki(out);
+ }
+ }
+ Parameter<?> param = clinst.getFirst();
+ if (param.getDefaultValue() != null) {
+ if (!param.getDefaultValue().equals(firstopt.getDefaultValue())) {
+ appendDefaultValueWiki(out, param);
+ }
+ } else {
+ if (firstopt.getDefaultValue() != null) {
+ appendNoDefaultValueWiki(out);
+ }
+ }
+ out.println("");
+ }
+ }
+ }
+ }
+
private static void appendDefaultClassLink(Document htmldoc, Parameter<?> opt, Element p) {
Element defa = htmldoc.createElement(HTMLUtil.HTML_A_TAG);
defa.setAttribute(HTMLUtil.HTML_HREF_ATTRIBUTE, linkForClassName(((ClassParameter<?>) opt).getDefaultValue().getCanonicalName()));
@@ -622,16 +864,15 @@ public class DocumentParameters {
}
private static void appendClassRestriction(Document htmldoc, Class<?> restriction, Element elemdd) {
- if(restriction == null) {
+ if (restriction == null) {
LOG.warning("No restriction class!");
return;
}
Element p = htmldoc.createElement(HTMLUtil.HTML_P_TAG);
p.appendChild(htmldoc.createTextNode(HEADER_CLASS_RESTRICTION));
- if(restriction.isInterface()) {
+ if (restriction.isInterface()) {
p.appendChild(htmldoc.createTextNode(HEADER_CLASS_RESTRICTION_IMPLEMENTING));
- }
- else {
+ } else {
p.appendChild(htmldoc.createTextNode(HEADER_CLASS_RESTRICTION_EXTENDING));
}
Element defa = htmldoc.createElement(HTMLUtil.HTML_A_TAG);
@@ -648,15 +889,36 @@ public class DocumentParameters {
elemdd.appendChild(p);
}
+ private static void appendClassRestrictionWiki(WikiStream out, Class<?> restriction) {
+ if (restriction == null) {
+ LOG.warning("No restriction class!");
+ return;
+ }
+ out.print(HEADER_CLASS_RESTRICTION);
+ if (restriction.isInterface()) {
+ out.print(HEADER_CLASS_RESTRICTION_IMPLEMENTING);
+ } else {
+ out.print(HEADER_CLASS_RESTRICTION_EXTENDING);
+ }
+ out.javadocLink(restriction, null);
+ out.println();
+ }
+
+ private static void appendNoClassRestrictionWiki(WikiStream out) {
+ out.print(HEADER_CLASS_RESTRICTION);
+ out.print(NO_CLASS_RESTRICTION);
+ out.println();
+ }
+
private static void appendKnownImplementationsIfNonempty(Document htmldoc, ClassParameter<?> opt, Element elemdd) {
- if(opt.getRestrictionClass() != Object.class) {
+ if (opt.getRestrictionClass() != Object.class) {
List<Class<?>> iter = opt.getKnownImplementations();
- if(!iter.isEmpty()) {
+ if (!iter.isEmpty()) {
Element p = htmldoc.createElement(HTMLUtil.HTML_P_TAG);
p.appendChild(htmldoc.createTextNode(HEADER_KNOWN_IMPLEMENTATIONS));
elemdd.appendChild(p);
Element ul = htmldoc.createElement(HTMLUtil.HTML_UL_TAG);
- for(Class<?> c : iter) {
+ for (Class<?> c : iter) {
Element li = htmldoc.createElement(HTMLUtil.HTML_LI_TAG);
Element defa = htmldoc.createElement(HTMLUtil.HTML_A_TAG);
defa.setAttribute(HTMLUtil.HTML_HREF_ATTRIBUTE, linkForClassName(c.getName()));
@@ -668,12 +930,24 @@ public class DocumentParameters {
}
// Report when not in properties file.
Iterator<Class<?>> clss = new ELKIServiceLoader(opt.getRestrictionClass());
- if(!clss.hasNext()) {
+ if (!clss.hasNext()) {
LOG.warning(opt.getRestrictionClass().getName() + " not in properties. No autocompletion available in release GUI.");
}
}
}
+ private static void appendKnownImplementationsWiki(WikiStream out, ClassParameter<?> opt) {
+ out.println(HEADER_KNOWN_IMPLEMENTATIONS);
+ List<Class<?>> implementations = opt.getKnownImplementations();
+ out.indent++;
+ for (Class<?> c : implementations) {
+ out.printitem("* ");
+ out.javadocLink(c, opt.getRestrictionClass());
+ out.println();
+ }
+ out.indent--;
+ }
+
/**
* Append string containing the default value.
*
@@ -682,13 +956,12 @@ public class DocumentParameters {
* @param optdd HTML Element
*/
private static void appendDefaultValueIfSet(Document htmldoc, Parameter<?> par, Element optdd) {
- if(par.hasDefaultValue()) {
+ if (par.hasDefaultValue()) {
Element p = htmldoc.createElement(HTMLUtil.HTML_P_TAG);
p.appendChild(htmldoc.createTextNode(HEADER_DEFAULT_VALUE));
- if(par instanceof ClassParameter<?>) {
+ if (par instanceof ClassParameter<?>) {
appendDefaultClassLink(htmldoc, par, p);
- }
- else {
+ } else {
Object def = par.getDefaultValue();
p.appendChild(htmldoc.createTextNode(def.toString()));
}
@@ -709,6 +982,23 @@ public class DocumentParameters {
optdd.appendChild(p);
}
+ private static void appendDefaultValueWiki(WikiStream out, Parameter<?> par) {
+ out.print(HEADER_DEFAULT_VALUE);
+ if (par instanceof ClassParameter<?>) {
+ final Class<?> name = ((ClassParameter<?>) par).getDefaultValue();
+ out.javadocLink(name, null);
+ } else {
+ Object def = par.getDefaultValue();
+ out.print(def.toString());
+ }
+ out.println();
+ }
+
+ private static void appendNoDefaultValueWiki(WikiStream out) {
+ out.print(HEADER_DEFAULT_VALUE);
+ out.println(NO_DEFAULT_VALUE);
+ }
+
/**
* Return a link for the class name
*
diff --git a/src/de/lmu/ifi/dbs/elki/application/internal/DocumentReferences.java b/src/de/lmu/ifi/dbs/elki/application/internal/DocumentReferences.java
index eaf05425..7878a759 100644
--- a/src/de/lmu/ifi/dbs/elki/application/internal/DocumentReferences.java
+++ b/src/de/lmu/ifi/dbs/elki/application/internal/DocumentReferences.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.application.internal;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -276,8 +276,8 @@ public class DocumentReferences {
}
private static List<Pair<Reference, List<Class<?>>>> sortedReferences() {
- List<Pair<Reference, List<Class<?>>>> refs = new ArrayList<Pair<Reference, List<Class<?>>>>();
- Map<Reference, List<Class<?>>> map = new HashMap<Reference, List<Class<?>>>();
+ List<Pair<Reference, List<Class<?>>>> refs = new ArrayList<>();
+ Map<Reference, List<Class<?>>> map = new HashMap<>();
for(final Class<?> cls : InspectionUtil.findAllImplementations(Object.class, true)) {
inspectClass(cls, refs, map);
@@ -291,9 +291,9 @@ public class DocumentReferences {
Reference ref = cls.getAnnotation(Reference.class);
List<Class<?>> list = map.get(ref);
if(list == null) {
- list = new ArrayList<Class<?>>(5);
+ list = new ArrayList<>(5);
map.put(ref, list);
- refs.add(new Pair<Reference, List<Class<?>>>(ref, list));
+ refs.add(new Pair<>(ref, list));
}
list.add(cls);
}
@@ -306,9 +306,9 @@ public class DocumentReferences {
Reference ref = m.getAnnotation(Reference.class);
List<Class<?>> list = map.get(ref);
if(list == null) {
- list = new ArrayList<Class<?>>(5);
+ list = new ArrayList<>(5);
map.put(ref, list);
- refs.add(new Pair<Reference, List<Class<?>>>(ref, list));
+ refs.add(new Pair<>(ref, list));
}
list.add(cls);
}
@@ -335,7 +335,7 @@ public class DocumentReferences {
* @return All classes with the reference annotation.
*/
public static ArrayList<Class<?>> findAllClassesWithReferences() {
- ArrayList<Class<?>> references = new ArrayList<Class<?>>();
+ ArrayList<Class<?>> references = new ArrayList<>();
for(final Class<?> cls : InspectionUtil.findAllImplementations(Object.class, true)) {
if(cls.isAnnotationPresent(Reference.class)) {
references.add(cls);
diff --git a/src/de/lmu/ifi/dbs/elki/application/internal/package-info.java b/src/de/lmu/ifi/dbs/elki/application/internal/package-info.java
index 56326655..ecd1724d 100644
--- a/src/de/lmu/ifi/dbs/elki/application/internal/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/application/internal/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/application/jsmap/JSONBuffer.java b/src/de/lmu/ifi/dbs/elki/application/jsmap/JSONBuffer.java
index 2458d39a..e1ecc2cb 100644
--- a/src/de/lmu/ifi/dbs/elki/application/jsmap/JSONBuffer.java
+++ b/src/de/lmu/ifi/dbs/elki/application/jsmap/JSONBuffer.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.application.jsmap;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -44,14 +44,14 @@ public class JSONBuffer {
*
* @apiviz.exclude
*/
- enum ops {
+ enum Operand {
HASH, ARRAY
}
/**
* Operations stack for detecting errors
*/
- final Stack<ops> stack = new Stack<ops>();
+ final Stack<Operand> stack = new Stack<>();
/**
* Constructor.
@@ -79,7 +79,7 @@ public class JSONBuffer {
* @return Buffer for chaining
*/
public JSONBuffer appendString(Object cont) {
- if(stack.empty() || stack.peek() != ops.ARRAY) {
+ if(stack.empty() || stack.peek() != Operand.ARRAY) {
throw new JSONException("Appending string outside of array context.");
}
addQuotedString(cont);
@@ -94,7 +94,7 @@ public class JSONBuffer {
* @return Buffer for chaining
*/
public JSONBuffer append(double cont) {
- if(stack.empty() || stack.peek() != ops.ARRAY) {
+ if(stack.empty() || stack.peek() != Operand.ARRAY) {
throw new JSONException("Appending double outside of array context.");
}
buffer.append(Double.toString(cont));
@@ -109,7 +109,7 @@ public class JSONBuffer {
* @return Buffer for chaining
*/
public JSONBuffer append(int cont) {
- if(stack.empty() || stack.peek() != ops.ARRAY) {
+ if(stack.empty() || stack.peek() != Operand.ARRAY) {
throw new JSONException("Appending double outside of array context.");
}
buffer.append(Integer.toString(cont));
@@ -180,7 +180,7 @@ public class JSONBuffer {
* @return Buffer for chaining
*/
public JSONBuffer appendKeyValue(Object key, Object val) {
- if(stack.empty() || stack.peek() != ops.HASH) {
+ if(stack.empty() || stack.peek() != Operand.HASH) {
throw new JSONException("Appending key-value outside of hash context.");
}
addQuotedString(key);
@@ -205,13 +205,13 @@ public class JSONBuffer {
* @return Buffer for chaining
*/
public JSONBuffer appendKeyHash(Object key) {
- if(stack.empty() || stack.peek() != ops.HASH) {
+ if(stack.empty() || stack.peek() != Operand.HASH) {
throw new JSONException("Appending key-value outside of hash context.");
}
addQuotedString(key);
buffer.append(":");
buffer.append("{");
- stack.push(ops.HASH);
+ stack.push(Operand.HASH);
return this;
}
@@ -222,13 +222,13 @@ public class JSONBuffer {
* @return Buffer for chaining
*/
public JSONBuffer appendKeyArray(Object key) {
- if(stack.empty() || stack.peek() != ops.HASH) {
+ if(stack.empty() || stack.peek() != Operand.HASH) {
throw new JSONException("Appending key-value outside of hash context.");
}
addQuotedString(key);
buffer.append(":");
buffer.append("[");
- stack.push(ops.ARRAY);
+ stack.push(Operand.ARRAY);
return this;
}
@@ -238,11 +238,11 @@ public class JSONBuffer {
* @return Buffer for chaining
*/
public JSONBuffer startArray() {
- if(!stack.empty() && stack.peek() != ops.ARRAY) {
+ if(!stack.empty() && stack.peek() != Operand.ARRAY) {
throw new JSONException("startArray() is only allowed in an empty context.");
}
buffer.append("[");
- stack.push(ops.ARRAY);
+ stack.push(Operand.ARRAY);
return this;
}
@@ -252,11 +252,11 @@ public class JSONBuffer {
* @return Buffer for chaining
*/
public JSONBuffer startHash() {
- if(!stack.empty() && stack.peek() != ops.ARRAY) {
+ if(!stack.empty() && stack.peek() != Operand.ARRAY) {
throw new JSONException("startHash() is only allowed in an empty context.");
}
buffer.append("{");
- stack.push(ops.HASH);
+ stack.push(Operand.HASH);
return this;
}
@@ -266,7 +266,7 @@ public class JSONBuffer {
* @return Buffer for chaining
*/
public JSONBuffer closeArray() {
- if(stack.empty() || stack.peek() != ops.ARRAY) {
+ if(stack.empty() || stack.peek() != Operand.ARRAY) {
throw new JSONException("Not in array context when closing.");
}
removeSeparator();
@@ -282,7 +282,7 @@ public class JSONBuffer {
* @return Buffer for chaining
*/
public JSONBuffer closeHash() {
- if(stack.empty() || stack.peek() != ops.HASH) {
+ if(stack.empty() || stack.peek() != Operand.HASH) {
throw new JSONException("Not in array context when closing.");
}
removeSeparator();
diff --git a/src/de/lmu/ifi/dbs/elki/application/jsmap/JSONResultHandler.java b/src/de/lmu/ifi/dbs/elki/application/jsmap/JSONResultHandler.java
index 217010da..9b1e723d 100644
--- a/src/de/lmu/ifi/dbs/elki/application/jsmap/JSONResultHandler.java
+++ b/src/de/lmu/ifi/dbs/elki/application/jsmap/JSONResultHandler.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.application.jsmap;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/application/jsmap/JSONWebServer.java b/src/de/lmu/ifi/dbs/elki/application/jsmap/JSONWebServer.java
index bcf628d0..6f8c8be7 100644
--- a/src/de/lmu/ifi/dbs/elki/application/jsmap/JSONWebServer.java
+++ b/src/de/lmu/ifi/dbs/elki/application/jsmap/JSONWebServer.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.application.jsmap;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,7 +27,6 @@ import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.URLDecoder;
-import java.util.Iterator;
import java.util.concurrent.Executors;
import com.sun.net.httpserver.Headers;
@@ -55,6 +54,7 @@ import de.lmu.ifi.dbs.elki.result.ResultHierarchy;
import de.lmu.ifi.dbs.elki.result.ResultUtil;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierScoreMeta;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.Hierarchy;
import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
/**
@@ -111,8 +111,7 @@ public class JSONWebServer implements HttpHandler {
server.start();
LOG.verbose("Webserver started on port " + port + ".");
- }
- catch(IOException e) {
+ } catch (IOException e) {
throw new AbortException("Could not start mini web server.", e);
}
}
@@ -142,25 +141,25 @@ public class JSONWebServer implements HttpHandler {
*/
protected void bundleToJSON(JSONBuffer re, DBIDRef id) {
SingleObjectBundle bundle = db.getBundle(id);
- if(bundle != null) {
- for(int j = 0; j < bundle.metaLength(); j++) {
+ if (bundle != null) {
+ for (int j = 0; j < bundle.metaLength(); j++) {
final Object data = bundle.data(j);
// TODO: refactor to JSONFormatters!
// Format a NumberVector
- if(data instanceof NumberVector) {
+ if (data instanceof NumberVector) {
NumberVector<?> v = (NumberVector<?>) data;
re.appendKeyArray(bundle.meta(j));
- for(int i = 0; i < v.getDimensionality(); i++) {
+ for (int i = 0; i < v.getDimensionality(); i++) {
re.append(v.doubleValue(i));
}
re.closeArray();
}
// Format a Polygon
- else if(data instanceof PolygonsObject) {
+ else if (data instanceof PolygonsObject) {
re.appendKeyArray(bundle.meta(j));
- for(Polygon p : ((PolygonsObject) data).getPolygons()) {
+ for (Polygon p : ((PolygonsObject) data).getPolygons()) {
re.startArray();
- for(int i = 0; i < p.size(); i++) {
+ for (int i = 0; i < p.size(); i++) {
Vector point = p.get(i);
re.append(point.getArrayRef());
}
@@ -172,12 +171,11 @@ public class JSONWebServer implements HttpHandler {
else {
re.appendKeyValue(bundle.meta(j), data);
}
- if(LOG.isDebuggingFiner()) {
+ if (LOG.isDebuggingFiner()) {
re.appendNewline();
}
}
- }
- else {
+ } else {
re.appendKeyValue("error", "Object not found.");
}
}
@@ -196,23 +194,24 @@ public class JSONWebServer implements HttpHandler {
Result cur = result;
int partpos = 0;
{
- for(; partpos < parts.length; partpos++) {
+ for (; partpos < parts.length; partpos++) {
// FIXME: handle name collisions. E.g. type_123?
boolean found = false;
- for(Result child : hier.getChildren(cur)) {
+ for (Hierarchy.Iter<Result> iter = hier.iterChildren(cur); iter.valid(); iter.advance()) {
// logger.debug("Testing result: " + child.getShortName() + " <-> " +
// parts[partpos]);
- if(child.getLongName().equals(parts[partpos]) || child.getShortName().equals(parts[partpos])) {
+ Result child = iter.get();
+ if (child.getLongName().equals(parts[partpos]) || child.getShortName().equals(parts[partpos])) {
cur = child;
found = true;
break;
}
}
- if(!found) {
+ if (!found) {
break;
}
}
- if(cur == null) {
+ if (cur == null) {
re.appendKeyValue("error", "result not found.");
return;
}
@@ -220,12 +219,11 @@ public class JSONWebServer implements HttpHandler {
// logger.debug(FormatUtil.format(parts, ",") + " " + partpos + " " + cur);
// Result structure discovery via "children" parameter.
- if(parts.length == partpos + 1) {
- if("children".equals(parts[partpos])) {
+ if (parts.length == partpos + 1) {
+ if ("children".equals(parts[partpos])) {
re.appendKeyArray("children");
- Iterator<Result> iter = hier.getChildren(cur).iterator();
- while(iter.hasNext()) {
- Result child = iter.next();
+ for (Hierarchy.Iter<Result> iter = hier.iterChildren(cur); iter.valid(); iter.advance()) {
+ Result child = iter.get();
re.startHash();
re.appendKeyValue("name", child.getShortName());
re.appendKeyValue("type", child.getClass().getSimpleName());
@@ -237,14 +235,13 @@ public class JSONWebServer implements HttpHandler {
}
// Database object access
- if(cur instanceof Database) {
- if(parts.length == partpos + 1) {
+ if (cur instanceof Database) {
+ if (parts.length == partpos + 1) {
DBID id = stringToDBID(parts[partpos]);
- if(id != null) {
+ if (id != null) {
bundleToJSON(re, id);
return;
- }
- else {
+ } else {
re.appendKeyValue("error", "Object not found");
return;
}
@@ -252,15 +249,14 @@ public class JSONWebServer implements HttpHandler {
}
// Relation object access
- if(cur instanceof Relation) {
- if(parts.length == partpos + 1) {
+ if (cur instanceof Relation) {
+ if (parts.length == partpos + 1) {
Relation<?> rel = (Relation<?>) cur;
DBID id = stringToDBID(parts[partpos]);
- if(id != null) {
+ if (id != null) {
Object data = rel.get(id);
re.appendKeyValue("data", data);
- }
- else {
+ } else {
re.appendKeyValue("error", "Object not found");
return;
}
@@ -268,11 +264,11 @@ public class JSONWebServer implements HttpHandler {
}
// Neighbor access
- if(cur instanceof NeighborSetPredicate) {
- if(parts.length == partpos + 1) {
+ if (cur instanceof NeighborSetPredicate) {
+ if (parts.length == partpos + 1) {
NeighborSetPredicate pred = (NeighborSetPredicate) cur;
DBID id = stringToDBID(parts[partpos]);
- if(id != null) {
+ if (id != null) {
DBIDs neighbors = pred.getNeighborDBIDs(id);
re.appendKeyValue("DBID", id);
re.appendKeyArray("neighbors");
@@ -281,8 +277,7 @@ public class JSONWebServer implements HttpHandler {
}
re.closeArray();
return;
- }
- else {
+ } else {
re.appendKeyValue("error", "Object not found");
return;
}
@@ -290,25 +285,25 @@ public class JSONWebServer implements HttpHandler {
}
// Outlier Score access
- if(cur instanceof OutlierResult) {
+ if (cur instanceof OutlierResult) {
OutlierResult or = (OutlierResult) cur;
- if(parts.length >= partpos + 1) {
- if("table".equals(parts[partpos])) {
+ if (parts.length >= partpos + 1) {
+ if ("table".equals(parts[partpos])) {
// Handle paging
int offset = 0;
int pagesize = 100;
- if(parts.length >= partpos + 2) {
+ if (parts.length >= partpos + 2) {
offset = Integer.valueOf(parts[partpos + 1]);
}
- if(parts.length >= partpos + 3) {
+ if (parts.length >= partpos + 3) {
pagesize = Integer.valueOf(parts[partpos + 2]);
}
re.appendKeyHash("paging");
re.appendKeyValue("offset", offset);
re.appendKeyValue("pagesize", pagesize);
re.closeHash();
- if(LOG.isDebuggingFiner()) {
+ if (LOG.isDebuggingFiner()) {
re.appendNewline();
}
@@ -319,14 +314,14 @@ public class JSONWebServer implements HttpHandler {
re.appendKeyArray("scores");
Relation<Double> scores = or.getScores();
DBIDIter iter = or.getOrdering().iter(scores.getDBIDs()).iter();
- for(int i = 0; i < offset && iter.valid(); i++) {
+ for (int i = 0; i < offset && iter.valid(); i++) {
iter.advance();
}
- for(int i = 0; i < pagesize && iter.valid(); i++, iter.advance()) {
+ for (int i = 0; i < pagesize && iter.valid(); i++, iter.advance()) {
re.startHash();
bundleToJSON(re, iter);
final Double val = scores.get(iter);
- if(val != null) {
+ if (val != null) {
re.appendKeyValue("score", val);
}
re.closeHash();
@@ -354,7 +349,7 @@ public class JSONWebServer implements HttpHandler {
re.appendKeyValue("base", meta.getTheoreticalBaseline());
re.appendKeyValue("type", meta.getClass().getSimpleName());
re.closeHash();
- if(LOG.isDebuggingFiner()) {
+ if (LOG.isDebuggingFiner()) {
re.appendNewline();
}
}
@@ -362,15 +357,14 @@ public class JSONWebServer implements HttpHandler {
@Override
public void handle(HttpExchange exchange) throws IOException {
String requestMethod = exchange.getRequestMethod();
- if(!requestMethod.equalsIgnoreCase("GET")) {
+ if (!requestMethod.equalsIgnoreCase("GET")) {
return;
}
String path = exchange.getRequestURI().getPath();
// logger.debug("Request for " + path);
- if(path.startsWith(PATH_JSON)) {
+ if (path.startsWith(PATH_JSON)) {
path = path.substring(PATH_JSON.length());
- }
- else {
+ } else {
LOG.warning("Unexpected path in request handler: " + path);
throw new AbortException("Unexpected path: " + path);
}
@@ -379,13 +373,13 @@ public class JSONWebServer implements HttpHandler {
String callback = null;
{
String query = exchange.getRequestURI().getQuery();
- if(query != null) {
+ if (query != null) {
String[] frags = query.split("&");
- for(String frag : frags) {
- if(frag.startsWith("jsonp=")) {
+ for (String frag : frags) {
+ if (frag.startsWith("jsonp=")) {
callback = URLDecoder.decode(frag.substring("jsonp=".length()), "UTF-8");
}
- if(frag.startsWith("callback=")) {
+ if (frag.startsWith("callback=")) {
callback = URLDecoder.decode(frag.substring("callback=".length()), "UTF-8");
}
}
@@ -398,7 +392,7 @@ public class JSONWebServer implements HttpHandler {
// Prepare JSON response.
StringBuilder response = new StringBuilder();
{
- if(callback != null) {
+ if (callback != null) {
response.append(callback);
response.append("(");
}
@@ -409,13 +403,12 @@ public class JSONWebServer implements HttpHandler {
jsonbuf.startHash();
resultToJSON(jsonbuf, path);
jsonbuf.closeHash();
- }
- catch(Throwable e) {
+ } catch (Throwable e) {
LOG.exception("Exception occurred in embedded web server:", e);
throw (new IOException(e));
}
// wrap up
- if(callback != null) {
+ if (callback != null) {
response.append(")");
}
}
@@ -429,4 +422,4 @@ public class JSONWebServer implements HttpHandler {
responseBody.write(rbuf);
responseBody.close();
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/application/jsmap/package-info.java b/src/de/lmu/ifi/dbs/elki/application/jsmap/package-info.java
index e89e272c..458bbd93 100644
--- a/src/de/lmu/ifi/dbs/elki/application/jsmap/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/application/jsmap/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/application/package-info.java b/src/de/lmu/ifi/dbs/elki/application/package-info.java
index 35b3b3d9..b2e79f5d 100644
--- a/src/de/lmu/ifi/dbs/elki/application/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/application/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/application/visualization/KNNExplorer.java b/src/de/lmu/ifi/dbs/elki/application/visualization/KNNExplorer.java
deleted file mode 100644
index 34daefa2..00000000
--- a/src/de/lmu/ifi/dbs/elki/application/visualization/KNNExplorer.java
+++ /dev/null
@@ -1,586 +0,0 @@
-package de.lmu.ifi.dbs.elki.application.visualization;
-
-/*
- This file is part of ELKI:
- Environment for Developing KDD-Applications Supported by Index-Structures
-
- Copyright (C) 2012
- Ludwig-Maximilians-Universität München
- Lehr- und Forschungseinheit für Datenbanksysteme
- ELKI Development Team
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-import java.awt.BorderLayout;
-import java.awt.Color;
-import java.awt.Component;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.util.HashMap;
-
-import javax.swing.DefaultListCellRenderer;
-import javax.swing.DefaultListModel;
-import javax.swing.ImageIcon;
-import javax.swing.JButton;
-import javax.swing.JFrame;
-import javax.swing.JLabel;
-import javax.swing.JList;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JSpinner;
-import javax.swing.SpinnerModel;
-import javax.swing.SpinnerNumberModel;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
-import javax.swing.event.ListSelectionEvent;
-import javax.swing.event.ListSelectionListener;
-
-import org.apache.batik.util.SVGConstants;
-import org.w3c.dom.Element;
-
-import de.lmu.ifi.dbs.elki.KDDTask;
-import de.lmu.ifi.dbs.elki.application.AbstractApplication;
-import de.lmu.ifi.dbs.elki.data.NumberVector;
-import de.lmu.ifi.dbs.elki.data.VectorUtil;
-import de.lmu.ifi.dbs.elki.database.Database;
-import de.lmu.ifi.dbs.elki.database.StaticArrayDatabase;
-import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
-import de.lmu.ifi.dbs.elki.database.ids.DistanceDBIDPair;
-import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
-import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
-import de.lmu.ifi.dbs.elki.database.relation.Relation;
-import de.lmu.ifi.dbs.elki.database.relation.RelationUtil;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
-import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
-import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
-import de.lmu.ifi.dbs.elki.math.scales.LinearScale;
-import de.lmu.ifi.dbs.elki.utilities.DatabaseUtil;
-import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ClassParameter;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
-import de.lmu.ifi.dbs.elki.visualization.batikutil.JSVGSynchronizedCanvas;
-import de.lmu.ifi.dbs.elki.visualization.batikutil.LazyCanvasResizer;
-import de.lmu.ifi.dbs.elki.visualization.batikutil.NodeReplacer;
-import de.lmu.ifi.dbs.elki.visualization.css.CSSClassManager.CSSNamingConflict;
-import de.lmu.ifi.dbs.elki.visualization.savedialog.SVGSaveDialog;
-import de.lmu.ifi.dbs.elki.visualization.style.PropertiesBasedStyleLibrary;
-import de.lmu.ifi.dbs.elki.visualization.style.StyleLibrary;
-import de.lmu.ifi.dbs.elki.visualization.svg.SVGPath;
-import de.lmu.ifi.dbs.elki.visualization.svg.SVGPlot;
-import de.lmu.ifi.dbs.elki.visualization.svg.SVGSimpleLinearAxis;
-import de.lmu.ifi.dbs.elki.visualization.svg.SVGUtil;
-
-/**
- * User application to explore the k Nearest Neighbors for a given data set and
- * distance function. When selecting one or more data entries, the nearest
- * neighbors each are determined and visualized.
- *
- * <p>
- * Reference:<br/>
- *
- * Elke Achtert, Thomas Bernecker, Hans-Peter Kriegel, Erich Schubert, Arthur
- * Zimek:<br/>
- *
- * ELKI in Time: ELKI 0.2 for the Performance Evaluation of Distance Measures
- * for Time Series.<br/>
- *
- * In Proc. 11th International Symposium on Spatial and Temporal Databases (SSTD
- * 2009), Aalborg, Denmark, 2009.
- * </p>
- *
- * <h3>Usage example:</h3>
- *
- * <p>
- * Main invocation:<br/>
- *
- * <code>java -cp elki.jar de.lmu.ifi.dbs.elki.application.visualization.KNNExplorer</code>
- * </p>
- *
- * <p>
- * The application supports the usual parameterization, in particular parameters
- * <code>-dbc.in</code> and <code>-explorer.distancefunction</code> to select an
- * input file and the distance function to explore.
- * </p>
- *
- * @author Erich Schubert
- *
- * @apiviz.composedOf ExplorerWindow
- *
- * @param <O> Object type
- * @param <D> Distance type
- */
-@Reference(authors = "E. Achtert, T. Bernecker, H.-P. Kriegel, E. Schubert, A. Zimek", title = "ELKI in Time: ELKI 0.2 for the Performance Evaluation of Distance Measures for Time Series", booktitle = "Proceedings of the 11th International Symposium on Spatial and Temporal Databases (SSTD), Aalborg, Denmark, 2009", url = "http://dx.doi.org/10.1007/978-3-642-02982-0_35")
-public class KNNExplorer<O extends NumberVector<?>, D extends NumberDistance<D, ?>> extends AbstractApplication {
- // TODO: replace by a wrapper creating appropriate visualization modules.
-
- /**
- * Parameter to specify the distance function to determine the distance
- * between database objects, must extend
- * {@link de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction}.
- * <p>
- * Key: {@code -explorer.distancefunction}
- * </p>
- * <p>
- * Default value:
- * {@link de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction}
- * </p>
- */
- public static final OptionID DISTANCE_FUNCTION_ID = new OptionID("explorer.distancefunction", "Distance function to determine the distance between database objects.");
-
- /**
- * Holds the database connection to have the algorithm run with.
- */
- private Database database;
-
- /**
- * Holds the instance of the distance function specified by
- * {@link #DISTANCE_FUNCTION_ID}.
- */
- private DistanceFunction<O, D> distanceFunction;
-
- /**
- * Constructor.
- *
- * @param database Database
- * @param distanceFunction Distance function
- */
- public KNNExplorer(Database database, DistanceFunction<O, D> distanceFunction) {
- super();
- this.database = database;
- this.distanceFunction = distanceFunction;
- }
-
- @Override
- public void run() throws IllegalStateException {
- database.initialize();
- Relation<O> relation = database.getRelation(distanceFunction.getInputTypeRestriction());
- DistanceQuery<O, D> distFunc = database.getDistanceQuery(relation, distanceFunction);
- (new ExplorerWindow()).run(database, distFunc);
- }
-
- /**
- * Main window of KNN Explorer.
- *
- * @author Erich Schubert
- */
- class ExplorerWindow {
- /**
- * Default Window Title
- */
- private static final String WINDOW_TITLE_BASE = "ELKI k Nearest Neighbors Explorer";
-
- /**
- * Maximum resolution for plotted lines to improve performance for long time
- * series.
- */
- private static final int MAXRESOLUTION = 1000;
-
- /**
- * SVG graph object ID (for replacing)
- */
- private static final String SERIESID = "series";
-
- // The frame.
- protected JFrame frame = new JFrame(WINDOW_TITLE_BASE);
-
- // The spinner
- protected JSpinner spinner;
-
- // The list of series
- private JList seriesList = new JList();
-
- // The "Quit" button, to close the application.
- protected JButton quitButton = new JButton("Quit");
-
- // The "Export" button, to save the image
- protected JButton saveButton = new JButton("Export");
-
- // The SVG canvas.
- protected JSVGSynchronizedCanvas svgCanvas = new JSVGSynchronizedCanvas();
-
- // The plot
- SVGPlot plot;
-
- // Viewport
- Element viewport;
-
- // Dimensionality
- protected int dim;
-
- // k
- protected int k = 20;
-
- // Scale
- protected LinearScale s;
-
- // The current database
- protected Relation<? extends O> data;
-
- // Distance cache
- protected HashMap<DBID, Double> distancecache = new HashMap<DBID, Double>();
-
- // Canvas scaling ratio
- protected double ratio;
-
- /**
- * Holds the instance of the distance function specified by
- * {@link #DISTANCE_FUNCTION_ID}.
- */
- private DistanceQuery<O, D> distanceQuery;
-
- /**
- * Holds the associated kNN query
- */
- private KNNQuery<O, D> knnQuery;
-
- /**
- * The label representation
- */
- protected Relation<String> labelRep;
-
- private Database db;
-
- /**
- * Constructor.
- */
- public ExplorerWindow() {
- super();
-
- frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
-
- // ELKI icon
- try {
- frame.setIconImage(new ImageIcon(KDDTask.class.getResource("elki-icon.png")).getImage());
- }
- catch(Exception e) {
- // Ignore - icon not found is not fatal.
- }
-
- // Create a panel and add the button, status label and the SVG canvas.
- final JPanel bigpanel = new JPanel(new BorderLayout());
-
- // set up spinner
- SpinnerModel model = new SpinnerNumberModel(k, 1, 1000, 1);
- spinner = new JSpinner(model);
- JPanel spinnerPanel = new JPanel(new BorderLayout());
- spinnerPanel.add(BorderLayout.WEST, new JLabel("k"));
- spinnerPanel.add(BorderLayout.EAST, spinner);
-
- // button panel
- JPanel buttonPanel = new JPanel(new BorderLayout());
- buttonPanel.add(BorderLayout.WEST, saveButton);
- buttonPanel.add(BorderLayout.EAST, quitButton);
-
- // set up cell renderer
- seriesList.setCellRenderer(new SeriesLabelRenderer());
-
- JPanel sidepanel = new JPanel(new BorderLayout());
- sidepanel.add(BorderLayout.NORTH, spinnerPanel);
- sidepanel.add(BorderLayout.CENTER, new JScrollPane(seriesList));
- sidepanel.add(BorderLayout.SOUTH, buttonPanel);
-
- bigpanel.add(BorderLayout.WEST, sidepanel);
- bigpanel.add(BorderLayout.CENTER, svgCanvas);
-
- frame.getContentPane().add(bigpanel);
-
- spinner.addChangeListener(new ChangeListener() {
- @Override
- public void stateChanged(ChangeEvent e) {
- updateK((Integer) (spinner.getValue()));
- updateSelection();
- }
- });
-
- seriesList.addListSelectionListener(new ListSelectionListener() {
- @Override
- public void valueChanged(ListSelectionEvent e) {
- if(!e.getValueIsAdjusting()) {
- updateSelection();
- }
- }
- });
-
- saveButton.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent ae) {
- SVGSaveDialog.showSaveDialog(plot, 512, 512);
- }
- });
-
- quitButton.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- frame.setVisible(false);
- frame.dispose();
- }
- });
-
- // display
- frame.setSize(600, 600);
-
- // resize listener
- LazyCanvasResizer listener = new LazyCanvasResizer(frame) {
- @Override
- public void executeResize(double newratio) {
- ratio = newratio;
- updateSize();
- updateSelection();
- }
- };
- ratio = listener.getActiveRatio();
- frame.addComponentListener(listener);
- }
-
- /**
- * Update the SVG plot size.
- */
- public void updateSize() {
- SVGUtil.setAtt(plot.getRoot(), SVGConstants.SVG_VIEW_BOX_ATTRIBUTE, "0 0 " + ratio + " 1");
- SVGUtil.setAtt(viewport, SVGConstants.SVG_WIDTH_ATTRIBUTE, ratio);
- SVGUtil.setAtt(viewport, SVGConstants.SVG_HEIGHT_ATTRIBUTE, "1");
- SVGUtil.setAtt(viewport, SVGConstants.SVG_VIEW_BOX_ATTRIBUTE, (-0.1 * StyleLibrary.SCALE) + " " + (-0.1 * StyleLibrary.SCALE) + " " + (ratio + 0.2) * StyleLibrary.SCALE + " " + 1.2 * StyleLibrary.SCALE);
- }
-
- /**
- * Process the given Database and distance function.
- *
- * @param db Database
- * @param distanceQuery Distance function
- */
- public void run(Database db, DistanceQuery<O, D> distanceQuery) {
- this.db = db;
- this.data = distanceQuery.getRelation();
- this.labelRep = DatabaseUtil.guessObjectLabelRepresentation(db);
- this.dim = RelationUtil.dimensionality(distanceQuery.getRelation());
- this.distanceQuery = distanceQuery;
- this.updateK(k);
-
- double min = Double.MAX_VALUE;
- double max = Double.MIN_VALUE;
- for(DBIDIter iditer = data.iterDBIDs(); iditer.valid(); iditer.advance()) {
- O vec = data.get(iditer);
- DoubleMinMax mm = VectorUtil.getRangeDouble(vec);
- min = Math.min(min, mm.getMin());
- max = Math.max(max, mm.getMax());
- }
- this.s = new LinearScale(min, max);
-
- this.frame.setTitle(distanceQuery.getClass().getSimpleName() + " - " + WINDOW_TITLE_BASE);
-
- plot = new SVGPlot();
- viewport = plot.svgElement(SVGConstants.SVG_SVG_TAG);
- plot.getRoot().appendChild(viewport);
- updateSize();
-
- try {
- StyleLibrary style = new PropertiesBasedStyleLibrary();
- SVGSimpleLinearAxis.drawAxis(plot, viewport, this.s, 0.0, StyleLibrary.SCALE, 0.0, 0.0, SVGSimpleLinearAxis.LabelStyle.LEFTHAND, style);
- }
- catch(CSSNamingConflict e) {
- LoggingUtil.exception(e);
- }
- plot.updateStyleElement();
-
- // insert the actual data series.
- Element egroup = plot.svgElement(SVGConstants.SVG_G_TAG);
- SVGUtil.setAtt(egroup, SVGConstants.SVG_ID_ATTRIBUTE, SERIESID);
- viewport.appendChild(egroup);
- plot.putIdElement(SERIESID, egroup);
-
- svgCanvas.setPlot(plot);
-
- DefaultListModel m = new DefaultListModel();
- for(DBIDIter iditer = data.iterDBIDs(); iditer.valid(); iditer.advance()) {
- m.addElement(DBIDUtil.deref(iditer));
- }
- seriesList.setModel(m);
-
- frame.setVisible(true);
- }
-
- void updateK(int k) {
- this.k = k;
- knnQuery = db.getKNNQuery(distanceQuery, k);
- }
-
- /**
- * Process the users new selection.
- */
- protected void updateSelection() {
- Object[] sel = seriesList.getSelectedValues();
- // prepare replacement tag.
- Element newe = plot.svgElement(SVGConstants.SVG_G_TAG);
- SVGUtil.setAtt(newe, SVGConstants.SVG_ID_ATTRIBUTE, SERIESID);
-
- distancecache.clear();
-
- for(Object o : sel) {
- DBID idx = (DBID) o;
-
- KNNResult<D> knn = knnQuery.getKNNForDBID(idx, k);
-
- double maxdist = knn.getKNNDistance().doubleValue();
- // avoid division by zero.
- if(maxdist == 0) {
- maxdist = 1;
- }
-
- for (int i = knn.size() - 1; i >= 0; i--) {
- DistanceDBIDPair<D> pair = knn.get(i);
- Element line = plotSeries(pair, MAXRESOLUTION);
- double dist = pair.getDistance().doubleValue() / maxdist;
- Color color = getColor(dist);
- String colstr = "#" + Integer.toHexString(color.getRGB()).substring(2);
- String width = (DBIDUtil.equal(pair, idx)) ? "0.5%" : "0.2%";
- SVGUtil.setStyle(line, "stroke: " + colstr + "; stroke-width: " + width + "; fill: none");
- newe.appendChild(line);
- // put into cache
- Double known = distancecache.get(DBIDUtil.deref(pair));
- if(known == null || dist < known) {
- distancecache.put(DBIDUtil.deref(pair), dist);
- }
- }
- }
- plot.scheduleUpdate(new NodeReplacer(newe, plot, SERIESID));
- seriesList.repaint();
- }
-
- /**
- * Get the appropriate color for the given distance.
- *
- * @param dist Distance
- * @return Color
- */
- Color getColor(double dist) {
- Color color = new Color((int) (255 * dist), 0, (int) (255 * (1.0 - dist)));
- return color;
- }
-
- /**
- * Plot a single time series.
- *
- * @param idx Object index
- * @param resolution Maximum number of steps to plot
- * @return SVG element
- */
- private Element plotSeries(DBIDRef idx, int resolution) {
- O series = data.get(idx);
-
- double step = 1.0;
- if(resolution < dim) {
- step = (double) dim / (double) resolution;
- }
-
- SVGPath path = new SVGPath();
- for(double id = 0; id < dim; id += step) {
- int i = (int) Math.floor(id);
- path.drawTo(StyleLibrary.SCALE * ratio * (((double) i) / (dim - 1)), StyleLibrary.SCALE * (1.0 - s.getScaled(series.doubleValue(i))));
- }
- Element p = path.makeElement(plot);
- return p;
- }
-
- /**
- * Renderer for the labels, with coloring as in the plot.
- *
- * @author Erich Schubert
- *
- * @apiviz.exclude
- */
- private class SeriesLabelRenderer extends DefaultListCellRenderer {
- /**
- * Serial version
- */
- private static final long serialVersionUID = 1L;
-
- /**
- * Constructor.
- */
- public SeriesLabelRenderer() {
- super();
- }
-
- @Override
- public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
- String label = null;
- if(label == null || label == "") {
- label = labelRep.get((DBID) value);
- }
- if(label == null || label == "") {
- label = ((DBID) value).toString();
- }
- // setText(label);
- Component renderer = super.getListCellRendererComponent(list, label, index, isSelected, cellHasFocus);
- Double known = distancecache.get(value);
- if(known != null) {
- setBackground(getColor(known));
- }
- return renderer;
- }
- }
- }
-
- /**
- * Parameterization class.
- *
- * @author Erich Schubert
- *
- * @apiviz.exclude
- */
- public static class Parameterizer<O extends NumberVector<?>, D extends NumberDistance<D, ?>> extends AbstractApplication.Parameterizer {
- protected Database database = null;
-
- protected DistanceFunction<O, D> distanceFunction = null;
-
- @Override
- protected void makeOptions(Parameterization config) {
- super.makeOptions(config);
- // parameter database connection
- final ObjectParameter<Database> dbpar = new ObjectParameter<Database>(OptionID.DATABASE_CONNECTION, Database.class, StaticArrayDatabase.class);
- if(config.grab(dbpar)) {
- database = dbpar.instantiateClass(config);
- }
-
- // Distance function
- final ClassParameter<DistanceFunction<O, D>> dfpar = new ClassParameter<DistanceFunction<O, D>>(DISTANCE_FUNCTION_ID, DistanceFunction.class, EuclideanDistanceFunction.class);
- if(config.grab(dfpar)) {
- distanceFunction = dfpar.instantiateClass(config);
- }
- }
-
- @Override
- protected KNNExplorer<O, D> makeInstance() {
- return new KNNExplorer<O, D>(database, distanceFunction);
- }
- }
-
- /**
- * Main method to run this application.
- *
- * @param args the arguments to run this application
- */
- public static void main(String[] args) {
- runCLIApplication(KNNExplorer.class, args);
- }
-} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/data/AbstractNumberVector.java b/src/de/lmu/ifi/dbs/elki/data/AbstractNumberVector.java
index 95e81891..aec6a579 100644
--- a/src/de/lmu/ifi/dbs/elki/data/AbstractNumberVector.java
+++ b/src/de/lmu/ifi/dbs/elki/data/AbstractNumberVector.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/Arithmetic.java b/src/de/lmu/ifi/dbs/elki/data/Arithmetic.java
index 534f7717..c9236539 100644
--- a/src/de/lmu/ifi/dbs/elki/data/Arithmetic.java
+++ b/src/de/lmu/ifi/dbs/elki/data/Arithmetic.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/Bit.java b/src/de/lmu/ifi/dbs/elki/data/Bit.java
index 7272e235..219ac2dd 100644
--- a/src/de/lmu/ifi/dbs/elki/data/Bit.java
+++ b/src/de/lmu/ifi/dbs/elki/data/Bit.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/BitVector.java b/src/de/lmu/ifi/dbs/elki/data/BitVector.java
index d662af66..750f6f5b 100644
--- a/src/de/lmu/ifi/dbs/elki/data/BitVector.java
+++ b/src/de/lmu/ifi/dbs/elki/data/BitVector.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/ClassLabel.java b/src/de/lmu/ifi/dbs/elki/data/ClassLabel.java
index ce3b76a9..96df671d 100644
--- a/src/de/lmu/ifi/dbs/elki/data/ClassLabel.java
+++ b/src/de/lmu/ifi/dbs/elki/data/ClassLabel.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,7 +26,6 @@ package de.lmu.ifi.dbs.elki.data;
import java.util.HashMap;
import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
-import de.lmu.ifi.dbs.elki.utilities.InspectionUtilFrequentlyScanned;
/**
* A ClassLabel to identify a certain class of objects that is to discern from
@@ -88,11 +87,11 @@ public abstract class ClassLabel implements Comparable<ClassLabel> {
* @apiviz.has ClassLabel - - «creates»
* @apiviz.stereotype factory
*/
- public abstract static class Factory<L extends ClassLabel> implements InspectionUtilFrequentlyScanned {
+ public abstract static class Factory<L extends ClassLabel> {
/**
* Set for reusing the same objects.
*/
- protected HashMap<String, L> existing = new HashMap<String, L>();
+ protected HashMap<String, L> existing = new HashMap<>();
/**
* Convert a string into a class label.
diff --git a/src/de/lmu/ifi/dbs/elki/data/Cluster.java b/src/de/lmu/ifi/dbs/elki/data/Cluster.java
index 95e9fb6a..00e1b693 100644
--- a/src/de/lmu/ifi/dbs/elki/data/Cluster.java
+++ b/src/de/lmu/ifi/dbs/elki/data/Cluster.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,21 +23,12 @@ package de.lmu.ifi.dbs.elki.data;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.ArrayList;
import java.util.Comparator;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
import de.lmu.ifi.dbs.elki.data.model.Model;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.result.textwriter.TextWriteable;
import de.lmu.ifi.dbs.elki.result.textwriter.TextWriterStream;
-import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.Hierarchical;
-import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.Hierarchy;
-import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.HierarchyReferenceLists;
-import de.lmu.ifi.dbs.elki.utilities.iterator.EmptyIterator;
/**
* Generic cluster class, that may or not have hierarchical information. Note
@@ -53,23 +44,13 @@ import de.lmu.ifi.dbs.elki.utilities.iterator.EmptyIterator;
* @param <M> Model object type
*
* @author Erich Schubert
- *
+ *
* @apiviz.landmark
*
* @apiviz.composedOf DBIDs
* @apiviz.composedOf Model
- * @apiviz.has Hierarchy
*/
-// TODO: return unmodifiable collections?
-// TODO: disallow clusters without a DBIDs?
-// TODO: add Model interface and delegations consequently since we have the
-// DBID group and hierarchy delegators?
-public class Cluster<M extends Model> implements Hierarchical<Cluster<M>>, TextWriteable {
- /**
- * Object that the hierarchy management is delegated to.
- */
- private Hierarchy<Cluster<M>> hierarchy = null;
-
+public class Cluster<M extends Model> implements TextWriteable {
/**
* Cluster name.
*/
@@ -97,44 +78,13 @@ public class Cluster<M extends Model> implements Hierarchical<Cluster<M>>, TextW
* @param ids Object Group
* @param noise Noise flag
* @param model Model. May be null.
- * @param hierarchy Hierarchy object. May be null.
*/
- public Cluster(String name, DBIDs ids, boolean noise, M model, Hierarchy<Cluster<M>> hierarchy) {
+ public Cluster(String name, DBIDs ids, boolean noise, M model) {
super();
- // TODO: any way to check that this is a C? (see asC() method)
this.name = name;
this.ids = ids;
this.noise = noise;
this.model = model;
- this.hierarchy = hierarchy;
- }
-
- /**
- * Constructor with hierarchy information. A new FullHierarchy object will be
- * created to store the hierarchy information.
- *
- * @param name Cluster name. May be null.
- * @param ids Object Group
- * @param noise Noise flag
- * @param model Model. May be null.
- * @param children Children. Will NOT be copied.
- * @param parents Parents. Will NOT be copied.
- */
- public Cluster(String name, DBIDs ids, boolean noise, M model, List<Cluster<M>> children, List<Cluster<M>> parents) {
- this(name, ids, noise, model, null);
- this.setHierarchy(new HierarchyReferenceLists<Cluster<M>>(this, children, parents));
- }
-
- /**
- * Constructor without hierarchy information.
- *
- * @param name Cluster name. May be null.
- * @param ids Object group
- * @param noise Noise flag
- * @param model Model
- */
- public Cluster(String name, DBIDs ids, boolean noise, M model) {
- this(name, ids, noise, model, null);
}
/**
@@ -145,7 +95,7 @@ public class Cluster<M extends Model> implements Hierarchical<Cluster<M>>, TextW
* @param model Model
*/
public Cluster(String name, DBIDs ids, M model) {
- this(name, ids, false, model, null);
+ this(name, ids, false, model);
}
/**
@@ -156,7 +106,7 @@ public class Cluster<M extends Model> implements Hierarchical<Cluster<M>>, TextW
* @param model Model
*/
public Cluster(DBIDs ids, boolean noise, M model) {
- this(null, ids, noise, model, null);
+ this(null, ids, noise, model);
}
/**
@@ -166,7 +116,7 @@ public class Cluster<M extends Model> implements Hierarchical<Cluster<M>>, TextW
* @param model Model
*/
public Cluster(DBIDs ids, M model) {
- this(null, ids, false, model, null);
+ this(null, ids, false, model);
}
/**
@@ -177,7 +127,7 @@ public class Cluster<M extends Model> implements Hierarchical<Cluster<M>>, TextW
* @param noise Noise flag
*/
public Cluster(String name, DBIDs ids, boolean noise) {
- this(name, ids, noise, null, null);
+ this(name, ids, noise, null);
}
/**
@@ -187,7 +137,7 @@ public class Cluster<M extends Model> implements Hierarchical<Cluster<M>>, TextW
* @param ids Object group
*/
public Cluster(String name, DBIDs ids) {
- this(name, ids, false, null, null);
+ this(name, ids, false, null);
}
/**
@@ -197,7 +147,7 @@ public class Cluster<M extends Model> implements Hierarchical<Cluster<M>>, TextW
* @param noise Noise flag
*/
public Cluster(DBIDs ids, boolean noise) {
- this(null, ids, noise, null, null);
+ this(null, ids, noise, null);
}
/**
@@ -206,125 +156,7 @@ public class Cluster<M extends Model> implements Hierarchical<Cluster<M>>, TextW
* @param ids Object group
*/
public Cluster(DBIDs ids) {
- this(null, ids, false, null, null);
- }
-
- /**
- * Constructor with hierarchy but noise flag defaulting to false.
- *
- * @param name Cluster name. May be null.
- * @param ids Object group
- * @param model Model. May be null.
- * @param hierarchy Hierarchy object. May be null.
- */
- public Cluster(String name, DBIDs ids, M model, Hierarchy<Cluster<M>> hierarchy) {
- this(name, ids, false, model, hierarchy);
- }
-
- /**
- * Constructor with hierarchy information, but no noise flag. A new
- * FullHierarchy object will be created to store the hierarchy information.
- *
- * @param name Cluster name. May be null.
- * @param ids Object Group
- * @param model Model. May be null.
- * @param children Children. Will NOT be copied.
- * @param parents Parents. Will NOT be copied.
- */
- public Cluster(String name, DBIDs ids, M model, List<Cluster<M>> children, List<Cluster<M>> parents) {
- this(name, ids, false, model, null);
- this.setHierarchy(new HierarchyReferenceLists<Cluster<M>>(this, children, parents));
- }
-
- /**
- * Test hierarchy
- */
- @Override
- public final boolean isHierarchical() {
- if(hierarchy == null) {
- return false;
- }
- return true;
- }
-
- /**
- * Delegate to hierarchy object
- */
- @Override
- public int numChildren() {
- if(hierarchy == null) {
- return 0;
- }
- return hierarchy.numChildren(this);
- }
-
- /**
- * Delegate to hierarchy object
- */
- @Override
- public List<Cluster<M>> getChildren() {
- if(hierarchy == null) {
- return new ArrayList<Cluster<M>>(0);
- }
- return hierarchy.getChildren(this);
- }
-
- /**
- * Delegate to hierarchy object
- */
- @Override
- public Iterator<Cluster<M>> iterDescendants() {
- if(hierarchy == null) {
- return EmptyIterator.STATIC();
- }
- return hierarchy.iterDescendants(this);
- }
-
- /**
- * Collect descendants
- *
- * @return Set of descendants
- */
- public Set<Cluster<M>> getDescendants() {
- HashSet<Cluster<M>> set = new HashSet<Cluster<M>>();
- // add all
- for(Iterator<Cluster<M>> iter = iterDescendants(); iter.hasNext();) {
- set.add(iter.next());
- }
- return set;
- }
-
- /**
- * Delegate to hierarchy object
- */
- @Override
- public int numParents() {
- if(hierarchy == null) {
- return 0;
- }
- return hierarchy.numParents(this);
- }
-
- /**
- * Delegate to hierarchy object
- */
- @Override
- public List<Cluster<M>> getParents() {
- if(hierarchy == null) {
- return new ArrayList<Cluster<M>>(0);
- }
- return hierarchy.getParents(this);
- }
-
- /**
- * Delegate to hierarchy object
- */
- @Override
- public Iterator<Cluster<M>> iterAncestors() {
- if(hierarchy == null) {
- return EmptyIterator.STATIC();
- }
- return hierarchy.iterAncestors(this);
+ this(null, ids, false, null);
}
/**
@@ -337,36 +169,17 @@ public class Cluster<M extends Model> implements Hierarchical<Cluster<M>>, TextW
}
/**
- * Get hierarchy object
- *
- * @return hierarchy object
- */
- public Hierarchy<Cluster<M>> getHierarchy() {
- return hierarchy;
- }
-
- /**
- * Set hierarchy object
- *
- * @param hierarchy new hierarchy object
- */
- public void setHierarchy(Hierarchy<Cluster<M>> hierarchy) {
- this.hierarchy = hierarchy;
- }
-
- /**
* Return either the assigned name or the suggested label
*
* @return a name for the cluster
*/
public String getNameAutomatic() {
- if(name != null) {
+ if (name != null) {
return name;
}
- if(isNoise()) {
+ if (isNoise()) {
return "Noise";
- }
- else {
+ } else {
return "Cluster";
}
}
@@ -436,34 +249,25 @@ public class Cluster<M extends Model> implements Hierarchical<Cluster<M>>, TextW
public void writeToText(TextWriterStream out, String label) {
String name = getNameAutomatic();
out.commentPrintLn(TextWriterStream.SER_MARKER + " " + Cluster.class.getName());
- if(name != null) {
+ if (name != null) {
out.commentPrintLn("Name: " + name);
}
out.commentPrintLn("Noise flag: " + isNoise());
out.commentPrintLn("Size: " + ids.size());
// print hierarchy information.
- if(isHierarchical()) {
- out.commentPrint("Parents: ");
- for(int i = 0; i < numParents(); i++) {
- if(i > 0) {
- out.commentPrint(", ");
- }
- out.commentPrint(getParents().get(i).getNameAutomatic());
- }
- out.commentPrintLn();
- out.commentPrint("Children: ");
- for(int i = 0; i < numChildren(); i++) {
- if(i > 0) {
- out.commentPrint(", ");
- }
- out.commentPrint(getChildren().get(i).getNameAutomatic());
- }
- out.commentPrintLn();
- }
+ /*
+ * if (isHierarchical()) { out.commentPrint("Parents: "); for (int i = 0; i
+ * < numParents(); i++) { if (i > 0) { out.commentPrint(", "); }
+ * out.commentPrint(getParents().get(i).getNameAutomatic()); }
+ * out.commentPrintLn(); out.commentPrint("Children: "); for (int i = 0; i <
+ * numChildren(); i++) { if (i > 0) { out.commentPrint(", "); }
+ * out.commentPrint(getChildren().get(i).getNameAutomatic()); }
+ * out.commentPrintLn(); }
+ */
// also print model, if any and printable
- if(getModel() != null) {
+ if (getModel() != null) {
out.commentPrintLn("Model class: " + getModel().getClass().getName());
- if(getModel() instanceof TextWriteable) {
+ if (getModel() instanceof TextWriteable) {
((TextWriteable) getModel()).writeToText(out, label);
}
}
@@ -491,31 +295,27 @@ public class Cluster<M extends Model> implements Hierarchical<Cluster<M>>, TextW
* A partial comparator for Clusters, based on their name. Useful for sorting
* clusters. Do NOT use in e.g. a TreeSet since it is
* <em>inconsistent with equals</em>.
- *
- * @author Erich Schubert
- *
- * @apiviz.exclude
*/
- public static class PartialComparator implements Comparator<Cluster<?>> {
+ public static Comparator<Cluster<?>> BY_NAME_SORTER = new Comparator<Cluster<?>>() {
@Override
public int compare(Cluster<?> o1, Cluster<?> o2) {
- if(o1 == o2) {
+ if (o1 == o2) {
return 0;
}
// sort by label if possible
- if(o1 != null && o1.name != null && o2 != null && o2.name != null) {
+ if (o1 != null && o1.name != null && o2 != null && o2.name != null) {
int lblresult = o1.name.compareTo(o2.getName());
- if(lblresult != 0) {
+ if (lblresult != 0) {
return lblresult;
}
}
int hashresult = o1.hashCode() - o2.hashCode();
- if(hashresult != 0) {
+ if (hashresult != 0) {
return hashresult;
}
return 0;
}
- }
+ };
/** {@inheritDoc} */
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/data/Clustering.java b/src/de/lmu/ifi/dbs/elki/data/Clustering.java
index f4312c4c..ae70662e 100644
--- a/src/de/lmu/ifi/dbs/elki/data/Clustering.java
+++ b/src/de/lmu/ifi/dbs/elki/data/Clustering.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,13 +25,15 @@ package de.lmu.ifi.dbs.elki.data;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
-import java.util.Set;
import de.lmu.ifi.dbs.elki.data.model.Model;
import de.lmu.ifi.dbs.elki.result.BasicResult;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.HashMapHierarchy;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.Hierarchy;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.Hierarchy.Iter;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.ModifiableHierarchy;
/**
* Result class for clusterings. Can be used for both hierarchical and
@@ -41,8 +43,9 @@ import de.lmu.ifi.dbs.elki.result.BasicResult;
* instead they can be an arbitrary forest of directed graphs that COULD contain
* cycles.
*
- * This class is NOT iterable for a simple reason: there is more than one method to do so.
- * You need to specify whether you want to use getToplevelClusters() or getAllClusters().
+ * This class is NOT iterable for a simple reason: there is more than one method
+ * to do so. You need to specify whether you want to use getToplevelClusters()
+ * or getAllClusters().
*
* @author Erich Schubert
*
@@ -57,6 +60,11 @@ public class Clustering<M extends Model> extends BasicResult {
private List<Cluster<M>> toplevelclusters;
/**
+ * Cluster hierarchy.
+ */
+ private ModifiableHierarchy<Cluster<M>> hierarchy;
+
+ /**
* Constructor with a list of top level clusters
*
* @param name The long name (for pretty printing)
@@ -66,6 +74,7 @@ public class Clustering<M extends Model> extends BasicResult {
public Clustering(String name, String shortname, List<Cluster<M>> toplevelclusters) {
super(name, shortname);
this.toplevelclusters = toplevelclusters;
+ this.hierarchy = new HashMapHierarchy<>();
}
/**
@@ -81,10 +90,21 @@ public class Clustering<M extends Model> extends BasicResult {
/**
* Add a cluster to the clustering.
*
- * @param n new cluster
+ * @param clus new cluster
+ */
+ public void addToplevelCluster(Cluster<M> clus) {
+ toplevelclusters.add(clus);
+ hierarchy.add(clus);
+ }
+
+ /**
+ * Add a cluster to the clustering.
+ *
+ * @param parent Parent cluster
+ * @param child Child cluster.
*/
- public void addCluster(Cluster<M> n) {
- toplevelclusters.add(n);
+ public void addChildCluster(Cluster<M> parent, Cluster<M> child) {
+ hierarchy.add(parent, child);
}
/**
@@ -97,24 +117,62 @@ public class Clustering<M extends Model> extends BasicResult {
}
/**
+ * Get the cluster hierarchy.
+ *
+ * @return Cluster hierarchy.
+ */
+ public Hierarchy<Cluster<M>> getClusterHierarchy() {
+ return hierarchy;
+ }
+
+ /**
* Collect all clusters (recursively) into a List.
*
* @return List of all clusters.
*/
public List<Cluster<M>> getAllClusters() {
- Set<Cluster<M>> clu = new HashSet<Cluster<M>>();
- for(Cluster<M> rc : toplevelclusters) {
- if(!clu.contains(rc)) {
- clu.add(rc);
- for (Iterator<Cluster<M>> iter = rc.iterDescendants(); iter.hasNext(); ) {
- clu.add(iter.next());
- }
- }
+ ArrayList<Cluster<M>> res = new ArrayList<>(hierarchy.size());
+ for (Hierarchy.Iter<Cluster<M>> iter = hierarchy.iterAll(); iter.valid(); iter.advance()) {
+ res.add(iter.get());
}
- // Note: we canNOT use TreeSet above, because this comparator is only
- // partial!
- ArrayList<Cluster<M>> res = new ArrayList<Cluster<M>>(clu);
- Collections.sort(res, new Cluster.PartialComparator());
+ Collections.sort(res, Cluster.BY_NAME_SORTER);
return res;
}
+
+ /**
+ * Iterate over the top level clusters.
+ *
+ * @return Iterator
+ */
+ public Iter<Cluster<M>> iterToplevelClusters() {
+ return new Hierarchy.Iter<Cluster<M>>() {
+ Iterator<Cluster<M>> iter;
+
+ Cluster<M> cur;
+
+ { // Constructor.
+ iter = toplevelclusters.iterator();
+ advance();
+ }
+
+ @Override
+ public boolean valid() {
+ return cur != null;
+ }
+
+ @Override
+ public void advance() {
+ if (iter.hasNext()) {
+ cur = iter.next();
+ } else {
+ cur = null;
+ }
+ }
+
+ @Override
+ public Cluster<M> get() {
+ return cur;
+ }
+ };
+ }
}
diff --git a/src/de/lmu/ifi/dbs/elki/data/DoubleVector.java b/src/de/lmu/ifi/dbs/elki/data/DoubleVector.java
index dfc0a316..6c13c342 100644
--- a/src/de/lmu/ifi/dbs/elki/data/DoubleVector.java
+++ b/src/de/lmu/ifi/dbs/elki/data/DoubleVector.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -142,29 +142,17 @@ public class DoubleVector extends AbstractNumberVector<Double> {
@Override
@Deprecated
public Double getValue(int dimension) {
- try {
- return values[dimension];
- } catch (IndexOutOfBoundsException e) {
- throw new IllegalArgumentException("Dimension " + dimension + " out of range.");
- }
+ return values[dimension];
}
@Override
public double doubleValue(int dimension) {
- try {
- return values[dimension];
- } catch (IndexOutOfBoundsException e) {
- throw new IllegalArgumentException("Dimension " + dimension + " out of range.");
- }
+ return values[dimension];
}
@Override
public long longValue(int dimension) {
- try {
- return (long) values[dimension];
- } catch (IndexOutOfBoundsException e) {
- throw new IllegalArgumentException("Dimension " + dimension + " out of range.");
- }
+ return (long) values[dimension];
}
/**
@@ -354,7 +342,6 @@ public class DoubleVector extends AbstractNumberVector<Double> {
@Override
public void toByteBuffer(ByteBuffer buffer, DoubleVector vec) throws IOException {
- assert (vec.values.length < Short.MAX_VALUE) : "This serializer only supports a maximum dimensionality of " + Short.MAX_VALUE + "!";
assert (buffer.remaining() >= ByteArrayUtil.SIZE_DOUBLE * vec.values.length);
ByteArrayUtil.writeUnsignedVarint(buffer, vec.values.length);
for (int i = 0; i < vec.values.length; i++) {
@@ -364,7 +351,6 @@ public class DoubleVector extends AbstractNumberVector<Double> {
@Override
public int getByteSize(DoubleVector vec) {
- assert (vec.values.length < Short.MAX_VALUE) : "This serializer only supports a maximum dimensionality of " + Short.MAX_VALUE + "!";
return ByteArrayUtil.getUnsignedVarintSize(vec.values.length) + ByteArrayUtil.SIZE_DOUBLE * vec.values.length;
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/data/ExternalID.java b/src/de/lmu/ifi/dbs/elki/data/ExternalID.java
index 1fc9873c..702b0431 100644
--- a/src/de/lmu/ifi/dbs/elki/data/ExternalID.java
+++ b/src/de/lmu/ifi/dbs/elki/data/ExternalID.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/FeatureVector.java b/src/de/lmu/ifi/dbs/elki/data/FeatureVector.java
index c3b255c6..f6f2f751 100644
--- a/src/de/lmu/ifi/dbs/elki/data/FeatureVector.java
+++ b/src/de/lmu/ifi/dbs/elki/data/FeatureVector.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -48,8 +48,8 @@ public interface FeatureVector<D> {
/**
* Returns the value in the specified dimension.
*
- * @param dimension the desired dimension, where 1 &le; dimension &le;
- * <code>this.getDimensionality()</code>
+ * @param dimension the desired dimension, where 0 &le; dimension &le;
+ * <code>this.getDimensionality()-1</code>
* @return the value in the specified dimension
*/
D getValue(int dimension);
diff --git a/src/de/lmu/ifi/dbs/elki/data/FloatVector.java b/src/de/lmu/ifi/dbs/elki/data/FloatVector.java
index 821c16c3..d750af01 100644
--- a/src/de/lmu/ifi/dbs/elki/data/FloatVector.java
+++ b/src/de/lmu/ifi/dbs/elki/data/FloatVector.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/HierarchicalClassLabel.java b/src/de/lmu/ifi/dbs/elki/data/HierarchicalClassLabel.java
index 3db21bd8..7e84b2bf 100644
--- a/src/de/lmu/ifi/dbs/elki/data/HierarchicalClassLabel.java
+++ b/src/de/lmu/ifi/dbs/elki/data/HierarchicalClassLabel.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -49,7 +49,7 @@ public class HierarchicalClassLabel extends ClassLabel {
/**
* Type information.
*/
- public static final SimpleTypeInformation<HierarchicalClassLabel> TYPE = new SimpleTypeInformation<HierarchicalClassLabel>(HierarchicalClassLabel.class);
+ public static final SimpleTypeInformation<HierarchicalClassLabel> TYPE = new SimpleTypeInformation<>(HierarchicalClassLabel.class);
/**
* Holds the Pattern to separate different levels parsing input.
diff --git a/src/de/lmu/ifi/dbs/elki/data/HyperBoundingBox.java b/src/de/lmu/ifi/dbs/elki/data/HyperBoundingBox.java
index 299f329b..a1533b0c 100644
--- a/src/de/lmu/ifi/dbs/elki/data/HyperBoundingBox.java
+++ b/src/de/lmu/ifi/dbs/elki/data/HyperBoundingBox.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -136,7 +136,7 @@ public class HyperBoundingBox implements SpatialComparable, Externalizable {
*/
@Override
public String toString() {
- return "[Min(" + FormatUtil.format(min, ",", FormatUtil.NF8) + "), Max(" + FormatUtil.format(max, ",", FormatUtil.NF8) + ")]";
+ return "[Min(" + FormatUtil.format(min, ",", FormatUtil.NF) + "), Max(" + FormatUtil.format(max, ",", FormatUtil.NF) + ")]";
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/data/IntegerVector.java b/src/de/lmu/ifi/dbs/elki/data/IntegerVector.java
index 595fcd94..a5f95650 100644
--- a/src/de/lmu/ifi/dbs/elki/data/IntegerVector.java
+++ b/src/de/lmu/ifi/dbs/elki/data/IntegerVector.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -98,7 +98,7 @@ public class IntegerVector extends AbstractNumberVector<Integer> {
* Returns the value of the specified attribute.
*
* @param dimension the selected attribute. Attributes are counted starting
- * with 1.
+ * with 0.
*
* @throws IllegalArgumentException if the specified dimension is out of range
* of the possible attributes
@@ -109,7 +109,7 @@ public class IntegerVector extends AbstractNumberVector<Integer> {
@Deprecated
public Integer getValue(int dimension) {
try {
- return Integer.valueOf(values[dimension - 1]);
+ return Integer.valueOf(values[dimension]);
} catch (IndexOutOfBoundsException e) {
throw new IllegalArgumentException("Dimension " + dimension + " out of range.");
}
@@ -119,7 +119,7 @@ public class IntegerVector extends AbstractNumberVector<Integer> {
* Returns the value of the specified attribute.
*
* @param dimension the selected attribute. Attributes are counted starting
- * with 1.
+ * with 0.
*
* @throws IllegalArgumentException if the specified dimension is out of range
* of the possible attributes
@@ -129,7 +129,7 @@ public class IntegerVector extends AbstractNumberVector<Integer> {
@Override
public double doubleValue(int dimension) {
try {
- return values[dimension - 1];
+ return values[dimension];
} catch (IndexOutOfBoundsException e) {
throw new IllegalArgumentException("Dimension " + dimension + " out of range.");
}
@@ -139,7 +139,7 @@ public class IntegerVector extends AbstractNumberVector<Integer> {
* Returns the value of the specified attribute as long.
*
* @param dimension the selected attribute. Attributes are counted starting
- * with 1.
+ * with 0.
*
* @throws IllegalArgumentException if the specified dimension is out of range
* of the possible attributes
@@ -149,7 +149,7 @@ public class IntegerVector extends AbstractNumberVector<Integer> {
@Override
public long longValue(int dimension) {
try {
- return values[dimension - 1];
+ return values[dimension];
} catch (IndexOutOfBoundsException e) {
throw new IllegalArgumentException("Dimension " + dimension + " out of range.");
}
diff --git a/src/de/lmu/ifi/dbs/elki/data/Interval.java b/src/de/lmu/ifi/dbs/elki/data/Interval.java
index 1b16fb88..978f9153 100644
--- a/src/de/lmu/ifi/dbs/elki/data/Interval.java
+++ b/src/de/lmu/ifi/dbs/elki/data/Interval.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/LabelList.java b/src/de/lmu/ifi/dbs/elki/data/LabelList.java
index 0301eff3..74685710 100644
--- a/src/de/lmu/ifi/dbs/elki/data/LabelList.java
+++ b/src/de/lmu/ifi/dbs/elki/data/LabelList.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/ModifiableHyperBoundingBox.java b/src/de/lmu/ifi/dbs/elki/data/ModifiableHyperBoundingBox.java
index 360fe5e9..3f1a3c8e 100644
--- a/src/de/lmu/ifi/dbs/elki/data/ModifiableHyperBoundingBox.java
+++ b/src/de/lmu/ifi/dbs/elki/data/ModifiableHyperBoundingBox.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -82,7 +82,7 @@ public class ModifiableHyperBoundingBox extends HyperBoundingBox {
* <code>dimension</code>
*/
public void setMax(int dimension, double value) {
- max[dimension - 1] = value;
+ max[dimension] = value;
}
/**
@@ -95,7 +95,7 @@ public class ModifiableHyperBoundingBox extends HyperBoundingBox {
* <code>dimension</code>
*/
public void setMin(int dimension, double value) {
- max[dimension - 1] = value;
+ max[dimension] = value;
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/data/NumberVector.java b/src/de/lmu/ifi/dbs/elki/data/NumberVector.java
index ac5e302a..4fbd36dd 100644
--- a/src/de/lmu/ifi/dbs/elki/data/NumberVector.java
+++ b/src/de/lmu/ifi/dbs/elki/data/NumberVector.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/OneDimensionalDoubleVector.java b/src/de/lmu/ifi/dbs/elki/data/OneDimensionalDoubleVector.java
index 7198d820..3412c835 100644
--- a/src/de/lmu/ifi/dbs/elki/data/OneDimensionalDoubleVector.java
+++ b/src/de/lmu/ifi/dbs/elki/data/OneDimensionalDoubleVector.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/RationalNumber.java b/src/de/lmu/ifi/dbs/elki/data/RationalNumber.java
index cf388481..6d9cbe8f 100644
--- a/src/de/lmu/ifi/dbs/elki/data/RationalNumber.java
+++ b/src/de/lmu/ifi/dbs/elki/data/RationalNumber.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/SimpleClassLabel.java b/src/de/lmu/ifi/dbs/elki/data/SimpleClassLabel.java
index b0ee779c..8799370d 100644
--- a/src/de/lmu/ifi/dbs/elki/data/SimpleClassLabel.java
+++ b/src/de/lmu/ifi/dbs/elki/data/SimpleClassLabel.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/SparseDoubleVector.java b/src/de/lmu/ifi/dbs/elki/data/SparseDoubleVector.java
index 1b07d5e9..110f3084 100644
--- a/src/de/lmu/ifi/dbs/elki/data/SparseDoubleVector.java
+++ b/src/de/lmu/ifi/dbs/elki/data/SparseDoubleVector.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,10 +28,13 @@ import gnu.trove.iterator.TIntDoubleIterator;
import gnu.trove.map.TIntDoubleMap;
import gnu.trove.map.hash.TIntDoubleHashMap;
+import java.io.IOException;
+import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.BitSet;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
+import de.lmu.ifi.dbs.elki.persistent.ByteArrayUtil;
import de.lmu.ifi.dbs.elki.persistent.ByteBufferSerializer;
import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayAdapter;
import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
@@ -47,7 +50,6 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
*
* @author Arthur Zimek
*/
-// TODO: implement ByteArraySerializer<SparseDoubleVector>
public class SparseDoubleVector extends AbstractNumberVector<Double> implements SparseNumberVector<Double> {
/**
* Static instance.
@@ -55,6 +57,11 @@ public class SparseDoubleVector extends AbstractNumberVector<Double> implements
public static final SparseDoubleVector.Factory FACTORY = new SparseDoubleVector.Factory();
/**
+ * Serializer using varint encoding.
+ */
+ public static final ByteBufferSerializer<SparseDoubleVector> VARIABLE_SERIALIZER = new VariableSerializer();
+
+ /**
* Indexes of values.
*/
private final int[] indexes;
@@ -165,7 +172,7 @@ public class SparseDoubleVector extends AbstractNumberVector<Double> implements
for (int i = 0; i < values.length; i++) {
double value = values[i];
if (value != 0.0f) {
- this.indexes[pos] = i + 1;
+ this.indexes[pos] = i;
this.values[pos] = value;
pos++;
}
@@ -296,7 +303,7 @@ public class SparseDoubleVector extends AbstractNumberVector<Double> implements
for (int i = 0; i < dim; i++) {
values[i] = adapter.get(array, i);
}
- // TODO: inefficient
+ // TODO: improve efficiency
return new SparseDoubleVector(values);
}
@@ -307,7 +314,7 @@ public class SparseDoubleVector extends AbstractNumberVector<Double> implements
for (int i = 0; i < dim; i++) {
values[i] = adapter.getDouble(array, i);
}
- // TODO: inefficient
+ // TODO: improve efficiency
return new SparseDoubleVector(values);
}
@@ -318,10 +325,9 @@ public class SparseDoubleVector extends AbstractNumberVector<Double> implements
@Override
public ByteBufferSerializer<SparseDoubleVector> getDefaultSerializer() {
- // FIXME: add a serializer
- return null;
+ return VARIABLE_SERIALIZER;
}
-
+
@Override
public Class<? super SparseDoubleVector> getRestrictionClass() {
return SparseDoubleVector.class;
@@ -355,4 +361,48 @@ public class SparseDoubleVector extends AbstractNumberVector<Double> implements
* Empty map.
*/
public static final TIntDoubleMap EMPTYMAP = new TUnmodifiableIntDoubleMap(new TIntDoubleHashMap());
+
+ /**
+ * Serialization class using VarInt encodings.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.uses SparseDoubleVector - - «serializes»
+ */
+ public static class VariableSerializer implements ByteBufferSerializer<SparseDoubleVector> {
+ @Override
+ public SparseDoubleVector fromByteBuffer(ByteBuffer buffer) throws IOException {
+ final int dimensionality = ByteArrayUtil.readUnsignedVarint(buffer);
+ final int nonzero = ByteArrayUtil.readUnsignedVarint(buffer);
+ final int[] dims = new int[nonzero];
+ final double[] values = new double[nonzero];
+ for (int i = 0; i < nonzero; i++) {
+ dims[i] = ByteArrayUtil.readUnsignedVarint(buffer);
+ values[i] = buffer.getDouble();
+ }
+ return new SparseDoubleVector(dims, values, dimensionality);
+ }
+
+ @Override
+ public void toByteBuffer(ByteBuffer buffer, SparseDoubleVector vec) throws IOException {
+ ByteArrayUtil.writeUnsignedVarint(buffer, vec.dimensionality);
+ ByteArrayUtil.writeUnsignedVarint(buffer, vec.values.length);
+ for (int i = 0; i < vec.values.length; i++) {
+ ByteArrayUtil.writeUnsignedVarint(buffer, vec.indexes[i]);
+ buffer.putDouble(vec.values[i]);
+ }
+ }
+
+ @Override
+ public int getByteSize(SparseDoubleVector vec) {
+ int sum = 0;
+ sum += ByteArrayUtil.getUnsignedVarintSize(vec.dimensionality);
+ sum += ByteArrayUtil.getUnsignedVarintSize(vec.values.length);
+ for (int d : vec.indexes) {
+ sum += ByteArrayUtil.getUnsignedVarintSize(d);
+ }
+ sum += vec.values.length * ByteArrayUtil.SIZE_DOUBLE;
+ return sum;
+ }
+ }
}
diff --git a/src/de/lmu/ifi/dbs/elki/data/SparseFeatureVector.java b/src/de/lmu/ifi/dbs/elki/data/SparseFeatureVector.java
index 97ec8857..a430ad3c 100644
--- a/src/de/lmu/ifi/dbs/elki/data/SparseFeatureVector.java
+++ b/src/de/lmu/ifi/dbs/elki/data/SparseFeatureVector.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/SparseFloatVector.java b/src/de/lmu/ifi/dbs/elki/data/SparseFloatVector.java
index de3e7293..ca337b4b 100644
--- a/src/de/lmu/ifi/dbs/elki/data/SparseFloatVector.java
+++ b/src/de/lmu/ifi/dbs/elki/data/SparseFloatVector.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -30,10 +30,13 @@ import gnu.trove.map.TIntDoubleMap;
import gnu.trove.map.TIntFloatMap;
import gnu.trove.map.hash.TIntFloatHashMap;
+import java.io.IOException;
+import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.BitSet;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
+import de.lmu.ifi.dbs.elki.persistent.ByteArrayUtil;
import de.lmu.ifi.dbs.elki.persistent.ByteBufferSerializer;
import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayAdapter;
import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
@@ -49,7 +52,6 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
*
* @author Arthur Zimek
*/
-// TODO: implement ByteArraySerializer<SparseFloatVector>
public class SparseFloatVector extends AbstractNumberVector<Float> implements SparseNumberVector<Float> {
/**
* Static instance.
@@ -57,6 +59,11 @@ public class SparseFloatVector extends AbstractNumberVector<Float> implements Sp
public static final SparseFloatVector.Factory FACTORY = new SparseFloatVector.Factory();
/**
+ * Serializer using varint encoding.
+ */
+ public static final ByteBufferSerializer<SparseFloatVector> VARIABLE_SERIALIZER = new VariableSerializer();
+
+ /**
* Indexes of values.
*/
private final int[] indexes;
@@ -167,7 +174,7 @@ public class SparseFloatVector extends AbstractNumberVector<Float> implements Sp
for (int i = 0; i < values.length; i++) {
float value = values[i];
if (value != 0.0f) {
- this.indexes[pos] = i + 1;
+ this.indexes[pos] = i;
this.values[pos] = value;
pos++;
}
@@ -333,8 +340,7 @@ public class SparseFloatVector extends AbstractNumberVector<Float> implements Sp
@Override
public ByteBufferSerializer<SparseFloatVector> getDefaultSerializer() {
- // FIXME: add a serializer
- return null;
+ return VARIABLE_SERIALIZER;
}
@Override
@@ -370,4 +376,48 @@ public class SparseFloatVector extends AbstractNumberVector<Float> implements Sp
* Empty map.
*/
public static final TIntFloatMap EMPTYMAP = new TUnmodifiableIntFloatMap(new TIntFloatHashMap());
+
+ /**
+ * Serialization class using VarInt encodings.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.uses SparseFloatVector - - «serializes»
+ */
+ public static class VariableSerializer implements ByteBufferSerializer<SparseFloatVector> {
+ @Override
+ public SparseFloatVector fromByteBuffer(ByteBuffer buffer) throws IOException {
+ final int dimensionality = ByteArrayUtil.readUnsignedVarint(buffer);
+ final int nonzero = ByteArrayUtil.readUnsignedVarint(buffer);
+ final int[] dims = new int[nonzero];
+ final float[] values = new float[nonzero];
+ for (int i = 0; i < nonzero; i++) {
+ dims[i] = ByteArrayUtil.readUnsignedVarint(buffer);
+ values[i] = buffer.getFloat();
+ }
+ return new SparseFloatVector(dims, values, dimensionality);
+ }
+
+ @Override
+ public void toByteBuffer(ByteBuffer buffer, SparseFloatVector vec) throws IOException {
+ ByteArrayUtil.writeUnsignedVarint(buffer, vec.dimensionality);
+ ByteArrayUtil.writeUnsignedVarint(buffer, vec.values.length);
+ for (int i = 0; i < vec.values.length; i++) {
+ ByteArrayUtil.writeUnsignedVarint(buffer, vec.indexes[i]);
+ buffer.putFloat(vec.values[i]);
+ }
+ }
+
+ @Override
+ public int getByteSize(SparseFloatVector vec) {
+ int sum = 0;
+ sum += ByteArrayUtil.getUnsignedVarintSize(vec.dimensionality);
+ sum += ByteArrayUtil.getUnsignedVarintSize(vec.values.length);
+ for (int d : vec.indexes) {
+ sum += ByteArrayUtil.getUnsignedVarintSize(d);
+ }
+ sum += vec.values.length * ByteArrayUtil.SIZE_FLOAT;
+ return sum;
+ }
+ }
}
diff --git a/src/de/lmu/ifi/dbs/elki/data/SparseNumberVector.java b/src/de/lmu/ifi/dbs/elki/data/SparseNumberVector.java
index 6ac1cc66..26ab968a 100644
--- a/src/de/lmu/ifi/dbs/elki/data/SparseNumberVector.java
+++ b/src/de/lmu/ifi/dbs/elki/data/SparseNumberVector.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/Subspace.java b/src/de/lmu/ifi/dbs/elki/data/Subspace.java
index 8a6a2d14..a564d8b5 100644
--- a/src/de/lmu/ifi/dbs/elki/data/Subspace.java
+++ b/src/de/lmu/ifi/dbs/elki/data/Subspace.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/VectorUtil.java b/src/de/lmu/ifi/dbs/elki/data/VectorUtil.java
index ce8102fc..205dee17 100644
--- a/src/de/lmu/ifi/dbs/elki/data/VectorUtil.java
+++ b/src/de/lmu/ifi/dbs/elki/data/VectorUtil.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -38,6 +38,7 @@ import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.database.relation.RelationUtil;
import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
import de.lmu.ifi.dbs.elki.math.MathUtil;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.Matrix;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
import de.lmu.ifi.dbs.elki.utilities.datastructures.QuickSelect;
@@ -68,7 +69,7 @@ public final class VectorUtil {
public static DoubleMinMax getRangeDouble(NumberVector<?> vec) {
DoubleMinMax minmax = new DoubleMinMax();
- for(int i = 0; i < vec.getDimensionality(); i++) {
+ for (int i = 0; i < vec.getDimensionality(); i++) {
minmax.put(vec.doubleValue(i));
}
@@ -77,7 +78,7 @@ public final class VectorUtil {
/**
* Produce a new vector based on random numbers in [0:1].
- *
+ *
* @param factory Vector factory
* @param dim desired dimensionality
* @param r Random generator
@@ -113,9 +114,10 @@ public final class VectorUtil {
BitSet both = (BitSet) b1.clone();
both.and(b2);
+ // TODO: add precomputed length to data type!
// Length of first vector
double l1 = 0.0;
- for(int i = b1.nextSetBit(0); i >= 0; i = b1.nextSetBit(i + 1)) {
+ for (int i = b1.nextSetBit(0); i >= 0; i = b1.nextSetBit(i + 1)) {
final double val = v1.doubleValue(i);
l1 += val * val;
}
@@ -123,7 +125,7 @@ public final class VectorUtil {
// Length of second vector
double l2 = 0.0;
- for(int i = b2.nextSetBit(0); i >= 0; i = b2.nextSetBit(i + 1)) {
+ for (int i = b2.nextSetBit(0); i >= 0; i = b2.nextSetBit(i + 1)) {
final double val = v2.doubleValue(i);
l2 += val * val;
}
@@ -131,10 +133,11 @@ public final class VectorUtil {
// Cross product
double cross = 0.0;
- for(int i = both.nextSetBit(0); i >= 0; i = both.nextSetBit(i + 1)) {
+ for (int i = both.nextSetBit(0); i >= 0; i = both.nextSetBit(i + 1)) {
cross += v1.doubleValue(i) * v2.doubleValue(i);
}
- return cross / (l1 * l2);
+ final double a = cross / (l1 * l2);
+ return (a > 1.0) ? 1.0 : a;
}
/**
@@ -153,14 +156,15 @@ public final class VectorUtil {
double[] oe = o.getArrayRef();
final int dim = v1.getDimensionality();
double s = 0, e1 = 0, e2 = 0;
- for(int k = 0; k < dim; k++) {
+ for (int k = 0; k < dim; k++) {
final double r1 = v1.doubleValue(k) - oe[k];
final double r2 = v2.doubleValue(k) - oe[k];
s += r1 * r2;
e1 += r1 * r1;
e2 += r2 * r2;
}
- return Math.sqrt((s / e1) * (s / e2));
+ final double a = Math.sqrt((s / e1) * (s / e2));
+ return (a > 1.0) ? 1.0 : a;
}
/**
@@ -178,14 +182,15 @@ public final class VectorUtil {
// We can just compute all three in parallel.
final int dim = v1.getDimensionality();
double s = 0, e1 = 0, e2 = 0;
- for(int k = 0; k < dim; k++) {
+ for (int k = 0; k < dim; k++) {
final double r1 = v1.doubleValue(k) - o.doubleValue(k);
final double r2 = v2.doubleValue(k) - o.doubleValue(k);
s += r1 * r2;
e1 += r1 * r1;
e2 += r2 * r2;
}
- return Math.sqrt((s / e1) * (s / e2));
+ final double a = Math.sqrt((s / e1) * (s / e2));
+ return (a > 1.0) ? 1.0 : a;
}
/**
@@ -198,7 +203,7 @@ public final class VectorUtil {
* @return Angle
*/
public static double cosAngle(NumberVector<?> v1, NumberVector<?> v2) {
- if(v1 instanceof SparseNumberVector<?> && v2 instanceof SparseNumberVector<?>) {
+ if (v1 instanceof SparseNumberVector<?> && v2 instanceof SparseNumberVector<?>) {
return angleSparse((SparseNumberVector<?>) v1, (SparseNumberVector<?>) v2);
}
// Essentially, we want to compute this:
@@ -208,22 +213,23 @@ public final class VectorUtil {
final int d2 = v2.getDimensionality();
final int dim = Math.min(d1, d2);
double s = 0, e1 = 0, e2 = 0;
- for(int k = 0; k < dim; k++) {
+ for (int k = 0; k < dim; k++) {
final double r1 = v1.doubleValue(k);
final double r2 = v2.doubleValue(k);
s += r1 * r2;
e1 += r1 * r1;
e2 += r2 * r2;
}
- for(int k = dim; k < d1; k++) {
+ for (int k = dim; k < d1; k++) {
final double r1 = v1.doubleValue(k);
e1 += r1 * r1;
}
- for(int k = dim; k < d2; k++) {
+ for (int k = dim; k < d2; k++) {
final double r2 = v2.doubleValue(k);
e2 += r2 * r2;
}
- return Math.min(Math.sqrt((s / e1) * (s / e2)), 1);
+ final double a = Math.sqrt((s / e1) * (s / e2));
+ return (a > 1.0) ? 1.0 : a;
}
// TODO: add more precise but slower O(n^2) angle computation according to:
@@ -238,7 +244,7 @@ public final class VectorUtil {
* @return Angle
*/
public static double minCosAngle(SpatialComparable v1, SpatialComparable v2) {
- if(v1 instanceof NumberVector<?> && v2 instanceof NumberVector<?>) {
+ if (v1 instanceof NumberVector<?> && v2 instanceof NumberVector<?>) {
return cosAngle((NumberVector<?>) v1, (NumberVector<?>) v2);
}
// Essentially, we want to compute this:
@@ -246,28 +252,27 @@ public final class VectorUtil {
// We can just compute all three in parallel.
final int dim = v1.getDimensionality();
double s1 = 0, s2 = 0, e1 = 0, e2 = 0;
- for(int k = 0; k < dim; k++) {
+ for (int k = 0; k < dim; k++) {
final double min1 = v1.getMin(k), max1 = v1.getMax(k);
final double min2 = v2.getMin(k), max2 = v2.getMax(k);
final double p1 = min1 * min2, p2 = min1 * max2;
final double p3 = max1 * min2, p4 = max1 * max2;
s1 += Math.max(Math.max(p1, p2), Math.max(p3, p4));
s2 += Math.min(Math.min(p1, p2), Math.min(p3, p4));
- if(max1 < 0) {
+ if (max1 < 0) {
e1 += max1 * max1;
- }
- else if(min1 > 0) {
+ } else if (min1 > 0) {
e1 += min1 * min1;
} // else: 0
- if(max2 < 0) {
+ if (max2 < 0) {
e2 += max2 * max2;
- }
- else if(min2 > 0) {
+ } else if (min2 > 0) {
e2 += min2 * min2;
} // else: 0
}
final double s = Math.max(s1, Math.abs(s2));
- return Math.min(Math.sqrt((s / e1) * (s / e2)), 1.0);
+ final double a = Math.sqrt((s / e1) * (s / e2));
+ return (a > 1.0) ? 1.0 : a;
}
/**
@@ -282,7 +287,7 @@ public final class VectorUtil {
public static double scalarProduct(NumberVector<?> d1, NumberVector<?> d2) {
final int dim = d1.getDimensionality();
double result = 0.0;
- for(int i = 0; i < dim; i++) {
+ for (int i = 0; i < dim; i++) {
result += d1.doubleValue(i) * d2.doubleValue(i);
}
return result;
@@ -308,10 +313,35 @@ public final class VectorUtil {
}
/**
+ * This is an ugly hack, but we don't want to have the {@link Matrix} class
+ * depend on {@link NumberVector}. Maybe a future version will no longer need
+ * this.
+ *
+ * @param mat Matrix
+ * @param v Vector
+ * @return {@code mat * v}, as double array.
+ */
+ public static double[] fastTimes(Matrix mat, NumberVector<?> v) {
+ final double[][] elements = mat.getArrayRef();
+ final int cdim = mat.getColumnDimensionality();
+ final double[] X = new double[elements.length];
+ // multiply it with each row from A
+ for (int i = 0; i < elements.length; i++) {
+ final double[] Arowi = elements[i];
+ double s = 0;
+ for (int k = 0; k < cdim; k++) {
+ s += Arowi[k] * v.doubleValue(k);
+ }
+ X[i] = s;
+ }
+ return X;
+ }
+
+ /**
* Compare number vectors by a single dimension.
*
* @author Erich Schubert
- *
+ *
* @apiviz.exclude
*/
public static class SortDBIDsBySingleDimension implements Comparator<DBIDRef> {
@@ -363,7 +393,7 @@ public final class VectorUtil {
* Compare number vectors by a single dimension.
*
* @author Erich Schubert
- *
+ *
* @apiviz.exclude
*/
public static class SortVectorsBySingleDimension implements Comparator<NumberVector<?>> {
@@ -421,7 +451,8 @@ public final class VectorUtil {
values.put(d, v.doubleValue(d));
}
}
- // We can't avoid this cast, because Java doesn't know that V is a SparseNumberVector:
+ // We can't avoid this cast, because Java doesn't know that V is a
+ // SparseNumberVector:
@SuppressWarnings("unchecked")
V projectedVector = (V) sfactory.newNumberVector(values, selectedAttributes.cardinality());
return projectedVector;
diff --git a/src/de/lmu/ifi/dbs/elki/data/images/AbstractComputeColorHistogram.java b/src/de/lmu/ifi/dbs/elki/data/images/AbstractComputeColorHistogram.java
index cb6ca494..25181acd 100644
--- a/src/de/lmu/ifi/dbs/elki/data/images/AbstractComputeColorHistogram.java
+++ b/src/de/lmu/ifi/dbs/elki/data/images/AbstractComputeColorHistogram.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.images;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/images/BlendComposite.java b/src/de/lmu/ifi/dbs/elki/data/images/BlendComposite.java
index e45d27bd..1c3037d6 100644
--- a/src/de/lmu/ifi/dbs/elki/data/images/BlendComposite.java
+++ b/src/de/lmu/ifi/dbs/elki/data/images/BlendComposite.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.images;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/images/ComputeColorHistogram.java b/src/de/lmu/ifi/dbs/elki/data/images/ComputeColorHistogram.java
index a13a4086..daa74726 100644
--- a/src/de/lmu/ifi/dbs/elki/data/images/ComputeColorHistogram.java
+++ b/src/de/lmu/ifi/dbs/elki/data/images/ComputeColorHistogram.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.images;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/images/ComputeHSBColorHistogram.java b/src/de/lmu/ifi/dbs/elki/data/images/ComputeHSBColorHistogram.java
index e9b428f1..96f3bf73 100644
--- a/src/de/lmu/ifi/dbs/elki/data/images/ComputeHSBColorHistogram.java
+++ b/src/de/lmu/ifi/dbs/elki/data/images/ComputeHSBColorHistogram.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.images;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/images/ComputeNaiveHSBColorHistogram.java b/src/de/lmu/ifi/dbs/elki/data/images/ComputeNaiveHSBColorHistogram.java
index 30fe21be..d6bf2e6c 100644
--- a/src/de/lmu/ifi/dbs/elki/data/images/ComputeNaiveHSBColorHistogram.java
+++ b/src/de/lmu/ifi/dbs/elki/data/images/ComputeNaiveHSBColorHistogram.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.images;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/images/ComputeNaiveRGBColorHistogram.java b/src/de/lmu/ifi/dbs/elki/data/images/ComputeNaiveRGBColorHistogram.java
index d28ed29b..5c40262e 100644
--- a/src/de/lmu/ifi/dbs/elki/data/images/ComputeNaiveRGBColorHistogram.java
+++ b/src/de/lmu/ifi/dbs/elki/data/images/ComputeNaiveRGBColorHistogram.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.images;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/images/ImageUtil.java b/src/de/lmu/ifi/dbs/elki/data/images/ImageUtil.java
index 10722c36..06363625 100644
--- a/src/de/lmu/ifi/dbs/elki/data/images/ImageUtil.java
+++ b/src/de/lmu/ifi/dbs/elki/data/images/ImageUtil.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.images;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/images/package-info.java b/src/de/lmu/ifi/dbs/elki/data/images/package-info.java
index 4a9d19ac..1a76913e 100644
--- a/src/de/lmu/ifi/dbs/elki/data/images/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/data/images/package-info.java
@@ -7,7 +7,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/model/BaseModel.java b/src/de/lmu/ifi/dbs/elki/data/model/BaseModel.java
index 56d7cd3f..98fa0567 100644
--- a/src/de/lmu/ifi/dbs/elki/data/model/BaseModel.java
+++ b/src/de/lmu/ifi/dbs/elki/data/model/BaseModel.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.model;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/model/Bicluster.java b/src/de/lmu/ifi/dbs/elki/data/model/Bicluster.java
index eb7755a7..27cdef74 100644
--- a/src/de/lmu/ifi/dbs/elki/data/model/Bicluster.java
+++ b/src/de/lmu/ifi/dbs/elki/data/model/Bicluster.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.model;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/model/BiclusterWithInverted.java b/src/de/lmu/ifi/dbs/elki/data/model/BiclusterWithInverted.java
index 1f582fdd..12d4f18b 100644
--- a/src/de/lmu/ifi/dbs/elki/data/model/BiclusterWithInverted.java
+++ b/src/de/lmu/ifi/dbs/elki/data/model/BiclusterWithInverted.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.model;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/model/ClusterModel.java b/src/de/lmu/ifi/dbs/elki/data/model/ClusterModel.java
index 5bd3123c..eacab5bc 100644
--- a/src/de/lmu/ifi/dbs/elki/data/model/ClusterModel.java
+++ b/src/de/lmu/ifi/dbs/elki/data/model/ClusterModel.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.model;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/iterator/OneItemIterator.java b/src/de/lmu/ifi/dbs/elki/data/model/CoreObjectsModel.java
index f6b00242..4a79d350 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/OneItemIterator.java
+++ b/src/de/lmu/ifi/dbs/elki/data/model/CoreObjectsModel.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.utilities.iterator;
+package de.lmu.ifi.dbs.elki.data.model;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,47 +23,41 @@ package de.lmu.ifi.dbs.elki.utilities.iterator;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.Iterator;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
/**
- * Dummy iterator/iterable that returns a single object, once.
- *
- * Note: a "null" object is not supported.
+ * Cluster model using "core" objects. Currently only used by the Generalized
+ * DBSCAN implementation when the {@code -gdbscan.core-model} flag is set.
*
* @author Erich Schubert
- *
- * @param <T> Object type to return
*/
-public class OneItemIterator<T> implements Iterator<T> {
+public class CoreObjectsModel extends BaseModel {
/**
- * Object to return.
+ * Objects that are part of the cluster core.
*/
- private T object = null;
-
+ DBIDs core;
+
/**
* Constructor.
*
- * @param object Object to return once.
+ * @param core Core objects
*/
- public OneItemIterator(T object) {
+ public CoreObjectsModel(DBIDs core) {
super();
- this.object = object;
- }
-
- @Override
- public boolean hasNext() {
- return (object != null);
+ this.core = core;
}
- @Override
- public T next() {
- T ret = object;
- object = null;
- return ret;
+ /**
+ * Get the core object IDs.
+ *
+ * @return Core object IDs
+ */
+ public DBIDs getCoreObjects() {
+ return core;
}
@Override
- public void remove() {
- throw new UnsupportedOperationException();
+ public String toString() {
+ return "CoreModel";
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/data/model/CorrelationAnalysisSolution.java b/src/de/lmu/ifi/dbs/elki/data/model/CorrelationAnalysisSolution.java
index 4240cb83..364fc3dc 100644
--- a/src/de/lmu/ifi/dbs/elki/data/model/CorrelationAnalysisSolution.java
+++ b/src/de/lmu/ifi/dbs/elki/data/model/CorrelationAnalysisSolution.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.model;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/model/CorrelationModel.java b/src/de/lmu/ifi/dbs/elki/data/model/CorrelationModel.java
index 1a111985..6cfa5137 100644
--- a/src/de/lmu/ifi/dbs/elki/data/model/CorrelationModel.java
+++ b/src/de/lmu/ifi/dbs/elki/data/model/CorrelationModel.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.model;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/model/DendrogramModel.java b/src/de/lmu/ifi/dbs/elki/data/model/DendrogramModel.java
index 0ea1fe2b..ac1c53f0 100644
--- a/src/de/lmu/ifi/dbs/elki/data/model/DendrogramModel.java
+++ b/src/de/lmu/ifi/dbs/elki/data/model/DendrogramModel.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.data.model;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/model/DimensionModel.java b/src/de/lmu/ifi/dbs/elki/data/model/DimensionModel.java
index 104ade9a..36b5653e 100644
--- a/src/de/lmu/ifi/dbs/elki/data/model/DimensionModel.java
+++ b/src/de/lmu/ifi/dbs/elki/data/model/DimensionModel.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.model;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/model/EMModel.java b/src/de/lmu/ifi/dbs/elki/data/model/EMModel.java
index 3856b9b1..e83f4c72 100644
--- a/src/de/lmu/ifi/dbs/elki/data/model/EMModel.java
+++ b/src/de/lmu/ifi/dbs/elki/data/model/EMModel.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.model;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/model/KMeansModel.java b/src/de/lmu/ifi/dbs/elki/data/model/KMeansModel.java
index da6e81f8..a1867695 100644
--- a/src/de/lmu/ifi/dbs/elki/data/model/KMeansModel.java
+++ b/src/de/lmu/ifi/dbs/elki/data/model/KMeansModel.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.model;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/model/LinearEquationModel.java b/src/de/lmu/ifi/dbs/elki/data/model/LinearEquationModel.java
index 366c7717..cff9cc42 100644
--- a/src/de/lmu/ifi/dbs/elki/data/model/LinearEquationModel.java
+++ b/src/de/lmu/ifi/dbs/elki/data/model/LinearEquationModel.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.model;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/model/MeanModel.java b/src/de/lmu/ifi/dbs/elki/data/model/MeanModel.java
index 15c3d571..84896d06 100644
--- a/src/de/lmu/ifi/dbs/elki/data/model/MeanModel.java
+++ b/src/de/lmu/ifi/dbs/elki/data/model/MeanModel.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.model;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/model/MedoidModel.java b/src/de/lmu/ifi/dbs/elki/data/model/MedoidModel.java
index 5540b931..6df2356d 100644
--- a/src/de/lmu/ifi/dbs/elki/data/model/MedoidModel.java
+++ b/src/de/lmu/ifi/dbs/elki/data/model/MedoidModel.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.model;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/model/Model.java b/src/de/lmu/ifi/dbs/elki/data/model/Model.java
index 627bc084..fb2d533f 100644
--- a/src/de/lmu/ifi/dbs/elki/data/model/Model.java
+++ b/src/de/lmu/ifi/dbs/elki/data/model/Model.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.model;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/model/OPTICSModel.java b/src/de/lmu/ifi/dbs/elki/data/model/OPTICSModel.java
index 16a9619b..bf942ff5 100644
--- a/src/de/lmu/ifi/dbs/elki/data/model/OPTICSModel.java
+++ b/src/de/lmu/ifi/dbs/elki/data/model/OPTICSModel.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.model;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/model/SubspaceModel.java b/src/de/lmu/ifi/dbs/elki/data/model/SubspaceModel.java
index 65607d8a..1cace130 100644
--- a/src/de/lmu/ifi/dbs/elki/data/model/SubspaceModel.java
+++ b/src/de/lmu/ifi/dbs/elki/data/model/SubspaceModel.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.model;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/model/package-info.java b/src/de/lmu/ifi/dbs/elki/data/model/package-info.java
index c8f514ec..a7789826 100644
--- a/src/de/lmu/ifi/dbs/elki/data/model/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/data/model/package-info.java
@@ -8,7 +8,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/package-info.java b/src/de/lmu/ifi/dbs/elki/data/package-info.java
index 8d1eb82f..73d500ea 100644
--- a/src/de/lmu/ifi/dbs/elki/data/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/data/package-info.java
@@ -15,7 +15,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/projection/FeatureSelection.java b/src/de/lmu/ifi/dbs/elki/data/projection/FeatureSelection.java
index bcb64800..f60f1145 100644
--- a/src/de/lmu/ifi/dbs/elki/data/projection/FeatureSelection.java
+++ b/src/de/lmu/ifi/dbs/elki/data/projection/FeatureSelection.java
@@ -1,9 +1,10 @@
package de.lmu.ifi.dbs.elki.data.projection;
+
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,9 +30,16 @@ import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
import de.lmu.ifi.dbs.elki.data.type.VectorFieldTypeInformation;
import de.lmu.ifi.dbs.elki.data.type.VectorTypeInformation;
+import de.lmu.ifi.dbs.elki.datasource.filter.transform.NumberVectorFeatureSelectionFilter;
import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayAdapter;
import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayLikeUtil;
import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.SubsetArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterEqualConstraint;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.ListEachConstraint;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntListParameter;
/**
* Projection class for number vectors.
@@ -61,30 +69,38 @@ public class FeatureSelection<V extends FeatureVector<F>, F> implements Projecti
* Array adapter.
*/
protected ArrayAdapter<F, V> adapter;
-
+
/**
* Constructor.
*
* @param dims Dimensions
- * @param factory Object factory
*/
- public FeatureSelection(int[] dims, FeatureVector.Factory<V, F> factory) {
- this.adapter = new SubsetArrayAdapter<F, V>(getAdapter(factory), dims);
- this.factory = factory;
+ public FeatureSelection(int[] dims) {
+ this.adapter = new SubsetArrayAdapter<>(getAdapter(factory), dims);
this.dimensionality = dims.length;
int mind = 0;
- for(int dim : dims) {
+ for (int dim : dims) {
mind = Math.max(mind, dim + 1);
}
this.mindim = mind;
}
+ @SuppressWarnings("unchecked")
+ @Override
+ public void initialize(SimpleTypeInformation<V> in) {
+ final VectorFieldTypeInformation<V> vin = (VectorFieldTypeInformation<V>) in;
+ factory = (FeatureVector.Factory<V, F>) vin.getFactory();
+ if (vin.getDimensionality() < mindim) {
+ throw new AbortException("Data does not have enough dimensions for this projection!");
+ }
+ }
+
@Override
public V project(V data) {
return factory.newFeatureVector(data, adapter);
}
-
+
/**
* Choose the best adapter for this.
*
@@ -95,7 +111,7 @@ public class FeatureSelection<V extends FeatureVector<F>, F> implements Projecti
*/
@SuppressWarnings("unchecked")
private static <V extends FeatureVector<F>, F> ArrayAdapter<F, ? super V> getAdapter(Factory<V, F> factory) {
- if(factory instanceof NumberVector.Factory) {
+ if (factory instanceof NumberVector.Factory) {
return (ArrayAdapter<F, ? super V>) ArrayLikeUtil.NUMBERVECTORADAPTER;
}
return (ArrayAdapter<F, ? super V>) ArrayLikeUtil.FEATUREVECTORADAPTER;
@@ -103,15 +119,43 @@ public class FeatureSelection<V extends FeatureVector<F>, F> implements Projecti
@Override
public SimpleTypeInformation<V> getOutputDataTypeInformation() {
- @SuppressWarnings("unchecked")
- final Class<V> cls = (Class<V>) factory.getClass();
- return new VectorFieldTypeInformation<V>(cls, dimensionality);
+ return new VectorFieldTypeInformation<>(factory, dimensionality);
}
@Override
public TypeInformation getInputDataTypeInformation() {
@SuppressWarnings("unchecked")
- final Class<V> cls = (Class<V>) factory.getClass();
- return new VectorTypeInformation<V>(cls, mindim, Integer.MAX_VALUE);
+ final Class<V> cls = (Class<V>) factory.getRestrictionClass();
+ return new VectorTypeInformation<>(cls, mindim, Integer.MAX_VALUE);
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer<V extends FeatureVector<F>, F> extends AbstractParameterizer {
+ /**
+ * Dimensions to select.
+ */
+ int[] dims = null;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+
+ IntListParameter selectedAttributesP = new IntListParameter(NumberVectorFeatureSelectionFilter.Parameterizer.SELECTED_ATTRIBUTES_ID);
+ selectedAttributesP.addConstraint(new ListEachConstraint<Integer>(new GreaterEqualConstraint(0)));
+ if (config.grab(selectedAttributesP)) {
+ dims = ArrayLikeUtil.toPrimitiveIntegerArray(selectedAttributesP.getValue());
+ }
+ }
+
+ @Override
+ protected FeatureSelection<V, F> makeInstance() {
+ return new FeatureSelection<>(dims);
+ }
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/data/projection/LatLngToECEFProjection.java b/src/de/lmu/ifi/dbs/elki/data/projection/LatLngToECEFProjection.java
new file mode 100644
index 00000000..ee7ba931
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/data/projection/LatLngToECEFProjection.java
@@ -0,0 +1,113 @@
+package de.lmu.ifi.dbs.elki.data.projection;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
+import de.lmu.ifi.dbs.elki.data.type.VectorFieldTypeInformation;
+import de.lmu.ifi.dbs.elki.math.geodesy.EarthModel;
+import de.lmu.ifi.dbs.elki.math.geodesy.SphericalVincentyEarthModel;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
+
+/**
+ * Project (Latitude, Longitude) vectors to (X, Y, Z), from spherical
+ * coordinates to ECEF (earth-centered earth-fixed).
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.composedOf EarthModel
+ *
+ * @param <V> Vector type
+ */
+public class LatLngToECEFProjection<V extends NumberVector<?>> implements Projection<V, V> {
+ /**
+ * Vector factory to use.
+ */
+ private NumberVector.Factory<V, ?> factory;
+
+ /**
+ * Earth model to use.
+ */
+ private EarthModel model;
+
+ /**
+ * Constructor.
+ *
+ * @param model Earth model to use.
+ */
+ public LatLngToECEFProjection(EarthModel model) {
+ super();
+ this.model = model;
+ }
+
+ @Override
+ public void initialize(SimpleTypeInformation<V> in) {
+ final VectorFieldTypeInformation<V> vin = (VectorFieldTypeInformation<V>) in;
+ factory = (NumberVector.Factory<V, ?>) vin.getFactory();
+ }
+
+ @Override
+ public V project(V data) {
+ return factory.newNumberVector(model.latLngDegToECEF(data.doubleValue(0), data.doubleValue(1)));
+ }
+
+ @Override
+ public SimpleTypeInformation<? super V> getInputDataTypeInformation() {
+ return new VectorFieldTypeInformation<>(NumberVector.class, 2, 2);
+ }
+
+ @Override
+ public SimpleTypeInformation<V> getOutputDataTypeInformation() {
+ return new VectorFieldTypeInformation<>(factory, 3, 3, factory.getDefaultSerializer());
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @apiviz.exclude
+ *
+ * @author Erich Schubert
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ /**
+ * Earth model to use.
+ */
+ EarthModel model;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ ObjectParameter<EarthModel> modelP = new ObjectParameter<>(EarthModel.MODEL_ID, EarthModel.class, SphericalVincentyEarthModel.class);
+ if (config.grab(modelP)) {
+ model = modelP.instantiateClass(config);
+ }
+ }
+
+ @Override
+ protected LatLngToECEFProjection<NumberVector<?>> makeInstance() {
+ return new LatLngToECEFProjection<>(model);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/data/projection/LngLatToECEFProjection.java b/src/de/lmu/ifi/dbs/elki/data/projection/LngLatToECEFProjection.java
new file mode 100644
index 00000000..d6769c9c
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/data/projection/LngLatToECEFProjection.java
@@ -0,0 +1,113 @@
+package de.lmu.ifi.dbs.elki.data.projection;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
+import de.lmu.ifi.dbs.elki.data.type.VectorFieldTypeInformation;
+import de.lmu.ifi.dbs.elki.math.geodesy.EarthModel;
+import de.lmu.ifi.dbs.elki.math.geodesy.SphericalVincentyEarthModel;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
+
+/**
+ * Project (Longitude, Latitude) vectors to (X, Y, Z), from spherical
+ * coordinates to ECEF (earth-centered earth-fixed).
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.composedOf EarthModel
+ *
+ * @param <V> Vector type
+ */
+public class LngLatToECEFProjection<V extends NumberVector<?>> implements Projection<V, V> {
+ /**
+ * Earth model to use
+ */
+ EarthModel model;
+
+ /**
+ * Vector factory to use.
+ */
+ private NumberVector.Factory<V, ?> factory;
+
+ /**
+ * Constructor.
+ *
+ * @param model Earth model to use.
+ */
+ public LngLatToECEFProjection(EarthModel model) {
+ super();
+ this.model = model;
+ }
+
+ @Override
+ public void initialize(SimpleTypeInformation<V> in) {
+ final VectorFieldTypeInformation<V> vin = (VectorFieldTypeInformation<V>) in;
+ factory = (NumberVector.Factory<V, ?>) vin.getFactory();
+ }
+
+ @Override
+ public V project(V data) {
+ return factory.newNumberVector(model.latLngDegToECEF(data.doubleValue(1), data.doubleValue(0)));
+ }
+
+ @Override
+ public SimpleTypeInformation<? super V> getInputDataTypeInformation() {
+ return new VectorFieldTypeInformation<>(NumberVector.class, 2, 2);
+ }
+
+ @Override
+ public SimpleTypeInformation<V> getOutputDataTypeInformation() {
+ return new VectorFieldTypeInformation<>(factory, 3, 3, factory.getDefaultSerializer());
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @apiviz.exclude
+ *
+ * @author Erich Schubert
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ /**
+ * Earth model to use.
+ */
+ EarthModel model;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ ObjectParameter<EarthModel> modelP = new ObjectParameter<>(EarthModel.MODEL_ID, EarthModel.class, SphericalVincentyEarthModel.class);
+ if (config.grab(modelP)) {
+ model = modelP.instantiateClass(config);
+ }
+ }
+
+ @Override
+ protected LngLatToECEFProjection<NumberVector<?>> makeInstance() {
+ return new LngLatToECEFProjection<>(model);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/data/projection/NumericalFeatureSelection.java b/src/de/lmu/ifi/dbs/elki/data/projection/NumericalFeatureSelection.java
index 9154839f..ea03888b 100644
--- a/src/de/lmu/ifi/dbs/elki/data/projection/NumericalFeatureSelection.java
+++ b/src/de/lmu/ifi/dbs/elki/data/projection/NumericalFeatureSelection.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.projection;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -30,10 +30,19 @@ import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
import de.lmu.ifi.dbs.elki.data.type.VectorFieldTypeInformation;
import de.lmu.ifi.dbs.elki.data.type.VectorTypeInformation;
+import de.lmu.ifi.dbs.elki.datasource.filter.transform.NumberVectorFeatureSelectionFilter;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterEqualConstraint;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.ListEachConstraint;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntListParameter;
/**
* Projection class for number vectors.
*
+ * FIXME: Use int[] instead of a BitSet, to allow reordering?
+ *
* @author Erich Schubert
*
* @param <V> Vector type
@@ -63,25 +72,32 @@ public class NumericalFeatureSelection<V extends NumberVector<?>> implements Pro
* Constructor.
*
* @param bits Dimensions
- * @param factory Object factory
*/
- public NumericalFeatureSelection(BitSet bits, NumberVector.Factory<V, ?> factory) {
+ public NumericalFeatureSelection(BitSet bits) {
super();
this.bits = bits;
- this.factory = factory;
this.dimensionality = bits.cardinality();
int mind = 0;
- for(int i = bits.nextSetBit(0); i >= 0; i = bits.nextSetBit(i + 1)) {
+ for (int i = bits.nextSetBit(0); i >= 0; i = bits.nextSetBit(i + 1)) {
mind = Math.max(mind, i + 1);
}
this.mindim = mind;
}
@Override
+ public void initialize(SimpleTypeInformation<V> in) {
+ final VectorFieldTypeInformation<V> vin = (VectorFieldTypeInformation<V>) in;
+ factory = (NumberVector.Factory<V, ?>) vin.getFactory();
+ if (vin.getDimensionality() < mindim) {
+ throw new AbortException("Data does not have enough dimensions for this projection!");
+ }
+ }
+
+ @Override
public V project(V data) {
double[] dbl = new double[dimensionality];
- for(int i = bits.nextSetBit(0), j = 0; i >= 0; i = bits.nextSetBit(i + 1), j++) {
+ for (int i = bits.nextSetBit(0), j = 0; i >= 0; i = bits.nextSetBit(i + 1), j++) {
dbl[j] = data.doubleValue(i);
}
return factory.newNumberVector(dbl);
@@ -89,15 +105,44 @@ public class NumericalFeatureSelection<V extends NumberVector<?>> implements Pro
@Override
public SimpleTypeInformation<V> getOutputDataTypeInformation() {
- @SuppressWarnings("unchecked")
- final Class<V> cls = (Class<V>) factory.getRestrictionClass();
- return new VectorFieldTypeInformation<V>(cls, dimensionality);
+ return new VectorFieldTypeInformation<>(factory, dimensionality);
}
@Override
public TypeInformation getInputDataTypeInformation() {
- @SuppressWarnings("unchecked")
- final Class<V> cls = (Class<V>) factory.getRestrictionClass();
- return new VectorTypeInformation<V>(cls, mindim, Integer.MAX_VALUE);
+ return new VectorTypeInformation<>(NumberVector.class, mindim, Integer.MAX_VALUE);
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer<V extends NumberVector<?>> extends AbstractParameterizer {
+ /**
+ * Dimensions to select.
+ */
+ BitSet dims = new BitSet();
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+
+ IntListParameter selectedAttributesP = new IntListParameter(NumberVectorFeatureSelectionFilter.Parameterizer.SELECTED_ATTRIBUTES_ID);
+ selectedAttributesP.addConstraint(new ListEachConstraint<Integer>(new GreaterEqualConstraint(0)));
+ if (config.grab(selectedAttributesP)) {
+ dims.clear();
+ for (int in : selectedAttributesP.getValue()) {
+ dims.set(in);
+ }
+ }
+ }
+
+ @Override
+ protected NumericalFeatureSelection<V> makeInstance() {
+ return new NumericalFeatureSelection<>(dims);
+ }
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/data/projection/Projection.java b/src/de/lmu/ifi/dbs/elki/data/projection/Projection.java
index c9cd98d2..b1e458e4 100644
--- a/src/de/lmu/ifi/dbs/elki/data/projection/Projection.java
+++ b/src/de/lmu/ifi/dbs/elki/data/projection/Projection.java
@@ -1,13 +1,10 @@
package de.lmu.ifi.dbs.elki.data.projection;
-import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
-import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
-
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,15 +23,26 @@ import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
+import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable;
+
/**
* Projection interface.
*
* @author Erich Schubert
- *
+ *
* @param <IN> Input data type
* @param <OUT> Output data type
*/
-public interface Projection<IN, OUT> {
+public interface Projection<IN, OUT> extends Parameterizable {
+ /**
+ * Initialize
+ *
+ * @param in Data type to use for projecting.
+ */
+ public void initialize(SimpleTypeInformation<IN> in);
+
/**
* Project a single instance.
*
@@ -42,13 +50,6 @@ public interface Projection<IN, OUT> {
* @return Projected data
*/
public OUT project(IN data);
-
- /**
- * Output type restriction
- *
- * @return Output type
- */
- public SimpleTypeInformation<OUT> getOutputDataTypeInformation();
/**
* Input type information.
@@ -56,4 +57,11 @@ public interface Projection<IN, OUT> {
* @return Type restriction
*/
public TypeInformation getInputDataTypeInformation();
+
+ /**
+ * Output type restriction
+ *
+ * @return Output type
+ */
+ public SimpleTypeInformation<OUT> getOutputDataTypeInformation();
}
diff --git a/src/de/lmu/ifi/dbs/elki/data/projection/RandomProjection.java b/src/de/lmu/ifi/dbs/elki/data/projection/RandomProjection.java
new file mode 100644
index 00000000..74edd3e1
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/data/projection/RandomProjection.java
@@ -0,0 +1,166 @@
+package de.lmu.ifi.dbs.elki.data.projection;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
+import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
+import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.data.type.VectorFieldTypeInformation;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.randomprojections.AchlioptasRandomProjectionFamily;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.randomprojections.RandomProjectionFamily;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterEqualConstraint;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
+
+/**
+ * Randomized projections of the data.
+ *
+ * This class allows projecting the data with different types of random
+ * projections, in particular database friendly projections (as suggested by
+ * Achlioptas, see {@link AchlioptasRandomProjectionFamily}), but also as
+ * suggested for locality sensitive hashing (LSH).
+ *
+ * @author Erich Schubert
+ *
+ * @param <V> Vector type
+ */
+public class RandomProjection<V extends NumberVector<?>> implements Projection<V, V> {
+ /**
+ * Class logger.
+ */
+ private static final Logging LOG = Logging.getLogger(RandomProjection.class);
+
+ /**
+ * Vector factory.
+ */
+ private NumberVector.Factory<V, ?> factory = null;
+
+ /**
+ * Output dimensionality.
+ */
+ private int dimensionality;
+
+ /**
+ * Projection matrix.
+ */
+ private RandomProjectionFamily.Projection projection = null;
+
+ /**
+ * Random projection family
+ */
+ private RandomProjectionFamily family;
+
+ /**
+ * Constructor.
+ *
+ * @param dimensionality Desired dimensionality
+ * @param family Random projection family
+ */
+ public RandomProjection(int dimensionality, RandomProjectionFamily family) {
+ super();
+ this.dimensionality = dimensionality;
+ this.family = family;
+ }
+
+ @Override
+ public void initialize(SimpleTypeInformation<V> in) {
+ final VectorFieldTypeInformation<V> vin = (VectorFieldTypeInformation<V>) in;
+ factory = (NumberVector.Factory<V, ?>) vin.getFactory();
+ int inputdim = vin.getDimensionality();
+
+ projection = family.generateProjection(inputdim, dimensionality);
+ if (LOG.isDebugging()) {
+ LOG.debug(projection.toString());
+ }
+ }
+
+ @Override
+ public V project(V data) {
+ return factory.newNumberVector(projection.project(data));
+ }
+
+ @Override
+ public TypeInformation getInputDataTypeInformation() {
+ return TypeUtil.NUMBER_VECTOR_FIELD;
+ }
+
+ @Override
+ public SimpleTypeInformation<V> getOutputDataTypeInformation() {
+ return new VectorFieldTypeInformation<>(factory, dimensionality);
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ /**
+ * Parameter for the projection family.
+ */
+ public static final OptionID FAMILY_ID = new OptionID("randomproj.family", "Projection family to use.");
+
+ /**
+ * Parameter for the desired output dimensionality.
+ */
+ public static final OptionID DIMENSIONALITY_ID = new OptionID("randomproj.dimensionality", "Amount of dimensions to project to.");
+
+ /**
+ * Output dimensionality.
+ */
+ private int dimensionality;
+
+ /**
+ * Random generator.
+ */
+ private RandomProjectionFamily family;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ ObjectParameter<RandomProjectionFamily> familyP = new ObjectParameter<>(FAMILY_ID, RandomProjectionFamily.class);
+ familyP.setDefaultValue(AchlioptasRandomProjectionFamily.class);
+ if (config.grab(familyP)) {
+ family = familyP.instantiateClass(config);
+ }
+
+ IntParameter dimP = new IntParameter(DIMENSIONALITY_ID);
+ dimP.addConstraint(new GreaterEqualConstraint(1));
+ if (config.grab(dimP)) {
+ dimensionality = dimP.intValue();
+ }
+ }
+
+ @Override
+ protected RandomProjection<NumberVector<?>> makeInstance() {
+ return new RandomProjection<>(dimensionality, family);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/data/projection/package-info.java b/src/de/lmu/ifi/dbs/elki/data/projection/package-info.java
index d39c51ba..2fe8b010 100644
--- a/src/de/lmu/ifi/dbs/elki/data/projection/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/data/projection/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/spatial/Polygon.java b/src/de/lmu/ifi/dbs/elki/data/spatial/Polygon.java
index 3bb771c1..eef19e82 100644
--- a/src/de/lmu/ifi/dbs/elki/data/spatial/Polygon.java
+++ b/src/de/lmu/ifi/dbs/elki/data/spatial/Polygon.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.spatial;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,12 +25,9 @@ package de.lmu.ifi.dbs.elki.data.spatial;
import java.util.Iterator;
import java.util.List;
-import java.util.ListIterator;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
-import de.lmu.ifi.dbs.elki.utilities.iterator.ReverseListIterator;
-import de.lmu.ifi.dbs.elki.utilities.iterator.UnmodifiableIterator;
-import de.lmu.ifi.dbs.elki.utilities.iterator.UnmodifiableListIterator;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.iterator.ArrayListIter;
/**
* Class representing a simple polygon. While you can obviously store non-simple
@@ -41,7 +38,7 @@ import de.lmu.ifi.dbs.elki.utilities.iterator.UnmodifiableListIterator;
*
* @apiviz.composedOf Vector
*/
-public class Polygon implements Iterable<Vector>, SpatialComparable {
+public class Polygon implements SpatialComparable {
/**
* The actual points
*/
@@ -66,15 +63,15 @@ public class Polygon implements Iterable<Vector>, SpatialComparable {
super();
this.points = points;
// Compute the bounds.
- if(points.size() > 0) {
+ if (points.size() > 0) {
final Iterator<Vector> iter = points.iterator();
final Vector first = iter.next();
final int dim = first.getDimensionality();
min = first.getArrayCopy();
max = first.getArrayCopy();
- while(iter.hasNext()) {
+ while (iter.hasNext()) {
Vector next = iter.next();
- for(int i = 0; i < dim; i++) {
+ for (int i = 0; i < dim; i++) {
final double cur = next.get(i);
min[i] = Math.min(min[i], cur);
max[i] = Math.max(max[i], cur);
@@ -90,27 +87,13 @@ public class Polygon implements Iterable<Vector>, SpatialComparable {
this.max = new double[] { maxx, maxy };
}
- @Override
- public Iterator<Vector> iterator() {
- return new UnmodifiableIterator<Vector>(points.iterator());
- }
-
/**
- * Get a list iterator.
+ * Get an iterator to the vector contents.
*
- * @return List iterator.
+ * @return Iterator
*/
- public ListIterator<Vector> listIterator() {
- return new UnmodifiableListIterator<Vector>(points.listIterator());
- }
-
- /**
- * Return an iterator that iterates the list backwards.
- *
- * @return Reversed iterator
- */
- public ListIterator<Vector> descendingIterator() {
- return new UnmodifiableListIterator<Vector>(new ReverseListIterator<Vector>(points));
+ public ArrayListIter<Vector> iter() {
+ return new ArrayListIter<>(points);
}
/**
@@ -120,15 +103,15 @@ public class Polygon implements Iterable<Vector>, SpatialComparable {
*/
public void appendToBuffer(StringBuilder buf) {
Iterator<Vector> iter = points.iterator();
- while(iter.hasNext()) {
+ while (iter.hasNext()) {
double[] data = iter.next().getArrayRef();
- for(int i = 0; i < data.length; i++) {
- if(i > 0) {
+ for (int i = 0; i < data.length; i++) {
+ if (i > 0) {
buf.append(",");
}
buf.append(data[i]);
}
- if(iter.hasNext()) {
+ if (iter.hasNext()) {
buf.append(" ");
}
}
@@ -181,7 +164,7 @@ public class Polygon implements Iterable<Vector>, SpatialComparable {
* @return -1, 0, 1 for counterclockwise, undefined and clockwise.
*/
public int testClockwise() {
- if(points.size() < 3) {
+ if (points.size() < 3) {
return 0;
}
final int size = points.size();
@@ -189,7 +172,7 @@ public class Polygon implements Iterable<Vector>, SpatialComparable {
int c = 0;
// TODO: faster when using an iterator?
- for(int i = 0; i < size; i++) {
+ for (int i = 0; i < size; i++) {
// Three consecutive points
final int j = (i + 1) % size;
final int k = (i + 2) % size;
@@ -198,20 +181,17 @@ public class Polygon implements Iterable<Vector>, SpatialComparable {
final double dyji = points.get(j).get(1) - points.get(i).get(1);
final double dxkj = points.get(k).get(0) - points.get(j).get(0);
final double z = (dxji * dykj) - (dyji * dxkj);
- if(z < 0) {
+ if (z < 0) {
c--;
- }
- else if(z > 0) {
+ } else if (z > 0) {
c++;
}
}
- if(c > 0) {
+ if (c > 0) {
return -1;
- }
- else if(c < 0) {
+ } else if (c < 0) {
return +1;
- }
- else {
+ } else {
return 0;
}
}
@@ -238,13 +218,13 @@ public class Polygon implements Iterable<Vector>, SpatialComparable {
public boolean intersects2DIncomplete(Polygon other) {
assert (this.getDimensionality() == 2);
assert (other.getDimensionality() == 2);
- for(Vector v : this.points) {
- if(other.containsPoint2D(v)) {
+ for (Vector v : this.points) {
+ if (other.containsPoint2D(v)) {
return true;
}
}
- for(Vector v : other.points) {
- if(this.containsPoint2D(v)) {
+ for (Vector v : other.points) {
+ if (this.containsPoint2D(v)) {
return true;
}
}
@@ -269,14 +249,14 @@ public class Polygon implements Iterable<Vector>, SpatialComparable {
Iterator<Vector> it = points.iterator();
Vector pre = points.get(points.size() - 1);
- while(it.hasNext()) {
+ while (it.hasNext()) {
final Vector cur = it.next();
final double curx = cur.get(0);
final double cury = cur.get(1);
final double prex = pre.get(0);
final double prey = pre.get(1);
- if(((cury > testy) != (prey > testy))) {
- if((testx < (prex - curx) * (testy - cury) / (prey - cury) + curx)) {
+ if (((cury > testy) != (prey > testy))) {
+ if ((testx < (prex - curx) * (testy - cury) / (prey - cury) + curx)) {
c = !c;
}
}
@@ -284,4 +264,4 @@ public class Polygon implements Iterable<Vector>, SpatialComparable {
}
return c;
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/data/spatial/PolygonsObject.java b/src/de/lmu/ifi/dbs/elki/data/spatial/PolygonsObject.java
index f329c948..dbda87bd 100644
--- a/src/de/lmu/ifi/dbs/elki/data/spatial/PolygonsObject.java
+++ b/src/de/lmu/ifi/dbs/elki/data/spatial/PolygonsObject.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.spatial;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/spatial/SpatialComparable.java b/src/de/lmu/ifi/dbs/elki/data/spatial/SpatialComparable.java
index c81ce10e..0783a748 100644
--- a/src/de/lmu/ifi/dbs/elki/data/spatial/SpatialComparable.java
+++ b/src/de/lmu/ifi/dbs/elki/data/spatial/SpatialComparable.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.spatial;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,12 +23,13 @@ package de.lmu.ifi.dbs.elki.data.spatial;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
-
/**
* Defines the required methods needed for comparison of spatial objects.
*
* @author Elke Achtert
+ *
+ * @apiviz.landmark
+ * @apiviz.excludeSubtypes
*/
public interface SpatialComparable {
/**
@@ -55,4 +56,4 @@ public interface SpatialComparable {
* @return the maximum coordinate at the specified dimension
*/
double getMax(int dimension);
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/data/spatial/SpatialSingleMaxComparator.java b/src/de/lmu/ifi/dbs/elki/data/spatial/SpatialSingleMaxComparator.java
new file mode 100644
index 00000000..8e491b97
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/data/spatial/SpatialSingleMaxComparator.java
@@ -0,0 +1,64 @@
+package de.lmu.ifi.dbs.elki.data.spatial;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import java.util.Comparator;
+
+/**
+ * Comparator for sorting spatial objects by the maximum value in a single
+ * dimension.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.uses SpatialComparable
+ */
+public class SpatialSingleMaxComparator implements Comparator<SpatialComparable> {
+ /**
+ * Current dimension.
+ */
+ int dim;
+
+ /**
+ * Constructor.
+ *
+ * @param dim Dimension to sort by.
+ */
+ public SpatialSingleMaxComparator(int dim) {
+ super();
+ this.dim = dim;
+ }
+
+ /**
+ * Set the dimension to sort by.
+ *
+ * @param dim Dimension
+ */
+ public void setDimension(int dim) {
+ this.dim = dim;
+ }
+
+ @Override
+ public int compare(SpatialComparable o1, SpatialComparable o2) {
+ return Double.compare(o1.getMax(dim), o2.getMax(dim));
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/data/spatial/SpatialSingleMeanComparator.java b/src/de/lmu/ifi/dbs/elki/data/spatial/SpatialSingleMeanComparator.java
new file mode 100644
index 00000000..ec8f4a38
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/data/spatial/SpatialSingleMeanComparator.java
@@ -0,0 +1,66 @@
+package de.lmu.ifi.dbs.elki.data.spatial;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import java.util.Comparator;
+
+/**
+ * Comparator for sorting spatial objects by the mean value in a single
+ * dimension.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.uses SpatialComparable
+ */
+public class SpatialSingleMeanComparator implements Comparator<SpatialComparable> {
+ /**
+ * Current dimension.
+ */
+ int dim;
+
+ /**
+ * Constructor.
+ *
+ * @param dim Dimension to sort by.
+ */
+ public SpatialSingleMeanComparator(int dim) {
+ super();
+ this.dim = dim;
+ }
+
+ /**
+ * Set the dimension to sort by.
+ *
+ * @param dim Dimension
+ */
+ public void setDimension(int dim) {
+ this.dim = dim;
+ }
+
+ @Override
+ public int compare(SpatialComparable o1, SpatialComparable o2) {
+ final double v1 = o1.getMin(dim) + o1.getMax(dim);
+ final double v2 = o2.getMin(dim) + o2.getMax(dim);
+ return Double.compare(v1, v2);
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/data/spatial/SpatialSingleMinComparator.java b/src/de/lmu/ifi/dbs/elki/data/spatial/SpatialSingleMinComparator.java
new file mode 100644
index 00000000..8156cbd1
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/data/spatial/SpatialSingleMinComparator.java
@@ -0,0 +1,64 @@
+package de.lmu.ifi.dbs.elki.data.spatial;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import java.util.Comparator;
+
+/**
+ * Comparator for sorting spatial objects by the minimum value in a single
+ * dimension.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.uses SpatialComparable
+ */
+public class SpatialSingleMinComparator implements Comparator<SpatialComparable> {
+ /**
+ * Current dimension.
+ */
+ int dim;
+
+ /**
+ * Constructor.
+ *
+ * @param dim Dimension to sort by.
+ */
+ public SpatialSingleMinComparator(int dim) {
+ super();
+ this.dim = dim;
+ }
+
+ /**
+ * Set the dimension to sort by.
+ *
+ * @param dim Dimension
+ */
+ public void setDimension(int dim) {
+ this.dim = dim;
+ }
+
+ @Override
+ public int compare(SpatialComparable o1, SpatialComparable o2) {
+ return Double.compare(o1.getMin(dim), o2.getMin(dim));
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/data/spatial/SpatialUtil.java b/src/de/lmu/ifi/dbs/elki/data/spatial/SpatialUtil.java
index 607acd1c..3d50f6e2 100644
--- a/src/de/lmu/ifi/dbs/elki/data/spatial/SpatialUtil.java
+++ b/src/de/lmu/ifi/dbs/elki/data/spatial/SpatialUtil.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.spatial;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/spatial/package-info.java b/src/de/lmu/ifi/dbs/elki/data/spatial/package-info.java
index e418bcaf..a208bd04 100644
--- a/src/de/lmu/ifi/dbs/elki/data/spatial/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/data/spatial/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/GeneratorInterface.java b/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/GeneratorInterface.java
index 363c6c3b..7988ade4 100644
--- a/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/GeneratorInterface.java
+++ b/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/GeneratorInterface.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.synthetic.bymodel;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/GeneratorInterfaceDynamic.java b/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/GeneratorInterfaceDynamic.java
index cd3f18b7..5523355f 100644
--- a/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/GeneratorInterfaceDynamic.java
+++ b/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/GeneratorInterfaceDynamic.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.synthetic.bymodel;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/GeneratorMain.java b/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/GeneratorMain.java
index 603507c1..0dccaf77 100644
--- a/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/GeneratorMain.java
+++ b/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/GeneratorMain.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.synthetic.bymodel;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -70,7 +70,7 @@ public class GeneratorMain {
/**
* List of clusters to generate.
*/
- protected LinkedList<GeneratorInterface> generators = new LinkedList<GeneratorInterface>();
+ protected LinkedList<GeneratorInterface> generators = new LinkedList<>();
/**
* Controls whether points are tested against the model during generation.
@@ -109,9 +109,9 @@ public class GeneratorMain {
}
// Prepare result bundle
MultipleObjectsBundle bundle = new MultipleObjectsBundle();
- VectorFieldTypeInformation<DoubleVector> type = new VectorFieldTypeInformation<DoubleVector>(DoubleVector.FACTORY, dim);
- bundle.appendColumn(type, new ArrayList<Object>());
- bundle.appendColumn(TypeUtil.CLASSLABEL, new ArrayList<Object>());
+ VectorFieldTypeInformation<DoubleVector> type = new VectorFieldTypeInformation<>(DoubleVector.FACTORY, dim);
+ bundle.appendColumn(type, new ArrayList<>());
+ bundle.appendColumn(TypeUtil.CLASSLABEL, new ArrayList<>());
bundle.appendColumn(TypeUtil.MODEL, new ArrayList<Model>());
// generate clusters
diff --git a/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/GeneratorSingleCluster.java b/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/GeneratorSingleCluster.java
index d2970de7..ccbeb9b7 100644
--- a/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/GeneratorSingleCluster.java
+++ b/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/GeneratorSingleCluster.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.synthetic.bymodel;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -30,7 +30,7 @@ import java.util.Random;
import de.lmu.ifi.dbs.elki.data.model.Model;
import de.lmu.ifi.dbs.elki.math.linearalgebra.AffineTransformation;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
-import de.lmu.ifi.dbs.elki.math.statistics.distribution.DistributionWithRandom;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.Distribution;
import de.lmu.ifi.dbs.elki.utilities.exceptions.UnableToComplyException;
/**
@@ -47,7 +47,7 @@ public class GeneratorSingleCluster implements GeneratorInterfaceDynamic, Model
/**
* The distribution generators for each axis
*/
- private List<DistributionWithRandom> axes = new ArrayList<DistributionWithRandom>();
+ private List<Distribution> axes = new ArrayList<>();
/**
* The transformation matrix
@@ -121,7 +121,7 @@ public class GeneratorSingleCluster implements GeneratorInterfaceDynamic, Model
* @throws UnableToComplyException thrown when no new generators may be added
* anymore
*/
- public void addGenerator(DistributionWithRandom gen) throws UnableToComplyException {
+ public void addGenerator(Distribution gen) throws UnableToComplyException {
if(trans != null) {
throw new UnableToComplyException("Generators may no longer be added when transformations have been applied.");
}
@@ -231,11 +231,11 @@ public class GeneratorSingleCluster implements GeneratorInterfaceDynamic, Model
*/
@Override
public List<Vector> generate(int count) throws UnableToComplyException {
- ArrayList<Vector> result = new ArrayList<Vector>(count);
+ ArrayList<Vector> result = new ArrayList<>(count);
while(result.size() < count) {
double[] d = new double[dim];
int i = 0;
- for(DistributionWithRandom axis : axes) {
+ for(Distribution axis : axes) {
d[i] = axis.nextRandom();
i++;
}
@@ -269,7 +269,7 @@ public class GeneratorSingleCluster implements GeneratorInterfaceDynamic, Model
double density = 1.0;
int i = 0;
- for(DistributionWithRandom axis : axes) {
+ for(Distribution axis : axes) {
density = density * axis.pdf(o.get(i));
i++;
}
@@ -400,7 +400,7 @@ public class GeneratorSingleCluster implements GeneratorInterfaceDynamic, Model
* @param i Generator axis i
* @return Distribution
*/
- public DistributionWithRandom getDistribution(int i) {
+ public Distribution getDistribution(int i) {
return axes.get(i);
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/GeneratorStatic.java b/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/GeneratorStatic.java
index 7075bcb4..b8b0dff0 100644
--- a/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/GeneratorStatic.java
+++ b/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/GeneratorStatic.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.synthetic.bymodel;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/package-info.java b/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/package-info.java
index 51dcd8e8..714a7835 100644
--- a/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/package-info.java
@@ -13,7 +13,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/synthetic/package-info.java b/src/de/lmu/ifi/dbs/elki/data/synthetic/package-info.java
index c311cf0b..98957f09 100644
--- a/src/de/lmu/ifi/dbs/elki/data/synthetic/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/data/synthetic/package-info.java
@@ -7,7 +7,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/type/AlternativeTypeInformation.java b/src/de/lmu/ifi/dbs/elki/data/type/AlternativeTypeInformation.java
index f4eba35e..f1d85620 100644
--- a/src/de/lmu/ifi/dbs/elki/data/type/AlternativeTypeInformation.java
+++ b/src/de/lmu/ifi/dbs/elki/data/type/AlternativeTypeInformation.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.type;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,13 +23,13 @@ package de.lmu.ifi.dbs.elki.data.type;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
-
/**
* Class that combines multiple type restrictions into one using the "or"
* operator.
*
* @author Erich Schubert
+ *
+ * @apiviz.composedOf TypeInformation
*/
public class AlternativeTypeInformation implements TypeInformation {
/**
@@ -49,8 +49,8 @@ public class AlternativeTypeInformation implements TypeInformation {
@Override
public boolean isAssignableFromType(TypeInformation type) {
- for(int i = 0; i < restrictions.length; i++) {
- if(restrictions[i].isAssignableFromType(type)) {
+ for (int i = 0; i < restrictions.length; i++) {
+ if (restrictions[i].isAssignableFromType(type)) {
return true;
}
}
@@ -59,8 +59,8 @@ public class AlternativeTypeInformation implements TypeInformation {
@Override
public boolean isAssignableFrom(Object other) {
- for(int i = 0; i < restrictions.length; i++) {
- if(restrictions[i].isAssignableFrom(other)) {
+ for (int i = 0; i < restrictions.length; i++) {
+ if (restrictions[i].isAssignableFrom(other)) {
return true;
}
}
@@ -70,12 +70,12 @@ public class AlternativeTypeInformation implements TypeInformation {
@Override
public String toString() {
StringBuilder buf = new StringBuilder();
- for(int i = 0; i < restrictions.length; i++) {
- if(i > 0) {
+ for (int i = 0; i < restrictions.length; i++) {
+ if (i > 0) {
buf.append(" OR ");
}
buf.append(restrictions[i].toString());
}
return buf.toString();
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/data/type/CombinedTypeInformation.java b/src/de/lmu/ifi/dbs/elki/data/type/CombinedTypeInformation.java
index 6d8c490c..efb22237 100644
--- a/src/de/lmu/ifi/dbs/elki/data/type/CombinedTypeInformation.java
+++ b/src/de/lmu/ifi/dbs/elki/data/type/CombinedTypeInformation.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.type;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,11 +23,12 @@ package de.lmu.ifi.dbs.elki.data.type;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
/**
* Class that combines multiple type restrictions into one using an "and" operator.
*
* @author Erich Schubert
+ *
+ * @apiviz.composedOf TypeInformation
*/
public class CombinedTypeInformation implements TypeInformation {
/**
diff --git a/src/de/lmu/ifi/dbs/elki/data/type/NoSupportedDataTypeException.java b/src/de/lmu/ifi/dbs/elki/data/type/NoSupportedDataTypeException.java
index 389d86dc..f1bfce91 100644
--- a/src/de/lmu/ifi/dbs/elki/data/type/NoSupportedDataTypeException.java
+++ b/src/de/lmu/ifi/dbs/elki/data/type/NoSupportedDataTypeException.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.type;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/type/SimpleTypeInformation.java b/src/de/lmu/ifi/dbs/elki/data/type/SimpleTypeInformation.java
index 738c66f8..dcf155db 100644
--- a/src/de/lmu/ifi/dbs/elki/data/type/SimpleTypeInformation.java
+++ b/src/de/lmu/ifi/dbs/elki/data/type/SimpleTypeInformation.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.type;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -30,6 +30,8 @@ import de.lmu.ifi.dbs.elki.persistent.ByteBufferSerializer;
*
* @author Erich Schubert
*
+ * @apiviz.composedOf ByteBuffererSerializer
+ *
* @param <T> Java type we represent.
*/
public class SimpleTypeInformation<T> implements TypeInformation {
diff --git a/src/de/lmu/ifi/dbs/elki/data/type/TypeInformation.java b/src/de/lmu/ifi/dbs/elki/data/type/TypeInformation.java
index d39afcad..d91a88c6 100644
--- a/src/de/lmu/ifi/dbs/elki/data/type/TypeInformation.java
+++ b/src/de/lmu/ifi/dbs/elki/data/type/TypeInformation.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.type;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/type/TypeInformationSerializer.java b/src/de/lmu/ifi/dbs/elki/data/type/TypeInformationSerializer.java
index 27eb5c2f..ac3fd164 100644
--- a/src/de/lmu/ifi/dbs/elki/data/type/TypeInformationSerializer.java
+++ b/src/de/lmu/ifi/dbs/elki/data/type/TypeInformationSerializer.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.type;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -159,7 +159,7 @@ public class TypeInformationSerializer implements ByteBufferSerializer<TypeInfor
label = ("".equals(label)) ? null : label;
String sername = ByteArrayUtil.STRING_SERIALIZER.fromByteBuffer(buffer);
ByteBufferSerializer<Object> serializer = (ByteBufferSerializer<Object>) Class.forName(sername).newInstance();
- return new SimpleTypeInformation<Object>(clz, label, serializer);
+ return new SimpleTypeInformation<>(clz, label, serializer);
} catch (ClassNotFoundException e) {
throw new UnsupportedOperationException("Cannot deserialize - class not found: " + e, e);
} catch (InstantiationException e) {
@@ -240,7 +240,7 @@ public class TypeInformationSerializer implements ByteBufferSerializer<TypeInfor
ByteBufferSerializer<DoubleVector> serializer = (ByteBufferSerializer<DoubleVector>) Class.forName(sername).newInstance();
int mindim = ByteArrayUtil.readSignedVarint(buffer);
int maxdim = ByteArrayUtil.readSignedVarint(buffer);
- return new VectorTypeInformation<DoubleVector>(clz, serializer, mindim, maxdim);
+ return new VectorTypeInformation<>(clz, serializer, mindim, maxdim);
} catch (ClassNotFoundException e) {
throw new UnsupportedOperationException("Cannot deserialize - class not found: "+e, e);
} catch (InstantiationException e) {
@@ -338,9 +338,9 @@ public class TypeInformationSerializer implements ByteBufferSerializer<TypeInfor
for (int i = 0; i < cols; i++) {
labels[i] = ByteArrayUtil.readString(buffer);
}
- return new VectorFieldTypeInformation<DoubleVector>(factory, mindim, labels, serializer);
+ return new VectorFieldTypeInformation<>(factory, mindim, labels, serializer);
} else {
- return new VectorFieldTypeInformation<DoubleVector>(factory, mindim, maxdim, serializer);
+ return new VectorFieldTypeInformation<>(factory, mindim, maxdim, serializer);
}
} catch (UnableToComplyException e) {
throw new UnsupportedOperationException("Cannot deserialize - cannot instantiate factory: "+e, e);
diff --git a/src/de/lmu/ifi/dbs/elki/data/type/TypeUtil.java b/src/de/lmu/ifi/dbs/elki/data/type/TypeUtil.java
index ea5f2fc2..4236740b 100644
--- a/src/de/lmu/ifi/dbs/elki/data/type/TypeUtil.java
+++ b/src/de/lmu/ifi/dbs/elki/data/type/TypeUtil.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.type;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -39,7 +39,7 @@ import de.lmu.ifi.dbs.elki.data.spatial.PolygonsObject;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDFactory;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Matrix;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
import de.lmu.ifi.dbs.elki.persistent.ByteArrayUtil;
@@ -63,42 +63,42 @@ public final class TypeUtil {
/**
* Input type for algorithms that accept anything.
*/
- public static final SimpleTypeInformation<Object> ANY = new SimpleTypeInformation<Object>(Object.class);
+ public static final SimpleTypeInformation<Object> ANY = new SimpleTypeInformation<>(Object.class);
/**
* Database IDs.
*/
- public static final SimpleTypeInformation<DBID> DBID = new SimpleTypeInformation<DBID>(DBID.class, DBIDFactory.FACTORY.getDBIDSerializer());
+ public static final SimpleTypeInformation<DBID> DBID = new SimpleTypeInformation<>(DBID.class, DBIDFactory.FACTORY.getDBIDSerializer());
/**
* Database ID lists.
*/
- public static final SimpleTypeInformation<DBIDs> DBIDS = new SimpleTypeInformation<DBIDs>(DBIDs.class);
+ public static final SimpleTypeInformation<DBIDs> DBIDS = new SimpleTypeInformation<>(DBIDs.class);
/**
* A string.
*/
- public static final SimpleTypeInformation<String> STRING = new SimpleTypeInformation<String>(String.class, ByteArrayUtil.STRING_SERIALIZER);
+ public static final SimpleTypeInformation<String> STRING = new SimpleTypeInformation<>(String.class, ByteArrayUtil.STRING_SERIALIZER);
/**
* A class label.
*/
- public static final SimpleTypeInformation<ClassLabel> CLASSLABEL = new SimpleTypeInformation<ClassLabel>(ClassLabel.class);
+ public static final SimpleTypeInformation<ClassLabel> CLASSLABEL = new SimpleTypeInformation<>(ClassLabel.class);
/**
* Simple class labels.
*/
- public static final SimpleTypeInformation<SimpleClassLabel> SIMPLE_CLASSLABEL = new SimpleTypeInformation<SimpleClassLabel>(SimpleClassLabel.class, SimpleClassLabel.SERIALIZER);
+ public static final SimpleTypeInformation<SimpleClassLabel> SIMPLE_CLASSLABEL = new SimpleTypeInformation<>(SimpleClassLabel.class, SimpleClassLabel.SERIALIZER);
/**
* A list of labels.
*/
- public static final SimpleTypeInformation<LabelList> LABELLIST = new SimpleTypeInformation<LabelList>(LabelList.class, LabelList.SERIALIZER);
+ public static final SimpleTypeInformation<LabelList> LABELLIST = new SimpleTypeInformation<>(LabelList.class, LabelList.SERIALIZER);
/**
* A list of neighbors.
*/
- public static final SimpleTypeInformation<DistanceDBIDResult<?>> NEIGHBORLIST = new SimpleTypeInformation<DistanceDBIDResult<?>>(DistanceDBIDResult.class);
+ public static final SimpleTypeInformation<DistanceDBIDList<?>> NEIGHBORLIST = new SimpleTypeInformation<>(DistanceDBIDList.class);
/**
* Either class label, object labels or a string - anything that will be
@@ -110,90 +110,90 @@ public final class TypeUtil {
/**
* Number vectors of <em>variable</em> length.
*/
- public static final SimpleTypeInformation<? super NumberVector<?>> NUMBER_VECTOR_VARIABLE_LENGTH = new SimpleTypeInformation<NumberVector<?>>(NumberVector.class);
+ public static final SimpleTypeInformation<? super NumberVector<?>> NUMBER_VECTOR_VARIABLE_LENGTH = new SimpleTypeInformation<>(NumberVector.class);
/**
* Input type for algorithms that require number vector fields.
*/
- public static final VectorFieldTypeInformation<NumberVector<?>> NUMBER_VECTOR_FIELD = new VectorFieldTypeInformation<NumberVector<?>>(NumberVector.class);
+ public static final VectorFieldTypeInformation<NumberVector<?>> NUMBER_VECTOR_FIELD = new VectorFieldTypeInformation<>(NumberVector.class);
/**
* Input type for algorithms that require number vector fields.
*
* If possible, please use {@link #NUMBER_VECTOR_FIELD}!
*/
- public static final VectorFieldTypeInformation<DoubleVector> DOUBLE_VECTOR_FIELD = new VectorFieldTypeInformation<DoubleVector>(DoubleVector.class);
+ public static final VectorFieldTypeInformation<DoubleVector> DOUBLE_VECTOR_FIELD = new VectorFieldTypeInformation<>(DoubleVector.class);
/**
* Input type for algorithms that require number vector fields.
*
* If possible, please use {@link #NUMBER_VECTOR_FIELD}!
*/
- public static final VectorFieldTypeInformation<FloatVector> FLOAT_VECTOR_FIELD = new VectorFieldTypeInformation<FloatVector>(FloatVector.class);
+ public static final VectorFieldTypeInformation<FloatVector> FLOAT_VECTOR_FIELD = new VectorFieldTypeInformation<>(FloatVector.class);
/**
* Input type for algorithms that require number vector fields.
*/
- public static final VectorFieldTypeInformation<BitVector> BIT_VECTOR_FIELD = new VectorFieldTypeInformation<BitVector>(BitVector.class);
+ public static final VectorFieldTypeInformation<BitVector> BIT_VECTOR_FIELD = new VectorFieldTypeInformation<>(BitVector.class);
/**
* Sparse float vector field.
*/
- public static final SimpleTypeInformation<SparseNumberVector<?>> SPARSE_VECTOR_VARIABLE_LENGTH = new SimpleTypeInformation<SparseNumberVector<?>>(SparseNumberVector.class);
+ public static final SimpleTypeInformation<SparseNumberVector<?>> SPARSE_VECTOR_VARIABLE_LENGTH = new SimpleTypeInformation<>(SparseNumberVector.class);
/**
* Sparse vector field.
*/
- public static final VectorFieldTypeInformation<SparseNumberVector<?>> SPARSE_VECTOR_FIELD = new VectorFieldTypeInformation<SparseNumberVector<?>>(SparseNumberVector.class);
+ public static final VectorFieldTypeInformation<SparseNumberVector<?>> SPARSE_VECTOR_FIELD = new VectorFieldTypeInformation<>(SparseNumberVector.class);
/**
* Sparse float vector field.
*
* If possible, please use {@link #SPARSE_VECTOR_FIELD} instead!
*/
- public static final VectorFieldTypeInformation<SparseFloatVector> SPARSE_FLOAT_FIELD = new VectorFieldTypeInformation<SparseFloatVector>(SparseFloatVector.class);
+ public static final VectorFieldTypeInformation<SparseFloatVector> SPARSE_FLOAT_FIELD = new VectorFieldTypeInformation<>(SparseFloatVector.class);
/**
* Sparse double vector field.
*
* If possible, please use {@link #SPARSE_VECTOR_FIELD} instead!
*/
- public static final VectorFieldTypeInformation<SparseDoubleVector> SPARSE_DOUBLE_FIELD = new VectorFieldTypeInformation<SparseDoubleVector>(SparseDoubleVector.class);
+ public static final VectorFieldTypeInformation<SparseDoubleVector> SPARSE_DOUBLE_FIELD = new VectorFieldTypeInformation<>(SparseDoubleVector.class);
/**
* External ID type.
*/
- public static final SimpleTypeInformation<ExternalID> EXTERNALID = new SimpleTypeInformation<ExternalID>(ExternalID.class);
+ public static final SimpleTypeInformation<ExternalID> EXTERNALID = new SimpleTypeInformation<>(ExternalID.class);
/**
* Type for polygons.
*/
- public static final SimpleTypeInformation<PolygonsObject> POLYGON_TYPE = new SimpleTypeInformation<PolygonsObject>(PolygonsObject.class);
+ public static final SimpleTypeInformation<PolygonsObject> POLYGON_TYPE = new SimpleTypeInformation<>(PolygonsObject.class);
/**
* Double type, outlier scores etc.
*/
- public static final SimpleTypeInformation<Double> DOUBLE = new SimpleTypeInformation<Double>(Double.class, ByteArrayUtil.DOUBLE_SERIALIZER);
+ public static final SimpleTypeInformation<Double> DOUBLE = new SimpleTypeInformation<>(Double.class, ByteArrayUtil.DOUBLE_SERIALIZER);
/**
* Integer type.
*/
- public static final SimpleTypeInformation<Integer> INTEGER = new SimpleTypeInformation<Integer>(Integer.class, ByteArrayUtil.INT_SERIALIZER);
+ public static final SimpleTypeInformation<Integer> INTEGER = new SimpleTypeInformation<>(Integer.class, ByteArrayUtil.INT_SERIALIZER);
/**
* Vector type.
*/
- public static final SimpleTypeInformation<Vector> VECTOR = new SimpleTypeInformation<Vector>(Vector.class);
+ public static final SimpleTypeInformation<Vector> VECTOR = new SimpleTypeInformation<>(Vector.class);
/**
* Matrix type.
*/
- public static final SimpleTypeInformation<Matrix> MATRIX = new SimpleTypeInformation<Matrix>(Matrix.class);
+ public static final SimpleTypeInformation<Matrix> MATRIX = new SimpleTypeInformation<>(Matrix.class);
/**
* Cluster model type.
*/
- public static final SimpleTypeInformation<Model> MODEL = new SimpleTypeInformation<Model>(Model.class);
+ public static final SimpleTypeInformation<Model> MODEL = new SimpleTypeInformation<>(Model.class);
/**
* Make a type array easily.
diff --git a/src/de/lmu/ifi/dbs/elki/data/type/VectorFieldTypeInformation.java b/src/de/lmu/ifi/dbs/elki/data/type/VectorFieldTypeInformation.java
index 7de2a121..d05eed34 100644
--- a/src/de/lmu/ifi/dbs/elki/data/type/VectorFieldTypeInformation.java
+++ b/src/de/lmu/ifi/dbs/elki/data/type/VectorFieldTypeInformation.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.type;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/data/type/VectorTypeInformation.java b/src/de/lmu/ifi/dbs/elki/data/type/VectorTypeInformation.java
index 4ba86a8b..7d568a55 100644
--- a/src/de/lmu/ifi/dbs/elki/data/type/VectorTypeInformation.java
+++ b/src/de/lmu/ifi/dbs/elki/data/type/VectorTypeInformation.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.data.type;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -31,6 +31,8 @@ import de.lmu.ifi.dbs.elki.persistent.ByteBufferSerializer;
*
* @author Erich Schubert
*
+ * @apiviz.has FeatureVector
+ *
* @param <V> Vector type
*/
public class VectorTypeInformation<V extends FeatureVector<?>> extends SimpleTypeInformation<V> {
diff --git a/src/de/lmu/ifi/dbs/elki/data/type/package-info.java b/src/de/lmu/ifi/dbs/elki/data/type/package-info.java
index 858efc7a..ad666ab4 100644
--- a/src/de/lmu/ifi/dbs/elki/data/type/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/data/type/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/AbstractDatabase.java b/src/de/lmu/ifi/dbs/elki/database/AbstractDatabase.java
index b62db142..8b3a64eb 100644
--- a/src/de/lmu/ifi/dbs/elki/database/AbstractDatabase.java
+++ b/src/de/lmu/ifi/dbs/elki/database/AbstractDatabase.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -82,17 +82,17 @@ public abstract class AbstractDatabase extends AbstractHierarchicalResult implem
/**
* The relations we manage.
*/
- protected final List<Relation<?>> relations = new java.util.Vector<Relation<?>>();
+ protected final List<Relation<?>> relations = new ArrayList<>();
/**
* Indexes.
*/
- protected final List<Index> indexes = new java.util.Vector<Index>();
+ protected final List<Index> indexes = new ArrayList<>();
/**
* Index factories.
*/
- protected final Collection<IndexFactory<?, ?>> indexFactories = new java.util.Vector<IndexFactory<?, ?>>();
+ protected final Collection<IndexFactory<?, ?>> indexFactories = new ArrayList<>();
/**
* Constructor.
@@ -154,7 +154,7 @@ public abstract class AbstractDatabase extends AbstractHierarchicalResult implem
return (Relation<O>) relation;
}
}
- List<TypeInformation> types = new ArrayList<TypeInformation>(relations.size());
+ List<TypeInformation> types = new ArrayList<>(relations.size());
for(Relation<?> relation : relations) {
types.add(relation.getDataTypeInformation());
}
@@ -269,7 +269,7 @@ public abstract class AbstractDatabase extends AbstractHierarchicalResult implem
}
}
KNNQuery<O, D> knnQuery = getKNNQuery(distanceQuery, DatabaseQuery.HINT_BULK, maxk);
- return new LinearScanRKNNQuery<O, D>(distanceQuery, knnQuery, maxk);
+ return new LinearScanRKNNQuery<>(distanceQuery, knnQuery, maxk);
}
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/database/Database.java b/src/de/lmu/ifi/dbs/elki/database/Database.java
index e5b9f7ff..da4cc827 100644
--- a/src/de/lmu/ifi/dbs/elki/database/Database.java
+++ b/src/de/lmu/ifi/dbs/elki/database/Database.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -42,7 +42,7 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.distance.similarityfunction.SimilarityFunction;
import de.lmu.ifi.dbs.elki.index.Index;
import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
-import de.lmu.ifi.dbs.elki.utilities.InspectionUtilFrequentlyScanned;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
/**
* Database specifies the requirements for any database implementation. Note
@@ -60,7 +60,17 @@ import de.lmu.ifi.dbs.elki.utilities.InspectionUtilFrequentlyScanned;
* @apiviz.has Index oneway - - manages
* @apiviz.has DataStoreListener oneway - - invokes
*/
-public interface Database extends HierarchicalResult, InspectionUtilFrequentlyScanned {
+public interface Database extends HierarchicalResult {
+ /**
+ * Option to specify the data source for the database.
+ *
+ * Key:
+ * <p>
+ * {@code -dbc}
+ * </p>
+ */
+ public static final OptionID DATABASE_CONNECTION_ID = new OptionID("dbc", "Database connection class.");
+
/**
* Initialize the database, for example by loading the input data. (Since this
* should NOT be done on construction time!)
diff --git a/src/de/lmu/ifi/dbs/elki/database/DatabaseEventManager.java b/src/de/lmu/ifi/dbs/elki/database/DatabaseEventManager.java
index ce6e4d9a..4b9c9d94 100644
--- a/src/de/lmu/ifi/dbs/elki/database/DatabaseEventManager.java
+++ b/src/de/lmu/ifi/dbs/elki/database/DatabaseEventManager.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.database;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -88,7 +88,7 @@ public class DatabaseEventManager {
public void flushDataStoreEvents() {
// inform listeners
Object[] listeners = listenerList.getListenerList();
- Map<Type, DBIDs> objects = new HashMap<Type, DBIDs>();
+ Map<Type, DBIDs> objects = new HashMap<>();
objects.put(currentDataStoreEventType, DBIDUtil.makeUnmodifiable(dataStoreObjects));
DataStoreEvent e = new DataStoreEvent(this, objects);
diff --git a/src/de/lmu/ifi/dbs/elki/database/HashmapDatabase.java b/src/de/lmu/ifi/dbs/elki/database/HashmapDatabase.java
index 069de73e..e7106927 100644
--- a/src/de/lmu/ifi/dbs/elki/database/HashmapDatabase.java
+++ b/src/de/lmu/ifi/dbs/elki/database/HashmapDatabase.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -44,13 +44,13 @@ import de.lmu.ifi.dbs.elki.datasource.FileBasedDatabaseConnection;
import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle;
import de.lmu.ifi.dbs.elki.datasource.bundle.ObjectBundle;
import de.lmu.ifi.dbs.elki.datasource.bundle.SingleObjectBundle;
+import de.lmu.ifi.dbs.elki.index.DynamicIndex;
import de.lmu.ifi.dbs.elki.index.Index;
import de.lmu.ifi.dbs.elki.index.IndexFactory;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.utilities.documentation.Description;
import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectListParameter;
@@ -172,7 +172,11 @@ public class HashmapDatabase extends AbstractDatabase implements UpdatableDataba
// Notify indexes of insertions
for (Index index : indexes) {
- index.insertAll(newids);
+ if (index instanceof DynamicIndex) {
+ ((DynamicIndex) index).insertAll(newids);
+ } else {
+ LOG.warning("Non-dynamic indexes have been added to the database. Updates are not possible!");
+ }
}
// fire insertion event
@@ -222,7 +226,7 @@ public class HashmapDatabase extends AbstractDatabase implements UpdatableDataba
private Relation<?> addNewRelation(SimpleTypeInformation<?> meta) {
@SuppressWarnings("unchecked")
SimpleTypeInformation<Object> ometa = (SimpleTypeInformation<Object>) meta;
- Relation<?> relation = new MaterializedRelation<Object>(this, ometa, ids);
+ Relation<?> relation = new MaterializedRelation<>(this, ometa, ids);
relations.add(relation);
getHierarchy().add(this, relation);
// Try to add indexes where appropriate
@@ -232,24 +236,27 @@ public class HashmapDatabase extends AbstractDatabase implements UpdatableDataba
final IndexFactory<Object, ?> ofact = (IndexFactory<Object, ?>) factory;
@SuppressWarnings("unchecked")
final Relation<Object> orep = (Relation<Object>) relation;
- addIndex(ofact.instantiate(orep));
+ Index index = ofact.instantiate(orep);
+ addIndex(index);
+ index.initialize();
}
}
return relation;
}
/**
- * Removes the objects from the database (by calling {@link #doDelete(DBIDRef)}
- * for each object) and indexes and fires a deletion event.
+ * Removes the objects from the database (by calling
+ * {@link #doDelete(DBIDRef)} for each object) and indexes and fires a
+ * deletion event.
*
- * {@inheritDoc}
+ * {@inheritDoc}
*/
@Override
public MultipleObjectsBundle delete(DBIDs ids) {
// Prepare bundle to return
MultipleObjectsBundle bundle = new MultipleObjectsBundle();
for (Relation<?> relation : relations) {
- ArrayList<Object> data = new ArrayList<Object>(ids.size());
+ ArrayList<Object> data = new ArrayList<>(ids.size());
for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
data.add(relation.get(iter));
}
@@ -261,7 +268,12 @@ public class HashmapDatabase extends AbstractDatabase implements UpdatableDataba
}
// Remove from indexes
for (Index index : indexes) {
- index.deleteAll(ids);
+ if (index instanceof DynamicIndex) {
+ ((DynamicIndex) index).deleteAll(ids);
+ } else {
+ LOG.warning("Non-dynamic indexes have been added to the database. Updates are not possible!");
+ }
+
}
// fire deletion event
eventManager.fireObjectsRemoved(ids);
@@ -270,10 +282,10 @@ public class HashmapDatabase extends AbstractDatabase implements UpdatableDataba
}
/**
- * Removes the object from the database (by calling {@link #doDelete(DBIDRef)})
- * and indexes and fires a deletion event.
- *
- * {@inheritDoc}
+ * Removes the object from the database (by calling {@link #doDelete(DBIDRef)}
+ * ) and indexes and fires a deletion event.
+ *
+ * {@inheritDoc}
*/
@Override
public SingleObjectBundle delete(DBIDRef id) {
@@ -285,7 +297,11 @@ public class HashmapDatabase extends AbstractDatabase implements UpdatableDataba
doDelete(id);
// Remove from indexes
for (Index index : indexes) {
- index.delete(id);
+ if (index instanceof DynamicIndex) {
+ ((DynamicIndex) index).delete(id);
+ } else {
+ LOG.warning("Non-dynamic indexes have been added to the database. Updates are not possible!");
+ }
}
// fire deletion event
eventManager.fireObjectRemoved(id);
@@ -338,12 +354,12 @@ public class HashmapDatabase extends AbstractDatabase implements UpdatableDataba
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
// Get database connection.
- final ObjectParameter<DatabaseConnection> dbcP = new ObjectParameter<DatabaseConnection>(OptionID.DATABASE_CONNECTION, DatabaseConnection.class, FileBasedDatabaseConnection.class);
+ final ObjectParameter<DatabaseConnection> dbcP = new ObjectParameter<>(Database.DATABASE_CONNECTION_ID, DatabaseConnection.class, FileBasedDatabaseConnection.class);
if (config.grab(dbcP)) {
databaseConnection = dbcP.instantiateClass(config);
}
// Get indexes.
- final ObjectListParameter<IndexFactory<?, ?>> indexFactoryP = new ObjectListParameter<IndexFactory<?, ?>>(INDEX_ID, IndexFactory.class, true);
+ final ObjectListParameter<IndexFactory<?, ?>> indexFactoryP = new ObjectListParameter<>(INDEX_ID, IndexFactory.class, true);
if (config.grab(indexFactoryP)) {
indexFactories = indexFactoryP.instantiateClasses(config);
}
diff --git a/src/de/lmu/ifi/dbs/elki/database/ProxyDatabase.java b/src/de/lmu/ifi/dbs/elki/database/ProxyDatabase.java
index 3f41326a..a06b7a12 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ProxyDatabase.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ProxyDatabase.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -43,14 +43,9 @@ public class ProxyDatabase extends AbstractDatabase {
private static final Logging LOG = Logging.getLogger(ProxyDatabase.class);
/**
- * Our DBIDs
- */
- final protected DBIDs ids;
-
- /**
* Our DBID representation
*/
- final protected DBIDView idrep;
+ protected DBIDView idrep;
/**
* Constructor.
@@ -59,8 +54,7 @@ public class ProxyDatabase extends AbstractDatabase {
*/
public ProxyDatabase(DBIDs ids) {
super();
- this.ids = ids;
- this.idrep = new DBIDView(this, this.ids);
+ this.idrep = new DBIDView(this, ids);
this.relations.add(idrep);
this.addChildResult(idrep);
}
@@ -73,11 +67,10 @@ public class ProxyDatabase extends AbstractDatabase {
*/
public ProxyDatabase(DBIDs ids, Iterable<Relation<?>> relations) {
super();
- this.ids = ids;
- this.idrep = new DBIDView(this, this.ids);
+ this.idrep = new DBIDView(this, ids);
this.relations.add(idrep);
this.addChildResult(idrep);
- for(Relation<?> orel : relations) {
+ for (Relation<?> orel : relations) {
Relation<?> relation = ProxyView.wrap(this, ids, orel);
this.relations.add(relation);
this.addChildResult(relation);
@@ -122,4 +115,19 @@ public class ProxyDatabase extends AbstractDatabase {
protected Logging getLogger() {
return LOG;
}
-} \ No newline at end of file
+
+ /**
+ * Set the DBIDs to use.
+ *
+ * @param ids DBIDs to use
+ */
+ public void setDBIDs(DBIDs ids) {
+ this.idrep.setDBIDs(ids);
+ // Update relations.
+ for (Relation<?> orel : this.relations) {
+ if (orel instanceof ProxyView) {
+ ((ProxyView<?>) orel).setDBIDs(this.idrep.getDBIDs());
+ }
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/database/QueryUtil.java b/src/de/lmu/ifi/dbs/elki/database/QueryUtil.java
index f65b3cba..73259b5d 100644
--- a/src/de/lmu/ifi/dbs/elki/database/QueryUtil.java
+++ b/src/de/lmu/ifi/dbs/elki/database/QueryUtil.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,10 +28,10 @@ import de.lmu.ifi.dbs.elki.database.query.distance.PrimitiveDistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.LinearScanKNNQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.LinearScanPrimitiveDistanceKNNQuery;
-import de.lmu.ifi.dbs.elki.database.query.knn.LinearScanRawDoubleDistanceKNNQuery;
+import de.lmu.ifi.dbs.elki.database.query.knn.DoubleOptimizedKNNQuery;
import de.lmu.ifi.dbs.elki.database.query.range.LinearScanPrimitiveDistanceRangeQuery;
import de.lmu.ifi.dbs.elki.database.query.range.LinearScanRangeQuery;
-import de.lmu.ifi.dbs.elki.database.query.range.LinearScanRawDoubleDistanceRangeQuery;
+import de.lmu.ifi.dbs.elki.database.query.range.DoubleOptimizedRangeQuery;
import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery;
import de.lmu.ifi.dbs.elki.database.query.rknn.RKNNQuery;
import de.lmu.ifi.dbs.elki.database.query.similarity.SimilarityQuery;
@@ -233,17 +233,17 @@ public final class QueryUtil {
if(distanceQuery.getDistanceFunction() instanceof PrimitiveDoubleDistanceFunction) {
final PrimitiveDistanceQuery<O, ?> pdq = (PrimitiveDistanceQuery<O, ?>) distanceQuery;
@SuppressWarnings("unchecked")
- final KNNQuery<O, ?> knnQuery = new LinearScanRawDoubleDistanceKNNQuery<O>((PrimitiveDistanceQuery<O, DoubleDistance>) pdq);
+ final KNNQuery<O, ?> knnQuery = new DoubleOptimizedKNNQuery<>((PrimitiveDistanceQuery<O, DoubleDistance>) pdq);
@SuppressWarnings("unchecked")
final KNNQuery<O, D> castQuery = (KNNQuery<O, D>) knnQuery;
return castQuery;
}
else {
final PrimitiveDistanceQuery<O, D> pdq = (PrimitiveDistanceQuery<O, D>) distanceQuery;
- return new LinearScanPrimitiveDistanceKNNQuery<O, D>(pdq);
+ return new LinearScanPrimitiveDistanceKNNQuery<>(pdq);
}
}
- return new LinearScanKNNQuery<O, D>(distanceQuery);
+ return new LinearScanKNNQuery<>(distanceQuery);
}
/**
@@ -260,16 +260,16 @@ public final class QueryUtil {
if(distanceQuery.getDistanceFunction() instanceof PrimitiveDoubleDistanceFunction) {
final PrimitiveDistanceQuery<O, ?> pdq = (PrimitiveDistanceQuery<O, ?>) distanceQuery;
@SuppressWarnings("unchecked")
- final RangeQuery<O, ?> knnQuery = new LinearScanRawDoubleDistanceRangeQuery<O>((PrimitiveDistanceQuery<O, DoubleDistance>) pdq);
+ final RangeQuery<O, ?> knnQuery = new DoubleOptimizedRangeQuery<>((PrimitiveDistanceQuery<O, DoubleDistance>) pdq);
@SuppressWarnings("unchecked")
final RangeQuery<O, D> castQuery = (RangeQuery<O, D>) knnQuery;
return castQuery;
}
else {
final PrimitiveDistanceQuery<O, D> pdq = (PrimitiveDistanceQuery<O, D>) distanceQuery;
- return new LinearScanPrimitiveDistanceRangeQuery<O, D>(pdq);
+ return new LinearScanPrimitiveDistanceRangeQuery<>(pdq);
}
}
- return new LinearScanRangeQuery<O, D>(distanceQuery);
+ return new LinearScanRangeQuery<>(distanceQuery);
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/database/StaticArrayDatabase.java b/src/de/lmu/ifi/dbs/elki/database/StaticArrayDatabase.java
index c2d66f5c..7916c75f 100644
--- a/src/de/lmu/ifi/dbs/elki/database/StaticArrayDatabase.java
+++ b/src/de/lmu/ifi/dbs/elki/database/StaticArrayDatabase.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -43,9 +43,9 @@ import de.lmu.ifi.dbs.elki.datasource.bundle.ObjectBundle;
import de.lmu.ifi.dbs.elki.index.Index;
import de.lmu.ifi.dbs.elki.index.IndexFactory;
import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.statistics.Duration;
import de.lmu.ifi.dbs.elki.utilities.documentation.Description;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectListParameter;
@@ -98,7 +98,7 @@ public class StaticArrayDatabase extends AbstractDatabase implements Parameteriz
this.idrep = null;
// Add indexes.
- if(indexFactories != null) {
+ if (indexFactories != null) {
this.indexFactories.addAll(indexFactories);
}
}
@@ -116,8 +116,8 @@ public class StaticArrayDatabase extends AbstractDatabase implements Parameteriz
*/
@Override
public void initialize() {
- if(databaseConnection != null) {
- if(LOG.isDebugging()) {
+ if (databaseConnection != null) {
+ if (LOG.isDebugging()) {
LOG.debugFine("Loading data from database connection.");
}
MultipleObjectsBundle objpackages = databaseConnection.loadData();
@@ -127,12 +127,11 @@ public class StaticArrayDatabase extends AbstractDatabase implements Parameteriz
// Find DBID column
int idrepnr = findDBIDColumn(objpackages);
// Build DBID array
- if(idrepnr == -1) {
+ if (idrepnr == -1) {
this.ids = DBIDUtil.generateStaticDBIDRange(objpackages.dataLength());
- }
- else {
+ } else {
final ArrayModifiableDBIDs newids = DBIDUtil.newArray(objpackages.dataLength());
- for(int j = 0; j < objpackages.dataLength(); j++) {
+ for (int j = 0; j < objpackages.dataLength(); j++) {
DBID newid = (DBID) objpackages.data(j, idrepnr);
newids.add(newid);
}
@@ -148,11 +147,11 @@ public class StaticArrayDatabase extends AbstractDatabase implements Parameteriz
Relation<?>[] targets = alignColumns(objpackages);
DBIDIter newid = ids.iter();
- for(int j = 0; j < objpackages.dataLength(); j++, newid.advance()) {
+ for (int j = 0; j < objpackages.dataLength(); j++, newid.advance()) {
// insert object
- for(int i = 0; i < targets.length; i++) {
+ for (int i = 0; i < targets.length; i++) {
// DBIDs were handled above.
- if(i == idrepnr) {
+ if (i == idrepnr) {
continue;
}
@SuppressWarnings("unchecked")
@@ -161,18 +160,26 @@ public class StaticArrayDatabase extends AbstractDatabase implements Parameteriz
}
}
- for(Relation<?> relation : relations) {
+ for (Relation<?> relation : relations) {
SimpleTypeInformation<?> meta = relation.getDataTypeInformation();
// Try to add indexes where appropriate
- for(IndexFactory<?, ?> factory : indexFactories) {
- if(factory.getInputTypeRestriction().isAssignableFromType(meta)) {
+ for (IndexFactory<?, ?> factory : indexFactories) {
+ if (factory.getInputTypeRestriction().isAssignableFromType(meta)) {
@SuppressWarnings("unchecked")
final IndexFactory<Object, ?> ofact = (IndexFactory<Object, ?>) factory;
@SuppressWarnings("unchecked")
final Relation<Object> orep = (Relation<Object>) relation;
final Index index = ofact.instantiate(orep);
+ Duration duration = LOG.isStatistics() ? LOG.newDuration(index.getClass().getName() + ".construction") : null;
+ if (duration != null) {
+ duration.begin();
+ }
+ index.initialize();
+ if (duration != null) {
+ duration.end();
+ LOG.statistics(duration);
+ }
addIndex(index);
- index.insertAll(ids);
}
}
}
@@ -184,7 +191,7 @@ public class StaticArrayDatabase extends AbstractDatabase implements Parameteriz
@Override
public void addIndex(Index index) {
- if(LOG.isDebuggingFiner()) {
+ if (LOG.isDebuggingFiner()) {
LOG.debugFine("Adding index: " + index);
}
this.indexes.add(index);
@@ -192,7 +199,6 @@ public class StaticArrayDatabase extends AbstractDatabase implements Parameteriz
this.addChildResult(index);
}
-
/**
* Find an DBID column.
*
@@ -200,9 +206,9 @@ public class StaticArrayDatabase extends AbstractDatabase implements Parameteriz
* @return DBID column
*/
protected int findDBIDColumn(ObjectBundle pack) {
- for(int i = 0; i < pack.metaLength(); i++) {
+ for (int i = 0; i < pack.metaLength(); i++) {
SimpleTypeInformation<?> meta = pack.meta(i);
- if(TypeUtil.DBID.isAssignableFromType(meta)) {
+ if (TypeUtil.DBID.isAssignableFromType(meta)) {
return i;
}
}
@@ -220,19 +226,19 @@ public class StaticArrayDatabase extends AbstractDatabase implements Parameteriz
// align representations.
Relation<?>[] targets = new Relation<?>[pack.metaLength()];
BitSet used = new BitSet(relations.size());
- for(int i = 0; i < targets.length; i++) {
+ for (int i = 0; i < targets.length; i++) {
SimpleTypeInformation<?> meta = pack.meta(i);
// TODO: aggressively try to match exact metas first?
// Try to match unused representations only
- for(int j = used.nextClearBit(0); j >= 0 && j < relations.size(); j = used.nextClearBit(j + 1)) {
+ for (int j = used.nextClearBit(0); j >= 0 && j < relations.size(); j = used.nextClearBit(j + 1)) {
Relation<?> relation = relations.get(j);
- if(relation.getDataTypeInformation().isAssignableFromType(meta)) {
+ if (relation.getDataTypeInformation().isAssignableFromType(meta)) {
targets[i] = relation;
used.set(j);
break;
}
}
- if(targets[i] == null) {
+ if (targets[i] == null) {
targets[i] = addNewRelation(meta);
used.set(relations.size() - 1);
}
@@ -249,7 +255,7 @@ public class StaticArrayDatabase extends AbstractDatabase implements Parameteriz
private Relation<?> addNewRelation(SimpleTypeInformation<?> meta) {
@SuppressWarnings("unchecked")
SimpleTypeInformation<Object> ometa = (SimpleTypeInformation<Object>) meta;
- Relation<?> relation = new MaterializedRelation<Object>(this, ometa, ids);
+ Relation<?> relation = new MaterializedRelation<>(this, ometa, ids);
relations.add(relation);
getHierarchy().add(this, relation);
return relation;
@@ -282,13 +288,13 @@ public class StaticArrayDatabase extends AbstractDatabase implements Parameteriz
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
// Get database connection.
- final ObjectParameter<DatabaseConnection> dbcP = new ObjectParameter<DatabaseConnection>(OptionID.DATABASE_CONNECTION, DatabaseConnection.class, FileBasedDatabaseConnection.class);
- if(config.grab(dbcP)) {
+ final ObjectParameter<DatabaseConnection> dbcP = new ObjectParameter<>(Database.DATABASE_CONNECTION_ID, DatabaseConnection.class, FileBasedDatabaseConnection.class);
+ if (config.grab(dbcP)) {
databaseConnection = dbcP.instantiateClass(config);
}
// Get indexes.
- final ObjectListParameter<IndexFactory<?, ?>> indexFactoryP = new ObjectListParameter<IndexFactory<?, ?>>(INDEX_ID, IndexFactory.class, true);
- if(config.grab(indexFactoryP)) {
+ final ObjectListParameter<IndexFactory<?, ?>> indexFactoryP = new ObjectListParameter<>(INDEX_ID, IndexFactory.class, true);
+ if (config.grab(indexFactoryP)) {
indexFactories = indexFactoryP.instantiateClasses(config);
}
}
@@ -298,4 +304,4 @@ public class StaticArrayDatabase extends AbstractDatabase implements Parameteriz
return new StaticArrayDatabase(databaseConnection, indexFactories);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/database/UpdatableDatabase.java b/src/de/lmu/ifi/dbs/elki/database/UpdatableDatabase.java
index 86555a86..f22dd799 100644
--- a/src/de/lmu/ifi/dbs/elki/database/UpdatableDatabase.java
+++ b/src/de/lmu/ifi/dbs/elki/database/UpdatableDatabase.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/DBIDDataStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/DBIDDataStore.java
index 7941219f..8c0eb2cb 100644
--- a/src/de/lmu/ifi/dbs/elki/database/datastore/DBIDDataStore.java
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/DBIDDataStore.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/DataStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/DataStore.java
index a6d5a704..384680c6 100644
--- a/src/de/lmu/ifi/dbs/elki/database/datastore/DataStore.java
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/DataStore.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreEvent.java b/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreEvent.java
index 5c0a6836..7942fb9b 100644
--- a/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreEvent.java
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreEvent.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.database.datastore;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreFactory.java b/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreFactory.java
index aca5b86f..7b3cd0e7 100644
--- a/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreFactory.java
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreFactory.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreIDMap.java b/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreIDMap.java
index cba8e4c9..adfd1354 100644
--- a/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreIDMap.java
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreIDMap.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreListener.java b/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreListener.java
index 609fe67d..a3f1319d 100644
--- a/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreListener.java
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreListener.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreUtil.java b/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreUtil.java
index a9052f87..6d0c2d0f 100644
--- a/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreUtil.java
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreUtil.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,6 +24,7 @@ package de.lmu.ifi.dbs.elki.database.datastore;
*/
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
/**
* Storage utility class. Mostly a shorthand for
@@ -123,4 +124,17 @@ public final class DataStoreUtil {
public static WritableRecordStore makeRecordStorage(DBIDs ids, int hints, Class<?>... dataclasses) {
return DataStoreFactory.FACTORY.makeRecordStorage(ids, hints, dataclasses);
}
+
+ /**
+ * Make a new storage, to associate the given ids with an double valued
+ * distance.
+ *
+ * @param ids DBIDs to store data for
+ * @param hints Hints for the storage manager
+ * @return new data store
+ */
+ public static WritableDoubleDistanceDataStore makeDoubleDistanceStorage(DBIDs ids, int hints) {
+ // FIXME: this is an ugly work-around.
+ return (WritableDoubleDistanceDataStore) DataStoreFactory.FACTORY.makeStorage(ids, hints, DoubleDistance.class);
+ }
}
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/DoubleDataStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/DoubleDataStore.java
index 3348a246..b121d195 100644
--- a/src/de/lmu/ifi/dbs/elki/database/datastore/DoubleDataStore.java
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/DoubleDataStore.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/DoubleDistanceDataStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/DoubleDistanceDataStore.java
index f74b681a..88b9d4dc 100644
--- a/src/de/lmu/ifi/dbs/elki/database/datastore/DoubleDistanceDataStore.java
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/DoubleDistanceDataStore.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/IntegerDataStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/IntegerDataStore.java
index e450c11b..969e2228 100644
--- a/src/de/lmu/ifi/dbs/elki/database/datastore/IntegerDataStore.java
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/IntegerDataStore.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/RecordStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/RecordStore.java
index 508dae8e..07bf2dcf 100644
--- a/src/de/lmu/ifi/dbs/elki/database/datastore/RecordStore.java
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/RecordStore.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDBIDDataStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDBIDDataStore.java
index 960b79ac..bae55a57 100644
--- a/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDBIDDataStore.java
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDBIDDataStore.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDataStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDataStore.java
index 93176445..c62fc721 100644
--- a/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDataStore.java
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDataStore.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDoubleDataStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDoubleDataStore.java
index 19cc54c7..a40f0ef4 100644
--- a/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDoubleDataStore.java
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDoubleDataStore.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDoubleDistanceDataStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDoubleDistanceDataStore.java
index 03a3e75e..f929d5d7 100644
--- a/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDoubleDistanceDataStore.java
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDoubleDistanceDataStore.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/WritableIntegerDataStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/WritableIntegerDataStore.java
index b8bf1348..fb323b02 100644
--- a/src/de/lmu/ifi/dbs/elki/database/datastore/WritableIntegerDataStore.java
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/WritableIntegerDataStore.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/WritableRecordStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/WritableRecordStore.java
index 0799fdfe..c4c182e9 100644
--- a/src/de/lmu/ifi/dbs/elki/database/datastore/WritableRecordStore.java
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/WritableRecordStore.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayDBIDStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayDBIDStore.java
index c9bc6438..2d5033ab 100644
--- a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayDBIDStore.java
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayDBIDStore.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -78,7 +78,7 @@ public class ArrayDBIDStore implements WritableDBIDDataStore {
@Override
public void assignVar(DBIDRef id, DBIDVar var) {
- data.assign(idmap.mapDBIDToOffset(id), var);
+ data.assignVar(idmap.mapDBIDToOffset(id), var);
}
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayDoubleDistanceStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayDoubleDistanceStore.java
index 99ec1382..2bf8161d 100644
--- a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayDoubleDistanceStore.java
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayDoubleDistanceStore.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayDoubleStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayDoubleStore.java
index 1d8920bf..501d5369 100644
--- a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayDoubleStore.java
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayDoubleStore.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayIntegerStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayIntegerStore.java
index bb250164..d5b5cfb9 100644
--- a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayIntegerStore.java
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayIntegerStore.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayRecordStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayRecordStore.java
index 4dd9a684..2767b180 100644
--- a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayRecordStore.java
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayRecordStore.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -62,7 +62,7 @@ public class ArrayRecordStore implements WritableRecordStore {
@Override
public <T> WritableDataStore<T> getStorage(int col, Class<? super T> datatype) {
// TODO: add type checking safety?
- return new StorageAccessor<T>(col);
+ return new StorageAccessor<>(col);
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayStore.java
index 29658818..367b634f 100644
--- a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayStore.java
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayStore.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDDBIDStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDDBIDStore.java
index 565d0848..9b8a4be8 100644
--- a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDDBIDStore.java
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDDBIDStore.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDDoubleDistanceStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDDoubleDistanceStore.java
index 82570639..be12b54c 100644
--- a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDDoubleDistanceStore.java
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDDoubleDistanceStore.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDDoubleStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDDoubleStore.java
index 944f9710..8d73b672 100644
--- a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDDoubleStore.java
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDDoubleStore.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDIntegerStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDIntegerStore.java
index f31c97f9..935f23f4 100644
--- a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDIntegerStore.java
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDIntegerStore.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDRecordStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDRecordStore.java
index 2926f14c..c9004a0f 100644
--- a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDRecordStore.java
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDRecordStore.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -83,7 +83,7 @@ public class MapIntegerDBIDRecordStore implements WritableRecordStore {
@Override
public <T> WritableDataStore<T> getStorage(int col, Class<? super T> datatype) {
// TODO: add type checking?
- return new StorageAccessor<T>(col);
+ return new StorageAccessor<>(col);
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDStore.java
index 236389e4..ede82f15 100644
--- a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDStore.java
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDStore.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -58,7 +58,7 @@ public class MapIntegerDBIDStore<T> implements WritableDataStore<T> {
*/
public MapIntegerDBIDStore() {
super();
- this.data = new TIntObjectHashMap<T>();
+ this.data = new TIntObjectHashMap<>();
}
/**
@@ -67,7 +67,7 @@ public class MapIntegerDBIDStore<T> implements WritableDataStore<T> {
* @param size Expected size
*/
public MapIntegerDBIDStore(int size) {
- this.data = new TIntObjectHashMap<T>(size);
+ this.data = new TIntObjectHashMap<>(size);
}
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapRecordStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapRecordStore.java
index 20778327..8c8c4bc9 100644
--- a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapRecordStore.java
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapRecordStore.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -76,7 +76,7 @@ public class MapRecordStore implements WritableRecordStore {
@Override
public <T> WritableDataStore<T> getStorage(int col, Class<? super T> datatype) {
// TODO: add type checking?
- return new StorageAccessor<T>(col);
+ return new StorageAccessor<>(col);
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapStore.java
index 9818afd2..c40e0a72 100644
--- a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapStore.java
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapStore.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -60,7 +60,7 @@ public class MapStore<T> implements WritableDataStore<T> {
*/
public MapStore() {
super();
- this.data = new HashMap<DBID, T>();
+ this.data = new HashMap<>();
}
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MemoryDataStoreFactory.java b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MemoryDataStoreFactory.java
index 06a80fd7..2a6cd1cb 100644
--- a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MemoryDataStoreFactory.java
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MemoryDataStoreFactory.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -65,10 +65,10 @@ public class MemoryDataStoreFactory implements DataStoreFactory {
if(ids instanceof DBIDRange) {
DBIDRange range = (DBIDRange) ids;
Object[] data = new Object[range.size()];
- return new ArrayStore<T>(data, range);
+ return new ArrayStore<>(data, range);
}
else {
- return new MapIntegerDBIDStore<T>(ids.size());
+ return new MapIntegerDBIDStore<>(ids.size());
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/package-info.java b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/package-info.java
index 6200bb46..5ea46015 100644
--- a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/package-info.java b/src/de/lmu/ifi/dbs/elki/database/datastore/package-info.java
index e5b4a259..f213019d 100644
--- a/src/de/lmu/ifi/dbs/elki/database/datastore/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/package-info.java
@@ -24,7 +24,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/ArrayDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/ArrayDBIDs.java
index 7e9c55c0..865e0bb7 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/ArrayDBIDs.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/ArrayDBIDs.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -47,7 +47,7 @@ public interface ArrayDBIDs extends DBIDs {
* @param index Position
* @param var Variable to assign the value to.
*/
- public void assign(int index, DBIDVar var);
+ public void assignVar(int index, DBIDVar var);
/**
* Iterable
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/ArrayModifiableDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/ArrayModifiableDBIDs.java
index ffac393b..3db40630 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/ArrayModifiableDBIDs.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/ArrayModifiableDBIDs.java
@@ -6,7 +6,7 @@ import java.util.Comparator;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/ArrayStaticDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/ArrayStaticDBIDs.java
index a14eac0c..47cf295f 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/ArrayStaticDBIDs.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/ArrayStaticDBIDs.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/DBID.java b/src/de/lmu/ifi/dbs/elki/database/ids/DBID.java
index 5abf4377..a773ee27 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/DBID.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/DBID.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDArrayIter.java b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDArrayIter.java
index fefe5ad1..ef1132b3 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDArrayIter.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDArrayIter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -22,7 +22,7 @@ package de.lmu.ifi.dbs.elki.database.ids;
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import de.lmu.ifi.dbs.elki.utilities.iterator.ArrayIter;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.iterator.ArrayIter;
/**
* Array iterators that can also go backwards and seek.
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDArrayMIter.java b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDArrayMIter.java
index 1de202a2..1aaefc8e 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDArrayMIter.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDArrayMIter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDFactory.java b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDFactory.java
index 646e6e4d..4c6472a7 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDFactory.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDFactory.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,6 +23,10 @@ package de.lmu.ifi.dbs.elki.database.ids;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNHeap;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.ids.integer.TrivialDBIDFactory;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.persistent.ByteBufferSerializer;
@@ -192,6 +196,27 @@ public interface DBIDFactory {
HashSetModifiableDBIDs newHashSet(DBIDs existing);
/**
+ * Create an appropriate heap for the distance function.
+ *
+ * This will use a double heap if appropriate.
+ *
+ * @param factory distance prototype
+ * @param k K value
+ * @param <D> distance type
+ * @return New heap of size k, appropriate for this distance type.
+ */
+ <D extends Distance<D>> KNNHeap<D> newHeap(D factory, int k);
+
+ /**
+ * Build a new heap from a given list.
+ *
+ * @param exist Existing result
+ * @param <D> Distance type
+ * @return New heap
+ */
+ <D extends Distance<D>> KNNHeap<D> newHeap(KNNList<D> exist);
+
+ /**
* Get a serializer for DBIDs.
*
* @return DBID serializer
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDIter.java b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDIter.java
index 268f4441..f051d51c 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDIter.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDIter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,7 +23,7 @@ package de.lmu.ifi.dbs.elki.database.ids;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import de.lmu.ifi.dbs.elki.utilities.iterator.Iter;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.iterator.Iter;
/**
* Iterator for DBIDs.
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDMIter.java b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDMIter.java
index 9f42c5a0..0fbed7e0 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDMIter.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDMIter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,7 +23,7 @@ package de.lmu.ifi.dbs.elki.database.ids;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import de.lmu.ifi.dbs.elki.utilities.iterator.MIter;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.iterator.MIter;
/**
* Modifiable DBID iterator.
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDPair.java b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDPair.java
index 8f03e279..bdbbe2da 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDPair.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDPair.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDRange.java b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDRange.java
index 8f7e428d..588cfe6a 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDRange.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDRange.java
@@ -6,7 +6,7 @@ import de.lmu.ifi.dbs.elki.database.datastore.DataStoreIDMap;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDRef.java b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDRef.java
index fce87c31..77cc621e 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDRef.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDRef.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDUtil.java b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDUtil.java
index 9cb4082a..78dba268 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDUtil.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDUtil.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,10 +25,17 @@ package de.lmu.ifi.dbs.elki.database.ids;
import java.util.Random;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNHeap;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
+import de.lmu.ifi.dbs.elki.database.ids.generic.DoubleDistanceKNNSubList;
+import de.lmu.ifi.dbs.elki.database.ids.generic.KNNSubList;
import de.lmu.ifi.dbs.elki.database.ids.generic.UnmodifiableArrayDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.generic.UnmodifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.integer.IntegerArrayDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.integer.IntegerDBIDs;
-import de.lmu.ifi.dbs.elki.database.ids.integer.TroveArrayDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.integer.UnmodifiableIntegerArrayDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.integer.UnmodifiableIntegerDBIDs;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
@@ -319,9 +326,33 @@ public final class DBIDUtil {
* @return size
*/
public static int intersectionSize(DBIDs first, DBIDs second) {
- if (first.size() > second.size()) {
- return intersectionSize(second, first);
+ // If exactly one is a Set, use it as second parameter.
+ if (second instanceof SetDBIDs) {
+ if (!(first instanceof SetDBIDs)) {
+ return internalIntersectionSize(first, second);
+ }
+ } else {
+ if (first instanceof SetDBIDs) {
+ return internalIntersectionSize(second, first);
+ }
}
+ // Both are the same type: both set or both non set.
+ // Smaller goes first.
+ if (first.size() <= second.size()) {
+ return internalIntersectionSize(first, second);
+ } else {
+ return internalIntersectionSize(second, first);
+ }
+ }
+
+ /**
+ * Compute the set intersection size of two sets.
+ *
+ * @param first First set
+ * @param second Second set
+ * @return size
+ */
+ private static int internalIntersectionSize(DBIDs first, DBIDs second) {
int c = 0;
for (DBIDIter it = first.iter(); it.valid(); it.advance()) {
if (second.contains(it)) {
@@ -398,8 +429,8 @@ public final class DBIDUtil {
if (existing instanceof StaticDBIDs) {
return (StaticDBIDs) existing;
}
- if (existing instanceof TroveArrayDBIDs) {
- return new UnmodifiableIntegerArrayDBIDs((TroveArrayDBIDs) existing);
+ if (existing instanceof IntegerArrayDBIDs) {
+ return new UnmodifiableIntegerArrayDBIDs((IntegerArrayDBIDs) existing);
}
if (existing instanceof IntegerDBIDs) {
return new UnmodifiableIntegerDBIDs((IntegerDBIDs) existing);
@@ -504,6 +535,31 @@ public final class DBIDUtil {
}
/**
+ * Create an appropriate heap for the distance type.
+ *
+ * This will use a double heap if appropriate.
+ *
+ * @param distancetype distance prototype
+ * @param k K value
+ * @param <D> distance type
+ * @return New heap of size k, appropriate for this distance type.
+ */
+ public static <D extends Distance<D>> KNNHeap<D> newHeap(D distancetype, int k) {
+ return DBIDFactory.FACTORY.newHeap(distancetype, k);
+ }
+
+ /**
+ * Build a new heap from a given list.
+ *
+ * @param exist Existing result
+ * @param <D> Distance type
+ * @return New heap
+ */
+ public static <D extends Distance<D>> KNNHeap<D> newHeap(KNNList<D> exist) {
+ return DBIDFactory.FACTORY.newHeap(exist);
+ }
+
+ /**
* Produce a random sample of the given DBIDs.
*
* @param source Original DBIDs
@@ -614,4 +670,23 @@ public final class DBIDUtil {
return sample;
}
}
+
+ /**
+ * Get a subset of the KNN result.
+ *
+ * @param list Existing list
+ * @param k k
+ * @param <D> distance type
+ * @return Subset
+ */
+ @SuppressWarnings("unchecked")
+ public static <D extends Distance<D>> KNNList<D> subList(KNNList<D> list, int k) {
+ if (k >= list.size()) {
+ return list;
+ }
+ if (list instanceof DoubleDistanceKNNList) {
+ return (KNNList<D>) new DoubleDistanceKNNSubList((DoubleDistanceKNNList) list, k);
+ }
+ return new KNNSubList<>(list, k);
+ }
}
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDVar.java b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDVar.java
index b66ae5f5..94480fe9 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDVar.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDVar.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDs.java
index 0b9db136..2bf2b28d 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDs.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDs.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/DoubleDBIDPair.java b/src/de/lmu/ifi/dbs/elki/database/ids/DoubleDBIDPair.java
index 06210076..970092b0 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/DoubleDBIDPair.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/DoubleDBIDPair.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/EmptyDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/EmptyDBIDs.java
index 995f917c..8a7b2e28 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/EmptyDBIDs.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/EmptyDBIDs.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -68,7 +68,7 @@ public class EmptyDBIDs implements ArrayStaticDBIDs, SetDBIDs {
}
@Override
- public void assign(int index, DBIDVar var) {
+ public void assignVar(int index, DBIDVar var) {
throw new ArrayIndexOutOfBoundsException();
}
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/HashSetDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/HashSetDBIDs.java
index 5ff0bc97..cabe9898 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/HashSetDBIDs.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/HashSetDBIDs.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/HashSetModifiableDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/HashSetModifiableDBIDs.java
index efb39bc8..6a57f5f0 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/HashSetModifiableDBIDs.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/HashSetModifiableDBIDs.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/ModifiableDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/ModifiableDBIDs.java
index 547f3297..1cd8c4e7 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/ModifiableDBIDs.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/ModifiableDBIDs.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/SetDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/SetDBIDs.java
index 7fd28326..3a92593e 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/SetDBIDs.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/SetDBIDs.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/StaticDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/StaticDBIDs.java
index ce616da3..2ba30d4b 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/StaticDBIDs.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/StaticDBIDs.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/DistanceDBIDResult.java b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DistanceDBIDList.java
index 2d7d68de..360dda12 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/DistanceDBIDResult.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DistanceDBIDList.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.distance.distanceresultlist;
+package de.lmu.ifi.dbs.elki.database.ids.distance;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,7 +24,6 @@ package de.lmu.ifi.dbs.elki.distance.distanceresultlist;
*/
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
-import de.lmu.ifi.dbs.elki.database.ids.DistanceDBIDPair;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
/**
@@ -57,18 +56,18 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
* @apiviz.landmark
*
* @apiviz.composedOf DistanceDBIDPair
- * @apiviz.has DistanceDBIDResultIter
+ * @apiviz.has DistanceDBIDListIter
*
* @param <D> Distance type
*/
-public interface DistanceDBIDResult<D extends Distance<D>> extends DBIDs {
+public interface DistanceDBIDList<D extends Distance<D>> extends DBIDs {
/**
* Size of list.
*
* @return Size
*/
@Override
- public int size();
+ int size();
/**
* Access a single pair.
@@ -76,7 +75,7 @@ public interface DistanceDBIDResult<D extends Distance<D>> extends DBIDs {
* @param off Offset
* @return Pair
*/
- public DistanceDBIDPair<D> get(int off);
+ DistanceDBIDPair<D> get(int off);
/**
* Get an iterator
@@ -84,5 +83,5 @@ public interface DistanceDBIDResult<D extends Distance<D>> extends DBIDs {
* @return New iterator
*/
@Override
- public DistanceDBIDResultIter<D> iter();
-} \ No newline at end of file
+ DistanceDBIDListIter<D> iter();
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/DistanceDBIDResultIter.java b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DistanceDBIDListIter.java
index d84e5d18..914f3676 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/DistanceDBIDResultIter.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DistanceDBIDListIter.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.distance.distanceresultlist;
+package de.lmu.ifi.dbs.elki.database.ids.distance;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,8 +23,7 @@ package de.lmu.ifi.dbs.elki.distance.distanceresultlist;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
-import de.lmu.ifi.dbs.elki.database.ids.DistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDArrayIter;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
/**
@@ -38,9 +37,8 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
* @apiviz.landmark
*
* @apiviz.has DistanceDBIDPair - - iterator for
- * @apiviz.has de.lmu.ifi.dbs.elki.database.ids.DBID - - iterator for
*/
-public interface DistanceDBIDResultIter<D extends Distance<D>> extends DBIDIter {
+public interface DistanceDBIDListIter<D extends Distance<D>> extends DBIDArrayIter {
/**
* Get the distance
*
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/DistanceDBIDPair.java b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DistanceDBIDPair.java
index 01a1f407..a9d879d9 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/DistanceDBIDPair.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DistanceDBIDPair.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.database.ids;
+package de.lmu.ifi.dbs.elki.database.ids.distance;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,6 +23,7 @@ package de.lmu.ifi.dbs.elki.database.ids;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
/**
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceDBIDList.java b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceDBIDList.java
new file mode 100644
index 00000000..85182313
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceDBIDList.java
@@ -0,0 +1,39 @@
+package de.lmu.ifi.dbs.elki.database.ids.distance;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+
+/**
+ * An object containing Double-DBID-Pairs.
+ *
+ * @author Erich Schubert
+ */
+public interface DoubleDistanceDBIDList extends DistanceDBIDList<DoubleDistance> {
+ @Override
+ DoubleDistanceDBIDListIter iter();
+
+ @Override
+ DoubleDistanceDBIDPair get(int off);
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/DoubleDistanceDBIDResultIter.java b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceDBIDListIter.java
index d022fe4c..68b2de1e 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/DoubleDistanceDBIDResultIter.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceDBIDListIter.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.distance.distanceresultlist;
+package de.lmu.ifi.dbs.elki.database.ids.distance;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,7 +23,6 @@ package de.lmu.ifi.dbs.elki.distance.distanceresultlist;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import de.lmu.ifi.dbs.elki.database.ids.DoubleDistanceDBIDPair;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
/**
@@ -31,7 +30,7 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
*
* @author Erich Schubert
*/
-public interface DoubleDistanceDBIDResultIter extends DistanceDBIDResultIter<DoubleDistance> {
+public interface DoubleDistanceDBIDListIter extends DistanceDBIDListIter<DoubleDistance> {
/**
* Get the distance
*
@@ -58,4 +57,4 @@ public interface DoubleDistanceDBIDResultIter extends DistanceDBIDResultIter<Dou
@Deprecated
@Override
public DoubleDistance getDistance();
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/DoubleDistanceDBIDPair.java b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceDBIDPair.java
index 72a9cfef..5286029b 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/DoubleDistanceDBIDPair.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceDBIDPair.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.database.ids;
+package de.lmu.ifi.dbs.elki.database.ids.distance;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,6 +23,7 @@ package de.lmu.ifi.dbs.elki.database.ids;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
/**
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/DoubleDistanceDBIDList.java b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceDBIDPairList.java
index 9ff22b74..f9bfc20a 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/DoubleDistanceDBIDList.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceDBIDPairList.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.distance.distanceresultlist;
+package de.lmu.ifi.dbs.elki.database.ids.distance;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -30,7 +30,7 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDFactory;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
-import de.lmu.ifi.dbs.elki.database.ids.DoubleDistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultUtil;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
/**
@@ -39,9 +39,9 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
* @author Erich Schubert
*
* @apiviz.composedOf DoubleDistanceDBIDPair
- * @apiviz.has DoubleDistanceDBIDResultIter
+ * @apiviz.has DoubleDistanceDBIDListIter
*/
-public class DoubleDistanceDBIDList implements ModifiableDistanceDBIDResult<DoubleDistance> {
+public class DoubleDistanceDBIDPairList implements ModifiableDoubleDistanceDBIDList {
/**
* Actual storage.
*/
@@ -50,9 +50,9 @@ public class DoubleDistanceDBIDList implements ModifiableDistanceDBIDResult<Doub
/**
* Constructor.
*/
- public DoubleDistanceDBIDList() {
+ public DoubleDistanceDBIDPairList() {
super();
- storage = new ArrayList<DoubleDistanceDBIDPair>();
+ storage = new ArrayList<>();
}
/**
@@ -60,9 +60,9 @@ public class DoubleDistanceDBIDList implements ModifiableDistanceDBIDResult<Doub
*
* @param initialCapacity Capacity
*/
- public DoubleDistanceDBIDList(int initialCapacity) {
+ public DoubleDistanceDBIDPairList(int initialCapacity) {
super();
- storage = new ArrayList<DoubleDistanceDBIDPair>(initialCapacity);
+ storage = new ArrayList<>(initialCapacity);
}
/**
@@ -85,6 +85,7 @@ public class DoubleDistanceDBIDList implements ModifiableDistanceDBIDResult<Doub
* @param dist Distance
* @param id ID
*/
+ @Override
public void add(double dist, DBIDRef id) {
storage.add(DBIDFactory.FACTORY.newDistancePair(dist, id));
}
@@ -94,6 +95,7 @@ public class DoubleDistanceDBIDList implements ModifiableDistanceDBIDResult<Doub
*
* @param pair Pair to add
*/
+ @Override
public void add(DoubleDistanceDBIDPair pair) {
storage.add(pair);
}
@@ -114,8 +116,8 @@ public class DoubleDistanceDBIDList implements ModifiableDistanceDBIDResult<Doub
}
@Override
- public DoubleDistanceDBIDResultIter iter() {
- return new Iter();
+ public DoubleDistanceDBIDListIter iter() {
+ return new Itr();
}
@Override
@@ -145,7 +147,7 @@ public class DoubleDistanceDBIDList implements ModifiableDistanceDBIDResult<Doub
*
* @apiviz.exclude
*/
- protected class Iter implements DoubleDistanceDBIDResultIter {
+ protected class Itr implements DoubleDistanceDBIDListIter {
/**
* Iterator position.
*/
@@ -186,5 +188,25 @@ public class DoubleDistanceDBIDList implements ModifiableDistanceDBIDResult<Doub
public String toString() {
return valid() ? getDistancePair().toString() : "null";
}
+
+ @Override
+ public int getOffset() {
+ return pos;
+ }
+
+ @Override
+ public void advance(int count) {
+ pos += count;
+ }
+
+ @Override
+ public void retract() {
+ --pos;
+ }
+
+ @Override
+ public void seek(int off) {
+ pos = off;
+ }
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceKNNHeap.java b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceKNNHeap.java
new file mode 100644
index 00000000..1e75f120
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceKNNHeap.java
@@ -0,0 +1,100 @@
+package de.lmu.ifi.dbs.elki.database.ids.distance;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+
+/**
+ * Interface for kNN heaps storing double distances and DBIDs.
+ *
+ * @author Erich Schubert
+ */
+public interface DoubleDistanceKNNHeap extends KNNHeap<DoubleDistance> {
+ /**
+ * Add a distance-id pair to the heap unless the distance is too large.
+ *
+ * Compared to the super.add() method, this often saves the pair construction.
+ *
+ * @param distance Distance value
+ * @param id ID number
+ */
+ void add(double distance, DBIDRef id);
+
+ /**
+ * Add a distance-id pair to the heap unless the distance is too large.
+ *
+ * Compared to the super.add() method, this often saves the pair construction.
+ *
+ * @param distance Distance value
+ * @param id ID number
+ */
+ @Deprecated
+ void add(Double distance, DBIDRef id);
+
+ /**
+ * Add a distance-id pair to the heap unless the distance is too large.
+ *
+ * Use for existing pairs.
+ *
+ * @param e Existing distance pair
+ */
+ void add(DoubleDistanceDBIDPair e);
+
+ /**
+ * {@inheritDoc}
+ *
+ * @deprecated if you know your distances are double-valued, you should be
+ * using the primitive type.
+ */
+ @Override
+ @Deprecated
+ void add(DoubleDistance dist, DBIDRef id);
+
+ /**
+ * Get the distance to the k nearest neighbor, or maxdist otherwise.
+ *
+ * @return Maximum distance
+ */
+ double doubleKNNDistance();
+
+ /**
+ * {@inheritDoc}
+ *
+ * @deprecated if you know your distances are double-valued, you should be
+ * using the primitive type.
+ */
+ @Override
+ @Deprecated
+ DoubleDistance getKNNDistance();
+
+ @Override
+ DoubleDistanceDBIDPair poll();
+
+ @Override
+ DoubleDistanceDBIDPair peek();
+
+ @Override
+ DoubleDistanceKNNList toKNNList();
+}
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceKNNList.java b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceKNNList.java
new file mode 100644
index 00000000..c54110ab
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceKNNList.java
@@ -0,0 +1,55 @@
+package de.lmu.ifi.dbs.elki.database.ids.distance;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+
+/**
+ * Double-valued KNN result.
+ *
+ * @author Erich Schubert
+ */
+public interface DoubleDistanceKNNList extends KNNList<DoubleDistance> {
+ /**
+ * {@inheritDoc}
+ *
+ * @deprecated use doubleKNNDistance()!
+ */
+ @Override
+ @Deprecated
+ DoubleDistance getKNNDistance();
+
+ /**
+ * Get the kNN distance as double value.
+ *
+ * @return Distance
+ */
+ double doubleKNNDistance();
+
+ @Override
+ DoubleDistanceDBIDListIter iter();
+
+ @Override
+ DoubleDistanceDBIDPair get(int off);
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/KNNHeap.java b/src/de/lmu/ifi/dbs/elki/database/ids/distance/KNNHeap.java
index cdcb7d98..c02071e7 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/KNNHeap.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/distance/KNNHeap.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.distance.distanceresultlist;
+package de.lmu.ifi.dbs.elki.database.ids.distance;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,31 +24,29 @@ package de.lmu.ifi.dbs.elki.distance.distanceresultlist;
*/
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
-import de.lmu.ifi.dbs.elki.database.ids.DistanceDBIDPair;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
/**
* Interface for kNN heaps.
*
- * To instantiate, use: {@link KNNUtil#newHeap}!
+ * To instantiate, use: {@link de.lmu.ifi.dbs.elki.database.ids.DBIDUtil#newHeap}!
*
* @author Erich Schubert
*
* @apiviz.landmark
*
- * @apiviz.uses GenericKNNList - - «serializes to»
- * @apiviz.uses DoubleDistanceKNNList - - «serializes to»
+ * @apiviz.uses KNNList - - «serializes to»
* @apiviz.composedOf DistanceDBIDPair
*
* @param <D> Distance function
*/
public interface KNNHeap<D extends Distance<D>> {
/**
- * Serialize to a {@link GenericKNNList}. This empties the heap!
+ * Serialize to a {@link KNNList}. This empties the heap!
*
* @return KNNList with the heaps contents.
*/
- KNNResult<D> toKNNList();
+ KNNList<D> toKNNList();
/**
* Get the K parameter ("maxsize" internally).
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/KNNResult.java b/src/de/lmu/ifi/dbs/elki/database/ids/distance/KNNList.java
index 785e5b8a..61b75ba8 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/KNNResult.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/distance/KNNList.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.distance.distanceresultlist;
+package de.lmu.ifi.dbs.elki.database.ids.distance;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,7 +23,6 @@ package de.lmu.ifi.dbs.elki.distance.distanceresultlist;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import de.lmu.ifi.dbs.elki.database.ids.DistanceDBIDPair;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
/**
@@ -56,11 +55,10 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
* @apiviz.landmark
*
* @apiviz.composedOf DistanceDBIDPair
- * @apiviz.has DistanceDBIDResultIter
*
* @param <D> Distance type
*/
-public interface KNNResult<D extends Distance<D>> extends DistanceDBIDResult<D> {
+public interface KNNList<D extends Distance<D>> extends DistanceDBIDList<D> {
/**
* Size
*/
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/ModifiableDistanceDBIDResult.java b/src/de/lmu/ifi/dbs/elki/database/ids/distance/ModifiableDistanceDBIDList.java
index 52889652..afb15f93 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/ModifiableDistanceDBIDResult.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/distance/ModifiableDistanceDBIDList.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.distance.distanceresultlist;
+package de.lmu.ifi.dbs.elki.database.ids.distance;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -32,7 +32,7 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
*
* @param <D> Distance type
*/
-public interface ModifiableDistanceDBIDResult<D extends Distance<D>> extends DistanceDBIDResult<D> {
+public interface ModifiableDistanceDBIDList<D extends Distance<D>> extends DistanceDBIDList<D> {
/**
* Add an object to this result.
*
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/distance/ModifiableDoubleDistanceDBIDList.java b/src/de/lmu/ifi/dbs/elki/database/ids/distance/ModifiableDoubleDistanceDBIDList.java
new file mode 100644
index 00000000..12cdaf69
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/distance/ModifiableDoubleDistanceDBIDList.java
@@ -0,0 +1,63 @@
+package de.lmu.ifi.dbs.elki.database.ids.distance;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.ModifiableDistanceDBIDList;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+
+/**
+ * An object containing Double-DBID-Pairs.
+ *
+ * @author Erich Schubert
+ */
+public interface ModifiableDoubleDistanceDBIDList extends DoubleDistanceDBIDList, ModifiableDistanceDBIDList<DoubleDistance> {
+ /**
+ * Add an element.
+ *
+ * @deprecated Pass a double value instead.
+ *
+ * @param dist Distance
+ * @param id ID
+ */
+ @Override
+ @Deprecated
+ void add(DoubleDistance dist, DBIDRef id);
+
+ /**
+ * Add an element.
+ *
+ * @param dist Distance
+ * @param id ID
+ */
+ void add(double dist, DBIDRef id);
+
+ /**
+ * Add an element.
+ *
+ * @param pair Pair to add
+ */
+ void add(DoubleDistanceDBIDPair pair);
+}
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/distance/package-info.java b/src/de/lmu/ifi/dbs/elki/database/ids/distance/package-info.java
new file mode 100644
index 00000000..7fefbedd
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/distance/package-info.java
@@ -0,0 +1,26 @@
+/**
+ * Distance-DBID pairs, lists and heaps.
+ */
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package de.lmu.ifi.dbs.elki.database.ids.distance;
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/AbstractKNNHeap.java b/src/de/lmu/ifi/dbs/elki/database/ids/generic/AbstractKNNHeap.java
index 30df7c16..2c2e60b0 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/AbstractKNNHeap.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/generic/AbstractKNNHeap.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.distance.distanceresultlist;
+package de.lmu.ifi.dbs.elki.database.ids.generic;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,11 +23,11 @@ package de.lmu.ifi.dbs.elki.distance.distanceresultlist;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.Comparator;
-import de.lmu.ifi.dbs.elki.database.ids.DistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNHeap;
+import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultUtil;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.TiedTopBoundedHeap;
/**
@@ -38,12 +38,7 @@ import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.TiedTopBoundedHeap;
* @param <P> pair type
* @param <D> distance type
*/
-abstract public class AbstractKNNHeap<P extends DistanceDBIDPair<D>, D extends Distance<D>> implements KNNHeap<D> {
- /**
- * Static comparator.
- */
- public static final Comparator<? super DistanceDBIDPair<?>> COMPARATOR = new Comp();
-
+abstract class AbstractKNNHeap<P extends DistanceDBIDPair<D>, D extends Distance<D>> implements KNNHeap<D> {
/**
* The actual heap.
*/
@@ -56,7 +51,7 @@ abstract public class AbstractKNNHeap<P extends DistanceDBIDPair<D>, D extends D
*/
public AbstractKNNHeap(int k) {
super();
- heap = new TiedTopBoundedHeap<P>(k, COMPARATOR);
+ heap = new TiedTopBoundedHeap<>(k, DistanceDBIDResultUtil.BY_REVERSE_DISTANCE);
}
/**
@@ -95,19 +90,4 @@ abstract public class AbstractKNNHeap<P extends DistanceDBIDPair<D>, D extends D
public P poll() {
return heap.poll();
}
-
- /**
- * Comparator to use.
- *
- * @author Erich Schubert
- *
- * @apiviz.exclude
- */
- protected static class Comp implements Comparator<DistanceDBIDPair<?>> {
- @SuppressWarnings("unchecked")
- @Override
- public int compare(DistanceDBIDPair<?> o1, DistanceDBIDPair<?> o2) {
- return -((DistanceDBIDPair<DoubleDistance>)o1).compareByDistance((DistanceDBIDPair<DoubleDistance>)o2);
- }
- }
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/generic/DBIDIterAdapter.java b/src/de/lmu/ifi/dbs/elki/database/ids/generic/DBIDIterAdapter.java
index 124d1b28..85fdcffd 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/generic/DBIDIterAdapter.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/generic/DBIDIterAdapter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.generic;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/GenericKNNHeap.java b/src/de/lmu/ifi/dbs/elki/database/ids/generic/DistanceDBIDPairKNNHeap.java
index c13887be..88459077 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/GenericKNNHeap.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/generic/DistanceDBIDPairKNNHeap.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.distance.distanceresultlist;
+package de.lmu.ifi.dbs.elki.database.ids.generic;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,21 +25,21 @@ package de.lmu.ifi.dbs.elki.distance.distanceresultlist;
import de.lmu.ifi.dbs.elki.database.ids.DBIDFactory;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
-import de.lmu.ifi.dbs.elki.database.ids.DistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDPair;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
/**
- * Heap for collecting kNN candiates with arbitrary distance types.
+ * Heap for collecting kNN candidates with arbitrary distance types.
*
- * For double distances, see {@link DoubleDistanceKNNHeap}
+ * For double distances, see {@link DoubleDistanceDBIDPairKNNHeap}
*
- * <b>To instantiate, use {@link KNNUtil#newHeap} instead!</b>
+ * <b>To instantiate, use {@link de.lmu.ifi.dbs.elki.database.ids.DBIDUtil#newHeap} instead!</b>
*
* @author Erich Schubert
*
* @param <D> Distance type
*/
-class GenericKNNHeap<D extends Distance<D>> extends AbstractKNNHeap<DistanceDBIDPair<D>, D> {
+public class DistanceDBIDPairKNNHeap<D extends Distance<D>> extends AbstractKNNHeap<DistanceDBIDPair<D>, D> {
/**
* Cached distance to k nearest neighbor (to avoid going through {@link #peek}
* each time).
@@ -49,22 +49,22 @@ class GenericKNNHeap<D extends Distance<D>> extends AbstractKNNHeap<DistanceDBID
/**
* Constructor.
*
- * <b>To instantiate, use {@link KNNUtil#newHeap} instead!</b>
+ * <b>To instantiate, use {@link de.lmu.ifi.dbs.elki.database.ids.DBIDUtil#newHeap} instead!</b>
*
* @param k Heap size
*/
- protected GenericKNNHeap(int k) {
+ public DistanceDBIDPairKNNHeap(int k) {
super(k);
}
/**
- * Serialize to a {@link GenericKNNList}. This empties the heap!
+ * Serialize to a {@link DistanceDBIDPairKNNList}. This empties the heap!
*
* @return KNNList with the heaps contents.
*/
@Override
- public GenericKNNList<D> toKNNList() {
- return new GenericKNNList<D>(this);
+ public DistanceDBIDPairKNNList<D> toKNNList() {
+ return new DistanceDBIDPairKNNList<>(this);
}
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/GenericKNNList.java b/src/de/lmu/ifi/dbs/elki/database/ids/generic/DistanceDBIDPairKNNList.java
index 71217b23..bc5392d6 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/GenericKNNList.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/generic/DistanceDBIDPairKNNList.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.distance.distanceresultlist;
+package de.lmu.ifi.dbs.elki.database.ids.generic;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,7 +26,10 @@ package de.lmu.ifi.dbs.elki.distance.distanceresultlist;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
-import de.lmu.ifi.dbs.elki.database.ids.DistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNHeap;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.Heap;
@@ -37,7 +40,7 @@ import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.Heap;
*
* @param <D> Distance type
*/
-public class GenericKNNList<D extends Distance<D>> implements KNNResult<D> {
+public class DistanceDBIDPairKNNList<D extends Distance<D>> implements KNNList<D> {
/**
* The value of k this was materialized for.
*/
@@ -54,14 +57,13 @@ public class GenericKNNList<D extends Distance<D>> implements KNNResult<D> {
*
* @param heap Calling heap
*/
- protected GenericKNNList(KNNHeap<D> heap) {
+ protected DistanceDBIDPairKNNList(KNNHeap<D> heap) {
super();
this.data = new Object[heap.size()];
this.k = heap.getK();
- assert (heap.size() >= this.k) : "Heap doesn't contain enough objects!";
// Get sorted data from heap; but in reverse.
int i = heap.size();
- while(heap.size() > 0) {
+ while (heap.size() > 0) {
i--;
assert (i >= 0);
data[i] = heap.poll();
@@ -76,14 +78,14 @@ public class GenericKNNList<D extends Distance<D>> implements KNNResult<D> {
* @param heap Calling heap
* @param k K value
*/
- public GenericKNNList(Heap<? extends DistanceDBIDPair<D>> heap, int k) {
+ public DistanceDBIDPairKNNList(Heap<? extends DistanceDBIDPair<D>> heap, int k) {
super();
this.data = new Object[heap.size()];
this.k = k;
assert (heap.size() >= this.k) : "Heap doesn't contain enough objects!";
// Get sorted data from heap; but in reverse.
int i = heap.size();
- while(!heap.isEmpty()) {
+ while (!heap.isEmpty()) {
i--;
assert (i >= 0);
data[i] = heap.poll();
@@ -106,10 +108,10 @@ public class GenericKNNList<D extends Distance<D>> implements KNNResult<D> {
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append("kNNList[");
- for(DistanceDBIDResultIter<D> iter = this.iter(); iter.valid();) {
+ for (DistanceDBIDListIter<D> iter = this.iter(); iter.valid();) {
buf.append(iter.getDistance()).append(':').append(DBIDUtil.toString(iter));
iter.advance();
- if(iter.valid()) {
+ if (iter.valid()) {
buf.append(',');
}
}
@@ -124,7 +126,7 @@ public class GenericKNNList<D extends Distance<D>> implements KNNResult<D> {
}
@Override
- public DistanceDBIDResultIter<D> iter() {
+ public DistanceDBIDListIter<D> iter() {
return new Itr();
}
@@ -135,8 +137,8 @@ public class GenericKNNList<D extends Distance<D>> implements KNNResult<D> {
@Override
public boolean contains(DBIDRef o) {
- for(DBIDIter iter = iter(); iter.valid(); iter.advance()) {
- if(DBIDUtil.equal(iter, o)) {
+ for (DBIDIter iter = iter(); iter.valid(); iter.advance()) {
+ if (DBIDUtil.equal(iter, o)) {
return true;
}
}
@@ -155,7 +157,7 @@ public class GenericKNNList<D extends Distance<D>> implements KNNResult<D> {
*
* @apiviz.exclude
*/
- private class Itr implements DistanceDBIDResultIter<D> {
+ private class Itr implements DistanceDBIDListIter<D> {
/**
* Cursor position.
*/
@@ -185,5 +187,25 @@ public class GenericKNNList<D extends Distance<D>> implements KNNResult<D> {
public DistanceDBIDPair<D> getDistancePair() {
return get(pos);
}
+
+ @Override
+ public int getOffset() {
+ return pos;
+ }
+
+ @Override
+ public void advance(int count) {
+ pos += count;
+ }
+
+ @Override
+ public void retract() {
+ --pos;
+ }
+
+ @Override
+ public void seek(int off) {
+ pos += off;
+ }
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/DoubleDistanceKNNHeap.java b/src/de/lmu/ifi/dbs/elki/database/ids/generic/DoubleDistanceDBIDPairKNNHeap.java
index 7faa407d..829bb00c 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/DoubleDistanceKNNHeap.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/generic/DoubleDistanceDBIDPairKNNHeap.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.distance.distanceresultlist;
+package de.lmu.ifi.dbs.elki.database.ids.generic;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,22 +27,23 @@ import java.util.Comparator;
import de.lmu.ifi.dbs.elki.database.ids.DBIDFactory;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
-import de.lmu.ifi.dbs.elki.database.ids.DoubleDistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNHeap;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
/**
* Heap for collecting double-valued KNN instances.
*
- * See also: {@link KNNUtil#newHeap}!
+ * See also: {@link de.lmu.ifi.dbs.elki.database.ids.DBIDUtil#newHeap}!
*
- * Experiments have shown that it can be much more performant to track the
+ * Experiments have shown that it <em>can</em> be much more performant to track the
* knndistance <em>outside</em> of the heap, and do comparisons on the stack:
* <blockquote>
*
* <pre>
* {@code
* double knndist = Double.POSITIVE_INFINITY;
- * DoubleDistanceKNNHeap heap = new DoubleDistanceKNNHeap(k);
+ * DoubleDistanceDBIDPairKNNHeap heap = new DoubleDistanceDBIDPairKNNHeap(k);
* for (DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
* double dist = computeDistance(iditer, ...);
* if (dist < knndist) {
@@ -62,7 +63,7 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
*
* @author Erich Schubert
*/
-public class DoubleDistanceKNNHeap extends AbstractKNNHeap<DoubleDistanceDBIDPair, DoubleDistance> {
+public class DoubleDistanceDBIDPairKNNHeap extends AbstractKNNHeap<DoubleDistanceDBIDPair, DoubleDistance> implements DoubleDistanceKNNHeap {
/**
* Comparator class.
*/
@@ -77,22 +78,22 @@ public class DoubleDistanceKNNHeap extends AbstractKNNHeap<DoubleDistanceDBIDPai
/**
* Constructor.
*
- * See also: {@link KNNUtil#newHeap}!
+ * See also: {@link de.lmu.ifi.dbs.elki.database.ids.DBIDUtil#newHeap}!
*
* @param k Heap size
*/
- public DoubleDistanceKNNHeap(int k) {
+ public DoubleDistanceDBIDPairKNNHeap(int k) {
super(k);
}
/**
- * Serialize to a {@link DoubleDistanceKNNList}. This empties the heap!
+ * Serialize to a {@link DoubleDistanceDBIDPairKNNList}. This empties the heap!
*
* @return KNNList with the heaps contents.
*/
@Override
- public DoubleDistanceKNNList toKNNList() {
- return new DoubleDistanceKNNList(this);
+ public DoubleDistanceDBIDPairKNNList toKNNList() {
+ return new DoubleDistanceDBIDPairKNNList(this);
}
/**
@@ -103,6 +104,7 @@ public class DoubleDistanceKNNHeap extends AbstractKNNHeap<DoubleDistanceDBIDPai
* @param distance Distance value
* @param id ID number
*/
+ @Override
public final void add(final double distance, final DBIDRef id) {
if (size() < getK() || knndistance >= distance) {
heap.add(DBIDFactory.FACTORY.newDistancePair(distance, id));
@@ -118,6 +120,8 @@ public class DoubleDistanceKNNHeap extends AbstractKNNHeap<DoubleDistanceDBIDPai
* @param distance Distance value
* @param id ID number
*/
+ @Override
+ @Deprecated
public final void add(final Double distance, final DBIDRef id) {
if (size() < getK() || knndistance >= distance) {
heap.add(DBIDFactory.FACTORY.newDistancePair(distance, id));
@@ -133,7 +137,7 @@ public class DoubleDistanceKNNHeap extends AbstractKNNHeap<DoubleDistanceDBIDPai
}
}
- // @Override
+ @Override
public void add(final DoubleDistanceDBIDPair e) {
if (size() < getK() || knndistance >= e.doubleDistance()) {
heap.add(e);
@@ -159,6 +163,7 @@ public class DoubleDistanceKNNHeap extends AbstractKNNHeap<DoubleDistanceDBIDPai
*
* @return Maximum distance
*/
+ @Override
public double doubleKNNDistance() {
return knndistance;
}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/DoubleDistanceKNNList.java b/src/de/lmu/ifi/dbs/elki/database/ids/generic/DoubleDistanceDBIDPairKNNList.java
index 656377c6..c72529ad 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/DoubleDistanceKNNList.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/generic/DoubleDistanceDBIDPairKNNList.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.distance.distanceresultlist;
+package de.lmu.ifi.dbs.elki.database.ids.generic;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,7 +29,10 @@ import java.util.Iterator;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
-import de.lmu.ifi.dbs.elki.database.ids.DoubleDistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNHeap;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.Heap;
@@ -39,9 +42,9 @@ import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.Heap;
* @author Erich Schubert
*
* @apiviz.composedOf DoubleDistanceDBIDPair
- * @apiviz.has DoubleDistanceDBIDResultIter
+ * @apiviz.has DoubleDistanceDBIDListIter
*/
-public class DoubleDistanceKNNList implements KNNResult<DoubleDistance> {
+public class DoubleDistanceDBIDPairKNNList implements DoubleDistanceKNNList {
/**
* The value of k this was materialized for.
*/
@@ -58,14 +61,14 @@ public class DoubleDistanceKNNList implements KNNResult<DoubleDistance> {
* @param col Existing collection
* @param k K parameter
*/
- public DoubleDistanceKNNList(Collection<DoubleDistanceDBIDPair> col, int k) {
+ public DoubleDistanceDBIDPairKNNList(Collection<DoubleDistanceDBIDPair> col, int k) {
super();
this.data = new DoubleDistanceDBIDPair[col.size()];
this.k = k;
assert (col.size() >= this.k) : "Collection doesn't contain enough objects!";
// Get sorted data from heap; but in reverse.
Iterator<DoubleDistanceDBIDPair> it = col.iterator();
- for(int i = 0; it.hasNext(); i++) {
+ for (int i = 0; it.hasNext(); i++) {
data[i] = it.next();
}
assert (data.length == 0 || data[0] != null);
@@ -77,14 +80,13 @@ public class DoubleDistanceKNNList implements KNNResult<DoubleDistance> {
*
* @param heap Calling heap
*/
- protected DoubleDistanceKNNList(DoubleDistanceKNNHeap heap) {
+ protected DoubleDistanceDBIDPairKNNList(DoubleDistanceDBIDPairKNNHeap heap) {
super();
this.data = new DoubleDistanceDBIDPair[heap.size()];
this.k = heap.getK();
- assert (heap.size() >= this.k) : "Heap doesn't contain enough objects!";
// Get sorted data from heap; but in reverse.
int i = heap.size();
- while(heap.size() > 0) {
+ while (heap.size() > 0) {
i--;
assert (i >= 0);
data[i] = heap.poll();
@@ -100,14 +102,14 @@ public class DoubleDistanceKNNList implements KNNResult<DoubleDistance> {
* @param heap Calling heap
* @param k Target number of neighbors (before ties)
*/
- public DoubleDistanceKNNList(Heap<DoubleDistanceDBIDPair> heap, int k) {
+ public DoubleDistanceDBIDPairKNNList(Heap<DoubleDistanceDBIDPair> heap, int k) {
super();
this.data = new DoubleDistanceDBIDPair[heap.size()];
this.k = k;
assert (heap.size() >= this.k) : "Heap doesn't contain enough objects!";
// Get sorted data from heap; but in reverse.
int i = heap.size();
- while(heap.size() > 0) {
+ while (heap.size() > 0) {
i--;
assert (i >= 0);
data[i] = heap.poll();
@@ -121,34 +123,31 @@ public class DoubleDistanceKNNList implements KNNResult<DoubleDistance> {
return k;
}
- /**
- * {@inheritDoc}
- *
- * @deprecated use doubleKNNDistance()!
- */
@Override
@Deprecated
public DoubleDistance getKNNDistance() {
- return get(getK() - 1).getDistance();
+ if (size() < k) {
+ return DoubleDistance.INFINITE_DISTANCE;
+ }
+ return get(k - 1).getDistance();
}
- /**
- * Get the kNN distance as double value.
- *
- * @return Distance
- */
+ @Override
public double doubleKNNDistance() {
- return get(getK() - 1).doubleDistance();
+ if (size() < k) {
+ return Double.POSITIVE_INFINITY;
+ }
+ return get(k - 1).doubleDistance();
}
@Override
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append("kNNList[");
- for(DoubleDistanceDBIDResultIter iter = this.iter(); iter.valid();) {
+ for (DoubleDistanceDBIDListIter iter = this.iter(); iter.valid();) {
buf.append(iter.doubleDistance()).append(':').append(DBIDUtil.toString(iter));
iter.advance();
- if(iter.valid()) {
+ if (iter.valid()) {
buf.append(',');
}
}
@@ -162,7 +161,7 @@ public class DoubleDistanceKNNList implements KNNResult<DoubleDistance> {
}
@Override
- public DoubleDistanceDBIDResultIter iter() {
+ public DoubleDistanceDBIDListIter iter() {
return new Itr();
}
@@ -173,8 +172,8 @@ public class DoubleDistanceKNNList implements KNNResult<DoubleDistance> {
@Override
public boolean contains(DBIDRef o) {
- for(DBIDIter iter = iter(); iter.valid(); iter.advance()) {
- if(DBIDUtil.equal(iter, o)) {
+ for (DBIDIter iter = iter(); iter.valid(); iter.advance()) {
+ if (DBIDUtil.equal(iter, o)) {
return true;
}
}
@@ -193,7 +192,7 @@ public class DoubleDistanceKNNList implements KNNResult<DoubleDistance> {
*
* @apiviz.exclude
*/
- private class Itr implements DoubleDistanceDBIDResultIter {
+ private class Itr implements DoubleDistanceDBIDListIter {
/**
* Cursor position.
*/
@@ -216,7 +215,7 @@ public class DoubleDistanceKNNList implements KNNResult<DoubleDistance> {
/**
* {@inheritDoc}
- *
+ *
* @deprecated use {@link #doubleDistance}!
*/
@Override
@@ -234,5 +233,25 @@ public class DoubleDistanceKNNList implements KNNResult<DoubleDistance> {
public DoubleDistanceDBIDPair getDistancePair() {
return get(pos);
}
+
+ @Override
+ public int getOffset() {
+ return pos;
+ }
+
+ @Override
+ public void advance(int count) {
+ pos += count;
+ }
+
+ @Override
+ public void retract() {
+ --pos;
+ }
+
+ @Override
+ public void seek(int off) {
+ pos = off;
+ }
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/generic/DoubleDistanceKNNSubList.java b/src/de/lmu/ifi/dbs/elki/database/ids/generic/DoubleDistanceKNNSubList.java
new file mode 100644
index 00000000..c2854a54
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/generic/DoubleDistanceKNNSubList.java
@@ -0,0 +1,190 @@
+package de.lmu.ifi.dbs.elki.database.ids.generic;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNList;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+
+/**
+ * Sublist of an existing result to contain only the first k elements.
+ *
+ * TOOD: can be optimized slightly better.
+ *
+ * @author Erich Schubert
+ */
+public class DoubleDistanceKNNSubList implements DoubleDistanceKNNList {
+ /**
+ * Parameter k.
+ */
+ private final int k;
+
+ /**
+ * Actual size, including ties.
+ */
+ private final int size;
+
+ /**
+ * Wrapped inner result.
+ */
+ private final DoubleDistanceKNNList inner;
+
+ /**
+ * Constructor.
+ *
+ * @param inner Inner instance
+ * @param k k value
+ */
+ public DoubleDistanceKNNSubList(DoubleDistanceKNNList inner, int k) {
+ this.inner = inner;
+ this.k = k;
+ // Compute list size
+ {
+ DoubleDistanceDBIDPair dist = inner.get(k);
+ int i = k;
+ while (i + 1 < inner.size()) {
+ if (dist.compareByDistance(inner.get(i + 1)) < 0) {
+ break;
+ }
+ i++;
+ }
+ size = i;
+ }
+ }
+
+ @Override
+ public int getK() {
+ return k;
+ }
+
+ @Override
+ public DoubleDistanceDBIDPair get(int index) {
+ assert (index < size) : "Access beyond design size of list.";
+ return inner.get(index);
+ }
+
+ @Override
+ @Deprecated
+ public DoubleDistance getKNNDistance() {
+ return inner.get(k).getDistance();
+ }
+
+ @Override
+ public double doubleKNNDistance() {
+ return inner.get(k).doubleDistance();
+ }
+
+ @Override
+ public DoubleDistanceDBIDListIter iter() {
+ return new Itr();
+ }
+
+ @Override
+ public boolean contains(DBIDRef o) {
+ for (DBIDIter iter = iter(); iter.valid(); iter.advance()) {
+ if (DBIDUtil.equal(iter, o)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return size == 0;
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ /**
+ * Iterator for the sublist.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ private class Itr implements DoubleDistanceDBIDListIter {
+ /**
+ * Current position.
+ */
+ private int pos = 0;
+
+ @Override
+ public boolean valid() {
+ return pos < size;
+ }
+
+ @Override
+ public void advance() {
+ pos++;
+ }
+
+ @Override
+ @Deprecated
+ public DoubleDistance getDistance() {
+ return inner.get(pos).getDistance();
+ }
+
+ @Override
+ public double doubleDistance() {
+ return inner.get(pos).doubleDistance();
+ }
+
+ @Override
+ public DoubleDistanceDBIDPair getDistancePair() {
+ return inner.get(pos);
+ }
+
+ @Override
+ public int internalGetIndex() {
+ return inner.get(pos).internalGetIndex();
+ }
+
+ @Override
+ public int getOffset() {
+ return pos;
+ }
+
+ @Override
+ public void advance(int count) {
+ pos += count;
+ }
+
+ @Override
+ public void retract() {
+ --pos;
+ }
+
+ @Override
+ public void seek(int off) {
+ pos = off;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/GenericDistanceDBIDList.java b/src/de/lmu/ifi/dbs/elki/database/ids/generic/GenericDistanceDBIDList.java
index 05e4e687..9b6c188b 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/GenericDistanceDBIDList.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/generic/GenericDistanceDBIDList.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.distance.distanceresultlist;
+package de.lmu.ifi.dbs.elki.database.ids.generic;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,7 +29,10 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDFactory;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
-import de.lmu.ifi.dbs.elki.database.ids.DistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.ModifiableDistanceDBIDList;
+import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultUtil;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
/**
@@ -39,7 +42,7 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
*
* @param <D> Distance type
*/
-public class GenericDistanceDBIDList<D extends Distance<D>> implements ModifiableDistanceDBIDResult<D> {
+public class GenericDistanceDBIDList<D extends Distance<D>> implements ModifiableDistanceDBIDList<D> {
/**
* Actual storage.
*/
@@ -50,7 +53,7 @@ public class GenericDistanceDBIDList<D extends Distance<D>> implements Modifiabl
*/
public GenericDistanceDBIDList() {
super();
- storage = new ArrayList<DistanceDBIDPair<D>>();
+ storage = new ArrayList<>();
}
/**
@@ -60,7 +63,7 @@ public class GenericDistanceDBIDList<D extends Distance<D>> implements Modifiabl
*/
public GenericDistanceDBIDList(int initialCapacity) {
super();
- storage = new ArrayList<DistanceDBIDPair<D>>(initialCapacity);
+ storage = new ArrayList<>(initialCapacity);
}
@Override
@@ -93,8 +96,8 @@ public class GenericDistanceDBIDList<D extends Distance<D>> implements Modifiabl
}
@Override
- public DistanceDBIDResultIter<D> iter() {
- return new Iter();
+ public DistanceDBIDListIter<D> iter() {
+ return new Itr();
}
@Override
@@ -124,7 +127,7 @@ public class GenericDistanceDBIDList<D extends Distance<D>> implements Modifiabl
*
* @apiviz.exclude
*/
- protected class Iter implements DistanceDBIDResultIter<D> {
+ protected class Itr implements DistanceDBIDListIter<D> {
/**
* Iterator position.
*/
@@ -159,5 +162,25 @@ public class GenericDistanceDBIDList<D extends Distance<D>> implements Modifiabl
public String toString() {
return valid() ? getDistancePair().toString() : "null";
}
+
+ @Override
+ public int getOffset() {
+ return pos;
+ }
+
+ @Override
+ public void advance(int count) {
+ pos += count;
+ }
+
+ @Override
+ public void retract() {
+ --pos;
+ }
+
+ @Override
+ public void seek(int off) {
+ pos = off;
+ }
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/generic/KNNSubList.java b/src/de/lmu/ifi/dbs/elki/database/ids/generic/KNNSubList.java
new file mode 100644
index 00000000..3d7863fd
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/generic/KNNSubList.java
@@ -0,0 +1,180 @@
+package de.lmu.ifi.dbs.elki.database.ids.generic;
+
+import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Sublist of an existing result to contain only the first k elements.
+ *
+ * @author Erich Schubert
+ *
+ * @param <D> Distance
+ */
+public class KNNSubList<D extends Distance<D>> implements KNNList<D> {
+ /**
+ * Parameter k.
+ */
+ private final int k;
+
+ /**
+ * Actual size, including ties.
+ */
+ private final int size;
+
+ /**
+ * Wrapped inner result.
+ */
+ private final KNNList<D> inner;
+
+ /**
+ * Constructor.
+ *
+ * @param inner Inner instance
+ * @param k k value
+ */
+ public KNNSubList(KNNList<D> inner, int k) {
+ this.inner = inner;
+ this.k = k;
+ // Compute list size
+ // TODO: optimize for double distances.
+ {
+ DistanceDBIDPair<D> dist = inner.get(k);
+ int i = k;
+ while (i + 1 < inner.size()) {
+ if (dist.compareByDistance(inner.get(i + 1)) < 0) {
+ break;
+ }
+ i++;
+ }
+ size = i;
+ }
+ }
+
+ @Override
+ public int getK() {
+ return k;
+ }
+
+ @Override
+ public DistanceDBIDPair<D> get(int index) {
+ assert (index < size) : "Access beyond design size of list.";
+ return inner.get(index);
+ }
+
+ @Override
+ public D getKNNDistance() {
+ return inner.get(k).getDistance();
+ }
+
+ @Override
+ public DistanceDBIDListIter<D> iter() {
+ return new Itr();
+ }
+
+ @Override
+ public boolean contains(DBIDRef o) {
+ for (DBIDIter iter = iter(); iter.valid(); iter.advance()) {
+ if (DBIDUtil.equal(iter, o)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return size == 0;
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ /**
+ * Iterator for the sublist.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ private class Itr implements DistanceDBIDListIter<D> {
+ /**
+ * Current position.
+ */
+ private int pos = 0;
+
+ @Override
+ public boolean valid() {
+ return pos < size;
+ }
+
+ @Override
+ public void advance() {
+ pos++;
+ }
+
+ @Override
+ public D getDistance() {
+ return inner.get(pos).getDistance();
+ }
+
+ @Override
+ public DistanceDBIDPair<D> getDistancePair() {
+ return inner.get(pos);
+ }
+
+ @Override
+ public int internalGetIndex() {
+ return inner.get(pos).internalGetIndex();
+ }
+
+ @Override
+ public int getOffset() {
+ return pos;
+ }
+
+ @Override
+ public void advance(int count) {
+ pos -= count;
+ }
+
+ @Override
+ public void retract() {
+ --pos;
+ }
+
+ @Override
+ public void seek(int off) {
+ pos = off;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/generic/MaskedDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/generic/MaskedDBIDs.java
index 668ac0d8..2b481fca 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/generic/MaskedDBIDs.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/generic/MaskedDBIDs.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.generic;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/generic/MergedDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/generic/MergedDBIDs.java
index 9d2583e3..7df6975c 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/generic/MergedDBIDs.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/generic/MergedDBIDs.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.generic;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/generic/UnmodifiableArrayDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/generic/UnmodifiableArrayDBIDs.java
index abcdef54..318e4e79 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/generic/UnmodifiableArrayDBIDs.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/generic/UnmodifiableArrayDBIDs.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.generic;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -90,8 +90,8 @@ public class UnmodifiableArrayDBIDs implements ArrayStaticDBIDs {
}
@Override
- public void assign(int index, DBIDVar var) {
- inner.assign(index, var);
+ public void assignVar(int index, DBIDVar var) {
+ inner.assignVar(index, var);
}
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/generic/UnmodifiableDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/generic/UnmodifiableDBIDs.java
index fea35692..458dab3f 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/generic/UnmodifiableDBIDs.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/generic/UnmodifiableDBIDs.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.generic;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/generic/package-info.java b/src/de/lmu/ifi/dbs/elki/database/ids/generic/package-info.java
index 890b9c0a..9920cac7 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/generic/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/generic/package-info.java
@@ -7,7 +7,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/AbstractIntegerDBIDFactory.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/AbstractIntegerDBIDFactory.java
new file mode 100644
index 00000000..061deb08
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/AbstractIntegerDBIDFactory.java
@@ -0,0 +1,201 @@
+package de.lmu.ifi.dbs.elki.database.ids.integer;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.DBID;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDFactory;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDVar;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.HashSetModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNHeap;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNHeap;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
+import de.lmu.ifi.dbs.elki.database.ids.generic.DistanceDBIDPairKNNHeap;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+import de.lmu.ifi.dbs.elki.persistent.ByteBufferSerializer;
+import de.lmu.ifi.dbs.elki.persistent.FixedSizeByteBufferSerializer;
+
+/**
+ * Abstract base class for DBID factories.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.uses IntegerDBID oneway - - «create»
+ * @apiviz.uses IntegerDBIDPair oneway - - «create»
+ * @apiviz.uses IntegerDBIDRange oneway - - «create»
+ * @apiviz.uses TroveArrayModifiableDBIDs oneway - - «create»
+ * @apiviz.uses TroveHashSetModifiableDBIDs oneway - - «create»
+ */
+abstract class AbstractIntegerDBIDFactory implements DBIDFactory {
+ /**
+ * Invalid ID.
+ */
+ DBID invalid = new IntegerDBID(Integer.MIN_VALUE);
+
+ @Override
+ public DBID importInteger(int id) {
+ return new IntegerDBID(id);
+ }
+
+ @Override
+ public void assignVar(DBIDVar var, int val) {
+ if (var instanceof IntegerDBIDVar) {
+ ((IntegerDBIDVar)var).internalSetIndex(val);
+ } else {
+ var.set(new IntegerDBID(val));
+ }
+ }
+
+ @Override
+ public int compare(DBIDRef a, DBIDRef b) {
+ final int inta = a.internalGetIndex();
+ final int intb = b.internalGetIndex();
+ return (inta < intb ? -1 : (inta == intb ? 0 : 1));
+ }
+
+ @Override
+ public boolean equal(DBIDRef a, DBIDRef b) {
+ return a.internalGetIndex() == b.internalGetIndex();
+ }
+
+ @Override
+ public String toString(DBIDRef id) {
+ return Integer.toString(id.internalGetIndex());
+ }
+
+ @Override
+ public DBIDVar newVar(DBIDRef val) {
+ return new IntegerDBIDVar(val);
+ }
+
+ @Override
+ public ArrayModifiableDBIDs newArray() {
+ return new ArrayModifiableIntegerDBIDs();
+ }
+
+ @Override
+ public HashSetModifiableDBIDs newHashSet() {
+ return new TroveHashSetModifiableDBIDs();
+ }
+
+ @Override
+ public ArrayModifiableDBIDs newArray(int size) {
+ return new ArrayModifiableIntegerDBIDs(size);
+ }
+
+ @Override
+ public HashSetModifiableDBIDs newHashSet(int size) {
+ return new TroveHashSetModifiableDBIDs(size);
+ }
+
+ @Override
+ public ArrayModifiableDBIDs newArray(DBIDs existing) {
+ return new ArrayModifiableIntegerDBIDs(existing);
+ }
+
+ @Override
+ public HashSetModifiableDBIDs newHashSet(DBIDs existing) {
+ return new TroveHashSetModifiableDBIDs(existing);
+ }
+
+ @Override
+ public DBIDPair newPair(DBIDRef first, DBIDRef second) {
+ return new IntegerDBIDPair(first.internalGetIndex(), second.internalGetIndex());
+ }
+
+ @Override
+ public DoubleDBIDPair newPair(double val, DBIDRef id) {
+ return new IntegerDoubleDBIDPair(val, id.internalGetIndex());
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <D extends Distance<D>> DistanceDBIDPair<D> newDistancePair(D val, DBIDRef id) {
+ if (val instanceof DoubleDistance) {
+ return (DistanceDBIDPair<D>) new DoubleDistanceIntegerDBIDPair(((DoubleDistance) val).doubleValue(), id.internalGetIndex());
+ }
+ return new DistanceIntegerDBIDPair<>(val, id.internalGetIndex());
+ }
+
+ @Override
+ public DoubleDistanceDBIDPair newDistancePair(double val, DBIDRef id) {
+ return new DoubleDistanceIntegerDBIDPair(val, id.internalGetIndex());
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <D extends Distance<D>> KNNHeap<D> newHeap(D factory, int k) {
+ if (factory instanceof DoubleDistance) {
+ return (KNNHeap<D>) new DoubleDistanceIntegerDBIDKNNListHeap(k);
+ }
+ return new DistanceDBIDPairKNNHeap<>(k);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <D extends Distance<D>> KNNHeap<D> newHeap(KNNList<D> exist) {
+ if (exist instanceof DoubleDistanceKNNList) {
+ DoubleDistanceKNNHeap heap = new DoubleDistanceIntegerDBIDKNNListHeap(exist.getK());
+ // Insert backwards, as this will produce a proper heap
+ for (int i = exist.size() - 1; i >= 0; i--) {
+ heap.add((DoubleDistanceDBIDPair) exist.get(i));
+ }
+ return (KNNHeap<D>) heap;
+ } else {
+ DistanceDBIDPairKNNHeap<D> heap = new DistanceDBIDPairKNNHeap<>(exist.getK());
+ // Insert backwards, as this will produce a proper heap
+ for (int i = exist.size() - 1; i >= 0; i--) {
+ heap.add(exist.get(i));
+ }
+ return heap;
+ }
+ }
+
+ @Override
+ public ByteBufferSerializer<DBID> getDBIDSerializer() {
+ return IntegerDBID.DYNAMIC_SERIALIZER;
+ }
+
+ @Override
+ public FixedSizeByteBufferSerializer<DBID> getDBIDSerializerStatic() {
+ return IntegerDBID.STATIC_SERIALIZER;
+ }
+
+ @Override
+ public Class<? extends DBID> getTypeRestriction() {
+ return IntegerDBID.class;
+ }
+
+ @Override
+ public DBIDRef invalid() {
+ return invalid;
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/ArrayModifiableIntegerDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/ArrayModifiableIntegerDBIDs.java
new file mode 100644
index 00000000..dfff45b4
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/ArrayModifiableIntegerDBIDs.java
@@ -0,0 +1,306 @@
+package de.lmu.ifi.dbs.elki.database.ids.integer;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.Arrays;
+import java.util.Comparator;
+
+import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.DBID;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDVar;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+
+/**
+ * Class using a primitive int[] array as storage.
+ *
+ * @author Erich Schubert
+ */
+public class ArrayModifiableIntegerDBIDs implements ArrayModifiableDBIDs, IntegerArrayDBIDs {
+ /**
+ * The actual Trove array list.
+ */
+ private int[] store;
+
+ /**
+ * Occupied size.
+ */
+ private int size = 0;
+
+ /**
+ * Initial size.
+ */
+ public static final int INITIAL_SIZE = 21;
+
+ /**
+ * Constructor.
+ *
+ * @param size Initial size
+ */
+ protected ArrayModifiableIntegerDBIDs(int size) {
+ super();
+ this.store = new int[size];
+ }
+
+ /**
+ * Constructor.
+ */
+ protected ArrayModifiableIntegerDBIDs() {
+ super();
+ this.store = new int[INITIAL_SIZE];
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param existing Existing ids
+ */
+ protected ArrayModifiableIntegerDBIDs(DBIDs existing) {
+ this(existing.size());
+ this.addDBIDs(existing);
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return size == 0;
+ }
+
+ @Override
+ public DBID get(int i) {
+ return new IntegerDBID(store[i]);
+ }
+
+ @Override
+ public void assignVar(int index, DBIDVar var) {
+ if(var instanceof IntegerDBIDVar) {
+ ((IntegerDBIDVar) var).internalSetIndex(store[index]);
+ }
+ else {
+ // less efficient, involves object creation.
+ var.set(get(index));
+ }
+ }
+
+ /**
+ * Resize as desired.
+ *
+ * @param minsize Desired size
+ */
+ private void ensureSize(int minsize) {
+ int asize = store.length;
+ // Ensure a minimum size, to not run into an infinite loop below!
+ if (asize < 2) {
+ asize = 2;
+ }
+ while(asize < minsize) {
+ asize = (asize >> 1) + asize;
+ }
+ if(asize > store.length) {
+ store = Arrays.copyOf(store, asize);
+ }
+ }
+
+ @Override
+ public boolean addDBIDs(DBIDs ids) {
+ ensureSize(size + ids.size());
+ for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
+ store[size] = iter.internalGetIndex();
+ ++size;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean removeDBIDs(DBIDs ids) {
+ boolean success = false;
+ for(DBIDIter id = ids.iter(); id.valid(); id.advance()) {
+ int rm = id.internalGetIndex();
+ // TODO: when sorted, use binary search!
+ for(int i = 0; i < size; i++) {
+ if(store[i] == rm) {
+ --size;
+ store[i] = store[size];
+ success = true;
+ break;
+ }
+ }
+ }
+ return success;
+ }
+
+ @Override
+ public boolean add(DBIDRef e) {
+ if(size == store.length) {
+ ensureSize(size + 1);
+ }
+ store[size] = e.internalGetIndex();
+ ++size;
+ return true;
+ }
+
+ @Override
+ public boolean remove(DBIDRef o) {
+ int rm = o.internalGetIndex();
+ // TODO: when sorted, use binary search!
+ for(int i = 0; i < size; i++) {
+ if(store[i] == rm) {
+ --size;
+ store[i] = store[size];
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public DBID set(int index, DBIDRef element) {
+ int prev = store[index];
+ store[index] = element.internalGetIndex();
+ return new IntegerDBID(prev);
+ }
+
+ @Override
+ public DBID remove(int index) {
+ DBID ret = new IntegerDBID(store[index]);
+ --size;
+ if(size > 0) {
+ store[index] = store[size];
+ }
+ return ret;
+ }
+
+ @Override
+ public void clear() {
+ size = 0;
+ }
+
+ @Override
+ public int binarySearch(DBIDRef key) {
+ return Arrays.binarySearch(store, 0, size, key.internalGetIndex());
+ }
+
+ @Override
+ public boolean contains(DBIDRef o) {
+ // TODO: recognize sorted arrays, then use binary search?
+ int oid = o.internalGetIndex();
+ for(int i = 0; i < size; i++) {
+ if(store[i] == oid) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void sort() {
+ Arrays.sort(store, 0, size);
+ }
+
+ @Override
+ public void sort(Comparator<? super DBIDRef> comparator) {
+ IntegerDBIDArrayQuickSort.sort(store, 0, size, comparator);
+ }
+
+ @Override
+ public void sort(int start, int end, Comparator<? super DBIDRef> comparator) {
+ IntegerDBIDArrayQuickSort.sort(store, start, end, comparator);
+ }
+
+ @Override
+ public void swap(int a, int b) {
+ int tmp = store[b];
+ store[b] = store[a];
+ store[a] = tmp;
+ }
+
+ @Override
+ public IntegerDBIDArrayMIter iter() {
+ return new Itr();
+ }
+
+ /**
+ * Iterator class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ private class Itr implements IntegerDBIDArrayMIter {
+ /**
+ * Iterator position.
+ */
+ int pos = 0;
+
+ @Override
+ public int internalGetIndex() {
+ return store[pos];
+ }
+
+ @Override
+ public boolean valid() {
+ return pos < size && pos >= 0;
+ }
+
+ @Override
+ public void advance() {
+ ++pos;
+ }
+
+ @Override
+ public int getOffset() {
+ return pos;
+ }
+
+ @Override
+ public void advance(int count) {
+ pos += count;
+ }
+
+ @Override
+ public void retract() {
+ --pos;
+ }
+
+ @Override
+ public void seek(int off) {
+ pos = off;
+ }
+
+ @Override
+ public void remove() {
+ ArrayModifiableIntegerDBIDs.this.remove(pos);
+ }
+
+ @Override
+ public String toString() {
+ return Integer.toString(internalGetIndex()) + "@" + pos;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntArrayStaticDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/ArrayStaticIntegerDBIDs.java
index aa3b3cc0..4b4b5a42 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntArrayStaticDBIDs.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/ArrayStaticIntegerDBIDs.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -39,7 +39,7 @@ import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
*
* @apiviz.has IntegerDBID
*/
-public class IntArrayStaticDBIDs implements IntegerArrayStaticDBIDs {
+public class ArrayStaticIntegerDBIDs implements IntegerArrayStaticDBIDs {
/**
* The actual storage.
*/
@@ -50,7 +50,7 @@ public class IntArrayStaticDBIDs implements IntegerArrayStaticDBIDs {
*
* @param ids Array of ids.
*/
- public IntArrayStaticDBIDs(int... ids) {
+ public ArrayStaticIntegerDBIDs(int... ids) {
super();
this.ids = ids;
}
@@ -118,7 +118,7 @@ public class IntArrayStaticDBIDs implements IntegerArrayStaticDBIDs {
@Override
public String toString() {
- return Integer.toString(internalGetIndex());
+ return Integer.toString(internalGetIndex()) + "@" + pos;
}
}
@@ -149,7 +149,7 @@ public class IntArrayStaticDBIDs implements IntegerArrayStaticDBIDs {
}
@Override
- public void assign(int i, DBIDVar var) {
+ public void assignVar(int i, DBIDVar var) {
if (var instanceof IntegerDBIDVar) {
((IntegerDBIDVar)var).internalSetIndex(ids[i]);
} else {
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/DistanceIntegerDBIDPair.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/DistanceIntegerDBIDPair.java
index 01eec02e..a8930b87 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/DistanceIntegerDBIDPair.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/DistanceIntegerDBIDPair.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,9 +23,10 @@ package de.lmu.ifi.dbs.elki.database.ids.integer;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import de.lmu.ifi.dbs.elki.database.ids.DistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDPair;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+import de.lmu.ifi.dbs.elki.utilities.Util;
/**
* Class storing a double distance a DBID.
@@ -88,8 +89,13 @@ class DistanceIntegerDBIDPair<D extends Distance<D>> implements DistanceDBIDPair
}
if (o instanceof DoubleDistanceIntegerDBIDPair && distance instanceof DoubleDistance) {
DoubleDistanceIntegerDBIDPair p = (DoubleDistanceIntegerDBIDPair) o;
- return (this.id == p.id) && (((DoubleDistance) this.distance).doubleValue() == p.distance);
+ return (this.id == p.id) && (Double.compare(((DoubleDistance) this.distance).doubleValue(), p.distance) == 0);
}
return false;
}
+
+ @Override
+ public int hashCode() {
+ return Util.mixHashCodes(distance.hashCode(), id);
+ }
}
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDKNNHeap.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDKNNHeap.java
new file mode 100644
index 00000000..6c88c2d8
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDKNNHeap.java
@@ -0,0 +1,252 @@
+package de.lmu.ifi.dbs.elki.database.ids.integer;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.Arrays;
+
+import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNHeap;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.DoubleIntegerMaxHeap;
+
+/**
+ * Class to efficiently manage a kNN heap.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has DoubleDistanceIntegerDBIDKNNList
+ * @apiviz.composedOf DoubleIntegerMaxHeap
+ */
+public class DoubleDistanceIntegerDBIDKNNHeap implements DoubleDistanceKNNHeap {
+ /**
+ * k for this heap.
+ */
+ private final int k;
+
+ /**
+ * The main heap.
+ */
+ private final DoubleIntegerMaxHeap heap;
+
+ /**
+ * List to track ties.
+ */
+ private int[] ties;
+
+ /**
+ * Number of element in ties list.
+ */
+ private int numties = 0;
+
+ /**
+ * Current maximum value.
+ */
+ private double kdist = Double.POSITIVE_INFINITY;
+
+ /**
+ * Initial size of ties array.
+ */
+ private static final int INITIAL_TIES_SIZE = 11;
+
+ /**
+ * Constructor.
+ *
+ * @param k Size of knn.
+ */
+ public DoubleDistanceIntegerDBIDKNNHeap(int k) {
+ super();
+ this.k = k;
+ this.heap = new DoubleIntegerMaxHeap(k);
+ this.ties = new int[INITIAL_TIES_SIZE];
+ }
+
+ @Override
+ public int getK() {
+ return k;
+ }
+
+ @Override
+ @Deprecated
+ public DoubleDistance getKNNDistance() {
+ if (heap.size() < k) {
+ return DoubleDistance.INFINITE_DISTANCE;
+ }
+ return new DoubleDistance(kdist);
+ }
+
+ @Override
+ public double doubleKNNDistance() {
+ return kdist;
+ }
+
+ @Override
+ @Deprecated
+ public void add(DoubleDistance distance, DBIDRef id) {
+ add(distance.doubleValue(), id);
+ }
+
+ @Override
+ @Deprecated
+ public void add(Double distance, DBIDRef id) {
+ add(distance.doubleValue(), id);
+ }
+
+ @Override
+ public final void add(final double distance, final DBIDRef id) {
+ if (distance > kdist) {
+ return;
+ }
+ final int iid = id.internalGetIndex();
+ if (heap.size() < k) {
+ heap.add(distance, iid);
+ if (heap.size() >= k) {
+ kdist = heap.peekKey();
+ }
+ return;
+ }
+ // Tied with top:
+ if (distance >= kdist) {
+ addToTies(iid);
+ return;
+ }
+ // Old top element: (kdist, previd)
+ updateHeap(distance, iid);
+ }
+
+ @Override
+ public void add(DoubleDistanceDBIDPair e) {
+ add(e.doubleDistance(), e);
+ }
+
+ /**
+ * Do a full update for the heap.
+ *
+ * @param distance Distance
+ * @param iid Object id
+ */
+ private final void updateHeap(final double distance, final int iid) {
+ final double prevdist = kdist;
+ final int previd = heap.peekValue();
+ heap.replaceTopElement(distance, iid);
+ kdist = heap.peekKey();
+ // If the kdist improved, zap ties.
+ if (kdist < prevdist) {
+ numties = 0;
+ } else {
+ addToTies(previd);
+ }
+ }
+
+ /**
+ * Ensure the ties array has capacity for at least one more element.
+ *
+ * @param id Id to add
+ */
+ private final void addToTies(int id) {
+ if (ties.length == numties) {
+ ties = Arrays.copyOf(ties, (ties.length << 1) + 1); // grow.
+ }
+ ties[numties] = id;
+ ++numties;
+ }
+
+ @Override
+ public DoubleDistanceIntegerDBIDPair poll() {
+ final DoubleDistanceIntegerDBIDPair ret;
+ if (numties > 0) {
+ ret = new DoubleDistanceIntegerDBIDPair(kdist, ties[numties - 1]);
+ --numties;
+ } else {
+ ret = new DoubleDistanceIntegerDBIDPair(heap.peekKey(), heap.peekValue());
+ heap.poll();
+ }
+ return ret;
+ }
+
+ /**
+ * Pop the topmost element.
+ */
+ protected void pop() {
+ if (numties > 0) {
+ --numties;
+ } else {
+ heap.poll();
+ }
+ }
+
+ @Override
+ public DoubleDistanceIntegerDBIDPair peek() {
+ if (numties > 0) {
+ return new DoubleDistanceIntegerDBIDPair(kdist, ties[numties - 1]);
+ }
+ return new DoubleDistanceIntegerDBIDPair(heap.peekKey(), heap.peekValue());
+ }
+
+ @Override
+ public int size() {
+ return heap.size() + numties;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return heap.size() == 0;
+ }
+
+ @Override
+ public void clear() {
+ heap.clear();
+ numties = 0;
+ }
+
+ @Override
+ public DoubleDistanceIntegerDBIDKNNList toKNNList() {
+ return new DoubleDistanceIntegerDBIDKNNList(this);
+ }
+
+ /**
+ * Peek the topmost distance.
+ *
+ * @return distance
+ */
+ protected double peekDistance() {
+ if (numties > 0) {
+ return kdist;
+ } else {
+ return heap.peekKey();
+ }
+ }
+
+ /**
+ * Peek the topmost internal ID.
+ *
+ * @return internal id
+ */
+ protected int peekInternalDBID() {
+ if (numties > 0) {
+ return ties[numties - 1];
+ }
+ return heap.peekValue();
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDKNNList.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDKNNList.java
new file mode 100644
index 00000000..a74497e8
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDKNNList.java
@@ -0,0 +1,298 @@
+package de.lmu.ifi.dbs.elki.database.ids.integer;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import java.util.Arrays;
+
+import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.ModifiableDoubleDistanceDBIDList;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+
+/**
+ * Class to store double distance, integer DBID results.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.uses DoubleIntegerArrayQuickSort
+ */
+public class DoubleDistanceIntegerDBIDKNNList implements ModifiableDoubleDistanceDBIDList, DoubleDistanceKNNList, IntegerDBIDs {
+ /**
+ * Initial size allocation.
+ */
+ private static final int INITIAL_SIZE = 21;
+
+ /**
+ * The k value this list was generated for.
+ */
+ int k;
+
+ /**
+ * The size
+ */
+ int size;
+
+ /**
+ * Distance values
+ */
+ double[] dists;
+
+ /**
+ * DBIDs
+ */
+ int[] ids;
+
+ /**
+ * Constructor.
+ */
+ public DoubleDistanceIntegerDBIDKNNList() {
+ super();
+ this.k = -1;
+ this.dists = new double[INITIAL_SIZE];
+ this.ids = new int[INITIAL_SIZE];
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param k K parameter
+ * @param size Actual size
+ */
+ public DoubleDistanceIntegerDBIDKNNList(int k, int size) {
+ super();
+ this.k = k;
+ if (size > 0) {
+ this.dists = new double[size];
+ this.ids = new int[size];
+ } else {
+ this.dists = new double[INITIAL_SIZE];
+ this.ids = new int[INITIAL_SIZE];
+ }
+ }
+
+ /**
+ * Constructor from heap.
+ *
+ * @param heap KNN heap.
+ */
+ public DoubleDistanceIntegerDBIDKNNList(DoubleDistanceIntegerDBIDKNNHeap heap) {
+ super();
+ this.k = heap.getK();
+ this.size = heap.size();
+ this.dists = new double[size];
+ this.ids = new int[size];
+ for (int i = size - 1; i >= 0; i--) {
+ dists[i] = heap.peekDistance();
+ ids[i] = heap.peekInternalDBID();
+ heap.pop();
+ }
+ }
+
+ @Override
+ public DoubleDistanceIntegerDBIDListIter iter() {
+ return new Itr();
+ }
+
+ @Override
+ public boolean contains(DBIDRef o) {
+ final int q = o.internalGetIndex();
+ for (int i = 0; i < size; i++) {
+ if (q == ids[i]) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return size == 0;
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ @Override
+ public int getK() {
+ if (k <= 0) {
+ return size - 1;
+ }
+ return k;
+ }
+
+ @Override
+ public DoubleDistanceIntegerDBIDPair get(int index) {
+ return new DoubleDistanceIntegerDBIDPair(dists[index], ids[index]);
+ }
+
+ @Override
+ @Deprecated
+ public DoubleDistance getKNNDistance() {
+ return new DoubleDistance(doubleKNNDistance());
+ }
+
+ @Override
+ public double doubleKNNDistance() {
+ if (k <= 0) {
+ return dists[size - 1];
+ }
+ if (size < k) {
+ return Double.POSITIVE_INFINITY;
+ }
+ return dists[k - 1];
+ }
+
+ /**
+ * Add an entry, consisting of distance and internal index.
+ *
+ * @param dist Distance
+ * @param id Internal index
+ */
+ protected void add(double dist, int id) {
+ if (size == dists.length) {
+ final int newlength = (dists.length << 1) + 1;
+ dists = Arrays.copyOf(dists, newlength);
+ ids = Arrays.copyOf(ids, newlength);
+ }
+ dists[size] = dist;
+ ids[size] = id;
+ ++size;
+ }
+
+ @Override
+ @Deprecated
+ public void add(DoubleDistance dist, DBIDRef id) {
+ add(dist.doubleValue(), id);
+ }
+
+ @Override
+ public void add(double dist, DBIDRef id) {
+ add(dist, id.internalGetIndex());
+ }
+
+ @Override
+ public void add(DoubleDistanceDBIDPair pair) {
+ add(pair.doubleDistance(), pair.internalGetIndex());
+ }
+
+ @Override
+ public void sort() {
+ DoubleIntegerArrayQuickSort.sort(dists, ids, 0, size);
+ }
+
+ /**
+ * Reverse the list.
+ */
+ protected void reverse() {
+ for (int i = 0, j = size - 1; i < j; i++, j--) {
+ double tmpd = dists[j];
+ dists[j] = dists[i];
+ dists[i] = tmpd;
+ int tmpi = ids[j];
+ ids[j] = ids[i];
+ ids[i] = tmpi;
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder buf = new StringBuilder();
+ buf.append("kNNList[");
+ for (DoubleDistanceDBIDListIter iter = this.iter(); iter.valid();) {
+ buf.append(iter.doubleDistance()).append(':').append(iter.internalGetIndex());
+ iter.advance();
+ if (iter.valid()) {
+ buf.append(',');
+ }
+ }
+ buf.append(']');
+ return buf.toString();
+ }
+
+ /**
+ * List iterator.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ private class Itr implements DoubleDistanceIntegerDBIDListIter {
+ int offset = 0;
+
+ @Override
+ public boolean valid() {
+ return offset < size;
+ }
+
+ @Override
+ public void advance() {
+ ++offset;
+ }
+
+ @Override
+ public int getOffset() {
+ return offset;
+ }
+
+ @Override
+ public void advance(int count) {
+ offset += count;
+ }
+
+ @Override
+ public void retract() {
+ offset--;
+ }
+
+ @Override
+ public void seek(int off) {
+ offset = off;
+ }
+
+ @Override
+ public int internalGetIndex() {
+ return ids[offset];
+ }
+
+ @Override
+ public double doubleDistance() {
+ return dists[offset];
+ }
+
+ @Override
+ public DoubleDistanceDBIDPair getDistancePair() {
+ return new DoubleDistanceIntegerDBIDPair(dists[offset], ids[offset]);
+ }
+
+ @Override
+ @Deprecated
+ public DoubleDistance getDistance() {
+ return new DoubleDistance(dists[offset]);
+ }
+
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDKNNListHeap.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDKNNListHeap.java
new file mode 100644
index 00000000..ffc2266e
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDKNNListHeap.java
@@ -0,0 +1,315 @@
+package de.lmu.ifi.dbs.elki.database.ids.integer;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import java.util.Arrays;
+
+import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNHeap;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNList;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+
+/**
+ * Class to store double distance, integer DBID results.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.uses DoubleIntegerArrayQuickSort
+ */
+public class DoubleDistanceIntegerDBIDKNNListHeap implements DoubleDistanceKNNHeap, DoubleDistanceKNNList, IntegerDBIDs {
+ /**
+ * The k value this list was generated for.
+ */
+ int k;
+
+ /**
+ * The size
+ */
+ int size;
+
+ /**
+ * Distance values
+ */
+ double[] dists;
+
+ /**
+ * DBIDs
+ */
+ int[] ids;
+
+ /**
+ * Constructor.
+ *
+ * @param k K parameter
+ */
+ public DoubleDistanceIntegerDBIDKNNListHeap(int k) {
+ super();
+ this.k = k;
+ this.size = 0;
+ this.dists = new double[k + 1];
+ this.ids = new int[k + 1];
+ }
+
+ @Override
+ public DoubleDistanceIntegerDBIDListIter iter() {
+ return new Itr();
+ }
+
+ @Override
+ public boolean contains(DBIDRef o) {
+ final int q = o.internalGetIndex();
+ for(int i = 0; i < size; i++) {
+ if(q == ids[i]) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return size == 0;
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ @Override
+ public int getK() {
+ return k;
+ }
+
+ @Override
+ public DoubleDistanceIntegerDBIDPair get(int index) {
+ return new DoubleDistanceIntegerDBIDPair(dists[index], ids[index]);
+ }
+
+ @Override
+ @Deprecated
+ public DoubleDistance getKNNDistance() {
+ return new DoubleDistance(doubleKNNDistance());
+ }
+
+ @Override
+ public double doubleKNNDistance() {
+ if(size < k) {
+ return Double.POSITIVE_INFINITY;
+ }
+ return dists[k - 1];
+ }
+
+ /**
+ * Add an entry, consisting of distance and internal index.
+ *
+ * @param dist Distance
+ * @param id Internal index
+ */
+ protected void append(double dist, int id) {
+ ensureSize(size + 1);
+ dists[size] = dist;
+ ids[size] = id;
+ ++size;
+ }
+
+ /**
+ * Add a new element to the heap/list.
+ *
+ * @param dist Distance
+ * @param id Object ID
+ */
+ protected void add(double dist, int id) {
+ if(size < k) {
+ dists[size] = dist;
+ ids[size] = id;
+ ++size;
+ if(size == k) {
+ sort();
+ }
+ return;
+ }
+ if (dist > dists[size - 1]) {
+ return;
+ }
+ // Ensure we have enough space.
+ ensureSize(size + 1);
+ // Insertion sort:
+ int pos = size;
+ while(pos > 0 && dists[pos - 1] > dist) {
+ dists[pos] = dists[pos - 1];
+ ids[pos] = ids[pos - 1];
+ --pos;
+ }
+ dists[pos] = dist;
+ ids[pos] = id;
+ ++size;
+ // Truncate if necessary:
+ if(dists[k] > dists[k - 1]) {
+ size = k;
+ }
+ }
+
+ /**
+ * Ensure we have enough space.
+ *
+ * @param size Desired size
+ */
+ private void ensureSize(int size) {
+ if(size > dists.length) {
+ final int newlength = Math.max(size, (dists.length << 1) + 1);
+ dists = Arrays.copyOf(dists, newlength);
+ ids = Arrays.copyOf(ids, newlength);
+ }
+ }
+
+ @Override
+ @Deprecated
+ public void add(DoubleDistance dist, DBIDRef id) {
+ add(dist.doubleValue(), id);
+ }
+
+ @Override
+ @Deprecated
+ public void add(Double dist, DBIDRef id) {
+ add(dist.doubleValue(), id);
+ }
+
+ @Override
+ public void add(double dist, DBIDRef id) {
+ add(dist, id.internalGetIndex());
+ }
+
+ @Override
+ public void add(DoubleDistanceDBIDPair pair) {
+ add(pair.doubleDistance(), pair.internalGetIndex());
+ }
+
+ /**
+ * Sort the current contents of the list.
+ */
+ protected void sort() {
+ DoubleIntegerArrayQuickSort.sort(dists, ids, 0, size);
+ }
+
+ @Override
+ public void clear() {
+ size = 0;
+ Arrays.fill(dists, Double.NaN);
+ Arrays.fill(ids, -1);
+ }
+
+ @Override
+ public DoubleDistanceIntegerDBIDPair poll() {
+ return new DoubleDistanceIntegerDBIDPair(dists[k], ids[k]);
+ }
+
+ @Override
+ public DoubleDistanceIntegerDBIDPair peek() {
+ return new DoubleDistanceIntegerDBIDPair(dists[k], ids[k]);
+ }
+
+ @Override
+ public DoubleDistanceKNNList toKNNList() {
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder buf = new StringBuilder();
+ buf.append("kNNListHeap[");
+ for(DoubleDistanceDBIDListIter iter = this.iter(); iter.valid();) {
+ buf.append(iter.doubleDistance()).append(':').append(iter.internalGetIndex());
+ iter.advance();
+ if(iter.valid()) {
+ buf.append(',');
+ }
+ }
+ buf.append(']');
+ return buf.toString();
+ }
+
+ /**
+ * List iterator.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ private class Itr implements DoubleDistanceIntegerDBIDListIter {
+ int offset = 0;
+
+ @Override
+ public boolean valid() {
+ return offset < size;
+ }
+
+ @Override
+ public void advance() {
+ ++offset;
+ }
+
+ @Override
+ public int getOffset() {
+ return offset;
+ }
+
+ @Override
+ public void advance(int count) {
+ offset += count;
+ }
+
+ @Override
+ public void retract() {
+ offset--;
+ }
+
+ @Override
+ public void seek(int off) {
+ offset = off;
+ }
+
+ @Override
+ public int internalGetIndex() {
+ return ids[offset];
+ }
+
+ @Override
+ public double doubleDistance() {
+ return dists[offset];
+ }
+
+ @Override
+ public DoubleDistanceDBIDPair getDistancePair() {
+ return new DoubleDistanceIntegerDBIDPair(dists[offset], ids[offset]);
+ }
+
+ @Override
+ @Deprecated
+ public DoubleDistance getDistance() {
+ return new DoubleDistance(dists[offset]);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/DistributionWithRandom.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDListIter.java
index 02f5002f..0df81929 100644
--- a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/DistributionWithRandom.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDListIter.java
@@ -1,9 +1,10 @@
-package de.lmu.ifi.dbs.elki.math.statistics.distribution;
+package de.lmu.ifi.dbs.elki.database.ids.integer;
+
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -21,17 +22,13 @@ package de.lmu.ifi.dbs.elki.math.statistics.distribution;
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDListIter;
/**
- * Distribution that also has support for generating random numbers.
+ * Combination interface.
*
* @author Erich Schubert
*/
-public interface DistributionWithRandom extends Distribution {
- /**
- * Generate a new random value
- *
- * @return new random value
- */
- double nextRandom();
-} \ No newline at end of file
+public interface DoubleDistanceIntegerDBIDListIter extends DoubleDistanceDBIDListIter, IntegerDBIDArrayIter {
+ // Yet another painful combination interface.
+}
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDPair.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDPair.java
index 8334d2e3..1f3b2a45 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDPair.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDPair.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -22,9 +22,10 @@ package de.lmu.ifi.dbs.elki.database.ids.integer;
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import de.lmu.ifi.dbs.elki.database.ids.DistanceDBIDPair;
-import de.lmu.ifi.dbs.elki.database.ids.DoubleDistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPair;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+import de.lmu.ifi.dbs.elki.utilities.Util;
/**
* Class storing a double distance a DBID.
@@ -90,14 +91,20 @@ class DoubleDistanceIntegerDBIDPair implements DoubleDistanceDBIDPair, IntegerDB
}
if (o instanceof DoubleDistanceIntegerDBIDPair) {
DoubleDistanceIntegerDBIDPair p = (DoubleDistanceIntegerDBIDPair) o;
- return (this.id == p.id) && (this.distance == p.distance);
+ return (this.id == p.id) && (Double.compare(this.distance, p.distance) == 0);
}
if (o instanceof DistanceIntegerDBIDPair) {
DistanceIntegerDBIDPair<?> p = (DistanceIntegerDBIDPair<?>) o;
if (p.distance instanceof DoubleDistance) {
- return (this.id == p.id) && (this.distance == ((DoubleDistance) p.distance).doubleValue());
+ return (this.id == p.id) && (Double.compare(this.distance, ((DoubleDistance) p.distance).doubleValue()) == 0);
}
}
return false;
}
+
+ @Override
+ public int hashCode() {
+ long bits = Double.doubleToLongBits(distance);
+ return Util.mixHashCodes((int) (bits ^ (bits >>> 32)), id);
+ }
}
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleIntegerArrayQuickSort.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleIntegerArrayQuickSort.java
new file mode 100644
index 00000000..8f1c58d6
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleIntegerArrayQuickSort.java
@@ -0,0 +1,181 @@
+package de.lmu.ifi.dbs.elki.database.ids.integer;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Class to sort a double and an integer DBID array, using a quicksort with a
+ * best of 5 heuristic.
+ *
+ * @author Erich Schubert
+ */
+class DoubleIntegerArrayQuickSort {
+ /**
+ * Threshold for using insertion sort.
+ */
+ private static final int INSERTION_THRESHOLD = 22;
+
+ /**
+ * Sort the full array using the given comparator.
+ *
+ * @param keys Keys for sorting
+ * @param values Values for sorting
+ * @param len Length to sort.
+ */
+ public static void sort(double[] keys, int[] values, int len) {
+ sort(keys, values, 0, len);
+ }
+
+ /**
+ * Sort the array using the given comparator.
+ *
+ * @param keys Keys for sorting
+ * @param values Values for sorting
+ * @param start First index
+ * @param end Last index (exclusive)
+ */
+ public static void sort(double[] keys, int[] values, int start, int end) {
+ quickSort(keys, values, start, end);
+ }
+
+ /**
+ * Actual recursive sort function.
+ *
+ * @param keys Keys for sorting
+ * @param vals Values for sorting
+ * @param start First index
+ * @param end Last index (exclusive!)
+ */
+ private static void quickSort(double[] keys, int[] vals, final int start, final int end) {
+ final int len = end - start;
+ if (len < INSERTION_THRESHOLD) {
+ // Classic insertion sort.
+ for (int i = start + 1; i < end; i++) {
+ for (int j = i; j > start; j--) {
+ if (keys[j] < keys[j - 1]) {
+ swap(keys, vals, j, j - 1);
+ } else {
+ break;
+ }
+ }
+ }
+ return;
+ }
+
+ // Choose pivots by looking at five candidates.
+ final int seventh = (len >> 3) + (len >> 6) + 1;
+ final int m3 = (start + end) >> 1; // middle
+ final int m2 = m3 - seventh;
+ final int m1 = m2 - seventh;
+ final int m4 = m3 + seventh;
+ final int m5 = m4 + seventh;
+
+ // Mixture of insertion and merge sort:
+ if (keys[m1] > keys[m2]) {
+ swap(keys, vals, m1, m2);
+ }
+ if (keys[m3] > keys[m4]) {
+ swap(keys, vals, m3, m4);
+ }
+ // Merge 1+2 and 3+4
+ if (keys[m2] > keys[m4]) {
+ swap(keys, vals, m2, m4);
+ }
+ if (keys[m1] > keys[m3]) {
+ swap(keys, vals, m1, m3);
+ }
+ if (keys[m2] > keys[m3]) {
+ swap(keys, vals, m2, m3);
+ }
+ // Insertion sort m5:
+ if (keys[m4] > keys[m5]) {
+ swap(keys, vals, m4, m5);
+ if (keys[m3] > keys[m4]) {
+ swap(keys, vals, m3, m4);
+ if (keys[m2] > keys[m3]) {
+ swap(keys, vals, m2, m3);
+ if (keys[m1] > keys[m1]) {
+ swap(keys, vals, m1, m2);
+ }
+ }
+ }
+ }
+
+ // Move pivot to the front.
+ double pivotkey = keys[m3];
+ int pivotval = vals[m3];
+ keys[m3] = keys[start];
+ vals[m3] = vals[start];
+
+ // The interval to pivotize
+ int left = start + 1;
+ int right = end - 1;
+
+ // This is the classic QuickSort loop:
+ while (true) {
+ while (left <= right && keys[left] <= pivotkey) {
+ left++;
+ }
+ while (left <= right && pivotkey <= keys[right]) {
+ right--;
+ }
+ if (right <= left) {
+ break;
+ }
+ swap(keys, vals, left, right);
+ left++;
+ right--;
+ }
+
+ // Move pivot back into the appropriate place
+ keys[start] = keys[right];
+ vals[start] = vals[right];
+ keys[right] = pivotkey;
+ vals[right] = pivotval;
+
+ // Recursion:
+ if (start + 1 < right) {
+ quickSort(keys, vals, start, right);
+ }
+ if (right + 2 < end) {
+ quickSort(keys, vals, right + 1, end);
+ }
+ }
+
+ /**
+ * Swap two entries.
+ *
+ * @param keys Keys
+ * @param vals Values
+ * @param j First index
+ * @param i Second index
+ */
+ private static void swap(double[] keys, int[] vals, int j, int i) {
+ double td = keys[j];
+ keys[j] = keys[i];
+ keys[i] = td;
+ int ti = vals[j];
+ vals[j] = vals[i];
+ vals[i] = ti;
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/InspectionUtilFrequentlyScanned.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerArrayDBIDs.java
index 11ea1da8..61a12b3f 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/InspectionUtilFrequentlyScanned.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerArrayDBIDs.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.utilities;
+package de.lmu.ifi.dbs.elki.database.ids.integer;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,13 +23,14 @@ package de.lmu.ifi.dbs.elki.utilities;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs;
/**
- * Marker interface for classes that are frequently scanned for by the UI
- * (i.e. InspectionUtil) The classes will therefore be cached.
+ * Trivial combination interface.
*
* @author Erich Schubert
*/
-public interface InspectionUtilFrequentlyScanned {
- // empty
-} \ No newline at end of file
+public interface IntegerArrayDBIDs extends IntegerDBIDs, ArrayDBIDs {
+ @Override
+ IntegerDBIDArrayIter iter();
+}
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerArrayStaticDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerArrayStaticDBIDs.java
index 4bafd343..9e18631b 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerArrayStaticDBIDs.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerArrayStaticDBIDs.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,9 +29,8 @@ import de.lmu.ifi.dbs.elki.database.ids.ArrayStaticDBIDs;
* Combination of {@link ArrayStaticDBIDs} and {@link IntegerDBIDs}.
*
* @author Erich Schubert
- *
*/
-public interface IntegerArrayStaticDBIDs extends ArrayStaticDBIDs, IntegerDBIDs {
+public interface IntegerArrayStaticDBIDs extends ArrayStaticDBIDs, IntegerArrayDBIDs {
@Override
IntegerDBIDArrayIter iter();
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBID.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBID.java
index 91c00939..40243695 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBID.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBID.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -133,7 +133,7 @@ final class IntegerDBID implements DBID, IntegerDBIDRef {
}
@Override
- public void assign(int index, DBIDVar var) {
+ public void assignVar(int index, DBIDVar var) {
if (index != 0) {
throw new ArrayIndexOutOfBoundsException();
}
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDArrayIter.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDArrayIter.java
index b0e2d339..c604ac71 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDArrayIter.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDArrayIter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDArrayMIter.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDArrayMIter.java
index 21616f75..dcead6bd 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDArrayMIter.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDArrayMIter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDArrayQuickSort.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDArrayQuickSort.java
index 2c096ab9..90a97609 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDArrayQuickSort.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDArrayQuickSort.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDIter.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDIter.java
index 9b50d544..cc241475 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDIter.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDIter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDMIter.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDMIter.java
index 2e339dbc..c0291d5b 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDMIter.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDMIter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDPair.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDPair.java
index e716f5b5..1b1ab154 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDPair.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDPair.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDRange.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDRange.java
index 85c47f43..3ceb163d 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDRange.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDRange.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -189,7 +189,7 @@ class IntegerDBIDRange implements DBIDRange {
}
@Override
- public void assign(int index, DBIDVar var) {
+ public void assignVar(int index, DBIDVar var) {
if (var instanceof IntegerDBIDVar) {
((IntegerDBIDVar)var).internalSetIndex(start + index);
} else {
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDRef.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDRef.java
index 45854440..dc63b117 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDRef.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDRef.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDVar.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDVar.java
index 73d164e0..57d400df 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDVar.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDVar.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,7 +24,6 @@ package de.lmu.ifi.dbs.elki.database.ids.integer;
*/
import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDArrayIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
import de.lmu.ifi.dbs.elki.database.ids.DBIDVar;
import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
@@ -38,7 +37,7 @@ import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
*
* @author Erich Schubert
*/
-class IntegerDBIDVar implements DBIDVar {
+class IntegerDBIDVar implements DBIDVar, IntegerDBIDs {
/**
* The actual value.
*/
@@ -88,7 +87,7 @@ class IntegerDBIDVar implements DBIDVar {
}
@Override
- public DBIDArrayIter iter() {
+ public IntegerDBIDArrayIter iter() {
return new DBIDItr();
}
@@ -115,7 +114,7 @@ class IntegerDBIDVar implements DBIDVar {
*
* @apiviz.exclude
*/
- protected class DBIDItr implements DBIDArrayIter, IntegerDBIDRef {
+ protected class DBIDItr implements IntegerDBIDArrayIter, IntegerDBIDRef {
/**
* Iterator position: We use an integer so we can support retract().
*/
@@ -182,15 +181,15 @@ class IntegerDBIDVar implements DBIDVar {
}
@Override
- public void assign(int i, DBIDVar var) {
+ public void assignVar(int i, DBIDVar var) {
if (var instanceof IntegerDBIDVar) {
- ((IntegerDBIDVar)var).internalSetIndex(i);
+ ((IntegerDBIDVar) var).internalSetIndex(i);
} else {
// Much less efficient:
var.set(get(i));
}
}
-
+
@Override
public String toString() {
return Integer.toString(id);
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDs.java
index 8ffb9c6b..4acf91e6 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDs.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDs.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDoubleDBIDPair.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDoubleDBIDPair.java
index fe8c6a60..b522ffb2 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDoubleDBIDPair.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDoubleDBIDPair.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/ReusingDBIDFactory.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/ReusingDBIDFactory.java
index f6df2e0d..ebb36f22 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/ReusingDBIDFactory.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/ReusingDBIDFactory.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -33,14 +33,15 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
import de.lmu.ifi.dbs.elki.logging.Logging;
/**
- * Slightly more advanced DBID management, that allows reuse of DBIDs.
+ * Slightly more complex DBID management, that allows reuse of DBIDs.
+ *
+ * NOT tested a lot yet. Not reusing is much simpler!
+ *
+ * TODO: manage fragmentation of ranges?
*
* @author Erich Schubert
*
* @apiviz.stereotype factory
- * @apiviz.uses IntegerDBID oneway - - «create»
- * @apiviz.uses IntegerDBIDPair oneway - - «create»
- * @apiviz.uses IntegerDBIDRange oneway - - «create»
*/
public class ReusingDBIDFactory extends SimpleDBIDFactory {
/**
@@ -64,7 +65,7 @@ public class ReusingDBIDFactory extends SimpleDBIDFactory {
/**
* Returned range allocations
*/
- ArrayList<IntegerDBIDRange> returnedAllocations = new ArrayList<IntegerDBIDRange>();
+ ArrayList<IntegerDBIDRange> returnedAllocations = new ArrayList<>();
/**
* Constructor
@@ -115,7 +116,6 @@ public class ReusingDBIDFactory extends SimpleDBIDFactory {
@Override
public synchronized void deallocateDBIDRange(DBIDRange range) {
- // TODO: catch an eventual cast exception?
returnedAllocations.add((IntegerDBIDRange) range);
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/SimpleDBIDFactory.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/SimpleDBIDFactory.java
index 77c1a91b..c3abd43a 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/SimpleDBIDFactory.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/SimpleDBIDFactory.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,22 +23,9 @@ package de.lmu.ifi.dbs.elki.database.ids.integer;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDFactory;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDPair;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRange;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDVar;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
-import de.lmu.ifi.dbs.elki.database.ids.DistanceDBIDPair;
-import de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDPair;
-import de.lmu.ifi.dbs.elki.database.ids.DoubleDistanceDBIDPair;
-import de.lmu.ifi.dbs.elki.database.ids.HashSetModifiableDBIDs;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
-import de.lmu.ifi.dbs.elki.persistent.ByteBufferSerializer;
-import de.lmu.ifi.dbs.elki.persistent.FixedSizeByteBufferSerializer;
import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
/**
@@ -50,13 +37,8 @@ import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
*
* @apiviz.landmark
* @apiviz.stereotype factory
- * @apiviz.uses IntegerDBID oneway - - «create»
- * @apiviz.uses IntegerDBIDPair oneway - - «create»
- * @apiviz.uses IntegerDBIDRange oneway - - «create»
- * @apiviz.uses TroveArrayModifiableDBIDs oneway - - «create»
- * @apiviz.uses TroveHashSetModifiableDBIDs oneway - - «create»
*/
-public class SimpleDBIDFactory implements DBIDFactory {
+public class SimpleDBIDFactory extends AbstractIntegerDBIDFactory {
/**
* Keep track of the smallest dynamic DBID offset not used.
*/
@@ -68,11 +50,6 @@ public class SimpleDBIDFactory implements DBIDFactory {
int rangestart = 0;
/**
- * Invalid ID.
- */
- DBID invalid = new IntegerDBID(Integer.MIN_VALUE);
-
- /**
* Constructor.
*/
public SimpleDBIDFactory() {
@@ -81,10 +58,10 @@ public class SimpleDBIDFactory implements DBIDFactory {
@Override
public synchronized DBID generateSingleDBID() {
+ dynamicids--;
if(dynamicids == Integer.MIN_VALUE) {
throw new AbortException("DBID range allocation error - too many objects allocated!");
}
- dynamicids--;
return new IntegerDBID(dynamicids);
}
@@ -107,114 +84,4 @@ public class SimpleDBIDFactory implements DBIDFactory {
public void deallocateDBIDRange(DBIDRange range) {
// ignore.
}
-
- @Override
- public DBID importInteger(int id) {
- return new IntegerDBID(id);
- }
-
- @Override
- public void assignVar(DBIDVar var, int val) {
- if (var instanceof IntegerDBIDVar) {
- ((IntegerDBIDVar)var).internalSetIndex(val);
- } else {
- var.set(new IntegerDBID(val));
- }
- }
-
- @Override
- public int compare(DBIDRef a, DBIDRef b) {
- final int inta = a.internalGetIndex();
- final int intb = b.internalGetIndex();
- return (inta < intb ? -1 : (inta == intb ? 0 : 1));
- }
-
- @Override
- public boolean equal(DBIDRef a, DBIDRef b) {
- return a.internalGetIndex() == b.internalGetIndex();
- }
-
- @Override
- public String toString(DBIDRef id) {
- return Integer.toString(id.internalGetIndex());
- }
-
- @Override
- public DBIDVar newVar(DBIDRef val) {
- return new IntegerDBIDVar(val);
- }
-
- @Override
- public ArrayModifiableDBIDs newArray() {
- return new TroveArrayModifiableDBIDs();
- }
-
- @Override
- public HashSetModifiableDBIDs newHashSet() {
- return new TroveHashSetModifiableDBIDs();
- }
-
- @Override
- public ArrayModifiableDBIDs newArray(int size) {
- return new TroveArrayModifiableDBIDs(size);
- }
-
- @Override
- public HashSetModifiableDBIDs newHashSet(int size) {
- return new TroveHashSetModifiableDBIDs(size);
- }
-
- @Override
- public ArrayModifiableDBIDs newArray(DBIDs existing) {
- return new TroveArrayModifiableDBIDs(existing);
- }
-
- @Override
- public HashSetModifiableDBIDs newHashSet(DBIDs existing) {
- return new TroveHashSetModifiableDBIDs(existing);
- }
-
- @Override
- public DBIDPair newPair(DBIDRef first, DBIDRef second) {
- return new IntegerDBIDPair(first.internalGetIndex(), second.internalGetIndex());
- }
-
- @Override
- public DoubleDBIDPair newPair(double val, DBIDRef id) {
- return new IntegerDoubleDBIDPair(val, id.internalGetIndex());
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public <D extends Distance<D>> DistanceDBIDPair<D> newDistancePair(D val, DBIDRef id) {
- if (val instanceof DoubleDistance) {
- return (DistanceDBIDPair<D>) new DoubleDistanceIntegerDBIDPair(((DoubleDistance) val).doubleValue(), id.internalGetIndex());
- }
- return new DistanceIntegerDBIDPair<D>(val, id.internalGetIndex());
- }
-
- @Override
- public DoubleDistanceDBIDPair newDistancePair(double val, DBIDRef id) {
- return new DoubleDistanceIntegerDBIDPair(val, id.internalGetIndex());
- }
-
- @Override
- public ByteBufferSerializer<DBID> getDBIDSerializer() {
- return IntegerDBID.DYNAMIC_SERIALIZER;
- }
-
- @Override
- public FixedSizeByteBufferSerializer<DBID> getDBIDSerializerStatic() {
- return IntegerDBID.STATIC_SERIALIZER;
- }
-
- @Override
- public Class<? extends DBID> getTypeRestriction() {
- return IntegerDBID.class;
- }
-
- @Override
- public DBIDRef invalid() {
- return invalid;
- }
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/TrivialDBIDFactory.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/TrivialDBIDFactory.java
index a9d8aa90..577c29ac 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/TrivialDBIDFactory.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/TrivialDBIDFactory.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,51 +25,27 @@ package de.lmu.ifi.dbs.elki.database.ids.integer;
import java.util.concurrent.atomic.AtomicInteger;
-import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDFactory;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDPair;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRange;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDVar;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
-import de.lmu.ifi.dbs.elki.database.ids.DistanceDBIDPair;
-import de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDPair;
-import de.lmu.ifi.dbs.elki.database.ids.DoubleDistanceDBIDPair;
-import de.lmu.ifi.dbs.elki.database.ids.HashSetModifiableDBIDs;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
-import de.lmu.ifi.dbs.elki.persistent.ByteBufferSerializer;
-import de.lmu.ifi.dbs.elki.persistent.FixedSizeByteBufferSerializer;
import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
/**
* Trivial DBID management, that never reuses IDs and just gives them out in
- * sequence. Statically allocated DBID ranges are given positive values,
- * Dynamically allocated DBIDs are given negative values.
+ * sequence. All IDs will be positive.
*
* @author Erich Schubert
*
* @apiviz.landmark
* @apiviz.stereotype factory
- * @apiviz.uses IntegerDBID oneway - - «create»
- * @apiviz.uses IntegerDBIDPair oneway - - «create»
- * @apiviz.uses IntegerDBIDRange oneway - - «create»
- * @apiviz.uses TroveArrayModifiableDBIDs oneway - - «create»
- * @apiviz.uses TroveHashSetModifiableDBIDs oneway - - «create»
*/
-final public class TrivialDBIDFactory implements DBIDFactory {
+final public class TrivialDBIDFactory extends AbstractIntegerDBIDFactory {
/**
* Keep track of the smallest dynamic DBID offset not used.
*/
AtomicInteger next = new AtomicInteger(1);
/**
- * Invalid ID.
- */
- DBID invalid = new IntegerDBID(Integer.MIN_VALUE);
-
- /**
* Constructor.
*/
public TrivialDBIDFactory() {
@@ -105,114 +81,4 @@ final public class TrivialDBIDFactory implements DBIDFactory {
public void deallocateDBIDRange(DBIDRange range) {
// ignore.
}
-
- @Override
- public DBID importInteger(int id) {
- return new IntegerDBID(id);
- }
-
- @Override
- public void assignVar(DBIDVar var, int val) {
- if (var instanceof IntegerDBIDVar) {
- ((IntegerDBIDVar)var).internalSetIndex(val);
- } else {
- var.set(new IntegerDBID(val));
- }
- }
-
- @Override
- public int compare(DBIDRef a, DBIDRef b) {
- final int inta = a.internalGetIndex();
- final int intb = b.internalGetIndex();
- return (inta < intb ? -1 : (inta == intb ? 0 : 1));
- }
-
- @Override
- public boolean equal(DBIDRef a, DBIDRef b) {
- return a.internalGetIndex() == b.internalGetIndex();
- }
-
- @Override
- public String toString(DBIDRef id) {
- return Integer.toString(id.internalGetIndex());
- }
-
- @Override
- public DBIDVar newVar(DBIDRef val) {
- return new IntegerDBIDVar(val);
- }
-
- @Override
- public ArrayModifiableDBIDs newArray() {
- return new TroveArrayModifiableDBIDs();
- }
-
- @Override
- public HashSetModifiableDBIDs newHashSet() {
- return new TroveHashSetModifiableDBIDs();
- }
-
- @Override
- public ArrayModifiableDBIDs newArray(int size) {
- return new TroveArrayModifiableDBIDs(size);
- }
-
- @Override
- public HashSetModifiableDBIDs newHashSet(int size) {
- return new TroveHashSetModifiableDBIDs(size);
- }
-
- @Override
- public ArrayModifiableDBIDs newArray(DBIDs existing) {
- return new TroveArrayModifiableDBIDs(existing);
- }
-
- @Override
- public HashSetModifiableDBIDs newHashSet(DBIDs existing) {
- return new TroveHashSetModifiableDBIDs(existing);
- }
-
- @Override
- public DBIDPair newPair(DBIDRef first, DBIDRef second) {
- return new IntegerDBIDPair(first.internalGetIndex(), second.internalGetIndex());
- }
-
- @Override
- public DoubleDBIDPair newPair(double val, DBIDRef id) {
- return new IntegerDoubleDBIDPair(val, id.internalGetIndex());
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public <D extends Distance<D>> DistanceDBIDPair<D> newDistancePair(D val, DBIDRef id) {
- if (val instanceof DoubleDistance) {
- return (DistanceDBIDPair<D>) new DoubleDistanceIntegerDBIDPair(((DoubleDistance) val).doubleValue(), id.internalGetIndex());
- }
- return new DistanceIntegerDBIDPair<D>(val, id.internalGetIndex());
- }
-
- @Override
- public DoubleDistanceDBIDPair newDistancePair(double val, DBIDRef id) {
- return new DoubleDistanceIntegerDBIDPair(val, id.internalGetIndex());
- }
-
- @Override
- public ByteBufferSerializer<DBID> getDBIDSerializer() {
- return IntegerDBID.DYNAMIC_SERIALIZER;
- }
-
- @Override
- public FixedSizeByteBufferSerializer<DBID> getDBIDSerializerStatic() {
- return IntegerDBID.STATIC_SERIALIZER;
- }
-
- @Override
- public Class<? extends DBID> getTypeRestriction() {
- return IntegerDBID.class;
- }
-
- @Override
- public DBIDRef invalid() {
- return invalid;
- }
}
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveArrayDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveArrayDBIDs.java
index 313a0f3b..6980176a 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveArrayDBIDs.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveArrayDBIDs.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,7 +24,6 @@ package de.lmu.ifi.dbs.elki.database.ids.integer;
*/
import gnu.trove.list.TIntList;
-import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
@@ -40,7 +39,7 @@ import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
* @apiviz.has IntegerDBID
* @apiviz.has DBIDItr
*/
-public abstract class TroveArrayDBIDs implements ArrayDBIDs, IntegerDBIDs {
+public abstract class TroveArrayDBIDs implements IntegerArrayDBIDs {
/**
* Get the array store.
*
@@ -59,7 +58,7 @@ public abstract class TroveArrayDBIDs implements ArrayDBIDs, IntegerDBIDs {
}
@Override
- public void assign(int index, DBIDVar var) {
+ public void assignVar(int index, DBIDVar var) {
if (var instanceof IntegerDBIDVar) {
((IntegerDBIDVar)var).internalSetIndex(getStore().get(index));
} else {
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveArrayModifiableDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveArrayModifiableDBIDs.java
index 7e84eb56..41191b10 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveArrayModifiableDBIDs.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveArrayModifiableDBIDs.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -81,6 +81,7 @@ class TroveArrayModifiableDBIDs extends TroveArrayDBIDs implements ArrayModifiab
@Override
public boolean addDBIDs(DBIDs ids) {
boolean success = false;
+ store.ensureCapacity(ids.size());
for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
success |= store.add(DBIDUtil.asInteger(iter));
}
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveHashSetModifiableDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveHashSetModifiableDBIDs.java
index 9e65b3ae..9ebdccea 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveHashSetModifiableDBIDs.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveHashSetModifiableDBIDs.java
@@ -9,13 +9,13 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.ids.HashSetModifiableDBIDs;
-import de.lmu.ifi.dbs.elki.utilities.iterator.Iter;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.iterator.Iter;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -83,6 +83,7 @@ class TroveHashSetModifiableDBIDs implements HashSetModifiableDBIDs, IntegerDBID
@Override
public boolean addDBIDs(DBIDs ids) {
+ store.ensureCapacity(ids.size());
boolean success = false;
for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
success |= store.add(DBIDUtil.asInteger(iter));
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/UnmodifiableIntegerArrayDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/UnmodifiableIntegerArrayDBIDs.java
index 14e26748..ba30f54f 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/UnmodifiableIntegerArrayDBIDs.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/UnmodifiableIntegerArrayDBIDs.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -40,14 +40,14 @@ public class UnmodifiableIntegerArrayDBIDs implements IntegerArrayStaticDBIDs {
/**
* The DBIDs we wrap.
*/
- private final TroveArrayDBIDs inner;
+ private final IntegerArrayDBIDs inner;
/**
* Constructor.
*
* @param inner Inner DBID collection.
*/
- public UnmodifiableIntegerArrayDBIDs(TroveArrayDBIDs inner) {
+ public UnmodifiableIntegerArrayDBIDs(IntegerArrayDBIDs inner) {
super();
this.inner = inner;
}
@@ -87,8 +87,8 @@ public class UnmodifiableIntegerArrayDBIDs implements IntegerArrayStaticDBIDs {
}
@Override
- public void assign(int index, DBIDVar var) {
- inner.assign(index, var);
+ public void assignVar(int index, DBIDVar var) {
+ inner.assignVar(index, var);
}
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/UnmodifiableIntegerDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/UnmodifiableIntegerDBIDs.java
index 1d27f530..a3f03bd9 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/UnmodifiableIntegerDBIDs.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/UnmodifiableIntegerDBIDs.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/package-info.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/package-info.java
index 2508c930..74a39fb9 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/package-info.java
@@ -10,7 +10,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/package-info.java b/src/de/lmu/ifi/dbs/elki/database/ids/package-info.java
index 71af955c..eb0a6733 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/package-info.java
@@ -83,7 +83,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/package-info.java b/src/de/lmu/ifi/dbs/elki/database/package-info.java
index 73cf0596..0b5d16ea 100644
--- a/src/de/lmu/ifi/dbs/elki/database/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/database/package-info.java
@@ -9,7 +9,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/AbstractDataBasedQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/AbstractDataBasedQuery.java
index d9accf4f..5d0e8444 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/AbstractDataBasedQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/AbstractDataBasedQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/DatabaseQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/DatabaseQuery.java
index 28c89ee3..caba81e3 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/DatabaseQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/DatabaseQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/DistanceSimilarityQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/DistanceSimilarityQuery.java
index 9b9367fb..8906e07c 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/DistanceSimilarityQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/DistanceSimilarityQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/LinearScanQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/LinearScanQuery.java
index 4cace1cf..6cb35025 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/LinearScanQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/LinearScanQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/distance/AbstractDatabaseDistanceQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/distance/AbstractDatabaseDistanceQuery.java
index ed1ee50c..f530b72a 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/distance/AbstractDatabaseDistanceQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/distance/AbstractDatabaseDistanceQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.distance;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/distance/AbstractDistanceQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/distance/AbstractDistanceQuery.java
index b85ddef0..933bd0d3 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/distance/AbstractDistanceQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/distance/AbstractDistanceQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.distance;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/distance/DBIDDistanceQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/distance/DBIDDistanceQuery.java
index 28ca9b16..e619bc57 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/distance/DBIDDistanceQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/distance/DBIDDistanceQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.distance;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/distance/DistanceQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/distance/DistanceQuery.java
index c026162d..12e76ace 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/distance/DistanceQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/distance/DistanceQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.distance;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/distance/PrimitiveDistanceQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/distance/PrimitiveDistanceQuery.java
index 75bd9e39..ab3046ed 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/distance/PrimitiveDistanceQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/distance/PrimitiveDistanceQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.distance;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/distance/PrimitiveDistanceSimilarityQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/distance/PrimitiveDistanceSimilarityQuery.java
index 930d195c..5ca62a73 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/distance/PrimitiveDistanceSimilarityQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/distance/PrimitiveDistanceSimilarityQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.distance;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/distance/SpatialDistanceQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/distance/SpatialDistanceQuery.java
index 59f6534b..14839dd7 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/distance/SpatialDistanceQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/distance/SpatialDistanceQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.distance;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/distance/SpatialPrimitiveDistanceQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/distance/SpatialPrimitiveDistanceQuery.java
index 550c2c5c..c5a601bd 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/distance/SpatialPrimitiveDistanceQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/distance/SpatialPrimitiveDistanceQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.distance;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/distance/package-info.java b/src/de/lmu/ifi/dbs/elki/database/query/distance/package-info.java
index fdd116b7..97bc471d 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/distance/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/distance/package-info.java
@@ -7,7 +7,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/knn/AbstractDistanceKNNQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/knn/AbstractDistanceKNNQuery.java
index 0ac2e8ee..f9f7d018 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/knn/AbstractDistanceKNNQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/knn/AbstractDistanceKNNQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.knn;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,10 +23,15 @@ package de.lmu.ifi.dbs.elki.database.query.knn;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import java.util.ArrayList;
+import java.util.List;
+
+import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.AbstractDataBasedQuery;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
/**
@@ -51,8 +56,22 @@ public abstract class AbstractDistanceKNNQuery<O, D extends Distance<D>> extends
}
@Override
- abstract public KNNResult<D> getKNNForDBID(DBIDRef id, int k);
+ public List<? extends KNNList<D>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) {
+ // throw new
+ // UnsupportedOperationException(ExceptionMessages.UNSUPPORTED_NOT_YET);
+ // TODO: optimize
+ List<KNNList<D>> ret = new ArrayList<>(ids.size());
+ for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
+ ret.add(getKNNForDBID(iter, k));
+ }
+ return ret;
+ }
+
+ @Override
+ public KNNList<D> getKNNForDBID(DBIDRef id, int k) {
+ return getKNNForObject(relation.get(id), k);
+ }
@Override
- abstract public KNNResult<D> getKNNForObject(O obj, int k);
-} \ No newline at end of file
+ abstract public KNNList<D> getKNNForObject(O obj, int k);
+}
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/knn/DoubleOptimizedKNNQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/knn/DoubleOptimizedKNNQuery.java
new file mode 100644
index 00000000..b18db8f0
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/database/query/knn/DoubleOptimizedKNNQuery.java
@@ -0,0 +1,309 @@
+package de.lmu.ifi.dbs.elki.database.query.knn;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.ArrayList;
+
+import de.lmu.ifi.dbs.elki.database.ids.DBIDFactory;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNHeap;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
+import de.lmu.ifi.dbs.elki.database.ids.generic.DistanceDBIDPairKNNList;
+import de.lmu.ifi.dbs.elki.database.ids.generic.DoubleDistanceDBIDPairKNNHeap;
+import de.lmu.ifi.dbs.elki.database.ids.generic.DoubleDistanceDBIDPairKNNList;
+import de.lmu.ifi.dbs.elki.database.ids.integer.DoubleDistanceIntegerDBIDKNNList;
+import de.lmu.ifi.dbs.elki.database.ids.integer.DoubleDistanceIntegerDBIDKNNListHeap;
+import de.lmu.ifi.dbs.elki.database.query.distance.PrimitiveDistanceQuery;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultUtil;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.Heap;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.TiedTopBoundedHeap;
+
+/**
+ * Optimized linear scan query for {@link PrimitiveDoubleDistanceFunction}s.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.uses PrimitiveDoubleDistanceFunction
+ *
+ * @param <O> Object type
+ */
+public class DoubleOptimizedKNNQuery<O> extends LinearScanKNNQuery<O, DoubleDistance> {
+ /**
+ * Raw distance function.
+ */
+ PrimitiveDoubleDistanceFunction<O> rawdist;
+
+ /**
+ * Constructor.
+ *
+ * @param distanceQuery Distance function to use
+ */
+ @SuppressWarnings("unchecked")
+ public DoubleOptimizedKNNQuery(PrimitiveDistanceQuery<O, DoubleDistance> distanceQuery) {
+ super(distanceQuery);
+ if(!(distanceQuery.getDistanceFunction() instanceof PrimitiveDoubleDistanceFunction)) {
+ throw new UnsupportedOperationException("DoubleOptimizedKNNQuery instantiated for non-PrimitiveDoubleDistanceFunction!");
+ }
+ rawdist = (PrimitiveDoubleDistanceFunction<O>) distanceQuery.getDistanceFunction();
+ }
+
+ @Override
+ public KNNList<DoubleDistance> getKNNForDBID(DBIDRef id, int k) {
+ return getKNNForObject(relation.get(id), k);
+ }
+
+ @Override
+ public KNNList<DoubleDistance> getKNNForObject(O obj, int k) {
+ return getKNNForObjectBenchmarked(obj, k);
+ }
+
+ /**
+ * This is the straightforward implementation using the optimized heap.
+ *
+ * @param obj Query object
+ * @param k Desired number of neighbors
+ * @return kNN result
+ */
+ KNNList<DoubleDistance> getKNNForObjectKNNHeap(O obj, int k) {
+ // Optimization for double distances.
+ final DoubleDistanceKNNHeap heap = (DoubleDistanceKNNHeap) DBIDUtil.newHeap(DoubleDistance.FACTORY, k);
+ for(DBIDIter iter = relation.iterDBIDs(); iter.valid(); iter.advance()) {
+ heap.add(rawdist.doubleDistance(obj, relation.get(iter)), iter);
+ }
+ return heap.toKNNList();
+ }
+
+ /**
+ * This is the cleaner, supposedly faster implementation.
+ *
+ * @param obj Query object
+ * @param k Desired number of neighbors
+ * @return kNN result
+ */
+ KNNList<DoubleDistance> getKNNForObjectClean(O obj, int k) {
+ // Optimization for double distances.
+ final TiedTopBoundedHeap<DoubleDistanceDBIDPair> heap = new TiedTopBoundedHeap<>(k, DoubleDistanceDBIDPairKNNHeap.COMPARATOR);
+ final DBIDIter iter = relation.iterDBIDs();
+
+ // First k elements don't need checking.
+ double max = 0.;
+ for(int i = 0; i < k && iter.valid(); i++, iter.advance()) {
+ final double doubleDistance = rawdist.doubleDistance(obj, relation.get(iter));
+ heap.add(DBIDFactory.FACTORY.newDistancePair(doubleDistance, iter));
+ max = Math.max(max, doubleDistance);
+ }
+ // Remaining elements
+ for(; iter.valid(); iter.advance()) {
+ final double doubleDistance = rawdist.doubleDistance(obj, relation.get(iter));
+ if(doubleDistance <= max) {
+ heap.add(DBIDFactory.FACTORY.newDistancePair(doubleDistance, iter));
+ }
+ if(doubleDistance < max) {
+ max = heap.peek().doubleDistance();
+ }
+ }
+ return new DoubleDistanceDBIDPairKNNList(heap, k);
+ }
+
+ /**
+ * It does not make sense, but this version is faster in our larger
+ * benchmarks. Apparently, some JIT optimization kicks in better.
+ *
+ * @param obj Query object
+ * @param k Desired number of neighbors
+ * @return kNN result
+ */
+ KNNList<DoubleDistance> getKNNForObjectBenchmarked(O obj, int k) {
+ // THIS SHOULD BE SLOWER THAN THE VERSION ABOVE, BUT ISN'T!
+ final TiedTopBoundedHeap<DistanceDBIDPair<DoubleDistance>> heap = new TiedTopBoundedHeap<>(k, DistanceDBIDResultUtil.BY_REVERSE_DISTANCE);
+ final DBIDIter iter = relation.iterDBIDs();
+ // First k elements don't need checking.
+ double max = 0.;
+ for(int i = 0; i < k && iter.valid(); i++, iter.advance()) {
+ final double doubleDistance = rawdist.doubleDistance(obj, relation.get(iter));
+ heap.add(DBIDFactory.FACTORY.newDistancePair(new DoubleDistance(doubleDistance), iter));
+ max = Math.max(max, doubleDistance);
+ }
+ // Remaining elements
+ for(; iter.valid(); iter.advance()) {
+ final double doubleDistance = rawdist.doubleDistance(obj, relation.get(iter));
+ if(doubleDistance <= max) {
+ heap.add(DBIDFactory.FACTORY.newDistancePair(new DoubleDistance(doubleDistance), iter));
+ }
+ if(doubleDistance < max) {
+ max = heap.peek().getDistance().doubleValue();
+ }
+ }
+ return new DistanceDBIDPairKNNList<>(heap, k);
+ }
+
+ /**
+ * Another attempt at getting a faster knn heap.
+ *
+ * @param obj Query object
+ * @param k Desired number of neighbors
+ * @return kNN result
+ */
+ KNNList<DoubleDistance> getKNNForObjectBenchmarked2(O obj, int k) {
+ final Heap<DoubleDistanceDBIDPair> heap = new Heap<>(k, DistanceDBIDResultUtil.BY_REVERSE_DISTANCE);
+ final ArrayList<DoubleDistanceDBIDPair> ties = new ArrayList<>();
+ final DBIDIter iter = relation.iterDBIDs();
+ // First k elements don't need checking.
+ double max = 0.;
+ for(int i = 0; i < k && iter.valid(); i++, iter.advance()) {
+ final double doubleDistance = rawdist.distance(obj, relation.get(iter)).doubleValue();
+ heap.add(DBIDFactory.FACTORY.newDistancePair(doubleDistance, iter));
+ max = Math.max(max, doubleDistance);
+ }
+ // Remaining elements
+ for(; iter.valid(); iter.advance()) {
+ final double doubleDistance = rawdist.distance(obj, relation.get(iter)).doubleValue();
+ if(doubleDistance <= max) {
+ if(doubleDistance < max) {
+ DoubleDistanceDBIDPair prev = heap.replaceTopElement(DBIDFactory.FACTORY.newDistancePair(doubleDistance, iter));
+ double newkdist = heap.peek().doubleDistance();
+ if(newkdist < max) {
+ max = newkdist;
+ ties.clear();
+ }
+ else {
+ ties.add(prev);
+ }
+ }
+ else {
+ ties.add(DBIDFactory.FACTORY.newDistancePair(doubleDistance, iter));
+ }
+ }
+ }
+
+ DoubleDistanceIntegerDBIDKNNList ret = new DoubleDistanceIntegerDBIDKNNList(k, k + ties.size());
+ for(DoubleDistanceDBIDPair pair : ties) {
+ ret.add(pair);
+ }
+ while(!heap.isEmpty()) {
+ ret.add(heap.poll());
+ }
+ ret.sort(); // Actually, reverse.
+ return ret;
+ }
+
+ /**
+ * Next attempt at exploiting the JIT fully.
+ *
+ * @param obj Query object
+ * @param k Desired number of neighbors
+ * @return kNN result
+ */
+ KNNList<DoubleDistance> getKNNForObjectBenchmarked3(O obj, int k) {
+ DoubleDistanceKNNHeap heap = new DoubleDistanceIntegerDBIDKNNListHeap(k);
+ final DBIDIter iter = relation.iterDBIDs();
+ // First k elements don't need checking.
+ double max = 0.;
+ for(int i = 0; i < k && iter.valid(); i++, iter.advance()) {
+ final double doubleDistance = rawdist.doubleDistance(obj, relation.get(iter));
+ heap.add(doubleDistance, iter);
+ max = Math.max(max, doubleDistance);
+ }
+ // Remaining elements
+ for(; iter.valid(); iter.advance()) {
+ final double doubleDistance = rawdist.doubleDistance(obj, relation.get(iter));
+ if(doubleDistance <= max) {
+ heap.add(doubleDistance, iter);
+ }
+ if(doubleDistance < max) {
+ max = heap.peek().doubleDistance();
+ }
+ }
+ return heap.toKNNList();
+ }
+
+ /**
+ * Next attempt at exploiting the JIT fully.
+ *
+ * @param obj Query object
+ * @param k Desired number of neighbors
+ * @return kNN result
+ */
+ KNNList<DoubleDistance> getKNNForObjectBenchmarked4(O obj, int k) {
+ DoubleDistanceKNNHeap heap = new DoubleDistanceIntegerDBIDKNNListHeap(k);
+ final DBIDIter iter = relation.iterDBIDs();
+ // First k elements don't need checking.
+ for(int i = 0; i < k && iter.valid(); i++, iter.advance()) {
+ final double doubleDistance = rawdist.doubleDistance(obj, relation.get(iter));
+ heap.add(doubleDistance, iter);
+ }
+ double max = heap.doubleKNNDistance();
+ // Remaining elements
+ for(; iter.valid(); iter.advance()) {
+ final double doubleDistance = rawdist.doubleDistance(obj, relation.get(iter));
+ if(doubleDistance <= max) {
+ heap.add(doubleDistance, iter);
+ max = heap.doubleKNNDistance();
+ }
+ }
+ return heap.toKNNList();
+ }
+
+ /**
+ * Next attempt at exploiting the JIT fully.
+ *
+ * @param obj Query object
+ * @param k Desired number of neighbors
+ * @return kNN result
+ */
+ KNNList<DoubleDistance> getKNNForObjectBenchmarked5(O obj, int k) {
+ DoubleDistanceKNNHeap heap = new DoubleDistanceIntegerDBIDKNNListHeap(k);
+ double max = Double.POSITIVE_INFINITY;
+ for(DBIDIter iter = relation.iterDBIDs(); iter.valid(); iter.advance()) {
+ final double distance = rawdist.doubleDistance(obj, relation.get(iter));
+ if(distance <= max) {
+ heap.add(distance, iter);
+ max = heap.doubleKNNDistance();
+ }
+ }
+ return heap.toKNNList();
+ }
+
+ /**
+ * Next attempt at exploiting the JIT fully.
+ *
+ * @param obj Query object
+ * @param k Desired number of neighbors
+ * @return kNN result
+ */
+ KNNList<DoubleDistance> getKNNForObjectBenchmarked6(O obj, int k) {
+ DoubleDistanceKNNHeap heap = new DoubleDistanceIntegerDBIDKNNListHeap(k);
+ for(DBIDIter iter = relation.iterDBIDs(); iter.valid(); iter.advance()) {
+ final double distance = rawdist.doubleDistance(obj, relation.get(iter));
+ heap.add(distance, iter);
+ }
+ return heap.toKNNList();
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/knn/KNNQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/knn/KNNQuery.java
index 5b517509..c94f3d42 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/knn/KNNQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/knn/KNNQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.knn;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,8 +27,8 @@ import java.util.List;
import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
/**
@@ -37,7 +37,7 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
* @author Erich Schubert
*
* @apiviz.landmark
- * @apiviz.has KNNResult oneway - - «create»
+ * @apiviz.has KNNList oneway - - «create»
*
* @param <O> Object type
* @param <D> Distance type
@@ -50,7 +50,7 @@ public interface KNNQuery<O, D extends Distance<D>> extends DatabaseQuery {
* @param k Number of neighbors requested
* @return neighbors
*/
- public KNNResult<D> getKNNForDBID(DBIDRef id, int k);
+ public KNNList<D> getKNNForDBID(DBIDRef id, int k);
/**
* Bulk query method
@@ -59,7 +59,7 @@ public interface KNNQuery<O, D extends Distance<D>> extends DatabaseQuery {
* @param k Number of neighbors requested
* @return neighbors
*/
- public List<? extends KNNResult<D>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k);
+ public List<? extends KNNList<D>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k);
/**
* Get the k nearest neighbors for a particular id.
@@ -68,5 +68,5 @@ public interface KNNQuery<O, D extends Distance<D>> extends DatabaseQuery {
* @param k Number of neighbors requested
* @return neighbors
*/
- public KNNResult<D> getKNNForObject(O obj, int k);
+ public KNNList<D> getKNNForObject(O obj, int k);
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/knn/LinearScanKNNQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/knn/LinearScanKNNQuery.java
index 29fa9931..485330ea 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/knn/LinearScanKNNQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/knn/LinearScanKNNQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.knn;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,12 +29,12 @@ import java.util.List;
import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNHeap;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.LinearScanQuery;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.distance.PrimitiveDistanceQuery;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNHeap;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNUtil;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
/**
@@ -63,9 +63,9 @@ public class LinearScanKNNQuery<O, D extends Distance<D>> extends AbstractDistan
*/
private void linearScanBatchKNN(ArrayDBIDs ids, List<KNNHeap<D>> heaps) {
// The distance is computed on database IDs
- for(DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) {
+ for (DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) {
int index = 0;
- for(DBIDIter iter2 = ids.iter(); iter2.valid(); iter2.advance()) {
+ for (DBIDIter iter2 = ids.iter(); iter2.valid(); iter2.advance()) {
KNNHeap<D> heap = heaps.get(index);
heap.add(distanceQuery.distance(iter2, iter), iter);
index++;
@@ -74,27 +74,26 @@ public class LinearScanKNNQuery<O, D extends Distance<D>> extends AbstractDistan
}
@Override
- public KNNResult<D> getKNNForDBID(DBIDRef id, int k) {
- KNNHeap<D> heap = KNNUtil.newHeap(distanceQuery.getDistanceFactory(), k);
+ public KNNList<D> getKNNForDBID(DBIDRef id, int k) {
+ KNNHeap<D> heap = DBIDUtil.newHeap(distanceQuery.getDistanceFactory(), k);
D max = distanceQuery.getDistanceFactory().infiniteDistance();
- if(PrimitiveDistanceQuery.class.isInstance(distanceQuery)) {
+ if (PrimitiveDistanceQuery.class.isInstance(distanceQuery)) {
O obj = relation.get(id);
- for(DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) {
+ for (DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) {
final D dist = distanceQuery.distance(obj, relation.get(iter));
- if(max.compareTo(dist) > 0) {
+ if (max.compareTo(dist) > 0) {
heap.add(dist, iter);
- if(heap.size() >= k) {
+ if (heap.size() >= k) {
max = heap.getKNNDistance();
}
}
}
- }
- else {
- for(DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) {
+ } else {
+ for (DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) {
final D dist = distanceQuery.distance(id, iter);
- if(max.compareTo(dist) > 0) {
+ if (max.compareTo(dist) > 0) {
heap.add(dist, iter);
- if(heap.size() >= k) {
+ if (heap.size() >= k) {
max = heap.getKNNDistance();
}
}
@@ -104,27 +103,27 @@ public class LinearScanKNNQuery<O, D extends Distance<D>> extends AbstractDistan
}
@Override
- public List<KNNResult<D>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) {
+ public List<KNNList<D>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) {
final int size = ids.size();
- final List<KNNHeap<D>> heaps = new ArrayList<KNNHeap<D>>(size);
- for(int i = 0; i < size; i++) {
- heaps.add(KNNUtil.newHeap(distanceQuery.getDistanceFactory(), k));
+ final List<KNNHeap<D>> heaps = new ArrayList<>(size);
+ for (int i = 0; i < size; i++) {
+ heaps.add(DBIDUtil.newHeap(distanceQuery.getDistanceFactory(), k));
}
linearScanBatchKNN(ids, heaps);
// Serialize heaps
- List<KNNResult<D>> result = new ArrayList<KNNResult<D>>(size);
- for(KNNHeap<D> heap : heaps) {
+ List<KNNList<D>> result = new ArrayList<>(size);
+ for (KNNHeap<D> heap : heaps) {
result.add(heap.toKNNList());
}
return result;
}
@Override
- public KNNResult<D> getKNNForObject(O obj, int k) {
- KNNHeap<D> heap = KNNUtil.newHeap(distanceQuery.getDistanceFactory(), k);
- for(DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) {
+ public KNNList<D> getKNNForObject(O obj, int k) {
+ KNNHeap<D> heap = DBIDUtil.newHeap(distanceQuery.getDistanceFactory(), k);
+ for (DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) {
heap.add(distanceQuery.distance(obj, iter), iter);
}
return heap.toKNNList();
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/knn/LinearScanPrimitiveDistanceKNNQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/knn/LinearScanPrimitiveDistanceKNNQuery.java
index c4f09744..3f3fbc3f 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/knn/LinearScanPrimitiveDistanceKNNQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/knn/LinearScanPrimitiveDistanceKNNQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.knn;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,10 +29,10 @@ import java.util.List;
import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNHeap;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.distance.PrimitiveDistanceQuery;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNHeap;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNUtil;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
/**
@@ -74,22 +74,22 @@ public class LinearScanPrimitiveDistanceKNNQuery<O, D extends Distance<D>> exten
}
@Override
- public KNNResult<D> getKNNForDBID(DBIDRef id, int k) {
+ public KNNList<D> getKNNForDBID(DBIDRef id, int k) {
return getKNNForObject(relation.get(id), k);
}
@Override
- public List<KNNResult<D>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) {
+ public List<KNNList<D>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) {
final int size = ids.size();
- final List<KNNHeap<D>> heaps = new ArrayList<KNNHeap<D>>(size);
- List<O> objs = new ArrayList<O>(size);
+ final List<KNNHeap<D>> heaps = new ArrayList<>(size);
+ List<O> objs = new ArrayList<>(size);
for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
- heaps.add(KNNUtil.newHeap(distanceQuery.getDistanceFactory(), k));
+ heaps.add(DBIDUtil.newHeap(distanceQuery.getDistanceFactory(), k));
objs.add(relation.get(iter));
}
linearScanBatchKNN(objs, heaps);
- List<KNNResult<D>> result = new ArrayList<KNNResult<D>>(heaps.size());
+ List<KNNList<D>> result = new ArrayList<>(heaps.size());
for(KNNHeap<D> heap : heaps) {
result.add(heap.toKNNList());
}
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/knn/LinearScanRawDoubleDistanceKNNQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/knn/LinearScanRawDoubleDistanceKNNQuery.java
deleted file mode 100644
index 5e5eae2f..00000000
--- a/src/de/lmu/ifi/dbs/elki/database/query/knn/LinearScanRawDoubleDistanceKNNQuery.java
+++ /dev/null
@@ -1,143 +0,0 @@
-package de.lmu.ifi.dbs.elki.database.query.knn;
-
-/*
- This file is part of ELKI:
- Environment for Developing KDD-Applications Supported by Index-Structures
-
- Copyright (C) 2012
- Ludwig-Maximilians-Universität München
- Lehr- und Forschungseinheit für Datenbanksysteme
- ELKI Development Team
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-import de.lmu.ifi.dbs.elki.database.ids.DBIDFactory;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
-import de.lmu.ifi.dbs.elki.database.ids.DistanceDBIDPair;
-import de.lmu.ifi.dbs.elki.database.ids.DoubleDistanceDBIDPair;
-import de.lmu.ifi.dbs.elki.database.query.distance.PrimitiveDistanceQuery;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.AbstractKNNHeap;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceKNNHeap;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceKNNList;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.GenericKNNList;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
-import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.TiedTopBoundedHeap;
-
-/**
- * Optimized linear scan query for {@link PrimitiveDoubleDistanceFunction}s.
- *
- * @author Erich Schubert
- *
- * @apiviz.uses PrimitiveDoubleDistanceFunction
- *
- * @param <O> Object type
- */
-public class LinearScanRawDoubleDistanceKNNQuery<O> extends LinearScanPrimitiveDistanceKNNQuery<O, DoubleDistance> {
- /**
- * Raw distance function.
- */
- PrimitiveDoubleDistanceFunction<O> rawdist;
-
- /**
- * Constructor.
- *
- * @param distanceQuery Distance function to use
- */
- @SuppressWarnings("unchecked")
- public LinearScanRawDoubleDistanceKNNQuery(PrimitiveDistanceQuery<O, DoubleDistance> distanceQuery) {
- super(distanceQuery);
- if (!(distanceQuery.getDistanceFunction() instanceof PrimitiveDoubleDistanceFunction)) {
- throw new UnsupportedOperationException("LinearScanRawDoubleDistance instantiated for non-RawDoubleDistance!");
- }
- rawdist = (PrimitiveDoubleDistanceFunction<O>) distanceQuery.getDistanceFunction();
- }
-
- @Override
- public KNNResult<DoubleDistance> getKNNForDBID(DBIDRef id, int k) {
- return getKNNForObject(relation.get(id), k);
- }
-
- @Override
- public KNNResult<DoubleDistance> getKNNForObject(O obj, int k) {
- return getKNNForObjectBenchmarked(obj, k);
- }
-
- /**
- * This is the cleaner, supposedly faster implementation.
- *
- * @param obj Query object
- * @param k Desired number of neighbors
- * @return kNN result
- */
- KNNResult<DoubleDistance> getKNNForObjectClean(O obj, int k) {
- // Optimization for double distances.
- final TiedTopBoundedHeap<DoubleDistanceDBIDPair> heap = new TiedTopBoundedHeap<DoubleDistanceDBIDPair>(k, DoubleDistanceKNNHeap.COMPARATOR);
- final DBIDIter iter = relation.iterDBIDs();
-
- // First k elements don't need checking.
- double max = 0.;
- for (int i = 0; i < k && iter.valid(); i++, iter.advance()) {
- final double doubleDistance = rawdist.doubleDistance(obj, relation.get(iter));
- heap.add(DBIDFactory.FACTORY.newDistancePair(doubleDistance, iter));
- max = Math.max(max, doubleDistance);
- }
- // Remaining elements
- for (; iter.valid(); iter.advance()) {
- final double doubleDistance = rawdist.doubleDistance(obj, relation.get(iter));
- if (doubleDistance <= max) {
- heap.add(DBIDFactory.FACTORY.newDistancePair(doubleDistance, iter));
- }
- if (doubleDistance < max) {
- max = heap.peek().doubleDistance();
- }
- }
- return new DoubleDistanceKNNList(heap, k);
- }
-
- /**
- * It does not make sense, but this version is faster in our larger
- * benchmarks. Apparently, some JIT optimization kicks in better.
- *
- * @param obj Query object
- * @param k Desired number of neighbors
- * @return kNN result
- */
- KNNResult<DoubleDistance> getKNNForObjectBenchmarked(O obj, int k) {
- // THIS SHOULD BE SLOWER THAN THE VERSION ABOVE, BUT ISN'T!
- final TiedTopBoundedHeap<DistanceDBIDPair<DoubleDistance>> heap = new TiedTopBoundedHeap<DistanceDBIDPair<DoubleDistance>>(k, AbstractKNNHeap.COMPARATOR);
- final DBIDIter iter = relation.iterDBIDs();
- // First k elements don't need checking.
- double max = 0.;
- for (int i = 0; i < k && iter.valid(); i++, iter.advance()) {
- final double doubleDistance = rawdist.doubleDistance(obj, relation.get(iter));
- heap.add(DBIDFactory.FACTORY.newDistancePair(new DoubleDistance(doubleDistance), iter));
- max = Math.max(max, doubleDistance);
- }
- // Remaining elements
- for (; iter.valid(); iter.advance()) {
- final double doubleDistance = rawdist.doubleDistance(obj, relation.get(iter));
- if (doubleDistance <= max) {
- heap.add(DBIDFactory.FACTORY.newDistancePair(new DoubleDistance(doubleDistance), iter));
- }
- if (doubleDistance < max) {
- max = heap.peek().getDistance().doubleValue();
- }
- }
- return new GenericKNNList<DoubleDistance>(heap, k);
- }
-}
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/knn/PreprocessorKNNQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/knn/PreprocessorKNNQuery.java
index a1e12fc3..0f555c79 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/knn/PreprocessorKNNQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/knn/PreprocessorKNNQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.knn;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,10 +29,10 @@ import java.util.List;
import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.AbstractDataBasedQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNUtil;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.index.preprocessed.knn.AbstractMaterializeKNNPreprocessor;
import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
@@ -43,7 +43,7 @@ import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
*
* @author Erich Schubert
*/
-public class PreprocessorKNNQuery<O, D extends Distance<D>, T extends KNNResult<D>> extends AbstractDataBasedQuery<O> implements KNNQuery<O, D> {
+public class PreprocessorKNNQuery<O, D extends Distance<D>, T extends KNNList<D>> extends AbstractDataBasedQuery<O> implements KNNQuery<O, D> {
/**
* The last preprocessor result
*/
@@ -76,12 +76,12 @@ public class PreprocessorKNNQuery<O, D extends Distance<D>, T extends KNNResult<
}
@Override
- public KNNResult<D> getKNNForDBID(DBIDRef id, int k) {
+ public KNNList<D> getKNNForDBID(DBIDRef id, int k) {
if(!warned && k > preprocessor.getK()) {
LoggingUtil.warning("Requested more neighbors than preprocessed!");
}
if(!warned && k < preprocessor.getK()) {
- KNNResult<D> dr = preprocessor.get(id);
+ KNNList<D> dr = preprocessor.get(id);
int subk = k;
D kdist = dr.get(subk - 1).getDistance();
while(subk < dr.size()) {
@@ -95,7 +95,7 @@ public class PreprocessorKNNQuery<O, D extends Distance<D>, T extends KNNResult<
}
}
if(subk < dr.size()) {
- return KNNUtil.subList(dr, subk);
+ return DBIDUtil.subList(dr, subk);
}
else {
return dr;
@@ -105,14 +105,14 @@ public class PreprocessorKNNQuery<O, D extends Distance<D>, T extends KNNResult<
}
@Override
- public List<KNNResult<D>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) {
+ public List<KNNList<D>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) {
if(!warned && k > preprocessor.getK()) {
LoggingUtil.warning("Requested more neighbors than preprocessed!");
}
- List<KNNResult<D>> result = new ArrayList<KNNResult<D>>(ids.size());
+ List<KNNList<D>> result = new ArrayList<>(ids.size());
if(k < preprocessor.getK()) {
for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
- KNNResult<D> dr = preprocessor.get(iter);
+ KNNList<D> dr = preprocessor.get(iter);
int subk = k;
D kdist = dr.get(subk - 1).getDistance();
while(subk < dr.size()) {
@@ -126,7 +126,7 @@ public class PreprocessorKNNQuery<O, D extends Distance<D>, T extends KNNResult<
}
}
if(subk < dr.size()) {
- result.add(KNNUtil.subList(dr, subk));
+ result.add(DBIDUtil.subList(dr, subk));
}
else {
result.add(dr);
@@ -142,7 +142,7 @@ public class PreprocessorKNNQuery<O, D extends Distance<D>, T extends KNNResult<
}
@Override
- public KNNResult<D> getKNNForObject(O obj, int k) {
+ public KNNList<D> getKNNForObject(O obj, int k) {
throw new AbortException("Preprocessor KNN query only supports ID queries.");
}
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/knn/package-info.java b/src/de/lmu/ifi/dbs/elki/database/query/knn/package-info.java
index 63c3aa16..17d8e4b0 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/knn/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/knn/package-info.java
@@ -8,7 +8,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/package-info.java b/src/de/lmu/ifi/dbs/elki/database/query/package-info.java
index 386ce6f3..fb3539bc 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/package-info.java
@@ -81,7 +81,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/range/AbstractDistanceRangeQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/range/AbstractDistanceRangeQuery.java
index 9997f3d6..c348653b 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/range/AbstractDistanceRangeQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/range/AbstractDistanceRangeQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.range;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,9 +24,9 @@ package de.lmu.ifi.dbs.elki.database.query.range;
*/
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
import de.lmu.ifi.dbs.elki.database.query.AbstractDataBasedQuery;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
/**
@@ -55,8 +55,10 @@ public abstract class AbstractDistanceRangeQuery<O, D extends Distance<D>> exten
}
@Override
- abstract public DistanceDBIDResult<D> getRangeForDBID(DBIDRef id, D range);
+ public DistanceDBIDList<D> getRangeForDBID(DBIDRef id, D range) {
+ return getRangeForObject(relation.get(id), range);
+ }
@Override
- abstract public DistanceDBIDResult<D> getRangeForObject(O obj, D range);
-} \ No newline at end of file
+ abstract public DistanceDBIDList<D> getRangeForObject(O obj, D range);
+}
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/range/DoubleOptimizedRangeQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/range/DoubleOptimizedRangeQuery.java
new file mode 100644
index 00000000..209e8950
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/database/query/range/DoubleOptimizedRangeQuery.java
@@ -0,0 +1,95 @@
+package de.lmu.ifi.dbs.elki.database.query.range;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.ModifiableDoubleDistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.integer.DoubleDistanceIntegerDBIDKNNList;
+import de.lmu.ifi.dbs.elki.database.query.LinearScanQuery;
+import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+
+/**
+ * Default linear scan range query class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.uses PrimitiveDoubleDistanceFunction
+ *
+ * @param <O> Database object type
+ */
+public class DoubleOptimizedRangeQuery<O> extends LinearScanRangeQuery<O, DoubleDistance> implements LinearScanQuery {
+ /**
+ * Raw distance function.
+ */
+ PrimitiveDoubleDistanceFunction<O> rawdist;
+
+ /**
+ * Constructor.
+ *
+ * @param distanceQuery Distance function to use
+ */
+ @SuppressWarnings("unchecked")
+ public DoubleOptimizedRangeQuery(DistanceQuery<O, DoubleDistance> distanceQuery) {
+ super(distanceQuery);
+ if (!(distanceQuery.getDistanceFunction() instanceof PrimitiveDoubleDistanceFunction)) {
+ throw new UnsupportedOperationException("DoubleOptimizedRangeQuery instantiated for non-PrimitiveDoubleDistanceFunction!");
+ }
+ rawdist = (PrimitiveDoubleDistanceFunction<O>) distanceQuery.getDistanceFunction();
+ }
+
+ @Override
+ public DistanceDBIDList<DoubleDistance> getRangeForDBID(DBIDRef id, DoubleDistance range) {
+ double epsilon = range.doubleValue();
+
+ O qo = relation.get(id);
+ ModifiableDoubleDistanceDBIDList result = new DoubleDistanceIntegerDBIDKNNList();
+ for (DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) {
+ double doubleDistance = rawdist.doubleDistance(qo, relation.get(iter));
+ if (doubleDistance <= epsilon) {
+ result.add(doubleDistance, iter);
+ }
+ }
+ result.sort();
+ return result;
+ }
+
+ @Override
+ public DistanceDBIDList<DoubleDistance> getRangeForObject(O obj, DoubleDistance range) {
+ double epsilon = range.doubleValue();
+
+ ModifiableDoubleDistanceDBIDList result = new DoubleDistanceIntegerDBIDKNNList();
+ for (DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) {
+ double doubleDistance = rawdist.doubleDistance(obj, relation.get(iter));
+ if (doubleDistance <= epsilon) {
+ result.add(doubleDistance, iter);
+ }
+ }
+ result.sort();
+ return result;
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/range/LinearScanPrimitiveDistanceRangeQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/range/LinearScanPrimitiveDistanceRangeQuery.java
index 57fa2338..3b18c282 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/range/LinearScanPrimitiveDistanceRangeQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/range/LinearScanPrimitiveDistanceRangeQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.range;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,8 +24,8 @@ package de.lmu.ifi.dbs.elki.database.query.range;
*/
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
import de.lmu.ifi.dbs.elki.database.query.distance.PrimitiveDistanceQuery;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
/**
@@ -52,7 +52,7 @@ public class LinearScanPrimitiveDistanceRangeQuery<O, D extends Distance<D>> ext
}
@Override
- public DistanceDBIDResult<D> getRangeForDBID(DBIDRef id, D range) {
+ public DistanceDBIDList<D> getRangeForDBID(DBIDRef id, D range) {
// Note: subtle optimization. Get "id" only once!
return getRangeForObject(relation.get(id), range);
}
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/range/LinearScanRangeQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/range/LinearScanRangeQuery.java
index 13e13a5c..c886c537 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/range/LinearScanRangeQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/range/LinearScanRangeQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.range;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,10 +25,10 @@ package de.lmu.ifi.dbs.elki.database.query.range;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.generic.GenericDistanceDBIDList;
import de.lmu.ifi.dbs.elki.database.query.LinearScanQuery;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.GenericDistanceDBIDList;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
/**
@@ -53,8 +53,8 @@ public class LinearScanRangeQuery<O, D extends Distance<D>> extends AbstractDist
}
@Override
- public DistanceDBIDResult<D> getRangeForDBID(DBIDRef id, D range) {
- GenericDistanceDBIDList<D> result = new GenericDistanceDBIDList<D>();
+ public DistanceDBIDList<D> getRangeForDBID(DBIDRef id, D range) {
+ GenericDistanceDBIDList<D> result = new GenericDistanceDBIDList<>();
for(DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) {
D currentDistance = distanceQuery.distance(id, iter);
if(currentDistance.compareTo(range) <= 0) {
@@ -66,8 +66,8 @@ public class LinearScanRangeQuery<O, D extends Distance<D>> extends AbstractDist
}
@Override
- public DistanceDBIDResult<D> getRangeForObject(O obj, D range) {
- GenericDistanceDBIDList<D> result = new GenericDistanceDBIDList<D>();
+ public DistanceDBIDList<D> getRangeForObject(O obj, D range) {
+ GenericDistanceDBIDList<D> result = new GenericDistanceDBIDList<>();
for(DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) {
D currentDistance = distanceQuery.distance(obj, iter);
if(currentDistance.compareTo(range) <= 0) {
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/range/LinearScanRawDoubleDistanceRangeQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/range/LinearScanRawDoubleDistanceRangeQuery.java
deleted file mode 100644
index 18863b2d..00000000
--- a/src/de/lmu/ifi/dbs/elki/database/query/range/LinearScanRawDoubleDistanceRangeQuery.java
+++ /dev/null
@@ -1,99 +0,0 @@
-package de.lmu.ifi.dbs.elki.database.query.range;
-
-/*
- This file is part of ELKI:
- Environment for Developing KDD-Applications Supported by Index-Structures
-
- Copyright (C) 2012
- Ludwig-Maximilians-Universität München
- Lehr- und Forschungseinheit für Datenbanksysteme
- ELKI Development Team
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
-import de.lmu.ifi.dbs.elki.database.query.LinearScanQuery;
-import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
-import de.lmu.ifi.dbs.elki.database.query.distance.PrimitiveDistanceQuery;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceDBIDList;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
-
-/**
- * Default linear scan range query class.
- *
- * @author Erich Schubert
- *
- * @apiviz.uses PrimitiveDoubleDistanceFunction
- *
- * @param <O> Database object type
- */
-public class LinearScanRawDoubleDistanceRangeQuery<O> extends LinearScanRangeQuery<O, DoubleDistance> implements LinearScanQuery {
- /**
- * Constructor.
- *
- * @param distanceQuery Distance function to use
- */
- public LinearScanRawDoubleDistanceRangeQuery(DistanceQuery<O, DoubleDistance> distanceQuery) {
- super(distanceQuery);
- }
-
- @Override
- public DistanceDBIDResult<DoubleDistance> getRangeForDBID(DBIDRef id, DoubleDistance range) {
- if(distanceQuery instanceof PrimitiveDistanceQuery && distanceQuery.getDistanceFunction() instanceof PrimitiveDoubleDistanceFunction) {
- @SuppressWarnings("unchecked")
- PrimitiveDoubleDistanceFunction<O> rawdist = (PrimitiveDoubleDistanceFunction<O>) distanceQuery.getDistanceFunction();
- double epsilon = range.doubleValue();
-
- O qo = relation.get(id);
- DoubleDistanceDBIDList result = new DoubleDistanceDBIDList();
- for(DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) {
- double doubleDistance = rawdist.doubleDistance(qo, relation.get(iter));
- if(doubleDistance <= epsilon) {
- result.add(doubleDistance, iter);
- }
- }
- result.sort();
- return result;
- }
- else {
- return super.getRangeForDBID(id, range);
- }
- }
-
- @Override
- public DistanceDBIDResult<DoubleDistance> getRangeForObject(O obj, DoubleDistance range) {
- if(distanceQuery instanceof PrimitiveDistanceQuery && distanceQuery.getDistanceFunction() instanceof PrimitiveDoubleDistanceFunction) {
- @SuppressWarnings("unchecked")
- PrimitiveDoubleDistanceFunction<O> rawdist = (PrimitiveDoubleDistanceFunction<O>) distanceQuery.getDistanceFunction();
- double epsilon = range.doubleValue();
-
- DoubleDistanceDBIDList result = new DoubleDistanceDBIDList();
- for(DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) {
- double doubleDistance = rawdist.doubleDistance(obj, relation.get(iter));
- if(doubleDistance <= epsilon) {
- result.add(doubleDistance, iter);
- }
- }
- result.sort();
- return result;
- }
- else {
- return super.getRangeForObject(obj, range);
- }
- }
-} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/range/RangeQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/range/RangeQuery.java
index 9574cda7..0ec40dde 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/range/RangeQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/range/RangeQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.range;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,8 +24,8 @@ package de.lmu.ifi.dbs.elki.database.query.range;
*/
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
/**
@@ -47,7 +47,7 @@ public interface RangeQuery<O, D extends Distance<D>> extends DatabaseQuery {
* @param range Query range
* @return neighbors
*/
- public DistanceDBIDResult<D> getRangeForDBID(DBIDRef id, D range);
+ public DistanceDBIDList<D> getRangeForDBID(DBIDRef id, D range);
/**
* Get the nearest neighbors for a particular object in a given query range
@@ -56,5 +56,5 @@ public interface RangeQuery<O, D extends Distance<D>> extends DatabaseQuery {
* @param range Query range
* @return neighbors
*/
- public DistanceDBIDResult<D> getRangeForObject(O obj, D range);
+ public DistanceDBIDList<D> getRangeForObject(O obj, D range);
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/range/package-info.java b/src/de/lmu/ifi/dbs/elki/database/query/range/package-info.java
index a176e43d..b2e3427d 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/range/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/range/package-info.java
@@ -7,7 +7,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/rknn/AbstractRKNNQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/rknn/AbstractRKNNQuery.java
index a090b466..8a88bf0f 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/rknn/AbstractRKNNQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/rknn/AbstractRKNNQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.rknn;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,9 +24,9 @@ package de.lmu.ifi.dbs.elki.database.query.rknn;
*/
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
import de.lmu.ifi.dbs.elki.database.query.AbstractDataBasedQuery;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
/**
@@ -51,5 +51,5 @@ public abstract class AbstractRKNNQuery<O, D extends Distance<D>> extends Abstra
}
@Override
- abstract public DistanceDBIDResult<D> getRKNNForDBID(DBIDRef id, int k);
+ abstract public DistanceDBIDList<D> getRKNNForDBID(DBIDRef id, int k);
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/rknn/LinearScanRKNNQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/rknn/LinearScanRKNNQuery.java
index f0e33777..71cf0619 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/rknn/LinearScanRKNNQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/rknn/LinearScanRKNNQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.rknn;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -30,13 +30,13 @@ import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
+import de.lmu.ifi.dbs.elki.database.ids.generic.GenericDistanceDBIDList;
import de.lmu.ifi.dbs.elki.database.query.LinearScanQuery;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultIter;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.GenericDistanceDBIDList;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
/**
@@ -70,15 +70,15 @@ public class LinearScanRKNNQuery<O, D extends Distance<D>> extends AbstractRKNNQ
}
@Override
- public DistanceDBIDResult<D> getRKNNForObject(O obj, int k) {
- GenericDistanceDBIDList<D> rNNlist = new GenericDistanceDBIDList<D>();
+ public DistanceDBIDList<D> getRKNNForObject(O obj, int k) {
+ GenericDistanceDBIDList<D> rNNlist = new GenericDistanceDBIDList<>();
ArrayDBIDs allIDs = DBIDUtil.ensureArray(relation.getDBIDs());
- List<? extends KNNResult<D>> kNNLists = knnQuery.getKNNForBulkDBIDs(allIDs, k);
+ List<? extends KNNList<D>> kNNLists = knnQuery.getKNNForBulkDBIDs(allIDs, k);
int i = 0;
for (DBIDIter iter = allIDs.iter(); iter.valid(); iter.advance()) {
- KNNResult<D> knn = kNNLists.get(i);
+ KNNList<D> knn = kNNLists.get(i);
int last = Math.min(k - 1, knn.size() - 1);
D dist = distanceQuery.distance(obj, iter);
if(last < k - 1 || dist.compareTo(knn.get(last).getDistance()) < 1) {
@@ -91,16 +91,16 @@ public class LinearScanRKNNQuery<O, D extends Distance<D>> extends AbstractRKNNQ
}
@Override
- public DistanceDBIDResult<D> getRKNNForDBID(DBIDRef id, int k) {
- GenericDistanceDBIDList<D> rNNList = new GenericDistanceDBIDList<D>();
+ public DistanceDBIDList<D> getRKNNForDBID(DBIDRef id, int k) {
+ GenericDistanceDBIDList<D> rNNList = new GenericDistanceDBIDList<>();
ArrayDBIDs allIDs = DBIDUtil.ensureArray(relation.getDBIDs());
- List<? extends KNNResult<D>> kNNList = knnQuery.getKNNForBulkDBIDs(allIDs, k);
+ List<? extends KNNList<D>> kNNList = knnQuery.getKNNForBulkDBIDs(allIDs, k);
int i = 0;
for (DBIDIter iter = allIDs.iter(); iter.valid(); iter.advance()) {
- KNNResult<D> knn = kNNList.get(i);
- for(DistanceDBIDResultIter<D> n = knn.iter(); n.valid(); n.advance()) {
+ KNNList<D> knn = kNNList.get(i);
+ for(DistanceDBIDListIter<D> n = knn.iter(); n.valid(); n.advance()) {
if(DBIDUtil.equal(n, id)) {
rNNList.add(n.getDistance(), iter);
}
@@ -113,18 +113,18 @@ public class LinearScanRKNNQuery<O, D extends Distance<D>> extends AbstractRKNNQ
@Override
public List<GenericDistanceDBIDList<D>> getRKNNForBulkDBIDs(ArrayDBIDs ids, int k) {
- List<GenericDistanceDBIDList<D>> rNNList = new ArrayList<GenericDistanceDBIDList<D>>(ids.size());
+ List<GenericDistanceDBIDList<D>> rNNList = new ArrayList<>(ids.size());
for(int i = 0; i < ids.size(); i++) {
rNNList.add(new GenericDistanceDBIDList<D>());
}
ArrayDBIDs allIDs = DBIDUtil.ensureArray(relation.getDBIDs());
- List<? extends KNNResult<D>> kNNList = knnQuery.getKNNForBulkDBIDs(allIDs, k);
+ List<? extends KNNList<D>> kNNList = knnQuery.getKNNForBulkDBIDs(allIDs, k);
int i = 0;
for (DBIDIter iter = allIDs.iter(); iter.valid(); iter.advance()) {
- KNNResult<D> knn = kNNList.get(i);
- for(DistanceDBIDResultIter<D> n = knn.iter(); n.valid(); n.advance()) {
+ KNNList<D> knn = kNNList.get(i);
+ for(DistanceDBIDListIter<D> n = knn.iter(); n.valid(); n.advance()) {
int j = 0;
for (DBIDIter iter2 = ids.iter(); iter2.valid(); iter2.advance()) {
if(DBIDUtil.equal(n, iter2)) {
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/rknn/PreprocessorRKNNQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/rknn/PreprocessorRKNNQuery.java
index 8256ffad..9f8f9c71 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/rknn/PreprocessorRKNNQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/rknn/PreprocessorRKNNQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.rknn;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,9 +29,9 @@ import java.util.List;
import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
import de.lmu.ifi.dbs.elki.database.query.AbstractDataBasedQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNAndRKNNPreprocessor;
import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
@@ -75,7 +75,7 @@ public class PreprocessorRKNNQuery<O, D extends Distance<D>> extends AbstractDat
}
@Override
- public DistanceDBIDResult<D> getRKNNForDBID(DBIDRef id, int k) {
+ public DistanceDBIDList<D> getRKNNForDBID(DBIDRef id, int k) {
if(!warned && k != preprocessor.getK()) {
LoggingUtil.warning("Requested more neighbors than preprocessed!");
}
@@ -83,16 +83,16 @@ public class PreprocessorRKNNQuery<O, D extends Distance<D>> extends AbstractDat
}
@Override
- public DistanceDBIDResult<D> getRKNNForObject(O obj, int k) {
+ public DistanceDBIDList<D> getRKNNForObject(O obj, int k) {
throw new AbortException("Preprocessor KNN query only supports ID queries.");
}
@Override
- public List<? extends DistanceDBIDResult<D>> getRKNNForBulkDBIDs(ArrayDBIDs ids, int k) {
+ public List<? extends DistanceDBIDList<D>> getRKNNForBulkDBIDs(ArrayDBIDs ids, int k) {
if(!warned && k != preprocessor.getK()) {
LoggingUtil.warning("Requested more neighbors than preprocessed!");
}
- List<DistanceDBIDResult<D>> result = new ArrayList<DistanceDBIDResult<D>>(ids.size());
+ List<DistanceDBIDList<D>> result = new ArrayList<>(ids.size());
for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
result.add(preprocessor.getRKNN(iter));
}
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/rknn/RKNNQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/rknn/RKNNQuery.java
index dc21948e..0a05d797 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/rknn/RKNNQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/rknn/RKNNQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.rknn;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,8 +27,8 @@ import java.util.List;
import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
/**
@@ -36,7 +36,7 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
*
* @author Erich Schubert
*
- * @apiviz.uses DistanceDBIDResult oneway - - «create»
+ * @apiviz.uses DistanceDBIDList oneway - - «create»
*
* @param <O> Object type
* @param <D> Distance type
@@ -49,7 +49,7 @@ public interface RKNNQuery<O, D extends Distance<D>> extends DatabaseQuery {
* @param k number of neighbors requested
* @return reverse k nearest neighbors
*/
- public DistanceDBIDResult<D> getRKNNForDBID(DBIDRef id, int k);
+ public DistanceDBIDList<D> getRKNNForDBID(DBIDRef id, int k);
/**
* Get the reverse k nearest neighbors for a particular object.
@@ -58,7 +58,7 @@ public interface RKNNQuery<O, D extends Distance<D>> extends DatabaseQuery {
* @param k number of neighbors requested
* @return reverse k nearest neighbors
*/
- public DistanceDBIDResult<D> getRKNNForObject(O obj, int k);
+ public DistanceDBIDList<D> getRKNNForObject(O obj, int k);
/**
* Bulk query method for reverse k nearest neighbors for ids.
@@ -67,5 +67,5 @@ public interface RKNNQuery<O, D extends Distance<D>> extends DatabaseQuery {
* @param k number of neighbors requested
* @return reverse k nearest neighbors
*/
- public List<? extends DistanceDBIDResult<D>> getRKNNForBulkDBIDs(ArrayDBIDs ids, int k);
+ public List<? extends DistanceDBIDList<D>> getRKNNForBulkDBIDs(ArrayDBIDs ids, int k);
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/rknn/package-info.java b/src/de/lmu/ifi/dbs/elki/database/query/rknn/package-info.java
index a7e2bf37..8c0501b6 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/rknn/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/rknn/package-info.java
@@ -7,7 +7,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/similarity/AbstractDBIDSimilarityQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/similarity/AbstractDBIDSimilarityQuery.java
index 3d5ff71f..8dc6dd61 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/similarity/AbstractDBIDSimilarityQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/similarity/AbstractDBIDSimilarityQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.similarity;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/similarity/AbstractSimilarityQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/similarity/AbstractSimilarityQuery.java
index 21abe219..fbcf76a7 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/similarity/AbstractSimilarityQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/similarity/AbstractSimilarityQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.similarity;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/similarity/PrimitiveSimilarityQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/similarity/PrimitiveSimilarityQuery.java
index 5a604d0c..b98482a8 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/similarity/PrimitiveSimilarityQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/similarity/PrimitiveSimilarityQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.similarity;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/similarity/SimilarityQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/similarity/SimilarityQuery.java
index b25d13fc..3e02edc1 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/similarity/SimilarityQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/similarity/SimilarityQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.similarity;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/similarity/package-info.java b/src/de/lmu/ifi/dbs/elki/database/query/similarity/package-info.java
index d601d0a4..dde6909b 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/similarity/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/similarity/package-info.java
@@ -6,7 +6,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/relation/ConvertToStringView.java b/src/de/lmu/ifi/dbs/elki/database/relation/ConvertToStringView.java
index 4c25405b..3ce4d935 100644
--- a/src/de/lmu/ifi/dbs/elki/database/relation/ConvertToStringView.java
+++ b/src/de/lmu/ifi/dbs/elki/database/relation/ConvertToStringView.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.relation;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/relation/DBIDView.java b/src/de/lmu/ifi/dbs/elki/database/relation/DBIDView.java
index b8974ac2..7eb14983 100644
--- a/src/de/lmu/ifi/dbs/elki/database/relation/DBIDView.java
+++ b/src/de/lmu/ifi/dbs/elki/database/relation/DBIDView.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.relation;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -48,7 +48,7 @@ public class DBIDView extends AbstractHierarchicalResult implements Relation<DBI
/**
* The ids object
*/
- private final DBIDs ids;
+ private DBIDs ids;
/**
* Constructor.
@@ -80,10 +80,9 @@ public class DBIDView extends AbstractHierarchicalResult implements Relation<DBI
@Override
public void delete(DBIDRef id) {
- if(database instanceof UpdatableDatabase) {
+ if (database instanceof UpdatableDatabase) {
((UpdatableDatabase) database).delete(id);
- }
- else {
+ } else {
throw new UnsupportedOperationException("Deletions are not supported.");
}
}
@@ -103,6 +102,15 @@ public class DBIDView extends AbstractHierarchicalResult implements Relation<DBI
return ids.iter();
}
+ /**
+ * Set the DBIDs of the view.
+ *
+ * @param ids IDs to use
+ */
+ public void setDBIDs(DBIDs ids) {
+ this.ids = DBIDUtil.makeUnmodifiable(ids);
+ }
+
@Override
public int size() {
return ids.size();
@@ -117,4 +125,4 @@ public class DBIDView extends AbstractHierarchicalResult implements Relation<DBI
public String getShortName() {
return "DBID";
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/database/relation/MaterializedRelation.java b/src/de/lmu/ifi/dbs/elki/database/relation/MaterializedRelation.java
index 2d090e99..8df4a42b 100644
--- a/src/de/lmu/ifi/dbs/elki/database/relation/MaterializedRelation.java
+++ b/src/de/lmu/ifi/dbs/elki/database/relation/MaterializedRelation.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.relation;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/relation/ProjectedView.java b/src/de/lmu/ifi/dbs/elki/database/relation/ProjectedView.java
index 8f2b8c92..252b651b 100644
--- a/src/de/lmu/ifi/dbs/elki/database/relation/ProjectedView.java
+++ b/src/de/lmu/ifi/dbs/elki/database/relation/ProjectedView.java
@@ -12,7 +12,7 @@ import de.lmu.ifi.dbs.elki.result.AbstractHierarchicalResult;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -60,6 +60,7 @@ public class ProjectedView<IN, OUT> extends AbstractHierarchicalResult implement
super();
this.inner = inner;
this.projection = projection;
+ projection.initialize(inner.getDataTypeInformation());
}
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/database/relation/ProxyView.java b/src/de/lmu/ifi/dbs/elki/database/relation/ProxyView.java
index 9937c8ee..d6e12d60 100644
--- a/src/de/lmu/ifi/dbs/elki/database/relation/ProxyView.java
+++ b/src/de/lmu/ifi/dbs/elki/database/relation/ProxyView.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.relation;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -48,7 +48,7 @@ public class ProxyView<O> extends AbstractHierarchicalResult implements Relation
/**
* The DBIDs we contain
*/
- private final DBIDs idview;
+ private DBIDs idview;
/**
* The wrapped representation where we get the IDs from.
@@ -82,7 +82,7 @@ public class ProxyView<O> extends AbstractHierarchicalResult implements Relation
* @return Instance
*/
public static <O> ProxyView<O> wrap(Database database, DBIDs idview, Relation<O> inner) {
- return new ProxyView<O>(database, idview, inner);
+ return new ProxyView<>(database, idview, inner);
}
@Override
@@ -90,7 +90,7 @@ public class ProxyView<O> extends AbstractHierarchicalResult implements Relation
assert (idview.contains(id)) : "Accessing object not included in view.";
return inner.get(id);
}
-
+
@Override
public void set(DBIDRef id, O val) {
assert (idview.contains(id)) : "Accessing object not included in view.";
@@ -131,4 +131,13 @@ public class ProxyView<O> extends AbstractHierarchicalResult implements Relation
public String getShortName() {
return "partition";
}
-} \ No newline at end of file
+
+ /**
+ * Set the DBIDs to use.
+ *
+ * @param ids DBIDs
+ */
+ public void setDBIDs(DBIDs ids) {
+ this.idview = ids;
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/database/relation/Relation.java b/src/de/lmu/ifi/dbs/elki/database/relation/Relation.java
index 4969ad50..9ac4e408 100644
--- a/src/de/lmu/ifi/dbs/elki/database/relation/Relation.java
+++ b/src/de/lmu/ifi/dbs/elki/database/relation/Relation.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.relation;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/relation/RelationUtil.java b/src/de/lmu/ifi/dbs/elki/database/relation/RelationUtil.java
index 77f98f60..b6549d6c 100644
--- a/src/de/lmu/ifi/dbs/elki/database/relation/RelationUtil.java
+++ b/src/de/lmu/ifi/dbs/elki/database/relation/RelationUtil.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.relation;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/relation/package-info.java b/src/de/lmu/ifi/dbs/elki/database/relation/package-info.java
index 12ecf968..133d6574 100644
--- a/src/de/lmu/ifi/dbs/elki/database/relation/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/database/relation/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/AbstractDatabaseConnection.java b/src/de/lmu/ifi/dbs/elki/datasource/AbstractDatabaseConnection.java
index 25afa6bc..e9d9933f 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/AbstractDatabaseConnection.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/AbstractDatabaseConnection.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -199,7 +199,7 @@ public abstract class AbstractDatabaseConnection implements DatabaseConnection {
* @param config Parameterization
*/
protected void configFilters(Parameterization config) {
- final ObjectListParameter<ObjectFilter> filterParam = new ObjectListParameter<ObjectFilter>(FILTERS_ID, ObjectFilter.class, true);
+ final ObjectListParameter<ObjectFilter> filterParam = new ObjectListParameter<>(FILTERS_ID, ObjectFilter.class, true);
if(config.grab(filterParam)) {
filters = filterParam.instantiateClasses(config);
}
@@ -213,7 +213,7 @@ public abstract class AbstractDatabaseConnection implements DatabaseConnection {
* @param parserDefaultValueClass Default value
*/
protected void configParser(Parameterization config, Class<?> parserRestrictionClass, Class<?> parserDefaultValueClass) {
- ObjectParameter<Parser> parserParam = new ObjectParameter<Parser>(PARSER_ID, parserRestrictionClass, parserDefaultValueClass);
+ ObjectParameter<Parser> parserParam = new ObjectParameter<>(PARSER_ID, parserRestrictionClass, parserDefaultValueClass);
if(config.grab(parserParam)) {
parser = parserParam.instantiateClass(config);
}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/ArrayAdapterDatabaseConnection.java b/src/de/lmu/ifi/dbs/elki/datasource/ArrayAdapterDatabaseConnection.java
index 05eda9cb..1779f851 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/ArrayAdapterDatabaseConnection.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/ArrayAdapterDatabaseConnection.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -97,7 +97,7 @@ public class ArrayAdapterDatabaseConnection implements DatabaseConnection {
public MultipleObjectsBundle loadData() {
MultipleObjectsBundle b = new MultipleObjectsBundle();
if(startid != null) {
- List<DBID> ids = new ArrayList<DBID>(data.length);
+ List<DBID> ids = new ArrayList<>(data.length);
for(int i = 0; i < data.length; i++) {
ids.add(DBIDUtil.importInteger(startid.intValue() + i));
}
@@ -106,7 +106,7 @@ public class ArrayAdapterDatabaseConnection implements DatabaseConnection {
int mind = Integer.MAX_VALUE;
int maxd = 0;
- List<DoubleVector> vecs = new ArrayList<DoubleVector>(data.length);
+ List<DoubleVector> vecs = new ArrayList<>(data.length);
for(int i = 0; i < data.length; i++) {
mind = Math.min(mind, data[i].length);
maxd = Math.max(maxd, data[i].length);
@@ -114,10 +114,10 @@ public class ArrayAdapterDatabaseConnection implements DatabaseConnection {
}
SimpleTypeInformation<DoubleVector> type;
if(mind == maxd) {
- type = new VectorFieldTypeInformation<DoubleVector>(DoubleVector.FACTORY, mind);
+ type = new VectorFieldTypeInformation<>(DoubleVector.FACTORY, mind);
}
else {
- type = new SimpleTypeInformation<DoubleVector>(DoubleVector.class);
+ type = new SimpleTypeInformation<>(DoubleVector.class);
}
b.appendColumn(type, vecs);
if(labels != null) {
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/BundleDatabaseConnection.java b/src/de/lmu/ifi/dbs/elki/datasource/BundleDatabaseConnection.java
index 735ed149..c8821bc9 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/BundleDatabaseConnection.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/BundleDatabaseConnection.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/ConcatenateFilesDatabaseConnection.java b/src/de/lmu/ifi/dbs/elki/datasource/ConcatenateFilesDatabaseConnection.java
index 0caeadf7..c701efc9 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/ConcatenateFilesDatabaseConnection.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/ConcatenateFilesDatabaseConnection.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -85,7 +85,7 @@ public class ConcatenateFilesDatabaseConnection extends AbstractDatabaseConnecti
@Override
public MultipleObjectsBundle loadData() {
MultipleObjectsBundle objects = new MultipleObjectsBundle();
- objects.appendColumn(TypeUtil.STRING, new ArrayList<Object>());
+ objects.appendColumn(TypeUtil.STRING, new ArrayList<>());
for (File file : files) {
String filestr = file.getPath();
try {
@@ -111,7 +111,7 @@ public class ConcatenateFilesDatabaseConnection extends AbstractDatabaseConnecti
meta = source.getMeta();
for (int i = 0; i < meta.size(); i++) {
if (i + 1 >= objects.metaLength()) {
- objects.appendColumn(meta.get(i), new ArrayList<Object>());
+ objects.appendColumn(meta.get(i), new ArrayList<>());
} else {
// Ensure compatibility:
if (!objects.meta(i + 1).isAssignableFromType(meta.get(i))) {
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/DBIDRangeDatabaseConnection.java b/src/de/lmu/ifi/dbs/elki/datasource/DBIDRangeDatabaseConnection.java
index b93b81eb..2e7f59e7 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/DBIDRangeDatabaseConnection.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/DBIDRangeDatabaseConnection.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -63,12 +63,14 @@ public class DBIDRangeDatabaseConnection implements DatabaseConnection {
*/
public DBIDRangeDatabaseConnection(int start, int count) {
super();
+ this.start = start;
+ this.count = count;
}
@Override
public MultipleObjectsBundle loadData() {
MultipleObjectsBundle b = new MultipleObjectsBundle();
- List<DBID> ids = new ArrayList<DBID>(count);
+ List<DBID> ids = new ArrayList<>(count);
for(int i = 0; i < count; i++) {
ids.add(DBIDUtil.importInteger(start + i));
}
@@ -118,7 +120,7 @@ public class DBIDRangeDatabaseConnection implements DatabaseConnection {
}
@Override
- protected Object makeInstance() {
+ protected DBIDRangeDatabaseConnection makeInstance() {
return new DBIDRangeDatabaseConnection(start, count);
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/DatabaseConnection.java b/src/de/lmu/ifi/dbs/elki/datasource/DatabaseConnection.java
index 7417b4d4..6fe3ae39 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/DatabaseConnection.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/DatabaseConnection.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/EmptyDatabaseConnection.java b/src/de/lmu/ifi/dbs/elki/datasource/EmptyDatabaseConnection.java
index 43aab20a..70b1da50 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/EmptyDatabaseConnection.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/EmptyDatabaseConnection.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/ExternalIDJoinDatabaseConnection.java b/src/de/lmu/ifi/dbs/elki/datasource/ExternalIDJoinDatabaseConnection.java
index 53468c96..38aefaca 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/ExternalIDJoinDatabaseConnection.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/ExternalIDJoinDatabaseConnection.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -72,13 +72,13 @@ public class ExternalIDJoinDatabaseConnection extends AbstractDatabaseConnection
@Override
public MultipleObjectsBundle loadData() {
- List<MultipleObjectsBundle> bundles = new ArrayList<MultipleObjectsBundle>(sources.size());
+ List<MultipleObjectsBundle> bundles = new ArrayList<>(sources.size());
for (DatabaseConnection dbc : sources) {
bundles.add(dbc.loadData());
}
MultipleObjectsBundle first = bundles.get(0);
- TObjectIntHashMap<ExternalID> labelmap = new TObjectIntHashMap<ExternalID>(first.dataLength(), Constants.DEFAULT_LOAD_FACTOR, -1);
+ TObjectIntHashMap<ExternalID> labelmap = new TObjectIntHashMap<>(first.dataLength(), Constants.DEFAULT_LOAD_FACTOR, -1);
// Process first bundle
{
// Identify a label column
@@ -133,14 +133,14 @@ public class ExternalIDJoinDatabaseConnection extends AbstractDatabaseConnection
throw new AbortException("No external ID column found in source " + (c + 1) + " to join with. Got: " + buf.toString());
}
// Destination columns
- List<ArrayList<Object>> dcol = new ArrayList<ArrayList<Object>>(cur.metaLength());
+ List<ArrayList<Object>> dcol = new ArrayList<>(cur.metaLength());
for (int i = 0; i < cur.metaLength(); i++) {
// Skip the label columns
if (i == lblcol) {
dcol.add(null);
continue;
}
- ArrayList<Object> newcol = new ArrayList<Object>(first.dataLength());
+ ArrayList<Object> newcol = new ArrayList<>(first.dataLength());
// Pre-fill with nulls.
for (int j = 0; j < first.dataLength(); j++) {
newcol.add(null);
@@ -219,7 +219,7 @@ public class ExternalIDJoinDatabaseConnection extends AbstractDatabaseConnection
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
super.configFilters(config);
- final ObjectListParameter<DatabaseConnection> sourcesParam = new ObjectListParameter<DatabaseConnection>(SOURCES_ID, DatabaseConnection.class);
+ final ObjectListParameter<DatabaseConnection> sourcesParam = new ObjectListParameter<>(SOURCES_ID, DatabaseConnection.class);
if (config.grab(sourcesParam)) {
sources = sourcesParam.instantiateClasses(config);
}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/FileBasedDatabaseConnection.java b/src/de/lmu/ifi/dbs/elki/datasource/FileBasedDatabaseConnection.java
index 42347841..193fc551 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/FileBasedDatabaseConnection.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/FileBasedDatabaseConnection.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/GeneratorXMLDatabaseConnection.java b/src/de/lmu/ifi/dbs/elki/datasource/GeneratorXMLDatabaseConnection.java
index 9fe7febe..dcda0765 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/GeneratorXMLDatabaseConnection.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/GeneratorXMLDatabaseConnection.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -50,7 +50,7 @@ import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.GeneratorStatic;
import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
-import de.lmu.ifi.dbs.elki.math.statistics.distribution.DistributionWithRandom;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.Distribution;
import de.lmu.ifi.dbs.elki.math.statistics.distribution.GammaDistribution;
import de.lmu.ifi.dbs.elki.math.statistics.distribution.HaltonUniformDistribution;
import de.lmu.ifi.dbs.elki.math.statistics.distribution.NormalDistribution;
@@ -403,7 +403,7 @@ public class GeneratorXMLDatabaseConnection implements DatabaseConnection {
// *** new uniform generator
Random random = cluster.getNewRandomGenerator();
- DistributionWithRandom generator = new UniformDistribution(min, max, random);
+ Distribution generator = new UniformDistribution(min, max, random);
cluster.addGenerator(generator);
// TODO: check for unknown attributes.
@@ -437,7 +437,7 @@ public class GeneratorXMLDatabaseConnection implements DatabaseConnection {
// *** New normal distribution generator
Random random = cluster.getNewRandomGenerator();
- DistributionWithRandom generator = new NormalDistribution(mean, stddev, random);
+ Distribution generator = new NormalDistribution(mean, stddev, random);
cluster.addGenerator(generator);
// TODO: check for unknown attributes.
@@ -471,7 +471,7 @@ public class GeneratorXMLDatabaseConnection implements DatabaseConnection {
// *** New normal distribution generator
Random random = cluster.getNewRandomGenerator();
- DistributionWithRandom generator = new GammaDistribution(k, theta, random);
+ Distribution generator = new GammaDistribution(k, theta, random);
cluster.addGenerator(generator);
// TODO: check for unknown attributes.
@@ -506,7 +506,7 @@ public class GeneratorXMLDatabaseConnection implements DatabaseConnection {
// *** new uniform generator
Random random = cluster.getNewRandomGenerator();
- DistributionWithRandom generator = new HaltonUniformDistribution(min, max, random);
+ Distribution generator = new HaltonUniformDistribution(min, max, random);
cluster.addGenerator(generator);
// TODO: check for unknown attributes.
@@ -645,7 +645,7 @@ public class GeneratorXMLDatabaseConnection implements DatabaseConnection {
throw new UnableToComplyException("No cluster name given in specification file.");
}
- ArrayList<Vector> points = new ArrayList<Vector>();
+ ArrayList<Vector> points = new ArrayList<>();
// TODO: check for unknown attributes.
XMLNodeIterator iter = new XMLNodeIterator(cur.getFirstChild());
while (iter.hasNext()) {
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/InputStreamDatabaseConnection.java b/src/de/lmu/ifi/dbs/elki/datasource/InputStreamDatabaseConnection.java
index 109ef0cd..0e99b421 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/InputStreamDatabaseConnection.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/InputStreamDatabaseConnection.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -32,6 +32,7 @@ import de.lmu.ifi.dbs.elki.datasource.parser.NumberVectorLabelParser;
import de.lmu.ifi.dbs.elki.datasource.parser.Parser;
import de.lmu.ifi.dbs.elki.datasource.parser.StreamingParser;
import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.statistics.Duration;
import de.lmu.ifi.dbs.elki.utilities.documentation.Description;
import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
@@ -87,17 +88,41 @@ public class InputStreamDatabaseConnection extends AbstractDatabaseConnection {
if(LOG.isDebugging()) {
LOG.debugFine("Invoking filters.");
}
+ Duration duration = LOG.isStatistics() ? LOG.newDuration(this.getClass().getName() + ".load") : null;
+ if (duration != null) {
+ duration.begin();
+ }
MultipleObjectsBundle objects = MultipleObjectsBundle.fromStream(invokeFilters(streamParser));
+ if (duration != null) {
+ duration.end();
+ LOG.statistics(duration);
+ }
return objects;
}
else {
+ Duration duration = LOG.isStatistics() ? LOG.newDuration(this.getClass().getName() + ".parse") : null;
+ if (duration != null) {
+ duration.begin();
+ }
MultipleObjectsBundle parsingResult = parser.parse(in);
+ if (duration != null) {
+ duration.end();
+ LOG.statistics(duration);
+ }
// normalize objects and transform labels
if(LOG.isDebugging()) {
LOG.debugFine("Invoking filters.");
}
+ Duration fduration = LOG.isStatistics() ? LOG.newDuration(this.getClass().getName() + ".filter") : null;
+ if (fduration != null) {
+ fduration.begin();
+ }
MultipleObjectsBundle objects = invokeFilters(parsingResult);
+ if (fduration != null) {
+ fduration.end();
+ LOG.statistics(fduration);
+ }
return objects;
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/LabelJoinDatabaseConnection.java b/src/de/lmu/ifi/dbs/elki/datasource/LabelJoinDatabaseConnection.java
index a41be640..375afa14 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/LabelJoinDatabaseConnection.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/LabelJoinDatabaseConnection.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -72,13 +72,13 @@ public class LabelJoinDatabaseConnection extends AbstractDatabaseConnection impl
@Override
public MultipleObjectsBundle loadData() {
- List<MultipleObjectsBundle> bundles = new ArrayList<MultipleObjectsBundle>(sources.size());
+ List<MultipleObjectsBundle> bundles = new ArrayList<>(sources.size());
for (DatabaseConnection dbc : sources) {
bundles.add(dbc.loadData());
}
MultipleObjectsBundle first = bundles.get(0);
- TObjectIntHashMap<String> labelmap = new TObjectIntHashMap<String>(first.dataLength(), Constants.DEFAULT_LOAD_FACTOR, -1);
+ TObjectIntHashMap<String> labelmap = new TObjectIntHashMap<>(first.dataLength(), Constants.DEFAULT_LOAD_FACTOR, -1);
// Process first bundle
{
// Identify a label column
@@ -141,14 +141,14 @@ public class LabelJoinDatabaseConnection extends AbstractDatabaseConnection impl
throw new AbortException("No label column found in source " + (c + 1) + ", cannot join (do you want to use " + ExternalIDJoinDatabaseConnection.class.getSimpleName() + " instead?)");
}
// Destination columns
- List<ArrayList<Object>> dcol = new ArrayList<ArrayList<Object>>(cur.metaLength());
+ List<ArrayList<Object>> dcol = new ArrayList<>(cur.metaLength());
for (int i = 0; i < cur.metaLength(); i++) {
// Skip the label columns
if (i == lblcol) {
dcol.add(null);
continue;
}
- ArrayList<Object> newcol = new ArrayList<Object>(first.dataLength());
+ ArrayList<Object> newcol = new ArrayList<>(first.dataLength());
// Pre-fill with nulls.
for (int j = 0; j < first.dataLength(); j++) {
newcol.add(null);
@@ -239,7 +239,7 @@ public class LabelJoinDatabaseConnection extends AbstractDatabaseConnection impl
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
super.configFilters(config);
- final ObjectListParameter<DatabaseConnection> sourcesParam = new ObjectListParameter<DatabaseConnection>(SOURCES_ID, DatabaseConnection.class);
+ final ObjectListParameter<DatabaseConnection> sourcesParam = new ObjectListParameter<>(SOURCES_ID, DatabaseConnection.class);
if (config.grab(sourcesParam)) {
sources = sourcesParam.instantiateClasses(config);
}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/PresortedBlindJoinDatabaseConnection.java b/src/de/lmu/ifi/dbs/elki/datasource/PresortedBlindJoinDatabaseConnection.java
index 75c48731..4f52f5f2 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/PresortedBlindJoinDatabaseConnection.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/PresortedBlindJoinDatabaseConnection.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -67,7 +67,7 @@ public class PresortedBlindJoinDatabaseConnection extends AbstractDatabaseConnec
@Override
public MultipleObjectsBundle loadData() {
- List<MultipleObjectsBundle> bundles = new ArrayList<MultipleObjectsBundle>(sources.size());
+ List<MultipleObjectsBundle> bundles = new ArrayList<>(sources.size());
for(DatabaseConnection dbc : sources) {
bundles.add(dbc.loadData());
}
@@ -84,7 +84,7 @@ public class PresortedBlindJoinDatabaseConnection extends AbstractDatabaseConnec
}
}
- return first;
+ return invokeFilters(first);
}
@Override
@@ -114,7 +114,7 @@ public class PresortedBlindJoinDatabaseConnection extends AbstractDatabaseConnec
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
super.configFilters(config);
- final ObjectListParameter<DatabaseConnection> sourcesParam = new ObjectListParameter<DatabaseConnection>(SOURCES_ID, DatabaseConnection.class);
+ final ObjectListParameter<DatabaseConnection> sourcesParam = new ObjectListParameter<>(SOURCES_ID, DatabaseConnection.class);
if(config.grab(sourcesParam)) {
sources = sourcesParam.instantiateClasses(config);
}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/RandomDoubleVectorDatabaseConnection.java b/src/de/lmu/ifi/dbs/elki/datasource/RandomDoubleVectorDatabaseConnection.java
index bd157315..84891a86 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/RandomDoubleVectorDatabaseConnection.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/RandomDoubleVectorDatabaseConnection.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -82,8 +82,8 @@ public class RandomDoubleVectorDatabaseConnection extends AbstractDatabaseConnec
@Override
public MultipleObjectsBundle loadData() {
- VectorFieldTypeInformation<DoubleVector> type = new VectorFieldTypeInformation<DoubleVector>(DoubleVector.FACTORY, dim);
- List<DoubleVector> vectors = new ArrayList<DoubleVector>(size);
+ VectorFieldTypeInformation<DoubleVector> type = new VectorFieldTypeInformation<>(DoubleVector.FACTORY, dim);
+ List<DoubleVector> vectors = new ArrayList<>(size);
// Setup random generator
final Random rand = rnd.getRandom();
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/bundle/BundleMeta.java b/src/de/lmu/ifi/dbs/elki/datasource/bundle/BundleMeta.java
index 28354bd4..442c00e8 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/bundle/BundleMeta.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/bundle/BundleMeta.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.bundle;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/bundle/BundleReader.java b/src/de/lmu/ifi/dbs/elki/datasource/bundle/BundleReader.java
index a2a3fb7e..4f57cac8 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/bundle/BundleReader.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/bundle/BundleReader.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.bundle;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -115,8 +115,8 @@ public class BundleReader implements BundleStreamSource {
final int nummeta = buffer.getInt();
assert (nummeta > 0);
meta = new BundleMeta(nummeta);
- sers = new ArrayList<ByteBufferSerializer<?>>(nummeta);
- data = new ArrayList<Object>(nummeta);
+ sers = new ArrayList<>(nummeta);
+ data = new ArrayList<>(nummeta);
for (int i = 0; i < nummeta; i++) {
try {
@SuppressWarnings("unchecked")
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/bundle/BundleStreamSource.java b/src/de/lmu/ifi/dbs/elki/datasource/bundle/BundleStreamSource.java
index 8b831846..cbac6134 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/bundle/BundleStreamSource.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/bundle/BundleStreamSource.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.bundle;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/bundle/BundleWriter.java b/src/de/lmu/ifi/dbs/elki/datasource/bundle/BundleWriter.java
index 7efbd592..4b7c4a3d 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/bundle/BundleWriter.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/bundle/BundleWriter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.bundle;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/bundle/MultipleObjectsBundle.java b/src/de/lmu/ifi/dbs/elki/datasource/bundle/MultipleObjectsBundle.java
index c3e99a83..02a24996 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/bundle/MultipleObjectsBundle.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/bundle/MultipleObjectsBundle.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.bundle;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -55,7 +55,7 @@ public class MultipleObjectsBundle implements ObjectBundle {
*/
public MultipleObjectsBundle() {
this.meta = new BundleMeta();
- this.columns = new ArrayList<List<?>>();
+ this.columns = new ArrayList<>();
}
/**
@@ -232,7 +232,7 @@ public class MultipleObjectsBundle implements ObjectBundle {
bundle.meta.add(smeta.get(i));
}
for(int i = bundle.metaLength(); i < smeta.size(); i++) {
- List<Object> data = new ArrayList<Object>(bundle.dataLength() + 1);
+ List<Object> data = new ArrayList<>(bundle.dataLength() + 1);
bundle.appendColumn(smeta.get(i), data);
}
continue;
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/bundle/ObjectBundle.java b/src/de/lmu/ifi/dbs/elki/datasource/bundle/ObjectBundle.java
index 56966dcf..fbf88f3d 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/bundle/ObjectBundle.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/bundle/ObjectBundle.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.bundle;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/bundle/SingleObjectBundle.java b/src/de/lmu/ifi/dbs/elki/datasource/bundle/SingleObjectBundle.java
index 8a61426d..f0db03f7 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/bundle/SingleObjectBundle.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/bundle/SingleObjectBundle.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.bundle;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -50,7 +50,7 @@ public class SingleObjectBundle implements ObjectBundle {
* Constructor.
*/
public SingleObjectBundle() {
- this(new BundleMeta(), new ArrayList<Object>(5));
+ this(new BundleMeta(), new ArrayList<>(5));
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/bundle/StreamFromBundle.java b/src/de/lmu/ifi/dbs/elki/datasource/bundle/StreamFromBundle.java
index 971478da..de683b30 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/bundle/StreamFromBundle.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/bundle/StreamFromBundle.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.bundle;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/bundle/package-info.java b/src/de/lmu/ifi/dbs/elki/datasource/bundle/package-info.java
index 0b2cbad9..8834e40b 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/bundle/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/bundle/package-info.java
@@ -7,7 +7,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractConversionFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractConversionFilter.java
index 5948cd83..1cb68b30 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractConversionFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractConversionFilter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.filter;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,6 +27,8 @@ import java.util.List;
import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
/**
@@ -71,10 +73,17 @@ public abstract class AbstractConversionFilter<I, O> implements ObjectFilter {
// When necessary, perform an initialization scan
if(prepareStart(castType)) {
+ FiniteProgress pprog = getLogger().isVerbose() ? new FiniteProgress("Preparing normalization.", objects.dataLength(), getLogger()) : null;
for(Object o : column) {
@SuppressWarnings("unchecked")
final I obj = (I) o;
prepareProcessInstance(obj);
+ if (pprog != null) {
+ pprog.incrementProcessed(getLogger());
+ }
+ }
+ if (pprog != null) {
+ pprog.ensureCompleted(getLogger());
}
prepareComplete();
}
@@ -84,17 +93,31 @@ public abstract class AbstractConversionFilter<I, O> implements ObjectFilter {
bundle.appendColumn(convertedType(castType), castColumn);
// Normalization scan
+ FiniteProgress nprog = getLogger().isVerbose() ? new FiniteProgress("Data normalization.", objects.dataLength(), getLogger()) : null;
for(int i = 0; i < objects.dataLength(); i++) {
@SuppressWarnings("unchecked")
final I obj = (I) column.get(i);
final O normalizedObj = filterSingleObject(obj);
castColumn.set(i, normalizedObj);
+ if (nprog != null) {
+ nprog.incrementProcessed(getLogger());
+ }
+ }
+ if (nprog != null) {
+ nprog.ensureCompleted(getLogger());
}
}
return bundle;
}
/**
+ * Class logger.
+ *
+ * @return Logger
+ */
+ abstract protected Logging getLogger();
+
+ /**
* Normalize a single instance.
*
* You can implement this as UnsupportedOperationException if you override
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractStreamConversionFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractStreamConversionFilter.java
index 9b628f2d..5b48a8c0 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractStreamConversionFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractStreamConversionFilter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.filter;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,6 +24,7 @@ package de.lmu.ifi.dbs.elki.datasource.filter;
*/
import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
+import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
import de.lmu.ifi.dbs.elki.datasource.bundle.BundleMeta;
/**
@@ -105,7 +106,7 @@ public abstract class AbstractStreamConversionFilter<I, O> extends AbstractStrea
*
* @return Type restriction
*/
- protected abstract SimpleTypeInformation<? super I> getInputTypeRestriction();
+ protected abstract TypeInformation getInputTypeRestriction();
/**
* Get the output type from the input type after conversion.
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractStreamFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractStreamFilter.java
index 368be1a2..6a210db3 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractStreamFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractStreamFilter.java
@@ -8,7 +8,7 @@ import de.lmu.ifi.dbs.elki.datasource.bundle.StreamFromBundle;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractVectorConversionFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractVectorConversionFilter.java
index 66d10967..b9305aa6 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractVectorConversionFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractVectorConversionFilter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.filter;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractVectorStreamConversionFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractVectorStreamConversionFilter.java
index 695a54e0..6a15c41c 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractVectorStreamConversionFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractVectorStreamConversionFilter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.filter;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/ByLabelFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/ByLabelFilter.java
index 21f05739..2109761a 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/ByLabelFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/ByLabelFilter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.filter;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/ClassLabelFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/ClassLabelFilter.java
index 4a349d3d..e8dc69c3 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/ClassLabelFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/ClassLabelFilter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.filter;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -104,8 +104,8 @@ public class ClassLabelFilter implements ObjectFilter {
done = true;
// We split the label column into two parts
- List<ClassLabel> clscol = new ArrayList<ClassLabel>(objects.dataLength());
- List<LabelList> lblcol = new ArrayList<LabelList>(objects.dataLength());
+ List<ClassLabel> clscol = new ArrayList<>(objects.dataLength());
+ List<LabelList> lblcol = new ArrayList<>(objects.dataLength());
// Split the column
for (Object obj : objects.getColumn(i)) {
@@ -160,7 +160,7 @@ public class ClassLabelFilter implements ObjectFilter {
// parameter class label index
final IntParameter classLabelIndexParam = new IntParameter(CLASS_LABEL_INDEX_ID);
classLabelIndexParam.addConstraint(new GreaterEqualConstraint(0));
- final ObjectParameter<ClassLabel.Factory<?>> classlabelClassParam = new ObjectParameter<ClassLabel.Factory<?>>(CLASS_LABEL_CLASS_ID, ClassLabel.Factory.class, SimpleClassLabel.Factory.class);
+ final ObjectParameter<ClassLabel.Factory<?>> classlabelClassParam = new ObjectParameter<>(CLASS_LABEL_CLASS_ID, ClassLabel.Factory.class, SimpleClassLabel.Factory.class);
config.grab(classLabelIndexParam);
config.grab(classlabelClassParam);
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/ClassLabelFromPatternFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/ClassLabelFromPatternFilter.java
new file mode 100644
index 00000000..97624ac8
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/ClassLabelFromPatternFilter.java
@@ -0,0 +1,213 @@
+package de.lmu.ifi.dbs.elki.datasource.filter;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.BitSet;
+import java.util.regex.Pattern;
+
+import de.lmu.ifi.dbs.elki.data.LabelList;
+import de.lmu.ifi.dbs.elki.data.SimpleClassLabel;
+import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
+import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.datasource.bundle.BundleMeta;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.PatternParameter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.StringParameter;
+
+/**
+ * Streaming filter to derive an outlier class label.
+ *
+ * @author Erich Schubert
+ */
+public class ClassLabelFromPatternFilter extends AbstractStreamFilter {
+ /**
+ * Current meta data
+ */
+ BundleMeta meta = null;
+
+ /**
+ * Bitset of label columns
+ */
+ BitSet labelcols = new BitSet();
+
+ /**
+ * Label to return for positive matches.
+ */
+ SimpleClassLabel positive;
+
+ /**
+ * Label to return for negative matches.
+ */
+ SimpleClassLabel negative;
+
+ /**
+ * Matching pattern.
+ */
+ Pattern pattern;
+
+ /**
+ * Constructor.
+ *
+ * @param pattern Pattern for matching
+ * @param positive Positive label
+ * @param negative Negative label
+ */
+ public ClassLabelFromPatternFilter(Pattern pattern, String positive, String negative) {
+ super();
+ this.pattern = pattern;
+ this.positive = new SimpleClassLabel(positive);
+ this.negative = new SimpleClassLabel(negative);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param pattern Pattern for matching
+ * @param positive Positive label
+ * @param negative Negative label
+ */
+ public ClassLabelFromPatternFilter(Pattern pattern, SimpleClassLabel positive, SimpleClassLabel negative) {
+ super();
+ this.pattern = pattern;
+ this.positive = positive;
+ this.negative = negative;
+ }
+
+ @Override
+ public BundleMeta getMeta() {
+ if (meta == null) {
+ // Rebuild metadata.
+ BundleMeta origmeta = source.getMeta();
+ meta = new BundleMeta(origmeta.size() + 1);
+ meta.add(TypeUtil.SIMPLE_CLASSLABEL);
+ labelcols.clear();
+ for (int i = 0; i < origmeta.size(); i++) {
+ final SimpleTypeInformation<?> orig = origmeta.get(i);
+ if (TypeUtil.GUESSED_LABEL.isAssignableFromType(orig)) {
+ labelcols.set(i);
+ }
+ meta.add(orig);
+ }
+ }
+ return meta;
+ }
+
+ @Override
+ public Object data(int rnum) {
+ if (rnum > 0) {
+ return source.data(rnum - 1);
+ }
+ if (meta == null) {
+ getMeta(); // Trigger build
+ }
+ for (int i = labelcols.nextSetBit(0); i >= 0; i = labelcols.nextSetBit(i + 1)) {
+ Object o = source.data(i);
+ if (o == null) {
+ continue;
+ }
+ if (o instanceof LabelList) {
+ for (String l : (LabelList) o) {
+ if (pattern.matcher(l).find()) {
+ return positive;
+ }
+ }
+ continue;
+ }
+ if (pattern.matcher(o.toString()).find()) {
+ return positive;
+ }
+ }
+ return negative;
+ }
+
+ @Override
+ public Event nextEvent() {
+ final Event ev = source.nextEvent();
+ if (Event.META_CHANGED.equals(ev)) {
+ meta = null;
+ }
+ return ev;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ /**
+ * Pattern for recognizing positive objects.
+ */
+ public static final OptionID PATTERN_ID = new OptionID("class.pattern", "Regular expression to identify positive objects.");
+
+ /**
+ * Class label to assign to positive instances.
+ */
+ public static final OptionID POSITIVE_ID = new OptionID("class.positive", "Class label to use for positive instances.");
+
+ /**
+ * Class label to assign to negative instances.
+ */
+ public static final OptionID NEGATIVE_ID = new OptionID("class.negative", "Class label to use for negative instances.");
+
+ /**
+ * Matching pattern.
+ */
+ Pattern pattern;
+
+ /**
+ * Names for positive and negative classes.
+ */
+ String positive, negative;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+
+ PatternParameter patternP = new PatternParameter(PATTERN_ID);
+ if (config.grab(patternP)) {
+ pattern = patternP.getValue();
+ }
+
+ StringParameter positiveP = new StringParameter(POSITIVE_ID, "positive");
+ if (config.grab(positiveP)) {
+ positive = positiveP.getValue();
+ }
+
+ StringParameter negativeP = new StringParameter(NEGATIVE_ID, "negative");
+ if (config.grab(negativeP)) {
+ negative = negativeP.getValue();
+ }
+ }
+
+ @Override
+ protected ClassLabelFromPatternFilter makeInstance() {
+ return new ClassLabelFromPatternFilter(pattern, positive, negative);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/ExternalIDFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/ExternalIDFilter.java
index 2753534a..926ebe99 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/ExternalIDFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/ExternalIDFilter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.filter;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -87,8 +87,8 @@ public class ExternalIDFilter implements ObjectFilter {
done = true;
// We split the label column into two parts
- List<ExternalID> eidcol = new ArrayList<ExternalID>(objects.dataLength());
- List<LabelList> lblcol = new ArrayList<LabelList>(objects.dataLength());
+ List<ExternalID> eidcol = new ArrayList<>(objects.dataLength());
+ List<LabelList> lblcol = new ArrayList<>(objects.dataLength());
// Split the column
for (Object obj : objects.getColumn(i)) {
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/FilterUtil.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/FilterUtil.java
index 7b794066..9ef9d34f 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/FilterUtil.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/FilterUtil.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.filter;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/FixedDBIDsFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/FixedDBIDsFilter.java
index 2e5071a4..7f09b905 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/FixedDBIDsFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/FixedDBIDsFilter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.filter;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/HistogramJitterFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/HistogramJitterFilter.java
index 6723a12a..37f8f8d9 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/HistogramJitterFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/HistogramJitterFilter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.filter;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -158,7 +158,7 @@ public class HistogramJitterFilter<V extends NumberVector<?>> extends AbstractVe
@Override
protected HistogramJitterFilter<DoubleVector> makeInstance() {
- return new HistogramJitterFilter<DoubleVector>(jitter, rnd);
+ return new HistogramJitterFilter<>(jitter, rnd);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/NaNFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/NaNFilter.java
new file mode 100644
index 00000000..769f3009
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/NaNFilter.java
@@ -0,0 +1,185 @@
+package de.lmu.ifi.dbs.elki.datasource.filter;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.ArrayList;
+import java.util.BitSet;
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.datasource.bundle.BundleMeta;
+import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * A filter to drop all records that contain NaN values.
+ *
+ * Note: currently, only dense vector columns are supported.
+ *
+ * TODO: add support for sparse vectors.
+ *
+ * @author Erich Schubert
+ */
+public class NaNFilter extends AbstractStreamFilter {
+ /**
+ * Class logger
+ */
+ private static final Logging LOG = Logging.getLogger(NaNFilter.class);
+
+ /**
+ * Columns to check.
+ */
+ private BitSet densecols = null;
+
+ /**
+ * Constructor.
+ */
+ public NaNFilter() {
+ super();
+ }
+
+ @Override
+ public BundleMeta getMeta() {
+ return source.getMeta();
+ }
+
+ @Override
+ public Object data(int rnum) {
+ return source.data(rnum);
+ }
+
+ @Override
+ public Event nextEvent() {
+ while (true) {
+ Event ev = source.nextEvent();
+ switch(ev) {
+ case END_OF_STREAM:
+ return ev;
+ case META_CHANGED:
+ updateMeta(source.getMeta());
+ return ev;
+ case NEXT_OBJECT:
+ if (densecols == null) {
+ updateMeta(source.getMeta());
+ }
+ boolean good = true;
+ for (int j = densecols.nextSetBit(0); j >= 0; j = densecols.nextSetBit(j + 1)) {
+ NumberVector<?> v = (NumberVector<?>) source.data(j);
+ if (v == null) {
+ good = false;
+ break;
+ }
+ for (int i = 0; i < v.getDimensionality(); i++) {
+ if (Double.isNaN(v.doubleValue(i))) {
+ good = false;
+ break;
+ }
+ }
+ }
+ if (good) {
+ return ev;
+ }
+ continue;
+ }
+ }
+ }
+
+ /**
+ * Process an updated meta record.
+ *
+ * @param meta Meta record
+ */
+ private void updateMeta(BundleMeta meta) {
+ int cols = meta.size();
+ if (densecols == null) {
+ densecols = new BitSet();
+ } else {
+ densecols.clear();
+ }
+ for (int i = 0; i < cols; i++) {
+ if (TypeUtil.SPARSE_VECTOR_VARIABLE_LENGTH.isAssignableFromType(meta.get(i))) {
+ throw new AbortException("Filtering sparse vectors is not yet supported by this filter. Please contribute.");
+ }
+ // TODO: only check for double and float?
+ if (TypeUtil.NUMBER_VECTOR_VARIABLE_LENGTH.isAssignableFromType(meta.get(i))) {
+ densecols.set(i);
+ continue;
+ }
+ if (TypeUtil.DOUBLE_VECTOR_FIELD.isAssignableFromType(meta.get(i))) {
+ densecols.set(i);
+ continue;
+ }
+ }
+ }
+
+ @Override
+ public MultipleObjectsBundle filter(final MultipleObjectsBundle objects) {
+ if (LOG.isDebuggingFinest()) {
+ LOG.debugFinest("Removing records with NaN values.");
+ }
+
+ updateMeta(objects.meta());
+ MultipleObjectsBundle bundle = new MultipleObjectsBundle();
+ for (int j = 0; j < objects.metaLength(); j++) {
+ bundle.appendColumn(objects.meta(j), new ArrayList<>());
+ }
+ for (int i = 0; i < objects.dataLength(); i++) {
+ final Object[] row = objects.getRow(i);
+ boolean good = true;
+ for (int j = densecols.nextSetBit(0); j >= 0; j = densecols.nextSetBit(j + 1)) {
+ NumberVector<?> v = (NumberVector<?>) row[j];
+ if (v == null) {
+ good = false;
+ break;
+ }
+ for (int d = 0; d < v.getDimensionality(); d++) {
+ if (Double.isNaN(v.doubleValue(d))) {
+ good = false;
+ break;
+ }
+ }
+ }
+ if (good) {
+ bundle.appendSimple(row);
+ }
+ }
+ return bundle;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected Object makeInstance() {
+ return new NaNFilter();
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/NoMissingValuesFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/NoMissingValuesFilter.java
index bfc6ad5c..b3f0af53 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/NoMissingValuesFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/NoMissingValuesFilter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.filter;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -97,7 +97,7 @@ public class NoMissingValuesFilter extends AbstractStreamFilter {
MultipleObjectsBundle bundle = new MultipleObjectsBundle();
for(int j = 0; j < objects.metaLength(); j++) {
- bundle.appendColumn(objects.meta(j), new ArrayList<Object>());
+ bundle.appendColumn(objects.meta(j), new ArrayList<>());
}
for(int i = 0; i < objects.dataLength(); i++) {
boolean good = true;
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/NoOpFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/NoOpFilter.java
index 264f58fd..ce758763 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/NoOpFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/NoOpFilter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.filter;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/ObjectFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/ObjectFilter.java
index b3670e9b..5073cea8 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/ObjectFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/ObjectFilter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.filter;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,7 +24,6 @@ package de.lmu.ifi.dbs.elki.datasource.filter;
*/
import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle;
-import de.lmu.ifi.dbs.elki.utilities.InspectionUtilFrequentlyScanned;
/**
* Object filters as part of the input step.
@@ -35,7 +34,7 @@ import de.lmu.ifi.dbs.elki.utilities.InspectionUtilFrequentlyScanned;
*
* @apiviz.uses MultipleObjectsBundle oneway - - «filters»
*/
-public interface ObjectFilter extends InspectionUtilFrequentlyScanned {
+public interface ObjectFilter {
/**
* Filter a set of object packages.
*
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/RandomSamplingStreamFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/RandomSamplingStreamFilter.java
index 0fbec083..5c8d07d0 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/RandomSamplingStreamFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/RandomSamplingStreamFilter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.filter;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/ShuffleObjectsFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/ShuffleObjectsFilter.java
index 01a6da10..b8bf968b 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/ShuffleObjectsFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/ShuffleObjectsFilter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.filter;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -96,7 +96,7 @@ public class ShuffleObjectsFilter implements ObjectFilter {
for (int j = 0; j < objects.metaLength(); j++) {
// Reorder column accordingly
List<?> in = objects.getColumn(j);
- List<Object> data = new ArrayList<Object>(size);
+ List<Object> data = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
data.add(in.get(offsets[i]));
}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/SortByLabelFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/SortByLabelFilter.java
index 308a54b1..d35d9cde 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/SortByLabelFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/SortByLabelFilter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.filter;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -89,7 +89,7 @@ public class SortByLabelFilter implements ObjectFilter {
for (int j = 0; j < objects.metaLength(); j++) {
// Reorder column accordingly
List<?> in = objects.getColumn(j);
- List<Object> data = new ArrayList<Object>(size);
+ List<Object> data = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
data.add(in.get(offsets[i]));
}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/SparseVectorFieldFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/SparseVectorFieldFilter.java
index d3ef418d..97960907 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/SparseVectorFieldFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/SparseVectorFieldFilter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.filter;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,6 +27,7 @@ import de.lmu.ifi.dbs.elki.data.SparseNumberVector;
import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
import de.lmu.ifi.dbs.elki.data.type.VectorFieldTypeInformation;
+import de.lmu.ifi.dbs.elki.logging.Logging;
/**
* Class that turns sparse float vectors into a proper vector field, by setting
@@ -38,6 +39,11 @@ import de.lmu.ifi.dbs.elki.data.type.VectorFieldTypeInformation;
*/
public class SparseVectorFieldFilter<V extends SparseNumberVector<?>> extends AbstractConversionFilter<V, V> {
/**
+ * Class logger.
+ */
+ private static final Logging LOG = Logging.getLogger(SparseVectorFieldFilter.class);
+
+ /**
* Maximum dimension.
*/
int maxdim = -1;
@@ -74,6 +80,11 @@ public class SparseVectorFieldFilter<V extends SparseNumberVector<?>> extends Ab
@Override
protected SimpleTypeInformation<? super V> convertedType(SimpleTypeInformation<V> in) {
SparseNumberVector.Factory<V, ?> factory = (SparseNumberVector.Factory<V, ?>) FilterUtil.guessFactory(in);
- return new VectorFieldTypeInformation<V>(factory, maxdim);
+ return new VectorFieldTypeInformation<>(factory, maxdim);
+ }
+
+ @Override
+ protected Logging getLogger() {
+ return LOG;
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/SplitNumberVectorFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/SplitNumberVectorFilter.java
index 898eeff7..8146bd5b 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/SplitNumberVectorFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/SplitNumberVectorFilter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.filter;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -87,10 +87,10 @@ public class SplitNumberVectorFilter<V extends NumberVector<?>> implements Objec
Factory<V, ?> factory = FilterUtil.guessFactory(vtype);
// Get the replacement type informations
- VectorFieldTypeInformation<V> type1 = new VectorFieldTypeInformation<V>(factory, dims.length);
- VectorFieldTypeInformation<V> type2 = new VectorFieldTypeInformation<V>(factory, vtype.getDimensionality() - dims.length);
- final List<V> col1 = new ArrayList<V>(column.size());
- final List<V> col2 = new ArrayList<V>(column.size());
+ VectorFieldTypeInformation<V> type1 = new VectorFieldTypeInformation<>(factory, dims.length);
+ VectorFieldTypeInformation<V> type2 = new VectorFieldTypeInformation<>(factory, vtype.getDimensionality() - dims.length);
+ final List<V> col1 = new ArrayList<>(column.size());
+ final List<V> col2 = new ArrayList<>(column.size());
bundle.appendColumn(type1, col1);
bundle.appendColumn(type2, col2);
@@ -145,7 +145,7 @@ public class SplitNumberVectorFilter<V extends NumberVector<?>> implements Objec
for (int i = 1; i < dims.length; i++) {
m = Math.max(dims[i], m);
}
- return new VectorFieldTypeInformation<NumberVector<?>>(NumberVector.class, m, Integer.MAX_VALUE);
+ return new VectorFieldTypeInformation<>(NumberVector.class, m, Integer.MAX_VALUE);
}
/**
@@ -182,7 +182,7 @@ public class SplitNumberVectorFilter<V extends NumberVector<?>> implements Objec
@Override
protected SplitNumberVectorFilter<V> makeInstance() {
- return new SplitNumberVectorFilter<V>(dims);
+ return new SplitNumberVectorFilter<>(dims);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/StreamFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/StreamFilter.java
index 5d121659..798cd05d 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/StreamFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/StreamFilter.java
@@ -6,7 +6,7 @@ import de.lmu.ifi.dbs.elki.datasource.bundle.BundleStreamSource;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AbstractNormalization.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AbstractNormalization.java
index 2dcf09f8..0b4d7ae0 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AbstractNormalization.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AbstractNormalization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.filter.normalization;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,7 +25,6 @@ package de.lmu.ifi.dbs.elki.datasource.filter.normalization;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
-import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle;
import de.lmu.ifi.dbs.elki.datasource.filter.AbstractVectorConversionFilter;
import de.lmu.ifi.dbs.elki.math.linearalgebra.LinearEquationSystem;
@@ -51,11 +50,6 @@ public abstract class AbstractNormalization<O extends NumberVector<?>> extends A
}
@Override
- public MultipleObjectsBundle normalizeObjects(MultipleObjectsBundle objects) {
- return super.filter(objects);
- }
-
- @Override
public LinearEquationSystem transform(LinearEquationSystem linearEquationSystem) {
// FIXME: implement.
throw new UnsupportedOperationException("Not yet implemented!");
@@ -65,4 +59,4 @@ public abstract class AbstractNormalization<O extends NumberVector<?>> extends A
public String toString() {
return getClass().getName();
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AbstractStreamNormalization.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AbstractStreamNormalization.java
index a1e2c55e..54fc7794 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AbstractStreamNormalization.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AbstractStreamNormalization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.filter.normalization;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,7 +25,6 @@ package de.lmu.ifi.dbs.elki.datasource.filter.normalization;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
-import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle;
import de.lmu.ifi.dbs.elki.datasource.filter.AbstractVectorStreamConversionFilter;
import de.lmu.ifi.dbs.elki.math.linearalgebra.LinearEquationSystem;
@@ -49,11 +48,6 @@ public abstract class AbstractStreamNormalization<O extends NumberVector<?>> ext
initializeOutputType(in);
return in;
}
-
- @Override
- public MultipleObjectsBundle normalizeObjects(MultipleObjectsBundle objects) {
- return super.filter(objects);
- }
@Override
public LinearEquationSystem transform(LinearEquationSystem linearEquationSystem) {
@@ -67,4 +61,4 @@ public abstract class AbstractStreamNormalization<O extends NumberVector<?>> ext
result.append("normalization class: ").append(getClass().getName());
return result.toString();
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AttributeWiseCDFNormalization.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AttributeWiseCDFNormalization.java
new file mode 100644
index 00000000..8fd46336
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AttributeWiseCDFNormalization.java
@@ -0,0 +1,294 @@
+package de.lmu.ifi.dbs.elki.datasource.filter.normalization;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
+import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.data.type.VectorFieldTypeInformation;
+import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle;
+import de.lmu.ifi.dbs.elki.datasource.filter.FilterUtil;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.LinearEquationSystem;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.Distribution;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.DistributionEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.meta.BestFitEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.tests.KolmogorovSmirnovTest;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.ExceptionMessages;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectListParameter;
+
+/**
+ * Class to perform and undo a normalization on real vectors by estimating the
+ * distribution of values along each dimension independently, then rescaling
+ * objects to the cumulative density function (CDF) value at the original
+ * coordinate.
+ *
+ * This process is for example also discussed in section 3.4 of
+ * <p>
+ * Effects of Feature Normalization on Image Retrieval <br/>
+ * S. Aksoy, R. M. Haralick
+ * </p>
+ * but they do not detail how to obtain an appropriate function `F`.
+ *
+ * @author Erich Schubert
+ * @param <V> vector type
+ *
+ * @apiviz.uses NumberVector
+ * @apiviz.uses DistributionEstimator
+ */
+// TODO: extract superclass AbstractAttributeWiseNormalization
+public class AttributeWiseCDFNormalization<V extends NumberVector<?>> implements Normalization<V> {
+ /**
+ * Class logger.
+ */
+ private static final Logging LOG = Logging.getLogger(AttributeWiseCDFNormalization.class);
+
+ /**
+ * Stores the distribution estimators
+ */
+ private List<DistributionEstimator<?>> estimators;
+
+ /**
+ * Stores the estimated distributions
+ */
+ private List<Distribution> dists;
+
+ /**
+ * Number vector factory.
+ */
+ protected NumberVector.Factory<V, ?> factory;
+
+ /**
+ * Constructor.
+ *
+ * @param estimators Distribution estimators
+ */
+ public AttributeWiseCDFNormalization(List<DistributionEstimator<?>> estimators) {
+ super();
+ this.estimators = estimators;
+ }
+
+ @Override
+ public MultipleObjectsBundle filter(MultipleObjectsBundle objects) {
+ if (objects.dataLength() == 0) {
+ return objects;
+ }
+ for (int r = 0; r < objects.metaLength(); r++) {
+ SimpleTypeInformation<?> type = (SimpleTypeInformation<?>) objects.meta(r);
+ final List<?> column = (List<?>) objects.getColumn(r);
+ if (!TypeUtil.NUMBER_VECTOR_FIELD.isAssignableFromType(type)) {
+ continue;
+ }
+ @SuppressWarnings("unchecked")
+ final List<V> castColumn = (List<V>) column;
+ // Get the replacement type information
+ @SuppressWarnings("unchecked")
+ final VectorFieldTypeInformation<V> castType = (VectorFieldTypeInformation<V>) type;
+ factory = FilterUtil.guessFactory(castType);
+
+ // Scan to find the best
+ final int dim = castType.getDimensionality();
+ dists = new ArrayList<>(dim);
+ // Scratch space for testing:
+ double[] test = new double[castColumn.size()];
+
+ // We iterate over dimensions, this kind of filter needs fast random
+ // access.
+ Adapter<V> adapter = new Adapter<>();
+ for (int d = 0; d < dim; d++) {
+ adapter.dim = d;
+ if (estimators.size() == 1) {
+ dists.add(estimators.get(0).estimate(castColumn, adapter));
+ } else {
+ Distribution best = null;
+ double bestq = Double.POSITIVE_INFINITY;
+ trials: for (DistributionEstimator<?> est : estimators) {
+ try {
+ Distribution dist = est.estimate(castColumn, adapter);
+ for (int i = 0; i < test.length; i++) {
+ test[i] = dist.cdf(castColumn.get(i).doubleValue(d));
+ if (Double.isNaN(test[i])) {
+ LOG.warning("Got NaN after fitting " + est.toString() + ": " + dist.toString());
+ continue trials;
+ }
+ if (Double.isInfinite(test[i])) {
+ LOG.warning("Got infinite value after fitting " + est.toString() + ": " + dist.toString());
+ continue trials;
+ }
+ }
+ Arrays.sort(test);
+ double q = KolmogorovSmirnovTest.simpleTest(test);
+ if (LOG.isVeryVerbose()) {
+ LOG.veryverbose("Estimator " + est.toString() + " (" + dist.toString() + ") has maximum deviation " + q + " for dimension " + d);
+ }
+ if (best == null || q < bestq) {
+ best = dist;
+ bestq = q;
+ }
+ } catch (ArithmeticException e) {
+ if (LOG.isVeryVerbose()) {
+ LOG.veryverbose("Fitting distribution " + est + " failed: " + e.getMessage());
+ }
+ continue;
+ }
+ }
+ if (LOG.isVerbose()) {
+ LOG.verbose("Best fit for dimension " + d + ": " + best.toString());
+ }
+ dists.add(best);
+ }
+ }
+
+ // Normalization scan
+ double[] buf = new double[dim];
+ for (int i = 0; i < objects.dataLength(); i++) {
+ final V obj = castColumn.get(i);
+ for (int d = 0; d < dim; d++) {
+ buf[d] = dists.get(d).cdf(obj.doubleValue(d));
+ }
+ castColumn.set(i, factory.newNumberVector(buf));
+ }
+ }
+ return objects;
+ }
+
+ @Override
+ public V restore(V featureVector) throws NonNumericFeaturesException {
+ throw new UnsupportedOperationException(ExceptionMessages.UNSUPPORTED_NOT_YET);
+ }
+
+ @Override
+ public LinearEquationSystem transform(LinearEquationSystem linearEquationSystem) {
+ throw new UnsupportedOperationException(ExceptionMessages.UNSUPPORTED_NOT_YET);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder result = new StringBuilder();
+ result.append("normalization class: ").append(getClass().getName());
+ result.append('\n');
+ result.append("normalization distributions: ");
+ boolean first = true;
+ for (DistributionEstimator<?> est : estimators) {
+ if (!first) {
+ result.append(',');
+ }
+ first = false;
+ result.append(est.getClass().getSimpleName());
+ }
+ return result.toString();
+ }
+
+ private static class Adapter<V extends NumberVector<?>> implements NumberArrayAdapter<Double, List<V>> {
+ /**
+ * Dimension to process.
+ */
+
+ int dim;
+
+ @Override
+ public int size(List<V> array) {
+ return array.size();
+ }
+
+ @Override
+ public Double get(List<V> array, int off) throws IndexOutOfBoundsException {
+ return getDouble(array, off);
+ }
+
+ @Override
+ public double getDouble(List<V> array, int off) throws IndexOutOfBoundsException {
+ return array.get(off).doubleValue(dim);
+ }
+
+ @Override
+ public float getFloat(List<V> array, int off) throws IndexOutOfBoundsException {
+ return array.get(off).floatValue(dim);
+ }
+
+ @Override
+ public int getInteger(List<V> array, int off) throws IndexOutOfBoundsException {
+ return array.get(off).intValue(dim);
+ }
+
+ @Override
+ public short getShort(List<V> array, int off) throws IndexOutOfBoundsException {
+ return array.get(off).shortValue(dim);
+ }
+
+ @Override
+ public long getLong(List<V> array, int off) throws IndexOutOfBoundsException {
+ return array.get(off).longValue(dim);
+ }
+
+ @Override
+ public byte getByte(List<V> array, int off) throws IndexOutOfBoundsException {
+ return array.get(off).byteValue(dim);
+ }
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer<V extends NumberVector<?>> extends AbstractParameterizer {
+ /**
+ * Parameter for distribution estimators.
+ */
+ public static final OptionID DISTRIBUTIONS_ID = new OptionID("normalize.distributions", "A list of the distribution estimators to try.");
+
+ /**
+ * Stores the distribution estimators
+ */
+ private List<DistributionEstimator<?>> estimators;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ ObjectListParameter<DistributionEstimator<?>> estP = new ObjectListParameter<>(DISTRIBUTIONS_ID, DistributionEstimator.class);
+ List<Class<? extends DistributionEstimator<?>>> def = new ArrayList<>(1);
+ def.add(BestFitEstimator.class);
+ estP.setDefaultValue(def);
+ if (config.grab(estP)) {
+ estimators = estP.instantiateClasses(config);
+ }
+ }
+
+ @Override
+ protected AttributeWiseCDFNormalization<V> makeInstance() {
+ return new AttributeWiseCDFNormalization<>(estimators);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AttributeWiseErfNormalization.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AttributeWiseErfNormalization.java
index f5e24bca..9a263171 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AttributeWiseErfNormalization.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AttributeWiseErfNormalization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.filter.normalization;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,6 +26,7 @@ package de.lmu.ifi.dbs.elki.datasource.filter.normalization;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.math.statistics.distribution.NormalDistribution;
/**
@@ -40,6 +41,11 @@ import de.lmu.ifi.dbs.elki.math.statistics.distribution.NormalDistribution;
*/
public class AttributeWiseErfNormalization<O extends NumberVector<?>> extends AbstractNormalization<O> {
/**
+ * Class logger.
+ */
+ private static final Logging LOG = Logging.getLogger(AttributeWiseErfNormalization.class);
+
+ /**
* Constructor.
*/
public AttributeWiseErfNormalization() {
@@ -54,7 +60,7 @@ public class AttributeWiseErfNormalization<O extends NumberVector<?>> extends Ab
@Override
protected O filterSingleObject(O obj) {
double[] val = new double[obj.getDimensionality()];
- for(int i = 0; i < val.length; i++) {
+ for (int i = 0; i < val.length; i++) {
val[i] = NormalDistribution.erf(obj.doubleValue(i));
}
return factory.newNumberVector(val);
@@ -64,4 +70,9 @@ public class AttributeWiseErfNormalization<O extends NumberVector<?>> extends Ab
protected SimpleTypeInformation<? super O> getInputTypeRestriction() {
return TypeUtil.NUMBER_VECTOR_FIELD;
}
+
+ @Override
+ protected Logging getLogger() {
+ return LOG;
+ }
}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AttributeWiseMADNormalization.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AttributeWiseMADNormalization.java
new file mode 100644
index 00000000..8c4f15e1
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AttributeWiseMADNormalization.java
@@ -0,0 +1,202 @@
+package de.lmu.ifi.dbs.elki.datasource.filter.normalization;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.List;
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
+import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.data.type.VectorFieldTypeInformation;
+import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle;
+import de.lmu.ifi.dbs.elki.datasource.filter.FilterUtil;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.LinearEquationSystem;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.NormalDistribution;
+import de.lmu.ifi.dbs.elki.utilities.FormatUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.QuickSelect;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.ExceptionMessages;
+
+/**
+ * Median Absolute Deviation is used for scaling the data set as follows:
+ *
+ * First, the median, and median absolute deviation are computed in each axis.
+ * Then, each value is projected to (x - median(X)) / MAD(X).
+ *
+ * This is similar to z-standardization of data sets, except that it is more
+ * robust towards outliers, and only slightly more expensive to compute.
+ *
+ * @author Erich Schubert
+ * @param <V> vector type
+ *
+ * @apiviz.uses NumberVector
+ */
+// TODO: extract superclass AbstractAttributeWiseNormalization
+public class AttributeWiseMADNormalization<V extends NumberVector<?>> implements Normalization<V> {
+ /**
+ * Class logger.
+ */
+ private static final Logging LOG = Logging.getLogger(AttributeWiseMADNormalization.class);
+
+ /**
+ * Number vector factory.
+ */
+ protected NumberVector.Factory<V, ?> factory;
+
+ /**
+ * Stores the median in each dimension.
+ */
+ private double[] median = new double[0];
+
+ /**
+ * Stores the median absolute deviation in each dimension.
+ */
+ private double[] madsigma = new double[0];
+
+ /**
+ * Constructor.
+ */
+ public AttributeWiseMADNormalization() {
+ super();
+ }
+
+ @Override
+ public MultipleObjectsBundle filter(MultipleObjectsBundle objects) {
+ if (objects.dataLength() == 0) {
+ return objects;
+ }
+ for (int r = 0; r < objects.metaLength(); r++) {
+ SimpleTypeInformation<?> type = (SimpleTypeInformation<?>) objects.meta(r);
+ final List<?> column = (List<?>) objects.getColumn(r);
+ if (!TypeUtil.NUMBER_VECTOR_FIELD.isAssignableFromType(type)) {
+ continue;
+ }
+ @SuppressWarnings("unchecked")
+ final List<V> castColumn = (List<V>) column;
+ // Get the replacement type information
+ @SuppressWarnings("unchecked")
+ final VectorFieldTypeInformation<V> castType = (VectorFieldTypeInformation<V>) type;
+ factory = FilterUtil.guessFactory(castType);
+
+ // Scan to find the best
+ final int dim = castType.getDimensionality();
+ median = new double[dim];
+ madsigma = new double[dim];
+ // Scratch space for testing:
+ double[] test = new double[castColumn.size()];
+
+ FiniteProgress dprog = LOG.isVerbose() ? new FiniteProgress("Analyzing data.", dim, LOG) : null;
+ // We iterate over dimensions, this kind of filter needs fast random
+ // access.
+ for (int d = 0; d < dim; d++) {
+ for (int i = 0; i < test.length; i++) {
+ test[i] = castColumn.get(i).doubleValue(d);
+ }
+ final double med = QuickSelect.median(test);
+ median[d] = med;
+ for (int i = 0; i < test.length; i++) {
+ test[i] = Math.abs(test[i] - med);
+ }
+ // Rescale the true MAD for the best standard deviation estimate:
+ madsigma[d] = QuickSelect.median(test) * NormalDistribution.ONEBYPHIINV075;
+ if (dprog != null) {
+ dprog.incrementProcessed(LOG);
+ }
+ }
+ if (dprog != null) {
+ dprog.ensureCompleted(LOG);
+ }
+
+ FiniteProgress nprog = LOG.isVerbose() ? new FiniteProgress("Data normalization.", objects.dataLength(), LOG) : null;
+ // Normalization scan
+ double[] buf = new double[dim];
+ for (int i = 0; i < objects.dataLength(); i++) {
+ final V obj = castColumn.get(i);
+ for (int d = 0; d < dim; d++) {
+ buf[d] = normalize(d, obj.doubleValue(d));
+ }
+ castColumn.set(i, factory.newNumberVector(buf));
+ if (nprog != null) {
+ nprog.incrementProcessed(LOG);
+ }
+ }
+ if (nprog != null) {
+ nprog.ensureCompleted(LOG);
+ }
+ }
+ return objects;
+ }
+
+ @Override
+ public V restore(V featureVector) throws NonNumericFeaturesException {
+ if (featureVector.getDimensionality() == median.length) {
+ double[] values = new double[featureVector.getDimensionality()];
+ for (int d = 0; d < featureVector.getDimensionality(); d++) {
+ values[d] = restore(d, featureVector.doubleValue(d));
+ }
+ return factory.newNumberVector(values);
+ } else {
+ throw new NonNumericFeaturesException("Attributes cannot be resized: current dimensionality: " + featureVector.getDimensionality() + " former dimensionality: " + median.length);
+ }
+ }
+
+ @Override
+ public LinearEquationSystem transform(LinearEquationSystem linearEquationSystem) throws NonNumericFeaturesException {
+ throw new UnsupportedOperationException(ExceptionMessages.UNSUPPORTED_NOT_YET);
+ }
+
+ /**
+ * Normalize a single dimension.
+ *
+ * @param d Dimension
+ * @param val Value
+ * @return Normalized value
+ */
+ private double normalize(int d, double val) {
+ return (val - median[d]) / madsigma[d];
+ }
+
+ /**
+ * Restore a single dimension.
+ *
+ * @param d Dimension
+ * @param val Value
+ * @return Normalized value
+ */
+ private double restore(int d, double val) {
+ return (val * madsigma[d]) + median[d];
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder result = new StringBuilder();
+ result.append("normalization class: ").append(getClass().getName());
+ result.append('\n');
+ result.append("normalization median: ").append(FormatUtil.format(median));
+ result.append('\n');
+ result.append("normalization MAD sigma: ").append(FormatUtil.format(madsigma));
+ return result.toString();
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AttributeWiseMinMaxNormalization.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AttributeWiseMinMaxNormalization.java
index 62c0bf12..31f72660 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AttributeWiseMinMaxNormalization.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AttributeWiseMinMaxNormalization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.filter.normalization;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,6 +28,7 @@ import java.util.ArrayList;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.math.linearalgebra.LinearEquationSystem;
import de.lmu.ifi.dbs.elki.utilities.FormatUtil;
import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayLikeUtil;
@@ -52,6 +53,11 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Parameter;
// TODO: extract superclass AbstractAttributeWiseNormalization
public class AttributeWiseMinMaxNormalization<V extends NumberVector<?>> extends AbstractNormalization<V> {
/**
+ * Class logger.
+ */
+ private static final Logging LOG = Logging.getLogger(AttributeWiseMinMaxNormalization.class);
+
+ /**
* Parameter for minimum.
*/
public static final OptionID MINIMA_ID = new OptionID("normalize.min", "a comma separated concatenation of the minimum values in each dimension that are mapped to 0. If no value is specified, the minimum value of the attribute range in this dimension will be taken.");
@@ -91,24 +97,24 @@ public class AttributeWiseMinMaxNormalization<V extends NumberVector<?>> extends
@Override
protected void prepareProcessInstance(V featureVector) {
// First object? Then initialize.
- if(minima.length == 0 || maxima.length == 0) {
+ if (minima.length == 0 || maxima.length == 0) {
int dimensionality = featureVector.getDimensionality();
minima = new double[dimensionality];
maxima = new double[dimensionality];
- for(int i = 0; i < dimensionality; i++) {
+ for (int i = 0; i < dimensionality; i++) {
maxima[i] = -Double.MAX_VALUE;
minima[i] = Double.MAX_VALUE;
}
}
- if(minima.length != featureVector.getDimensionality()) {
+ if (minima.length != featureVector.getDimensionality()) {
throw new IllegalArgumentException("FeatureVectors differ in length.");
}
- for(int d = 0; d < featureVector.getDimensionality(); d++) {
+ for (int d = 0; d < featureVector.getDimensionality(); d++) {
final double val = featureVector.doubleValue(d);
- if(val > maxima[d]) {
+ if (val > maxima[d]) {
maxima[d] = val;
}
- if(val < minima[d]) {
+ if (val < minima[d]) {
minima[d] = val;
}
}
@@ -117,10 +123,10 @@ public class AttributeWiseMinMaxNormalization<V extends NumberVector<?>> extends
@Override
protected V filterSingleObject(V featureVector) {
double[] values = new double[featureVector.getDimensionality()];
- if(minima.length != featureVector.getDimensionality()) {
+ if (minima.length != featureVector.getDimensionality()) {
throw new IllegalArgumentException("FeatureVectors and given Minima/Maxima differ in length.");
}
- for(int d = 0; d < featureVector.getDimensionality(); d++) {
+ for (int d = 0; d < featureVector.getDimensionality(); d++) {
values[d] = (featureVector.doubleValue(d) - minima[d]) / factor(d);
}
return factory.newNumberVector(values);
@@ -128,14 +134,13 @@ public class AttributeWiseMinMaxNormalization<V extends NumberVector<?>> extends
@Override
public V restore(V featureVector) throws NonNumericFeaturesException {
- if(featureVector.getDimensionality() == maxima.length && featureVector.getDimensionality() == minima.length) {
+ if (featureVector.getDimensionality() == maxima.length && featureVector.getDimensionality() == minima.length) {
double[] values = new double[featureVector.getDimensionality()];
- for(int d = 0; d < featureVector.getDimensionality(); d++) {
+ for (int d = 0; d < featureVector.getDimensionality(); d++) {
values[d] = (featureVector.doubleValue(d) * (factor(d)) + minima[d]);
}
return factory.newNumberVector(values);
- }
- else {
+ } else {
throw new NonNumericFeaturesException("Attributes cannot be resized: current dimensionality: " + featureVector.getDimensionality() + " former dimensionality: " + maxima.length);
}
}
@@ -161,10 +166,10 @@ public class AttributeWiseMinMaxNormalization<V extends NumberVector<?>> extends
int[] row = linearEquationSystem.getRowPermutations();
int[] col = linearEquationSystem.getColumnPermutations();
- for(int i = 0; i < coeff.length; i++) {
- for(int r = 0; r < coeff.length; r++) {
+ for (int i = 0; i < coeff.length; i++) {
+ for (int r = 0; r < coeff.length; r++) {
double sum = 0.0;
- for(int c = 0; c < coeff[0].length; c++) {
+ for (int c = 0; c < coeff[0].length; c++) {
sum += minima[c] * coeff[row[r]][col[c]] / factor(c);
coeff[row[r]][col[c]] = coeff[row[r]][col[c]] / factor(c);
}
@@ -186,12 +191,17 @@ public class AttributeWiseMinMaxNormalization<V extends NumberVector<?>> extends
result.append("normalization maxima: ").append(FormatUtil.format(maxima));
return result.toString();
}
-
+
@Override
protected SimpleTypeInformation<? super V> getInputTypeRestriction() {
return TypeUtil.NUMBER_VECTOR_FIELD;
}
+ @Override
+ protected Logging getLogger() {
+ return LOG;
+ }
+
/**
* Parameterization class.
*
@@ -214,20 +224,20 @@ public class AttributeWiseMinMaxNormalization<V extends NumberVector<?>> extends
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
DoubleListParameter minimaP = new DoubleListParameter(MINIMA_ID, true);
- if(config.grab(minimaP)) {
+ if (config.grab(minimaP)) {
minima = ArrayLikeUtil.toPrimitiveDoubleArray(minimaP.getValue());
}
DoubleListParameter maximaP = new DoubleListParameter(MAXIMA_ID, true);
- if(config.grab(maximaP)) {
+ if (config.grab(maximaP)) {
maxima = ArrayLikeUtil.toPrimitiveDoubleArray(maximaP.getValue());
}
- ArrayList<Parameter<?>> global_1 = new ArrayList<Parameter<?>>();
+ ArrayList<Parameter<?>> global_1 = new ArrayList<>();
global_1.add(minimaP);
global_1.add(maximaP);
config.checkConstraint(new AllOrNoneMustBeSetGlobalConstraint(global_1));
- ArrayList<ListParameter<?>> global = new ArrayList<ListParameter<?>>();
+ ArrayList<ListParameter<?>> global = new ArrayList<>();
global.add(minimaP);
global.add(maximaP);
config.checkConstraint(new EqualSizeGlobalConstraint(global));
@@ -235,7 +245,7 @@ public class AttributeWiseMinMaxNormalization<V extends NumberVector<?>> extends
@Override
protected AttributeWiseMinMaxNormalization<V> makeInstance() {
- return new AttributeWiseMinMaxNormalization<V>(minima, maxima);
+ return new AttributeWiseMinMaxNormalization<>(minima, maxima);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AttributeWiseVarianceNormalization.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AttributeWiseVarianceNormalization.java
index 0671231d..072d1a68 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AttributeWiseVarianceNormalization.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AttributeWiseVarianceNormalization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.filter.normalization;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -96,15 +96,22 @@ public class AttributeWiseVarianceNormalization<V extends NumberVector<?>> exten
this.stddev = stddev;
}
+ /**
+ * Constructor.
+ */
+ public AttributeWiseVarianceNormalization() {
+ super();
+ }
+
@Override
protected boolean prepareStart(SimpleTypeInformation<V> in) {
- return (mean.length == 0 || stddev.length == 0);
+ return (mean == null || stddev == null || mean.length == 0 || stddev.length == 0);
}
@Override
protected void prepareProcessInstance(V featureVector) {
// First object? Then init. (We didn't have a dimensionality before!)
- if(mvs == null) {
+ if(mvs == null || mvs.length == 0) {
int dimensionality = featureVector.getDimensionality();
mvs = MeanVariance.newArray(dimensionality);
}
@@ -231,6 +238,11 @@ public class AttributeWiseVarianceNormalization<V extends NumberVector<?>> exten
return result.toString();
}
+ @Override
+ protected Logging getLogger() {
+ return LOG;
+ }
+
/**
* Parameterization class.
*
@@ -268,12 +280,12 @@ public class AttributeWiseVarianceNormalization<V extends NumberVector<?>> exten
}
}
- ArrayList<Parameter<?>> global_1 = new ArrayList<Parameter<?>>();
+ ArrayList<Parameter<?>> global_1 = new ArrayList<>();
global_1.add(meanP);
global_1.add(stddevP);
config.checkConstraint(new AllOrNoneMustBeSetGlobalConstraint(global_1));
- ArrayList<ListParameter<?>> global = new ArrayList<ListParameter<?>>();
+ ArrayList<ListParameter<?>> global = new ArrayList<>();
global.add(meanP);
global.add(stddevP);
config.checkConstraint(new EqualSizeGlobalConstraint(global));
@@ -281,7 +293,7 @@ public class AttributeWiseVarianceNormalization<V extends NumberVector<?>> exten
@Override
protected AttributeWiseVarianceNormalization<V> makeInstance() {
- return new AttributeWiseVarianceNormalization<V>(mean, stddev);
+ return new AttributeWiseVarianceNormalization<>(mean, stddev);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/InverseDocumentFrequencyNormalization.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/InverseDocumentFrequencyNormalization.java
index 24f3a850..94bcb32f 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/InverseDocumentFrequencyNormalization.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/InverseDocumentFrequencyNormalization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.filter.normalization;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -32,6 +32,7 @@ import java.util.BitSet;
import de.lmu.ifi.dbs.elki.data.SparseNumberVector;
import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.logging.Logging;
/**
* Normalization for text frequency vectors, using the inverse document
@@ -45,6 +46,11 @@ import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
*/
public class InverseDocumentFrequencyNormalization<V extends SparseNumberVector<?>> extends AbstractNormalization<V> {
/**
+ * Class logger.
+ */
+ private static final Logging LOG = Logging.getLogger(InverseDocumentFrequencyNormalization.class);
+
+ /**
* The IDF storage.
*/
TIntDoubleMap idf = new TIntDoubleHashMap();
@@ -116,4 +122,9 @@ public class InverseDocumentFrequencyNormalization<V extends SparseNumberVector<
protected SimpleTypeInformation<? super V> getInputTypeRestriction() {
return TypeUtil.SPARSE_VECTOR_FIELD;
}
+
+ @Override
+ protected Logging getLogger() {
+ return LOG;
+ }
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/LengthNormalization.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/LengthNormalization.java
index 457cc6eb..a12dea3b 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/LengthNormalization.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/LengthNormalization.java
@@ -27,7 +27,7 @@ import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DoubleNorm;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.math.linearalgebra.LinearEquationSystem;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
@@ -101,7 +101,7 @@ public class LengthNormalization<V extends NumberVector<?>> extends AbstractStre
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- ObjectParameter<DoubleNorm<? super V>> normP = new ObjectParameter<DoubleNorm<? super V>>(NORM_ID, DoubleNorm.class, EuclideanDistanceFunction.class);
+ ObjectParameter<DoubleNorm<? super V>> normP = new ObjectParameter<>(NORM_ID, DoubleNorm.class, EuclideanDistanceFunction.class);
if(config.grab(normP)) {
norm = normP.instantiateClass(config);
}
@@ -109,7 +109,7 @@ public class LengthNormalization<V extends NumberVector<?>> extends AbstractStre
@Override
protected LengthNormalization<V> makeInstance() {
- return new LengthNormalization<V>(norm);
+ return new LengthNormalization<>(norm);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/NonNumericFeaturesException.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/NonNumericFeaturesException.java
index 9f26482a..0abaac95 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/NonNumericFeaturesException.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/NonNumericFeaturesException.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.filter.normalization;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/Normalization.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/Normalization.java
index 96f6bdc1..3c3e7bdf 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/Normalization.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/Normalization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.filter.normalization;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,7 +23,6 @@ package de.lmu.ifi.dbs.elki.datasource.filter.normalization;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle;
import de.lmu.ifi.dbs.elki.datasource.filter.ObjectFilter;
import de.lmu.ifi.dbs.elki.math.linearalgebra.LinearEquationSystem;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable;
@@ -44,16 +43,6 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable;
*/
public interface Normalization<O> extends ObjectFilter, Parameterizable {
/**
- * Performs a normalization on a database object bundle.
- *
- * @param objects the database objects package
- * @return modified object bundle
- * @throws NonNumericFeaturesException if feature vectors differ in length or values are not
- * suitable to normalization
- */
- MultipleObjectsBundle normalizeObjects(MultipleObjectsBundle objects) throws NonNumericFeaturesException;
-
- /**
* Transforms a feature vector to the original attribute ranges.
*
* @param featureVector a feature vector to be transformed into original space
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/RankTieNormalization.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/RankTieNormalization.java
index 519a3743..bb9c2aec 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/RankTieNormalization.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/RankTieNormalization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.filter.normalization;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -68,7 +68,7 @@ public class RankTieNormalization implements ObjectFilter {
final List<? extends NumberVector<?>> castColumn = (List<? extends NumberVector<?>>) column;
// Get the replacement type information
final int dim = ((VectorFieldTypeInformation<?>) type).getDimensionality();
- final VectorFieldTypeInformation<IntegerVector> outType = new VectorFieldTypeInformation<IntegerVector>(IntegerVector.STATIC, dim);
+ final VectorFieldTypeInformation<IntegerVector> outType = new VectorFieldTypeInformation<>(IntegerVector.STATIC, dim);
// Output vectors
int[][] posvecs = new int[len][dim];
@@ -102,7 +102,7 @@ public class RankTieNormalization implements ObjectFilter {
}
// Prepare output data
- final List<IntegerVector> outColumn = new ArrayList<IntegerVector>(len);
+ final List<IntegerVector> outColumn = new ArrayList<>(len);
for(int i = 0; i < len; i++) {
outColumn.add(new IntegerVector(posvecs[i]));
}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/TFIDFNormalization.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/TFIDFNormalization.java
index 5d203c6b..5110d6fe 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/TFIDFNormalization.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/TFIDFNormalization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.filter.normalization;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,6 +28,7 @@ import gnu.trove.map.hash.TIntDoubleHashMap;
import java.util.BitSet;
import de.lmu.ifi.dbs.elki.data.SparseNumberVector;
+import de.lmu.ifi.dbs.elki.logging.Logging;
/**
* Perform full TF-IDF Normalization as commonly used in text mining.
@@ -44,6 +45,11 @@ import de.lmu.ifi.dbs.elki.data.SparseNumberVector;
*/
public class TFIDFNormalization<V extends SparseNumberVector<?>> extends InverseDocumentFrequencyNormalization<V> {
/**
+ * Class logger.
+ */
+ private static final Logging LOG = Logging.getLogger(TFIDFNormalization.class);
+
+ /**
* Constructor.
*/
public TFIDFNormalization() {
@@ -66,4 +72,9 @@ public class TFIDFNormalization<V extends SparseNumberVector<?>> extends Inverse
}
return ((SparseNumberVector.Factory<V, ?>) factory).newNumberVector(vals, featureVector.getDimensionality());
}
+
+ @Override
+ protected Logging getLogger() {
+ return LOG;
+ }
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/package-info.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/package-info.java
index c0c10a7c..15d689d7 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/package-info.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/package-info.java
index 82302cd3..87684499 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/package-info.java
@@ -7,7 +7,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/transform/AbstractSupervisedProjectionVectorFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/transform/AbstractSupervisedProjectionVectorFilter.java
new file mode 100644
index 00000000..742eb977
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/transform/AbstractSupervisedProjectionVectorFilter.java
@@ -0,0 +1,230 @@
+package de.lmu.ifi.dbs.elki.datasource.filter.transform;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import gnu.trove.list.TIntList;
+import gnu.trove.list.array.TIntArrayList;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import de.lmu.ifi.dbs.elki.data.ClassLabel;
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.NumberVector.Factory;
+import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
+import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.data.type.VectorFieldTypeInformation;
+import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle;
+import de.lmu.ifi.dbs.elki.datasource.filter.ClassLabelFilter;
+import de.lmu.ifi.dbs.elki.datasource.filter.ObjectFilter;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.Matrix;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayLikeUtil;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
+
+/**
+ * Base class for supervised projection methods.
+ *
+ * TODO: re-add sampling.
+ *
+ * @author Angela Peng
+ * @author Erich Schubert
+ *
+ * @param <V> Vector type
+ */
+public abstract class AbstractSupervisedProjectionVectorFilter<V extends NumberVector<?>> implements ObjectFilter {
+ /**
+ * r: the dimension to which the data should be reduced
+ */
+ protected int tdim;
+
+ /**
+ * Constructor.
+ *
+ * @param projdimension Projection dimensionality
+ */
+ public AbstractSupervisedProjectionVectorFilter(int projdimension) {
+ super();
+ this.tdim = projdimension;
+ }
+
+ @Override
+ public MultipleObjectsBundle filter(MultipleObjectsBundle objects) {
+ final int dataLength = objects.dataLength();
+ if (dataLength == 0) {
+ return objects;
+ }
+
+ List<? extends ClassLabel> classcolumn = null;
+ // First of all, identify a class label column.
+ for (int r = 0; r < objects.metaLength(); r++) {
+ SimpleTypeInformation<?> type = objects.meta(r);
+ List<?> column = objects.getColumn(r);
+ if (TypeUtil.CLASSLABEL.isAssignableFromType(type)) {
+ @SuppressWarnings("unchecked")
+ final List<? extends ClassLabel> castcolumn = (List<? extends ClassLabel>) column;
+ classcolumn = castcolumn;
+ break;
+ }
+ }
+ if (classcolumn == null) {
+ getLogger().warning("No class label column found (try " + ClassLabelFilter.class.getSimpleName() + ") -- cannot run " + this.getClass().getSimpleName());
+ return objects;
+ }
+
+ boolean somesuccess = false;
+ MultipleObjectsBundle bundle = new MultipleObjectsBundle();
+ // Secondly, look for columns to train the projection on.
+ for (int r = 0; r < objects.metaLength(); r++) {
+ SimpleTypeInformation<?> type = objects.meta(r);
+ List<?> column = objects.getColumn(r);
+ if (!TypeUtil.NUMBER_VECTOR_FIELD.isAssignableFromType(type)) {
+ bundle.appendColumn(type, column);
+ continue;
+ }
+ @SuppressWarnings("unchecked")
+ List<V> vectorcolumn = (List<V>) column;
+ final VectorFieldTypeInformation<?> vtype = (VectorFieldTypeInformation<?>) type;
+ @SuppressWarnings("unchecked")
+ NumberVector.Factory<V, ?> factory = (NumberVector.Factory<V, ?>) vtype.getFactory();
+ int dim = vtype.getDimensionality();
+
+ if (tdim > dim) {
+ if (getLogger().isVerbose()) {
+ getLogger().verbose("Setting projection dimension to original dimension: projection dimension: " + tdim + " larger than original dimension: " + dim);
+ }
+ tdim = dim;
+ }
+
+ try {
+ Matrix proj = computeProjectionMatrix(vectorcolumn, classcolumn, dim);
+ for (int i = 0; i < dataLength; i++) {
+ final Vector pv = proj.times(vectorcolumn.get(i).getColumnVector());
+ V filteredObj = factory.newNumberVector(pv, ArrayLikeUtil.VECTORADAPTER);
+ vectorcolumn.set(i, filteredObj);
+ }
+ bundle.appendColumn(convertedType(type, factory), column);
+ somesuccess = true;
+ } catch (Exception e) {
+ getLogger().error("Projection failed -- continuing with unprojected data!", e);
+ bundle.appendColumn(type, column);
+ continue;
+ }
+ }
+
+ if (!somesuccess) {
+ getLogger().warning("No vector field of fixed dimensionality found.");
+ return objects;
+ }
+ return bundle;
+ }
+
+ /**
+ * Get the output type from the input type after conversion.
+ *
+ * @param in input type restriction
+ * @param factory Vector factory
+ * @return output type restriction
+ */
+ protected SimpleTypeInformation<?> convertedType(SimpleTypeInformation<?> in, Factory<V, ?> factory) {
+ return new VectorFieldTypeInformation<>(factory, tdim);
+ }
+
+ /**
+ * Class logger.
+ *
+ * @return Logger
+ */
+ protected abstract Logging getLogger();
+
+ /**
+ * computes the projection matrix
+ *
+ * @param vectorcolumn Vectors
+ * @param classcolumn Class information
+ * @param dim Dimensionality Dimensionality
+ * @return Projection matrix
+ */
+ protected abstract Matrix computeProjectionMatrix(List<V> vectorcolumn, List<? extends ClassLabel> classcolumn, int dim);
+
+ /**
+ * Partition the bundle based on the class label.
+ *
+ * @param classcolumn
+ * @return
+ */
+ protected <O> Map<O, TIntList> partition(List<? extends O> classcolumn) {
+ Map<O, TIntList> classes = new HashMap<>();
+ Iterator<? extends O> iter = classcolumn.iterator();
+ for (int i = 0; iter.hasNext(); i++) {
+ O lbl = iter.next();
+ TIntList ids = classes.get(lbl);
+ if (ids == null) {
+ ids = new TIntArrayList();
+ classes.put(lbl, ids);
+ }
+ ids.add(i);
+ }
+ return classes;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ *
+ * @param <V> Vector type
+ */
+ public abstract static class Parameterizer<V extends NumberVector<?>> extends AbstractParameterizer {
+ /**
+ * The number of dimensions to keep.
+ */
+ public static final OptionID P_ID = new OptionID("projection.dim", "Projection dimensionality");
+
+ /**
+ * Target dimensionality.
+ */
+ protected int tdim;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ IntParameter dimP = new IntParameter(P_ID, 2);
+ dimP.addConstraint(new GreaterConstraint(0));
+
+ if (config.grab(dimP)) {
+ tdim = dimP.getValue();
+ }
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/transform/ClassicMultidimensionalScalingTransform.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/transform/ClassicMultidimensionalScalingTransform.java
new file mode 100644
index 00000000..d646b489
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/transform/ClassicMultidimensionalScalingTransform.java
@@ -0,0 +1,274 @@
+package de.lmu.ifi.dbs.elki.datasource.filter.transform;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.List;
+
+import de.lmu.ifi.dbs.elki.data.DoubleVector;
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
+import de.lmu.ifi.dbs.elki.data.type.VectorFieldTypeInformation;
+import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle;
+import de.lmu.ifi.dbs.elki.datasource.filter.ObjectFilter;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SquaredEuclideanDistanceFunction;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.Matrix;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.SingularValueDecomposition;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
+
+/**
+ * Rescale the data set using multidimensional scaling, MDS.
+ *
+ * Note: the current implementation is rather expensive, both memory- and
+ * runtime wise. Don't use for large data sets!
+ *
+ * TODO: a contributed block Lanczos algorithm would be beneficial, to speed up MDS.
+ *
+ * @author Erich Schubert
+ *
+ * @param <O> Data type
+ */
+@Alias({ "mds" })
+public class ClassicMultidimensionalScalingTransform<O> implements ObjectFilter {
+ /**
+ * Class logger.
+ */
+ private static final Logging LOG = Logging.getLogger(ClassicMultidimensionalScalingTransform.class);
+
+ /**
+ * Distance function to use.
+ */
+ PrimitiveDoubleDistanceFunction<? super O> dist = null;
+
+ /**
+ * Target dimensionality
+ */
+ int tdim;
+
+ /**
+ * Constructor.
+ *
+ * @param tdim Target dimensionality.
+ * @param dist Distance function to use.
+ */
+ public ClassicMultidimensionalScalingTransform(int tdim, PrimitiveDoubleDistanceFunction<? super O> dist) {
+ super();
+ this.tdim = tdim;
+ this.dist = dist;
+ }
+
+ @Override
+ public MultipleObjectsBundle filter(MultipleObjectsBundle objects) {
+ final int size = objects.dataLength();
+ if (size == 0) {
+ return objects;
+ }
+ MultipleObjectsBundle bundle = new MultipleObjectsBundle();
+
+ for (int r = 0; r < objects.metaLength(); r++) {
+ @SuppressWarnings("unchecked")
+ SimpleTypeInformation<Object> type = (SimpleTypeInformation<Object>) objects.meta(r);
+ @SuppressWarnings("unchecked")
+ final List<Object> column = (List<Object>) objects.getColumn(r);
+ if (!dist.getInputTypeRestriction().isAssignableFromType(type)) {
+ bundle.appendColumn(type, column);
+ continue;
+ }
+ // Get the replacement type information
+ @SuppressWarnings("unchecked")
+ final List<O> castColumn = (List<O>) column;
+ NumberVector.Factory<? extends NumberVector<?>, ?> factory = null;
+ {
+ if (type instanceof VectorFieldTypeInformation) {
+ final VectorFieldTypeInformation<?> ctype = (VectorFieldTypeInformation<?>) type;
+ // Note two-step cast, to make stricter compilers happy.
+ @SuppressWarnings("unchecked")
+ final VectorFieldTypeInformation<? extends NumberVector<?>> vtype = (VectorFieldTypeInformation<? extends NumberVector<?>>) ctype;
+ factory = (NumberVector.Factory<? extends NumberVector<?>, ?>) vtype.getFactory();
+ } else {
+ factory = DoubleVector.FACTORY;
+ }
+ bundle.appendColumn(new VectorFieldTypeInformation<>(factory, tdim), castColumn);
+ }
+
+ // Compute distance matrix.
+ Matrix mat = new Matrix(size, size);
+ double[][] imat = mat.getArrayRef();
+ {
+ FiniteProgress dprog = LOG.isVerbose() ? new FiniteProgress("Computing distance matrix.", (size * (size - 1)) >>> 1, LOG) : null;
+ for (int x = 0; x < size; x++) {
+ final O ox = castColumn.get(x);
+ for (int y = x + 1; y < size; y++) {
+ final O oy = castColumn.get(y);
+ double distance = Math.abs(dist.doubleDistance(ox, oy));
+ imat[x][y] = distance;
+ if (dprog != null) {
+ dprog.incrementProcessed(LOG);
+ }
+ }
+ }
+ if (dprog != null) {
+ dprog.ensureCompleted(LOG);
+ }
+ }
+ // Adjust distance matrix:
+ if (dist instanceof SquaredEuclideanDistanceFunction) {
+ // Don't square squared euclidean twice.
+ for (int x = 0; x < size; x++) {
+ for (int y = x + 1; y < size; y++) {
+ imat[x][y] *= -.5;
+ }
+ }
+ } else {
+ for (int x = 0; x < size; x++) {
+ for (int y = x + 1; y < size; y++) {
+ imat[x][y] *= -.5 * imat[x][y];
+ }
+ }
+ }
+ doubleCenterSymmetric(imat);
+ // Find eigenvectors.
+ {
+ // TODO: implement Block-Lanczos algorithm for partial SVD.
+ SingularValueDecomposition svd = new SingularValueDecomposition(mat);
+ Matrix u = svd.getU();
+ double[] lambda = svd.getSingularValues();
+ for (int i = 0; i < tdim; i++) {
+ lambda[i] = Math.sqrt(Math.abs(lambda[i]));
+ }
+
+ double[] buf = new double[tdim];
+ double[][] uraw = u.getArrayRef();
+ for (int i = 0; i < size; i++) {
+ double[] raw = uraw[i];
+ for (int x = 0; x < buf.length; x++) {
+ buf[x] = lambda[x] * raw[x];
+ }
+ column.set(i, factory.newNumberVector(buf));
+ }
+ }
+ }
+ return bundle;
+ }
+
+ /**
+ * Double-center the given matrix (only upper triangle is used).
+ *
+ * For improved numerical precision, we perform incremental updates to the
+ * mean values, instead of computing a large sum and then performing division.
+ *
+ * @param m Matrix to double-center.
+ */
+ public static void doubleCenterSymmetric(double[][] m) {
+ final int size = m.length;
+ // Storage for mean values - initially all 0.
+ double means[] = new double[size];
+ for (int x = 0; x < m.length; x++) {
+ final double[] rowx = m[x];
+ // We already added "x" values in previous iterations.
+ // Fake-add 0: mean + (0 - mean) / (x + 1)
+ double rmean = means[x] - means[x] / (x + 1);
+ for (int y = x + 1; y < rowx.length; y++) {
+ final double nv = rowx[y];
+ final double dx = nv - rmean, dy = nv - means[y];
+ // For x < y, this is the yth entry.
+ rmean += dx / (y + 1);
+ // For y > x, this is the xth entry
+ means[y] += dy / (x + 1);
+ }
+ means[x] = rmean;
+ }
+ // Compute total mean by averaging column means.
+ double mean = means[0];
+ for (int x = 1; x < size; x++) {
+ double dm = means[x] - mean;
+ mean += dm / (x + 1);
+ }
+ // Row and column center; also make symmetric.
+ for (int x = 0; x < size; x++) {
+ m[x][x] = -2. * means[x] + mean;
+ for (int y = x + 1; y < size; y++) {
+ final double nv = m[x][y] - means[x] - means[y] + mean;
+ m[x][y] = nv;
+ m[y][x] = nv;
+ }
+ }
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer<O extends NumberVector<?>> extends AbstractParameterizer {
+ /**
+ * Desired dimensionality.
+ */
+ public static final OptionID DIM_ID = new OptionID("mds.dim", "Output dimensionality.");
+
+ /**
+ * Distant metric.
+ */
+ public static final OptionID DISTANCE_ID = new OptionID("mds.distance", "Distance function to use.");
+
+ /**
+ * Target dimensionality.
+ */
+ int tdim;
+
+ /**
+ * Distance function to use.
+ */
+ PrimitiveDoubleDistanceFunction<? super O> dist = null;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+
+ IntParameter dimP = new IntParameter(DIM_ID);
+ if (config.grab(dimP)) {
+ tdim = dimP.intValue();
+ }
+
+ ObjectParameter<PrimitiveDoubleDistanceFunction<? super O>> distP = new ObjectParameter<>(DISTANCE_ID, PrimitiveDoubleDistanceFunction.class, SquaredEuclideanDistanceFunction.class);
+ if (config.grab(distP)) {
+ dist = distP.instantiateClass(config);
+ }
+ }
+
+ @Override
+ protected ClassicMultidimensionalScalingTransform<O> makeInstance() {
+ return new ClassicMultidimensionalScalingTransform<>(tdim, dist);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/transform/GlobalPrincipalComponentAnalysisTransform.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/transform/GlobalPrincipalComponentAnalysisTransform.java
index 18537a8d..3b4193ad 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/transform/GlobalPrincipalComponentAnalysisTransform.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/transform/GlobalPrincipalComponentAnalysisTransform.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.filter.transform;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -38,6 +38,7 @@ import de.lmu.ifi.dbs.elki.math.linearalgebra.VMath;
import de.lmu.ifi.dbs.elki.math.linearalgebra.pca.EigenPairFilter;
import de.lmu.ifi.dbs.elki.math.linearalgebra.pca.PCAResult;
import de.lmu.ifi.dbs.elki.math.linearalgebra.pca.PCARunner;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
@@ -47,12 +48,16 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
/**
* Apply principal component analysis to the data set.
*
- * TODO: add dimensionality reduction
+ * This process is also known as "Whitening transformation".
+ *
+ * If you want to also reduce dimensionality, set the
+ * {@link Parameterizer#FILTER_ID} parameter!
*
* @author Erich Schubert
*
* @param <O> Vector type
*/
+@Alias({ "whiten", "whitening", "pca" })
public class GlobalPrincipalComponentAnalysisTransform<O extends NumberVector<?>> extends AbstractVectorConversionFilter<O, O> {
/**
* Class logger.
@@ -101,7 +106,7 @@ public class GlobalPrincipalComponentAnalysisTransform<O extends NumberVector<?>
@Override
protected boolean prepareStart(SimpleTypeInformation<O> in) {
- if(!(in instanceof VectorFieldTypeInformation)) {
+ if (!(in instanceof VectorFieldTypeInformation)) {
throw new AbortException("PCA can only applied to fixed dimensionality vectors");
}
dim = ((VectorFieldTypeInformation<?>) in).getDimensionality();
@@ -121,31 +126,30 @@ public class GlobalPrincipalComponentAnalysisTransform<O extends NumberVector<?>
SortedEigenPairs eps = pcares.getEigenPairs();
covmat = null;
- if(filter == null) {
+ if (filter == null) {
proj = new double[dim][dim];
- for(int d = 0; d < dim; d++) {
+ for (int d = 0; d < dim; d++) {
EigenPair ep = eps.getEigenPair(d);
double[] ev = ep.getEigenvector().getArrayRef();
double eval = Math.sqrt(ep.getEigenvalue());
// Fill weighted and transposed:
- for(int i = 0; i < dim; i++) {
+ for (int i = 0; i < dim; i++) {
proj[d][i] = ev[i] / eval;
}
}
- }
- else {
+ } else {
List<EigenPair> axes = filter.filter(eps).getStrongEigenPairs();
final int pdim = axes.size(); // Projection dimensionality
if (LOG.isVerbose()) {
- LOG.verbose("Reducing dimensionality from "+dim+" to "+pdim+" via PCA.");
+ LOG.verbose("Reducing dimensionality from " + dim + " to " + pdim + " via PCA.");
}
proj = new double[pdim][dim];
- for(int d = 0; d < pdim; d++) {
+ for (int d = 0; d < pdim; d++) {
EigenPair ep = axes.get(d);
double[] ev = ep.getEigenvector().getArrayRef();
double eval = Math.sqrt(ep.getEigenvalue());
// Fill weighted and transposed:
- for(int i = 0; i < dim; i++) {
+ for (int i = 0; i < dim; i++) {
proj[d][i] = ev[i] / eval;
}
}
@@ -156,7 +160,7 @@ public class GlobalPrincipalComponentAnalysisTransform<O extends NumberVector<?>
@Override
protected O filterSingleObject(O obj) {
// Shift by mean and copy
- for(int i = 0; i < dim; i++) {
+ for (int i = 0; i < dim; i++) {
buf[i] = obj.doubleValue(i) - mean[i];
}
double[] p = VMath.times(proj, buf);
@@ -171,12 +175,12 @@ public class GlobalPrincipalComponentAnalysisTransform<O extends NumberVector<?>
@Override
protected SimpleTypeInformation<? super O> convertedType(SimpleTypeInformation<O> in) {
initializeOutputType(in);
- if(proj.length == dim) {
- return in;
- }
- else {
- return new VectorFieldTypeInformation<O>(factory, proj.length);
- }
+ return new VectorFieldTypeInformation<>(factory, proj.length);
+ }
+
+ @Override
+ protected Logging getLogger() {
+ return LOG;
}
/**
@@ -201,15 +205,15 @@ public class GlobalPrincipalComponentAnalysisTransform<O extends NumberVector<?>
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- ObjectParameter<EigenPairFilter> filterP = new ObjectParameter<EigenPairFilter>(FILTER_ID, EigenPairFilter.class, true);
- if(config.grab(filterP)) {
+ ObjectParameter<EigenPairFilter> filterP = new ObjectParameter<>(FILTER_ID, EigenPairFilter.class, true);
+ if (config.grab(filterP)) {
filter = filterP.instantiateClass(config);
}
}
@Override
- protected Object makeInstance() {
- return new GlobalPrincipalComponentAnalysisTransform<O>(filter);
+ protected GlobalPrincipalComponentAnalysisTransform<O> makeInstance() {
+ return new GlobalPrincipalComponentAnalysisTransform<>(filter);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/transform/LatLngToECEFFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/transform/LatLngToECEFFilter.java
new file mode 100644
index 00000000..998c8931
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/transform/LatLngToECEFFilter.java
@@ -0,0 +1,111 @@
+package de.lmu.ifi.dbs.elki.datasource.filter.transform;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
+import de.lmu.ifi.dbs.elki.data.type.VectorFieldTypeInformation;
+import de.lmu.ifi.dbs.elki.datasource.filter.AbstractStreamConversionFilter;
+import de.lmu.ifi.dbs.elki.math.geodesy.EarthModel;
+import de.lmu.ifi.dbs.elki.math.geodesy.SphericalVincentyEarthModel;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
+
+/**
+ * Project a 2D data set (latitude, longitude) to a 3D coordinate system (X, Y,
+ * Z), such that Euclidean distance is line-of-sight.
+ *
+ * @author Erich Schubert
+ *
+ * @param <V> Vector type.
+ */
+public class LatLngToECEFFilter<V extends NumberVector<?>> extends AbstractStreamConversionFilter<V, V> {
+ /**
+ * Vector factory to use.
+ */
+ private NumberVector.Factory<V, ?> factory;
+
+ /**
+ * Earth model to use.
+ */
+ private EarthModel model;
+
+ /**
+ * Constructor.
+ *
+ * @param model Earth model
+ */
+ public LatLngToECEFFilter(EarthModel model) {
+ super();
+ this.model = model;
+ }
+
+ @Override
+ protected V filterSingleObject(V obj) {
+ return factory.newNumberVector(model.latLngDegToECEF(obj.doubleValue(0), obj.doubleValue(1)));
+ }
+
+ @Override
+ protected SimpleTypeInformation<? super V> getInputTypeRestriction() {
+ return new VectorFieldTypeInformation<>(NumberVector.class, 2, 2);
+ }
+
+ @Override
+ protected SimpleTypeInformation<? super V> convertedType(SimpleTypeInformation<V> in) {
+ VectorFieldTypeInformation<V> vin = (VectorFieldTypeInformation<V>) in;
+ factory = (NumberVector.Factory<V, ?>) vin.getFactory();
+ return new VectorFieldTypeInformation<>(vin.getFactory(), 3, 3, in.getSerializer());
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ *
+ * @param <V> Vector type
+ */
+ public static class Parameterizer<V extends NumberVector<?>> extends AbstractParameterizer {
+ /**
+ * Earth model to use.
+ */
+ private EarthModel model;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ ObjectParameter<EarthModel> modelP = new ObjectParameter<>(EarthModel.MODEL_ID, EarthModel.class, SphericalVincentyEarthModel.class);
+ if (config.grab(modelP)) {
+ model = modelP.instantiateClass(config);
+ }
+ }
+
+ @Override
+ protected LatLngToECEFFilter<V> makeInstance() {
+ return new LatLngToECEFFilter<>(model);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/transform/LinearDiscriminantAnalysisFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/transform/LinearDiscriminantAnalysisFilter.java
new file mode 100644
index 00000000..76546d5c
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/transform/LinearDiscriminantAnalysisFilter.java
@@ -0,0 +1,165 @@
+package de.lmu.ifi.dbs.elki.datasource.filter.transform;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import gnu.trove.iterator.TIntIterator;
+import gnu.trove.list.TIntList;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import de.lmu.ifi.dbs.elki.data.ClassLabel;
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.Centroid;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.CovarianceMatrix;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.EigenvalueDecomposition;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.Matrix;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.SortedEigenPairs;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+
+/**
+ * Linear Discriminant Analysis (LDA) / Fisher's linear discriminant.
+ *
+ * Reference:
+ * <p>
+ * R. A. Fisher<br />
+ * The use of multiple measurements in taxonomic problems<br />
+ * Annals of Eugenics 7.2 (1936): 179-188.
+ * </p>
+ *
+ * @author Angela Peng
+ * @author Erich Schubert
+ *
+ * @param <V> Vector type
+ */
+@Alias("lda")
+@Reference(authors = "R. A. Fisher", title = "The use of multiple measurements in taxonomic problems", booktitle = "Annals of eugenics 7.2 (1936)", url = "http://dx.doi.org/10.1111/j.1469-1809.1936.tb02137.x")
+public class LinearDiscriminantAnalysisFilter<V extends NumberVector<?>> extends AbstractSupervisedProjectionVectorFilter<V> {
+ /**
+ * Class logger.
+ */
+ private static final Logging LOG = Logging.getLogger(LinearDiscriminantAnalysisFilter.class);
+
+ /**
+ * Constructor.
+ *
+ * @param projdimension Projection dimensionality.
+ */
+ public LinearDiscriminantAnalysisFilter(int projdimension) {
+ super(projdimension);
+ }
+
+ @Override
+ protected Matrix computeProjectionMatrix(List<V> vectorcolumn, List<? extends ClassLabel> classcolumn, int dim) {
+ Map<ClassLabel, TIntList> classes = partition(classcolumn);
+ // Fix indexing of classes:
+ List<ClassLabel> keys = new ArrayList<>(classes.keySet());
+ // Compute centroids:
+ List<Centroid> centroids = computeCentroids(dim, vectorcolumn, keys, classes);
+
+ final Matrix sigmaB, sigmaI;
+ // Between classes covariance:
+ {
+ CovarianceMatrix covmake = new CovarianceMatrix(dim);
+ for (Centroid c : centroids) {
+ covmake.put(c);
+ }
+ sigmaB = covmake.destroyToSampleMatrix();
+ }
+ {
+ // (Average) within class variance:
+ CovarianceMatrix covmake = new CovarianceMatrix(dim);
+ int numc = keys.size();
+ for (int i = 0; i < numc; i++) {
+ Centroid c = centroids.get(i);
+ // TODO: different weighting strategies? Sampling?
+ // Note: GNU Trove iterator, not ELKI style!
+ for (TIntIterator it = classes.get(keys.get(i)).iterator(); it.hasNext();) {
+ Vector delta = vectorcolumn.get(it.next()).getColumnVector().minusEquals(c);
+ covmake.put(delta);
+ }
+ }
+ sigmaI = covmake.destroyToSampleMatrix();
+ if (sigmaI.det() == 0) {
+ sigmaI.cheatToAvoidSingularity(1e-10);
+ }
+ }
+
+ Matrix sol = sigmaI.inverse().times(sigmaB);
+ EigenvalueDecomposition decomp = new EigenvalueDecomposition(sol);
+ SortedEigenPairs sorted = new SortedEigenPairs(decomp, false);
+ return sorted.eigenVectors(tdim).transpose();
+ }
+
+ /**
+ * Compute the centroid for each class.
+ *
+ * @param dim Dimensionality
+ * @param vectorcolumn Vector column
+ * @param keys Key index
+ * @param classes Classes
+ * @return Centroids for each class.
+ */
+ protected List<Centroid> computeCentroids(int dim, List<V> vectorcolumn, List<ClassLabel> keys, Map<ClassLabel, TIntList> classes) {
+ final int numc = keys.size();
+ List<Centroid> centroids = new ArrayList<>(numc);
+ for (int i = 0; i < numc; i++) {
+ Centroid c = new Centroid(dim);
+ // Note: GNU Trove iterator, not ELKI style!
+ for (TIntIterator it = classes.get(keys.get(i)).iterator(); it.hasNext();) {
+ c.put(vectorcolumn.get(it.next()));
+ }
+ centroids.add(c);
+ }
+ return centroids;
+ }
+
+ /**
+ * Class logger.
+ *
+ * @return Logger
+ */
+ @Override
+ protected Logging getLogger() {
+ return LOG;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Angela Peng
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer<V extends NumberVector<?>> extends AbstractSupervisedProjectionVectorFilter.Parameterizer<V> {
+ @Override
+ protected LinearDiscriminantAnalysisFilter<V> makeInstance() {
+ return new LinearDiscriminantAnalysisFilter<>(tdim);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/transform/LngLatToECEFFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/transform/LngLatToECEFFilter.java
new file mode 100644
index 00000000..ea0d4ef2
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/transform/LngLatToECEFFilter.java
@@ -0,0 +1,111 @@
+package de.lmu.ifi.dbs.elki.datasource.filter.transform;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
+import de.lmu.ifi.dbs.elki.data.type.VectorFieldTypeInformation;
+import de.lmu.ifi.dbs.elki.datasource.filter.AbstractStreamConversionFilter;
+import de.lmu.ifi.dbs.elki.math.geodesy.EarthModel;
+import de.lmu.ifi.dbs.elki.math.geodesy.SphericalVincentyEarthModel;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
+
+/**
+ * Project a 2D data set (longitude, latitude) to a 3D coordinate system (X, Y,
+ * Z), such that Euclidean distance is line-of-sight.
+ *
+ * @author Erich Schubert
+ *
+ * @param <V> Vector type.
+ */
+public class LngLatToECEFFilter<V extends NumberVector<?>> extends AbstractStreamConversionFilter<V, V> {
+ /**
+ * Vector factory to use.
+ */
+ private NumberVector.Factory<V, ?> factory;
+
+ /**
+ * Earth model to use.
+ */
+ private EarthModel model;
+
+ /**
+ * Constructor.
+ *
+ * @param model Earth model
+ */
+ public LngLatToECEFFilter(EarthModel model) {
+ super();
+ this.model = model;
+ }
+
+ @Override
+ protected V filterSingleObject(V obj) {
+ return factory.newNumberVector(model.latLngDegToECEF(obj.doubleValue(1), obj.doubleValue(0)));
+ }
+
+ @Override
+ protected SimpleTypeInformation<? super V> getInputTypeRestriction() {
+ return new VectorFieldTypeInformation<>(NumberVector.class, 2, 2);
+ }
+
+ @Override
+ protected SimpleTypeInformation<? super V> convertedType(SimpleTypeInformation<V> in) {
+ VectorFieldTypeInformation<V> vin = (VectorFieldTypeInformation<V>) in;
+ factory = (NumberVector.Factory<V, ?>) vin.getFactory();
+ return new VectorFieldTypeInformation<>(vin.getFactory(), 3, 3, in.getSerializer());
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ *
+ * @param <V> Vector type
+ */
+ public static class Parameterizer<V extends NumberVector<?>> extends AbstractParameterizer {
+ /**
+ * Earth model to use.
+ */
+ private EarthModel model;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ ObjectParameter<EarthModel> modelP = new ObjectParameter<>(EarthModel.MODEL_ID, EarthModel.class, SphericalVincentyEarthModel.class);
+ if (config.grab(modelP)) {
+ model = modelP.instantiateClass(config);
+ }
+ }
+
+ @Override
+ protected LngLatToECEFFilter<V> makeInstance() {
+ return new LngLatToECEFFilter<>(model);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/transform/NumberVectorFeatureSelectionFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/transform/NumberVectorFeatureSelectionFilter.java
index 82e7a1b6..720c88df 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/transform/NumberVectorFeatureSelectionFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/transform/NumberVectorFeatureSelectionFilter.java
@@ -81,7 +81,7 @@ public class NumberVectorFeatureSelectionFilter<V extends NumberVector<?>> exten
@Override
protected SimpleTypeInformation<? super V> convertedType(SimpleTypeInformation<V> in) {
initializeOutputType(in);
- return new VectorFieldTypeInformation<V>(factory, getDimensionality());
+ return new VectorFieldTypeInformation<>(factory, getDimensionality());
}
/**
@@ -139,7 +139,7 @@ public class NumberVectorFeatureSelectionFilter<V extends NumberVector<?>> exten
* Key: <code>-projectionfilter.selectedattributes</code>
* </p>
*/
- public static final OptionID SELECTED_ATTRIBUTES_ID = new OptionID("projectionfilter.selectedattributes", "a comma separated array of integer values d_i, where 0 <= d_i < the " + "dimensionality of the feature space " + "specifying the dimensions to be considered " + "for projection. If this parameter is not set, " + "no dimensions will be considered, i.e. the projection is a zero-dimensional feature space");
+ public static final OptionID SELECTED_ATTRIBUTES_ID = new OptionID("projectionfilter.selectedattributes", "a comma separated array of integer values d_i, where 0 <= d_i < the dimensionality of the feature space specifying the dimensions to be considered for projection. If this parameter is not set, no dimensions will be considered, i.e. the projection is a zero-dimensional feature space");
/**
* Selected attributes.
@@ -162,7 +162,7 @@ public class NumberVectorFeatureSelectionFilter<V extends NumberVector<?>> exten
@Override
protected NumberVectorFeatureSelectionFilter<DoubleVector> makeInstance() {
- return new NumberVectorFeatureSelectionFilter<DoubleVector>(selectedAttributes);
+ return new NumberVectorFeatureSelectionFilter<>(selectedAttributes);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/transform/NumberVectorRandomFeatureSelectionFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/transform/NumberVectorRandomFeatureSelectionFilter.java
index 7d799a1e..9b1ddbff 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/transform/NumberVectorRandomFeatureSelectionFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/transform/NumberVectorRandomFeatureSelectionFilter.java
@@ -94,7 +94,7 @@ public class NumberVectorRandomFeatureSelectionFilter<V extends NumberVector<?>>
protected SimpleTypeInformation<? super V> convertedType(SimpleTypeInformation<V> in) {
initializeRandomAttributes(in);
initializeOutputType(in);
- return new VectorFieldTypeInformation<V>(factory, k);
+ return new VectorFieldTypeInformation<>(factory, k);
}
/**
@@ -168,7 +168,7 @@ public class NumberVectorRandomFeatureSelectionFilter<V extends NumberVector<?>>
@Override
protected NumberVectorRandomFeatureSelectionFilter<DoubleVector> makeInstance() {
- return new NumberVectorRandomFeatureSelectionFilter<DoubleVector>(k, rnd);
+ return new NumberVectorRandomFeatureSelectionFilter<>(k, rnd);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/transform/ProjectionFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/transform/ProjectionFilter.java
new file mode 100644
index 00000000..af3f4c6e
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/transform/ProjectionFilter.java
@@ -0,0 +1,113 @@
+package de.lmu.ifi.dbs.elki.datasource.filter.transform;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2012
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.data.projection.Projection;
+import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
+import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
+import de.lmu.ifi.dbs.elki.datasource.filter.AbstractStreamConversionFilter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
+
+/**
+ * Apply a projection to the data.
+ *
+ * @author Erich Schubert
+ *
+ * @param <I> Input type
+ * @param <O> Output type
+ */
+public class ProjectionFilter<I, O> extends AbstractStreamConversionFilter<I, O> {
+ /**
+ * Projection to apply.
+ */
+ Projection<I, O> projection;
+
+ /**
+ * Constructor.
+ *
+ * @param projection Projection
+ */
+ public ProjectionFilter(Projection<I, O> projection) {
+ super();
+ this.projection = projection;
+ }
+
+ @Override
+ protected O filterSingleObject(I obj) {
+ return projection.project(obj);
+ }
+
+ @Override
+ protected TypeInformation getInputTypeRestriction() {
+ return projection.getInputDataTypeInformation();
+ }
+
+ @Override
+ protected SimpleTypeInformation<? super O> convertedType(SimpleTypeInformation<I> in) {
+ projection.initialize(in);
+ return projection.getOutputDataTypeInformation();
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ *
+ * @param <I> Input type
+ * @param <O> Output type
+ */
+ public static class Parameterizer<I, O> extends AbstractParameterizer {
+ /**
+ * Parameter to specify the projection to use
+ * <p>
+ * Key: {@code -projection}
+ * </p>
+ */
+ public static final OptionID PROJ_ID = new OptionID("projection", "Projection to use.");
+
+ /**
+ * Projection to apply.
+ */
+ Projection<I, O> projection;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ ObjectParameter<Projection<I, O>> projP = new ObjectParameter<>(PROJ_ID, Projection.class);
+ if (config.grab(projP)) {
+ projection = projP.instantiateClass(config);
+ }
+ }
+
+ @Override
+ protected ProjectionFilter<I, O> makeInstance() {
+ return new ProjectionFilter<>(projection);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/transform/package-info.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/transform/package-info.java
index 9f8d3262..7082f103 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/transform/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/transform/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/package-info.java b/src/de/lmu/ifi/dbs/elki/datasource/package-info.java
index 8aba2d30..98ce5b36 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/parser/AbstractParser.java b/src/de/lmu/ifi/dbs/elki/datasource/parser/AbstractParser.java
index 1f414055..1e689638 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/parser/AbstractParser.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/parser/AbstractParser.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.parser;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -54,7 +54,8 @@ public abstract class AbstractParser {
public static final char QUOTE_CHAR = '\"';
/**
- * A pattern catching most numbers that can be parsed using Double.parseDouble:
+ * A pattern catching most numbers that can be parsed using
+ * Double.parseDouble:
*
* Some examples: <code>1</code> <code>1.</code> <code>1.2</code>
* <code>.2</code> <code>-.2e-03</code>
@@ -62,16 +63,14 @@ public abstract class AbstractParser {
public static final String NUMBER_PATTERN = "[+-]?(?:\\d+\\.?|\\d*\\.\\d+)?(?:[eE][-]?\\d+)?";
/**
- * OptionID for the column separator parameter (defaults to whitespace as in
- * {@link #DEFAULT_SEPARATOR}.
+ * Default pattern for comments.
*/
- public static final OptionID COLUMN_SEPARATOR_ID = new OptionID("parser.colsep", "Column separator pattern. The default assumes whitespace separated data.");
+ public static final String COMMENT_PATTERN = "^\\s*(#|//|;).*$";
/**
- * OptionID for the quote character parameter (defaults to a double quotation
- * mark as in {@link #QUOTE_CHAR}.
+ * A sign to separate attributes.
*/
- public static final OptionID QUOTE_ID = new OptionID("parser.quote", "Quotation character. The default is to use a double quote.");
+ public static final String ATTRIBUTE_CONCATENATION = " ";
/**
* Stores the column separator pattern
@@ -84,25 +83,22 @@ public abstract class AbstractParser {
protected char quoteChar = QUOTE_CHAR;
/**
- * The comment character.
+ * Comment pattern.
*/
- public static final String COMMENT = "#";
-
- /**
- * A sign to separate attributes.
- */
- public static final String ATTRIBUTE_CONCATENATION = " ";
+ protected Pattern comment = null;
/**
* Constructor.
*
* @param colSep Column separator
* @param quoteChar Quote character
+ * @param comment Comment pattern
*/
- public AbstractParser(Pattern colSep, char quoteChar) {
+ public AbstractParser(Pattern colSep, char quoteChar, Pattern comment) {
super();
this.colSep = colSep;
this.quoteChar = quoteChar;
+ this.comment = comment;
}
/**
@@ -113,16 +109,16 @@ public abstract class AbstractParser {
* @return Tokenized string
*/
protected List<String> tokenize(String input) {
- ArrayList<String> matchList = new ArrayList<String>();
+ ArrayList<String> matchList = new ArrayList<>();
Matcher m = colSep.matcher(input);
int index = 0;
boolean inquote = (input.length() > 0) && (input.charAt(0) == quoteChar);
- while(m.find()) {
+ while (m.find()) {
// Quoted code path vs. regular code path
- if(inquote && m.start() > 0) {
+ if (inquote && m.start() > 0) {
// Closing quote found?
- if(m.start() > index + 1 && input.charAt(m.start() - 1) == quoteChar) {
+ if (m.start() > index + 1 && input.charAt(m.start() - 1) == quoteChar) {
// Strip quote characters
if (index + 1 < m.start() - 1) {
matchList.add(input.substring(index + 1, m.start() - 1));
@@ -132,8 +128,7 @@ public abstract class AbstractParser {
// new quote?
inquote = (index < input.length()) && (input.charAt(index) == quoteChar);
}
- }
- else {
+ } else {
// Add match before separator
if (index < m.start()) {
matchList.add(input.substring(index, m.start()));
@@ -145,25 +140,23 @@ public abstract class AbstractParser {
}
}
// Nothing found - return original string.
- if(index == 0) {
+ if (index == 0) {
matchList.add(input);
return matchList;
}
// Add tail after last separator.
- if(inquote) {
- if(input.charAt(input.length() - 1) == quoteChar) {
+ if (inquote) {
+ if (input.charAt(input.length() - 1) == quoteChar) {
if (index + 1 < input.length() - 1) {
matchList.add(input.substring(index + 1, input.length() - 1));
}
- }
- else {
- getLogger().warning("Invalid quoted line in input.");
+ } else {
+ getLogger().warning("Invalid quoted line in input: no closing quote found in: " + input);
if (index < input.length()) {
matchList.add(input.substring(index, input.length()));
}
}
- }
- else {
+ } else {
if (index < input.length()) {
matchList.add(input.substring(index, input.length()));
}
@@ -190,6 +183,43 @@ public abstract class AbstractParser {
}
/**
+ * Utility function, which is a bit more robust wrt. parsing double values. In
+ * particular: infinite values, and creates fewer objects.
+ *
+ * @param s String s
+ * @return parsed value
+ * @throws NumberFormatException
+ */
+ public static double parseDouble(String s) throws NumberFormatException {
+ try {
+ return Double.parseDouble(s);
+ } catch (NumberFormatException e) {
+ int len = s.length();
+ if (len > 0) {
+ int p = 0;
+ char cur = s.charAt(p);
+ boolean isNegative = cur == '-';
+ if (isNegative && ++p < len) {
+ cur = s.charAt(p);
+ }
+ if (cur == '∞') {
+ return isNegative ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
+ }
+ if (len - p == 3 && "Inf".regionMatches(true, 0, s, p, 3)) {
+ return isNegative ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
+ }
+ if (len - p == 8 && "Infinity".regionMatches(true, 0, s, p, 8)) {
+ return isNegative ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
+ }
+ if (len == 3 && "NaN".equalsIgnoreCase(s)) {
+ return Double.NaN;
+ }
+ }
+ throw e;
+ }
+ }
+
+ /**
* Parameterization class.
*
* @author Erich Schubert
@@ -198,6 +228,23 @@ public abstract class AbstractParser {
*/
public abstract static class Parameterizer extends AbstractParameterizer {
/**
+ * OptionID for the column separator parameter (defaults to whitespace as in
+ * {@link #DEFAULT_SEPARATOR}.
+ */
+ public static final OptionID COLUMN_SEPARATOR_ID = new OptionID("parser.colsep", "Column separator pattern. The default assumes whitespace separated data.");
+
+ /**
+ * OptionID for the quote character parameter (defaults to a double
+ * quotation mark as in {@link #QUOTE_CHAR}.
+ */
+ public static final OptionID QUOTE_ID = new OptionID("parser.quote", "Quotation character. The default is to use a double quote.");
+
+ /**
+ * Comment pattern.
+ */
+ public static final OptionID COMMENT_ID = new OptionID("string.comment", "Ignore lines in the input file that satisfy this pattern.");
+
+ /**
* Stores the column separator pattern
*/
protected Pattern colSep = null;
@@ -207,21 +254,30 @@ public abstract class AbstractParser {
*/
protected char quoteChar = QUOTE_CHAR;
+ /**
+ * Comment pattern.
+ */
+ protected Pattern comment = null;
+
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
PatternParameter colParam = new PatternParameter(COLUMN_SEPARATOR_ID, DEFAULT_SEPARATOR);
- if(config.grab(colParam)) {
+ if (config.grab(colParam)) {
colSep = colParam.getValue();
}
StringParameter quoteParam = new StringParameter(QUOTE_ID, String.valueOf(QUOTE_CHAR));
quoteParam.addConstraint(new StringLengthConstraint(1, 1));
- if(config.grab(quoteParam)) {
+ if (config.grab(quoteParam)) {
quoteChar = quoteParam.getValue().charAt(0);
}
+ PatternParameter commentP = new PatternParameter(COMMENT_ID, COMMENT_PATTERN);
+ if (config.grab(commentP)) {
+ comment = commentP.getValue();
+ }
}
@Override
protected abstract AbstractParser makeInstance();
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/parser/AbstractStreamingParser.java b/src/de/lmu/ifi/dbs/elki/datasource/parser/AbstractStreamingParser.java
index 79f17326..53b4b6e8 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/parser/AbstractStreamingParser.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/parser/AbstractStreamingParser.java
@@ -1,15 +1,10 @@
package de.lmu.ifi.dbs.elki.datasource.parser;
-import java.io.InputStream;
-import java.util.regex.Pattern;
-
-import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle;
-
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,6 +22,12 @@ import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle;
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
+import java.io.InputStream;
+import java.util.regex.Pattern;
+
+import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle;
+
/**
* Base class for streaming parsers.
*
@@ -38,9 +39,10 @@ public abstract class AbstractStreamingParser extends AbstractParser implements
*
* @param colSep Column separator pattern
* @param quoteChar Quote character
+ * @param comment Comment pattern
*/
- public AbstractStreamingParser(Pattern colSep, char quoteChar) {
- super(colSep, quoteChar);
+ public AbstractStreamingParser(Pattern colSep, char quoteChar, Pattern comment) {
+ super(colSep, quoteChar, comment);
}
@Override
@@ -48,4 +50,4 @@ public abstract class AbstractStreamingParser extends AbstractParser implements
this.initStream(in);
return MultipleObjectsBundle.fromStream(this);
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/parser/ArffParser.java b/src/de/lmu/ifi/dbs/elki/datasource/parser/ArffParser.java
index d1280fbe..718963d1 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/parser/ArffParser.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/parser/ArffParser.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.parser;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,7 +24,7 @@ package de.lmu.ifi.dbs.elki.datasource.parser;
*/
import gnu.trove.iterator.TIntObjectIterator;
-import gnu.trove.map.hash.TIntFloatHashMap;
+import gnu.trove.map.hash.TIntDoubleHashMap;
import gnu.trove.map.hash.TIntObjectHashMap;
import java.io.BufferedReader;
@@ -41,7 +41,7 @@ import de.lmu.ifi.dbs.elki.data.DoubleVector;
import de.lmu.ifi.dbs.elki.data.ExternalID;
import de.lmu.ifi.dbs.elki.data.LabelList;
import de.lmu.ifi.dbs.elki.data.SimpleClassLabel;
-import de.lmu.ifi.dbs.elki.data.SparseFloatVector;
+import de.lmu.ifi.dbs.elki.data.SparseDoubleVector;
import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
@@ -60,7 +60,11 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.PatternParameter;
* This parser is quite hackish, and contains lots of not yet configurable
* magic.
*
- * TODO: Sparse vectors are not yet fully supported.
+ * TODO: Allow configuration of the vector types (double, float)
+ *
+ * TODO: when encountering integer columns, produce integer vectors.
+ *
+ * TODO: allow optional class labels.
*
* @author Erich Schubert
*/
@@ -146,8 +150,8 @@ public class ArffParser implements Parser {
public MultipleObjectsBundle parse(InputStream instream) {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(instream));
- ArrayList<String> names = new ArrayList<String>();
- ArrayList<String> types = new ArrayList<String>();
+ ArrayList<String> names = new ArrayList<>();
+ ArrayList<String> types = new ArrayList<>();
readHeader(br);
parseAttributeStatements(br, names, types);
@@ -205,7 +209,7 @@ public class ArffParser implements Parser {
private Object[] loadSparseInstance(StreamTokenizer tokenizer, int[] targ, int[] dimsize, TypeInformation[] elkitypes, int metaLength) throws IOException {
// logger.warning("Sparse instance.");
- TIntObjectHashMap<Object> map = new TIntObjectHashMap<Object>();
+ TIntObjectHashMap<Object> map = new TIntObjectHashMap<>();
while(true) {
nextToken(tokenizer);
assert (tokenizer.ttype != StreamTokenizer.TT_EOF && tokenizer.ttype != StreamTokenizer.TT_EOL);
@@ -216,19 +220,21 @@ public class ArffParser implements Parser {
}
else {
// sparse token
- if(tokenizer.ttype != StreamTokenizer.TT_NUMBER) {
- throw new AbortException("Unexpected token type encountered: " + tokenizer.toString());
+ if(tokenizer.ttype != StreamTokenizer.TT_WORD) {
+ throw new AbortException("Unexpected token type encountered: " + tokenizer.toString() + " type: " + tokenizer.ttype);
}
- int dim = (int) tokenizer.nval;
+ int dim = Integer.valueOf(tokenizer.sval);
if(map.containsKey(dim)) {
throw new AbortException("Duplicate key in sparse vector: " + tokenizer.toString());
}
nextToken(tokenizer);
- if(tokenizer.ttype == StreamTokenizer.TT_NUMBER) {
- map.put(dim, Double.valueOf(tokenizer.nval));
- }
- else if(tokenizer.ttype == StreamTokenizer.TT_WORD) {
- map.put(dim, tokenizer.sval);
+ if(tokenizer.ttype == StreamTokenizer.TT_WORD) {
+ if(TypeUtil.NUMBER_VECTOR_FIELD.equals(elkitypes[targ[dim]])) {
+ map.put(dim, AbstractParser.parseDouble(tokenizer.sval));
+ }
+ else {
+ map.put(dim, tokenizer.sval);
+ }
}
else {
throw new AbortException("Unexpected token type encountered: " + tokenizer.toString());
@@ -247,7 +253,7 @@ public class ArffParser implements Parser {
}
assert (s >= 0);
if(TypeUtil.NUMBER_VECTOR_FIELD.equals(elkitypes[out])) {
- TIntFloatHashMap f = new TIntFloatHashMap(dimsize[out]);
+ TIntDoubleHashMap f = new TIntDoubleHashMap(dimsize[out]);
for(TIntObjectIterator<Object> iter = map.iterator(); iter.hasNext();) {
iter.advance();
int i = iter.key();
@@ -258,9 +264,9 @@ public class ArffParser implements Parser {
break;
}
double v = ((Double) iter.value()).doubleValue();
- f.put(i - s + 1, (float) v);
+ f.put(i - s, v);
}
- data[out] = new SparseFloatVector(f, dimsize[out]);
+ data[out] = new SparseDoubleVector(f, dimsize[out]);
}
else if(TypeUtil.LABELLIST.equals(elkitypes[out])) {
// Build a label list out of successive labels
@@ -292,10 +298,10 @@ public class ArffParser implements Parser {
}
}
else if(TypeUtil.CLASSLABEL.equals(elkitypes[out])) {
- String val = (String) map.get(s);
+ Object val = map.get(s);
if(val != null) {
// TODO: support other class label types.
- ClassLabel lbl = new SimpleClassLabel(val);
+ ClassLabel lbl = new SimpleClassLabel(String.valueOf(val));
data[out] = lbl;
}
else {
@@ -321,7 +327,7 @@ public class ArffParser implements Parser {
}
else if(tokenizer.ttype == StreamTokenizer.TT_WORD) {
try {
- cur[k] = Double.parseDouble(tokenizer.sval);
+ cur[k] = AbstractParser.parseDouble(tokenizer.sval);
}
catch(NumberFormatException e) {
throw new AbortException("Expected number value, got: " + tokenizer.sval);
@@ -381,7 +387,7 @@ public class ArffParser implements Parser {
{
tokenizer.resetSyntax();
tokenizer.whitespaceChars(0, ' ');
- tokenizer.ordinaryChars('0', '9');
+ tokenizer.ordinaryChars('0', '9'); // Do not parse numbers
tokenizer.ordinaryChar('-');
tokenizer.ordinaryChar('.');
tokenizer.wordChars(' ' + 1, '\u00FF');
@@ -421,12 +427,12 @@ public class ArffParser implements Parser {
labels[i] = names.get(out + i);
}
if(!sparse) {
- VectorFieldTypeInformation<DoubleVector> type = new VectorFieldTypeInformation<DoubleVector>(DoubleVector.FACTORY, dimsize[out], labels);
+ VectorFieldTypeInformation<DoubleVector> type = new VectorFieldTypeInformation<>(DoubleVector.FACTORY, dimsize[out], labels);
bundle.appendColumn(type, new ArrayList<DoubleVector>());
}
else {
- VectorFieldTypeInformation<SparseFloatVector> type = new VectorFieldTypeInformation<SparseFloatVector>(SparseFloatVector.FACTORY, dimsize[out], labels);
- bundle.appendColumn(type, new ArrayList<SparseFloatVector>());
+ VectorFieldTypeInformation<SparseDoubleVector> type = new VectorFieldTypeInformation<>(SparseDoubleVector.FACTORY, dimsize[out], labels);
+ bundle.appendColumn(type, new ArrayList<SparseDoubleVector>());
}
}
else if(TypeUtil.LABELLIST.equals(etyp[out])) {
@@ -434,13 +440,13 @@ public class ArffParser implements Parser {
for(int i = 1; i < dimsize[out]; i++) {
label.append(' ').append(names.get(out + i));
}
- bundle.appendColumn(new SimpleTypeInformation<LabelList>(LabelList.class, label.toString()), new ArrayList<LabelList>());
+ bundle.appendColumn(new SimpleTypeInformation<>(LabelList.class, label.toString()), new ArrayList<LabelList>());
}
else if(TypeUtil.EXTERNALID.equals(etyp[out])) {
- bundle.appendColumn(new SimpleTypeInformation<ExternalID>(ExternalID.class, names.get(out)), new ArrayList<ExternalID>());
+ bundle.appendColumn(new SimpleTypeInformation<>(ExternalID.class, names.get(out)), new ArrayList<ExternalID>());
}
else if(TypeUtil.CLASSLABEL.equals(etyp[out])) {
- bundle.appendColumn(new SimpleTypeInformation<ClassLabel>(ClassLabel.class, names.get(out)), new ArrayList<ClassLabel>());
+ bundle.appendColumn(new SimpleTypeInformation<>(ClassLabel.class, names.get(out)), new ArrayList<ClassLabel>());
}
else {
throw new AbortException("Unsupported type for column " + in + "->" + out + ": " + ((etyp[out] != null) ? etyp[out].toString() : "null"));
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/parser/BitVectorLabelParser.java b/src/de/lmu/ifi/dbs/elki/datasource/parser/BitVectorLabelParser.java
index 32a26d7d..07019040 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/parser/BitVectorLabelParser.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/parser/BitVectorLabelParser.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.parser;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -63,11 +63,12 @@ public class BitVectorLabelParser extends AbstractParser implements Parser {
/**
* Constructor.
*
- * @param colSep
- * @param quoteChar
+ * @param colSep Column separator
+ * @param quoteChar Quotation character
+ * @param comment Comment pattern
*/
- public BitVectorLabelParser(Pattern colSep, char quoteChar) {
- super(colSep, quoteChar);
+ public BitVectorLabelParser(Pattern colSep, char quoteChar, Pattern comment) {
+ super(colSep, quoteChar, comment);
}
@Override
@@ -75,48 +76,47 @@ public class BitVectorLabelParser extends AbstractParser implements Parser {
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
int lineNumber = 0;
int dimensionality = -1;
- List<BitVector> vectors = new ArrayList<BitVector>();
- List<LabelList> labels = new ArrayList<LabelList>();
+ List<BitVector> vectors = new ArrayList<>();
+ List<LabelList> labels = new ArrayList<>();
try {
- for(String line; (line = reader.readLine()) != null; lineNumber++) {
- if(!line.startsWith(COMMENT) && line.length() > 0) {
- List<String> entries = tokenize(line);
- // FIXME: use more efficient storage right away?
- List<Bit> attributes = new ArrayList<Bit>();
- LabelList ll = null;
- for(String entry : entries) {
- try {
- Bit attribute = Bit.valueOf(entry);
- attributes.add(attribute);
- }
- catch(NumberFormatException e) {
- if(ll == null) {
- ll = new LabelList(1);
- }
- ll.add(entry);
+ for (String line; (line = reader.readLine()) != null; lineNumber++) {
+ // Skip empty lines and comments
+ if (line.length() <= 0 || (comment != null && comment.matcher(line).matches())) {
+ continue;
+ }
+ List<String> entries = tokenize(line);
+ // FIXME: use more efficient storage right away?
+ List<Bit> attributes = new ArrayList<>();
+ LabelList ll = null;
+ for (String entry : entries) {
+ try {
+ Bit attribute = Bit.valueOf(entry);
+ attributes.add(attribute);
+ } catch (NumberFormatException e) {
+ if (ll == null) {
+ ll = new LabelList(1);
}
+ ll.add(entry);
}
+ }
- if(dimensionality < 0) {
- dimensionality = attributes.size();
- }
- else if(dimensionality != attributes.size()) {
- throw new IllegalArgumentException("Differing dimensionality in line " + lineNumber + ".");
- }
-
- vectors.add(new BitVector(attributes.toArray(new Bit[attributes.size()])));
- labels.add(ll);
+ if (dimensionality < 0) {
+ dimensionality = attributes.size();
+ } else if (dimensionality != attributes.size()) {
+ throw new IllegalArgumentException("Differing dimensionality in line " + lineNumber + ".");
}
+
+ vectors.add(new BitVector(attributes.toArray(new Bit[attributes.size()])));
+ labels.add(ll);
}
- }
- catch(IOException e) {
+ } catch (IOException e) {
throw new IllegalArgumentException("Error while parsing line " + lineNumber + ".");
}
return MultipleObjectsBundle.makeSimple(getTypeInformation(dimensionality), vectors, TypeUtil.LABELLIST, labels);
}
protected VectorFieldTypeInformation<BitVector> getTypeInformation(int dimensionality) {
- return new VectorFieldTypeInformation<BitVector>(BitVector.FACTORY, dimensionality);
+ return new VectorFieldTypeInformation<>(BitVector.FACTORY, dimensionality);
}
@Override
@@ -134,7 +134,7 @@ public class BitVectorLabelParser extends AbstractParser implements Parser {
public static class Parameterizer extends AbstractParser.Parameterizer {
@Override
protected BitVectorLabelParser makeInstance() {
- return new BitVectorLabelParser(colSep, quoteChar);
+ return new BitVectorLabelParser(colSep, quoteChar, comment);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/parser/DoubleVectorLabelParser.java b/src/de/lmu/ifi/dbs/elki/datasource/parser/DoubleVectorLabelParser.java
index 0c291fb4..b95dce74 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/parser/DoubleVectorLabelParser.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/parser/DoubleVectorLabelParser.java
@@ -49,7 +49,8 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameteriz
*
* @apiviz.has DoubleVector
*
- * @deprecated Use NumberVectorLabelParser instead, which defaults to DoubleVector.
+ * @deprecated Use NumberVectorLabelParser instead, which defaults to
+ * DoubleVector.
*/
@Deprecated
public class DoubleVectorLabelParser extends NumberVectorLabelParser<DoubleVector> {
@@ -61,19 +62,20 @@ public class DoubleVectorLabelParser extends NumberVectorLabelParser<DoubleVecto
/**
* Constructor.
*
- * @param colSep
- * @param quoteChar
- * @param labelIndices
+ * @param colSep Column separator
+ * @param quoteChar Quotation character
+ * @param comment Comment pattern
+ * @param labelIndices Indices to use as labels
*/
- public DoubleVectorLabelParser(Pattern colSep, char quoteChar, BitSet labelIndices) {
- super(colSep, quoteChar, labelIndices, DoubleVector.FACTORY);
+ public DoubleVectorLabelParser(Pattern colSep, char quoteChar, Pattern comment, BitSet labelIndices) {
+ super(colSep, quoteChar, comment, labelIndices, DoubleVector.FACTORY);
}
/**
* Constructor with default values.
*/
public DoubleVectorLabelParser() {
- this(Pattern.compile(DEFAULT_SEPARATOR), QUOTE_CHAR, new BitSet());
+ this(Pattern.compile(DEFAULT_SEPARATOR), QUOTE_CHAR, Pattern.compile(COMMENT_PATTERN), new BitSet());
}
@Override
@@ -96,7 +98,7 @@ public class DoubleVectorLabelParser extends NumberVectorLabelParser<DoubleVecto
@Override
protected DoubleVectorLabelParser makeInstance() {
- return new DoubleVectorLabelParser(colSep, quoteChar, labelIndices);
+ return new DoubleVectorLabelParser(colSep, quoteChar, comment, labelIndices);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/parser/FloatVectorLabelParser.java b/src/de/lmu/ifi/dbs/elki/datasource/parser/FloatVectorLabelParser.java
index 6288da8e..71b65cfc 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/parser/FloatVectorLabelParser.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/parser/FloatVectorLabelParser.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.datasource.parser;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -57,19 +57,20 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameteriz
@Deprecated
public class FloatVectorLabelParser extends NumberVectorLabelParser<FloatVector> {
/**
- * Class logger
+ * Class logger.
*/
private static final Logging LOG = Logging.getLogger(FloatVectorLabelParser.class);
/**
* Constructor.
*
- * @param colSep
- * @param quoteChar
- * @param labelIndices
+ * @param colSep Column separator
+ * @param quoteChar Quotation character
+ * @param comment Comment pattern
+ * @param labelIndices Indices to use as labels
*/
- public FloatVectorLabelParser(Pattern colSep, char quoteChar, BitSet labelIndices) {
- super(colSep, quoteChar, labelIndices, FloatVector.FACTORY);
+ public FloatVectorLabelParser(Pattern colSep, char quoteChar, Pattern comment, BitSet labelIndices) {
+ super(colSep, quoteChar, comment, labelIndices, FloatVector.FACTORY);
}
@Override
@@ -92,7 +93,7 @@ public class FloatVectorLabelParser extends NumberVectorLabelParser<FloatVector>
@Override
protected FloatVectorLabelParser makeInstance() {
- return new FloatVectorLabelParser(colSep, quoteChar, labelIndices);
+ return new FloatVectorLabelParser(colSep, quoteChar, comment, labelIndices);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/parser/NumberVectorLabelParser.java b/src/de/lmu/ifi/dbs/elki/datasource/parser/NumberVectorLabelParser.java
index ea44c072..39da752b 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/parser/NumberVectorLabelParser.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/parser/NumberVectorLabelParser.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.parser;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -40,6 +40,7 @@ import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
import de.lmu.ifi.dbs.elki.data.type.VectorFieldTypeInformation;
+import de.lmu.ifi.dbs.elki.data.type.VectorTypeInformation;
import de.lmu.ifi.dbs.elki.datasource.bundle.BundleMeta;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayLikeUtil;
@@ -97,16 +98,6 @@ public class NumberVectorLabelParser<V extends NumberVector<?>> extends Abstract
public static final OptionID VECTOR_TYPE_ID = new OptionID("parser.vector-type", "The type of vectors to create for numerical attributes.");
/**
- * Constant used for unknown dimensionality (e.g. empty files)
- */
- public static final int DIMENSIONALITY_UNKNOWN = -1;
-
- /**
- * Constant used for records of variable dimensionality (e.g. time series)
- */
- public static final int DIMENSIONALITY_VARIABLE = -2;
-
- /**
* Keeps the indices of the attributes to be treated as a string label.
*/
protected BitSet labelIndices;
@@ -129,7 +120,7 @@ public class NumberVectorLabelParser<V extends NumberVector<?>> extends Abstract
/**
* Dimensionality reported.
*/
- protected int dimensionality;
+ protected int mindim, maxdim;
/**
* Metadata.
@@ -167,7 +158,7 @@ public class NumberVectorLabelParser<V extends NumberVector<?>> extends Abstract
* @param factory Vector factory
*/
public NumberVectorLabelParser(NumberVector.Factory<V, ?> factory) {
- this(Pattern.compile(DEFAULT_SEPARATOR), QUOTE_CHAR, null, factory);
+ this(Pattern.compile(DEFAULT_SEPARATOR), QUOTE_CHAR, Pattern.compile(COMMENT_PATTERN), null, factory);
}
/**
@@ -175,11 +166,12 @@ public class NumberVectorLabelParser<V extends NumberVector<?>> extends Abstract
*
* @param colSep Column separator
* @param quoteChar Quote character
+ * @param comment Comment pattern
* @param labelIndices Column indexes that are numeric.
* @param factory Vector factory
*/
- public NumberVectorLabelParser(Pattern colSep, char quoteChar, BitSet labelIndices, NumberVector.Factory<V, ?> factory) {
- super(colSep, quoteChar);
+ public NumberVectorLabelParser(Pattern colSep, char quoteChar, Pattern comment, BitSet labelIndices, NumberVector.Factory<V, ?> factory) {
+ super(colSep, quoteChar, comment);
this.labelIndices = labelIndices;
this.factory = factory;
}
@@ -188,7 +180,8 @@ public class NumberVectorLabelParser<V extends NumberVector<?>> extends Abstract
public void initStream(InputStream in) {
reader = new BufferedReader(new InputStreamReader(in));
lineNumber = 1;
- dimensionality = DIMENSIONALITY_UNKNOWN;
+ mindim = Integer.MAX_VALUE;
+ maxdim = 0;
columnnames = null;
labelcolumns = new BitSet();
if (labelIndices != null) {
@@ -210,31 +203,34 @@ public class NumberVectorLabelParser<V extends NumberVector<?>> extends Abstract
}
try {
for (String line; (line = reader.readLine()) != null; lineNumber++) {
- if (!line.startsWith(COMMENT) && line.length() > 0) {
- parseLineInternal(line);
- // Maybe a header column?
- if (curvec == null) {
- continue;
- }
- if (dimensionality == DIMENSIONALITY_UNKNOWN) {
- dimensionality = curvec.getDimensionality();
- buildMeta();
- nextevent = Event.NEXT_OBJECT;
- return Event.META_CHANGED;
- } else if (dimensionality > 0) {
- if (dimensionality != curvec.getDimensionality()) {
- dimensionality = DIMENSIONALITY_VARIABLE;
- buildMeta();
- nextevent = Event.NEXT_OBJECT;
- return Event.META_CHANGED;
- }
- } else if (curlbl != null && meta != null && meta.size() == 1) {
- buildMeta();
- nextevent = Event.NEXT_OBJECT;
- return Event.META_CHANGED;
- }
- return Event.NEXT_OBJECT;
+ // Skip empty lines and comments
+ if (line.length() <= 0 || (comment != null && comment.matcher(line).matches())) {
+ continue;
+ }
+ parseLineInternal(line);
+ // Maybe a header column?
+ if (curvec == null) {
+ continue;
}
+ final int curdim = curvec.getDimensionality();
+ if (maxdim < mindim) {
+ mindim = curdim;
+ maxdim = curdim;
+ buildMeta();
+ nextevent = Event.NEXT_OBJECT;
+ return Event.META_CHANGED;
+ } else if (mindim < curdim || maxdim > curdim) {
+ mindim = Math.min(mindim, curdim);
+ maxdim = Math.max(maxdim, curdim);
+ buildMeta();
+ nextevent = Event.NEXT_OBJECT;
+ return Event.META_CHANGED;
+ } else if (curlbl != null && meta != null && meta.size() == 1) {
+ buildMeta();
+ nextevent = Event.NEXT_OBJECT;
+ return Event.META_CHANGED;
+ }
+ return Event.NEXT_OBJECT;
}
reader.close();
reader = null;
@@ -250,11 +246,11 @@ public class NumberVectorLabelParser<V extends NumberVector<?>> extends Abstract
protected void buildMeta() {
if (labelcolumns.cardinality() > 0 || (labelIndices != null && labelIndices.cardinality() > 0)) {
meta = new BundleMeta(2);
- meta.add(getTypeInformation(dimensionality));
+ meta.add(getTypeInformation(mindim, maxdim));
meta.add(TypeUtil.LABELLIST);
} else {
meta = new BundleMeta(1);
- meta.add(getTypeInformation(dimensionality));
+ meta.add(getTypeInformation(mindim, maxdim));
}
}
@@ -287,7 +283,7 @@ public class NumberVectorLabelParser<V extends NumberVector<?>> extends Abstract
String ent = itr.next();
if (labelIndices == null || !labelIndices.get(i)) {
try {
- double attribute = Double.parseDouble(ent);
+ double attribute = parseDouble(ent);
attributes.add(attribute);
continue;
} catch (NumberFormatException e) {
@@ -333,15 +329,16 @@ public class NumberVectorLabelParser<V extends NumberVector<?>> extends Abstract
/**
* Get a prototype object for the given dimensionality.
*
- * @param dimensionality Dimensionality
+ * @param mindim Minimum dimensionality
+ * @param maxdim Maximum dimensionality
* @return Prototype object
*/
- SimpleTypeInformation<V> getTypeInformation(int dimensionality) {
- if (dimensionality > 0) {
+ SimpleTypeInformation<V> getTypeInformation(int mindim, int maxdim) {
+ if (mindim == maxdim) {
String[] colnames = null;
if (columnnames != null) {
- if (columnnames.size() - labelcolumns.cardinality() == dimensionality) {
- colnames = new String[dimensionality];
+ if (columnnames.size() - labelcolumns.cardinality() == mindim) {
+ colnames = new String[mindim];
for (int i = 0, j = 0; i < columnnames.size(); i++) {
if (!labelcolumns.get(i)) {
colnames[j] = columnnames.get(i);
@@ -350,13 +347,13 @@ public class NumberVectorLabelParser<V extends NumberVector<?>> extends Abstract
}
}
}
- return new VectorFieldTypeInformation<V>(factory, dimensionality, colnames);
- }
- // Variable dimensionality - return non-vector field type
- if (dimensionality == DIMENSIONALITY_VARIABLE) {
- return new SimpleTypeInformation<V>(factory.getRestrictionClass(), factory.getDefaultSerializer());
+ return new VectorFieldTypeInformation<>(factory, mindim, colnames);
+ } else if (mindim < maxdim) {
+ // Variable dimensionality - return non-vector field type
+ return new VectorTypeInformation<>(factory.getRestrictionClass(), factory.getDefaultSerializer(), mindim, maxdim);
+ } else {
+ throw new AbortException("No vectors were read from the input file - cannot determine vector data type.");
}
- throw new AbortException("No vectors were read from the input file - cannot determine vector data type.");
}
@Override
@@ -395,7 +392,7 @@ public class NumberVectorLabelParser<V extends NumberVector<?>> extends Abstract
* @param config Parameterization
*/
protected void getFactory(Parameterization config) {
- ObjectParameter<NumberVector.Factory<V, ?>> factoryP = new ObjectParameter<NumberVector.Factory<V, ?>>(VECTOR_TYPE_ID, NumberVector.Factory.class, DoubleVector.Factory.class);
+ ObjectParameter<NumberVector.Factory<V, ?>> factoryP = new ObjectParameter<>(VECTOR_TYPE_ID, NumberVector.Factory.class, DoubleVector.Factory.class);
if (config.grab(factoryP)) {
factory = factoryP.instantiateClass(config);
}
@@ -420,7 +417,7 @@ public class NumberVectorLabelParser<V extends NumberVector<?>> extends Abstract
@Override
protected NumberVectorLabelParser<V> makeInstance() {
- return new NumberVectorLabelParser<V>(colSep, quoteChar, labelIndices, factory);
+ return new NumberVectorLabelParser<>(colSep, quoteChar, comment, labelIndices, factory);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/parser/Parser.java b/src/de/lmu/ifi/dbs/elki/datasource/parser/Parser.java
index 5b511a92..a0b4e573 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/parser/Parser.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/parser/Parser.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.parser;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,7 +26,6 @@ package de.lmu.ifi.dbs.elki.datasource.parser;
import java.io.InputStream;
import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle;
-import de.lmu.ifi.dbs.elki.utilities.InspectionUtilFrequentlyScanned;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable;
/**
@@ -38,7 +37,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable;
* @apiviz.uses InputStream
* @apiviz.has MultipleObjectsBundle oneway - - «create»
*/
-public interface Parser extends Parameterizable, InspectionUtilFrequentlyScanned {
+public interface Parser extends Parameterizable {
/**
* Returns a list of the objects parsed from the specified input stream.
*
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/parser/SimplePolygonParser.java b/src/de/lmu/ifi/dbs/elki/datasource/parser/SimplePolygonParser.java
index ce366b9e..a3d46ed8 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/parser/SimplePolygonParser.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/parser/SimplePolygonParser.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.parser;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -77,11 +77,12 @@ public class SimplePolygonParser extends AbstractParser implements Parser {
/**
* Constructor.
*
- * @param colSep
- * @param quoteChar
+ * @param colSep Column separator
+ * @param quoteChar Quotation character
+ * @param comment Comment pattern
*/
- public SimplePolygonParser(Pattern colSep, char quoteChar) {
- super(colSep, quoteChar);
+ public SimplePolygonParser(Pattern colSep, char quoteChar, Pattern comment) {
+ super(colSep, quoteChar, comment);
}
@Override
@@ -89,35 +90,35 @@ public class SimplePolygonParser extends AbstractParser implements Parser {
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
int lineNumber = 1;
- List<PolygonsObject> polys = new ArrayList<PolygonsObject>();
+ List<PolygonsObject> polys = new ArrayList<>();
List<LabelList> labels = null;
- List<ExternalID> eids = new ArrayList<ExternalID>();
+ List<ExternalID> eids = new ArrayList<>();
try {
- for(String line; (line = reader.readLine()) != null; lineNumber++) {
- if(!line.startsWith(COMMENT) && line.length() > 0) {
- Object[] objs = parseLine(line);
- polys.add((PolygonsObject) objs[0]);
- if(objs[1] != null) {
- if(labels == null) {
- labels = new ArrayList<LabelList>();
- for(int i = 0; i < polys.size() - 1; i++) {
- labels.add(null);
- }
+ for (String line; (line = reader.readLine()) != null; lineNumber++) {
+ // Skip empty lines and comments
+ if (line.length() <= 0 || (comment != null && comment.matcher(line).matches())) {
+ continue;
+ }
+ Object[] objs = parseLine(line);
+ polys.add((PolygonsObject) objs[0]);
+ if (objs[1] != null) {
+ if (labels == null) {
+ labels = new ArrayList<>();
+ for (int i = 0; i < polys.size() - 1; i++) {
+ labels.add(null);
}
- labels.add((LabelList) objs[1]);
}
- eids.add((ExternalID) objs[2]);
+ labels.add((LabelList) objs[1]);
}
+ eids.add((ExternalID) objs[2]);
}
- }
- catch(IOException e) {
+ } catch (IOException e) {
throw new IllegalArgumentException("Error while parsing line " + lineNumber + ".");
}
- if(labels != null) {
+ if (labels != null) {
return MultipleObjectsBundle.makeSimple(TypeUtil.POLYGON_TYPE, polys, TypeUtil.LABELLIST, labels, TypeUtil.EXTERNALID, eids);
- }
- else {
+ } else {
return MultipleObjectsBundle.makeSimple(TypeUtil.POLYGON_TYPE, polys, TypeUtil.EXTERNALID, eids);
}
}
@@ -135,51 +136,48 @@ public class SimplePolygonParser extends AbstractParser implements Parser {
ExternalID eid = null;
LabelList labels = null;
- List<Polygon> polys = new ArrayList<Polygon>(1);
+ List<Polygon> polys = new ArrayList<>(1);
- List<Vector> coords = new ArrayList<Vector>();
- while(iter.hasNext()) {
+ List<Vector> coords = new ArrayList<>();
+ while (iter.hasNext()) {
String cur = iter.next();
Matcher m = COORD.matcher(cur);
- if(m.find()) {
+ if (m.find()) {
try {
double c1 = Double.parseDouble(m.group(1));
double c2 = Double.parseDouble(m.group(2));
- if(m.group(3) != null) {
+ if (m.group(3) != null) {
double c3 = Double.parseDouble(m.group(3));
coords.add(new Vector(new double[] { c1, c2, c3 }));
- }
- else {
+ } else {
coords.add(new Vector(new double[] { c1, c2 }));
}
continue;
- }
- catch(NumberFormatException e) {
+ } catch (NumberFormatException e) {
LOG.warning("Looked like a coordinate pair but didn't parse: " + cur);
}
}
// Polygon separator.
- if(cur.equals(POLYGON_SEPARATOR)) {
- if(coords.size() > 0) {
+ if (cur.equals(POLYGON_SEPARATOR)) {
+ if (coords.size() > 0) {
polys.add(new Polygon(coords));
- coords = new ArrayList<Vector>();
+ coords = new ArrayList<>();
}
continue;
}
// First label will become the External ID
- if(eid == null) {
+ if (eid == null) {
eid = new ExternalID(cur);
- }
- else {
+ } else {
// Label
- if(labels == null) {
+ if (labels == null) {
labels = new LabelList(1);
}
labels.add(cur);
}
}
// Complete polygon
- if(coords.size() > 0) {
+ if (coords.size() > 0) {
polys.add(new Polygon(coords));
}
return new Object[] { new PolygonsObject(polys), labels, eid };
@@ -201,19 +199,24 @@ public class SimplePolygonParser extends AbstractParser implements Parser {
@Override
protected void makeOptions(Parameterization config) {
PatternParameter colParam = new PatternParameter(COLUMN_SEPARATOR_ID, "\\s+");
- if(config.grab(colParam)) {
+ if (config.grab(colParam)) {
colSep = colParam.getValue();
}
StringParameter quoteParam = new StringParameter(QUOTE_ID, String.valueOf(QUOTE_CHAR));
quoteParam.addConstraint(new StringLengthConstraint(1, 1));
- if(config.grab(quoteParam)) {
+ if (config.grab(quoteParam)) {
quoteChar = quoteParam.getValue().charAt(0);
}
+
+ PatternParameter commentP = new PatternParameter(COMMENT_ID, COMMENT_PATTERN);
+ if (config.grab(commentP)) {
+ comment = commentP.getValue();
+ }
}
@Override
protected SimplePolygonParser makeInstance() {
- return new SimplePolygonParser(colSep, quoteChar);
+ return new SimplePolygonParser(colSep, quoteChar, comment);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/parser/SparseBitVectorLabelParser.java b/src/de/lmu/ifi/dbs/elki/datasource/parser/SparseBitVectorLabelParser.java
index 35e53bb7..5f9e5e05 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/parser/SparseBitVectorLabelParser.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/parser/SparseBitVectorLabelParser.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.parser;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -64,11 +64,12 @@ public class SparseBitVectorLabelParser extends AbstractParser implements Parser
/**
* Constructor.
*
- * @param colSep
- * @param quoteChar
+ * @param colSep Column separator
+ * @param quoteChar Quotation character
+ * @param comment Comment pattern
*/
- public SparseBitVectorLabelParser(Pattern colSep, char quoteChar) {
- super(colSep, quoteChar);
+ public SparseBitVectorLabelParser(Pattern colSep, char quoteChar, Pattern comment) {
+ super(colSep, quoteChar, comment);
}
@Override
@@ -76,54 +77,54 @@ public class SparseBitVectorLabelParser extends AbstractParser implements Parser
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
int lineNumber = 0;
int dimensionality = -1;
- List<BitVector> vectors = new ArrayList<BitVector>();
- List<LabelList> lblc = new ArrayList<LabelList>();
+ List<BitVector> vectors = new ArrayList<>();
+ List<LabelList> lblc = new ArrayList<>();
try {
- List<BitSet> bitSets = new ArrayList<BitSet>();
- List<LabelList> allLabels = new ArrayList<LabelList>();
- for(String line; (line = reader.readLine()) != null; lineNumber++) {
- if(!line.startsWith(COMMENT) && line.length() > 0) {
- List<String> entries = tokenize(line);
- BitSet bitSet = new BitSet();
- LabelList labels = null;
-
- for(String entry : entries) {
- try {
- int index = Integer.parseInt(entry);
- bitSet.set(index);
- dimensionality = Math.max(dimensionality, index);
- }
- catch(NumberFormatException e) {
- if(labels == null) {
- labels = new LabelList(1);
- }
- labels.add(entry);
+ List<BitSet> bitSets = new ArrayList<>();
+ List<LabelList> allLabels = new ArrayList<>();
+ for (String line; (line = reader.readLine()) != null; lineNumber++) {
+ // Skip empty lines and comments
+ if (line.length() <= 0 || (comment != null && comment.matcher(line).matches())) {
+ continue;
+ }
+ List<String> entries = tokenize(line);
+ BitSet bitSet = new BitSet();
+ LabelList labels = null;
+
+ for (String entry : entries) {
+ try {
+ int index = Integer.parseInt(entry);
+ bitSet.set(index);
+ dimensionality = Math.max(dimensionality, index);
+ } catch (NumberFormatException e) {
+ if (labels == null) {
+ labels = new LabelList(1);
}
+ labels.add(entry);
}
-
- bitSets.add(bitSet);
- allLabels.add(labels);
}
+
+ bitSets.add(bitSet);
+ allLabels.add(labels);
}
dimensionality++;
- for(int i = 0; i < bitSets.size(); i++) {
+ for (int i = 0; i < bitSets.size(); i++) {
BitSet bitSet = bitSets.get(i);
LabelList labels = allLabels.get(i);
vectors.add(new BitVector(bitSet, dimensionality));
lblc.add(labels);
}
- }
- catch(IOException e) {
+ } catch (IOException e) {
throw new IllegalArgumentException("Error while parsing line " + lineNumber + ".");
}
return MultipleObjectsBundle.makeSimple(getTypeInformation(dimensionality), vectors, TypeUtil.LABELLIST, lblc);
}
protected VectorFieldTypeInformation<BitVector> getTypeInformation(int dimensionality) {
- return new VectorFieldTypeInformation<BitVector>(BitVector.FACTORY, dimensionality);
+ return new VectorFieldTypeInformation<>(BitVector.FACTORY, dimensionality);
}
-
+
@Override
protected Logging getLogger() {
return LOG;
@@ -139,7 +140,7 @@ public class SparseBitVectorLabelParser extends AbstractParser implements Parser
public static class Parameterizer extends AbstractParser.Parameterizer {
@Override
protected SparseBitVectorLabelParser makeInstance() {
- return new SparseBitVectorLabelParser(colSep, quoteChar);
+ return new SparseBitVectorLabelParser(colSep, quoteChar, comment);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/parser/SparseFloatVectorLabelParser.java b/src/de/lmu/ifi/dbs/elki/datasource/parser/SparseFloatVectorLabelParser.java
index 9f658b0a..d5fe6219 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/parser/SparseFloatVectorLabelParser.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/parser/SparseFloatVectorLabelParser.java
@@ -75,10 +75,11 @@ public class SparseFloatVectorLabelParser extends SparseNumberVectorLabelParser<
*
* @param colSep Column separator
* @param quoteChar Quotation character
- * @param labelIndices Label indexes
+ * @param comment Comment pattern
+ * @param labelIndices Indices to use as labels
*/
- public SparseFloatVectorLabelParser(Pattern colSep, char quoteChar, BitSet labelIndices) {
- super(colSep, quoteChar, labelIndices, SparseFloatVector.FACTORY);
+ public SparseFloatVectorLabelParser(Pattern colSep, char quoteChar, Pattern comment, BitSet labelIndices) {
+ super(colSep, quoteChar, comment, labelIndices, SparseFloatVector.FACTORY);
}
/**
@@ -91,7 +92,7 @@ public class SparseFloatVectorLabelParser extends SparseNumberVectorLabelParser<
public static class Parameterizer extends SparseNumberVectorLabelParser.Parameterizer<SparseFloatVector> {
@Override
protected SparseFloatVectorLabelParser makeInstance() {
- return new SparseFloatVectorLabelParser(colSep, quoteChar, labelIndices);
+ return new SparseFloatVectorLabelParser(colSep, quoteChar, comment, labelIndices);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/parser/SparseNumberVectorLabelParser.java b/src/de/lmu/ifi/dbs/elki/datasource/parser/SparseNumberVectorLabelParser.java
index f4ec8c59..bdd8ab77 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/parser/SparseNumberVectorLabelParser.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/parser/SparseNumberVectorLabelParser.java
@@ -34,6 +34,7 @@ import de.lmu.ifi.dbs.elki.data.SparseFloatVector;
import de.lmu.ifi.dbs.elki.data.SparseNumberVector;
import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
import de.lmu.ifi.dbs.elki.data.type.VectorFieldTypeInformation;
+import de.lmu.ifi.dbs.elki.data.type.VectorTypeInformation;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.utilities.documentation.Description;
import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
@@ -86,12 +87,6 @@ public class SparseNumberVectorLabelParser<V extends SparseNumberVector<?>> exte
private static final Logging LOG = Logging.getLogger(SparseNumberVectorLabelParser.class);
/**
- * Holds the dimensionality of the parsed data which is the maximum occurring
- * index of any attribute.
- */
- private int maxdim = -1;
-
- /**
* Same as {@link #factory}, but subtype.
*/
private SparseNumberVector.Factory<V, ?> sparsefactory;
@@ -101,11 +96,12 @@ public class SparseNumberVectorLabelParser<V extends SparseNumberVector<?>> exte
*
* @param colSep Column separator
* @param quoteChar Quotation character
- * @param labelIndices Label indexes
+ * @param comment Comment pattern
+ * @param labelIndices Indices to use as labels
* @param factory Vector factory
*/
- public SparseNumberVectorLabelParser(Pattern colSep, char quoteChar, BitSet labelIndices, SparseNumberVector.Factory<V, ?> factory) {
- super(colSep, quoteChar, labelIndices, factory);
+ public SparseNumberVectorLabelParser(Pattern colSep, char quoteChar, Pattern comment, BitSet labelIndices, SparseNumberVector.Factory<V, ?> factory) {
+ super(colSep, quoteChar, comment, labelIndices, factory);
this.sparsefactory = factory;
}
@@ -116,7 +112,8 @@ public class SparseNumberVectorLabelParser<V extends SparseNumberVector<?>> exte
TIntDoubleHashMap values = new TIntDoubleHashMap(cardinality, 1);
LabelList labels = null;
-
+ int thismax = 0;
+
for (int i = 1; i < entries.size() - 1; i++) {
if (labelIndices == null || !labelIndices.get(i)) {
try {
@@ -124,7 +121,8 @@ public class SparseNumberVectorLabelParser<V extends SparseNumberVector<?>> exte
if (index >= maxdim) {
maxdim = index + 1;
}
- double attribute = Double.parseDouble(entries.get(i));
+ thismax = Math.max(thismax, index);
+ double attribute = parseDouble(entries.get(i));
values.put(index, attribute);
i++;
} catch (NumberFormatException e) {
@@ -144,17 +142,19 @@ public class SparseNumberVectorLabelParser<V extends SparseNumberVector<?>> exte
if (values.size() > maxdim) {
throw new AbortException("Invalid sparse vector seen: " + line);
}
+ if (thismax < mindim) {
+ mindim = thismax;
+ }
curvec = sparsefactory.newNumberVector(values, maxdim);
curlbl = labels;
}
@Override
- protected SimpleTypeInformation<V> getTypeInformation(int dimensionality) {
- if (dimensionality > 0) {
- return new VectorFieldTypeInformation<V>(factory, dimensionality);
- }
- if (dimensionality == DIMENSIONALITY_VARIABLE) {
- return new SimpleTypeInformation<V>(factory.getRestrictionClass(), factory.getDefaultSerializer());
+ protected SimpleTypeInformation<V> getTypeInformation(int mindim, int maxdim) {
+ if (mindim == maxdim) {
+ return new VectorFieldTypeInformation<>(factory, mindim);
+ } else if (mindim < maxdim) {
+ return new VectorTypeInformation<>(factory.getRestrictionClass(), factory.getDefaultSerializer(), mindim, maxdim);
}
throw new AbortException("No vectors were read from the input file - cannot determine vector data type.");
}
@@ -174,7 +174,7 @@ public class SparseNumberVectorLabelParser<V extends SparseNumberVector<?>> exte
public static class Parameterizer<V extends SparseNumberVector<?>> extends NumberVectorLabelParser.Parameterizer<V> {
@Override
protected void getFactory(Parameterization config) {
- ObjectParameter<SparseNumberVector.Factory<V, ?>> factoryP = new ObjectParameter<SparseNumberVector.Factory<V, ?>>(VECTOR_TYPE_ID, SparseNumberVector.Factory.class, SparseFloatVector.Factory.class);
+ ObjectParameter<SparseNumberVector.Factory<V, ?>> factoryP = new ObjectParameter<>(VECTOR_TYPE_ID, SparseNumberVector.Factory.class, SparseFloatVector.Factory.class);
if (config.grab(factoryP)) {
factory = factoryP.instantiateClass(config);
}
@@ -182,7 +182,7 @@ public class SparseNumberVectorLabelParser<V extends SparseNumberVector<?>> exte
@Override
protected SparseNumberVectorLabelParser<V> makeInstance() {
- return new SparseNumberVectorLabelParser<V>(colSep, quoteChar, labelIndices, (SparseNumberVector.Factory<V, ?>) factory);
+ return new SparseNumberVectorLabelParser<>(colSep, quoteChar, comment, labelIndices, (SparseNumberVector.Factory<V, ?>) factory);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/parser/StreamingParser.java b/src/de/lmu/ifi/dbs/elki/datasource/parser/StreamingParser.java
index 01579dc6..73d38e3c 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/parser/StreamingParser.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/parser/StreamingParser.java
@@ -8,7 +8,7 @@ import de.lmu.ifi.dbs.elki.datasource.bundle.BundleStreamSource;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/parser/StringParser.java b/src/de/lmu/ifi/dbs/elki/datasource/parser/StringParser.java
new file mode 100644
index 00000000..41f21c5d
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/datasource/parser/StringParser.java
@@ -0,0 +1,146 @@
+package de.lmu.ifi.dbs.elki.datasource.parser;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import de.lmu.ifi.dbs.elki.data.LabelList;
+import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Description;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Flag;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.PatternParameter;
+
+/**
+ * Parser that loads a text file for use with string similarity measures.
+ *
+ * The parser produces two relations: the first of type String, the second of
+ * type label list, which contains the same data for convenience.
+ *
+ * @author Felix Stahlberg
+ * @author Erich Schubert
+ */
+@Title("String Parser")
+@Description("Parses new line separated strings")
+public class StringParser implements Parser {
+ /**
+ * Comment pattern.
+ */
+ Pattern comment;
+
+ /**
+ * Flag to trim whitespace.
+ */
+ boolean trimWhitespace;
+
+ /**
+ * Constructor.
+ *
+ * @param comment Pattern for comments.
+ * @param trimWhitespace Trim leading and trailing whitespace.
+ */
+ public StringParser(Pattern comment, boolean trimWhitespace) {
+ super();
+ this.comment = comment;
+ this.trimWhitespace = trimWhitespace;
+ }
+
+ @Override
+ public MultipleObjectsBundle parse(InputStream in) {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(in));
+ int lineNumber = 0;
+ List<String> data = new ArrayList<>();
+ List<LabelList> labels = new ArrayList<>();
+ try {
+ for (String line; (line = reader.readLine()) != null; lineNumber++) {
+ // Skip empty lines and comments
+ if (line.length() <= 0 || (comment != null && comment.matcher(line).matches())) {
+ continue;
+ }
+ final String val = trimWhitespace ? line.trim() : line;
+ data.add(val);
+ LabelList ll = new LabelList(1);
+ ll.add(val);
+ labels.add(ll);
+ }
+ } catch (IOException e) {
+ throw new IllegalArgumentException("Error while parsing line " + lineNumber + ".");
+ }
+ return MultipleObjectsBundle.makeSimple(TypeUtil.STRING, data, TypeUtil.LABELLIST, labels);
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Felix Stahlberg
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ /**
+ * Flag to trim whitespace.
+ */
+ public static final OptionID TRIM_ID = new OptionID("string.trim", "Remove leading and trailing whitespace from each line.");
+
+ /**
+ * Comment pattern.
+ */
+ Pattern comment = null;
+
+ /**
+ * Flag to trim whitespace.
+ */
+ boolean trimWhitespace = false;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ PatternParameter commentP = new PatternParameter(AbstractParser.Parameterizer.COMMENT_ID, "^\\s*#.*$");
+ if (config.grab(commentP)) {
+ comment = commentP.getValue();
+ }
+
+ Flag trimP = new Flag(TRIM_ID);
+ if (config.grab(trimP)) {
+ trimWhitespace = trimP.isTrue();
+ }
+ }
+
+ @Override
+ protected StringParser makeInstance() {
+ return new StringParser(comment, trimWhitespace);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/parser/TermFrequencyParser.java b/src/de/lmu/ifi/dbs/elki/datasource/parser/TermFrequencyParser.java
index 2ea6ebb5..580c5320 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/parser/TermFrequencyParser.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/parser/TermFrequencyParser.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.datasource.parser;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,10 +24,11 @@ package de.lmu.ifi.dbs.elki.datasource.parser;
*/
import gnu.trove.iterator.TIntDoubleIterator;
+import gnu.trove.map.TObjectIntMap;
import gnu.trove.map.hash.TIntDoubleHashMap;
+import gnu.trove.map.hash.TObjectIntHashMap;
import java.util.BitSet;
-import java.util.HashMap;
import java.util.List;
import java.util.regex.Pattern;
@@ -36,6 +37,7 @@ import de.lmu.ifi.dbs.elki.data.SparseFloatVector;
import de.lmu.ifi.dbs.elki.data.SparseNumberVector;
import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
import de.lmu.ifi.dbs.elki.data.type.VectorFieldTypeInformation;
+import de.lmu.ifi.dbs.elki.data.type.VectorTypeInformation;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.utilities.documentation.Description;
import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
@@ -62,14 +64,14 @@ public class TermFrequencyParser<V extends SparseNumberVector<?>> extends Number
private static final Logging LOG = Logging.getLogger(TermFrequencyParser.class);
/**
- * Maximum dimension used.
+ * Number of different terms observed.
*/
- int maxdim;
+ int numterms;
/**
* Map.
*/
- HashMap<String, Integer> keymap;
+ TObjectIntMap<String> keymap;
/**
* Normalize.
@@ -85,15 +87,15 @@ public class TermFrequencyParser<V extends SparseNumberVector<?>> extends Number
* Constructor.
*
* @param normalize Normalize
- * @param colSep
- * @param quoteChar
- * @param labelIndices
+ * @param colSep Column separator
+ * @param quoteChar Quotation character
+ * @param comment Comment pattern
+ * @param labelIndices Indices to use as labels
*/
- public TermFrequencyParser(boolean normalize, Pattern colSep, char quoteChar, BitSet labelIndices, SparseNumberVector.Factory<V, ?> factory) {
- super(colSep, quoteChar, labelIndices, factory);
+ public TermFrequencyParser(boolean normalize, Pattern colSep, char quoteChar, Pattern comment, BitSet labelIndices, SparseNumberVector.Factory<V, ?> factory) {
+ super(colSep, quoteChar, comment, labelIndices, factory);
this.normalize = normalize;
- this.maxdim = 0;
- this.keymap = new HashMap<String, Integer>();
+ this.keymap = new TObjectIntHashMap<>(1001, .5f, -1);
this.sparsefactory = factory;
}
@@ -111,12 +113,12 @@ public class TermFrequencyParser<V extends SparseNumberVector<?>> extends Number
curterm = entries.get(i);
} else {
try {
- double attribute = Double.parseDouble(entries.get(i));
- Integer curdim = keymap.get(curterm);
- if (curdim == null) {
- curdim = Integer.valueOf(maxdim + 1);
+ double attribute = parseDouble(entries.get(i));
+ int curdim = keymap.get(curterm);
+ if (curdim < 0) {
+ curdim = numterms;
keymap.put(curterm, curdim);
- maxdim += 1;
+ ++numterms;
}
values.put(curdim, attribute);
len += attribute;
@@ -147,17 +149,16 @@ public class TermFrequencyParser<V extends SparseNumberVector<?>> extends Number
}
}
- curvec = sparsefactory.newNumberVector(values, maxdim);
+ curvec = sparsefactory.newNumberVector(values, numterms);
curlbl = labels;
}
@Override
- protected SimpleTypeInformation<V> getTypeInformation(int dimensionality) {
- if (dimensionality > 0) {
- return new VectorFieldTypeInformation<V>(factory, dimensionality);
- }
- if (dimensionality == DIMENSIONALITY_VARIABLE) {
- return new SimpleTypeInformation<V>(factory.getRestrictionClass(), factory.getDefaultSerializer());
+ protected SimpleTypeInformation<V> getTypeInformation(int mindim, int maxdim) {
+ if (mindim == maxdim) {
+ return new VectorFieldTypeInformation<>(factory, mindim);
+ } else if (mindim < maxdim) {
+ return new VectorTypeInformation<>(factory.getRestrictionClass(), factory.getDefaultSerializer(), mindim, maxdim);
}
throw new AbortException("No vectors were read from the input file - cannot determine vector data type.");
}
@@ -196,7 +197,7 @@ public class TermFrequencyParser<V extends SparseNumberVector<?>> extends Number
@Override
protected void getFactory(Parameterization config) {
- ObjectParameter<SparseNumberVector.Factory<V, ?>> factoryP = new ObjectParameter<SparseNumberVector.Factory<V, ?>>(VECTOR_TYPE_ID, SparseNumberVector.Factory.class, SparseFloatVector.Factory.class);
+ ObjectParameter<SparseNumberVector.Factory<V, ?>> factoryP = new ObjectParameter<>(VECTOR_TYPE_ID, SparseNumberVector.Factory.class, SparseFloatVector.Factory.class);
if (config.grab(factoryP)) {
factory = factoryP.instantiateClass(config);
}
@@ -204,7 +205,7 @@ public class TermFrequencyParser<V extends SparseNumberVector<?>> extends Number
@Override
protected TermFrequencyParser<V> makeInstance() {
- return new TermFrequencyParser<V>(normalize, colSep, quoteChar, labelIndices, (SparseNumberVector.Factory<V, ?>) factory);
+ return new TermFrequencyParser<>(normalize, colSep, quoteChar, comment, labelIndices, (SparseNumberVector.Factory<V, ?>) factory);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/parser/package-info.java b/src/de/lmu/ifi/dbs/elki/datasource/parser/package-info.java
index 58ae9a77..c21ab31f 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/parser/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/parser/package-info.java
@@ -42,7 +42,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/DistanceUtil.java b/src/de/lmu/ifi/dbs/elki/distance/DistanceUtil.java
index eaa6c96c..8c1b2035 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/DistanceUtil.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/DistanceUtil.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractDBIDDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractDBIDDistanceFunction.java
index 9216c4ac..84fa0fbe 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractDBIDDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractDBIDDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -37,6 +37,8 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
*
* @author Arthur Zimek
*
+ * @apiviz.excludeSubtypes
+ *
* @param <D> the type of Distance used
*/
public abstract class AbstractDBIDDistanceFunction<D extends Distance<D>> implements DBIDDistanceFunction<D> {
@@ -73,6 +75,6 @@ public abstract class AbstractDBIDDistanceFunction<D extends Distance<D>> implem
@SuppressWarnings("unchecked")
@Override
final public <O extends DBID> DistanceQuery<O, D> instantiate(Relation<O> database) {
- return (DistanceQuery<O, D>) new DBIDDistanceQuery<D>((Relation<DBID>) database, this);
+ return (DistanceQuery<O, D>) new DBIDDistanceQuery<>((Relation<DBID>) database, this);
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractDatabaseDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractDatabaseDistanceFunction.java
index 845ea0ea..3bad6528 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractDatabaseDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractDatabaseDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -33,6 +33,7 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
* @author Elke Achtert
*
* @apiviz.has AbstractDatabaseDistanceFunction.Instance
+ * @apiviz.excludeSubtypes
*
* @param <O> the type of DatabaseObject to compute the distances in between
* @param <D> the type of Distance used
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractIndexBasedDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractIndexBasedDistanceFunction.java
index 48947692..618a238d 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractIndexBasedDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractIndexBasedDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -40,6 +40,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
*
* @apiviz.has AbstractIndexBasedDistanceFunction.Instance
* @apiviz.composedOf IndexFactory
+ * @apiviz.excludeSubtypes
*
* @param <O> the type of object to compute the distances in between
* @param <I> the type of Index used
@@ -147,7 +148,7 @@ public abstract class AbstractIndexBasedDistanceFunction<O, I extends Index, D e
* @param defaultClass Default value
*/
public void configIndexFactory(Parameterization config, Class<?> restriction, Class<?> defaultClass) {
- ObjectParameter<F> param = new ObjectParameter<F>(INDEX_ID, restriction, defaultClass);
+ ObjectParameter<F> param = new ObjectParameter<>(INDEX_ID, restriction, defaultClass);
if(config.grab(param)) {
factory = param.instantiateClass(config);
}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractPrimitiveDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractPrimitiveDistanceFunction.java
index 1c94bc28..7aefd19c 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractPrimitiveDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractPrimitiveDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -33,6 +33,8 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
*
* @author Arthur Zimek
*
+ * @apiviz.excludeSubtypes
+ *
* @param <O> the type of objects to compute the distances in between
* @param <D> the type of Distance used
*/
@@ -70,6 +72,6 @@ public abstract class AbstractPrimitiveDistanceFunction<O, D extends Distance<D>
*/
@Override
public <T extends O> DistanceQuery<T, D> instantiate(Relation<T> relation) {
- return new PrimitiveDistanceQuery<T, D>(relation, this);
+ return new PrimitiveDistanceQuery<>(relation, this);
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractSpatialDoubleDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractSpatialDoubleDistanceFunction.java
new file mode 100644
index 00000000..ef1b28b9
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractSpatialDoubleDistanceFunction.java
@@ -0,0 +1,52 @@
+package de.lmu.ifi.dbs.elki.distance.distancefunction;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.database.query.distance.SpatialPrimitiveDistanceQuery;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+
+/**
+ * Abstract base class for typical distance functions that allow
+ * rectangle-to-rectangle lower bounds. These distances can then be used with
+ * R*-trees for acceleration.
+ *
+ * This class is largely a convenience class, to make implementing this type of
+ * distance functions easier.
+ *
+ * @author Erich Schubert
+ */
+public abstract class AbstractSpatialDoubleDistanceFunction extends AbstractVectorDoubleDistanceFunction implements SpatialPrimitiveDoubleDistanceFunction<NumberVector<?>> {
+ @Override
+ final public DoubleDistance minDist(SpatialComparable mbr1, SpatialComparable mbr2) {
+ return new DoubleDistance(doubleMinDist(mbr1, mbr2));
+ }
+
+ @Override
+ public <T extends NumberVector<?>> SpatialPrimitiveDistanceQuery<T, DoubleDistance> instantiate(Relation<T> relation) {
+ return new SpatialPrimitiveDistanceQuery<>(relation, this);
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractSpatialDoubleDistanceNorm.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractSpatialDoubleDistanceNorm.java
new file mode 100644
index 00000000..e350f880
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractSpatialDoubleDistanceNorm.java
@@ -0,0 +1,54 @@
+package de.lmu.ifi.dbs.elki.distance.distancefunction;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.database.query.distance.SpatialPrimitiveDistanceQuery;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+
+/**
+ * Abstract base class for typical distance functions that allow
+ * rectangle-to-rectangle lower bounds. These distances can then be used with
+ * R*-trees for acceleration.
+ *
+ * This class is largely a convenience class, to make implementing this type of
+ * distance functions easier.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.landmark
+ */
+public abstract class AbstractSpatialDoubleDistanceNorm extends AbstractVectorDoubleDistanceNorm implements SpatialPrimitiveDoubleDistanceFunction<NumberVector<?>> {
+ @Override
+ final public DoubleDistance minDist(SpatialComparable mbr1, SpatialComparable mbr2) {
+ return new DoubleDistance(doubleMinDist(mbr1, mbr2));
+ }
+
+ @Override
+ public <T extends NumberVector<?>> SpatialPrimitiveDistanceQuery<T, DoubleDistance> instantiate(Relation<T> relation) {
+ return new SpatialPrimitiveDistanceQuery<>(relation, this);
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractVectorDoubleDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractVectorDoubleDistanceFunction.java
index 24288ec1..ea178bbb 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractVectorDoubleDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractVectorDoubleDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,6 +24,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
*/
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.TypeUtil;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
@@ -35,6 +36,7 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
* @author Erich Schubert
*
* @apiviz.landmark
+ * @apiviz.excludeSubtypes
* @apiviz.uses NumberVector
* @apiviz.has DoubleDistance
*/
@@ -60,4 +62,41 @@ public abstract class AbstractVectorDoubleDistanceFunction extends AbstractPrimi
public DoubleDistance getDistanceFactory() {
return DoubleDistance.FACTORY;
}
-} \ No newline at end of file
+
+ /**
+ * Get the common dimensionality of the two objects. Throw an
+ * {@link IllegalArgumentException} otherwise.
+ *
+ * @param o1 First vector / MBR
+ * @param o2 Second vector / MBR
+ * @return Common dimensionality
+ * @throws IllegalArgumentException when dimensionalities are not the same.
+ */
+ public static final int dimensionality(SpatialComparable o1, SpatialComparable o2) {
+ final int dim1 = o1.getDimensionality();
+ final int dim2 = o2.getDimensionality();
+ if (dim1 != dim2) {
+ throw new IllegalArgumentException("Objects do not have the same dimensionality.");
+ }
+ return dim1;
+ }
+
+ /**
+ * Get the common dimensionality of the two objects. Throw an
+ * {@link IllegalArgumentException} otherwise.
+ *
+ * @param o1 First vector / MBR
+ * @param o2 Second vector / MBR
+ * @param expect Expected dimensionality
+ * @return Common dimensionality
+ * @throws IllegalArgumentException when dimensionalities are not the same.
+ */
+ public static final int dimensionality(SpatialComparable o1, SpatialComparable o2, int expect) {
+ final int dim1 = o1.getDimensionality();
+ final int dim2 = o2.getDimensionality();
+ if (dim1 != dim2 || dim1 != expect) {
+ throw new IllegalArgumentException("Objects do not have the expected dimensionality of " + expect);
+ }
+ return expect;
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractVectorDoubleDistanceNorm.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractVectorDoubleDistanceNorm.java
index 16d4160c..7555bb3a 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractVectorDoubleDistanceNorm.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractVectorDoubleDistanceNorm.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -31,6 +31,8 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
* norms.
*
* @author Erich Schubert
+ *
+ * @apiviz.landmark
*/
public abstract class AbstractVectorDoubleDistanceNorm extends AbstractVectorDoubleDistanceFunction implements DoubleNorm<NumberVector<?>> {
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/ArcCosineDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/ArcCosineDistanceFunction.java
index 344bb3ca..c95038cc 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/ArcCosineDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/ArcCosineDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,10 +28,7 @@ import de.lmu.ifi.dbs.elki.data.VectorUtil;
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.TypeUtil;
-import de.lmu.ifi.dbs.elki.database.query.distance.SpatialDistanceQuery;
-import de.lmu.ifi.dbs.elki.database.query.distance.SpatialPrimitiveDistanceQuery;
-import de.lmu.ifi.dbs.elki.database.relation.Relation;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
/**
@@ -42,7 +39,8 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
*
* @author Arthur Zimek
*/
-public class ArcCosineDistanceFunction extends AbstractVectorDoubleDistanceFunction implements SpatialPrimitiveDoubleDistanceFunction<NumberVector<?>> {
+@Alias({ "arccos" })
+public class ArcCosineDistanceFunction extends AbstractSpatialDoubleDistanceFunction {
/**
* Static instance
*/
@@ -71,7 +69,7 @@ public class ArcCosineDistanceFunction extends AbstractVectorDoubleDistanceFunct
@Override
public double doubleDistance(NumberVector<?> v1, NumberVector<?> v2) {
double d = Math.acos(VectorUtil.cosAngle(v1, v2));
- if(d < 0) {
+ if (d < 0) {
d = 0;
}
return d;
@@ -80,39 +78,29 @@ public class ArcCosineDistanceFunction extends AbstractVectorDoubleDistanceFunct
@Override
public double doubleMinDist(SpatialComparable mbr1, SpatialComparable mbr2) {
double d = Math.acos(VectorUtil.minCosAngle(mbr1, mbr2));
- if(d < 0) {
+ if (d < 0) {
d = 0;
}
return d;
}
@Override
- public DoubleDistance minDist(SpatialComparable mbr1, SpatialComparable mbr2) {
- return new DoubleDistance(doubleMinDist(mbr1, mbr2));
- }
-
- @Override
public String toString() {
return "ArcCosineDistance";
}
@Override
public boolean equals(Object obj) {
- if(obj == null) {
+ if (obj == null) {
return false;
}
- if(obj == this) {
+ if (obj == this) {
return true;
}
return this.getClass().equals(obj.getClass());
}
@Override
- public <T extends NumberVector<?>> SpatialDistanceQuery<T, DoubleDistance> instantiate(Relation<T> relation) {
- return new SpatialPrimitiveDistanceQuery<T, DoubleDistance>(relation, this);
- }
-
- @Override
public SimpleTypeInformation<? super NumberVector<?>> getInputTypeRestriction() {
return TypeUtil.NUMBER_VECTOR_VARIABLE_LENGTH;
}
@@ -130,4 +118,4 @@ public class ArcCosineDistanceFunction extends AbstractVectorDoubleDistanceFunct
return ArcCosineDistanceFunction.STATIC;
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/BrayCurtisDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/BrayCurtisDistanceFunction.java
new file mode 100644
index 00000000..20a989fc
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/BrayCurtisDistanceFunction.java
@@ -0,0 +1,149 @@
+package de.lmu.ifi.dbs.elki.distance.distancefunction;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Bray-Curtis distance function / Sørensen–Dice coefficient for continuous
+ * spaces.
+ *
+ * Reference:
+ * <p>
+ * J. R. Bray and J. T. Curtis<br />
+ * An ordination of the upland forest communities of southern Wisconsin<br />
+ * Ecological monographs 27.4
+ * </p>
+ * Also:
+ * <p>
+ * T. Sørensen<br />
+ * A method of establishing groups of equal amplitude in plant sociology based
+ * on similarity of species and its application to analyses of the vegetation on
+ * Danish commons<br />
+ * Kongelige Danske Videnskabernes Selskab 5 (4)
+ * </p>
+ * and:
+ * <p>
+ * L. R. Dice<br />
+ * Measures of the Amount of Ecologic Association Between Species<br />
+ * Ecology 26 (3)
+ * </p>
+ *
+ *
+ * Note: we modified the usual definition of Bray-Curtis for use with negative
+ * values. In essence, this function is defined as:
+ *
+ * ManhattanDistance(v1, v2) / (ManhattanNorm(v1) + ManhattanNorm(v2))
+ *
+ * This obviously limits the usefulness of this distance function for cases
+ * where this kind of normalization is desired. In particular in low dimensional
+ * data it should be used with care.
+ *
+ * TODO: add a version optimized for sparse vectors / binary data.
+ *
+ * @author Erich Schubert
+ */
+@Alias({ "bray-curtis", "braycurtis", "sorensen", "dice", "sorensen-dice" })
+@Reference(authors = "J. R. Bray and J. T. Curtis", title = "An ordination of the upland forest communities of southern Wisconsin", booktitle = "Ecological monographs 27.4", url = "http://dx.doi.org/10.2307/1942268")
+public class BrayCurtisDistanceFunction extends AbstractSpatialDoubleDistanceFunction {
+ /**
+ * Static instance.
+ */
+ public static final BrayCurtisDistanceFunction STATIC_CONTINUOUS = new BrayCurtisDistanceFunction();
+
+ /**
+ * Constructor.
+ *
+ * @deprecated Use {@link #STATIC_CONTINUOUS} instance instead.
+ */
+ @Deprecated
+ public BrayCurtisDistanceFunction() {
+ super();
+ }
+
+ /**
+ * Dummy method, just to attach a second reference.
+ */
+ @Reference(authors = "T. Sørensen", title = "A method of establishing groups of equal amplitude in plant sociology based on similarity of species and its application to analyses of the vegetation on Danish commons", booktitle = "Kongelige Danske Videnskabernes Selskab 5 (4)")
+ static void secondReference() {
+ // Empty, just to attach a second reference
+ };
+
+ /**
+ * Dummy method, just to attach a third reference.
+ */
+ @Reference(authors = "L. R. Dice", title = "Measures of the Amount of Ecologic Association Between Species", booktitle = "Ecology 26 (3)")
+ static void thirdReference() {
+ // Empty, just to attach a second reference
+ };
+
+ @Override
+ public double doubleDistance(NumberVector<?> v1, NumberVector<?> v2) {
+ final int dim = dimensionality(v1, v2);
+ double sumdiff = 0., sumsum = 0.;
+ for (int d = 0; d < dim; d++) {
+ double xd = v1.doubleValue(d), yd = v2.doubleValue(d);
+ sumdiff += Math.abs(xd - yd);
+ sumsum += Math.abs(xd) + Math.abs(yd);
+ }
+ return sumdiff / sumsum;
+ }
+
+ @Override
+ public double doubleMinDist(SpatialComparable mbr1, SpatialComparable mbr2) {
+ final int dim = dimensionality(mbr1, mbr2);
+ double sumdiff = 0., sumsum = 0.;
+ for (int d = 0; d < dim; d++) {
+ final double min1 = mbr1.getMin(d), max1 = mbr1.getMax(d);
+ final double min2 = mbr2.getMin(d), max2 = mbr2.getMax(d);
+ if (max1 < min2) {
+ sumdiff += min2 - max1;
+ } else if (min1 > max2) {
+ sumdiff += min1 - max2;
+ } else {
+ // Minimum difference is 0
+ }
+ sumsum += Math.max(-min1, max1) + Math.max(-min2, max2);
+ }
+ return sumdiff / sumsum;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected BrayCurtisDistanceFunction makeInstance() {
+ return BrayCurtisDistanceFunction.STATIC_CONTINUOUS;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/CanberraDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/CanberraDistanceFunction.java
index f6db7439..97ef19ce 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/CanberraDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/CanberraDistanceFunction.java
@@ -24,10 +24,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
*/
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
-import de.lmu.ifi.dbs.elki.database.query.distance.SpatialDistanceQuery;
-import de.lmu.ifi.dbs.elki.database.query.distance.SpatialPrimitiveDistanceQuery;
-import de.lmu.ifi.dbs.elki.database.relation.Relation;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
@@ -45,7 +42,8 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
* @author Erich Schubert
*/
@Reference(authors = "G. N. Lance, W. T. Williams", title = "Computer programs for hierarchical polythetic classification (similarity analysis).", booktitle = "Computer Journal, Volume 9, Issue 1", url = "http://comjnl.oxfordjournals.org/content/9/1/60.short")
-public class CanberraDistanceFunction extends AbstractVectorDoubleDistanceFunction implements SpatialPrimitiveDoubleDistanceFunction<NumberVector<?>> {
+@Alias({ "canberra" })
+public class CanberraDistanceFunction extends AbstractSpatialDoubleDistanceFunction {
/**
* Static instance. Use this!
*/
@@ -59,56 +57,46 @@ public class CanberraDistanceFunction extends AbstractVectorDoubleDistanceFuncti
}
@Override
- public double doubleDistance(NumberVector<?> o1, NumberVector<?> o2) {
- final int dim = o1.getDimensionality();
- double sum = 0.0;
- for(int i = 0; i < dim; i++) {
- double v1 = o1.doubleValue(i);
- double v2 = o2.doubleValue(i);
- final double div = Math.abs(v1) + Math.abs(v2);
+ public double doubleDistance(NumberVector<?> v1, NumberVector<?> v2) {
+ final int dim = dimensionality(v1, v2);
+ double agg = 0.;
+ for (int d = 0; d < dim; d++) {
+ final double xd = v1.doubleValue(d), yd = v2.doubleValue(d);
+ final double div = Math.abs(xd) + Math.abs(yd);
if (div > 0) {
- sum += Math.abs(v1 - v2) / div;
+ agg += Math.abs(xd - yd) / div;
}
}
- return sum;
+ return agg;
}
@Override
public double doubleMinDist(SpatialComparable mbr1, SpatialComparable mbr2) {
- final int dim = mbr1.getDimensionality();
- double sum = 0.0;
- for(int d = 0; d < dim; d++) {
- final double m1, m2;
- if(mbr1.getMax(d) < mbr2.getMin(d)) {
- m1 = mbr2.getMin(d);
- m2 = mbr1.getMax(d);
- }
- else if(mbr1.getMin(d) > mbr2.getMax(d)) {
- m1 = mbr1.getMin(d);
- m2 = mbr2.getMax(d);
- }
- else { // The mbrs intersect!
+ final int dim = dimensionality(mbr1, mbr2);
+ 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;
}
- final double manhattanI = m1 - m2;
final double a1 = Math.max(-mbr1.getMin(d), mbr1.getMax(d));
final double a2 = Math.max(-mbr2.getMin(d), mbr2.getMax(d));
final double div = a1 + a2;
- if (div > 0) {
- sum += manhattanI / div;
- }
+ // Cannot be 0, because then diff = 0 and we continued above.
+ agg += diff / div;
}
- return sum;
- }
-
- @Override
- public DoubleDistance minDist(SpatialComparable mbr1, SpatialComparable mbr2) {
- return new DoubleDistance(doubleMinDist(mbr1, mbr2));
+ return agg;
}
@Override
- public <T extends NumberVector<?>> SpatialDistanceQuery<T, DoubleDistance> instantiate(Relation<T> relation) {
- return new SpatialPrimitiveDistanceQuery<T, DoubleDistance>(relation, this);
+ public boolean isMetric() {
+ // As this is also reffered to as "canberra metric", it is probably a metric
+ // But *maybe* only for positive numbers only?
+ return true;
}
/**
@@ -124,4 +112,4 @@ public class CanberraDistanceFunction extends AbstractVectorDoubleDistanceFuncti
return CanberraDistanceFunction.STATIC;
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/ClarkDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/ClarkDistanceFunction.java
new file mode 100644
index 00000000..221a7db1
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/ClarkDistanceFunction.java
@@ -0,0 +1,112 @@
+package de.lmu.ifi.dbs.elki.distance.distancefunction;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Clark distance function for vector spaces.
+ *
+ * Reference:
+ * <p>
+ * M.-M. Deza and E. Deza<br />
+ * Dictionary of distances
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@Reference(authors = "M.-M. Deza and E. Deza", title = "Dictionary of distances", booktitle = "Dictionary of distances")
+public class ClarkDistanceFunction extends AbstractSpatialDoubleDistanceFunction {
+ /**
+ * Static instance.
+ */
+ public static final ClarkDistanceFunction STATIC = new ClarkDistanceFunction();
+
+ /**
+ * Constructor.
+ *
+ * @deprecated Use {@link #STATIC} instance instead.
+ */
+ @Deprecated
+ public ClarkDistanceFunction() {
+ super();
+ }
+
+ @Override
+ public double doubleDistance(NumberVector<?> v1, NumberVector<?> v2) {
+ final int dim = dimensionality(v1, v2);
+ double agg = 0.;
+ for (int d = 0; d < dim; d++) {
+ final double xd = v1.doubleValue(d), yd = v2.doubleValue(d);
+ final double div = Math.abs(xd) + Math.abs(yd);
+ if (div > 0.) {
+ final double v = (xd - yd) / div;
+ agg += v * v;
+ }
+ }
+ return Math.sqrt(agg / dim);
+ }
+
+ @Override
+ public double doubleMinDist(SpatialComparable mbr1, SpatialComparable mbr2) {
+ final int dim = dimensionality(mbr1, mbr2);
+ double agg = 0.;
+ for (int d = 0; d < dim; d++) {
+ final double min1 = mbr1.getMin(d), max1 = mbr1.getMax(d);
+ final double min2 = mbr2.getMin(d), max2 = mbr2.getMax(d);
+ final double diff;
+ if (max1 < min2) {
+ diff = min2 - max1;
+ } else if (min1 > max2) {
+ diff = min1 - max2;
+ } else {
+ // Minimum difference is 0
+ continue;
+ }
+ final double absmax1 = Math.max(-min1, max1);
+ final double absmax2 = Math.max(-min2, max2);
+ // Division by 0 cannot happen: then diff = 0 and we continued above!
+ final double v = diff / (absmax1 + absmax2);
+ agg += v * v;
+ }
+ return Math.sqrt(agg / dim);
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected ClarkDistanceFunction makeInstance() {
+ return ClarkDistanceFunction.STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/CosineDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/CosineDistanceFunction.java
index f333f6e2..bc86b6cf 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/CosineDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/CosineDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,10 +28,7 @@ import de.lmu.ifi.dbs.elki.data.VectorUtil;
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.TypeUtil;
-import de.lmu.ifi.dbs.elki.database.query.distance.SpatialDistanceQuery;
-import de.lmu.ifi.dbs.elki.database.query.distance.SpatialPrimitiveDistanceQuery;
-import de.lmu.ifi.dbs.elki.database.relation.Relation;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
/**
@@ -42,7 +39,8 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
*
* @author Arthur Zimek
*/
-public class CosineDistanceFunction extends AbstractVectorDoubleDistanceFunction implements SpatialPrimitiveDoubleDistanceFunction<NumberVector<?>> {
+@Alias({ "cosine" })
+public class CosineDistanceFunction extends AbstractSpatialDoubleDistanceFunction {
/**
* Static instance
*/
@@ -71,7 +69,7 @@ public class CosineDistanceFunction extends AbstractVectorDoubleDistanceFunction
@Override
public double doubleDistance(NumberVector<?> v1, NumberVector<?> v2) {
double d = 1 - VectorUtil.cosAngle(v1, v2);
- if(d < 0) {
+ if (d < 0) {
d = 0;
}
return d;
@@ -80,39 +78,29 @@ public class CosineDistanceFunction extends AbstractVectorDoubleDistanceFunction
@Override
public double doubleMinDist(SpatialComparable mbr1, SpatialComparable mbr2) {
double d = 1 - VectorUtil.minCosAngle(mbr1, mbr2);
- if(d < 0) {
+ if (d < 0) {
d = 0;
}
return d;
}
@Override
- public DoubleDistance minDist(SpatialComparable mbr1, SpatialComparable mbr2) {
- return new DoubleDistance(doubleMinDist(mbr1, mbr2));
- }
-
- @Override
public String toString() {
return "CosineDistance";
}
@Override
public boolean equals(Object obj) {
- if(obj == null) {
+ if (obj == null) {
return false;
}
- if(obj == this) {
+ if (obj == this) {
return true;
}
return this.getClass().equals(obj.getClass());
}
@Override
- public <T extends NumberVector<?>> SpatialDistanceQuery<T, DoubleDistance> instantiate(Relation<T> relation) {
- return new SpatialPrimitiveDistanceQuery<T, DoubleDistance>(relation, this);
- }
-
- @Override
public SimpleTypeInformation<? super NumberVector<?>> getInputTypeRestriction() {
return TypeUtil.NUMBER_VECTOR_VARIABLE_LENGTH;
}
@@ -130,4 +118,4 @@ public class CosineDistanceFunction extends AbstractVectorDoubleDistanceFunction
return CosineDistanceFunction.STATIC;
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/DBIDDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/DBIDDistanceFunction.java
index 857b96e1..aea91f40 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/DBIDDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/DBIDDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/DistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/DistanceFunction.java
index 0d38b418..ae5d2780 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/DistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/DistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/DoubleNorm.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/DoubleNorm.java
index 3d7ed70f..6ba5246a 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/DoubleNorm.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/DoubleNorm.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/EuclideanDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/EuclideanDistanceFunction.java
deleted file mode 100644
index 6bb910a4..00000000
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/EuclideanDistanceFunction.java
+++ /dev/null
@@ -1,179 +0,0 @@
-package de.lmu.ifi.dbs.elki.distance.distancefunction;
-
-/*
- This file is part of ELKI:
- Environment for Developing KDD-Applications Supported by Index-Structures
-
- Copyright (C) 2012
- Ludwig-Maximilians-Universität München
- Lehr- und Forschungseinheit für Datenbanksysteme
- ELKI Development Team
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-import de.lmu.ifi.dbs.elki.data.NumberVector;
-import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
-
-/**
- * Provides the Euclidean distance for FeatureVectors.
- *
- * @author Arthur Zimek
- */
-public class EuclideanDistanceFunction extends LPNormDistanceFunction implements SpatialPrimitiveDoubleDistanceFunction<NumberVector<?>> {
- /**
- * Static instance. Use this!
- */
- public static final EuclideanDistanceFunction STATIC = new EuclideanDistanceFunction();
-
- /**
- * Provides a Euclidean distance function that can compute the Euclidean
- * distance (that is a DoubleDistance) for FeatureVectors.
- *
- * @deprecated Use static instance!
- */
- @Deprecated
- public EuclideanDistanceFunction() {
- super(2.0);
- }
-
- @Override
- public double doubleDistance(NumberVector<?> v1, NumberVector<?> v2) {
- final int dim1 = v1.getDimensionality();
- if(dim1 != v2.getDimensionality()) {
- throw new IllegalArgumentException("Different dimensionality of FeatureVectors" + "\n first argument: " + v1.toString() + "\n second argument: " + v2.toString() + "\n" + v1.getDimensionality() + "!=" + v2.getDimensionality());
- }
- double sqrDist = 0;
- for(int i = 0; i < dim1; i++) {
- final double delta = v1.doubleValue(i) - v2.doubleValue(i);
- sqrDist += delta * delta;
- }
- return Math.sqrt(sqrDist);
- }
-
- @Override
- public double doubleNorm(NumberVector<?> v) {
- final int dim = v.getDimensionality();
- double sqrDist = 0;
- for(int i = 0; i < dim; i++) {
- final double delta = v.doubleValue(i);
- sqrDist += delta * delta;
- }
- return Math.sqrt(sqrDist);
- }
-
- protected double doubleMinDistObject(SpatialComparable mbr, NumberVector<?> v) {
- final int dim = mbr.getDimensionality();
- if(dim != v.getDimensionality()) {
- throw new IllegalArgumentException("Different dimensionality of objects\n " + "first argument: " + mbr.toString() + "\n " + "second argument: " + v.toString() + "\n" + dim + "!=" + v.getDimensionality());
- }
-
- double sqrDist = 0;
- for(int d = 0; d < dim; d++) {
- double value = v.doubleValue(d);
- double r;
- if(value < mbr.getMin(d)) {
- r = mbr.getMin(d);
- }
- else if(value > mbr.getMax(d)) {
- r = mbr.getMax(d);
- }
- else {
- r = value;
- }
-
- final double manhattanI = value - r;
- sqrDist += manhattanI * manhattanI;
- }
- return Math.sqrt(sqrDist);
- }
-
- @Override
- public double doubleMinDist(SpatialComparable mbr1, SpatialComparable mbr2) {
- // Some optimizations for simpler cases.
- if(mbr1 instanceof NumberVector) {
- if(mbr2 instanceof NumberVector) {
- return doubleDistance((NumberVector<?>) mbr1, (NumberVector<?>) mbr2);
- }
- else {
- return doubleMinDistObject(mbr2, (NumberVector<?>) mbr1);
- }
- }
- else if(mbr2 instanceof NumberVector) {
- return doubleMinDistObject(mbr1, (NumberVector<?>) mbr2);
- }
- final int dim1 = mbr1.getDimensionality();
- if(dim1 != mbr2.getDimensionality()) {
- throw new IllegalArgumentException("Different dimensionality of objects\n " + "first argument: " + mbr1.toString() + "\n " + "second argument: " + mbr2.toString());
- }
-
- double sqrDist = 0;
- for(int d = 0; d < dim1; d++) {
- final double m1, m2;
- if(mbr1.getMax(d) < mbr2.getMin(d)) {
- m1 = mbr2.getMin(d);
- m2 = mbr1.getMax(d);
- }
- else if(mbr1.getMin(d) > mbr2.getMax(d)) {
- m1 = mbr1.getMin(d);
- m2 = mbr2.getMax(d);
- }
- else { // The mbrs intersect!
- continue;
- }
- final double manhattanI = m1 - m2;
- sqrDist += manhattanI * manhattanI;
- }
- return Math.sqrt(sqrDist);
- }
-
- @Override
- public boolean isMetric() {
- return true;
- }
-
- @Override
- public String toString() {
- return "EuclideanDistance";
- }
-
- @Override
- public boolean equals(Object obj) {
- if(obj == null) {
- return false;
- }
- if(obj == this) {
- return true;
- }
- if(this.getClass().equals(obj.getClass())) {
- return true;
- }
- return super.equals(obj);
- }
-
- /**
- * Parameterization class.
- *
- * @author Erich Schubert
- *
- * @apiviz.exclude
- */
- public static class Parameterizer extends AbstractParameterizer {
- @Override
- protected EuclideanDistanceFunction makeInstance() {
- return EuclideanDistanceFunction.STATIC;
- }
- }
-} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/FilteredLocalPCABasedDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/FilteredLocalPCABasedDistanceFunction.java
index 2cf11a54..da2bb2ec 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/FilteredLocalPCABasedDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/FilteredLocalPCABasedDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/IndexBasedDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/IndexBasedDistanceFunction.java
index ba7d87d7..b8f02e94 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/IndexBasedDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/IndexBasedDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/Kulczynski1DistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/Kulczynski1DistanceFunction.java
new file mode 100644
index 00000000..59b9a29d
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/Kulczynski1DistanceFunction.java
@@ -0,0 +1,103 @@
+package de.lmu.ifi.dbs.elki.distance.distancefunction;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Kulczynski similarity 1, in distance form.
+ *
+ * Reference:
+ * <p>
+ * M.-M. Deza and E. Deza<br />
+ * Dictionary of distances
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@Reference(authors = "M.-M. Deza and E. Deza", title = "Dictionary of distances", booktitle = "Dictionary of distances")
+public class Kulczynski1DistanceFunction extends AbstractSpatialDoubleDistanceFunction {
+ /**
+ * Static instance.
+ */
+ public static final Kulczynski1DistanceFunction STATIC = new Kulczynski1DistanceFunction();
+
+ /**
+ * Constructor.
+ *
+ * @deprecated Use {@link #STATIC} instance instead.
+ */
+ @Deprecated
+ public Kulczynski1DistanceFunction() {
+ super();
+ }
+
+ @Override
+ public double doubleDistance(NumberVector<?> v1, NumberVector<?> v2) {
+ final int dim = dimensionality(v1, v2);
+ double sumdiff = 0., summin = 0.;
+ for (int d = 0; d < dim; d++) {
+ final double xd = v1.doubleValue(d), yd = v2.doubleValue(d);
+ sumdiff += Math.abs(xd - yd);
+ summin += Math.min(xd, yd);
+ }
+ return sumdiff / summin;
+ }
+
+ @Override
+ public double doubleMinDist(SpatialComparable mbr1, SpatialComparable mbr2) {
+ final int dim = dimensionality(mbr1, mbr2);
+ double sumdiff = 0., summin = 0.;
+ for (int d = 0; d < dim; d++) {
+ final double min1 = mbr1.getMin(d), max1 = mbr1.getMax(d);
+ final double min2 = mbr2.getMin(d), max2 = mbr2.getMax(d);
+ if (max1 < min2) {
+ sumdiff += min2 - max1;
+ } else if (min1 > max2) {
+ sumdiff += min1 - max2;
+ } else {
+ // Minimum difference is 0
+ }
+ summin += Math.min(min1, min2);
+ }
+ return sumdiff / summin;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected Kulczynski1DistanceFunction makeInstance() {
+ return Kulczynski1DistanceFunction.STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/LocallyWeightedDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/LocallyWeightedDistanceFunction.java
index 2ff0252c..024240b6 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/LocallyWeightedDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/LocallyWeightedDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -78,7 +78,7 @@ public class LocallyWeightedDistanceFunction<V extends NumberVector<?>> extends
// Generics (AFAICT)
@SuppressWarnings("unchecked")
LocalProjectionIndex<T, ?> indexinst = (LocalProjectionIndex<T, ?>) indexFactory.instantiate((Relation<V>) database);
- return new Instance<T>(database, indexinst, this);
+ return new Instance<>(database, indexinst, this);
}
@Override
@@ -254,7 +254,7 @@ public class LocallyWeightedDistanceFunction<V extends NumberVector<?>> extends
@Override
protected LocallyWeightedDistanceFunction<V> makeInstance() {
- return new LocallyWeightedDistanceFunction<V>(factory);
+ return new LocallyWeightedDistanceFunction<>(factory);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/LorentzianDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/LorentzianDistanceFunction.java
new file mode 100644
index 00000000..51140f36
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/LorentzianDistanceFunction.java
@@ -0,0 +1,115 @@
+package de.lmu.ifi.dbs.elki.distance.distancefunction;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Lorentzian distance function for vector spaces.
+ *
+ * Reference:
+ * <p>
+ * M.-M. Deza and E. Deza<br />
+ * Dictionary of distances
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@Reference(authors = "M.-M. Deza and E. Deza", title = "Dictionary of distances", booktitle = "Dictionary of distances")
+public class LorentzianDistanceFunction extends AbstractSpatialDoubleDistanceNorm {
+ /**
+ * Static instance.
+ */
+ public static final LorentzianDistanceFunction STATIC = new LorentzianDistanceFunction();
+
+ /**
+ * Constructor.
+ *
+ * @deprecated Use {@link #STATIC} instance instead.
+ */
+ @Deprecated
+ public LorentzianDistanceFunction() {
+ super();
+ }
+
+ @Override
+ public double doubleDistance(NumberVector<?> v1, NumberVector<?> v2) {
+ final int dim = dimensionality(v1, v2);
+ double agg = 0.;
+ for (int d = 0; d < dim; d++) {
+ final double xd = v1.doubleValue(d), yd = v2.doubleValue(d);
+ agg += Math.log(1 + Math.abs(xd - yd));
+ }
+ return agg;
+ }
+
+ @Override
+ public double doubleNorm(NumberVector<?> v1) {
+ final int dim = v1.getDimensionality();
+ double agg = 0.;
+ for (int i = 0; i < dim; i++) {
+ final double xi = v1.doubleValue(i);
+ agg += Math.log(1. + Math.abs(xi));
+ }
+ return agg;
+ }
+
+ @Override
+ public double doubleMinDist(SpatialComparable mbr1, SpatialComparable mbr2) {
+ final int dim = dimensionality(mbr1, mbr2);
+ double agg = 0.;
+ for (int d = 0; d < dim; d++) {
+ final double min1 = mbr1.getMin(d), max1 = mbr1.getMax(d);
+ final double min2 = mbr2.getMin(d), max2 = mbr2.getMax(d);
+ final double diff;
+ if (max1 < min2) {
+ diff = min2 - max1;
+ } else if (min1 > max2) {
+ diff = min1 - max2;
+ } else {
+ // Minimum difference is 0
+ continue;
+ }
+ agg += Math.log(1. + diff);
+ }
+ return agg;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected LorentzianDistanceFunction makeInstance() {
+ return LorentzianDistanceFunction.STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/MinKDistance.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/MinKDistance.java
index 294b7e40..5e29ec51 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/MinKDistance.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/MinKDistance.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,13 +26,14 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
import de.lmu.ifi.dbs.elki.database.QueryUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery;
import de.lmu.ifi.dbs.elki.database.query.distance.AbstractDatabaseDistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.DistanceUtil;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
@@ -115,7 +116,7 @@ public class MinKDistance<O, D extends Distance<D>> extends AbstractDatabaseDist
@Override
public <T extends O> DistanceQuery<T, D> instantiate(Relation<T> relation) {
- return new Instance<T>(relation, k, parentDistance);
+ return new Instance<>(relation, k, parentDistance);
}
/**
@@ -157,7 +158,7 @@ public class MinKDistance<O, D extends Distance<D>> extends AbstractDatabaseDist
@Override
public D distance(DBIDRef id1, DBIDRef id2) {
- KNNResult<D> neighborhood = knnQuery.getKNNForDBID(id1, k);
+ KNNList<D> neighborhood = knnQuery.getKNNForDBID(id1, k);
D truedist = parentDistanceQuery.distance(id1, id2);
return computeReachdist(neighborhood, truedist);
}
@@ -176,7 +177,7 @@ public class MinKDistance<O, D extends Distance<D>> extends AbstractDatabaseDist
* @param truedist True distance
* @return Reachability distance
*/
- protected D computeReachdist(KNNResult<D> neighborhood, D truedist) {
+ protected D computeReachdist(KNNList<D> neighborhood, D truedist) {
// TODO: need to check neighborhood size?
// TODO: Do we need to check we actually got the object itself in the
// neighborhood?
@@ -243,7 +244,7 @@ public class MinKDistance<O, D extends Distance<D>> extends AbstractDatabaseDist
k = kP.getValue();
}
- final ObjectParameter<DistanceFunction<? super O, D>> parentDistanceP = new ObjectParameter<DistanceFunction<? super O, D>>(DISTANCE_FUNCTION_ID, DistanceFunction.class, EuclideanDistanceFunction.class);
+ final ObjectParameter<DistanceFunction<? super O, D>> parentDistanceP = new ObjectParameter<>(DISTANCE_FUNCTION_ID, DistanceFunction.class, EuclideanDistanceFunction.class);
if (config.grab(parentDistanceP)) {
parentDistance = parentDistanceP.instantiateClass(config);
}
@@ -251,7 +252,7 @@ public class MinKDistance<O, D extends Distance<D>> extends AbstractDatabaseDist
@Override
protected MinKDistance<O, D> makeInstance() {
- return new MinKDistance<O, D>(parentDistance, k + (objectIsInKNN ? 0 : 1));
+ return new MinKDistance<>(parentDistance, k + (objectIsInKNN ? 0 : 1));
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/Norm.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/Norm.java
index 98ef1f1d..ae6605f2 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/Norm.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/Norm.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/PrimitiveDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/PrimitiveDistanceFunction.java
index f8b62225..8d293e9a 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/PrimitiveDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/PrimitiveDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/PrimitiveDoubleDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/PrimitiveDoubleDistanceFunction.java
index e4d19702..321885b9 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/PrimitiveDoubleDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/PrimitiveDoubleDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/ProxyDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/ProxyDistanceFunction.java
index 48d49a0c..58dd512a 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/ProxyDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/ProxyDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -61,7 +61,7 @@ public class ProxyDistanceFunction<O, D extends Distance<D>> extends AbstractDBI
* @return Proxy object
*/
public static <O, D extends Distance<D>> ProxyDistanceFunction<O, D> proxy(DistanceQuery<O, D> inner) {
- return new ProxyDistanceFunction<O, D>(inner);
+ return new ProxyDistanceFunction<>(inner);
}
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/RandomStableDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/RandomStableDistanceFunction.java
index e57ae501..3d6d1128 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/RandomStableDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/RandomStableDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/SharedNearestNeighborJaccardDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/SharedNearestNeighborJaccardDistanceFunction.java
index 5ff9a433..29732783 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/SharedNearestNeighborJaccardDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/SharedNearestNeighborJaccardDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -61,7 +61,7 @@ public class SharedNearestNeighborJaccardDistanceFunction<O> extends AbstractInd
@Override
public <T extends O> Instance<T> instantiate(Relation<T> database) {
SharedNearestNeighborIndex<O> indexi = indexFactory.instantiate((Relation<O>) database);
- return (Instance<T>) new Instance<O>((Relation<O>) database, indexi, this);
+ return (Instance<T>) new Instance<>((Relation<O>) database, indexi, this);
}
/**
@@ -157,7 +157,7 @@ public class SharedNearestNeighborJaccardDistanceFunction<O> extends AbstractInd
@Override
protected SharedNearestNeighborJaccardDistanceFunction<O> makeInstance() {
- return new SharedNearestNeighborJaccardDistanceFunction<O>(factory);
+ return new SharedNearestNeighborJaccardDistanceFunction<>(factory);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/SpatialPrimitiveDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/SpatialPrimitiveDistanceFunction.java
index 27dd1219..0a2b7840 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/SpatialPrimitiveDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/SpatialPrimitiveDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/SpatialPrimitiveDoubleDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/SpatialPrimitiveDoubleDistanceFunction.java
index 9ae39089..25a996c6 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/SpatialPrimitiveDoubleDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/SpatialPrimitiveDoubleDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/SquaredEuclideanDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/SquaredEuclideanDistanceFunction.java
deleted file mode 100644
index ff17f388..00000000
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/SquaredEuclideanDistanceFunction.java
+++ /dev/null
@@ -1,196 +0,0 @@
-package de.lmu.ifi.dbs.elki.distance.distancefunction;
-
-/*
- This file is part of ELKI:
- Environment for Developing KDD-Applications Supported by Index-Structures
-
- Copyright (C) 2012
- Ludwig-Maximilians-Universität München
- Lehr- und Forschungseinheit für Datenbanksysteme
- ELKI Development Team
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-import de.lmu.ifi.dbs.elki.data.NumberVector;
-import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
-import de.lmu.ifi.dbs.elki.database.query.distance.SpatialPrimitiveDistanceQuery;
-import de.lmu.ifi.dbs.elki.database.relation.Relation;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
-
-/**
- * Provides the squared Euclidean distance for FeatureVectors. This results in
- * the same rankings, but saves computing the square root as often.
- *
- * @author Arthur Zimek
- */
-public class SquaredEuclideanDistanceFunction extends AbstractVectorDoubleDistanceNorm implements SpatialPrimitiveDoubleDistanceFunction<NumberVector<?>> {
- /**
- * Static instance. Use this!
- */
- public static final SquaredEuclideanDistanceFunction STATIC = new SquaredEuclideanDistanceFunction();
-
- /**
- * Provides a Euclidean distance function that can compute the Euclidean
- * distance (that is a DoubleDistance) for FeatureVectors.
- *
- * @deprecated Use static instance!
- */
- @Deprecated
- public SquaredEuclideanDistanceFunction() {
- super();
- }
-
- @Override
- public double doubleNorm(NumberVector<?> v) {
- final int dim = v.getDimensionality();
- double sum = 0;
- for(int i = 0; i < dim; i++) {
- final double val = v.doubleValue(i);
- sum += val * val;
- }
- return sum;
- }
-
- /**
- * Provides the squared Euclidean distance between the given two vectors.
- *
- * @return the squared Euclidean distance between the given two vectors as raw
- * double value
- */
- @Override
- public double doubleDistance(NumberVector<?> v1, NumberVector<?> v2) {
- final int dim1 = v1.getDimensionality();
- if(dim1 != v2.getDimensionality()) {
- throw new IllegalArgumentException("Different dimensionality of FeatureVectors" + "\n first argument: " + v1.toString() + "\n second argument: " + v2.toString() + "\n" + v1.getDimensionality() + "!=" + v2.getDimensionality());
- }
- double sqrDist = 0;
- for(int i = 0; i < dim1; i++) {
- final double delta = v1.doubleValue(i) - v2.doubleValue(i);
- sqrDist += delta * delta;
- }
- return sqrDist;
- }
-
- protected double doubleMinDistObject(SpatialComparable mbr, NumberVector<?> v) {
- final int dim = mbr.getDimensionality();
- if(dim != v.getDimensionality()) {
- throw new IllegalArgumentException("Different dimensionality of objects\n " + "first argument: " + mbr.toString() + "\n " + "second argument: " + v.toString() + "\n" + dim + "!=" + v.getDimensionality());
- }
-
- double sqrDist = 0;
- for(int d = 0; d < dim; d++) {
- double value = v.doubleValue(d);
- double r;
- if(value < mbr.getMin(d)) {
- r = mbr.getMin(d);
- }
- else if(value > mbr.getMax(d)) {
- r = mbr.getMax(d);
- }
- else {
- r = value;
- }
-
- final double manhattanI = value - r;
- sqrDist += manhattanI * manhattanI;
- }
- return sqrDist;
- }
-
- @Override
- public double doubleMinDist(SpatialComparable mbr1, SpatialComparable mbr2) {
- // Some optimizations for simpler cases.
- if(mbr1 instanceof NumberVector) {
- if(mbr2 instanceof NumberVector) {
- return doubleDistance((NumberVector<?>) mbr1, (NumberVector<?>) mbr2);
- }
- else {
- return doubleMinDistObject(mbr2, (NumberVector<?>) mbr1);
- }
- }
- else if(mbr2 instanceof NumberVector) {
- return doubleMinDistObject(mbr1, (NumberVector<?>) mbr2);
- }
- final int dim1 = mbr1.getDimensionality();
- if(dim1 != mbr2.getDimensionality()) {
- throw new IllegalArgumentException("Different dimensionality of objects\n " + "first argument: " + mbr1.toString() + "\n " + "second argument: " + mbr2.toString());
- }
-
- double sqrDist = 0;
- for(int d = 0; d < dim1; d++) {
- final double m1, m2;
- if(mbr1.getMax(d) < mbr2.getMin(d)) {
- m1 = mbr2.getMin(d);
- m2 = mbr1.getMax(d);
- }
- else if(mbr1.getMin(d) > mbr2.getMax(d)) {
- m1 = mbr1.getMin(d);
- m2 = mbr2.getMax(d);
- }
- else { // The mbrs intersect!
- continue;
- }
- final double manhattanI = m1 - m2;
- sqrDist += manhattanI * manhattanI;
- }
- return sqrDist;
- }
-
- @Override
- public DoubleDistance minDist(SpatialComparable mbr1, SpatialComparable mbr2) {
- return new DoubleDistance(doubleMinDist(mbr1, mbr2));
- }
-
- @Override
- public boolean isMetric() {
- return false;
- }
-
- @Override
- public <T extends NumberVector<?>> SpatialPrimitiveDistanceQuery<T, DoubleDistance> instantiate(Relation<T> relation) {
- return new SpatialPrimitiveDistanceQuery<T, DoubleDistance>(relation, this);
- }
-
- @Override
- public String toString() {
- return "SquaredEuclideanDistance";
- }
-
- @Override
- public boolean equals(Object obj) {
- if(obj == null) {
- return false;
- }
- if(obj == this) {
- return true;
- }
- return this.getClass().equals(obj.getClass());
- }
-
- /**
- * Parameterization class.
- *
- * @author Erich Schubert
- *
- * @apiviz.exclude
- */
- public static class Parameterizer extends AbstractParameterizer {
- @Override
- protected SquaredEuclideanDistanceFunction makeInstance() {
- return SquaredEuclideanDistanceFunction.STATIC;
- }
- }
-} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/WeightedCanberraDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/WeightedCanberraDistanceFunction.java
new file mode 100644
index 00000000..66321b36
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/WeightedCanberraDistanceFunction.java
@@ -0,0 +1,91 @@
+package de.lmu.ifi.dbs.elki.distance.distancefunction;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2011
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+
+/**
+ * Weighted Canberra distance function, a variation of Manhattan distance.
+ *
+ * TODO: add parameterizer. As of now, this can only be used from Java code.
+ *
+ * @author Erich Schubert
+ */
+public class WeightedCanberraDistanceFunction extends AbstractSpatialDoubleDistanceFunction {
+ /**
+ * Weight array
+ */
+ protected double[] weights;
+
+ /**
+ * Constructor.
+ */
+ public WeightedCanberraDistanceFunction(double[] weights) {
+ super();
+ this.weights = 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 xd = v1.doubleValue(d), yd = v2.doubleValue(d);
+ final double div = Math.abs(xd) + Math.abs(yd);
+ if (div > 0.) {
+ agg += weights[d] * Math.abs(xd - yd) / div;
+ }
+ }
+ return agg;
+ }
+
+ @Override
+ public double doubleMinDist(SpatialComparable mbr1, SpatialComparable mbr2) {
+ final int dim = dimensionality(mbr1, mbr2, weights.length);
+ double agg = 0.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;
+ }
+ final double a1 = Math.max(-mbr1.getMin(d), mbr1.getMax(d));
+ final double a2 = Math.max(-mbr2.getMin(d), mbr2.getMax(d));
+ final double div = a1 + a2;
+ // Cannot be 0, because then diff = 0, and we continued before.
+ agg += weights[d] * diff / div;
+ }
+ return agg;
+ }
+
+ @Override
+ public boolean isMetric() {
+ // As this is also reffered to as "canberra metric", it is probably a metric
+ // But *maybe* only for positive numbers only?
+ return true;
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/WeightedDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/WeightedDistanceFunction.java
index 7bd09e97..fc155970 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/WeightedDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/WeightedDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -52,21 +52,15 @@ public class WeightedDistanceFunction extends AbstractVectorDoubleDistanceFuncti
assert (weightMatrix.getColumnDimensionality() == weightMatrix.getRowDimensionality());
}
- /**
- * Provides the Weighted distance for feature vectors.
- *
- * @return the Weighted distance between the given two vectors
- */
@Override
public double doubleDistance(NumberVector<?> o1, NumberVector<?> o2) {
- assert (o1.getDimensionality() == o2.getDimensionality()) : "Different dimensionality of FeatureVectors" + "\n first argument: " + o1.toString() + "\n second argument: " + o2.toString();
-
+ dimensionality(o1, o2, weightMatrix.getColumnDimensionality());
Vector o1_minus_o2 = o1.getColumnVector().minusEquals(o2.getColumnVector());
return MathUtil.mahalanobisDistance(weightMatrix, o1_minus_o2);
}
@Override
public VectorFieldTypeInformation<? super NumberVector<?>> getInputTypeRestriction() {
- return new VectorFieldTypeInformation<NumberVector<?>>(NumberVector.class, weightMatrix.getColumnDimensionality());
+ return new VectorFieldTypeInformation<>(NumberVector.class, weightMatrix.getColumnDimensionality());
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/AbstractSimilarityAdapter.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/AbstractSimilarityAdapter.java
index 74606083..890a3ece 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/AbstractSimilarityAdapter.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/AbstractSimilarityAdapter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.adapter;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -175,7 +175,7 @@ public abstract class AbstractSimilarityAdapter<O> extends AbstractDatabaseDista
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- final ObjectParameter<NormalizedSimilarityFunction<? super O, ? extends NumberDistance<?, ?>>> param = new ObjectParameter<NormalizedSimilarityFunction<? super O, ? extends NumberDistance<?, ?>>>(SIMILARITY_FUNCTION_ID, NormalizedSimilarityFunction.class, FractionalSharedNearestNeighborSimilarityFunction.class);
+ final ObjectParameter<NormalizedSimilarityFunction<? super O, ? extends NumberDistance<?, ?>>> param = new ObjectParameter<>(SIMILARITY_FUNCTION_ID, NormalizedSimilarityFunction.class, FractionalSharedNearestNeighborSimilarityFunction.class);
if(config.grab(param)) {
similarityFunction = param.instantiateClass(config);
}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/SimilarityAdapterArccos.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/ArccosSimilarityAdapter.java
index b77e4a7d..a808e2a5 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/SimilarityAdapterArccos.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/ArccosSimilarityAdapter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.adapter;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -41,20 +41,20 @@ import de.lmu.ifi.dbs.elki.distance.similarityfunction.NormalizedSimilarityFunct
*
* @param <O> Object class to process.
*/
-public class SimilarityAdapterArccos<O> extends AbstractSimilarityAdapter<O> {
+public class ArccosSimilarityAdapter<O> extends AbstractSimilarityAdapter<O> {
/**
* Constructor.
*
* @param similarityFunction Similarity function
*/
- public SimilarityAdapterArccos(NormalizedSimilarityFunction<? super O, ? extends NumberDistance<?, ?>> similarityFunction) {
+ public ArccosSimilarityAdapter(NormalizedSimilarityFunction<? super O, ? extends NumberDistance<?, ?>> similarityFunction) {
super(similarityFunction);
}
@Override
public <T extends O> DistanceQuery<T, DoubleDistance> instantiate(Relation<T> database) {
SimilarityQuery<T, ? extends NumberDistance<?, ?>> similarityQuery = similarityFunction.instantiate(database);
- return new Instance<T>(database, this, similarityQuery);
+ return new Instance<>(database, this, similarityQuery);
}
/**
@@ -91,8 +91,8 @@ public class SimilarityAdapterArccos<O> extends AbstractSimilarityAdapter<O> {
*/
public static class Parameterizer<O> extends AbstractSimilarityAdapter.Parameterizer<O> {
@Override
- protected SimilarityAdapterArccos<O> makeInstance() {
- return new SimilarityAdapterArccos<O>(similarityFunction);
+ protected ArccosSimilarityAdapter<O> makeInstance() {
+ return new ArccosSimilarityAdapter<>(similarityFunction);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/SimilarityAdapterLinear.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/LinearAdapterLinear.java
index ab7204ce..c78ff112 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/SimilarityAdapterLinear.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/LinearAdapterLinear.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.adapter;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -41,20 +41,20 @@ import de.lmu.ifi.dbs.elki.distance.similarityfunction.NormalizedSimilarityFunct
*
* @param <O> Object class to process.
*/
-public class SimilarityAdapterLinear<O> extends AbstractSimilarityAdapter<O> {
+public class LinearAdapterLinear<O> extends AbstractSimilarityAdapter<O> {
/**
* Constructor.
*
* @param similarityFunction Similarity function
*/
- public SimilarityAdapterLinear(NormalizedSimilarityFunction<? super O, ? extends NumberDistance<?, ?>> similarityFunction) {
+ public LinearAdapterLinear(NormalizedSimilarityFunction<? super O, ? extends NumberDistance<?, ?>> similarityFunction) {
super(similarityFunction);
}
@Override
public <T extends O> DistanceQuery<T, DoubleDistance> instantiate(Relation<T> database) {
SimilarityQuery<T, ? extends NumberDistance<?, ?>> similarityQuery = similarityFunction.instantiate(database);
- return new Instance<T>(database, this, similarityQuery);
+ return new Instance<>(database, this, similarityQuery);
}
/**
@@ -91,8 +91,8 @@ public class SimilarityAdapterLinear<O> extends AbstractSimilarityAdapter<O> {
*/
public static class Parameterizer<O> extends AbstractSimilarityAdapter.Parameterizer<O> {
@Override
- protected SimilarityAdapterLinear<O> makeInstance() {
- return new SimilarityAdapterLinear<O>(similarityFunction);
+ protected LinearAdapterLinear<O> makeInstance() {
+ return new LinearAdapterLinear<>(similarityFunction);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/SimilarityAdapterLn.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/LnSimilarityAdapter.java
index b1b63486..2a9b49f9 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/SimilarityAdapterLn.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/LnSimilarityAdapter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.adapter;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -41,20 +41,20 @@ import de.lmu.ifi.dbs.elki.distance.similarityfunction.NormalizedSimilarityFunct
*
* @param <O> object class to process.
*/
-public class SimilarityAdapterLn<O> extends AbstractSimilarityAdapter<O> {
+public class LnSimilarityAdapter<O> extends AbstractSimilarityAdapter<O> {
/**
* Constructor.
*
* @param similarityFunction Similarity function
*/
- public SimilarityAdapterLn(NormalizedSimilarityFunction<? super O, ? extends NumberDistance<?, ?>> similarityFunction) {
+ public LnSimilarityAdapter(NormalizedSimilarityFunction<? super O, ? extends NumberDistance<?, ?>> similarityFunction) {
super(similarityFunction);
}
@Override
public <T extends O> DistanceQuery<T, DoubleDistance> instantiate(Relation<T> database) {
SimilarityQuery<T, ? extends NumberDistance<?, ?>> similarityQuery = similarityFunction.instantiate(database);
- return new Instance<T>(database, this, similarityQuery);
+ return new Instance<>(database, this, similarityQuery);
}
/**
@@ -91,8 +91,8 @@ public class SimilarityAdapterLn<O> extends AbstractSimilarityAdapter<O> {
*/
public static class Parameterizer<O> extends AbstractSimilarityAdapter.Parameterizer<O> {
@Override
- protected SimilarityAdapterLn<O> makeInstance() {
- return new SimilarityAdapterLn<O>(similarityFunction);
+ protected LnSimilarityAdapter<O> makeInstance() {
+ return new LnSimilarityAdapter<>(similarityFunction);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/package-info.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/package-info.java
index 303d3500..14346688 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/colorhistogram/HSBHistogramQuadraticDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/colorhistogram/HSBHistogramQuadraticDistanceFunction.java
index 771e32f2..414a4787 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/colorhistogram/HSBHistogramQuadraticDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/colorhistogram/HSBHistogramQuadraticDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.colorhistogram;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -89,8 +89,14 @@ public class HSBHistogramQuadraticDistanceFunction extends WeightedDistanceFunct
final int sy = (y / quantb) % quants;
final int by = y % quantb;
- final double cos = Math.cos((hx + .5) / quanth * MathUtil.TWOPI) * (sx + .5) / quants - Math.cos((hy + .5) / quanth * MathUtil.TWOPI) * (sy + .5) / quants;
- final double sin = Math.sin((hx + .5) / quanth * MathUtil.TWOPI) * (sx + .5) / quants - Math.sin((hy + .5) / quanth * MathUtil.TWOPI) * (sy + .5) / quants;
+ final double chx = Math.cos((hx + .5) / quanth * MathUtil.TWOPI);
+ final double chy = Math.cos((hy + .5) / quanth * MathUtil.TWOPI);
+ // final double shx = Math.sin((hx + .5) / quanth * MathUtil.TWOPI);
+ final double shx = MathUtil.cosToSin((hx + .5) / quanth * MathUtil.TWOPI, chx);
+ // final double shy = Math.sin((hy + .5) / quanth * MathUtil.TWOPI);
+ final double shy = MathUtil.cosToSin((hy + .5) / quanth * MathUtil.TWOPI, chy);
+ final double cos = chx * (sx + .5) / quants - chy * (sy + .5) / quants;
+ final double sin = shx * (sx + .5) / quants - shy * (sy + .5) / quants;
final double db = (bx - by) / (double) quantb;
final double val = 1. - Math.sqrt((db * db + sin * sin + cos * cos) / 5);
m.set(x, y, val);
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/colorhistogram/HistogramIntersectionDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/colorhistogram/HistogramIntersectionDistanceFunction.java
index 2f38f68b..ffced03f 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/colorhistogram/HistogramIntersectionDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/colorhistogram/HistogramIntersectionDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.colorhistogram;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,12 +25,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.colorhistogram;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
-import de.lmu.ifi.dbs.elki.database.query.distance.SpatialDistanceQuery;
-import de.lmu.ifi.dbs.elki.database.query.distance.SpatialPrimitiveDistanceQuery;
-import de.lmu.ifi.dbs.elki.database.relation.Relation;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractVectorDoubleDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDoubleDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractSpatialDoubleDistanceFunction;
import de.lmu.ifi.dbs.elki.utilities.documentation.Description;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
@@ -48,7 +43,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
@Title("Color histogram intersection distance")
@Description("Distance function for color histograms that emphasizes 'strong' bins.")
@Reference(authors = "M. J. Swain, D. H. Ballard", title = "Color Indexing", booktitle = "International Journal of Computer Vision, 7(1), 32, 1991")
-public class HistogramIntersectionDistanceFunction extends AbstractVectorDoubleDistanceFunction implements SpatialPrimitiveDoubleDistanceFunction<NumberVector<?>> {
+public class HistogramIntersectionDistanceFunction extends AbstractSpatialDoubleDistanceFunction {
/**
* Static instance
*/
@@ -65,55 +60,33 @@ public class HistogramIntersectionDistanceFunction extends AbstractVectorDoubleD
}
@Override
- public DoubleDistance minDist(SpatialComparable mbr1, SpatialComparable mbr2) {
- return new DoubleDistance(doubleMinDist(mbr1, mbr2));
- }
-
- @Override
public double doubleDistance(NumberVector<?> v1, NumberVector<?> v2) {
- final int dim1 = v1.getDimensionality();
- if(dim1 != v2.getDimensionality()) {
- throw new IllegalArgumentException("Different dimensionality of FeatureVectors" + "\n first argument: " + v1.toString() + "\n second argument: " + v2.toString() + "\n" + v1.getDimensionality() + "!=" + v2.getDimensionality());
- }
- double dist = 0;
- double norm1 = 0;
- double norm2 = 0;
- for(int i = 0; i < dim1; i++) {
+ final int dim = dimensionality(v1, v2);
+ double agg = 0., norm1 = 0., norm2 = 0.;
+ for (int i = 0; i < dim; i++) {
final double val1 = v1.doubleValue(i);
final double val2 = v2.doubleValue(i);
- dist += Math.min(val1, val2);
+ agg += Math.min(val1, val2);
norm1 += val1;
norm2 += val2;
}
- dist = 1 - dist / Math.min(norm1, norm2);
- return dist;
+ return 1. - agg / Math.min(norm1, norm2);
}
@Override
public double doubleMinDist(SpatialComparable mbr1, SpatialComparable mbr2) {
- final int dim1 = mbr1.getDimensionality();
- if(dim1 != mbr2.getDimensionality()) {
- throw new IllegalArgumentException("Different dimensionality of FeatureVectors" + "\n first argument: " + mbr1.toString() + "\n second argument: " + mbr2.toString() + "\n" + mbr1.getDimensionality() + "!=" + mbr2.getDimensionality());
- }
- double dist = 0;
- double norm1 = 0;
- double norm2 = 0;
- for(int i = 0; i < dim1; i++) {
+ final int dim = dimensionality(mbr1, mbr2);
+ double agg = 0., norm1 = 0, norm2 = 0.;
+ for (int i = 0; i < dim; i++) {
final double min1 = mbr1.getMin(i);
final double max1 = mbr1.getMax(i);
final double min2 = mbr2.getMin(i);
final double max2 = mbr2.getMax(i);
- dist += Math.min(max1, max2);
+ agg += Math.min(max1, max2);
norm1 += min1;
norm2 += min2;
}
- dist = 1 - dist / Math.min(norm1, norm2);
- return dist;
- }
-
- @Override
- public <T extends NumberVector<?>> SpatialDistanceQuery<T, DoubleDistance> instantiate(Relation<T> relation) {
- return new SpatialPrimitiveDistanceQuery<T, DoubleDistance>(relation, this);
+ return 1 - agg / Math.min(norm1, norm2);
}
@Override
@@ -123,7 +96,7 @@ public class HistogramIntersectionDistanceFunction extends AbstractVectorDoubleD
@Override
public boolean equals(Object obj) {
- if(obj == null) {
+ if (obj == null) {
return false;
}
return this.getClass().equals(obj.getClass());
@@ -142,4 +115,4 @@ public class HistogramIntersectionDistanceFunction extends AbstractVectorDoubleD
return HistogramIntersectionDistanceFunction.STATIC;
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/colorhistogram/RGBHistogramQuadraticDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/colorhistogram/RGBHistogramQuadraticDistanceFunction.java
index 09dfa124..8cf0339e 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/colorhistogram/RGBHistogramQuadraticDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/colorhistogram/RGBHistogramQuadraticDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.colorhistogram;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/colorhistogram/package-info.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/colorhistogram/package-info.java
index 43e90206..a61c1e49 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/colorhistogram/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/colorhistogram/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/ERiCDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/ERiCDistanceFunction.java
index 55fd0e72..bece8279 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/ERiCDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/ERiCDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.correlation;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -113,7 +113,7 @@ public class ERiCDistanceFunction extends AbstractIndexBasedDistanceFunction<Num
// Generics (AFAICT)
@SuppressWarnings("unchecked")
FilteredLocalPCAIndex<T> indexinst = (FilteredLocalPCAIndex<T>) indexFactory.instantiate((Relation<NumberVector<?>>) database);
- return new Instance<T>(database, indexinst, this, delta, tau);
+ return new Instance<>(database, indexinst, this, delta, tau);
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/PCABasedCorrelationDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/PCABasedCorrelationDistanceFunction.java
index 20f96a29..4d5553a3 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/PCABasedCorrelationDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/PCABasedCorrelationDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.correlation;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -88,7 +88,7 @@ public class PCABasedCorrelationDistanceFunction extends AbstractIndexBasedDista
// Generics (AFAICT)
@SuppressWarnings("unchecked")
FilteredLocalPCAIndex<T> indexinst = (FilteredLocalPCAIndex<T>) indexFactory.instantiate((Relation<NumberVector<?>>) database);
- return new Instance<T>(database, indexinst, delta, this);
+ return new Instance<>(database, indexinst, delta, this);
}
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/PearsonCorrelationDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/PearsonCorrelationDistanceFunction.java
index 1ba14af2..8716ad6e 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/PearsonCorrelationDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/PearsonCorrelationDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.correlation;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/SquaredPearsonCorrelationDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/SquaredPearsonCorrelationDistanceFunction.java
index b4f8a3bd..8ddb0de6 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/SquaredPearsonCorrelationDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/SquaredPearsonCorrelationDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.correlation;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/WeightedPearsonCorrelationDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/WeightedPearsonCorrelationDistanceFunction.java
index fa1196fe..67b1dc27 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/WeightedPearsonCorrelationDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/WeightedPearsonCorrelationDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.correlation;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -93,4 +93,9 @@ public class WeightedPearsonCorrelationDistanceFunction extends AbstractVectorDo
}
return Arrays.equals(this.weights, ((WeightedPearsonCorrelationDistanceFunction)obj).weights);
}
+
+ @Override
+ public String toString() {
+ return "WeightedPearsonCorrelationDistanceFunction";
+ }
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/WeightedSquaredPearsonCorrelationDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/WeightedSquaredPearsonCorrelationDistanceFunction.java
index 141229f6..0c1848fc 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/WeightedSquaredPearsonCorrelationDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/WeightedSquaredPearsonCorrelationDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.correlation;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/package-info.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/package-info.java
index 2033dab1..c422a3da 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/DiskCacheBasedDoubleDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/DiskCacheBasedDoubleDistanceFunction.java
index a7ddb1ad..e84f18b8 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/DiskCacheBasedDoubleDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/DiskCacheBasedDoubleDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.external;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/DiskCacheBasedFloatDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/DiskCacheBasedFloatDistanceFunction.java
index 23da36b2..cd84853b 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/DiskCacheBasedFloatDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/DiskCacheBasedFloatDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.external;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/DistanceParser.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/DistanceParser.java
index c332670a..08c3c312 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/DistanceParser.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/DistanceParser.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.external;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/DistanceParsingResult.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/DistanceParsingResult.java
index 916451c0..3f43cb97 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/DistanceParsingResult.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/DistanceParsingResult.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.external;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/FileBasedDoubleDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/FileBasedDoubleDistanceFunction.java
index 5489a241..29546401 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/FileBasedDoubleDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/FileBasedDoubleDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.external;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -170,7 +170,7 @@ public class FileBasedDoubleDistanceFunction extends AbstractDBIDDistanceFunctio
matrixfile = MATRIX_PARAM.getValue();
}
- final ObjectParameter<DistanceParser<DoubleDistance>> PARSER_PARAM = new ObjectParameter<DistanceParser<DoubleDistance>>(PARSER_ID, DistanceParser.class, NumberDistanceParser.class);
+ final ObjectParameter<DistanceParser<DoubleDistance>> PARSER_PARAM = new ObjectParameter<>(PARSER_ID, DistanceParser.class, NumberDistanceParser.class);
if(config.grab(PARSER_PARAM)) {
ListParameterization parserConfig = new ListParameterization();
parserConfig.addParameter(DistanceParser.DISTANCE_ID, DoubleDistance.class);
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/FileBasedFloatDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/FileBasedFloatDistanceFunction.java
index 520c1f76..994d854d 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/FileBasedFloatDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/FileBasedFloatDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.external;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -168,13 +168,13 @@ public class FileBasedFloatDistanceFunction extends AbstractDBIDDistanceFunction
if(config.grab(MATRIX_PARAM)) {
matrixfile = MATRIX_PARAM.getValue();
}
- final ObjectParameter<DistanceParser<FloatDistance>> PARSER_PARAM = new ObjectParameter<DistanceParser<FloatDistance>>(PARSER_ID, DistanceParser.class, NumberDistanceParser.class);
+ final ObjectParameter<DistanceParser<FloatDistance>> PARSER_PARAM = new ObjectParameter<>(PARSER_ID, DistanceParser.class, NumberDistanceParser.class);
if(config.grab(PARSER_PARAM)) {
ListParameterization parserConfig = new ListParameterization();
parserConfig.addParameter(DistanceParser.DISTANCE_ID, FloatDistance.class);
ChainedParameterization combinedConfig = new ChainedParameterization(parserConfig, config);
combinedConfig.errorsTo(config);
- parser = PARSER_PARAM.instantiateClass(config);
+ parser = PARSER_PARAM.instantiateClass(combinedConfig);
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/NumberDistanceParser.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/NumberDistanceParser.java
index 82cc5b27..9a7315b3 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/NumberDistanceParser.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/NumberDistanceParser.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.external;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -79,10 +79,11 @@ public class NumberDistanceParser<D extends NumberDistance<D, ?>> extends Abstra
*
* @param colSep Column separator pattern
* @param quoteChar Quote character
+ * @param comment Comment pattern
* @param distanceFactory Distance factory to use
*/
- public NumberDistanceParser(Pattern colSep, char quoteChar, D distanceFactory) {
- super(colSep, quoteChar);
+ public NumberDistanceParser(Pattern colSep, char quoteChar, Pattern comment, D distanceFactory) {
+ super(colSep, quoteChar, comment);
this.distanceFactory = distanceFactory;
}
@@ -93,39 +94,41 @@ public class NumberDistanceParser<D extends NumberDistance<D, ?>> extends Abstra
IndefiniteProgress prog = LOG.isVerbose() ? new IndefiniteProgress("Parsing distance matrix", LOG) : null;
ModifiableDBIDs ids = DBIDUtil.newHashSet();
- Map<DBIDPair, D> distanceCache = new HashMap<DBIDPair, D>();
+ Map<DBIDPair, D> distanceCache = new HashMap<>();
try {
for (String line; (line = reader.readLine()) != null; lineNumber++) {
if (prog != null) {
prog.incrementProcessed(LOG);
}
- if (!line.startsWith(COMMENT) && line.length() > 0) {
- List<String> entries = tokenize(line);
- if (entries.size() != 3) {
- throw new IllegalArgumentException("Line " + lineNumber + " does not have the " + "required input format: id1 id2 distanceValue! " + line);
- }
-
- DBID id1, id2;
- try {
- id1 = DBIDUtil.importInteger(Integer.parseInt(entries.get(0)));
- } catch (NumberFormatException e) {
- throw new IllegalArgumentException("Error in line " + lineNumber + ": id1 is no integer!");
- }
-
- try {
- id2 = DBIDUtil.importInteger(Integer.parseInt(entries.get(1)));
- } catch (NumberFormatException e) {
- throw new IllegalArgumentException("Error in line " + lineNumber + ": id2 is no integer!");
- }
-
- try {
- D distance = distanceFactory.parseString(entries.get(2));
- put(id1, id2, distance, distanceCache);
- ids.add(id1);
- ids.add(id2);
- } catch (IllegalArgumentException e) {
- throw new IllegalArgumentException("Error in line " + lineNumber + ":" + e.getMessage(), e);
- }
+ // Skip empty lines and comments
+ if (line.length() <= 0 || (comment != null && comment.matcher(line).matches())) {
+ continue;
+ }
+ List<String> entries = tokenize(line);
+ if (entries.size() != 3) {
+ throw new IllegalArgumentException("Line " + lineNumber + " does not have the " + "required input format: id1 id2 distanceValue! " + line);
+ }
+
+ DBID id1, id2;
+ try {
+ id1 = DBIDUtil.importInteger(Integer.parseInt(entries.get(0)));
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("Error in line " + lineNumber + ": id1 is no integer!");
+ }
+
+ try {
+ id2 = DBIDUtil.importInteger(Integer.parseInt(entries.get(1)));
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("Error in line " + lineNumber + ": id2 is no integer!");
+ }
+
+ try {
+ D distance = distanceFactory.parseString(entries.get(2));
+ put(id1, id2, distance, distanceCache);
+ ids.add(id1);
+ ids.add(id2);
+ } catch (IllegalArgumentException e) {
+ throw new IllegalArgumentException("Error in line " + lineNumber + ":" + e.getMessage(), e);
}
}
} catch (IOException e) {
@@ -147,7 +150,7 @@ public class NumberDistanceParser<D extends NumberDistance<D, ?>> extends Abstra
}
}
}
- return new DistanceParsingResult<D>(distanceCache);
+ return new DistanceParsingResult<>(distanceCache);
}
/**
@@ -211,7 +214,7 @@ public class NumberDistanceParser<D extends NumberDistance<D, ?>> extends Abstra
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- ObjectParameter<D> distFuncP = new ObjectParameter<D>(DISTANCE_ID, Distance.class);
+ ObjectParameter<D> distFuncP = new ObjectParameter<>(DISTANCE_ID, Distance.class);
if (config.grab(distFuncP)) {
distanceFactory = distFuncP.instantiateClass(config);
}
@@ -219,7 +222,7 @@ public class NumberDistanceParser<D extends NumberDistance<D, ?>> extends Abstra
@Override
protected NumberDistanceParser<D> makeInstance() {
- return new NumberDistanceParser<D>(colSep, quoteChar, distanceFactory);
+ return new NumberDistanceParser<>(colSep, quoteChar, comment, distanceFactory);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/package-info.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/package-info.java
index 3099122a..53b692fa 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/package-info.java
@@ -6,7 +6,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/geo/DimensionSelectingLatLngDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/geo/DimensionSelectingLatLngDistanceFunction.java
index 42fd869d..1974e533 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/geo/DimensionSelectingLatLngDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/geo/DimensionSelectingLatLngDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.geo;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,25 +27,25 @@ 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.database.query.distance.SpatialPrimitiveDistanceQuery;
-import de.lmu.ifi.dbs.elki.database.relation.Relation;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractVectorDoubleDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDoubleDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
-import de.lmu.ifi.dbs.elki.math.GeoUtil;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractSpatialDoubleDistanceFunction;
+import de.lmu.ifi.dbs.elki.math.geodesy.EarthModel;
+import de.lmu.ifi.dbs.elki.math.geodesy.SphericalVincentyEarthModel;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.NotImplementedException;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterEqualConstraint;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.NoDuplicateValueGlobalConstraint;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
/**
* Distance function for 2D vectors in Latitude, Longitude form.
*
* @author Erich Schubert
*/
-public class DimensionSelectingLatLngDistanceFunction extends AbstractVectorDoubleDistanceFunction implements SpatialPrimitiveDoubleDistanceFunction<NumberVector<?>> {
+public class DimensionSelectingLatLngDistanceFunction extends AbstractSpatialDoubleDistanceFunction {
/**
* Latitude dimension.
*/
@@ -57,54 +57,90 @@ public class DimensionSelectingLatLngDistanceFunction extends AbstractVectorDoub
final int dimlng;
/**
+ * Earth model used.
+ */
+ final EarthModel model;
+
+ /**
* Constructor.
*
* @param dimlat Dimension storing the latitude
* @param dimlng Dimension storing the longitude
+ * @param model Earth model
*/
- public DimensionSelectingLatLngDistanceFunction(int dimlat, int dimlng) {
+ public DimensionSelectingLatLngDistanceFunction(int dimlat, int dimlng, EarthModel model) {
super();
this.dimlat = dimlat;
this.dimlng = dimlng;
+ this.model = model;
}
@Override
public double doubleDistance(NumberVector<?> o1, NumberVector<?> o2) {
- return GeoUtil.haversineFormulaDeg(o1.doubleValue(dimlat), o1.doubleValue(dimlng), o2.doubleValue(dimlat), o2.doubleValue(dimlng));
+ return model.distanceDeg(o1.doubleValue(dimlat), o1.doubleValue(dimlng), o2.doubleValue(dimlat), o2.doubleValue(dimlng));
}
@Override
+ @Reference(authors = "Erich Schubert, Arthur Zimek and Hans-Peter Kriegel", title = "Geodetic Distance Queries on R-Trees for Indexing Geographic Data", booktitle = "Advances in Spatial and Temporal Databases - 13th International Symposium, SSTD 2013, Munich, Germany")
public double doubleMinDist(SpatialComparable mbr1, SpatialComparable mbr2) {
if (mbr1 instanceof NumberVector) {
if (mbr2 instanceof NumberVector) {
return doubleDistance((NumberVector<?>) mbr1, (NumberVector<?>) mbr2);
} else {
NumberVector<?> o1 = (NumberVector<?>) mbr1;
- return GeoUtil.latlngMinDistDeg(o1.doubleValue(dimlat), o1.doubleValue(dimlng), mbr2.getMin(dimlat), mbr2.getMin(dimlng), mbr2.getMax(dimlat), mbr2.getMax(dimlng));
+ return model.minDistDeg(o1.doubleValue(dimlat), o1.doubleValue(dimlng), mbr2.getMin(dimlat), mbr2.getMin(dimlng), mbr2.getMax(dimlat), mbr2.getMax(dimlng));
}
} else {
if (mbr2 instanceof NumberVector) {
NumberVector<?> o2 = (NumberVector<?>) mbr2;
- return GeoUtil.latlngMinDistDeg(o2.doubleValue(dimlat), o2.doubleValue(dimlng), mbr1.getMin(dimlat), mbr1.getMin(dimlng), mbr1.getMax(dimlat), mbr1.getMax(dimlng));
+ return model.minDistDeg(o2.doubleValue(dimlat), o2.doubleValue(dimlng), mbr1.getMin(dimlat), mbr1.getMin(dimlng), mbr1.getMax(dimlat), mbr1.getMax(dimlng));
} else {
- throw new UnsupportedOperationException("MBR to MBR mindist is not yet implemented.");
+ throw new NotImplementedException("This distance function cannot - yet - be used with this algorithm, as the lower bound rectangle to rectangle distances have not yet been formalized for geodetic data.");
}
}
}
@Override
- public DoubleDistance minDist(SpatialComparable mbr1, SpatialComparable mbr2) {
- return new DoubleDistance(doubleMinDist(mbr1, mbr2));
+ public SimpleTypeInformation<? super NumberVector<?>> getInputTypeRestriction() {
+ return new VectorFieldTypeInformation<>(NumberVector.class, Math.max(dimlat, dimlng), Integer.MAX_VALUE);
}
@Override
- public SimpleTypeInformation<? super NumberVector<?>> getInputTypeRestriction() {
- return new VectorFieldTypeInformation<NumberVector<?>>(NumberVector.class, Math.max(dimlat, dimlng), Integer.MAX_VALUE);
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + dimlat;
+ result = prime * result + dimlng;
+ result = prime * result + ((model == null) ? 0 : model.hashCode());
+ return result;
}
@Override
- public <T extends NumberVector<?>> SpatialPrimitiveDistanceQuery<T, DoubleDistance> instantiate(Relation<T> relation) {
- return new SpatialPrimitiveDistanceQuery<T, DoubleDistance>(relation, this);
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ DimensionSelectingLatLngDistanceFunction other = (DimensionSelectingLatLngDistanceFunction) obj;
+ if (dimlat != other.dimlat) {
+ return false;
+ }
+ if (dimlng != other.dimlng) {
+ return false;
+ }
+ if (model == null) {
+ if (other.model != null) {
+ return false;
+ }
+ } else if (!model.equals(other.model)) {
+ return false;
+ }
+ return true;
}
/**
@@ -135,6 +171,11 @@ public class DimensionSelectingLatLngDistanceFunction extends AbstractVectorDoub
*/
int dimlng;
+ /**
+ * Earth model used.
+ */
+ EarthModel model;
+
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
@@ -149,11 +190,15 @@ public class DimensionSelectingLatLngDistanceFunction extends AbstractVectorDoub
dimlng = dimlngP.getValue();
}
config.checkConstraint(new NoDuplicateValueGlobalConstraint(dimlatP, dimlngP));
+ ObjectParameter<EarthModel> modelP = new ObjectParameter<>(EarthModel.MODEL_ID, EarthModel.class, SphericalVincentyEarthModel.class);
+ if (config.grab(modelP)) {
+ model = modelP.instantiateClass(config);
+ }
}
@Override
protected DimensionSelectingLatLngDistanceFunction makeInstance() {
- return new DimensionSelectingLatLngDistanceFunction(dimlat, dimlng);
+ return new DimensionSelectingLatLngDistanceFunction(dimlat, dimlng, model);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/geo/LatLngDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/geo/LatLngDistanceFunction.java
index 31bed1c5..221cfa2b 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/geo/LatLngDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/geo/LatLngDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.geo;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,86 +27,94 @@ 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.database.query.distance.SpatialPrimitiveDistanceQuery;
-import de.lmu.ifi.dbs.elki.database.relation.Relation;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractVectorDoubleDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDoubleDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
-import de.lmu.ifi.dbs.elki.math.GeoUtil;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractSpatialDoubleDistanceFunction;
+import de.lmu.ifi.dbs.elki.math.geodesy.EarthModel;
+import de.lmu.ifi.dbs.elki.math.geodesy.SphericalVincentyEarthModel;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.NotImplementedException;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
/**
* Distance function for 2D vectors in Latitude, Longitude form.
*
* @author Erich Schubert
*/
-public class LatLngDistanceFunction extends AbstractVectorDoubleDistanceFunction implements SpatialPrimitiveDoubleDistanceFunction<NumberVector<?>> {
+public class LatLngDistanceFunction extends AbstractSpatialDoubleDistanceFunction {
/**
- * Static instance.
+ * Earth model to use.
*/
- public static final LatLngDistanceFunction STATIC = new LatLngDistanceFunction();
+ private EarthModel model;
/**
- * Constructor. Use static instance instead!
+ * Constructor.
*/
- @Deprecated
- public LatLngDistanceFunction() {
+ public LatLngDistanceFunction(EarthModel model) {
super();
+ this.model = model;
}
@Override
public double doubleDistance(NumberVector<?> o1, NumberVector<?> o2) {
- return GeoUtil.haversineFormulaDeg(o1.doubleValue(0), o1.doubleValue(1), o2.doubleValue(0), o2.doubleValue(1));
+ return model.distanceDeg(o1.doubleValue(0), o1.doubleValue(1), o2.doubleValue(0), o2.doubleValue(1));
}
@Override
+ @Reference(authors = "Erich Schubert, Arthur Zimek and Hans-Peter Kriegel", title = "Geodetic Distance Queries on R-Trees for Indexing Geographic Data", booktitle = "Advances in Spatial and Temporal Databases - 13th International Symposium, SSTD 2013, Munich, Germany")
public double doubleMinDist(SpatialComparable mbr1, SpatialComparable mbr2) {
if (mbr1 instanceof NumberVector) {
if (mbr2 instanceof NumberVector) {
return doubleDistance((NumberVector<?>) mbr1, (NumberVector<?>) mbr2);
} else {
NumberVector<?> o1 = (NumberVector<?>) mbr1;
- return GeoUtil.latlngMinDistDeg(o1.doubleValue(0), o1.doubleValue(1), mbr2.getMin(0), mbr2.getMin(1), mbr2.getMax(0), mbr2.getMax(1));
+ return model.minDistDeg(o1.doubleValue(0), o1.doubleValue(1), mbr2.getMin(0), mbr2.getMin(1), mbr2.getMax(0), mbr2.getMax(1));
}
} else {
if (mbr2 instanceof NumberVector) {
NumberVector<?> o2 = (NumberVector<?>) mbr2;
- return GeoUtil.latlngMinDistDeg(o2.doubleValue(0), o2.doubleValue(1), mbr1.getMin(0), mbr1.getMin(1), mbr1.getMax(0), mbr1.getMax(1));
+ return model.minDistDeg(o2.doubleValue(0), o2.doubleValue(1), mbr1.getMin(0), mbr1.getMin(1), mbr1.getMax(0), mbr1.getMax(1));
} else {
- throw new UnsupportedOperationException("MBR to MBR mindist is not yet implemented.");
+ throw new NotImplementedException("This distance function cannot - yet - be used with this algorithm, as the lower bound rectangle to rectangle distances have not yet been formalized for geodetic data.");
}
}
}
@Override
- public DoubleDistance minDist(SpatialComparable mbr1, SpatialComparable mbr2) {
- return new DoubleDistance(doubleMinDist(mbr1, mbr2));
+ public SimpleTypeInformation<? super NumberVector<?>> getInputTypeRestriction() {
+ return new VectorFieldTypeInformation<>(NumberVector.class, 2);
}
@Override
- public SimpleTypeInformation<? super NumberVector<?>> getInputTypeRestriction() {
- return new VectorFieldTypeInformation<NumberVector<?>>(NumberVector.class, 2);
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((model == null) ? 0 : model.hashCode());
+ return result;
}
@Override
public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
if (obj == null) {
return false;
}
- if (obj == this) {
- return true;
+ if (getClass() != obj.getClass()) {
+ return false;
}
- if (this.getClass().equals(obj.getClass())) {
- return true;
+ LatLngDistanceFunction other = (LatLngDistanceFunction) obj;
+ if (model == null) {
+ if (other.model != null) {
+ return false;
+ }
+ } else if (!model.equals(other.model)) {
+ return false;
}
- return super.equals(obj);
+ return true;
}
- @Override
- public <T extends NumberVector<?>> SpatialPrimitiveDistanceQuery<T, DoubleDistance> instantiate(Relation<T> relation) {
- return new SpatialPrimitiveDistanceQuery<T, DoubleDistance>(relation, this);
- }
-
/**
* Parameterization class.
*
@@ -115,9 +123,23 @@ public class LatLngDistanceFunction extends AbstractVectorDoubleDistanceFunction
* @apiviz.exclude
*/
public static class Parameterizer extends AbstractParameterizer {
+ /**
+ * Earth model used.
+ */
+ EarthModel model;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ ObjectParameter<EarthModel> modelP = new ObjectParameter<>(EarthModel.MODEL_ID, EarthModel.class, SphericalVincentyEarthModel.class);
+ if (config.grab(modelP)) {
+ model = modelP.instantiateClass(config);
+ }
+ }
+
@Override
protected LatLngDistanceFunction makeInstance() {
- return LatLngDistanceFunction.STATIC;
+ return new LatLngDistanceFunction(model);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/geo/LngLatDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/geo/LngLatDistanceFunction.java
index 7064224a..98a219dd 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/geo/LngLatDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/geo/LngLatDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.geo;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,86 +27,99 @@ 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.database.query.distance.SpatialPrimitiveDistanceQuery;
-import de.lmu.ifi.dbs.elki.database.relation.Relation;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractVectorDoubleDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDoubleDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
-import de.lmu.ifi.dbs.elki.math.GeoUtil;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractSpatialDoubleDistanceFunction;
+import de.lmu.ifi.dbs.elki.math.geodesy.EarthModel;
+import de.lmu.ifi.dbs.elki.math.geodesy.SphericalVincentyEarthModel;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.NotImplementedException;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
/**
* Distance function for 2D vectors in Longitude, Latitude form.
*
* @author Erich Schubert
*/
-public class LngLatDistanceFunction extends AbstractVectorDoubleDistanceFunction implements SpatialPrimitiveDoubleDistanceFunction<NumberVector<?>> {
+public class LngLatDistanceFunction extends AbstractSpatialDoubleDistanceFunction {
/**
- * Static instance.
+ * Earth model to use.
*/
- public static final LngLatDistanceFunction STATIC = new LngLatDistanceFunction();
+ private EarthModel model;
/**
- * Constructor. Use static instance instead!
+ * Constructor.
*/
- @Deprecated
- public LngLatDistanceFunction() {
+ public LngLatDistanceFunction(EarthModel model) {
super();
+ this.model = model;
}
@Override
public double doubleDistance(NumberVector<?> o1, NumberVector<?> o2) {
- return GeoUtil.haversineFormulaDeg(o1.doubleValue(1), o1.doubleValue(0), o2.doubleValue(1), o2.doubleValue(0));
+ return model.distanceDeg(o1.doubleValue(1), o1.doubleValue(0), o2.doubleValue(1), o2.doubleValue(0));
}
@Override
+ @Reference(authors = "Erich Schubert, Arthur Zimek and Hans-Peter Kriegel", title = "Geodetic Distance Queries on R-Trees for Indexing Geographic Data", booktitle = "Advances in Spatial and Temporal Databases - 13th International Symposium, SSTD 2013, Munich, Germany")
public double doubleMinDist(SpatialComparable mbr1, SpatialComparable mbr2) {
if (mbr1 instanceof NumberVector) {
if (mbr2 instanceof NumberVector) {
return doubleDistance((NumberVector<?>) mbr1, (NumberVector<?>) mbr2);
} else {
NumberVector<?> o1 = (NumberVector<?>) mbr1;
- return GeoUtil.latlngMinDistDeg(o1.doubleValue(1), o1.doubleValue(0), mbr2.getMin(1), mbr2.getMin(0), mbr2.getMax(1), mbr2.getMax(0));
+ return model.minDistDeg(o1.doubleValue(1), o1.doubleValue(0), mbr2.getMin(1), mbr2.getMin(0), mbr2.getMax(1), mbr2.getMax(0));
}
} else {
if (mbr2 instanceof NumberVector) {
NumberVector<?> o2 = (NumberVector<?>) mbr2;
- return GeoUtil.latlngMinDistDeg(o2.doubleValue(1), o2.doubleValue(0), mbr1.getMin(1), mbr1.getMin(0), mbr1.getMax(1), mbr1.getMax(0));
+ return model.minDistDeg(o2.doubleValue(1), o2.doubleValue(0), mbr1.getMin(1), mbr1.getMin(0), mbr1.getMax(1), mbr1.getMax(0));
} else {
- throw new UnsupportedOperationException("MBR to MBR mindist is not yet implemented.");
+ throw new NotImplementedException("This distance function cannot - yet - be used with this algorithm, as the lower bound rectangle to rectangle distances have not yet been formalized for geodetic data.");
}
}
}
@Override
- public DoubleDistance minDist(SpatialComparable mbr1, SpatialComparable mbr2) {
- return new DoubleDistance(doubleMinDist(mbr1, mbr2));
+ public SimpleTypeInformation<? super NumberVector<?>> getInputTypeRestriction() {
+ return new VectorFieldTypeInformation<>(NumberVector.class, 2);
}
@Override
- public SimpleTypeInformation<? super NumberVector<?>> getInputTypeRestriction() {
- return new VectorFieldTypeInformation<NumberVector<?>>(NumberVector.class, 2);
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((model == null) ? 0 : model.hashCode());
+ return result;
}
@Override
public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
if (obj == null) {
return false;
}
- if (obj == this) {
- return true;
+ if (getClass() != obj.getClass()) {
+ return false;
}
- if (this.getClass().equals(obj.getClass())) {
- return true;
+ LngLatDistanceFunction other = (LngLatDistanceFunction) obj;
+ if (model == null) {
+ if (other.model != null) {
+ return false;
+ }
+ } else if (!model.equals(other.model)) {
+ return false;
}
- return super.equals(obj);
+ return true;
}
@Override
- public <T extends NumberVector<?>> SpatialPrimitiveDistanceQuery<T, DoubleDistance> instantiate(Relation<T> relation) {
- return new SpatialPrimitiveDistanceQuery<T, DoubleDistance>(relation, this);
+ public String toString() {
+ return "LngLatDistanceFunction [model=" + model + "]";
}
-
+
/**
* Parameterization class.
*
@@ -115,9 +128,23 @@ public class LngLatDistanceFunction extends AbstractVectorDoubleDistanceFunction
* @apiviz.exclude
*/
public static class Parameterizer extends AbstractParameterizer {
+ /**
+ * Earth model used.
+ */
+ EarthModel model;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ ObjectParameter<EarthModel> modelP = new ObjectParameter<>(EarthModel.MODEL_ID, EarthModel.class, SphericalVincentyEarthModel.class);
+ if (config.grab(modelP)) {
+ model = modelP.instantiateClass(config);
+ }
+ }
+
@Override
protected LngLatDistanceFunction makeInstance() {
- return LngLatDistanceFunction.STATIC;
+ return new LngLatDistanceFunction(model);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/geo/package-info.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/geo/package-info.java
index 913447fd..4c05cc5a 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/geo/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/geo/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/JeffreyDivergenceDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/histogram/HistogramMatchDistanceFunction.java
index 1ac5f2a4..947c50fe 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/JeffreyDivergenceDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/histogram/HistogramMatchDistanceFunction.java
@@ -1,4 +1,4 @@
-package de.lmu.ifi.dbs.elki.distance.distancefunction;
+package de.lmu.ifi.dbs.elki.distance.distancefunction.histogram;
/*
This file is part of ELKI:
@@ -24,50 +24,49 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
*/
import de.lmu.ifi.dbs.elki.data.NumberVector;
-import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractVectorDoubleDistanceFunction;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
/**
- * Provides the Jeffrey Divergence Distance for FeatureVectors.
+ * Distance function based on histogram matching, i.e. Manhattan distance on the
+ * cumulative density function.
+ *
+ * This distance function assumes there exist a natural order in the vectors,
+ * i.e. they should be some 1-dimensional histogram.
*
* @author Erich Schubert
*/
-@Reference(authors="J. Puzicha, J.M. Buhmann, Y. Rubner, C. Tomasi", title="Empirical evaluation of dissimilarity measures for color and texture", booktitle="Proc. 7th IEEE International Conference on Computer Vision", url="http://dx.doi.org/10.1109/ICCV.1999.790412")
-public class JeffreyDivergenceDistanceFunction extends AbstractVectorDoubleDistanceFunction {
+public class HistogramMatchDistanceFunction extends AbstractVectorDoubleDistanceFunction {
/**
* Static instance. Use this!
*/
- public static final JeffreyDivergenceDistanceFunction STATIC = new JeffreyDivergenceDistanceFunction();
+ public static final HistogramMatchDistanceFunction STATIC = new HistogramMatchDistanceFunction();
/**
- * Constructor for the Jeffrey divergence.
+ * Constructor for the Histogram match distance function.
*
* @deprecated Use static instance!
*/
@Deprecated
- public JeffreyDivergenceDistanceFunction() {
+ public HistogramMatchDistanceFunction() {
+ super();
}
@Override
public double doubleDistance(NumberVector<?> v1, NumberVector<?> v2) {
- final int dim1 = v1.getDimensionality();
- if(dim1 != v2.getDimensionality()) {
- throw new IllegalArgumentException("Different dimensionality of FeatureVectors" + "\n first argument: " + v1.toString() + "\n second argument: " + v2.toString() + "\n" + v1.getDimensionality() + "!=" + v2.getDimensionality());
- }
- double dist = 0;
- for(int i = 0; i < dim1; i++) {
- final double xi = v1.doubleValue(i);
- final double yi = v2.doubleValue(i);
- final double mi = .5 * (xi + yi);
- dist += xi * Math.log(xi / mi);
- dist += yi * Math.log(yi / mi);
+ final int dim = dimensionality(v1, v2);
+ double xs = 0., ys = 0., agg = 0.;
+ for(int i = 0; i < dim; i++) {
+ xs += v1.doubleValue(i);
+ ys += v2.doubleValue(i);
+ agg += Math.abs(xs - ys);
}
- return dist;
+ return agg;
}
@Override
public String toString() {
- return "JeffreyDivergenceDistance";
+ return "HistogramMatchDistanceFunction";
}
@Override
@@ -93,8 +92,8 @@ public class JeffreyDivergenceDistanceFunction extends AbstractVectorDoubleDista
*/
public static class Parameterizer extends AbstractParameterizer {
@Override
- protected JeffreyDivergenceDistanceFunction makeInstance() {
- return JeffreyDivergenceDistanceFunction.STATIC;
+ protected HistogramMatchDistanceFunction makeInstance() {
+ return STATIC;
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/histogram/KolmogorovSmirnovDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/histogram/KolmogorovSmirnovDistanceFunction.java
new file mode 100644
index 00000000..fa2fff76
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/histogram/KolmogorovSmirnovDistanceFunction.java
@@ -0,0 +1,101 @@
+package de.lmu.ifi.dbs.elki.distance.distancefunction.histogram;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2011
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractVectorDoubleDistanceFunction;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Distance function based on the Kolmogorov-Smirnov goodness of fit test.
+ *
+ * This distance function assumes there exist a natural order in the vectors,
+ * i.e. they should be some 1-dimensional histogram.
+ *
+ * @author Erich Schubert
+ */
+public class KolmogorovSmirnovDistanceFunction extends AbstractVectorDoubleDistanceFunction {
+ /**
+ * Static instance. Use this!
+ */
+ public static final KolmogorovSmirnovDistanceFunction STATIC = new KolmogorovSmirnovDistanceFunction();
+
+ /**
+ * Constructor for the Kolmogorov-Smirnov distance function.
+ *
+ * @deprecated Use static instance!
+ */
+ @Deprecated
+ public KolmogorovSmirnovDistanceFunction() {
+ super();
+ }
+
+ @Override
+ public double doubleDistance(NumberVector<?> v1, NumberVector<?> v2) {
+ final int dim = dimensionality(v1, v2);
+ double xs = 0., ys = 0., agg = 0.;
+ for (int i = 0; i < dim; i++) {
+ xs += v1.doubleValue(i);
+ ys += v2.doubleValue(i);
+ double diff = Math.abs(xs - ys);
+ if (diff > agg) {
+ agg = diff;
+ }
+ }
+ return agg;
+ }
+
+ @Override
+ public String toString() {
+ return "KolmogorovSmirnovDistanceFunction";
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (obj == this) {
+ return true;
+ }
+ if (this.getClass().equals(obj.getClass())) {
+ return true;
+ }
+ return super.equals(obj);
+ }
+
+ /**
+ * Parameterization class, using the static instance.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected KolmogorovSmirnovDistanceFunction makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/histogram/package-info.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/histogram/package-info.java
new file mode 100644
index 00000000..e6a9a8be
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/histogram/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Distance functions for <b>one-dimensional</b> histograms.
+ */
+package de.lmu.ifi.dbs.elki.distance.distancefunction.histogram; \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/EuclideanDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/EuclideanDistanceFunction.java
new file mode 100644
index 00000000..03116430
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/EuclideanDistanceFunction.java
@@ -0,0 +1,167 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Provides the Euclidean distance for FeatureVectors.
+ *
+ * @author Arthur Zimek
+ */
+@Alias({ "euclidean", "euclid", "l2", "EuclideanDistanceFunction", "de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction" })
+public class EuclideanDistanceFunction extends LPNormDistanceFunction {
+ /**
+ * Static instance. Use this!
+ */
+ public static final EuclideanDistanceFunction STATIC = new EuclideanDistanceFunction();
+
+ /**
+ * Provides a Euclidean distance function that can compute the Euclidean
+ * distance (that is a DoubleDistance) for FeatureVectors.
+ *
+ * @deprecated Use static instance!
+ */
+ @Deprecated
+ public EuclideanDistanceFunction() {
+ super(2.);
+ }
+
+ @Override
+ public double doubleDistance(NumberVector<?> v1, NumberVector<?> v2) {
+ final int dim = dimensionality(v1, v2);
+ double agg = 0.;
+ for (int d = 0; d < dim; d++) {
+ final double delta = v1.doubleValue(d) - v2.doubleValue(d);
+ agg += delta * delta;
+ }
+ return Math.sqrt(agg);
+ }
+
+ @Override
+ public double doubleNorm(NumberVector<?> v) {
+ final int dim = v.getDimensionality();
+ double agg = 0.;
+ for (int d = 0; d < dim; d++) {
+ final double val = v.doubleValue(d);
+ agg += val * val;
+ }
+ return Math.sqrt(agg);
+ }
+
+ protected double doubleMinDistObject(NumberVector<?> v, SpatialComparable mbr) {
+ final int dim = dimensionality(mbr, v);
+ double agg = 0.;
+ for (int d = 0; d < dim; d++) {
+ final double value = v.doubleValue(d), min = mbr.getMin(d);
+ final double diff;
+ if (value < min) {
+ diff = min - value;
+ } else {
+ final double max = mbr.getMax(d);
+ if (value > max) {
+ diff = value - max;
+ } else {
+ continue;
+ }
+ }
+ agg += diff * diff;
+ }
+ return Math.sqrt(agg);
+ }
+
+ @Override
+ public double doubleMinDist(SpatialComparable mbr1, SpatialComparable mbr2) {
+ // Some optimizations for simpler cases.
+ if (mbr1 instanceof NumberVector) {
+ if (mbr2 instanceof NumberVector) {
+ return doubleDistance((NumberVector<?>) mbr1, (NumberVector<?>) mbr2);
+ } else {
+ return doubleMinDistObject((NumberVector<?>) mbr1, mbr2);
+ }
+ } else if (mbr2 instanceof NumberVector) {
+ return doubleMinDistObject((NumberVector<?>) mbr2, mbr1);
+ }
+ final int dim = dimensionality(mbr1, mbr2);
+
+ double agg = 0.;
+ for (int d = 0; d < dim; d++) {
+ final double diff;
+ final double d1 = mbr2.getMin(d) - mbr1.getMax(d);
+ if (d1 > 0.) {
+ diff = d1;
+ } else {
+ final double d2 = mbr1.getMin(d) - mbr2.getMax(d);
+ if (d2 > 0.) {
+ diff = d2;
+ } else {
+ continue;
+ }
+ }
+ agg += diff * diff;
+ }
+ return Math.sqrt(agg);
+ }
+
+ @Override
+ public boolean isMetric() {
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "EuclideanDistance";
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (obj == this) {
+ return true;
+ }
+ if (this.getClass().equals(obj.getClass())) {
+ return true;
+ }
+ return super.equals(obj);
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected EuclideanDistanceFunction makeInstance() {
+ return EuclideanDistanceFunction.STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/LPNormDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/LPNormDistanceFunction.java
index 98b9929a..c25e04f1 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/LPNormDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/LPNormDistanceFunction.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.distance.distancefunction;
+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) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,9 +25,8 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
-import de.lmu.ifi.dbs.elki.database.query.distance.SpatialPrimitiveDistanceQuery;
-import de.lmu.ifi.dbs.elki.database.relation.Relation;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractSpatialDoubleDistanceNorm;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
@@ -41,16 +40,17 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleParameter;
*
* @apiviz.landmark
*/
-public class LPNormDistanceFunction extends AbstractVectorDoubleDistanceNorm implements SpatialPrimitiveDoubleDistanceFunction<NumberVector<?>> {
+@Alias({ "lp", "minkowski", "p", "de.lmu.ifi.dbs.elki.distance.distancefunction.LPNormDistanceFunction" })
+public class LPNormDistanceFunction extends AbstractSpatialDoubleDistanceNorm {
/**
* OptionID for the "p" parameter
*/
public static final OptionID P_ID = new OptionID("lpnorm.p", "the degree of the L-P-Norm (positive number)");
/**
- * Keeps the currently set p.
+ * Keeps the currently set p and its inverse
*/
- private double p;
+ protected double p, invp;
/**
* Constructor, internal version.
@@ -60,89 +60,60 @@ public class LPNormDistanceFunction extends AbstractVectorDoubleDistanceNorm imp
public LPNormDistanceFunction(double p) {
super();
this.p = p;
+ this.invp = 1. / p;
}
- /**
- * Returns the distance between the specified FeatureVectors as a LP-Norm for
- * the currently set p.
- *
- * @param v1 first FeatureVector
- * @param v2 second FeatureVector
- * @return the distance between the specified FeatureVectors as a LP-Norm for
- * the currently set p
- */
@Override
public double doubleDistance(NumberVector<?> v1, NumberVector<?> v2) {
- final int dim1 = v1.getDimensionality();
- if(dim1 != v2.getDimensionality()) {
- throw new IllegalArgumentException("Different dimensionality of FeatureVectors\n first argument: " + v1.toString() + "\n second argument: " + v2.toString());
- }
-
- double sqrDist = 0;
- for(int i = 0; i < dim1; i++) {
- final double delta = Math.abs(v1.doubleValue(i) - v2.doubleValue(i));
- sqrDist += Math.pow(delta, p);
+ final int dim = dimensionality(v1, v2);
+ double agg = 0.;
+ for (int d = 0; d < dim; 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);
}
- return Math.pow(sqrDist, 1.0 / p);
+ return Math.pow(agg, invp);
}
@Override
public double doubleNorm(NumberVector<?> v) {
final int dim = v.getDimensionality();
- double sqrDist = 0;
- for(int i = 0; i < dim; i++) {
- final double delta = v.doubleValue(i);
- sqrDist += Math.pow(delta, p);
+ double agg = 0.;
+ for (int d = 0; d < dim; d++) {
+ final double xd = v.doubleValue(d);
+ agg += Math.pow(xd >= 0. ? xd : -xd, p);
}
- return Math.pow(sqrDist, 1.0 / p);
- }
-
- /**
- * Get the functions p parameter.
- *
- * @return p
- */
- public double getP() {
- return p;
+ return Math.pow(agg, invp);
}
@Override
public double doubleMinDist(SpatialComparable mbr1, SpatialComparable mbr2) {
// Optimization for the simplest case
- if(mbr1 instanceof NumberVector) {
- if(mbr2 instanceof NumberVector) {
+ if (mbr1 instanceof NumberVector) {
+ if (mbr2 instanceof NumberVector) {
return doubleDistance((NumberVector<?>) mbr1, (NumberVector<?>) mbr2);
}
}
// TODO: optimize for more simpler cases: obj vs. rect?
- final int dim1 = mbr1.getDimensionality();
- if(dim1 != mbr2.getDimensionality()) {
- throw new IllegalArgumentException("Different dimensionality of objects\n " + "first argument: " + mbr1.toString() + "\n " + "second argument: " + mbr2.toString());
- }
-
- double sumDist = 0;
- for(int d = 0; d < dim1; d++) {
- final double m1, m2;
- if(mbr1.getMax(d) < mbr2.getMin(d)) {
- m1 = mbr2.getMin(d);
- m2 = mbr1.getMax(d);
- }
- else if(mbr1.getMin(d) > mbr2.getMax(d)) {
- m1 = mbr1.getMin(d);
- m2 = mbr2.getMax(d);
+ final int dim = dimensionality(mbr1, mbr2);
+
+ double agg = 0.;
+ for (int d = 0; d < dim; d++) {
+ final double diff;
+ final double d1 = mbr2.getMin(d) - mbr1.getMax(d);
+ if (d1 > 0.) {
+ diff = d1;
+ } else {
+ final double d2 = mbr1.getMin(d) - mbr2.getMax(d);
+ if (d2 > 0.) {
+ diff = d2;
+ } else { // The mbrs intersect!
+ continue;
+ }
}
- else { // The mbrs intersect!
- continue;
- }
- final double manhattanI = m1 - m2;
- sumDist += Math.pow(manhattanI, p);
+ agg += Math.pow(diff, p);
}
- return Math.pow(sumDist, 1.0 / p);
- }
-
- @Override
- public DoubleDistance minDist(SpatialComparable mbr1, SpatialComparable mbr2) {
- return new DoubleDistance(doubleMinDist(mbr1, mbr2));
+ return Math.pow(agg, invp);
}
@Override
@@ -152,25 +123,29 @@ public class LPNormDistanceFunction extends AbstractVectorDoubleDistanceNorm imp
@Override
public String toString() {
- return "L_" + p + " Norm";
+ return "L_" + p + "Norm";
+ }
+
+ /**
+ * Get the functions p parameter.
+ *
+ * @return p
+ */
+ public double getP() {
+ return p;
}
@Override
public boolean equals(Object obj) {
- if(obj == null) {
+ if (obj == null) {
return false;
}
- if(obj instanceof LPNormDistanceFunction) {
+ if (obj instanceof LPNormDistanceFunction) {
return this.p == ((LPNormDistanceFunction) obj).p;
}
return false;
}
- @Override
- public <T extends NumberVector<?>> SpatialPrimitiveDistanceQuery<T, DoubleDistance> instantiate(Relation<T> relation) {
- return new SpatialPrimitiveDistanceQuery<T, DoubleDistance>(relation, this);
- }
-
/**
* Parameterization class.
*
@@ -182,30 +157,30 @@ public class LPNormDistanceFunction extends AbstractVectorDoubleDistanceNorm imp
/**
* The value of p.
*/
- protected double p = 0.0;
+ protected double p;
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
final DoubleParameter paramP = new DoubleParameter(P_ID);
- paramP.addConstraint(new GreaterConstraint(0));
- if(config.grab(paramP)) {
+ paramP.addConstraint(new GreaterConstraint(0.));
+ if (config.grab(paramP)) {
p = paramP.getValue();
}
}
@Override
protected LPNormDistanceFunction makeInstance() {
- if(p == 1.0) {
+ if (p == 1.0) {
return ManhattanDistanceFunction.STATIC;
}
- if(p == 2.0) {
+ if (p == 2.0) {
return EuclideanDistanceFunction.STATIC;
}
- if(p == Double.POSITIVE_INFINITY) {
+ if (p == Double.POSITIVE_INFINITY) {
return MaximumDistanceFunction.STATIC;
}
return new LPNormDistanceFunction(p);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/ManhattanDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/ManhattanDistanceFunction.java
index a97ef086..9b8f80a7 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/ManhattanDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/ManhattanDistanceFunction.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.distance.distancefunction;
+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) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,6 +25,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
/**
@@ -33,8 +34,8 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
*
* @author Arthur Zimek
*/
-// TODO: add spatial!
-public class ManhattanDistanceFunction extends LPNormDistanceFunction implements SpatialPrimitiveDoubleDistanceFunction<NumberVector<?>> {
+@Alias({ "taxicab", "cityblock", "l1", "ManhattanDistanceFunction", "de.lmu.ifi.dbs.elki.distance.distancefunction.ManhattanDistanceFunction" })
+public class ManhattanDistanceFunction extends LPNormDistanceFunction {
/**
* The static instance to use.
*/
@@ -48,67 +49,47 @@ public class ManhattanDistanceFunction extends LPNormDistanceFunction implements
*/
@Deprecated
public ManhattanDistanceFunction() {
- super(1.0);
+ super(1.);
}
- /**
- * Compute the Manhattan distance.
- *
- * @param v1 first vector
- * @param v2 second vector
- * @return Manhattan distance value
- */
@Override
public double doubleDistance(NumberVector<?> v1, NumberVector<?> v2) {
- final int dim = v1.getDimensionality();
- if (dim != v2.getDimensionality()) {
- throw new IllegalArgumentException("Different dimensionality of FeatureVectors" + "\n first argument: " + v1.toString() + "\n second argument: " + v2.toString());
- }
- double sum = 0;
- for (int i = 0; i < dim; i++) {
- sum += Math.abs(v1.doubleValue(i) - v2.doubleValue(i));
+ final int dim = dimensionality(v1, v2);
+ double agg = 0.;
+ for (int d = 0; d < dim; d++) {
+ final double xd = v1.doubleValue(d), yd = v2.doubleValue(d);
+ final double val = (xd >= yd) ? xd - yd : yd - xd;
+ agg += val;
}
- return sum;
+ return agg;
}
- /**
- * Returns the Manhattan norm of the given vector.
- *
- * @param v the vector to compute the norm of
- * @return the Manhattan norm of the given vector
- */
@Override
public double doubleNorm(NumberVector<?> v) {
final int dim = v.getDimensionality();
- double sum = 0;
- for (int i = 0; i < dim; i++) {
- sum += Math.abs(v.doubleValue(i));
+ double agg = 0.;
+ for (int d = 0; d < dim; d++) {
+ final double xd = v.doubleValue(d);
+ agg += (xd >= 0.) ? xd : -xd;
}
- return sum;
+ return agg;
}
- private double doubleMinDistObject(SpatialComparable mbr, NumberVector<?> v) {
- final int dim = mbr.getDimensionality();
- if (dim != v.getDimensionality()) {
- throw new IllegalArgumentException("Different dimensionality of objects\n " + "first argument: " + mbr.toString() + "\n " + "second argument: " + v.toString() + "\n" + dim + "!=" + v.getDimensionality());
- }
-
- double sumDist = 0;
+ protected double doubleMinDistObject(NumberVector<?> v, SpatialComparable mbr) {
+ final int dim = dimensionality(mbr, v);
+ double agg = 0.;
for (int d = 0; d < dim; d++) {
- final double value = v.doubleValue(d);
- final double r;
- if (value < mbr.getMin(d)) {
- r = mbr.getMin(d);
- } else if (value > mbr.getMax(d)) {
- r = mbr.getMax(d);
+ final double value = v.doubleValue(d), min = mbr.getMin(d);
+ if (value < min) {
+ agg += min - value;
} else {
- r = value;
+ final double max = mbr.getMax(d);
+ if (value > max) {
+ agg += value - max;
+ }
}
-
- final double manhattanI = Math.abs(value - r);
- sumDist += manhattanI;
}
- return sumDist;
+ return agg;
}
@Override
@@ -118,32 +99,26 @@ public class ManhattanDistanceFunction extends LPNormDistanceFunction implements
if (mbr2 instanceof NumberVector) {
return doubleDistance((NumberVector<?>) mbr1, (NumberVector<?>) mbr2);
} else {
- return doubleMinDistObject(mbr2, (NumberVector<?>) mbr1);
+ return doubleMinDistObject((NumberVector<?>) mbr1, mbr2);
}
} else if (mbr2 instanceof NumberVector) {
- return doubleMinDistObject(mbr1, (NumberVector<?>) mbr2);
- }
- final int dim1 = mbr1.getDimensionality();
- if (dim1 != mbr2.getDimensionality()) {
- throw new IllegalArgumentException("Different dimensionality of objects\n " + "first argument: " + mbr1.toString() + "\n " + "second argument: " + mbr2.toString());
+ return doubleMinDistObject((NumberVector<?>) mbr2, mbr1);
}
+ final int dim = dimensionality(mbr1, mbr2);
- double sumDist = 0;
- for (int d = 0; d < dim1; d++) {
- final double m1, m2;
- if (mbr1.getMax(d) < mbr2.getMin(d)) {
- m1 = mbr2.getMin(d);
- m2 = mbr1.getMax(d);
- } else if (mbr1.getMin(d) > mbr2.getMax(d)) {
- m1 = mbr1.getMin(d);
- m2 = mbr2.getMax(d);
- } else { // The mbrs intersect!
- continue;
+ double agg = 0.;
+ for (int d = 0; d < dim; d++) {
+ final double d1 = mbr2.getMin(d) - mbr1.getMax(d);
+ if (d1 > 0.) {
+ agg += d1;
+ } else {
+ final double d2 = mbr1.getMin(d) - mbr2.getMax(d);
+ if (d2 > 0.) {
+ agg += d2;
+ }
}
- final double manhattanI = m1 - m2;
- sumDist += manhattanI;
}
- return sumDist;
+ return agg;
}
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/MaximumDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/MaximumDistanceFunction.java
index 30b47c9d..1b54e278 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/MaximumDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/MaximumDistanceFunction.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.distance.distancefunction;
+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) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,6 +25,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
/**
@@ -33,7 +34,8 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
*
* @author Erich Schubert
*/
-public class MaximumDistanceFunction extends LPNormDistanceFunction implements SpatialPrimitiveDoubleDistanceFunction<NumberVector<?>> {
+@Alias({ "maximum", "max", "chebyshev", "de.lmu.ifi.dbs.elki.distance.distancefunction.MaximumDistanceFunction" })
+public class MaximumDistanceFunction extends LPNormDistanceFunction {
/**
* Static instance.
*/
@@ -52,50 +54,62 @@ public class MaximumDistanceFunction extends LPNormDistanceFunction implements S
@Override
public double doubleDistance(NumberVector<?> v1, NumberVector<?> v2) {
- final int dim1 = v1.getDimensionality();
- if(dim1 != v2.getDimensionality()) {
- throw new IllegalArgumentException("Different dimensionality of FeatureVectors" + "\n first argument: " + v1.toString() + "\n second argument: " + v2.toString());
- }
- double max = 0;
- for(int i = 0; i < dim1; i++) {
- final double d = Math.abs(v1.doubleValue(i) - v2.doubleValue(i));
- max = Math.max(d, max);
+ final int dim = dimensionality(v1, v2);
+ double agg = 0.;
+ for (int d = 0; d < dim; d++) {
+ final double xd = v1.doubleValue(d), yd = v2.doubleValue(d);
+ final double val = (xd >= yd) ? xd - yd : yd - xd;
+ if (val > agg) {
+ agg = val;
+ }
}
- return max;
+ return agg;
}
@Override
public double doubleNorm(NumberVector<?> v) {
final int dim = v.getDimensionality();
- double max = 0;
- for(int i = 0; i < dim; i++) {
- max = Math.max(v.doubleValue(i), max);
+ double agg = 0.;
+ for (int d = 0; d < dim; d++) {
+ final double xd = v.doubleValue(d);
+ final double val = (xd >= 0.) ? xd : -xd;
+ if (val > agg) {
+ agg = val;
+ }
}
- return max;
+ return agg;
}
@Override
public double doubleMinDist(SpatialComparable mbr1, SpatialComparable mbr2) {
- final int dim1 = mbr1.getDimensionality();
- if(dim1 != mbr2.getDimensionality()) {
- throw new IllegalArgumentException("Different dimensionality of objects.");
- }
- double max = 0;
- for(int i = 0; i < dim1; i++) {
- final double d;
- if(mbr1.getMax(i) < mbr2.getMin(i)) {
- d = mbr2.getMin(i) - mbr1.getMin(i);
+ // Some optimizations for simpler cases.
+ if (mbr1 instanceof NumberVector) {
+ if (mbr2 instanceof NumberVector) {
+ return doubleDistance((NumberVector<?>) mbr1, (NumberVector<?>) mbr2);
}
- else if(mbr1.getMin(i) > mbr2.getMax(i)) {
- d = mbr1.getMin(i) - mbr2.getMax(i);
+ }
+ // TODO: add optimization for point to MBR?
+ final int dim = dimensionality(mbr1, mbr2);
+ double agg = 0.;
+ for (int d = 0; d < dim; d++) {
+ final double diff;
+ final double d1 = mbr2.getMin(d) - mbr1.getMax(d);
+ if (d1 > 0.) {
+ diff = d1;
+ } else {
+ final double d2 = mbr1.getMin(d) - mbr2.getMax(d);
+ if (d2 > 0.) {
+ diff = d2;
+ } else {
+ // The objects overlap in this dimension.
+ continue;
+ }
}
- else {
- // The object overlap in this dimension.
- continue;
+ if (diff > agg) {
+ agg = diff;
}
- max = Math.max(d, max);
}
- return max;
+ return agg;
}
@Override
@@ -110,13 +124,13 @@ public class MaximumDistanceFunction extends LPNormDistanceFunction implements S
@Override
public boolean equals(Object obj) {
- if(obj == null) {
+ if (obj == null) {
return false;
}
- if(obj == this) {
+ if (obj == this) {
return true;
}
- if(this.getClass().equals(obj.getClass())) {
+ if (this.getClass().equals(obj.getClass())) {
return true;
}
return super.equals(obj);
@@ -135,4 +149,4 @@ public class MaximumDistanceFunction extends LPNormDistanceFunction implements S
return MaximumDistanceFunction.STATIC;
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/MinimumDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/MinimumDistanceFunction.java
index a336c126..552e3139 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/MinimumDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/MinimumDistanceFunction.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.distance.distancefunction;
+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) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,9 +25,8 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
-import de.lmu.ifi.dbs.elki.database.query.distance.SpatialPrimitiveDistanceQuery;
-import de.lmu.ifi.dbs.elki.database.relation.Relation;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractSpatialDoubleDistanceNorm;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
/**
@@ -36,8 +35,8 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
*
* @author Erich Schubert
*/
-// TODO: add spatial?
-public class MinimumDistanceFunction extends AbstractVectorDoubleDistanceNorm implements SpatialPrimitiveDoubleDistanceFunction<NumberVector<?>> {
+@Alias({ "minimum", "min", "de.lmu.ifi.dbs.elki.distance.distancefunction.MinimumDistanceFunction" })
+public class MinimumDistanceFunction extends AbstractSpatialDoubleDistanceNorm {
/**
* Static instance. Use this.
*/
@@ -56,60 +55,67 @@ public class MinimumDistanceFunction extends AbstractVectorDoubleDistanceNorm im
@Override
public double doubleDistance(NumberVector<?> v1, NumberVector<?> v2) {
- final int dim = v1.getDimensionality();
- if(dim != v2.getDimensionality()) {
- throw new IllegalArgumentException("Different dimensionality of FeatureVectors" + "\n first argument: " + v1.toString() + "\n second argument: " + v2.toString());
- }
- double min = Double.MAX_VALUE;
- for(int i = 0; i < dim; i++) {
- final double d = Math.abs(v1.doubleValue(i) - v2.doubleValue(i));
- min = Math.min(d, min);
+ final int dim = dimensionality(v1, v2);
+ double agg = Double.POSITIVE_INFINITY;
+ for (int d = 0; d < dim; d++) {
+ final double xd = v1.doubleValue(d), yd = v2.doubleValue(d);
+ final double val = (xd >= yd) ? xd - yd : yd - xd;
+ if (val < agg) {
+ agg = val;
+ }
}
- return min;
+ return agg;
}
@Override
public double doubleNorm(NumberVector<?> v) {
final int dim = v.getDimensionality();
- double min = Double.POSITIVE_INFINITY;
- for(int i = 0; i < dim; i++) {
- min = Math.min(v.doubleValue(i), min);
+ double agg = Double.POSITIVE_INFINITY;
+ for (int d = 0; d < dim; d++) {
+ final double xd = v.doubleValue(d);
+ final double val = (xd >= 0.) ? xd : -xd;
+ if (val < agg) {
+ agg = val;
+ }
}
- return min;
+ return agg;
}
-
+
@Override
public double doubleMinDist(SpatialComparable mbr1, SpatialComparable mbr2) {
- final int dim = mbr1.getDimensionality();
- if(dim != mbr2.getDimensionality()) {
- throw new IllegalArgumentException("Different dimensionality of FeatureVectors" + "\n first argument: " + mbr1.toString() + "\n second argument: " + mbr2.toString());
- }
- double min = Double.MAX_VALUE;
- for(int i = 0; i < dim; i++) {
- final double min1 = mbr1.getMin(i);
- final double max1 = mbr1.getMax(i);
- final double min2 = mbr2.getMin(i);
- final double max2 = mbr2.getMax(i);
- final double d;
- if(max1 <= min2) {
- d = min2 - max1;
+ // Some optimizations for simpler cases.
+ if (mbr1 instanceof NumberVector) {
+ if (mbr2 instanceof NumberVector) {
+ return doubleDistance((NumberVector<?>) mbr1, (NumberVector<?>) mbr2);
}
- else if(max2 <= min1) {
- d = min1 - max2;
+ }
+ // TODO: add optimization for point to MBR?
+ final int dim = dimensionality(mbr1, mbr2);
+ double agg = Double.POSITIVE_INFINITY;
+ for (int d = 0; d < dim; d++) {
+ final double diff;
+ final double d1 = mbr2.getMin(d) - mbr1.getMax(d);
+ if (d1 > 0.) {
+ diff = d1;
+ } else {
+ final double d2 = mbr1.getMin(d) - mbr2.getMax(d);
+ if (d2 > 0.) {
+ diff = d2;
+ } else {
+ // The objects overlap in this dimension.
+ return 0.;
+ }
}
- else {
- // Overlap in this dimension
- min = 0.0;
- break;
+ if (diff < agg) {
+ agg = diff;
}
- min = Math.min(d, min);
}
- return min;
+ return agg;
}
@Override
- public DoubleDistance minDist(SpatialComparable mbr1, SpatialComparable mbr2) {
- return new DoubleDistance(doubleMinDist(mbr1, mbr2));
+ public boolean isMetric() {
+ return false;
}
@Override
@@ -118,19 +124,17 @@ public class MinimumDistanceFunction extends AbstractVectorDoubleDistanceNorm im
}
@Override
- public <T extends NumberVector<?>> SpatialPrimitiveDistanceQuery<T, DoubleDistance> instantiate(Relation<T> relation) {
- return new SpatialPrimitiveDistanceQuery<T, DoubleDistance>(relation, this);
- }
-
- @Override
public boolean equals(Object obj) {
- if(obj == null) {
+ if (obj == null) {
return false;
}
- if(obj == this) {
+ if (obj == this) {
+ return true;
+ }
+ if (this.getClass().equals(obj.getClass())) {
return true;
}
- return this.getClass().equals(obj.getClass());
+ return super.equals(obj);
}
/**
@@ -146,4 +150,4 @@ public class MinimumDistanceFunction extends AbstractVectorDoubleDistanceNorm im
return MinimumDistanceFunction.STATIC;
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/SparseEuclideanDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/SparseEuclideanDistanceFunction.java
index 8d68eb1d..bf621103 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/SparseEuclideanDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/SparseEuclideanDistanceFunction.java
@@ -1,9 +1,10 @@
-package de.lmu.ifi.dbs.elki.distance.distancefunction;
+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) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -37,7 +38,7 @@ public class SparseEuclideanDistanceFunction extends SparseLPNormDistanceFunctio
* Static instance
*/
public static final SparseEuclideanDistanceFunction STATIC = new SparseEuclideanDistanceFunction();
-
+
/**
* Constructor.
*
@@ -53,44 +54,45 @@ public class SparseEuclideanDistanceFunction extends SparseLPNormDistanceFunctio
// Get the bit masks
BitSet b1 = v1.getNotNullMask();
BitSet b2 = v2.getNotNullMask();
- double sqrDist = 0;
+ double accu = 0;
int i1 = b1.nextSetBit(0);
int i2 = b2.nextSetBit(0);
- while(i1 >= 0 && i2 >= 0) {
- if(i1 == i2) {
- // Set in both
- double manhattanI = v1.doubleValue(i1) - v2.doubleValue(i2);
- sqrDist += manhattanI * manhattanI;
+ while (true) {
+ if (i1 == i2) {
+ if (i1 < 0) {
+ break;
+ }
+ // Both vectors have a value.
+ double val = v1.doubleValue(i1) - v2.doubleValue(i2);
+ accu += val * val;
i1 = b1.nextSetBit(i1 + 1);
i2 = b2.nextSetBit(i2 + 1);
- }
- else if(i1 < i2 && i1 >= 0) {
+ } else if (i2 < 0 || (i1 < i2 && i1 >= 0)) {
// In first only
- double manhattanI = v1.doubleValue(i1);
- sqrDist += manhattanI * manhattanI;
+ double val = v1.doubleValue(i1);
+ accu += val * val;
i1 = b1.nextSetBit(i1 + 1);
- }
- else {
+ } else {
// In second only
- double manhattanI = v2.doubleValue(i2);
- sqrDist += manhattanI * manhattanI;
- i2 = b1.nextSetBit(i2 + 1);
+ double val = v2.doubleValue(i2);
+ accu += val * val;
+ i2 = b2.nextSetBit(i2 + 1);
}
}
- return Math.sqrt(sqrDist);
+ return Math.sqrt(accu);
}
@Override
public double doubleNorm(SparseNumberVector<?> v1) {
- double sqrDist = 0;
+ double accu = 0;
// Get the bit masks
BitSet b1 = v1.getNotNullMask();
// Set in first only
- for(int i = b1.nextSetBit(0); i >= 0; i = b1.nextSetBit(i + 1)) {
- double manhattanI = v1.doubleValue(i);
- sqrDist += manhattanI * manhattanI;
+ for (int i = b1.nextSetBit(0); i >= 0; i = b1.nextSetBit(i + 1)) {
+ double val = v1.doubleValue(i);
+ accu += val * val;
}
- return Math.sqrt(sqrDist);
+ return Math.sqrt(accu);
}
/**
@@ -106,4 +108,4 @@ public class SparseEuclideanDistanceFunction extends SparseLPNormDistanceFunctio
return SparseEuclideanDistanceFunction.STATIC;
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/SparseLPNormDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/SparseLPNormDistanceFunction.java
index b0cbc0dc..53d63ff8 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/SparseLPNormDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/SparseLPNormDistanceFunction.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.distance.distancefunction;
+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) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,6 +28,8 @@ import java.util.BitSet;
import de.lmu.ifi.dbs.elki.data.SparseNumberVector;
import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractPrimitiveDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.DoubleNorm;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
@@ -58,31 +60,32 @@ public class SparseLPNormDistanceFunction extends AbstractPrimitiveDistanceFunct
// Get the bit masks
BitSet b1 = v1.getNotNullMask();
BitSet b2 = v2.getNotNullMask();
- double sqrDist = 0;
+ double accu = 0;
int i1 = b1.nextSetBit(0);
int i2 = b2.nextSetBit(0);
- while(i1 >= 0 && i2 >= 0) {
- if(i1 == i2) {
- // Set in both
- double manhattanI = Math.abs(v1.doubleValue(i1) - v2.doubleValue(i2));
- sqrDist += Math.pow(manhattanI, p);
+ while (true) {
+ if (i1 == i2) {
+ if (i1 < 0) {
+ break;
+ }
+ // Both vectors have a value.
+ double val = Math.abs(v1.doubleValue(i1) - v2.doubleValue(i2));
+ accu += Math.pow(val, p);
i1 = b1.nextSetBit(i1 + 1);
i2 = b2.nextSetBit(i2 + 1);
- }
- else if(i1 < i2 && i1 >= 0) {
+ } else if (i2 < 0 || (i1 < i2 && i1 >= 0)) {
// In first only
- double manhattanI = Math.abs(v1.doubleValue(i1));
- sqrDist += Math.pow(manhattanI, p);
+ double val = Math.abs(v1.doubleValue(i1));
+ accu += Math.pow(val, p);
i1 = b1.nextSetBit(i1 + 1);
- }
- else {
+ } else {
// In second only
- double manhattanI = Math.abs(v2.doubleValue(i2));
- sqrDist += Math.pow(manhattanI, p);
- i2 = b1.nextSetBit(i2 + 1);
+ double val = Math.abs(v2.doubleValue(i2));
+ accu += Math.pow(val, p);
+ i2 = b2.nextSetBit(i2 + 1);
}
}
- return Math.pow(sqrDist, 1.0 / p);
+ return Math.pow(accu, 1.0 / p);
}
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/SparseManhattanDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/SparseManhattanDistanceFunction.java
index 597dd6ca..4e397e0c 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/SparseManhattanDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/SparseManhattanDistanceFunction.java
@@ -1,9 +1,9 @@
-package de.lmu.ifi.dbs.elki.distance.distancefunction;
+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) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -53,29 +53,32 @@ public class SparseManhattanDistanceFunction extends SparseLPNormDistanceFunctio
// Get the bit masks
BitSet b1 = v1.getNotNullMask();
BitSet b2 = v2.getNotNullMask();
- double sqrDist = 0;
+ double accu = 0;
int i1 = b1.nextSetBit(0);
int i2 = b2.nextSetBit(0);
- while(i1 >= 0 && i2 >= 0) {
- if(i1 == i2) {
- // Set in both
- sqrDist += Math.abs(v1.doubleValue(i1) - v2.doubleValue(i2));
+ while (true) {
+ if (i1 == i2) {
+ if (i1 < 0) {
+ break;
+ }
+ // Both vectors have a value.
+ double val = Math.abs(v1.doubleValue(i1) - v2.doubleValue(i2));
+ accu += val;
i1 = b1.nextSetBit(i1 + 1);
i2 = b2.nextSetBit(i2 + 1);
- }
- else if(i1 < i2 && i1 >= 0) {
+ } else if (i2 < 0 || (i1 < i2 && i1 >= 0)) {
// In first only
- sqrDist += Math.abs(v1.doubleValue(i1));
+ double val = Math.abs(v1.doubleValue(i1));
+ accu += val;
i1 = b1.nextSetBit(i1 + 1);
- }
- else {
+ } else {
// In second only
- double manhattanI = Math.abs(v2.doubleValue(i2));
- sqrDist += manhattanI;
- i2 = b1.nextSetBit(i2 + 1);
+ double val = Math.abs(v2.doubleValue(i2));
+ accu += val;
+ i2 = b2.nextSetBit(i2 + 1);
}
}
- return sqrDist;
+ return accu;
}
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/SparseMaximumDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/SparseMaximumDistanceFunction.java
index 720b8017..f01ae32b 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/SparseMaximumDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/SparseMaximumDistanceFunction.java
@@ -1,4 +1,4 @@
-package de.lmu.ifi.dbs.elki.distance.distancefunction;
+package de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski;
import java.util.BitSet;
@@ -8,7 +8,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -53,29 +53,32 @@ public class SparseMaximumDistanceFunction extends SparseLPNormDistanceFunction
// Get the bit masks
BitSet b1 = v1.getNotNullMask();
BitSet b2 = v2.getNotNullMask();
- double sqrDist = 0;
+ double accu = 0;
int i1 = b1.nextSetBit(0);
int i2 = b2.nextSetBit(0);
- while(i1 >= 0 && i2 >= 0) {
- if(i1 == i2) {
- // Set in both
- sqrDist = Math.max(sqrDist, Math.abs(v1.doubleValue(i1) - v2.doubleValue(i2)));
+ while (true) {
+ if (i1 == i2) {
+ if (i1 < 0) {
+ break;
+ }
+ // Both vectors have a value.
+ double val = Math.abs(v1.doubleValue(i1) - v2.doubleValue(i2));
+ accu = Math.max(accu, val);
i1 = b1.nextSetBit(i1 + 1);
i2 = b2.nextSetBit(i2 + 1);
- }
- else if(i1 < i2 && i1 >= 0) {
+ } else if (i2 < 0 || (i1 < i2 && i1 >= 0)) {
// In first only
- sqrDist = Math.max(sqrDist, Math.abs(v1.doubleValue(i1)));
+ double val = Math.abs(v1.doubleValue(i1));
+ accu = Math.max(accu, val);
i1 = b1.nextSetBit(i1 + 1);
- }
- else {
+ } else {
// In second only
- double manhattanI = Math.abs(v2.doubleValue(i2));
- sqrDist = Math.max(sqrDist, manhattanI);
- i2 = b1.nextSetBit(i2 + 1);
+ double val = Math.abs(v2.doubleValue(i2));
+ accu = Math.max(accu, val);
+ i2 = b2.nextSetBit(i2 + 1);
}
}
- return sqrDist;
+ return accu;
}
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/SquaredEuclideanDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/SquaredEuclideanDistanceFunction.java
new file mode 100644
index 00000000..8f02e40b
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/SquaredEuclideanDistanceFunction.java
@@ -0,0 +1,166 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractSpatialDoubleDistanceNorm;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Provides the squared Euclidean distance for FeatureVectors. This results in
+ * the same rankings, but saves computing the square root as often.
+ *
+ * @author Arthur Zimek
+ */
+@Alias({ "squaredeuclidean", "de.lmu.ifi.dbs.elki.distance.distancefunction.SquaredEuclideanDistanceFunction" })
+public class SquaredEuclideanDistanceFunction extends AbstractSpatialDoubleDistanceNorm {
+ /**
+ * Static instance. Use this!
+ */
+ public static final SquaredEuclideanDistanceFunction STATIC = new SquaredEuclideanDistanceFunction();
+
+ /**
+ * Provides a Euclidean distance function that can compute the Euclidean
+ * distance (that is a DoubleDistance) for FeatureVectors.
+ *
+ * @deprecated Use static instance!
+ */
+ @Deprecated
+ public SquaredEuclideanDistanceFunction() {
+ super();
+ }
+
+ @Override
+ public double doubleDistance(NumberVector<?> v1, NumberVector<?> v2) {
+ final int dim = dimensionality(v1, v2);
+ double agg = 0.;
+ for (int d = 0; d < dim; d++) {
+ final double delta = v1.doubleValue(d) - v2.doubleValue(d);
+ agg += delta * delta;
+ }
+ 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 val = v.doubleValue(d);
+ agg += val * val;
+ }
+ return agg;
+ }
+
+ protected double doubleMinDistObject(NumberVector<?> v, SpatialComparable mbr) {
+ final int dim = dimensionality(mbr, v);
+ double agg = 0.;
+ for (int d = 0; d < dim; d++) {
+ final double value = v.doubleValue(d), min = mbr.getMin(d);
+ final double diff;
+ if (value < min) {
+ diff = min - value;
+ } else {
+ final double max = mbr.getMax(d);
+ if (value > max) {
+ diff = value - max;
+ } else {
+ continue;
+ }
+ }
+ agg += diff * diff;
+ }
+ return agg;
+ }
+
+ @Override
+ public double doubleMinDist(SpatialComparable mbr1, SpatialComparable mbr2) {
+ // Some optimizations for simpler cases.
+ if (mbr1 instanceof NumberVector) {
+ if (mbr2 instanceof NumberVector) {
+ return doubleDistance((NumberVector<?>) mbr1, (NumberVector<?>) mbr2);
+ } else {
+ return doubleMinDistObject((NumberVector<?>) mbr1, mbr2);
+ }
+ } else if (mbr2 instanceof NumberVector) {
+ return doubleMinDistObject((NumberVector<?>) mbr2, mbr1);
+ }
+ final int dim = dimensionality(mbr1, mbr2);
+
+ double agg = 0.;
+ for (int d = 0; d < dim; d++) {
+ final double diff;
+ final double d1 = mbr2.getMin(d) - mbr1.getMax(d);
+ if (d1 > 0.) {
+ diff = d1;
+ } else {
+ final double d2 = mbr1.getMin(d) - mbr2.getMax(d);
+ if (d2 > 0.) {
+ diff = d2;
+ } else {
+ continue;
+ }
+ }
+ agg += diff * diff;
+ }
+ return agg;
+ }
+
+ @Override
+ public boolean isMetric() {
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return "SquaredEuclideanDistance";
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (obj == this) {
+ return true;
+ }
+ return this.getClass().equals(obj.getClass());
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected SquaredEuclideanDistanceFunction makeInstance() {
+ return SquaredEuclideanDistanceFunction.STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/WeightedEuclideanDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/WeightedEuclideanDistanceFunction.java
new file mode 100644
index 00000000..2bc85aae
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/WeightedEuclideanDistanceFunction.java
@@ -0,0 +1,124 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.Arrays;
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+
+/**
+ * Provides the Euclidean distance for FeatureVectors.
+ *
+ * @author Erich Schubert
+ */
+public class WeightedEuclideanDistanceFunction extends WeightedLPNormDistanceFunction {
+ /**
+ * Constructor.
+ *
+ * @param weights
+ */
+ public WeightedEuclideanDistanceFunction(double[] weights) {
+ super(2.0, weights);
+ }
+
+ /**
+ * Provides the Euclidean distance between the given two vectors.
+ *
+ * @return the Euclidean distance between the given two vectors as raw double
+ * value
+ */
+ @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 = (v1.doubleValue(d) - v2.doubleValue(d));
+ agg += delta * delta * weights[d];
+ }
+ return Math.sqrt(agg);
+ }
+
+ @Override
+ public double doubleNorm(NumberVector<?> obj) {
+ final int dim = obj.getDimensionality();
+ double agg = 0.;
+ for (int d = 0; d < dim; d++) {
+ final double delta = obj.doubleValue(dim);
+ agg += delta * delta * weights[d];
+ }
+ return Math.sqrt(agg);
+ }
+
+ @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);
+ }
+ }
+ // 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;
+ }
+ agg += diff * diff * weights[d];
+ }
+ return Math.sqrt(agg);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof WeightedEuclideanDistanceFunction)) {
+ if (obj.getClass().equals(WeightedLPNormDistanceFunction.class)) {
+ return super.equals(obj);
+ }
+ if (obj.getClass().equals(EuclideanDistanceFunction.class)) {
+ for (double d : weights) {
+ if (d != 1.0) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+ WeightedEuclideanDistanceFunction other = (WeightedEuclideanDistanceFunction) obj;
+ return Arrays.equals(this.weights, other.weights);
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/WeightedLPNormDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/WeightedLPNormDistanceFunction.java
index 6a76366f..3d49c95a 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/WeightedLPNormDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/WeightedLPNormDistanceFunction.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.distance.distancefunction;
+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) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,7 +29,7 @@ import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
/**
- * Weighted version of the Euclidean distance function.
+ * Weighted version of the Minkowski L_p metrics distance function.
*
* @author Erich Schubert
*/
@@ -53,70 +53,63 @@ public class WeightedLPNormDistanceFunction extends LPNormDistanceFunction {
@Override
public double doubleDistance(NumberVector<?> v1, NumberVector<?> v2) {
- final int dim = weights.length;
- if(dim != v1.getDimensionality()) {
- throw new IllegalArgumentException("Dimensionality of FeatureVector doesn't match weights!");
- }
- if(dim != v2.getDimensionality()) {
- throw new IllegalArgumentException("Dimensionality of FeatureVector doesn't match weights!");
+ 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));
+ agg += Math.pow(delta, p) * weights[d];
}
+ return Math.pow(agg, invp);
+ }
- final double p = getP();
- double sqrDist = 0;
- for(int i = 0; i < dim; i++) {
- final double delta = Math.abs(v1.doubleValue(i) - v2.doubleValue(i));
- sqrDist += Math.pow(delta, p) * weights[i - 1];
+ @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));
+ agg += Math.pow(delta, p) * weights[d];
}
- return Math.pow(sqrDist, 1.0 / p);
+ return Math.pow(agg, invp);
}
-
+
@Override
public double doubleMinDist(SpatialComparable mbr1, SpatialComparable mbr2) {
// Optimization for the simplest case
- if(mbr1 instanceof NumberVector) {
- if(mbr2 instanceof NumberVector) {
+ if (mbr1 instanceof NumberVector) {
+ if (mbr2 instanceof NumberVector) {
return doubleDistance((NumberVector<?>) mbr1, (NumberVector<?>) mbr2);
}
}
// TODO: optimize for more simpler cases: obj vs. rect?
- final int dim1 = mbr1.getDimensionality();
- if(dim1 != mbr2.getDimensionality()) {
- throw new IllegalArgumentException("Different dimensionality of objects\n " + "first argument: " + mbr1.toString() + "\n " + "second argument: " + mbr2.toString());
- }
-
- final double p = getP();
- double sumDist = 0;
- for(int d = 0; d < dim1; d++) {
- final double m1, m2;
- if(mbr1.getMax(d) < mbr2.getMin(d)) {
- m1 = mbr2.getMin(d);
- m2 = mbr1.getMax(d);
- }
- else if(mbr1.getMin(d) > mbr2.getMax(d)) {
- m1 = mbr1.getMin(d);
- m2 = mbr2.getMax(d);
- }
- else { // The mbrs intersect!
+ 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;
}
- final double manhattanI = m1 - m2;
- sumDist += Math.pow(manhattanI, p) * weights[d - 1];
+ agg += Math.pow(diff, p) * weights[d];
}
- return Math.pow(sumDist, 1.0 / p);
+ return Math.pow(agg, invp);
}
@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.0) {
+ if (!(obj instanceof WeightedLPNormDistanceFunction)) {
+ if (obj instanceof LPNormDistanceFunction && super.equals(obj)) {
+ for (double d : weights) {
+ if (d != 1.0) {
return false;
}
}
@@ -127,4 +120,4 @@ public class WeightedLPNormDistanceFunction extends LPNormDistanceFunction {
WeightedLPNormDistanceFunction other = (WeightedLPNormDistanceFunction) obj;
return Arrays.equals(this.weights, other.weights);
}
-} \ No newline at end of file
+}
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
new file mode 100644
index 00000000..186f0435
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/WeightedManhattanDistanceFunction.java
@@ -0,0 +1,110 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.Arrays;
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+
+/**
+ * Weighted version of the Minkowski L_p metrics distance function.
+ *
+ * @author Erich Schubert
+ */
+public class WeightedManhattanDistanceFunction extends WeightedLPNormDistanceFunction {
+ /**
+ * Constructor.
+ *
+ * @param weights Weight vector
+ */
+ public WeightedManhattanDistanceFunction(double[] weights) {
+ super(1.0, 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));
+ 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));
+ agg += delta * weights[d];
+ }
+ return agg;
+ }
+
+ @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);
+ }
+ }
+ // 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;
+ }
+ agg += diff * weights[d];
+ }
+ return agg;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof WeightedManhattanDistanceFunction)) {
+ if (obj instanceof WeightedLPNormDistanceFunction) {
+ return super.equals(obj);
+ }
+ return false;
+ }
+ WeightedManhattanDistanceFunction other = (WeightedManhattanDistanceFunction) obj;
+ return Arrays.equals(this.weights, other.weights);
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/WeightedSquaredEuclideanDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/WeightedSquaredEuclideanDistanceFunction.java
index e00f8e07..4e361c10 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/WeightedSquaredEuclideanDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/WeightedSquaredEuclideanDistanceFunction.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.distance.distancefunction;
+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) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,6 +26,8 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
import java.util.Arrays;
import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractSpatialDoubleDistanceNorm;
/**
* Provides the squared Euclidean distance for FeatureVectors. This results in
@@ -33,7 +35,7 @@ import de.lmu.ifi.dbs.elki.data.NumberVector;
*
* @author Arthur Zimek
*/
-public class WeightedSquaredEuclideanDistanceFunction extends AbstractVectorDoubleDistanceFunction {
+public class WeightedSquaredEuclideanDistanceFunction extends AbstractSpatialDoubleDistanceNorm {
/**
* Weight array
*/
@@ -57,16 +59,49 @@ public class WeightedSquaredEuclideanDistanceFunction extends AbstractVectorDoub
*/
@Override
public double doubleDistance(NumberVector<?> v1, NumberVector<?> v2) {
- final int dim1 = v1.getDimensionality();
- if(dim1 != v2.getDimensionality()) {
- throw new IllegalArgumentException("Different dimensionality of FeatureVectors" + "\n first argument: " + v1.toString() + "\n second argument: " + v2.toString() + "\n" + v1.getDimensionality() + "!=" + v2.getDimensionality());
+ final int dim = dimensionality(v1, v2, weights.length);
+ double agg = 0.;
+ for (int d = 0; d < dim; d++) {
+ final double delta = (v1.doubleValue(d) - v2.doubleValue(d));
+ agg += delta * delta * weights[d];
}
- double sqrDist = 0;
- for(int i = 0; i < dim1; i++) {
- final double delta = v1.doubleValue(i) - v2.doubleValue(i);
- sqrDist += delta * delta * weights[i - 1];
+ return agg;
+ }
+
+ @Override
+ public double doubleNorm(NumberVector<?> obj) {
+ final int dim = obj.getDimensionality();
+ double agg = 0.;
+ for (int d = 0; d < dim; d++) {
+ final double delta = obj.doubleValue(dim);
+ agg += delta * delta * weights[d];
+ }
+ return agg;
+ }
+
+ @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);
+ }
+ }
+ // 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;
+ }
+ agg += diff * diff * weights[d];
}
- return sqrDist;
+ return agg;
}
@Override
@@ -76,16 +111,16 @@ public class WeightedSquaredEuclideanDistanceFunction extends AbstractVectorDoub
@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 WeightedSquaredEuclideanDistanceFunction)) {
- if(obj.getClass().equals(SquaredEuclideanDistanceFunction.class)) {
- for(double d : weights) {
- if(d != 1.0) {
+ if (!(obj instanceof WeightedSquaredEuclideanDistanceFunction)) {
+ if (obj.getClass().equals(SquaredEuclideanDistanceFunction.class)) {
+ for (double d : weights) {
+ if (d != 1.0) {
return false;
}
}
@@ -96,4 +131,4 @@ public class WeightedSquaredEuclideanDistanceFunction extends AbstractVectorDoub
WeightedSquaredEuclideanDistanceFunction other = (WeightedSquaredEuclideanDistanceFunction) obj;
return Arrays.equals(this.weights, other.weights);
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/iterator/package-info.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/package-info.java
index 9a889d1d..c52167f3 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/minkowski/package-info.java
@@ -1,11 +1,11 @@
/**
- * <p>Various {@link java.util.Iterator} decorators and adapters.</p>
+ * <p>Minkowski space L_p norms such as the popular Euclidean and Manhattan distances.</p>
*/
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,4 +23,4 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-package de.lmu.ifi.dbs.elki.utilities.iterator; \ No newline at end of file
+package de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski; \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/package-info.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/package-info.java
index f71ae4a2..19d72baf 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/package-info.java
@@ -42,7 +42,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/probabilistic/ChiSquaredDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/probabilistic/ChiSquaredDistanceFunction.java
new file mode 100644
index 00000000..3fb44680
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/probabilistic/ChiSquaredDistanceFunction.java
@@ -0,0 +1,135 @@
+package de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2011
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractSpatialDoubleDistanceFunction;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Chi-Squared distance function, symmetric version.
+ *
+ * Reference:
+ * <p>
+ * J. Puzicha, J.M. Buhmann, Y. Rubner, C. Tomasi<br />
+ * Empirical evaluation of dissimilarity measures for color and texture<br />
+ * Proc. 7th IEEE International Conference on Computer Vision
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@Alias("chisq")
+@Reference(authors = "J. Puzicha, J.M. Buhmann, Y. Rubner, C. Tomasi", title = "Empirical evaluation of dissimilarity measures for color and texture", booktitle = "Proc. 7th IEEE International Conference on Computer Vision", url = "http://dx.doi.org/10.1109/ICCV.1999.790412")
+public class ChiSquaredDistanceFunction extends AbstractSpatialDoubleDistanceFunction {
+ /**
+ * Static instance. Use this!
+ */
+ public static final ChiSquaredDistanceFunction STATIC = new ChiSquaredDistanceFunction();
+
+ /**
+ * Constructor for the Chi-Squared distance function.
+ *
+ * @deprecated Use static instance!
+ */
+ @Deprecated
+ public ChiSquaredDistanceFunction() {
+ super();
+ }
+
+ @Override
+ public double doubleDistance(NumberVector<?> v1, NumberVector<?> v2) {
+ final int dim = dimensionality(v1, v2);
+ double agg = 0.;
+ for (int d = 0; d < dim; d++) {
+ final double xd = v1.doubleValue(d), yd = v2.doubleValue(d);
+ final double di = xd - yd;
+ final double si = xd + yd;
+ if (!(si > 0. || si < 0.) || !(di > 0. || di < 0.)) {
+ continue;
+ }
+ agg += di * di / si;
+ }
+ return 2. * agg;
+ }
+
+ @Override
+ public double doubleMinDist(SpatialComparable mbr1, SpatialComparable mbr2) {
+ final int dim = dimensionality(mbr1, mbr2);
+ double agg = 0.;
+ for (int d = 0; d < dim; d++) {
+ final double min1 = mbr1.getMin(d), max1 = mbr1.getMax(d);
+ final double min2 = mbr2.getMin(d), max2 = mbr2.getMax(d);
+ final double diff; // Minimum difference
+ if (max1 < min2) {
+ diff = min2 - max1;
+ } else if (max2 < min1) {
+ diff = max2 - min1;
+ } else {
+ continue; // 0.
+ }
+ final double si = max1 + max2; // Maximum sum
+ if (!(si > 0. || si < 0.) || !(diff > 0. || diff < 0.)) {
+ continue;
+ }
+ agg += diff * diff / si;
+ }
+ return 2. * agg;
+ }
+
+ @Override
+ public String toString() {
+ return "ChiSquaredDistance";
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (obj == this) {
+ return true;
+ }
+ if (this.getClass().equals(obj.getClass())) {
+ return true;
+ }
+ return super.equals(obj);
+ }
+
+ /**
+ * Parameterization class, using the static instance.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected ChiSquaredDistanceFunction makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/probabilistic/JeffreyDivergenceDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/probabilistic/JeffreyDivergenceDistanceFunction.java
new file mode 100644
index 00000000..73b944cf
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/probabilistic/JeffreyDivergenceDistanceFunction.java
@@ -0,0 +1,137 @@
+package de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2011
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractSpatialDoubleDistanceFunction;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Provides the Jeffrey Divergence Distance for FeatureVectors.
+ *
+ * Reference:
+ * <p>
+ * J. Puzicha, J.M. Buhmann, Y. Rubner, C. Tomasi<br />
+ * Empirical evaluation of dissimilarity measures for color and texture<br />
+ * Proc. 7th IEEE International Conference on Computer Vision
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@Reference(authors = "J. Puzicha, J.M. Buhmann, Y. Rubner, C. Tomasi", title = "Empirical evaluation of dissimilarity measures for color and texture", booktitle = "Proc. 7th IEEE International Conference on Computer Vision", url = "http://dx.doi.org/10.1109/ICCV.1999.790412")
+public class JeffreyDivergenceDistanceFunction extends AbstractSpatialDoubleDistanceFunction {
+ /**
+ * Static instance. Use this!
+ */
+ public static final JeffreyDivergenceDistanceFunction STATIC = new JeffreyDivergenceDistanceFunction();
+
+ /**
+ * Constructor for the Jeffrey divergence.
+ *
+ * @deprecated Use static instance!
+ */
+ @Deprecated
+ public JeffreyDivergenceDistanceFunction() {
+ super();
+ }
+
+ @Override
+ public double doubleDistance(NumberVector<?> v1, NumberVector<?> v2) {
+ final int dim = dimensionality(v1, v2);
+ double agg = 0.;
+ for (int d = 0; d < dim; d++) {
+ final double xd = v1.doubleValue(d), yd = v2.doubleValue(d);
+ if (xd == yd) {
+ continue;
+ }
+ final double md = .5 * (xd + yd);
+ if (!(md > 0. || md < 0.)) {
+ continue;
+ }
+ if (xd > 0.) {
+ agg += xd * Math.log(xd / md);
+ }
+ if (yd > 0.) {
+ agg += yd * Math.log(yd / md);
+ }
+ }
+ return agg;
+ }
+
+ @Override
+ public double doubleMinDist(SpatialComparable mbr1, SpatialComparable mbr2) {
+ final int dim = dimensionality(mbr1, mbr2);
+ double agg = 0;
+ for (int d = 0; d < dim; d++) {
+ final double min1 = mbr1.getMin(d), max1 = mbr1.getMax(d);
+ final double min2 = mbr2.getMin(d), max2 = mbr2.getMax(d);
+ final double md = .5 * (max1 + max2);
+ if (!(md > 0. || md < 0.)) {
+ continue;
+ }
+ if (min1 > 0.) {
+ agg += min1 * Math.log(min1 / md);
+ }
+ if (min2 > 0.) {
+ agg += min2 * Math.log(min2 / md);
+ }
+ }
+ return agg;
+ }
+
+ @Override
+ public String toString() {
+ return "JeffreyDivergenceDistance";
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (obj == this) {
+ return true;
+ }
+ if (this.getClass().equals(obj.getClass())) {
+ return true;
+ }
+ return super.equals(obj);
+ }
+
+ /**
+ * Parameterization class, using the static instance.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected JeffreyDivergenceDistanceFunction makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/probabilistic/JensenShannonDivergenceDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/probabilistic/JensenShannonDivergenceDistanceFunction.java
new file mode 100644
index 00000000..d7692dcc
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/probabilistic/JensenShannonDivergenceDistanceFunction.java
@@ -0,0 +1,74 @@
+package de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2011
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Jensen-Shannon Divergence is essentially the same as Jeffrey divergence, only
+ * scaled by half.
+ *
+ * @author Erich Schubert
+ */
+public class JensenShannonDivergenceDistanceFunction extends JeffreyDivergenceDistanceFunction {
+ /**
+ * Static instance. Use this!
+ */
+ public static final JensenShannonDivergenceDistanceFunction STATIC = new JensenShannonDivergenceDistanceFunction();
+
+ /**
+ * Constructor for the Jensen-Shannon divergence.
+ *
+ * @deprecated Use static instance!
+ */
+ @Deprecated
+ public JensenShannonDivergenceDistanceFunction() {
+ super();
+ }
+
+ @Override
+ public double doubleDistance(NumberVector<?> v1, NumberVector<?> v2) {
+ return .5 * super.doubleDistance(v1, v2);
+ }
+
+ @Override
+ public String toString() {
+ return "JensenShannonDivergenceDistance";
+ }
+
+ /**
+ * Parameterization class, using the static instance.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected JensenShannonDivergenceDistanceFunction makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/probabilistic/KullbackLeiblerDivergenceAsymmetricDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/probabilistic/KullbackLeiblerDivergenceAsymmetricDistanceFunction.java
new file mode 100644
index 00000000..c0f61d43
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/probabilistic/KullbackLeiblerDivergenceAsymmetricDistanceFunction.java
@@ -0,0 +1,121 @@
+package de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2011
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractVectorDoubleDistanceFunction;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Kullback-Leibler (asymmetric!) Distance, also known as relative entropy,
+ * information deviation or just KL-distance
+ *
+ * For a version with the arguments reversed, see
+ * {@link KullbackLeiblerDivergenceReverseAsymmetricDistanceFunction}.
+ *
+ * For a symmetric version, see {@link JeffreyDivergenceDistanceFunction}.
+ *
+ * Reference:
+ * <p>
+ * S. Kullback<br />
+ * Information theory and statistics<br />
+ * Courier Dover Publications, 1997.
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@Reference(authors = "S. Kullback", title = "Information theory and statistics", booktitle = "Information theory and statistics, Courier Dover Publications, 1997.")
+@Alias("kl")
+public class KullbackLeiblerDivergenceAsymmetricDistanceFunction extends AbstractVectorDoubleDistanceFunction {
+ /**
+ * Static instance. Use this!
+ */
+ public static final KullbackLeiblerDivergenceAsymmetricDistanceFunction STATIC = new KullbackLeiblerDivergenceAsymmetricDistanceFunction();
+
+ /**
+ * Constructor for the Kullback-Leibler divergence.
+ *
+ * @deprecated Use static instance!
+ */
+ @Deprecated
+ public KullbackLeiblerDivergenceAsymmetricDistanceFunction() {
+ super();
+ }
+
+ @Override
+ public double doubleDistance(NumberVector<?> v1, NumberVector<?> v2) {
+ final int dim = dimensionality(v1, v2);
+ double agg = 0.;
+ for (int d = 0; d < dim; d++) {
+ final double xd = v1.doubleValue(d), yd = v2.doubleValue(d);
+ if (yd <= 0.) {
+ return Double.POSITIVE_INFINITY;
+ }
+ if (xd > 0.) {
+ agg += xd * Math.log(xd / yd);
+ }
+ }
+ return agg;
+ }
+
+ @Override
+ public boolean isSymmetric() {
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return "KullbackLeiblerDivergenceDistance";
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (obj == this) {
+ return true;
+ }
+ if (this.getClass().equals(obj.getClass())) {
+ return true;
+ }
+ return super.equals(obj);
+ }
+
+ /**
+ * Parameterization class, using the static instance.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected KullbackLeiblerDivergenceAsymmetricDistanceFunction makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/probabilistic/KullbackLeiblerDivergenceReverseAsymmetricDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/probabilistic/KullbackLeiblerDivergenceReverseAsymmetricDistanceFunction.java
new file mode 100644
index 00000000..08bddc1b
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/probabilistic/KullbackLeiblerDivergenceReverseAsymmetricDistanceFunction.java
@@ -0,0 +1,122 @@
+package de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2011
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractVectorDoubleDistanceFunction;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Kullback-Leibler (asymmetric!) Distance, also known as relative entropy,
+ * information deviation or just KL-distance.
+ *
+ * This version has the arguments reversed, see
+ * {@link KullbackLeiblerDivergenceAsymmetricDistanceFunction} for the "forward"
+ * version.
+ *
+ * For a symmetric version, see {@link JeffreyDivergenceDistanceFunction}.
+ *
+ * Reference:
+ * <p>
+ * S. Kullback<br />
+ * Information theory and statistics<br />
+ * Courier Dover Publications, 1997.
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@Reference(authors = "S. Kullback", title = "Information theory and statistics", booktitle = "Information theory and statistics, Courier Dover Publications, 1997.")
+@Alias("kli")
+public class KullbackLeiblerDivergenceReverseAsymmetricDistanceFunction extends AbstractVectorDoubleDistanceFunction {
+ /**
+ * Static instance. Use this!
+ */
+ public static final KullbackLeiblerDivergenceReverseAsymmetricDistanceFunction STATIC = new KullbackLeiblerDivergenceReverseAsymmetricDistanceFunction();
+
+ /**
+ * Constructor for the Kullback-Leibler divergence.
+ *
+ * @deprecated Use static instance!
+ */
+ @Deprecated
+ public KullbackLeiblerDivergenceReverseAsymmetricDistanceFunction() {
+ super();
+ }
+
+ @Override
+ public double doubleDistance(NumberVector<?> v1, NumberVector<?> v2) {
+ final int dim = dimensionality(v1, v2);
+ double agg = 0.;
+ for (int d = 0; d < dim; d++) {
+ final double xd = v1.doubleValue(d), yd = v2.doubleValue(d);
+ if (xd <= 0.) {
+ return Double.POSITIVE_INFINITY;
+ }
+ if (yd > 0.) {
+ agg += yd * Math.log(yd / xd);
+ }
+ }
+ return agg;
+ }
+
+ @Override
+ public boolean isSymmetric() {
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return "KullbackLeiblerDivergenceDistance";
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (obj == this) {
+ return true;
+ }
+ if (this.getClass().equals(obj.getClass())) {
+ return true;
+ }
+ return super.equals(obj);
+ }
+
+ /**
+ * Parameterization class, using the static instance.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected KullbackLeiblerDivergenceReverseAsymmetricDistanceFunction makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/probabilistic/SqrtJensenShannonDivergenceDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/probabilistic/SqrtJensenShannonDivergenceDistanceFunction.java
new file mode 100644
index 00000000..af0590fc
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/probabilistic/SqrtJensenShannonDivergenceDistanceFunction.java
@@ -0,0 +1,120 @@
+package de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2011
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractVectorDoubleDistanceFunction;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * The square root of Jensen-Shannon divergence is metric.
+ *
+ * Reference (proof of triangle inequality, distance called D_PQ):
+ * <p>
+ * D. M. Endres, J. E. Schindelin<br />
+ * A new metric for probability distributions<br />
+ * IEEE Transactions on Information Theory, 49(7).
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@Reference(authors = "D. M. Endres, J. E. Schindelin", title = "A new metric for probability distributions", booktitle = "IEEE Transactions on Information Theory, 49(7)", url = "http://dx.doi.org/10.1109/TIT.2003.813506")
+public class SqrtJensenShannonDivergenceDistanceFunction extends AbstractVectorDoubleDistanceFunction {
+ /**
+ * Static instance. Use this!
+ */
+ public static final SqrtJensenShannonDivergenceDistanceFunction STATIC = new SqrtJensenShannonDivergenceDistanceFunction();
+
+ /**
+ * Constructor for sqrt Jensen Shannon divergence.
+ *
+ * @deprecated Use static instance!
+ */
+ @Deprecated
+ public SqrtJensenShannonDivergenceDistanceFunction() {
+ super();
+ }
+
+ @Override
+ public double doubleDistance(NumberVector<?> v1, NumberVector<?> v2) {
+ final int dim = dimensionality(v1, v2);
+ double agg = 0.;
+ for(int d = 0; d < dim; d++) {
+ final double xd = v1.doubleValue(d), yd = v2.doubleValue(d);
+ if(xd == yd) {
+ continue;
+ }
+ final double md = .5 * (xd + yd);
+ if(!(md > 0. || md < 0.)) {
+ continue;
+ }
+ if(xd > 0.) {
+ agg += xd * Math.log(xd / md);
+ }
+ if(yd > 0.) {
+ agg += yd * Math.log(yd / md);
+ }
+ }
+ return Math.sqrt(agg);
+ }
+
+ @Override
+ public boolean isMetric() {
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "SqrtJensenShannonDivergenceDistance";
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if(obj == null) {
+ return false;
+ }
+ if(obj == this) {
+ return true;
+ }
+ if(this.getClass().equals(obj.getClass())) {
+ return true;
+ }
+ return super.equals(obj);
+ }
+
+ /**
+ * Parameterization class, using the static instance.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected SqrtJensenShannonDivergenceDistanceFunction makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/probabilistic/package-info.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/probabilistic/package-info.java
new file mode 100644
index 00000000..335c6ae0
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/probabilistic/package-info.java
@@ -0,0 +1,6 @@
+/**
+ * Distance from probability theory, mostly divergences such as K-L-divergence, J-divergence.
+ *
+ * @author Erich Schubert
+ */
+package de.lmu.ifi.dbs.elki.distance.distancefunction.probabilistic; \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/strings/LevenshteinDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/strings/LevenshteinDistanceFunction.java
new file mode 100644
index 00000000..fbc75a22
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/strings/LevenshteinDistanceFunction.java
@@ -0,0 +1,135 @@
+package de.lmu.ifi.dbs.elki.distance.distancefunction.strings;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
+import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractPrimitiveDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.IntegerDistance;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Description;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Classic Levenshtein distance on strings.
+ *
+ * Reference:
+ * <p>
+ * V. I. Levenshtein<br>
+ * Binary codes capable of correcting deletions, insertions and reversals.<br>
+ * Soviet physics doklady. Vol. 10. 1966.
+ * </p>
+ *
+ * TODO: add case insensitive flag.
+ *
+ * @author Felix Stahlberg
+ * @author Erich Schubert
+ *
+ * @apiviz.uses String
+ */
+@Description("Levenshtein distance.")
+@Reference(authors = "V. I. Levenshtein", title = "Binary codes capable of correcting deletions, insertions and reversals.", booktitle = "Soviet physics doklady. Vol. 10. 1966.")
+public class LevenshteinDistanceFunction extends AbstractPrimitiveDistanceFunction<String, IntegerDistance> {
+ /**
+ * Static instance, case sensitive.
+ */
+ public static final LevenshteinDistanceFunction STATIC_SENSITIVE = new LevenshteinDistanceFunction();
+
+ /**
+ * Constructor. Use static instance instead.
+ */
+ @Deprecated
+ public LevenshteinDistanceFunction() {
+ super();
+ }
+
+ @Override
+ public IntegerDistance distance(String o1, String o2) {
+ if (o1.equals(o2)) {
+ return new IntegerDistance(0);
+ }
+ final int cost = levenshteinDistance(o1, o2);
+ return new IntegerDistance(cost);
+ }
+
+ /**
+ * Levenshtein distance for two strings.
+ *
+ * @param o1 First string
+ * @param o2 Second string
+ * @return Levenshtein distance
+ */
+ public static int levenshteinDistance(String o1, String o2) {
+ // Let o2 be the shorter one:
+ if (o1.length() < o2.length()) {
+ return levenshteinDistance(o2, o1);
+ }
+ final int l1 = o1.length(), l2 = o2.length();
+ // Use two buffers:
+ int[] curr = new int[l2 + 1], prev = new int[l2 + 1];
+ // Initial row
+ for (int j = 0; j <= l2; j++) {
+ curr[j] = j;
+ }
+ for (int i = 0; i < l1; i++) {
+ // Swap curr and prev:
+ int[] tmp = curr;
+ curr = prev;
+ prev = tmp;
+ // Compute next row:
+ curr[0] = i + 1;
+ for (int j = 0; j < l2; j++) {
+ // TODO: allow case insensitive comparisons?
+ final int cost = (o1.charAt(i) == o2.charAt(j)) ? 0 : 1;
+ curr[j + 1] = Math.min(prev[j + 1] + 1, Math.min(curr[j] + 1, prev[j] + cost));
+ }
+ }
+ final int cost = curr[o2.length()];
+ return cost;
+ }
+
+ @Override
+ public IntegerDistance getDistanceFactory() {
+ return IntegerDistance.FACTORY;
+ }
+
+ @Override
+ public SimpleTypeInformation<? super String> getInputTypeRestriction() {
+ return TypeUtil.STRING;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected LevenshteinDistanceFunction makeInstance() {
+ return STATIC_SENSITIVE;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/strings/NormalizedLevenshteinDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/strings/NormalizedLevenshteinDistanceFunction.java
new file mode 100644
index 00000000..0861c6af
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/strings/NormalizedLevenshteinDistanceFunction.java
@@ -0,0 +1,96 @@
+package de.lmu.ifi.dbs.elki.distance.distancefunction.strings;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
+import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractPrimitiveDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Description;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Levenshtein distance on strings, normalized by string length.
+ *
+ * Reference:
+ * <p>
+ * V. I. Levenshtein<br>
+ * Binary codes capable of correcting deletions, insertions and reversals.<br>
+ * Soviet physics doklady. Vol. 10. 1966.
+ * </p>
+ *
+ * TODO: add case insensitive flag.
+ *
+ * @author Felix Stahlberg
+ * @author Erich Schubert
+ *
+ * @apiviz.uses String
+ */
+@Description("Levenshtein distance, normalized by average string length.")
+@Reference(authors = "V. I. Levenshtein", title = "Binary codes capable of correcting deletions, insertions and reversals.", booktitle = "Soviet physics doklady. Vol. 10. 1966.")
+public class NormalizedLevenshteinDistanceFunction extends AbstractPrimitiveDistanceFunction<String, DoubleDistance> {
+ /**
+ * Static instance, case sensitive.
+ */
+ public static final NormalizedLevenshteinDistanceFunction STATIC_SENSITIVE = new NormalizedLevenshteinDistanceFunction();
+
+ /**
+ * Constructor. Use static instance instead.
+ */
+ @Deprecated
+ public NormalizedLevenshteinDistanceFunction() {
+ super();
+ }
+
+ @Override
+ public DoubleDistance distance(String o1, String o2) {
+ int cost = LevenshteinDistanceFunction.levenshteinDistance(o1, o2);
+ return new DoubleDistance(cost * 2.0 / (o1.length() + o2.length()));
+ }
+
+ @Override
+ public DoubleDistance getDistanceFactory() {
+ return DoubleDistance.FACTORY;
+ }
+
+ @Override
+ public SimpleTypeInformation<? super String> getInputTypeRestriction() {
+ return TypeUtil.STRING;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected NormalizedLevenshteinDistanceFunction makeInstance() {
+ return STATIC_SENSITIVE;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/strings/package-info.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/strings/package-info.java
new file mode 100644
index 00000000..a2f3fd2d
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/strings/package-info.java
@@ -0,0 +1,27 @@
+/**
+ * <p>Distance functions for strings.</p>
+ */
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package de.lmu.ifi.dbs.elki.distance.distancefunction.strings;
+
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/AbstractDimensionsSelectingDoubleDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/AbstractDimensionsSelectingDoubleDistanceFunction.java
index 6bedd394..25cb6407 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/AbstractDimensionsSelectingDoubleDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/AbstractDimensionsSelectingDoubleDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.subspace;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/AbstractPreferenceVectorBasedCorrelationDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/AbstractPreferenceVectorBasedCorrelationDistanceFunction.java
index e662bef1..f3a07639 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/AbstractPreferenceVectorBasedCorrelationDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/AbstractPreferenceVectorBasedCorrelationDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.subspace;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/DiSHDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/DiSHDistanceFunction.java
index 77633578..7303797d 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/DiSHDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/DiSHDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.subspace;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -64,7 +64,7 @@ public class DiSHDistanceFunction extends AbstractPreferenceVectorBasedCorrelati
// Generics (AFAICT)
@SuppressWarnings("unchecked")
DiSHPreferenceVectorIndex<T> indexinst = (DiSHPreferenceVectorIndex<T>) indexFactory.instantiate((Relation<NumberVector<?>>) database);
- return new Instance<T>(database, indexinst, getEpsilon(), this);
+ return new Instance<>(database, indexinst, getEpsilon(), this);
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/DimensionSelectingDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/DimensionSelectingDistanceFunction.java
index e1d52710..fe593f0a 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/DimensionSelectingDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/DimensionSelectingDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.subspace;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,14 +23,13 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.subspace;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import java.util.BitSet;
+
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.VectorFieldTypeInformation;
import de.lmu.ifi.dbs.elki.data.type.VectorTypeInformation;
-import de.lmu.ifi.dbs.elki.database.query.distance.SpatialPrimitiveDistanceQuery;
-import de.lmu.ifi.dbs.elki.database.relation.Relation;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractPrimitiveDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDoubleDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractSpatialDoubleDistanceNorm;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
@@ -44,7 +43,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
*
* @author Elke Achtert
*/
-public class DimensionSelectingDistanceFunction extends AbstractPrimitiveDistanceFunction<NumberVector<?>, DoubleDistance> implements SpatialPrimitiveDoubleDistanceFunction<NumberVector<?>> {
+public class DimensionSelectingDistanceFunction extends AbstractSpatialDoubleDistanceNorm implements DimensionSelectingSubspaceDistanceFunction<NumberVector<?>, DoubleDistance> {
/**
* Parameter for dimensionality.
*/
@@ -76,7 +75,7 @@ public class DimensionSelectingDistanceFunction extends AbstractPrimitiveDistanc
*/
@Override
public double doubleDistance(NumberVector<?> v1, NumberVector<?> v2) {
- if(dim >= v1.getDimensionality() || dim >= v2.getDimensionality() || dim < 0) {
+ if (dim >= v1.getDimensionality() || dim >= v2.getDimensionality() || dim < 0) {
throw new IllegalArgumentException("Specified dimension to be considered " + "is larger that dimensionality of FeatureVectors:" + "\n first argument: " + v1.toString() + "\n second argument: " + v2.toString() + "\n dimension: " + dim);
}
@@ -86,20 +85,18 @@ public class DimensionSelectingDistanceFunction extends AbstractPrimitiveDistanc
@Override
public double doubleMinDist(SpatialComparable mbr1, SpatialComparable mbr2) {
- if(dim >= mbr1.getDimensionality() || dim >= mbr2.getDimensionality() || dim < 0) {
+ if (dim >= mbr1.getDimensionality() || dim >= mbr2.getDimensionality() || dim < 0) {
throw new IllegalArgumentException("Specified dimension to be considered " + "is larger that dimensionality of FeatureVectors:" + "\n first argument: " + mbr1.toString() + "\n second argument: " + mbr2.toString() + "\n dimension: " + dim);
}
double m1, m2;
- if(mbr1.getMax(dim) < mbr2.getMin(dim)) {
+ if (mbr1.getMax(dim) < mbr2.getMin(dim)) {
m1 = mbr1.getMax(dim);
m2 = mbr2.getMin(dim);
- }
- else if(mbr1.getMin(dim) > mbr2.getMax(dim)) {
+ } else if (mbr1.getMin(dim) > mbr2.getMax(dim)) {
m1 = mbr1.getMin(dim);
m2 = mbr2.getMax(dim);
- }
- else { // The mbrs intersect!
+ } else { // The mbrs intersect!
m1 = 0;
m2 = 0;
}
@@ -109,13 +106,8 @@ public class DimensionSelectingDistanceFunction extends AbstractPrimitiveDistanc
}
@Override
- public DoubleDistance distance(NumberVector<?> o1, NumberVector<?> o2) {
- return new DoubleDistance(doubleDistance(o1, o2));
- }
-
- @Override
- public DoubleDistance minDist(SpatialComparable mbr1, SpatialComparable mbr2) {
- return new DoubleDistance(doubleMinDist(mbr1, mbr2));
+ public double doubleNorm(NumberVector<?> obj) {
+ return Math.abs(obj.doubleValue(dim));
}
/**
@@ -128,31 +120,45 @@ public class DimensionSelectingDistanceFunction extends AbstractPrimitiveDistanc
}
@Override
- public VectorTypeInformation<? super NumberVector<?>> getInputTypeRestriction() {
- return new VectorFieldTypeInformation<NumberVector<?>>(NumberVector.class, dim, Integer.MAX_VALUE);
+ @Deprecated
+ public BitSet getSelectedDimensions() {
+ BitSet bs = new BitSet(dim + 1);
+ bs.set(dim);
+ return bs;
}
@Override
- public DoubleDistance getDistanceFactory() {
- return DoubleDistance.FACTORY;
+ public void setSelectedDimensions(BitSet dimensions) {
+ dim = dimensions.nextSetBit(0);
+ if (dim == -1) {
+ throw new IllegalStateException("No dimension was set.");
+ }
+ if (dimensions.nextSetBit(dim + 1) > 0) {
+ throw new IllegalStateException("More than one dimension was set.");
+ }
}
@Override
- public <T extends NumberVector<?>> SpatialPrimitiveDistanceQuery<T, DoubleDistance> instantiate(Relation<T> database) {
- return new SpatialPrimitiveDistanceQuery<T, DoubleDistance>(database, this);
+ public VectorTypeInformation<? super NumberVector<?>> getInputTypeRestriction() {
+ return new VectorFieldTypeInformation<>(NumberVector.class, dim, Integer.MAX_VALUE);
+ }
+
+ @Override
+ public DoubleDistance getDistanceFactory() {
+ return DoubleDistance.FACTORY;
}
@Override
public boolean equals(Object obj) {
- if(obj == null) {
+ if (obj == null) {
return false;
}
- if(!this.getClass().equals(obj.getClass())) {
+ if (!this.getClass().equals(obj.getClass())) {
return false;
}
return this.dim == ((DimensionSelectingDistanceFunction) obj).dim;
}
-
+
/**
* Parameterization class.
*
@@ -168,7 +174,7 @@ public class DimensionSelectingDistanceFunction extends AbstractPrimitiveDistanc
super.makeOptions(config);
final IntParameter dimP = new IntParameter(DIM_ID);
dimP.addConstraint(new GreaterEqualConstraint(0));
- if(config.grab(dimP)) {
+ if (config.grab(dimP)) {
dim = dimP.getValue();
}
}
@@ -178,4 +184,4 @@ public class DimensionSelectingDistanceFunction extends AbstractPrimitiveDistanc
return new DimensionSelectingDistanceFunction(dim);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/DimensionSelectingSubspaceDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/DimensionSelectingSubspaceDistanceFunction.java
index acc24bf7..f60e2fdc 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/DimensionSelectingSubspaceDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/DimensionSelectingSubspaceDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.subspace;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,8 +24,8 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.subspace;
*/
import java.util.BitSet;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
/**
* Interface for dimension selecting subspace distance functions.
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/HiSCDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/HiSCDistanceFunction.java
index 0703ab2d..a339c389 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/HiSCDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/HiSCDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.subspace;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -66,7 +66,7 @@ public class HiSCDistanceFunction<V extends NumberVector<?>> extends AbstractPre
// Generics (AFAICT)
@SuppressWarnings("unchecked")
HiSCPreferenceVectorIndex<T> indexinst = (HiSCPreferenceVectorIndex<T>) indexFactory.instantiate((Relation<V>) database);
- return new Instance<T>(database, indexinst, getEpsilon(), this);
+ return new Instance<>(database, indexinst, getEpsilon(), this);
}
/**
@@ -152,7 +152,7 @@ public class HiSCDistanceFunction<V extends NumberVector<?>> extends AbstractPre
@Override
protected HiSCDistanceFunction<V> makeInstance() {
- return new HiSCDistanceFunction<V>(factory, epsilon);
+ return new HiSCDistanceFunction<>(factory, epsilon);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/LocalSubspaceDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/LocalSubspaceDistanceFunction.java
index ff38d3d9..efcf6a3c 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/LocalSubspaceDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/LocalSubspaceDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.subspace;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -68,7 +68,7 @@ public class LocalSubspaceDistanceFunction extends AbstractIndexBasedDistanceFun
// We can't really avoid these warnings, due to a limitation in Java Generics (AFAICT)
@SuppressWarnings("unchecked")
FilteredLocalPCAIndex<V> indexinst = (FilteredLocalPCAIndex<V>) indexFactory.instantiate((Relation<NumberVector<?>>)database);
- return new Instance<V>(database, indexinst, this);
+ return new Instance<>(database, indexinst, this);
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/SubspaceEuclideanDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/SubspaceEuclideanDistanceFunction.java
index 48518afd..d24fc62e 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/SubspaceEuclideanDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/SubspaceEuclideanDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.subspace;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/SubspaceLPNormDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/SubspaceLPNormDistanceFunction.java
index ccfc51d9..2fbdf876 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/SubspaceLPNormDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/SubspaceLPNormDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.subspace;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -32,8 +32,8 @@ import de.lmu.ifi.dbs.elki.data.type.VectorFieldTypeInformation;
import de.lmu.ifi.dbs.elki.database.query.distance.SpatialPrimitiveDistanceQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DoubleNorm;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.LPNormDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDoubleDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.LPNormDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
@@ -171,7 +171,7 @@ public class SubspaceLPNormDistanceFunction extends AbstractDimensionsSelectingD
@Override
public <T extends NumberVector<?>> SpatialPrimitiveDistanceQuery<T, DoubleDistance> instantiate(Relation<T> database) {
- return new SpatialPrimitiveDistanceQuery<T, DoubleDistance>(database, this);
+ return new SpatialPrimitiveDistanceQuery<>(database, this);
}
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/SubspaceManhattanDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/SubspaceManhattanDistanceFunction.java
index fb777d81..ccca76da 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/SubspaceManhattanDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/SubspaceManhattanDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.subspace;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/package-info.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/package-info.java
index 85035eec..2b5db4c5 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/timeseries/AbstractEditDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/timeseries/AbstractEditDistanceFunction.java
index a88dbded..76630586 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/timeseries/AbstractEditDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/timeseries/AbstractEditDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.timeseries;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/timeseries/DTWDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/timeseries/DTWDistanceFunction.java
index d3fab3c0..eedd3a7c 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/timeseries/DTWDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/timeseries/DTWDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.timeseries;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/timeseries/EDRDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/timeseries/EDRDistanceFunction.java
index 4c177b03..0e38d8bd 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/timeseries/EDRDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/timeseries/EDRDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.timeseries;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/timeseries/ERPDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/timeseries/ERPDistanceFunction.java
index a4525a6b..fd5bb61c 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/timeseries/ERPDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/timeseries/ERPDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.timeseries;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/timeseries/LCSSDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/timeseries/LCSSDistanceFunction.java
index 192f8d6f..2998248d 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/timeseries/LCSSDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/timeseries/LCSSDistanceFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction.timeseries;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/timeseries/package-info.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/timeseries/package-info.java
index cad7fba9..4edbe89f 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/timeseries/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/timeseries/package-info.java
@@ -8,7 +8,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/DistanceDBIDResultUtil.java b/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/DistanceDBIDResultUtil.java
index aea23be6..d1564fd8 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/DistanceDBIDResultUtil.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/DistanceDBIDResultUtil.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distanceresultlist;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,7 +27,9 @@ import java.util.Comparator;
import java.util.List;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
-import de.lmu.ifi.dbs.elki.database.ids.DistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
/**
@@ -44,7 +46,7 @@ public final class DistanceDBIDResultUtil {
* @return comparator
*/
@SuppressWarnings("unchecked")
- public static <D extends DistanceDBIDPair<?>> Comparator<D> distanceComparator() {
+ public static <D extends DistanceDBIDPair<?>> Comparator<? super D> distanceComparator() {
return (Comparator<D>) BY_DISTANCE_THEN_DBID;
}
@@ -70,13 +72,24 @@ public final class DistanceDBIDResultUtil {
}
};
- public static String toString(DistanceDBIDResult<?> res) {
+ /**
+ * Static comparator for heaps.
+ */
+ public static final Comparator<DistanceDBIDPair<?>> BY_REVERSE_DISTANCE = new Comparator<DistanceDBIDPair<?>>() {
+ @SuppressWarnings("unchecked")
+ @Override
+ public int compare(DistanceDBIDPair<?> o1, DistanceDBIDPair<?> o2) {
+ return -((DistanceDBIDPair<DoubleDistance>)o1).compareByDistance((DistanceDBIDPair<DoubleDistance>)o2);
+ }
+ };
+
+ public static String toString(DistanceDBIDList<?> res) {
StringBuilder buf = new StringBuilder();
buf.append('[');
- DistanceDBIDResultIter<?> iter = res.iter();
+ DistanceDBIDListIter<?> iter = res.iter();
for(; iter.valid(); iter.advance()) {
if(buf.length() > 1) {
- buf.append(", ");
+ buf.append(',').append(' ');
}
buf.append(iter.getDistancePair().toString());
}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/KNNUtil.java b/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/KNNUtil.java
deleted file mode 100644
index fa658941..00000000
--- a/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/KNNUtil.java
+++ /dev/null
@@ -1,372 +0,0 @@
-package de.lmu.ifi.dbs.elki.distance.distanceresultlist;
-
-/*
- This file is part of ELKI:
- Environment for Developing KDD-Applications Supported by Index-Structures
-
- Copyright (C) 2012
- Ludwig-Maximilians-Universität München
- Lehr- und Forschungseinheit für Datenbanksysteme
- ELKI Development Team
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-import java.util.AbstractList;
-import java.util.Iterator;
-import java.util.List;
-
-import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
-import de.lmu.ifi.dbs.elki.database.ids.DistanceDBIDPair;
-import de.lmu.ifi.dbs.elki.database.ids.DoubleDistanceDBIDPair;
-import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
-import de.lmu.ifi.dbs.elki.distance.DistanceUtil;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
-
-/**
- * Helper classes for kNN results.
- *
- * @author Erich Schubert
- *
- * @apiviz.landmark
- *
- * @apiviz.has KNNResult oneway - - «processes»
- * @apiviz.has KNNHeap oneway - - «creates»
- * @apiviz.has DistanceView
- * @apiviz.has KNNSubList
- */
-public final class KNNUtil {
- /**
- * Fake constructor: do not instantiate.
- */
- private KNNUtil() {
- // Empty.
- }
-
- /**
- * Create an appropriate heap for the distance function.
- *
- * This will use a double heap if appropriate.
- *
- * @param df Distance function
- * @param k K value
- * @param <D> distance type
- * @return New heap of size k, appropriate for this distance function.
- */
- @SuppressWarnings("unchecked")
- public static <D extends Distance<D>> KNNHeap<D> newHeap(DistanceFunction<?, D> df, int k) {
- if (DistanceUtil.isDoubleDistanceFunction(df)) {
- return (KNNHeap<D>) new DoubleDistanceKNNHeap(k);
- }
- return new GenericKNNHeap<D>(k);
- }
-
- /**
- * Create an appropriate heap for the distance function.
- *
- * This will use a double heap if appropriate.
- *
- * @param df Distance function
- * @param k K value
- * @param <D> distance type
- * @return New heap of size k, appropriate for this distance function.
- */
- @SuppressWarnings("unchecked")
- public static <D extends Distance<D>> KNNHeap<D> newHeap(DistanceQuery<?, D> df, int k) {
- if (DistanceUtil.isDoubleDistanceFunction(df)) {
- return (KNNHeap<D>) new DoubleDistanceKNNHeap(k);
- }
- return new GenericKNNHeap<D>(k);
- }
-
- /**
- * Create an appropriate heap for the distance function.
- *
- * This will use a double heap if appropriate.
- *
- * @param factory distance prototype
- * @param k K value
- * @param <D> distance type
- * @return New heap of size k, appropriate for this distance type.
- */
- @SuppressWarnings("unchecked")
- public static <D extends Distance<D>> KNNHeap<D> newHeap(D factory, int k) {
- if (factory instanceof DoubleDistance) {
- return (KNNHeap<D>) new DoubleDistanceKNNHeap(k);
- }
- return new GenericKNNHeap<D>(k);
- }
-
- /**
- * Build a new heap from a given list.
- *
- * @param exist Existing result
- * @param <D> Distance type
- * @return New heap
- */
- @SuppressWarnings("unchecked")
- public static <D extends Distance<D>> KNNHeap<D> newHeap(KNNResult<D> exist) {
- if (exist instanceof DoubleDistanceKNNList) {
- DoubleDistanceKNNHeap heap = new DoubleDistanceKNNHeap(exist.getK());
- // Insert backwards, as this will produce a proper heap
- for (int i = exist.size() - 1; i >= 0; i--) {
- heap.add((DoubleDistanceDBIDPair) exist.get(i));
- }
- return (KNNHeap<D>) heap;
- } else {
- GenericKNNHeap<D> heap = new GenericKNNHeap<D>(exist.getK());
- // Insert backwards, as this will produce a proper heap
- for (int i = exist.size() - 1; i >= 0; i--) {
- heap.add(exist.get(i));
- }
- return heap;
- }
- }
-
- /**
- * Sublist of an existing result to contain only the first k elements.
- *
- * @author Erich Schubert
- *
- * @param <D> Distance
- */
- protected static class KNNSubList<D extends Distance<D>> implements KNNResult<D> {
- /**
- * Parameter k.
- */
- private final int k;
-
- /**
- * Actual size, including ties.
- */
- private final int size;
-
- /**
- * Wrapped inner result.
- */
- private final KNNResult<D> inner;
-
- /**
- * Constructor.
- *
- * @param inner Inner instance
- * @param k k value
- */
- public KNNSubList(KNNResult<D> inner, int k) {
- this.inner = inner;
- this.k = k;
- // Compute list size
- // TODO: optimize for double distances.
- {
- DistanceDBIDPair<D> dist = inner.get(k);
- int i = k;
- while (i + 1 < inner.size()) {
- if (dist.compareByDistance(inner.get(i + 1)) < 0) {
- break;
- }
- i++;
- }
- size = i;
- }
- }
-
- @Override
- public int getK() {
- return k;
- }
-
- @Override
- public DistanceDBIDPair<D> get(int index) {
- assert (index < size) : "Access beyond design size of list.";
- return inner.get(index);
- }
-
- @Override
- public D getKNNDistance() {
- return inner.get(k).getDistance();
- }
-
- @Override
- public DistanceDBIDResultIter<D> iter() {
- return new Itr();
- }
-
- @Override
- public boolean contains(DBIDRef o) {
- for (DBIDIter iter = iter(); iter.valid(); iter.advance()) {
- if (DBIDUtil.equal(iter, o)) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public boolean isEmpty() {
- return size == 0;
- }
-
- @Override
- public int size() {
- return size;
- }
-
- /**
- * Iterator for the sublist.
- *
- * @author Erich Schubert
- *
- * @apiviz.exclude
- */
- private class Itr implements DistanceDBIDResultIter<D> {
- /**
- * Current position.
- */
- private int pos = 0;
-
- @Override
- public boolean valid() {
- return pos < size;
- }
-
- @Override
- public void advance() {
- pos++;
- }
-
- @Override
- public D getDistance() {
- return inner.get(pos).getDistance();
- }
-
- @Override
- public DistanceDBIDPair<D> getDistancePair() {
- return inner.get(pos);
- }
-
- @Override
- public int internalGetIndex() {
- return inner.get(pos).internalGetIndex();
- }
- }
- }
-
- /**
- * Proxy iterator for accessing DBIDs.
- *
- * @author Erich Schubert
- */
- protected static class DistanceItr<D extends Distance<D>> implements Iterator<D> {
- /**
- * The real iterator.
- */
- DistanceDBIDResultIter<D> itr;
-
- /**
- * Constructor.
- *
- * @param distanceDBIDResultIter Iterator
- */
- protected DistanceItr(DistanceDBIDResultIter<D> distanceDBIDResultIter) {
- super();
- this.itr = distanceDBIDResultIter;
- }
-
- @Override
- public boolean hasNext() {
- return itr.valid();
- }
-
- @Override
- public D next() {
- D dist = itr.getDistance();
- itr.advance();
- return dist;
- }
-
- @Override
- public void remove() {
- throw new UnsupportedOperationException();
- }
- }
-
- /**
- * A view on the Distances of the result.
- *
- * @author Erich Schubert
- *
- * @apiviz.composedOf DistanceItr
- */
- protected static class DistanceView<D extends Distance<D>> extends AbstractList<D> implements List<D> {
- /**
- * The true list.
- */
- final KNNResult<D> parent;
-
- /**
- * Constructor.
- *
- * @param parent Owner
- */
- public DistanceView(KNNResult<D> parent) {
- super();
- this.parent = parent;
- }
-
- @Override
- public D get(int i) {
- return parent.get(i).getDistance();
- }
-
- @Override
- public Iterator<D> iterator() {
- return new DistanceItr<D>(parent.iter());
- }
-
- @Override
- public int size() {
- return parent.size();
- }
- }
-
- /**
- * View as list of distances.
- *
- * @param list Result to proxy
- * @param <D> distance type
- * @return List of distances view
- */
- public static <D extends Distance<D>> List<D> asDistanceList(KNNResult<D> list) {
- return new DistanceView<D>(list);
- }
-
- /**
- * Get a subset of the KNN result.
- *
- * @param list Existing list
- * @param k k
- * @param <D> distance type
- * @return Subset
- */
- public static <D extends Distance<D>> KNNResult<D> subList(KNNResult<D> list, int k) {
- if (k >= list.size()) {
- return list;
- }
- return new KNNSubList<D>(list, k);
- }
-}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/package-info.java b/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/package-info.java
index 3d2a4b3b..e96621b5 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distanceresultlist/package-info.java
@@ -1,38 +1,11 @@
/**
* <p>Classes for building and storing the results of distance-based queries</p>
- *
- * <p>The classes in this package essentially form three groups:
- * <ol>
- * <li>{@link de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNHeap} for <b>building kNN results</b>.
- * It allows adding new candidates (and loses old candidates automatically), but it is not iterable.<br />
- * To get an instance, use {@link de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNUtil#newHeap}!
- * </li>
- * <li>{@link de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult} is the <b>final kNN result</b>
- * obtained by serializing a heap via {@link de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNHeap#toKNNList}.
- * It is iterable and totally ordered, but can no longer be modified (unless you call
- * {@link de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNUtil#newHeap}!</li>
- * <li>{@link de.lmu.ifi.dbs.elki.distance.distanceresultlist.GenericDistanceDBIDList} and the optimized
- * counterpart {@link de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceDBIDList}, are
- * <b>modifiable, but not necessarily sorted</b> lists of neighbors, useful for example for range queries.</li>
- * </ol>
- * </p>
- *
- * <p>Try to choose the most appropriate one! Heaps are optimized for updates but bad for reading,
- * KNNResult is optimized for reading but unmodifiable, and the lists are easy to modify,
- * but less efficient than heaps.</p>
- *
- * @apiviz.exclude java.util.*
- * @apiviz.exclude elki.database.query.*
- * @apiviz.exclude elki.database.ids.DBIDIter
- * @apiviz.exclude elki.database.ids.DBIDs
- * @apiviz.exclude KNNUtil.DistanceItr
- * @apiviz.exclude DoubleDistance
*/
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancevalue/AbstractDistance.java b/src/de/lmu/ifi/dbs/elki/distance/distancevalue/AbstractDistance.java
index 3e5e86af..c0573ae5 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancevalue/AbstractDistance.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancevalue/AbstractDistance.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancevalue;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancevalue/BitDistance.java b/src/de/lmu/ifi/dbs/elki/distance/distancevalue/BitDistance.java
index 9c81188f..026e90aa 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancevalue/BitDistance.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancevalue/BitDistance.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancevalue;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -84,16 +84,6 @@ public class BitDistance extends NumberDistance<BitDistance, Bit> {
return new BitDistance(val > 0);
}
- @Override
- public BitDistance plus(BitDistance distance) {
- return new BitDistance(this.bitValue() || distance.bitValue());
- }
-
- @Override
- public BitDistance minus(BitDistance distance) {
- return new BitDistance(this.bitValue() ^ distance.bitValue());
- }
-
/**
* Returns the value of this BitDistance as a boolean.
*
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancevalue/CorrelationDistance.java b/src/de/lmu/ifi/dbs/elki/distance/distancevalue/CorrelationDistance.java
index 080f13c9..fc288809 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancevalue/CorrelationDistance.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancevalue/CorrelationDistance.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancevalue;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancevalue/Distance.java b/src/de/lmu/ifi/dbs/elki/distance/distancevalue/Distance.java
index 73e11fa6..40dff25d 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancevalue/Distance.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancevalue/Distance.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancevalue;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -41,23 +41,6 @@ import java.io.Externalizable;
*/
public interface Distance<D extends Distance<D>> extends Comparable<D>, Externalizable {
/**
- * Returns a new distance as sum of this distance and the given distance.
- *
- * @param distance the distance to be added to this distance
- * @return a new distance as sum of this distance and the given distance
- */
- D plus(D distance);
-
- /**
- * Returns a new Distance by subtracting the given distance from this
- * distance.
- *
- * @param distance the distance to be subtracted from this distance
- * @return a new Distance by subtracting the given distance from this distance
- */
- D minus(D distance);
-
- /**
* Any implementing class should implement a proper toString-method for
* printing the result-values.
*
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancevalue/DoubleDistance.java b/src/de/lmu/ifi/dbs/elki/distance/distancevalue/DoubleDistance.java
index acf72c8d..4126374d 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancevalue/DoubleDistance.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancevalue/DoubleDistance.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancevalue;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -88,40 +88,6 @@ public class DoubleDistance extends NumberDistance<DoubleDistance, Double> {
return new DoubleDistance(val);
}
- @Override
- public DoubleDistance plus(DoubleDistance distance) {
- return new DoubleDistance(this.value + distance.value);
- }
-
- @Override
- public DoubleDistance minus(DoubleDistance distance) {
- return new DoubleDistance(this.value - distance.value);
- }
-
- /**
- * Returns a new distance as the product of this distance and the given
- * distance.
- *
- * @param distance the distance to be multiplied with this distance
- * @return a new distance as the product of this distance and the given
- * distance
- */
- public DoubleDistance times(DoubleDistance distance) {
- return new DoubleDistance(this.value * distance.value);
- }
-
- /**
- * Returns a new distance as the product of this distance and the given double
- * value.
- *
- * @param lambda the double value this distance should be multiplied with
- * @return a new distance as the product of this distance and the given double
- * value
- */
- public DoubleDistance times(double lambda) {
- return new DoubleDistance(this.value * lambda);
- }
-
/**
* Writes the double value of this DoubleDistance to the specified stream.
*/
@@ -226,7 +192,7 @@ public class DoubleDistance extends NumberDistance<DoubleDistance, Double> {
@Override
public String toString() {
- return FormatUtil.NF8.format(value);
+ return FormatUtil.NF.format(value);
}
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancevalue/FloatDistance.java b/src/de/lmu/ifi/dbs/elki/distance/distancevalue/FloatDistance.java
index 2e88b147..f72d5c1b 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancevalue/FloatDistance.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancevalue/FloatDistance.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancevalue;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -88,40 +88,6 @@ public class FloatDistance extends NumberDistance<FloatDistance, Float> {
return new FloatDistance((float) val);
}
- @Override
- public FloatDistance plus(FloatDistance distance) {
- return new FloatDistance(value + distance.value);
- }
-
- @Override
- public FloatDistance minus(FloatDistance distance) {
- return new FloatDistance(value - distance.value);
- }
-
- /**
- * Returns a new distance as the product of this distance and the given
- * distance.
- *
- * @param distance the distance to be multiplied with this distance
- * @return a new distance as the product of this distance and the given
- * distance
- */
- public FloatDistance times(FloatDistance distance) {
- return new FloatDistance(value * distance.value);
- }
-
- /**
- * Returns a new distance as the product of this distance and the given float
- * value.
- *
- * @param lambda the float value this distance should be multiplied with
- * @return a new distance as the product of this distance and the given double
- * value
- */
- public FloatDistance times(float lambda) {
- return new FloatDistance(value * lambda);
- }
-
/**
* Writes the float value of this FloatDistance to the specified stream.
*/
@@ -232,7 +198,7 @@ public class FloatDistance extends NumberDistance<FloatDistance, Float> {
@Override
public String toString() {
- return FormatUtil.NF8.format(value);
+ return FormatUtil.NF.format(value);
}
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancevalue/IntegerDistance.java b/src/de/lmu/ifi/dbs/elki/distance/distancevalue/IntegerDistance.java
index d776b3ae..0e206f88 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancevalue/IntegerDistance.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancevalue/IntegerDistance.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancevalue;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -73,16 +73,6 @@ public class IntegerDistance extends NumberDistance<IntegerDistance, Integer> {
return new IntegerDistance((int) val);
}
- @Override
- public IntegerDistance minus(IntegerDistance distance) {
- return new IntegerDistance(this.value - distance.value);
- }
-
- @Override
- public IntegerDistance plus(IntegerDistance distance) {
- return new IntegerDistance(this.value + distance.value);
- }
-
/**
* Writes the integer value of this IntegerDistance to the specified stream.
*/
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancevalue/NumberDistance.java b/src/de/lmu/ifi/dbs/elki/distance/distancevalue/NumberDistance.java
index 9a915c2b..92d2f4ec 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancevalue/NumberDistance.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancevalue/NumberDistance.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancevalue;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancevalue/PCACorrelationDistance.java b/src/de/lmu/ifi/dbs/elki/distance/distancevalue/PCACorrelationDistance.java
index 79f27055..69087d59 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancevalue/PCACorrelationDistance.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancevalue/PCACorrelationDistance.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancevalue;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -126,16 +126,6 @@ public class PCACorrelationDistance extends CorrelationDistance<PCACorrelationDi
}
@Override
- public PCACorrelationDistance plus(PCACorrelationDistance distance) {
- return new PCACorrelationDistance(this.correlationValue + distance.getCorrelationValue(), this.euclideanValue + distance.getEuclideanValue());
- }
-
- @Override
- public PCACorrelationDistance minus(PCACorrelationDistance distance) {
- return new PCACorrelationDistance(this.correlationValue - distance.getCorrelationValue(), this.euclideanValue - distance.getEuclideanValue());
- }
-
- @Override
public boolean isInfiniteDistance() {
return correlationValue == Integer.MAX_VALUE || euclideanValue == Double.POSITIVE_INFINITY;
}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancevalue/PreferenceVectorBasedCorrelationDistance.java b/src/de/lmu/ifi/dbs/elki/distance/distancevalue/PreferenceVectorBasedCorrelationDistance.java
index a5617372..0c82e6b5 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancevalue/PreferenceVectorBasedCorrelationDistance.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancevalue/PreferenceVectorBasedCorrelationDistance.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancevalue;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -105,42 +105,6 @@ public class PreferenceVectorBasedCorrelationDistance extends CorrelationDistanc
}
/**
- * @throws IllegalArgumentException if the dimensionality values and common
- * preference vectors of this distance and the specified distance are
- * not equal
- */
- @Override
- public PreferenceVectorBasedCorrelationDistance plus(PreferenceVectorBasedCorrelationDistance distance) {
- if(this.dimensionality != distance.dimensionality) {
- throw new IllegalArgumentException("The dimensionality values of this distance " + "and the specified distance need to be equal.\n" + "this.dimensionality " + this.dimensionality + "\n" + "distance.dimensionality " + distance.dimensionality + "\n");
- }
-
- if(!this.commonPreferenceVector.equals(distance.commonPreferenceVector)) {
- throw new IllegalArgumentException("The common preference vectors of this distance " + "and the specified distance need to be equal.\n" + "this.commonPreferenceVector " + this.commonPreferenceVector + "\n" + "distance.commonPreferenceVector " + distance.commonPreferenceVector + "\n");
- }
-
- return new PreferenceVectorBasedCorrelationDistance(dimensionality, getCorrelationValue() + distance.getCorrelationValue(), getEuclideanValue() + distance.getEuclideanValue(), (BitSet) commonPreferenceVector.clone());
- }
-
- /**
- * @throws IllegalArgumentException if the dimensionality values and common
- * preference vectors of this distance and the specified distance are
- * not equal
- */
- @Override
- public PreferenceVectorBasedCorrelationDistance minus(PreferenceVectorBasedCorrelationDistance distance) {
- if(this.dimensionality != distance.dimensionality) {
- throw new IllegalArgumentException("The dimensionality values of this distance " + "and the specified distance need to be equal.\n" + "this.dimensionality " + this.dimensionality + "\n" + "distance.dimensionality " + distance.dimensionality + "\n");
- }
-
- if(!this.commonPreferenceVector.equals(distance.commonPreferenceVector)) {
- throw new IllegalArgumentException("The common preference vectors of this distance " + "and the specified distance need to be equal.\n" + "this.commonPreferenceVector " + this.commonPreferenceVector + "\n" + "distance.commonPreferenceVector " + distance.commonPreferenceVector + "\n");
- }
-
- return new PreferenceVectorBasedCorrelationDistance(dimensionality, getCorrelationValue() - distance.getCorrelationValue(), getEuclideanValue() - distance.getEuclideanValue(), (BitSet) commonPreferenceVector.clone());
- }
-
- /**
* Checks if the dimensionality values of this distance and the specified
* distance are equal. If the check fails an IllegalArgumentException is
* thrown, otherwise
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancevalue/SubspaceDistance.java b/src/de/lmu/ifi/dbs/elki/distance/distancevalue/SubspaceDistance.java
index 094961b4..bc29b382 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancevalue/SubspaceDistance.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancevalue/SubspaceDistance.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.distancevalue;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -88,16 +88,6 @@ public class SubspaceDistance extends AbstractDistance<SubspaceDistance> {
this.affineDistance = affineDistance;
}
- @Override
- public SubspaceDistance plus(SubspaceDistance distance) {
- return new SubspaceDistance(this.subspaceDistance + distance.subspaceDistance, this.affineDistance + distance.affineDistance);
- }
-
- @Override
- public SubspaceDistance minus(SubspaceDistance distance) {
- return new SubspaceDistance(this.subspaceDistance - distance.subspaceDistance, this.affineDistance - distance.affineDistance);
- }
-
/**
* Returns a string representation of this SubspaceDistance.
*
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancevalue/package-info.java b/src/de/lmu/ifi/dbs/elki/distance/distancevalue/package-info.java
index f302b854..ab0fdd9f 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancevalue/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancevalue/package-info.java
@@ -13,7 +13,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/package-info.java b/src/de/lmu/ifi/dbs/elki/distance/package-info.java
index 801d4314..744c74e1 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/package-info.java
@@ -7,7 +7,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/AbstractDBIDSimilarityFunction.java b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/AbstractDBIDSimilarityFunction.java
index 163438ce..22790a01 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/AbstractDBIDSimilarityFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/AbstractDBIDSimilarityFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.similarityfunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/AbstractIndexBasedSimilarityFunction.java b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/AbstractIndexBasedSimilarityFunction.java
index 039f7f2b..2147bbff 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/AbstractIndexBasedSimilarityFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/AbstractIndexBasedSimilarityFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.similarityfunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -141,7 +141,7 @@ public abstract class AbstractIndexBasedSimilarityFunction<O, I extends Index, R
* @param defaultClass Default class
*/
protected void configIndexFactory(Parameterization config, final Class<?> restrictionClass, final Class<?> defaultClass) {
- final ObjectParameter<F> param = new ObjectParameter<F>(INDEX_ID, restrictionClass, defaultClass);
+ final ObjectParameter<F> param = new ObjectParameter<>(INDEX_ID, restrictionClass, defaultClass);
if(config.grab(param)) {
factory = param.instantiateClass(config);
}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/AbstractPrimitiveSimilarityFunction.java b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/AbstractPrimitiveSimilarityFunction.java
index c408d1bb..2a9c2f88 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/AbstractPrimitiveSimilarityFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/AbstractPrimitiveSimilarityFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.similarityfunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -34,6 +34,8 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
*
* @author Arthur Zimek
*
+ * @apiviz.excludeSubtypes
+ *
* @param <O> object type
* @param <D> distance type
*/
@@ -59,6 +61,6 @@ public abstract class AbstractPrimitiveSimilarityFunction<O, D extends Distance<
@Override
public <T extends O> SimilarityQuery<T, D> instantiate(Relation<T> relation) {
- return new PrimitiveSimilarityQuery<T, D>(relation, this);
+ return new PrimitiveSimilarityQuery<>(relation, this);
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/DBIDSimilarityFunction.java b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/DBIDSimilarityFunction.java
index e7316115..7b6eef34 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/DBIDSimilarityFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/DBIDSimilarityFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.similarityfunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/FractionalSharedNearestNeighborSimilarityFunction.java b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/FractionalSharedNearestNeighborSimilarityFunction.java
index a28790b9..2e0dd52d 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/FractionalSharedNearestNeighborSimilarityFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/FractionalSharedNearestNeighborSimilarityFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.similarityfunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -40,14 +40,11 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameteriz
*
* @author Arthur Zimek
*
- * @apiviz.has
- * de.lmu.ifi.dbs.elki.index.preprocessed.snn.SharedNearestNeighborIndex
- * .Factory
- * @apiviz.uses Instance oneway - - «create»
+ * @apiviz.has de.lmu.ifi.dbs.elki.index.preprocessed.snn.SharedNearestNeighborIndex.Factory
+ * @apiviz.has Instance oneway - - «create»
*
* @param <O> object type
*/
-// todo arthur comment class
public class FractionalSharedNearestNeighborSimilarityFunction<O> extends AbstractIndexBasedSimilarityFunction<O, SharedNearestNeighborIndex<O>, ArrayDBIDs, DoubleDistance> implements NormalizedSimilarityFunction<O, DoubleDistance> {
/**
* Constructor.
@@ -62,7 +59,7 @@ public class FractionalSharedNearestNeighborSimilarityFunction<O> extends Abstra
@Override
public <T extends O> Instance<T> instantiate(Relation<T> database) {
SharedNearestNeighborIndex<O> indexi = indexFactory.instantiate((Relation<O>) database);
- return (Instance<T>) new Instance<O>((Relation<O>) database, indexi);
+ return (Instance<T>) new Instance<>((Relation<O>) database, indexi);
}
/**
@@ -96,17 +93,15 @@ public class FractionalSharedNearestNeighborSimilarityFunction<O> extends Abstra
int intersection = 0;
DBIDIter iter1 = neighbors1.iter();
DBIDIter iter2 = neighbors2.iter();
- while(iter1.valid() && iter2.valid()) {
+ while (iter1.valid() && iter2.valid()) {
final int comp = DBIDUtil.compare(iter1, iter2);
- if(comp == 0) {
+ if (comp == 0) {
intersection++;
iter1.advance();
iter2.advance();
- }
- else if(comp < 0) {
+ } else if (comp < 0) {
iter1.advance();
- }
- else // iter2 < iter1
+ } else // iter2 < iter1
{
iter2.advance();
}
@@ -151,7 +146,7 @@ public class FractionalSharedNearestNeighborSimilarityFunction<O> extends Abstra
@Override
protected FractionalSharedNearestNeighborSimilarityFunction<O> makeInstance() {
- return new FractionalSharedNearestNeighborSimilarityFunction<O>(factory);
+ return new FractionalSharedNearestNeighborSimilarityFunction<>(factory);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/IndexBasedSimilarityFunction.java b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/IndexBasedSimilarityFunction.java
index 29ae9ce3..33192e38 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/IndexBasedSimilarityFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/IndexBasedSimilarityFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.similarityfunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -33,6 +33,7 @@ import de.lmu.ifi.dbs.elki.index.Index;
*
* @author Erich Schubert
*
+ * @apiviz.has Instance oneway - - «create»
* @apiviz.landmark
*
* @param <O> Object type
diff --git a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/InvertedDistanceSimilarityFunction.java b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/InvertedDistanceSimilarityFunction.java
index 2a97a5a3..9c974f17 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/InvertedDistanceSimilarityFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/InvertedDistanceSimilarityFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.similarityfunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -46,7 +46,7 @@ public class InvertedDistanceSimilarityFunction<O> extends AbstractPrimitiveSimi
* </p>
* <p>
* Default value:
- * {@link de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction}
+ * {@link de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction}
* </p>
*/
public static final OptionID DISTANCE_FUNCTION_ID = new OptionID("adapter.distancefunction", "Distance function to derive the similarity between database objects from.");
diff --git a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/Kulczynski1SimilarityFunction.java b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/Kulczynski1SimilarityFunction.java
new file mode 100644
index 00000000..462279d5
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/Kulczynski1SimilarityFunction.java
@@ -0,0 +1,110 @@
+package de.lmu.ifi.dbs.elki.distance.similarityfunction;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
+import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Kulczynski similarity 1.
+ *
+ * Reference:
+ * <p>
+ * M.-M. Deza and E. Deza<br />
+ * Dictionary of distances
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@Reference(authors = "M.-M. Deza and E. Deza", title = "Dictionary of distances", booktitle = "Dictionary of distances")
+public class Kulczynski1SimilarityFunction extends AbstractPrimitiveSimilarityFunction<NumberVector<?>, DoubleDistance> {
+ /**
+ * Static instance.
+ */
+ public static final Kulczynski1SimilarityFunction STATIC = new Kulczynski1SimilarityFunction();
+
+ /**
+ * Constructor.
+ *
+ * @deprecated Use {@link #STATIC} instance instead.
+ */
+ @Deprecated
+ public Kulczynski1SimilarityFunction() {
+ super();
+ }
+
+ @Override
+ public DoubleDistance getDistanceFactory() {
+ return DoubleDistance.FACTORY;
+ }
+
+ @Override
+ public SimpleTypeInformation<? super NumberVector<?>> getInputTypeRestriction() {
+ return TypeUtil.NUMBER_VECTOR_FIELD;
+ }
+
+ @Override
+ public DoubleDistance similarity(NumberVector<?> o1, NumberVector<?> o2) {
+ return new DoubleDistance(doubleSimilarity(o1, o2));
+ }
+
+ /**
+ * Compute the similarity.
+ *
+ * @param v1 First vector
+ * @param v2 Second vector
+ * @return Similarity
+ */
+ public double doubleSimilarity(NumberVector<?> v1, NumberVector<?> v2) {
+ final int dim1 = v1.getDimensionality();
+ if (dim1 != v2.getDimensionality()) {
+ throw new IllegalArgumentException("Different dimensionality of FeatureVectors" + "\n first argument: " + v1.toString() + "\n second argument: " + v2.toString() + "\n" + v1.getDimensionality() + "!=" + v2.getDimensionality());
+ }
+ double sumdiff = 0., summin = 0.;
+ for (int i = 0; i < dim1; i++) {
+ double xi = v1.doubleValue(i), yi = v2.doubleValue(i);
+ sumdiff += Math.abs(xi - yi);
+ summin += Math.min(xi, yi);
+ }
+ return summin / sumdiff;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected Kulczynski1SimilarityFunction makeInstance() {
+ return Kulczynski1SimilarityFunction.STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/Kulczynski2SimilarityFunction.java b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/Kulczynski2SimilarityFunction.java
new file mode 100644
index 00000000..a59010b8
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/Kulczynski2SimilarityFunction.java
@@ -0,0 +1,113 @@
+package de.lmu.ifi.dbs.elki.distance.similarityfunction;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
+import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Kulczynski similarity 2.
+ *
+ * Reference:
+ * <p>
+ * M.-M. Deza and E. Deza<br />
+ * Dictionary of distances
+ * </p>
+ *
+ * TODO: add an optimized version for binary data.
+ *
+ * @author Erich Schubert
+ */
+@Reference(authors = "M.-M. Deza and E. Deza", title = "Dictionary of distances", booktitle = "Dictionary of distances")
+public class Kulczynski2SimilarityFunction extends AbstractPrimitiveSimilarityFunction<NumberVector<?>, DoubleDistance> {
+ /**
+ * Static instance.
+ */
+ public static final Kulczynski2SimilarityFunction STATIC_CONTINUOUS = new Kulczynski2SimilarityFunction();
+
+ /**
+ * Constructor.
+ *
+ * @deprecated Use {@link #STATIC_CONTINUOUS} instance instead.
+ */
+ @Deprecated
+ public Kulczynski2SimilarityFunction() {
+ super();
+ }
+
+ @Override
+ public DoubleDistance getDistanceFactory() {
+ return DoubleDistance.FACTORY;
+ }
+
+ @Override
+ public SimpleTypeInformation<? super NumberVector<?>> getInputTypeRestriction() {
+ return TypeUtil.NUMBER_VECTOR_FIELD;
+ }
+
+ @Override
+ public DoubleDistance similarity(NumberVector<?> o1, NumberVector<?> o2) {
+ return new DoubleDistance(doubleSimilarity(o1, o2));
+ }
+
+ /**
+ * Compute the similarity.
+ *
+ * @param v1 First vector
+ * @param v2 Second vector
+ * @return Similarity
+ */
+ public double doubleSimilarity(NumberVector<?> v1, NumberVector<?> v2) {
+ final int dim1 = v1.getDimensionality();
+ if (dim1 != v2.getDimensionality()) {
+ throw new IllegalArgumentException("Different dimensionality of FeatureVectors" + "\n first argument: " + v1.toString() + "\n second argument: " + v2.toString() + "\n" + v1.getDimensionality() + "!=" + v2.getDimensionality());
+ }
+ double sumx = 0., sumy = 0., summin = 0.;
+ for (int i = 0; i < dim1; i++) {
+ double xi = v1.doubleValue(i), yi = v2.doubleValue(i);
+ sumx += xi;
+ sumy += yi;
+ summin += Math.min(xi, yi);
+ }
+ return dim1 * .5 * (dim1 / sumx + dim1 / sumy) * summin;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected Kulczynski2SimilarityFunction makeInstance() {
+ return Kulczynski2SimilarityFunction.STATIC_CONTINUOUS;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/NormalizedPrimitiveSimilarityFunction.java b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/NormalizedPrimitiveSimilarityFunction.java
index fc86a3bc..6e8bd76a 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/NormalizedPrimitiveSimilarityFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/NormalizedPrimitiveSimilarityFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.similarityfunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/NormalizedSimilarityFunction.java b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/NormalizedSimilarityFunction.java
index b2be1a56..dcfd8e74 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/NormalizedSimilarityFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/NormalizedSimilarityFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.similarityfunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/PrimitiveSimilarityFunction.java b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/PrimitiveSimilarityFunction.java
index b5642d0c..d4d84734 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/PrimitiveSimilarityFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/PrimitiveSimilarityFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.similarityfunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -33,6 +33,7 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
* @author Elke Achtert
*
* @apiviz.landmark
+ * @apiviz.excludeSubtypes
*
* @param <O> object type
* @param <D> distance type
diff --git a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/SharedNearestNeighborSimilarityFunction.java b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/SharedNearestNeighborSimilarityFunction.java
index 3e757778..5faba431 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/SharedNearestNeighborSimilarityFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/SharedNearestNeighborSimilarityFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.similarityfunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -41,7 +41,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameteriz
* @author Arthur Zimek
*
* @apiviz.has de.lmu.ifi.dbs.elki.index.preprocessed.snn.SharedNearestNeighborIndex.Factory
- * @apiviz.uses Instance oneway - - «create»
+ * @apiviz.has Instance oneway - - «create»
*
* @param <O> object type
*/
@@ -94,7 +94,7 @@ public class SharedNearestNeighborSimilarityFunction<O> extends AbstractIndexBas
@Override
public <T extends O> Instance<T> instantiate(Relation<T> database) {
SharedNearestNeighborIndex<O> indexi = indexFactory.instantiate((Relation<O>) database);
- return (Instance<T>) new Instance<O>((Relation<O>) database, indexi);
+ return (Instance<T>) new Instance<>((Relation<O>) database, indexi);
}
/**
@@ -148,7 +148,7 @@ public class SharedNearestNeighborSimilarityFunction<O> extends AbstractIndexBas
@Override
protected SharedNearestNeighborSimilarityFunction<O> makeInstance() {
- return new SharedNearestNeighborSimilarityFunction<O>(factory);
+ return new SharedNearestNeighborSimilarityFunction<>(factory);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/SimilarityFunction.java b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/SimilarityFunction.java
index d8324a80..0e3f4ce6 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/SimilarityFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/SimilarityFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.similarityfunction;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/kernel/FooKernelFunction.java b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/kernel/FooKernelFunction.java
index be9ba959..d56b3f04 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/kernel/FooKernelFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/kernel/FooKernelFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.similarityfunction.kernel;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -107,7 +107,7 @@ public class FooKernelFunction extends AbstractPrimitiveDistanceFunction<NumberV
@Override
public <T extends NumberVector<?>> DistanceSimilarityQuery<T, DoubleDistance> instantiate(Relation<T> database) {
- return new PrimitiveDistanceSimilarityQuery<T, DoubleDistance>(database, this, this);
+ return new PrimitiveDistanceSimilarityQuery<>(database, this, this);
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/kernel/KernelMatrix.java b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/kernel/KernelMatrix.java
index 50dd0b4f..ed3731ba 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/kernel/KernelMatrix.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/kernel/KernelMatrix.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.similarityfunction.kernel;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/kernel/LinearKernelFunction.java b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/kernel/LinearKernelFunction.java
index ffd2d0e3..0ae44b29 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/kernel/LinearKernelFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/kernel/LinearKernelFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.similarityfunction.kernel;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -92,6 +92,6 @@ public class LinearKernelFunction<O extends NumberVector<?>> extends AbstractPri
@Override
public <T extends O> DistanceSimilarityQuery<T, DoubleDistance> instantiate(Relation<T> database) {
- return new PrimitiveDistanceSimilarityQuery<T, DoubleDistance>(database, this, this);
+ return new PrimitiveDistanceSimilarityQuery<>(database, this, this);
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/kernel/PolynomialKernelFunction.java b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/kernel/PolynomialKernelFunction.java
index 1a7f97f5..07963962 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/kernel/PolynomialKernelFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/kernel/PolynomialKernelFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.distance.similarityfunction.kernel;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -107,7 +107,7 @@ public class PolynomialKernelFunction extends AbstractPrimitiveDistanceFunction<
@Override
public <T extends NumberVector<?>> DistanceSimilarityQuery<T, DoubleDistance> instantiate(Relation<T> database) {
- return new PrimitiveDistanceSimilarityQuery<T, DoubleDistance>(database, this, this);
+ return new PrimitiveDistanceSimilarityQuery<>(database, this, this);
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/kernel/package-info.java b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/kernel/package-info.java
index 6d2e46fc..ec847f80 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/kernel/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/kernel/package-info.java
@@ -7,7 +7,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/package-info.java b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/package-info.java
index ba53fba3..6e5ad0e0 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/package-info.java
@@ -7,7 +7,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/AutomaticEvaluation.java b/src/de/lmu/ifi/dbs/elki/evaluation/AutomaticEvaluation.java
index 65a4771e..fe2e1dc5 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/AutomaticEvaluation.java
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/AutomaticEvaluation.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.evaluation;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,9 +27,10 @@ import java.util.Collection;
import java.util.Iterator;
import java.util.regex.Pattern;
-import de.lmu.ifi.dbs.elki.algorithm.clustering.trivial.ByLabelOrAllInOneClustering;
+import de.lmu.ifi.dbs.elki.algorithm.clustering.trivial.ByLabelClustering;
import de.lmu.ifi.dbs.elki.data.Cluster;
import de.lmu.ifi.dbs.elki.data.Clustering;
+import de.lmu.ifi.dbs.elki.data.type.NoSupportedDataTypeException;
import de.lmu.ifi.dbs.elki.evaluation.clustering.EvaluateClustering;
import de.lmu.ifi.dbs.elki.evaluation.histogram.ComputeOutlierHistogram;
import de.lmu.ifi.dbs.elki.evaluation.outlier.OutlierPrecisionAtKCurve;
@@ -72,13 +73,13 @@ public class AutomaticEvaluation implements Evaluator {
protected void autoEvaluateOutliers(HierarchicalResult baseResult, Result newResult) {
Collection<OutlierResult> outliers = ResultUtil.filterResults(newResult, OutlierResult.class);
- if(LOG.isDebugging()) {
+ if (LOG.isDebugging()) {
LOG.debug("Number of new outlier results: " + outliers.size());
}
- if(outliers.size() > 0) {
+ if (outliers.size() > 0) {
ResultUtil.ensureClusteringResult(ResultUtil.findDatabase(baseResult), baseResult);
Collection<Clustering<?>> clusterings = ResultUtil.filterResults(baseResult, Clustering.class);
- if(clusterings.size() == 0) {
+ if (clusterings.size() == 0) {
LOG.warning("Could not find a clustering result, even after running 'ensureClusteringResult'?!?");
return;
}
@@ -87,24 +88,24 @@ public class AutomaticEvaluation implements Evaluator {
int min = Integer.MAX_VALUE;
int total = 0;
String label = null;
- if(basec.getAllClusters().size() > 1) {
- for(Cluster<?> c : basec.getAllClusters()) {
+ if (basec.getAllClusters().size() > 1) {
+ for (Cluster<?> c : basec.getAllClusters()) {
final int csize = c.getIDs().size();
total += csize;
- if(csize < min) {
+ if (csize < min) {
min = csize;
label = c.getName();
}
}
}
- if(label == null) {
+ if (label == null) {
LOG.warning("Could not evaluate outlier results, as I could not find a minority label.");
return;
}
- if(min == 1) {
+ if (min == 1) {
LOG.warning("The minority class label had a single object. Try using 'ClassLabelFilter' to identify the class label column.");
}
- if(min > 0.05 * total) {
+ if (min > 0.05 * total) {
LOG.warning("The minority class I discovered (labeled '" + label + "') has " + (min * 100. / total) + "% of objects. Outlier classes should be more rare!");
}
LOG.verbose("Evaluating using minority class: " + label);
@@ -122,26 +123,27 @@ public class AutomaticEvaluation implements Evaluator {
protected void autoEvaluateClusterings(HierarchicalResult baseResult, Result newResult) {
Collection<Clustering<?>> clusterings = ResultUtil.filterResults(newResult, Clustering.class);
- if(LOG.isDebugging()) {
+ if (LOG.isDebugging()) {
LOG.warning("Number of new clustering results: " + clusterings.size());
}
for (Iterator<Clustering<?>> c = clusterings.iterator(); c.hasNext();) {
Clustering<?> test = c.next();
if ("allinone-clustering".equals(test.getShortName())) {
c.remove();
- }
- else if ("allinnoise-clustering".equals(test.getShortName())) {
+ } else if ("allinnoise-clustering".equals(test.getShortName())) {
c.remove();
- }
- else if ("bylabel-clustering".equals(test.getShortName())) {
+ } else if ("bylabel-clustering".equals(test.getShortName())) {
c.remove();
- }
- else if ("bymodel-clustering".equals(test.getShortName())) {
+ } else if ("bymodel-clustering".equals(test.getShortName())) {
c.remove();
}
}
if (clusterings.size() > 0) {
- new EvaluateClustering(new ByLabelOrAllInOneClustering(), false, true).processNewResult(baseResult, newResult);
+ try {
+ new EvaluateClustering(new ByLabelClustering(), false, true).processNewResult(baseResult, newResult);
+ } catch (NoSupportedDataTypeException e) {
+ // Pass - the data probably did not have labels.
+ }
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/Evaluator.java b/src/de/lmu/ifi/dbs/elki/evaluation/Evaluator.java
index 61a1bb63..140b29ef 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/Evaluator.java
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/Evaluator.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.evaluation;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -30,6 +30,8 @@ import de.lmu.ifi.dbs.elki.result.ResultProcessor;
* evaluations, ...
*
* @author Erich Schubert
+ *
+ * @apiviz.excludeSubtypes
*/
public interface Evaluator extends ResultProcessor {
// Empty now - uses ResultProcessor API and serves merely UI purposes.
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/NoAutomaticEvaluation.java b/src/de/lmu/ifi/dbs/elki/evaluation/NoAutomaticEvaluation.java
index efe3d1ac..640a8c9d 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/NoAutomaticEvaluation.java
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/NoAutomaticEvaluation.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.evaluation;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/clustering/BCubed.java b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/BCubed.java
index fdfaaaa9..3353b593 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/clustering/BCubed.java
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/BCubed.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.evaluation.clustering;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/clustering/ClusterContingencyTable.java b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/ClusterContingencyTable.java
index c77c7438..c3f8129f 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/clustering/ClusterContingencyTable.java
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/ClusterContingencyTable.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.evaluation.clustering;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/clustering/EditDistance.java b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/EditDistance.java
index 9a0f63f8..6bbda98a 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/clustering/EditDistance.java
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/EditDistance.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.evaluation.clustering;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,7 +26,7 @@ import de.lmu.ifi.dbs.elki.evaluation.clustering.ClusterContingencyTable.Util;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
/**
- * Edit distance measures
+ * Edit distance measures.
*
* <p>
* Pantel, P. and Lin, D.<br />
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/clustering/Entropy.java b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/Entropy.java
index b174f3ed..58f19f65 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/clustering/Entropy.java
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/Entropy.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.evaluation.clustering;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,18 +25,18 @@ package de.lmu.ifi.dbs.elki.evaluation.clustering;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
/**
- * Entropy based measures
+ * Entropy based measures.
*
* References:
* <p>
* Meilă, M.<br />
* Comparing clusterings by the variation of information<br />
- * Learning theory and kernel machines Volume 2777/2003
+ * Learning theory and kernel machines
* </p>
*
* @author Sascha Goldhofer
*/
-@Reference(authors = "Meilă, M.", title = "Comparing clusterings by the variation of information", booktitle = "Learning theory and kernel machines Volume 2777/2003", url = "http://dx.doi.org/10.1007/978-3-540-45167-9_14")
+@Reference(authors = "Meilă, M.", title = "Comparing clusterings by the variation of information", booktitle = "Learning theory and kernel machines", url = "http://dx.doi.org/10.1007/978-3-540-45167-9_14")
public class Entropy {
/**
* Entropy in first
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/clustering/EvaluateClustering.java b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/EvaluateClustering.java
index 2cbd1024..6db25736 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/clustering/EvaluateClustering.java
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/EvaluateClustering.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.evaluation.clustering;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -268,7 +268,7 @@ public class EvaluateClustering implements Evaluator {
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- ObjectParameter<ClusteringAlgorithm<?>> referencealgP = new ObjectParameter<ClusteringAlgorithm<?>>(REFERENCE_ID, ClusteringAlgorithm.class, ByLabelOrAllInOneClustering.class);
+ ObjectParameter<ClusteringAlgorithm<?>> referencealgP = new ObjectParameter<>(REFERENCE_ID, ClusteringAlgorithm.class, ByLabelOrAllInOneClustering.class);
if(config.grab(referencealgP)) {
referencealg = referencealgP.instantiateClass(config);
}
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/clustering/PairCounting.java b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/PairCounting.java
index 903a0bee..24aa17ff 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/clustering/PairCounting.java
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/PairCounting.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.evaluation.clustering;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/clustering/SetMatchingPurity.java b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/SetMatchingPurity.java
index 0cc79b45..1a003117 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/clustering/SetMatchingPurity.java
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/SetMatchingPurity.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.evaluation.clustering;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,7 +26,7 @@ import de.lmu.ifi.dbs.elki.evaluation.clustering.ClusterContingencyTable.Util;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
/**
- * Set matching purity measures
+ * Set matching purity measures.
*
* References:
* <p>
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/clustering/package-info.java b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/package-info.java
index 0b61fa75..7dc244fd 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/clustering/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/clustering/pairsegments/ClusterPairSegmentAnalysis.java b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/pairsegments/ClusterPairSegmentAnalysis.java
index 123cd4a1..76508563 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/clustering/pairsegments/ClusterPairSegmentAnalysis.java
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/pairsegments/ClusterPairSegmentAnalysis.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.evaluation.clustering.pairsegments;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/clustering/pairsegments/Segment.java b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/pairsegments/Segment.java
index 23621d83..76769d78 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/clustering/pairsegments/Segment.java
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/pairsegments/Segment.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.evaluation.clustering.pairsegments;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/clustering/pairsegments/Segments.java b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/pairsegments/Segments.java
index 507c2ebb..b7215579 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/clustering/pairsegments/Segments.java
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/pairsegments/Segments.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.evaluation.clustering.pairsegments;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -131,10 +131,10 @@ public class Segments extends BasicResult implements Iterable<Segment> {
super("cluster pair segments", "pair-segments");
this.clusterings = clusterings;
this.clusteringsCount = clusterings.size();
- segments = new TreeMap<Segment, Segment>(); // TODO: replace with array list
+ segments = new TreeMap<>(); // TODO: replace with array list
numclusters = new int[clusteringsCount];
- clusters = new ArrayList<List<? extends Cluster<?>>>(clusteringsCount);
+ clusters = new ArrayList<>(clusteringsCount);
// save count of clusters
int clusteringIndex = 0;
@@ -289,7 +289,7 @@ public class Segments extends BasicResult implements Iterable<Segment> {
* segment
*/
public List<Segment> getPairedSegments(Segment unpairedSegment) {
- ArrayList<Segment> pairedSegments = new ArrayList<Segment>();
+ ArrayList<Segment> pairedSegments = new ArrayList<>();
// search the segments. Index at "unpairedClustering" being the wildcard.
segments: for(Segment segment : this) {
// if mismatch except at unpaired Clustering index => exclude.
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/clustering/pairsegments/package-info.java b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/pairsegments/package-info.java
index 27176ff6..01d0d09a 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/clustering/pairsegments/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/pairsegments/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/histogram/ComputeOutlierHistogram.java b/src/de/lmu/ifi/dbs/elki/evaluation/histogram/ComputeOutlierHistogram.java
index a49db68b..cb740e3e 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/histogram/ComputeOutlierHistogram.java
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/histogram/ComputeOutlierHistogram.java
@@ -34,7 +34,7 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.evaluation.Evaluator;
import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
import de.lmu.ifi.dbs.elki.result.HistogramResult;
@@ -233,13 +233,13 @@ public class ComputeOutlierHistogram implements Evaluator {
result = scaling.getScaled(result);
hist.putData(result, positive);
}
- Collection<DoubleVector> collHist = new ArrayList<DoubleVector>(hist.getNumBins());
+ Collection<DoubleVector> collHist = new ArrayList<>(hist.getNumBins());
for (ObjHistogram.Iter<DoubleDoublePair> iter = hist.iter(); iter.valid(); iter.advance()) {
DoubleDoublePair data = iter.getValue();
DoubleVector row = new DoubleVector(new double[] { iter.getCenter(), data.first, data.second });
collHist.add(row);
}
- return new HistogramResult<DoubleVector>("Outlier Score Histogram", "outlier-histogram", collHist);
+ return new HistogramResult<>("Outlier Score Histogram", "outlier-histogram", collHist);
}
@Override
@@ -299,7 +299,7 @@ public class ComputeOutlierHistogram implements Evaluator {
bins = binsP.getValue();
}
- ObjectParameter<ScalingFunction> scalingP = new ObjectParameter<ScalingFunction>(SCALING_ID, ScalingFunction.class, IdentityScaling.class);
+ ObjectParameter<ScalingFunction> scalingP = new ObjectParameter<>(SCALING_ID, ScalingFunction.class, IdentityScaling.class);
if (config.grab(scalingP)) {
scaling = scalingP.instantiateClass(config);
}
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/histogram/package-info.java b/src/de/lmu/ifi/dbs/elki/evaluation/histogram/package-info.java
index e02426d7..a07bcc30 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/histogram/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/histogram/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/index/IndexPurity.java b/src/de/lmu/ifi/dbs/elki/evaluation/index/IndexPurity.java
index 3fc928a9..ac0f3457 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/index/IndexPurity.java
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/index/IndexPurity.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.evaluation.index;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -76,7 +76,7 @@ public class IndexPurity implements Evaluator {
Node<?> n = index.getNode(leaf.getEntryID());
final int total = n.getNumEntries();
- HashMap<String, Integer> map = new HashMap<String, Integer>(total);
+ HashMap<String, Integer> map = new HashMap<>(total);
for(int i = 0; i < total; i++) {
DBID id = ((SpatialPointLeafEntry) n.getEntry(i)).getDBID();
String label = lblrel.get(id);
@@ -96,9 +96,9 @@ public class IndexPurity implements Evaluator {
}
mv.put(gini);
}
- Collection<DoubleVector> col = new ArrayList<DoubleVector>();
+ Collection<DoubleVector> col = new ArrayList<>();
col.add(new DoubleVector(new double[] { mv.getMean(), mv.getSampleStddev() }));
- database.getHierarchy().add((Result) index, new CollectionResult<DoubleVector>("Gini coefficient of index", "index-gini", col));
+ database.getHierarchy().add((Result) index, new CollectionResult<>("Gini coefficient of index", "index-gini", col));
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/index/IndexStatistics.java b/src/de/lmu/ifi/dbs/elki/evaluation/index/IndexStatistics.java
index cce2c79f..f7c9caa8 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/index/IndexStatistics.java
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/index/IndexStatistics.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.evaluation.index;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -61,10 +61,10 @@ public class IndexStatistics implements Evaluator {
return;
}
for(IndexTree<?, ?> index : indexes) {
- header = new ArrayList<String>();
+ header = new ArrayList<>();
header.add(index.toString());
}
- Collection<Pair<String, String>> col = new ArrayList<Pair<String, String>>();
+ Collection<Pair<String, String>> col = new ArrayList<>();
IndexMetaResult analysis = new IndexMetaResult(col, header);
db.getHierarchy().add(db, analysis);
}
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/index/package-info.java b/src/de/lmu/ifi/dbs/elki/evaluation/index/package-info.java
index 2532b148..67fdaa98 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/index/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/index/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/outlier/JudgeOutlierScores.java b/src/de/lmu/ifi/dbs/elki/evaluation/outlier/JudgeOutlierScores.java
index 2ffe4e05..1639515a 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/outlier/JudgeOutlierScores.java
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/outlier/JudgeOutlierScores.java
@@ -33,7 +33,7 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.evaluation.Evaluator;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
@@ -161,7 +161,7 @@ public class JudgeOutlierScores implements Evaluator {
LOG.verbose("Scores: " + posscore + " " + negscore);
- ArrayList<Vector> s = new ArrayList<Vector>(1);
+ ArrayList<Vector> s = new ArrayList<>(1);
s.add(new Vector(new double[] { (posscore + negscore) * .5, posscore, negscore }));
return new ScoreResult(s);
}
@@ -226,7 +226,7 @@ public class JudgeOutlierScores implements Evaluator {
positiveClassName = positiveClassNameP.getValue();
}
- ObjectParameter<ScalingFunction> scalingP = new ObjectParameter<ScalingFunction>(SCALING_ID, ScalingFunction.class, IdentityScaling.class);
+ ObjectParameter<ScalingFunction> scalingP = new ObjectParameter<>(SCALING_ID, ScalingFunction.class, IdentityScaling.class);
if (config.grab(scalingP)) {
scaling = scalingP.instantiateClass(config);
}
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/outlier/OutlierPrecisionAtKCurve.java b/src/de/lmu/ifi/dbs/elki/evaluation/outlier/OutlierPrecisionAtKCurve.java
index 11a98876..72967d58 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/outlier/OutlierPrecisionAtKCurve.java
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/outlier/OutlierPrecisionAtKCurve.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.evaluation.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/outlier/OutlierPrecisionRecallCurve.java b/src/de/lmu/ifi/dbs/elki/evaluation/outlier/OutlierPrecisionRecallCurve.java
index bc58355b..a3d9d92f 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/outlier/OutlierPrecisionRecallCurve.java
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/outlier/OutlierPrecisionRecallCurve.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.evaluation.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/outlier/OutlierROCCurve.java b/src/de/lmu/ifi/dbs/elki/evaluation/outlier/OutlierROCCurve.java
index 3baa642b..0d92c50a 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/outlier/OutlierROCCurve.java
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/outlier/OutlierROCCurve.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.evaluation.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -40,6 +40,7 @@ import de.lmu.ifi.dbs.elki.result.Result;
import de.lmu.ifi.dbs.elki.result.ResultUtil;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
import de.lmu.ifi.dbs.elki.result.textwriter.TextWriterStream;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
import de.lmu.ifi.dbs.elki.utilities.DatabaseUtil;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
@@ -65,7 +66,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.PatternParameter;
* @apiviz.uses ROC
* @apiviz.has ROCResult oneway - - «create»
*/
-// TODO: maybe add a way to process clustering results as well?
+@Alias({ "ComputeROCCurve", "de.lmu.ifi.dbs.elki.evaluation.roc.ComputeROCCurve" })
public class OutlierROCCurve implements Evaluator {
/**
* The label we use for marking ROCAUC values.
@@ -102,12 +103,12 @@ public class OutlierROCCurve implements Evaluator {
}
private ROCResult computeROCResult(int size, SetDBIDs positiveids, DBIDs order) {
- if(order.size() != size) {
+ if (order.size() != size) {
throw new IllegalStateException("Iterable result doesn't match database size - incomplete ordering?");
}
- XYCurve roccurve = ROC.materializeROC(size, positiveids, new ROC.SimpleAdapter(order.iter()));
+ XYCurve roccurve = ROC.materializeROC(new ROC.DBIDsTest(positiveids), new ROC.SimpleAdapter(order.iter()));
double rocauc = XYCurve.areaUnderCurve(roccurve);
- if(LOG.isVerbose()) {
+ if (LOG.isVerbose()) {
LOG.verbose(ROCAUC_LABEL + ": " + rocauc);
}
@@ -117,9 +118,9 @@ public class OutlierROCCurve implements Evaluator {
}
private ROCResult computeROCResult(int size, SetDBIDs positiveids, OutlierResult or) {
- XYCurve roccurve = ROC.materializeROC(size, positiveids, new ROC.OutlierScoreAdapter(or));
+ XYCurve roccurve = ROC.materializeROC(new ROC.DBIDsTest(positiveids), new ROC.OutlierScoreAdapter(or));
double rocauc = XYCurve.areaUnderCurve(roccurve);
- if(LOG.isVerbose()) {
+ if (LOG.isVerbose()) {
LOG.verbose(ROCAUC_LABEL + ": " + rocauc);
}
@@ -134,7 +135,7 @@ public class OutlierROCCurve implements Evaluator {
// Prepare
SetDBIDs positiveids = DBIDUtil.ensureSet(DatabaseUtil.getObjectsByLabelMatch(db, positiveClassName));
- if(positiveids.size() == 0) {
+ if (positiveids.size() == 0) {
LOG.warning("Computing a ROC curve failed - no objects matched.");
return;
}
@@ -143,7 +144,7 @@ public class OutlierROCCurve implements Evaluator {
List<OutlierResult> oresults = ResultUtil.getOutlierResults(result);
List<OrderingResult> orderings = ResultUtil.getOrderingResults(result);
// Outlier results are the main use case.
- for(OutlierResult o : oresults) {
+ for (OutlierResult o : oresults) {
db.getHierarchy().add(o, computeROCResult(o.getScores().size(), positiveids, o));
// Process them only once.
orderings.remove(o.getOrdering());
@@ -152,13 +153,13 @@ public class OutlierROCCurve implements Evaluator {
// FIXME: find appropriate place to add the derived result
// otherwise apply an ordering to the database IDs.
- for(OrderingResult or : orderings) {
+ for (OrderingResult or : orderings) {
DBIDs sorted = or.iter(or.getDBIDs());
db.getHierarchy().add(or, computeROCResult(or.getDBIDs().size(), positiveids, sorted));
nonefound = false;
}
- if(nonefound) {
+ if (nonefound) {
return;
// logger.warning("No results found to process with ROC curve analyzer. Got "+iterables.size()+" iterables, "+orderings.size()+" orderings.");
}
@@ -228,7 +229,7 @@ public class OutlierROCCurve implements Evaluator {
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
PatternParameter positiveClassNameP = new PatternParameter(POSITIVE_CLASS_NAME_ID);
- if(config.grab(positiveClassNameP)) {
+ if (config.grab(positiveClassNameP)) {
positiveClassName = positiveClassNameP.getValue();
}
}
@@ -238,4 +239,4 @@ public class OutlierROCCurve implements Evaluator {
return new OutlierROCCurve(positiveClassName);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/outlier/OutlierSmROCCurve.java b/src/de/lmu/ifi/dbs/elki/evaluation/outlier/OutlierSmROCCurve.java
index 0cd3d9ea..71ec42f5 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/outlier/OutlierSmROCCurve.java
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/outlier/OutlierSmROCCurve.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.evaluation.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/outlier/OutlierThresholdClustering.java b/src/de/lmu/ifi/dbs/elki/evaluation/outlier/OutlierThresholdClustering.java
index 5d5173ca..04233378 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/outlier/OutlierThresholdClustering.java
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/outlier/OutlierThresholdClustering.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.evaluation.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -92,7 +92,7 @@ public class OutlierThresholdClustering implements Evaluator {
if(scaling instanceof OutlierScalingFunction) {
((OutlierScalingFunction) scaling).prepare(or);
}
- ArrayList<ModifiableDBIDs> idlists = new ArrayList<ModifiableDBIDs>(threshold.length + 1);
+ ArrayList<ModifiableDBIDs> idlists = new ArrayList<>(threshold.length + 1);
for(int i = 0; i <= threshold.length; i++) {
idlists.add(DBIDUtil.newHashSet());
}
@@ -109,10 +109,10 @@ public class OutlierThresholdClustering implements Evaluator {
}
idlists.get(i).add(iter);
}
- Clustering<Model> c = new Clustering<Model>("Outlier threshold clustering", "threshold-clustering");
+ Clustering<Model> c = new Clustering<>("Outlier threshold clustering", "threshold-clustering");
for(int i = 0; i <= threshold.length; i++) {
String name = (i == 0) ? "Inlier" : "Outlier_" + threshold[i - 1];
- c.addCluster(new Cluster<Model>(name, idlists.get(i), (i > 0)));
+ c.addToplevelCluster(new Cluster<>(name, idlists.get(i), (i > 0)));
}
return c;
}
@@ -154,7 +154,7 @@ public class OutlierThresholdClustering implements Evaluator {
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- ObjectParameter<ScalingFunction> scalingP = new ObjectParameter<ScalingFunction>(SCALING_ID, ScalingFunction.class, IdentityScaling.class);
+ ObjectParameter<ScalingFunction> scalingP = new ObjectParameter<>(SCALING_ID, ScalingFunction.class, IdentityScaling.class);
if(config.grab(scalingP)) {
scaling = scalingP.instantiateClass(config);
}
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/outlier/package-info.java b/src/de/lmu/ifi/dbs/elki/evaluation/outlier/package-info.java
index f85a1c3a..1e5e6933 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/outlier/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/outlier/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/package-info.java b/src/de/lmu/ifi/dbs/elki/evaluation/package-info.java
index f48a8e9f..8b8a96dc 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/roc/ROC.java b/src/de/lmu/ifi/dbs/elki/evaluation/roc/ROC.java
index 558dfb94..0ca42b29 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/roc/ROC.java
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/roc/ROC.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.evaluation.roc;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,26 +23,22 @@ package de.lmu.ifi.dbs.elki.evaluation.roc;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.Iterator;
-import java.util.Set;
-
import de.lmu.ifi.dbs.elki.data.Cluster;
+import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDPair;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
-import de.lmu.ifi.dbs.elki.database.ids.DistanceDBIDPair;
-import de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDPair;
-import de.lmu.ifi.dbs.elki.database.ids.SetDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultIter;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.math.geometry.XYCurve;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
-import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
-import de.lmu.ifi.dbs.elki.utilities.pairs.PairInterface;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arrays.IntegerArrayQuickSort;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arrays.IntegerComparator;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.iterator.ArrayIter;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.iterator.Iter;
/**
* Compute ROC (Receiver Operating Characteristics) curves.
@@ -63,56 +59,36 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.PairInterface;
*
* @author Erich Schubert
*
- * @apiviz.uses SimpleAdapter
- * @apiviz.uses DistanceResultAdapter
- * @apiviz.uses OutlierScoreAdapter
+ * @apiviz.composedOf ScoreIter
+ * @apiviz.composedOf Predicate
+ * @apiviz.has XYCurve
*/
-// TODO: add lazy Iterator<> based results that do not require full
-// materialization
public class ROC {
/**
- * Compute a ROC curve given a set of positive IDs and a sorted list of
- * (comparable, ID)s, where the comparable object is used to decided when two
- * objects are interchangeable.
+ * Iterator for comparing scores.
*
- * @param <C> Reference type
- * @param size Database size
- * @param ids Collection of positive IDs, should support efficient contains()
- * @param nei List of neighbors along with some comparable object to detect
- * 'same positions'.
- * @return area under curve
+ * @author Erich Schubert
*/
- public static <C extends Comparable<? super C>, T> XYCurve materializeROC(int size, Set<? super T> ids, Iterator<? extends PairInterface<C, T>> nei) {
- final int postot = ids.size(), negtot = size - postot;
- int poscnt = 0, negcnt = 0;
- XYCurve curve = new XYCurve("False Positive Rate", "True Positive Rate", postot + 2);
-
- // start in bottom left
- curve.add(0.0, 0.0);
+ public static interface ScoreIter extends Iter {
+ /**
+ * Test whether the score is the same as the previous objects score.
+ *
+ * When there is no previous result, implementations should return false!
+ *
+ * @return Boolean
+ */
+ boolean tiedToPrevious();
+ }
- C prevval = null;
- while(nei.hasNext()) {
- // Analyze next point
- PairInterface<C, T> cur = nei.next();
- // positive or negative match?
- if(ids.contains(cur.getSecond())) {
- poscnt += 1;
- }
- else {
- negcnt += 1;
- }
- // defer calculation for ties
- if((prevval != null) && (prevval.compareTo(cur.getFirst()) == 0)) {
- continue;
- }
- // Add a new point.
- curve.addAndSimplify(negcnt / (double) negtot, poscnt / (double) postot);
- prevval = cur.getFirst();
- }
- // Ensure we end up in the top right corner.
- // Simplification will skip this if we already were.
- curve.addAndSimplify(1.0, 1.0);
- return curve;
+ /**
+ * Predicate to test whether an object is a true positive or false positive.
+ *
+ * @author Erich Schubert
+ *
+ * @param <T> Data type
+ */
+ public static interface Predicate<T> {
+ boolean test(T o);
}
/**
@@ -120,46 +96,36 @@ public class ROC {
* (comparable, ID)s, where the comparable object is used to decided when two
* objects are interchangeable.
*
- * @param <C> Reference type
- * @param size Database size
- * @param ids Collection of positive IDs, should support efficient contains()
- * @param nei List of neighbors along with some comparable object to detect
- * 'same positions'.
+ * @param <I> Iterator type
+ * @param predicate Predicate to test for positive objects
+ * @param iter Iterator over results, with ties.
* @return area under curve
*/
- public static <C extends Comparable<? super C>> XYCurve materializeROC(int size, SetDBIDs ids, Iterator<? extends PairInterface<C, ? extends DBIDRef>> nei) {
- final int postot = ids.size(), negtot = size - postot;
+ public static <I extends ScoreIter> XYCurve materializeROC(Predicate<? super I> predicate, I iter) {
int poscnt = 0, negcnt = 0;
- XYCurve curve = new XYCurve("False Positive Rate", "True Positive Rate", postot + 2);
+ XYCurve curve = new XYCurve("False Positive Rate", "True Positive Rate");
// start in bottom left
curve.add(0.0, 0.0);
- C prevval = null;
- while(nei.hasNext()) {
- // Rates at *previous* data point. Because of tie handling strategy!
- final double trueneg = negcnt / (double) negtot;
- final double truepos = poscnt / (double) postot;
- // Analyze next point
- PairInterface<C, ? extends DBIDRef> cur = nei.next();
+ while (iter.valid()) {
// positive or negative match?
- if(ids.contains(cur.getSecond())) {
- poscnt += 1;
- }
- else {
- negcnt += 1;
- }
- // defer calculation for ties
- if((prevval != null) && (prevval.compareTo(cur.getFirst()) == 0)) {
- continue;
- }
- // Add point for *previous* result (since we are no longer tied with it)
- curve.addAndSimplify(trueneg, truepos);
- prevval = cur.getFirst();
+ do {
+ if (predicate.test(iter)) {
+ ++poscnt;
+ } else {
+ ++negcnt;
+ }
+ iter.advance();
+ } // Loop while tied:
+ while (iter.valid() && iter.tiedToPrevious());
+ // Add a new point.
+ curve.addAndSimplify(negcnt, poscnt);
}
// Ensure we end up in the top right corner.
// Simplification will skip this if we already were.
- curve.addAndSimplify(1.0, 1.0);
+ curve.addAndSimplify(negcnt, poscnt);
+ curve.rescale(1. / negcnt, 1. / poscnt);
return curve;
}
@@ -172,8 +138,10 @@ public class ROC {
* The ROC values would be incorrect then anyway!
*
* @author Erich Schubert
+ *
+ * @apiviz.composedOf DBIDIter
*/
- public static class SimpleAdapter implements Iterator<DBIDPair> {
+ public static class SimpleAdapter implements ScoreIter, DBIDRef {
/**
* Original Iterator
*/
@@ -190,20 +158,35 @@ public class ROC {
}
@Override
- public boolean hasNext() {
- return this.iter.valid();
+ public boolean valid() {
+ return iter.valid();
+ }
+
+ @Override
+ public void advance() {
+ iter.advance();
+ }
+
+ @Override
+ public boolean tiedToPrevious() {
+ return false; // No information.
+ }
+
+ @Override
+ public int internalGetIndex() {
+ return iter.internalGetIndex();
}
+ @Deprecated
@Override
- public DBIDPair next() {
- DBIDPair pair = DBIDUtil.newPair(iter, iter);
- this.iter.advance();
- return pair;
+ public int hashCode() {
+ return super.hashCode();
}
+ @Deprecated
@Override
- public void remove() {
- throw new UnsupportedOperationException();
+ public boolean equals(Object obj) {
+ return super.equals(obj);
}
}
@@ -216,39 +199,63 @@ public class ROC {
* The ROC values would be incorrect then anyway!
*
* @author Erich Schubert
+ *
+ * @apiviz.composedOf DistanceDBIDListIter
+ *
* @param <D> Distance type
*/
- public static class DistanceResultAdapter<D extends Distance<D>> implements Iterator<Pair<D, DBIDRef>> {
+ public static class DistanceResultAdapter<D extends Distance<D>> implements ScoreIter, DBIDRef {
/**
* Original Iterator
*/
- private DistanceDBIDResultIter<D> iter;
+ private DistanceDBIDListIter<D> iter;
+
+ /**
+ * Distance of previous.
+ */
+ private D prevDist = null;
/**
* Constructor
*
* @param iter Iterator for distance results
*/
- public DistanceResultAdapter(DistanceDBIDResultIter<D> iter) {
+ public DistanceResultAdapter(DistanceDBIDListIter<D> iter) {
super();
this.iter = iter;
}
@Override
- public boolean hasNext() {
- return this.iter.valid();
+ public boolean valid() {
+ return iter.valid();
}
@Override
- public Pair<D, DBIDRef> next() {
- DistanceDBIDPair<D> d = this.iter.getDistancePair();
- this.iter.advance();
- return new Pair<D, DBIDRef>(d.getDistance(), d);
+ public void advance() {
+ prevDist = iter.getDistance();
+ iter.advance();
}
@Override
- public void remove() {
- throw new UnsupportedOperationException();
+ public int internalGetIndex() {
+ return iter.internalGetIndex();
+ }
+
+ @Override
+ public boolean tiedToPrevious() {
+ return iter.getDistance().equals(prevDist);
+ }
+
+ @Deprecated
+ @Override
+ public int hashCode() {
+ return super.hashCode();
+ }
+
+ @Deprecated
+ @Override
+ public boolean equals(Object obj) {
+ return super.equals(obj);
}
}
@@ -261,19 +268,26 @@ public class ROC {
* The ROC values would be incorrect then anyway!
*
* @author Erich Schubert
+ *
+ * @apiviz.composedOf OutlierResult
*/
- public static class OutlierScoreAdapter implements Iterator<DoubleDBIDPair> {
+ public static class OutlierScoreAdapter implements ScoreIter, DBIDRef {
/**
- * Original Iterator
+ * Original iterator.
*/
private DBIDIter iter;
/**
- * Outlier score
+ * Outlier score.
*/
private Relation<Double> scores;
/**
+ * Previous value.
+ */
+ double prev = Double.NaN;
+
+ /**
* Constructor.
*
* @param o Result
@@ -285,20 +299,315 @@ public class ROC {
}
@Override
- public boolean hasNext() {
- return this.iter.valid();
+ public boolean valid() {
+ return iter.valid();
}
@Override
- public DoubleDBIDPair next() {
- DoubleDBIDPair pair = DBIDUtil.newPair(scores.get(iter), iter);
+ public void advance() {
+ prev = scores.get(iter);
iter.advance();
- return pair;
}
@Override
- public void remove() {
- throw new UnsupportedOperationException();
+ public boolean tiedToPrevious() {
+ return scores.get(iter) == prev;
+ }
+
+ @Override
+ public int internalGetIndex() {
+ return iter.internalGetIndex();
+ }
+
+ @Deprecated
+ @Override
+ public int hashCode() {
+ return super.hashCode();
+ }
+
+ @Deprecated
+ @Override
+ public boolean equals(Object obj) {
+ return super.equals(obj);
+ }
+ }
+
+ /**
+ * Class to iterate over a number vector in decreasing order.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.composedOf NumberVector
+ */
+ public static class DecreasingVectorIter implements ScoreIter, IntegerComparator, ArrayIter {
+ /**
+ * Order of dimensions.
+ */
+ private int[] sort;
+
+ /**
+ * Data vector.
+ */
+ private NumberVector<?> vec;
+
+ /**
+ * Current position.
+ */
+ int pos = 0;
+
+ /**
+ * Constructor.
+ *
+ * @param vec Vector to iterate over.
+ */
+ public DecreasingVectorIter(NumberVector<?> vec) {
+ this.vec = vec;
+ final int dim = vec.getDimensionality();
+ this.sort = new int[dim];
+ for (int d = 0; d < dim; d++) {
+ sort[d] = d;
+ }
+ IntegerArrayQuickSort.sort(sort, this);
+ }
+
+ @Override
+ public int compare(int x, int y) {
+ return Double.compare(vec.doubleValue(y), vec.doubleValue(x));
+ }
+
+ public int dim() {
+ return sort[pos];
+ }
+
+ @Override
+ public boolean valid() {
+ return pos < vec.getDimensionality();
+ }
+
+ @Override
+ public void advance() {
+ ++pos;
+ }
+
+ @Override
+ public boolean tiedToPrevious() {
+ return pos > 0 && Double.compare(vec.doubleValue(sort[pos]), vec.doubleValue(sort[pos - 1])) == 0;
+ }
+
+ @Override
+ public int getOffset() {
+ return pos;
+ }
+
+ @Override
+ public void advance(int count) {
+ pos += count;
+ }
+
+ @Override
+ public void retract() {
+ pos--;
+ }
+
+ @Override
+ public void seek(int off) {
+ pos = off;
+ }
+ }
+
+ /**
+ * Class to iterate over a number vector in decreasing order.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.composedOf NumberVector
+ */
+ public static class IncreasingVectorIter implements ScoreIter, IntegerComparator, ArrayIter {
+ /**
+ * Order of dimensions.
+ */
+ private int[] sort;
+
+ /**
+ * Data vector.
+ */
+ private NumberVector<?> vec;
+
+ /**
+ * Current position.
+ */
+ int pos = 0;
+
+ /**
+ * Constructor.
+ *
+ * @param vec Vector to iterate over.
+ */
+ public IncreasingVectorIter(NumberVector<?> vec) {
+ this.vec = vec;
+ final int dim = vec.getDimensionality();
+ this.sort = new int[dim];
+ for (int d = 0; d < dim; d++) {
+ sort[d] = d;
+ }
+ IntegerArrayQuickSort.sort(sort, this);
+ }
+
+ @Override
+ public int compare(int x, int y) {
+ return Double.compare(vec.doubleValue(x), vec.doubleValue(y));
+ }
+
+ public int dim() {
+ return sort[pos];
+ }
+
+ @Override
+ public boolean valid() {
+ return pos < vec.getDimensionality();
+ }
+
+ @Override
+ public void advance() {
+ ++pos;
+ }
+
+ @Override
+ public boolean tiedToPrevious() {
+ return pos > 0 && Double.compare(vec.doubleValue(sort[pos]), vec.doubleValue(sort[pos - 1])) == 0;
+ }
+
+ @Override
+ public int getOffset() {
+ return pos;
+ }
+
+ @Override
+ public void advance(int count) {
+ pos += count;
+ }
+
+ @Override
+ public void retract() {
+ pos--;
+ }
+
+ @Override
+ public void seek(int off) {
+ pos = off;
+ }
+ }
+
+ /**
+ * Class that uses a NumberVector as reference, and considers all non-zero
+ * values as positive entries.
+ *
+ * @apiviz.composedOf NumberVector
+ *
+ * @author Erich Schubert
+ */
+ public static class VectorNonZero extends VectorOverThreshold {
+ /**
+ * Constructor.
+ *
+ * @param vec Reference vector.
+ */
+ public VectorNonZero(NumberVector<?> vec) {
+ super(vec, 0.);
+ }
+ }
+
+ /**
+ * Class that uses a NumberVector as reference, and considers all non-zero
+ * values as positive entries.
+ *
+ * @apiviz.composedOf NumberVector
+ *
+ * @author Erich Schubert
+ */
+ public static class VectorOverThreshold implements Predicate<DecreasingVectorIter> {
+ /**
+ * Vector to use as reference
+ */
+ NumberVector<?> vec;
+
+ /**
+ * Threshold
+ */
+ double threshold;
+
+ /**
+ * Constructor.
+ *
+ * @param vec Reference vector.
+ * @param threshold Threshold value.
+ */
+ public VectorOverThreshold(NumberVector<?> vec, double threshold) {
+ super();
+ this.vec = vec;
+ this.threshold = threshold;
+ }
+
+ @Override
+ public boolean test(DecreasingVectorIter o) {
+ return Math.abs(vec.doubleValue(o.dim())) > threshold;
+ }
+ }
+
+ /**
+ * Class that uses a NumberVector as reference, and considers all zero values
+ * as positive entries.
+ *
+ * @apiviz.composedOf NumberVector
+ *
+ * @author Erich Schubert
+ */
+ public static class VectorZero implements Predicate<IncreasingVectorIter> {
+ /**
+ * Vector to use as reference
+ */
+ NumberVector<?> vec;
+
+ /**
+ * Constructor.
+ *
+ * @param vec Reference vector.
+ */
+ public VectorZero(NumberVector<?> vec) {
+ this.vec = vec;
+ }
+
+ @Override
+ public boolean test(IncreasingVectorIter o) {
+ return Math.abs(vec.doubleValue(o.dim())) < Double.MIN_NORMAL;
+ }
+ }
+
+ /**
+ * Test predicate using a DBID set as positive elements.
+ *
+ * @apiviz.composedOf DBIDs
+ *
+ * @author Erich Schubert
+ */
+ public static class DBIDsTest implements Predicate<DBIDRef> {
+ /**
+ * DBID set.
+ */
+ private DBIDs set;
+
+ /**
+ * Constructor.
+ *
+ * @param set Set of positive objects
+ */
+ public DBIDsTest(DBIDs set) {
+ this.set = set;
+ }
+
+ @Override
+ public boolean test(DBIDRef o) {
+ return set.contains(o);
}
}
@@ -311,7 +620,7 @@ public class ROC {
* @param nei Query result
* @return area under curve
*/
- public static <D extends Distance<D>> double computeROCAUCDistanceResult(int size, Cluster<?> clus, DistanceDBIDResult<D> nei) {
+ public static <D extends Distance<D>> double computeROCAUCDistanceResult(int size, Cluster<?> clus, DistanceDBIDList<D> nei) {
// TODO: ensure the collection has efficient "contains".
return ROC.computeROCAUCDistanceResult(size, clus.getIDs(), nei);
}
@@ -325,9 +634,9 @@ public class ROC {
* @param nei Query Result
* @return area under curve
*/
- public static <D extends Distance<D>> double computeROCAUCDistanceResult(int size, DBIDs ids, DistanceDBIDResult<D> nei) {
+ public static <D extends Distance<D>> double computeROCAUCDistanceResult(int size, DBIDs ids, DistanceDBIDList<D> nei) {
// TODO: do not materialize the ROC, but introduce an iterator interface
- XYCurve roc = materializeROC(size, DBIDUtil.ensureSet(ids), new DistanceResultAdapter<D>(nei.iter()));
+ XYCurve roc = materializeROC(new DBIDsTest(DBIDUtil.ensureSet(ids)), new DistanceResultAdapter<>(nei.iter()));
return XYCurve.areaUnderCurve(roc);
}
@@ -341,7 +650,7 @@ public class ROC {
*/
public static double computeROCAUCSimple(int size, DBIDs ids, DBIDs nei) {
// TODO: do not materialize the ROC, but introduce an iterator interface
- XYCurve roc = materializeROC(size, DBIDUtil.ensureSet(ids), new SimpleAdapter(nei.iter()));
+ XYCurve roc = materializeROC(new DBIDsTest(DBIDUtil.ensureSet(ids)), new SimpleAdapter(nei.iter()));
return XYCurve.areaUnderCurve(roc);
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/roc/package-info.java b/src/de/lmu/ifi/dbs/elki/evaluation/roc/package-info.java
index 5ee2de70..c6934ba2 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/roc/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/roc/package-info.java
@@ -7,7 +7,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/similaritymatrix/ComputeSimilarityMatrixImage.java b/src/de/lmu/ifi/dbs/elki/evaluation/similaritymatrix/ComputeSimilarityMatrixImage.java
index 72173d30..90a11583 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/similaritymatrix/ComputeSimilarityMatrixImage.java
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/similaritymatrix/ComputeSimilarityMatrixImage.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.evaluation.similaritymatrix;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -41,7 +41,7 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.evaluation.Evaluator;
import de.lmu.ifi.dbs.elki.logging.Logging;
@@ -358,7 +358,7 @@ public class ComputeSimilarityMatrixImage<O> implements Evaluator {
distanceFunction = distanceFunctionP.instantiateClass(config);
}
- ObjectParameter<ScalingFunction> scalingP = new ObjectParameter<ScalingFunction>(SCALING_ID, ScalingFunction.class, true);
+ ObjectParameter<ScalingFunction> scalingP = new ObjectParameter<>(SCALING_ID, ScalingFunction.class, true);
if(config.grab(scalingP)) {
scaling = scalingP.instantiateClass(config);
}
@@ -371,7 +371,7 @@ public class ComputeSimilarityMatrixImage<O> implements Evaluator {
@Override
protected ComputeSimilarityMatrixImage<O> makeInstance() {
- return new ComputeSimilarityMatrixImage<O>(distanceFunction, scaling, skipzero);
+ return new ComputeSimilarityMatrixImage<>(distanceFunction, scaling, skipzero);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/similaritymatrix/package-info.java b/src/de/lmu/ifi/dbs/elki/evaluation/similaritymatrix/package-info.java
index 619c3f83..4acc0ec6 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/similaritymatrix/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/similaritymatrix/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/gui/GUIUtil.java b/src/de/lmu/ifi/dbs/elki/gui/GUIUtil.java
index 11a2725f..27cccded 100644
--- a/src/de/lmu/ifi/dbs/elki/gui/GUIUtil.java
+++ b/src/de/lmu/ifi/dbs/elki/gui/GUIUtil.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.gui;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/gui/configurator/AbstractParameterConfigurator.java b/src/de/lmu/ifi/dbs/elki/gui/configurator/AbstractParameterConfigurator.java
index 977af410..c6883653 100644
--- a/src/de/lmu/ifi/dbs/elki/gui/configurator/AbstractParameterConfigurator.java
+++ b/src/de/lmu/ifi/dbs/elki/gui/configurator/AbstractParameterConfigurator.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.gui.configurator;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/gui/configurator/AbstractSingleParameterConfigurator.java b/src/de/lmu/ifi/dbs/elki/gui/configurator/AbstractSingleParameterConfigurator.java
index 6d30ce25..240515cd 100644
--- a/src/de/lmu/ifi/dbs/elki/gui/configurator/AbstractSingleParameterConfigurator.java
+++ b/src/de/lmu/ifi/dbs/elki/gui/configurator/AbstractSingleParameterConfigurator.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.gui.configurator;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/gui/configurator/ClassListParameterConfigurator.java b/src/de/lmu/ifi/dbs/elki/gui/configurator/ClassListParameterConfigurator.java
index 603a52a9..182c7a0a 100644
--- a/src/de/lmu/ifi/dbs/elki/gui/configurator/ClassListParameterConfigurator.java
+++ b/src/de/lmu/ifi/dbs/elki/gui/configurator/ClassListParameterConfigurator.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.gui.configurator;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -76,7 +76,7 @@ public class ClassListParameterConfigurator extends AbstractSingleParameterConfi
/**
* The combobox we are abusing to produce the popup
*/
- final JComboBox combo;
+ final JComboBox<String> combo;
/**
* The popup menu.
@@ -96,7 +96,7 @@ public class ClassListParameterConfigurator extends AbstractSingleParameterConfi
button.setToolTipText(param.getShortDescription());
button.addActionListener(this);
// So the first item doesn't get automatically selected
- combo = new JComboBox();
+ combo = new JComboBox<>();
combo.setEditable(true);
combo.setPrototypeDisplayValue(cp.getRestrictionClass().getSimpleName());
popup = new SuperPopup(combo);
@@ -193,7 +193,7 @@ public class ClassListParameterConfigurator extends AbstractSingleParameterConfi
*
* @param combo Combo box used for data storage.
*/
- public SuperPopup(JComboBox combo) {
+ public SuperPopup(JComboBox<String> combo) {
super(combo);
}
diff --git a/src/de/lmu/ifi/dbs/elki/gui/configurator/ClassParameterConfigurator.java b/src/de/lmu/ifi/dbs/elki/gui/configurator/ClassParameterConfigurator.java
index 4fdcac10..cbe03a4f 100644
--- a/src/de/lmu/ifi/dbs/elki/gui/configurator/ClassParameterConfigurator.java
+++ b/src/de/lmu/ifi/dbs/elki/gui/configurator/ClassParameterConfigurator.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.gui.configurator;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -49,7 +49,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Parameter;
* @apiviz.uses ClassParameter
*/
public class ClassParameterConfigurator extends AbstractSingleParameterConfigurator<ClassParameter<?>> implements ActionListener, ChangeListener {
- final JComboBox value;
+ final JComboBox<String> value;
final ConfiguratorPanel child;
@@ -60,7 +60,7 @@ public class ClassParameterConfigurator extends AbstractSingleParameterConfigura
GridBagConstraints constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.weightx = 1.0;
- value = new JComboBox();
+ value = new JComboBox<>();
value.setToolTipText(param.getShortDescription());
value.setPrototypeDisplayValue(cp.getRestrictionClass().getSimpleName());
parent.add(value, constraints);
diff --git a/src/de/lmu/ifi/dbs/elki/gui/configurator/ConfiguratorPanel.java b/src/de/lmu/ifi/dbs/elki/gui/configurator/ConfiguratorPanel.java
index c21d11a4..440d5d0a 100644
--- a/src/de/lmu/ifi/dbs/elki/gui/configurator/ConfiguratorPanel.java
+++ b/src/de/lmu/ifi/dbs/elki/gui/configurator/ConfiguratorPanel.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.gui.configurator;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -61,12 +61,12 @@ public class ConfiguratorPanel extends JPanel implements ChangeListener {
/**
* Keep a map of parameter
*/
- private Map<Object, ParameterConfigurator> childconfig = new HashMap<Object, ParameterConfigurator>();
+ private Map<Object, ParameterConfigurator> childconfig = new HashMap<>();
/**
* Child options
*/
- private ArrayList<ParameterConfigurator> children = new ArrayList<ParameterConfigurator>();
+ private ArrayList<ParameterConfigurator> children = new ArrayList<>();
/**
* The event listeners for this panel.
diff --git a/src/de/lmu/ifi/dbs/elki/gui/configurator/EnumParameterConfigurator.java b/src/de/lmu/ifi/dbs/elki/gui/configurator/EnumParameterConfigurator.java
index 0e5740a8..f361efa2 100644
--- a/src/de/lmu/ifi/dbs/elki/gui/configurator/EnumParameterConfigurator.java
+++ b/src/de/lmu/ifi/dbs/elki/gui/configurator/EnumParameterConfigurator.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.gui.configurator;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -44,7 +44,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.EnumParameter;
* @apiviz.uses EnumParameter
*/
public class EnumParameterConfigurator extends AbstractSingleParameterConfigurator<EnumParameter<?>> implements ActionListener {
- final JComboBox value;
+ final JComboBox<String> value;
public EnumParameterConfigurator(EnumParameter<?> cp, JComponent parent) {
super(cp, parent);
@@ -53,7 +53,7 @@ public class EnumParameterConfigurator extends AbstractSingleParameterConfigurat
GridBagConstraints constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.weightx = 1.0;
- value = new JComboBox();
+ value = new JComboBox<>();
value.setToolTipText(param.getShortDescription());
value.setPrototypeDisplayValue(cp.getPossibleValues().iterator().next());
parent.add(value, constraints);
diff --git a/src/de/lmu/ifi/dbs/elki/gui/configurator/FileParameterConfigurator.java b/src/de/lmu/ifi/dbs/elki/gui/configurator/FileParameterConfigurator.java
index f9355579..1fce49f0 100644
--- a/src/de/lmu/ifi/dbs/elki/gui/configurator/FileParameterConfigurator.java
+++ b/src/de/lmu/ifi/dbs/elki/gui/configurator/FileParameterConfigurator.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.gui.configurator;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/gui/configurator/FlagParameterConfigurator.java b/src/de/lmu/ifi/dbs/elki/gui/configurator/FlagParameterConfigurator.java
index bec04b70..5f73663c 100644
--- a/src/de/lmu/ifi/dbs/elki/gui/configurator/FlagParameterConfigurator.java
+++ b/src/de/lmu/ifi/dbs/elki/gui/configurator/FlagParameterConfigurator.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.gui.configurator;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/gui/configurator/ParameterConfigurator.java b/src/de/lmu/ifi/dbs/elki/gui/configurator/ParameterConfigurator.java
index 9bd879f6..6118355c 100644
--- a/src/de/lmu/ifi/dbs/elki/gui/configurator/ParameterConfigurator.java
+++ b/src/de/lmu/ifi/dbs/elki/gui/configurator/ParameterConfigurator.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.gui.configurator;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/gui/configurator/TextParameterConfigurator.java b/src/de/lmu/ifi/dbs/elki/gui/configurator/TextParameterConfigurator.java
index 582381cb..411d056d 100644
--- a/src/de/lmu/ifi/dbs/elki/gui/configurator/TextParameterConfigurator.java
+++ b/src/de/lmu/ifi/dbs/elki/gui/configurator/TextParameterConfigurator.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.gui.configurator;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/gui/configurator/package-info.java b/src/de/lmu/ifi/dbs/elki/gui/configurator/package-info.java
index 5c8f2f4e..cb7ef043 100644
--- a/src/de/lmu/ifi/dbs/elki/gui/configurator/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/gui/configurator/package-info.java
@@ -8,7 +8,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/gui/icons/StockIcon.java b/src/de/lmu/ifi/dbs/elki/gui/icons/StockIcon.java
index 4896bce0..c0550da3 100644
--- a/src/de/lmu/ifi/dbs/elki/gui/icons/StockIcon.java
+++ b/src/de/lmu/ifi/dbs/elki/gui/icons/StockIcon.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.gui.icons;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -88,7 +88,7 @@ public class StockIcon {
public static final String PROCESS_STOP = "process-stop";
- private static final Map<String, SoftReference<Icon>> iconcache = new HashMap<String, SoftReference<Icon>>();
+ private static final Map<String, SoftReference<Icon>> iconcache = new HashMap<>();
/**
* Get a particular stock icon.
@@ -107,7 +107,7 @@ public class StockIcon {
java.net.URL imgURL = StockIcon.class.getResource(name + ".png");
if(imgURL != null) {
Icon icon = new ImageIcon(imgURL);
- iconcache.put(name, new SoftReference<Icon>(icon));
+ iconcache.put(name, new SoftReference<>(icon));
return icon;
}
else {
diff --git a/src/de/lmu/ifi/dbs/elki/gui/icons/package-info.java b/src/de/lmu/ifi/dbs/elki/gui/icons/package-info.java
index 986b2de1..c7ffb7d0 100644
--- a/src/de/lmu/ifi/dbs/elki/gui/icons/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/gui/icons/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/gui/minigui/MiniGUI.java b/src/de/lmu/ifi/dbs/elki/gui/minigui/MiniGUI.java
index 36010fc5..f60ac69e 100644
--- a/src/de/lmu/ifi/dbs/elki/gui/minigui/MiniGUI.java
+++ b/src/de/lmu/ifi/dbs/elki/gui/minigui/MiniGUI.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.gui.minigui;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -59,6 +59,7 @@ import de.lmu.ifi.dbs.elki.gui.util.ParameterTable;
import de.lmu.ifi.dbs.elki.gui.util.ParametersModel;
import de.lmu.ifi.dbs.elki.gui.util.SavedSettingsFile;
import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
import de.lmu.ifi.dbs.elki.utilities.FormatUtil;
import de.lmu.ifi.dbs.elki.utilities.exceptions.UnableToComplyException;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.ParameterException;
@@ -78,6 +79,7 @@ import de.lmu.ifi.dbs.elki.workflow.OutputStep;
* @apiviz.owns ParameterTable
* @apiviz.owns DynamicParameters
*/
+@Alias({"mini", "minigui"})
public class MiniGUI extends AbstractApplication {
/**
* Filename for saved settings.
@@ -127,7 +129,7 @@ public class MiniGUI extends AbstractApplication {
/**
* Combo box for saved settings.
*/
- protected JComboBox savedCombo;
+ protected JComboBox<String> savedCombo;
/**
* Model to link the combobox with.
@@ -165,7 +167,7 @@ public class MiniGUI extends AbstractApplication {
// Combo box for saved settings
savedSettingsModel = new SettingsComboboxModel(store);
- savedCombo = new JComboBox(savedSettingsModel);
+ savedCombo = new JComboBox<>(savedSettingsModel);
savedCombo.setEditable(true);
savedCombo.setSelectedItem("[Saved Settings]");
buttonPanel.add(savedCombo);
@@ -259,7 +261,7 @@ public class MiniGUI extends AbstractApplication {
});
// Create parameter table
- parameterTable = new ParameterTable(parameterModel, parameters);
+ parameterTable = new ParameterTable(frame, parameterModel, parameters);
// Create the scroll pane and add the table to it.
JScrollPane scrollPane = new JScrollPane(parameterTable);
@@ -341,6 +343,7 @@ public class MiniGUI extends AbstractApplication {
List<String> remainingParameters = config.getRemainingParameters();
// update table:
+ parameterTable.removeEditor();
parameterTable.setEnabled(false);
parameters.updateFromTrackParameters(track);
// Add remaining parameters
@@ -473,7 +476,7 @@ public class MiniGUI extends AbstractApplication {
*
* @apiviz.composedOf de.lmu.ifi.dbs.elki.gui.util.SavedSettingsFile
*/
- class SettingsComboboxModel extends AbstractListModel implements ComboBoxModel {
+ class SettingsComboboxModel extends AbstractListModel<String> implements ComboBoxModel<String> {
/**
* Serial version.
*/
@@ -512,7 +515,7 @@ public class MiniGUI extends AbstractApplication {
}
@Override
- public Object getElementAt(int index) {
+ public String getElementAt(int index) {
return store.getElementAt(store.size() - 1 - index).first;
}
diff --git a/src/de/lmu/ifi/dbs/elki/gui/minigui/package-info.java b/src/de/lmu/ifi/dbs/elki/gui/minigui/package-info.java
index 944b4a8e..7acb0045 100644
--- a/src/de/lmu/ifi/dbs/elki/gui/minigui/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/gui/minigui/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/gui/multistep/MultiStepGUI.java b/src/de/lmu/ifi/dbs/elki/gui/multistep/MultiStepGUI.java
index 820bc543..11a45d25 100644
--- a/src/de/lmu/ifi/dbs/elki/gui/multistep/MultiStepGUI.java
+++ b/src/de/lmu/ifi/dbs/elki/gui/multistep/MultiStepGUI.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.gui.multistep;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -32,12 +32,12 @@ import java.util.ArrayList;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
-import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
-import javax.swing.UIManager;
import de.lmu.ifi.dbs.elki.KDDTask;
+import de.lmu.ifi.dbs.elki.application.AbstractApplication;
+import de.lmu.ifi.dbs.elki.gui.GUIUtil;
import de.lmu.ifi.dbs.elki.gui.minigui.MiniGUI;
import de.lmu.ifi.dbs.elki.gui.multistep.panels.AlgorithmTabPanel;
import de.lmu.ifi.dbs.elki.gui.multistep.panels.EvaluationTabPanel;
@@ -48,8 +48,11 @@ import de.lmu.ifi.dbs.elki.gui.multistep.panels.SavedSettingsTabPanel;
import de.lmu.ifi.dbs.elki.gui.util.LogPanel;
import de.lmu.ifi.dbs.elki.gui.util.SavedSettingsFile;
import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.UnableToComplyException;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.ListParameterization;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.SerializedParameterization;
import de.lmu.ifi.dbs.elki.workflow.OutputStep;
/**
@@ -65,32 +68,51 @@ import de.lmu.ifi.dbs.elki.workflow.OutputStep;
* @apiviz.composedOf OutputTabPanel
* @apiviz.composedOf SavedSettingsTabPanel
*/
-public class MultiStepGUI extends JPanel {
+@Alias({ "multi", "multigui", "multistepgui" })
+public class MultiStepGUI extends AbstractApplication {
/**
- * Serial version
+ * ELKI logger for the GUI
*/
- private static final long serialVersionUID = 1L;
+ private static final Logging LOG = Logging.getLogger(MultiStepGUI.class);
/**
- * ELKI logger for the GUI
+ * The frame
*/
- private static final Logging LOG = Logging.getLogger(MultiStepGUI.class);
+ JFrame frame;
/**
* Logging output area.
*/
protected LogPanel outputArea;
+ /**
+ * Input panel.
+ */
private InputTabPanel inputTab;
+ /**
+ * Algorithm panel.
+ */
private AlgorithmTabPanel algTab;
+ /**
+ * Evaluation panel.
+ */
private EvaluationTabPanel evalTab;
+ /**
+ * Output panel.
+ */
private OutputTabPanel outTab;
+ /**
+ * Logging panel.
+ */
private LoggingTabPanel logTab;
+ /**
+ * Saved settingspanel.
+ */
private SavedSettingsTabPanel setTab;
/**
@@ -98,7 +120,15 @@ public class MultiStepGUI extends JPanel {
*/
public MultiStepGUI() {
super();
- this.setLayout(new GridBagLayout());
+ frame = new JFrame("ELKI ExpGUI");
+ frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+ try {
+ frame.setIconImage(new ImageIcon(KDDTask.class.getResource("elki-icon.png")).getImage());
+ } catch (Exception e) {
+ // Ignore - icon not found is not fatal.
+ }
+
+ frame.setLayout(new GridBagLayout());
{
// setup text output area
outputArea = new LogPanel();
@@ -114,7 +144,7 @@ public class MultiStepGUI extends JPanel {
constraints.gridy = 1;
constraints.weightx = 1;
constraints.weighty = 1;
- add(outputPane, constraints);
+ frame.add(outputPane, constraints);
// reconfigure logging
outputArea.becomeDefaultLogger();
@@ -130,24 +160,23 @@ public class MultiStepGUI extends JPanel {
constraints.gridy = 0;
constraints.weightx = 1;
constraints.weighty = 1;
- add(panels, constraints);
+ frame.add(panels, constraints);
addPanels(panels);
}
+ frame.pack();
}
private void addPanels(JTabbedPane panels) {
SavedSettingsFile settings = new SavedSettingsFile(MiniGUI.SAVED_SETTINGS_FILENAME);
try {
settings.load();
- }
- catch(FileNotFoundException e) {
+ } catch (FileNotFoundException e) {
LOG.warning("Error loading saved settings.", e);
- }
- catch(IOException e) {
+ } catch (IOException e) {
LOG.exception(e);
}
-
+
inputTab = new InputTabPanel();
algTab = new AlgorithmTabPanel(inputTab);
evalTab = new EvaluationTabPanel(inputTab, algTab);
@@ -173,15 +202,15 @@ public class MultiStepGUI extends JPanel {
// Clear errors after each step, so they don't consider themselves failed
// because of earlier errors.
logTab.setParameters(config);
- //config.clearErrors();
+ // config.clearErrors();
inputTab.setParameters(config);
- //config.clearErrors();
+ // config.clearErrors();
algTab.setParameters(config);
- //config.clearErrors();
+ // config.clearErrors();
evalTab.setParameters(config);
- //config.clearErrors();
+ // config.clearErrors();
outTab.setParameters(config);
- //config.clearErrors();
+ // config.clearErrors();
}
/**
@@ -198,36 +227,11 @@ public class MultiStepGUI extends JPanel {
outTab.appendParameters(params);
return params.serialize();
}
-
- /**
- * Create the GUI and show it. For thread safety, this method should be
- * invoked from the event-dispatching thread.
- */
- protected static void createAndShowGUI() {
- // Create and set up the window.
- JFrame frame = new JFrame("ELKI ExpGUI");
- frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
- try {
- UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
- }
- catch(Exception e) {
- // ignore
- }
- try {
- frame.setIconImage(new ImageIcon(KDDTask.class.getResource("elki-icon.png")).getImage());
- }
- catch(Exception e) {
- // Ignore - icon not found is not fatal.
- }
-
- // Create and set up the content pane.
- MultiStepGUI newContentPane = new MultiStepGUI();
- newContentPane.setOpaque(true); // content panes must be opaque
- frame.setContentPane(newContentPane);
- // Display the window.
- frame.pack();
+ @Override
+ public void run() throws UnableToComplyException {
frame.setVisible(true);
+ outputArea.becomeDefaultLogger();
}
/**
@@ -235,13 +239,26 @@ public class MultiStepGUI extends JPanel {
*
* @param args command line parameters
*/
- public static void main(String[] args) {
+ public static void main(final String[] args) {
+ GUIUtil.logUncaughtExceptions(LOG);
+ GUIUtil.setLookAndFeel();
OutputStep.setDefaultHandlerVisualizer();
+
javax.swing.SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
- createAndShowGUI();
+ try {
+ final MultiStepGUI gui = new MultiStepGUI();
+ gui.run();
+ if (args != null && args.length > 0) {
+ gui.setParameters(new SerializedParameterization(args));
+ } else {
+ gui.setParameters(new SerializedParameterization());
+ }
+ } catch (UnableToComplyException e) {
+ LOG.exception(e);
+ }
}
});
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/gui/multistep/package-info.java b/src/de/lmu/ifi/dbs/elki/gui/multistep/package-info.java
index 35a08689..3e8f11b2 100644
--- a/src/de/lmu/ifi/dbs/elki/gui/multistep/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/gui/multistep/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/AlgorithmTabPanel.java b/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/AlgorithmTabPanel.java
index f6eb2955..d6622e8f 100644
--- a/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/AlgorithmTabPanel.java
+++ b/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/AlgorithmTabPanel.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.gui.multistep.panels;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,7 +26,6 @@ package de.lmu.ifi.dbs.elki.gui.multistep.panels;
import java.lang.ref.WeakReference;
import de.lmu.ifi.dbs.elki.database.Database;
-import de.lmu.ifi.dbs.elki.utilities.designpattern.Observer;
import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
import de.lmu.ifi.dbs.elki.workflow.AlgorithmStep;
@@ -36,7 +35,7 @@ import de.lmu.ifi.dbs.elki.workflow.AlgorithmStep;
*
* @author Erich Schubert
*/
-public class AlgorithmTabPanel extends ParameterTabPanel implements Observer<Object> {
+public class AlgorithmTabPanel extends ParameterTabPanel {
/**
* Serial version.
*/
@@ -65,13 +64,13 @@ public class AlgorithmTabPanel extends ParameterTabPanel implements Observer<Obj
public AlgorithmTabPanel(InputTabPanel input) {
super();
this.input = input;
- input.addObserver(this);
+ input.addPanelListener(this);
}
@Override
protected synchronized void configureStep(Parameterization config) {
algorithms = config.tryInstantiate(AlgorithmStep.class);
- if(config.getErrors().size() > 0) {
+ if (config.getErrors().size() > 0) {
algorithms = null;
}
basedOnDatabase = null;
@@ -79,10 +78,10 @@ public class AlgorithmTabPanel extends ParameterTabPanel implements Observer<Obj
@Override
protected void executeStep() {
- if(input.canRun() && !input.isComplete()) {
+ if (input.canRun() && !input.isComplete()) {
input.execute();
}
- if(!input.isComplete()) {
+ if (!input.isComplete()) {
throw new AbortException("Input data not available.");
}
// Get the database and run the algorithms
@@ -93,18 +92,17 @@ public class AlgorithmTabPanel extends ParameterTabPanel implements Observer<Obj
@Override
protected Status getStatus() {
- if(algorithms == null) {
+ if (algorithms == null) {
return Status.STATUS_UNCONFIGURED;
}
- if(!input.canRun()) {
+ if (!input.canRun()) {
return Status.STATUS_CONFIGURED;
}
checkDependencies();
- if(input.isComplete() && basedOnDatabase != null) {
- if(algorithms.getResult() == null) {
+ if (input.isComplete() && basedOnDatabase != null) {
+ if (algorithms.getResult() == null) {
return Status.STATUS_FAILED;
- }
- else {
+ } else {
return Status.STATUS_COMPLETE;
}
}
@@ -117,15 +115,15 @@ public class AlgorithmTabPanel extends ParameterTabPanel implements Observer<Obj
* @return Algorithm step
*/
public AlgorithmStep getAlgorithmStep() {
- if(algorithms == null) {
+ if (algorithms == null) {
throw new AbortException("Algorithms not configured.");
}
return algorithms;
}
@Override
- public void update(Object o) {
- if(o == input) {
+ public void panelUpdated(ParameterTabPanel o) {
+ if (o == input) {
checkDependencies();
updateStatus();
}
@@ -135,12 +133,12 @@ public class AlgorithmTabPanel extends ParameterTabPanel implements Observer<Obj
* Test if the dependencies are still valid.
*/
private void checkDependencies() {
- if(basedOnDatabase != null) {
- if(!input.isComplete() || basedOnDatabase.get() != input.getInputStep().getDatabase()) {
+ if (basedOnDatabase != null) {
+ if (!input.isComplete() || basedOnDatabase.get() != input.getInputStep().getDatabase()) {
// We've become invalidated, notify.
basedOnDatabase = null;
- observers.notifyObservers(this);
+ firePanelUpdated();
}
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/EvaluationTabPanel.java b/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/EvaluationTabPanel.java
index 9a74e250..d8d4153c 100644
--- a/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/EvaluationTabPanel.java
+++ b/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/EvaluationTabPanel.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.gui.multistep.panels;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,7 +27,6 @@ import java.lang.ref.WeakReference;
import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
-import de.lmu.ifi.dbs.elki.utilities.designpattern.Observer;
import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
import de.lmu.ifi.dbs.elki.workflow.EvaluationStep;
@@ -37,7 +36,7 @@ import de.lmu.ifi.dbs.elki.workflow.EvaluationStep;
*
* @author Erich Schubert
*/
-public class EvaluationTabPanel extends ParameterTabPanel implements Observer<Object> {
+public class EvaluationTabPanel extends ParameterTabPanel {
/**
* Serial version.
*/
@@ -72,8 +71,8 @@ public class EvaluationTabPanel extends ParameterTabPanel implements Observer<Ob
super();
this.input = input;
this.algs = algs;
- input.addObserver(this);
- algs.addObserver(this);
+ input.addPanelListener(this);
+ algs.addPanelListener(this);
}
@Override
@@ -136,7 +135,7 @@ public class EvaluationTabPanel extends ParameterTabPanel implements Observer<Ob
}
@Override
- public void update(Object o) {
+ public void panelUpdated(ParameterTabPanel o) {
if (o == input || o == algs) {
checkDependencies();
updateStatus();
@@ -151,7 +150,7 @@ public class EvaluationTabPanel extends ParameterTabPanel implements Observer<Ob
if (!input.isComplete() || !algs.isComplete() || basedOnResult.get() != algs.getAlgorithmStep().getResult()) {
// We've become invalidated, notify.
basedOnResult = null;
- observers.notifyObservers(this);
+ firePanelUpdated();
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/InputTabPanel.java b/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/InputTabPanel.java
index 9d88e900..2f4d027b 100644
--- a/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/InputTabPanel.java
+++ b/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/InputTabPanel.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.gui.multistep.panels;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/LoggingTabPanel.java b/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/LoggingTabPanel.java
index 5bf4c086..c4933673 100644
--- a/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/LoggingTabPanel.java
+++ b/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/LoggingTabPanel.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.gui.multistep.panels;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,9 +23,10 @@ package de.lmu.ifi.dbs.elki.gui.multistep.panels;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import de.lmu.ifi.dbs.elki.application.AbstractApplication;
import de.lmu.ifi.dbs.elki.logging.LoggingConfiguration;
import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.logging.Logging.Level;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.WrongParameterValueException;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Flag;
@@ -51,13 +52,14 @@ public class LoggingTabPanel extends ParameterTabPanel {
@Override
protected synchronized void configureStep(Parameterization config) {
- StringParameter debugParam = new StringParameter(OptionID.DEBUG);
+ StringParameter debugParam = new StringParameter(AbstractApplication.Parameterizer.DEBUG_ID);
debugParam.setOptional(true);
- Flag verboseFlag = new Flag(OptionID.VERBOSE_FLAG);
+ Flag verboseFlag = new Flag(AbstractApplication.Parameterizer.VERBOSE_ID);
// Verbose mode is a lot simpler
if (config.grab(verboseFlag) && verboseFlag.isTrue()) {
- LoggingConfiguration.setVerbose(true);
+ LoggingConfiguration.setVerbose(Level.VERBOSE);
}
+ // FIXME: add second level of verbosity!
if (config.grab(debugParam)) {
try {
LoggingUtil.parseDebugParameter(debugParam);
diff --git a/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/OutputTabPanel.java b/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/OutputTabPanel.java
index 48ddc344..12af18d3 100644
--- a/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/OutputTabPanel.java
+++ b/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/OutputTabPanel.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.gui.multistep.panels;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,7 +26,6 @@ package de.lmu.ifi.dbs.elki.gui.multistep.panels;
import java.lang.ref.WeakReference;
import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
-import de.lmu.ifi.dbs.elki.utilities.designpattern.Observer;
import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
import de.lmu.ifi.dbs.elki.workflow.OutputStep;
@@ -36,7 +35,7 @@ import de.lmu.ifi.dbs.elki.workflow.OutputStep;
*
* @author Erich Schubert
*/
-public class OutputTabPanel extends ParameterTabPanel implements Observer<Object> {
+public class OutputTabPanel extends ParameterTabPanel {
/**
* Serial version.
*/
@@ -71,8 +70,8 @@ public class OutputTabPanel extends ParameterTabPanel implements Observer<Object
super();
this.input = input;
this.evals = evals;
- input.addObserver(this);
- evals.addObserver(this);
+ input.addPanelListener(this);
+ evals.addPanelListener(this);
}
@Override
@@ -121,7 +120,7 @@ public class OutputTabPanel extends ParameterTabPanel implements Observer<Object
}
@Override
- public void update(Object o) {
+ public void panelUpdated(ParameterTabPanel o) {
if (o == input || o == evals) {
checkDependencies();
updateStatus();
@@ -136,7 +135,7 @@ public class OutputTabPanel extends ParameterTabPanel implements Observer<Object
if (!input.isComplete() || !evals.isComplete() || basedOnResult.get() != evals.getEvaluationStep().getResult()) {
// We've become invalidated, notify.
basedOnResult = null;
- observers.notifyObservers(this);
+ firePanelUpdated();
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/ParameterTabPanel.java b/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/ParameterTabPanel.java
index cb72e6cd..667960a1 100644
--- a/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/ParameterTabPanel.java
+++ b/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/ParameterTabPanel.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.gui.multistep.panels;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -40,8 +40,6 @@ import javax.swing.event.ChangeListener;
import de.lmu.ifi.dbs.elki.gui.configurator.ConfiguratorPanel;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.utilities.FormatUtil;
-import de.lmu.ifi.dbs.elki.utilities.designpattern.Observer;
-import de.lmu.ifi.dbs.elki.utilities.designpattern.Observers;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.ParameterException;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.UnspecifiedParameterException;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.ListParameterization;
@@ -131,11 +129,6 @@ public abstract class ParameterTabPanel extends JPanel implements ChangeListener
private final JLabel statusText;
/**
- * Observers of this panel
- */
- protected final Observers<ParameterTabPanel> observers = new Observers<ParameterTabPanel>();
-
- /**
* Input pane
*/
public ParameterTabPanel() {
@@ -237,7 +230,7 @@ public abstract class ParameterTabPanel extends JPanel implements ChangeListener
// Update status and notify observers
updateStatus();
- observers.notifyObservers(this);
+ firePanelUpdated();
}
/**
@@ -291,7 +284,7 @@ public abstract class ParameterTabPanel extends JPanel implements ChangeListener
LOG.exception(e);
}
updateStatus();
- observers.notifyObservers(this);
+ firePanelUpdated();
}
/**
@@ -347,12 +340,18 @@ public abstract class ParameterTabPanel extends JPanel implements ChangeListener
runButton.setEnabled(canRun());
}
- public void addObserver(Observer<? super ParameterTabPanel> o) {
- observers.add(o);
+ protected void firePanelUpdated() {
+ for (ParameterTabPanel p : listenerList.getListeners(ParameterTabPanel.class)) {
+ p.panelUpdated(this);
+ }
+ }
+
+ public void addPanelListener(ParameterTabPanel o) {
+ listenerList.add(ParameterTabPanel.class, o);
}
- public void removeObserver(Observer<? super ParameterTabPanel> o) {
- observers.remove(o);
+ public void removePanelListener(ParameterTabPanel o) {
+ listenerList.remove(ParameterTabPanel.class, o);
}
@Override
@@ -362,4 +361,13 @@ public abstract class ParameterTabPanel extends JPanel implements ChangeListener
updateParameterTable();
}
}
+
+ /**
+ * Called when an observed panel changes.
+ *
+ * @param o Observed panel
+ */
+ void panelUpdated(ParameterTabPanel o) {
+ // Do nothing by default.
+ };
}
diff --git a/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/SavedSettingsTabPanel.java b/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/SavedSettingsTabPanel.java
index 845df73c..acebdc16 100644
--- a/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/SavedSettingsTabPanel.java
+++ b/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/SavedSettingsTabPanel.java
@@ -1,9 +1,10 @@
package de.lmu.ifi.dbs.elki.gui.multistep.panels;
+
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -73,7 +74,7 @@ public class SavedSettingsTabPanel extends JPanel {
/**
* The combo box to use
*/
- JComboBox savedCombo;
+ JComboBox<String> savedCombo;
/**
* The UI to set parameters on.
@@ -96,7 +97,7 @@ public class SavedSettingsTabPanel extends JPanel {
// Dropdown for saved settings
{
savedSettingsModel = new SettingsComboboxModel(store);
- savedCombo = new JComboBox(savedSettingsModel);
+ savedCombo = new JComboBox<>(savedSettingsModel);
savedCombo.setEditable(true);
savedCombo.setSelectedItem("[Saved Settings]");
GridBagConstraints constraints = new GridBagConstraints();
@@ -111,7 +112,7 @@ public class SavedSettingsTabPanel extends JPanel {
{
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
-
+
// button to load settings
JButton loadButton = new JButton("Load");
loadButton.setMnemonic(KeyEvent.VK_L);
@@ -137,8 +138,7 @@ public class SavedSettingsTabPanel extends JPanel {
store.put(key, gui.serializeParameters());
try {
store.save();
- }
- catch(IOException e1) {
+ } catch (IOException e1) {
LOG.exception(e1);
}
savedSettingsModel.update();
@@ -155,8 +155,7 @@ public class SavedSettingsTabPanel extends JPanel {
store.remove(key);
try {
store.save();
- }
- catch(IOException e1) {
+ } catch (IOException e1) {
LOG.exception(e1);
}
savedCombo.setSelectedItem("[Saved Settings]");
@@ -164,7 +163,7 @@ public class SavedSettingsTabPanel extends JPanel {
}
});
buttonPanel.add(removeButton);
-
+
GridBagConstraints constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.gridx = 0;
@@ -182,7 +181,7 @@ public class SavedSettingsTabPanel extends JPanel {
*
* @apiviz.composedOf de.lmu.ifi.dbs.elki.gui.util.SavedSettingsFile
*/
- class SettingsComboboxModel extends AbstractListModel implements ComboBoxModel {
+ class SettingsComboboxModel extends AbstractListModel<String> implements ComboBoxModel<String> {
/**
* Serial version
*/
@@ -215,14 +214,14 @@ public class SavedSettingsTabPanel extends JPanel {
@Override
public void setSelectedItem(Object anItem) {
- if(anItem instanceof String) {
+ if (anItem instanceof String) {
selected = (String) anItem;
}
}
@Override
- public Object getElementAt(int index) {
- return store.getElementAt(index).first;
+ public String getElementAt(int index) {
+ return store.getElementAt(store.size() - 1 - index).first;
}
@Override
@@ -237,4 +236,4 @@ public class SavedSettingsTabPanel extends JPanel {
fireContentsChanged(this, 0, getSize() + 1);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/package-info.java b/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/package-info.java
index b9d4d90a..77d1779d 100644
--- a/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/gui/package-info.java b/src/de/lmu/ifi/dbs/elki/gui/package-info.java
index 34a29371..8fa23e0d 100644
--- a/src/de/lmu/ifi/dbs/elki/gui/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/gui/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/gui/util/DynamicParameters.java b/src/de/lmu/ifi/dbs/elki/gui/util/DynamicParameters.java
index e9c80da6..d974a6d6 100644
--- a/src/de/lmu/ifi/dbs/elki/gui/util/DynamicParameters.java
+++ b/src/de/lmu/ifi/dbs/elki/gui/util/DynamicParameters.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.gui.util;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -122,7 +122,7 @@ public class DynamicParameters {
*/
public DynamicParameters() {
super();
- this.parameters = new ArrayList<Node>();
+ this.parameters = new ArrayList<>();
}
/**
@@ -213,7 +213,7 @@ public class DynamicParameters {
* @return Array list of String parameters.
*/
public synchronized ArrayList<String> serializeParameters() {
- ArrayList<String> p = new ArrayList<String>(2 * parameters.size());
+ ArrayList<String> p = new ArrayList<>(2 * parameters.size());
for (Node t : parameters) {
if (t.param != null) {
if (t.param instanceof RemainingOptions) {
diff --git a/src/de/lmu/ifi/dbs/elki/gui/util/LogPane.java b/src/de/lmu/ifi/dbs/elki/gui/util/LogPane.java
index dcc2cf5b..4664b852 100644
--- a/src/de/lmu/ifi/dbs/elki/gui/util/LogPane.java
+++ b/src/de/lmu/ifi/dbs/elki/gui/util/LogPane.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.gui.util;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/gui/util/LogPanel.java b/src/de/lmu/ifi/dbs/elki/gui/util/LogPanel.java
index cb410ee9..23bbb3f2 100644
--- a/src/de/lmu/ifi/dbs/elki/gui/util/LogPanel.java
+++ b/src/de/lmu/ifi/dbs/elki/gui/util/LogPanel.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.gui.util;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -67,7 +67,7 @@ public class LogPanel extends JPanel {
/**
* Current progress bars
*/
- protected HashMap<Progress, JProgressBar> pbarmap = new HashMap<Progress, JProgressBar>();
+ protected HashMap<Progress, JProgressBar> pbarmap = new HashMap<>();
/**
* Constructor.
diff --git a/src/de/lmu/ifi/dbs/elki/gui/util/ParameterTable.java b/src/de/lmu/ifi/dbs/elki/gui/util/ParameterTable.java
index a28d3f43..105242c0 100644
--- a/src/de/lmu/ifi/dbs/elki/gui/util/ParameterTable.java
+++ b/src/de/lmu/ifi/dbs/elki/gui/util/ParameterTable.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.gui.util;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,21 +27,29 @@ import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
+import java.awt.FileDialog;
+import java.awt.Frame;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
import java.io.File;
import java.util.BitSet;
import javax.swing.AbstractCellEditor;
+import javax.swing.Action;
+import javax.swing.ActionMap;
import javax.swing.DefaultCellEditor;
+import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JComboBox;
-import javax.swing.JFileChooser;
+import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.JTextField;
+import javax.swing.KeyStroke;
+import javax.swing.SwingUtilities;
import javax.swing.plaf.basic.BasicComboPopup;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;
@@ -94,6 +102,11 @@ public class ParameterTable extends JTable {
static final Color COLOR_DEFAULT_VALUE = new Color(0xDFDFDF);
/**
+ * Containing frame.
+ */
+ protected Frame frame;
+
+ /**
* The parameters we edit.
*/
protected DynamicParameters parameters;
@@ -101,11 +114,13 @@ public class ParameterTable extends JTable {
/**
* Constructor
*
+ * @param frame Containing frame
* @param pm Parameter Model
* @param parameters Parameter storage
*/
- public ParameterTable(ParametersModel pm, DynamicParameters parameters) {
+ public ParameterTable(Frame frame, ParametersModel pm, DynamicParameters parameters) {
super(pm);
+ this.frame = frame;
this.parameters = parameters;
this.setPreferredScrollableViewportSize(new Dimension(800, 400));
this.setFillsViewportHeight(true);
@@ -141,16 +156,16 @@ public class ParameterTable extends JTable {
@Override
public void setValue(Object value) {
- if(value instanceof String) {
+ if (value instanceof String) {
setText((String) value);
setToolTipText(null);
return;
}
- if(value instanceof DynamicParameters.Node) {
+ if (value instanceof DynamicParameters.Node) {
Parameter<?> o = ((DynamicParameters.Node) value).param;
// Simulate a tree using indentation - there is no JTreeTable AFAICT
StringBuilder buf = new StringBuilder();
- for(int i = 1; i < ((DynamicParameters.Node) value).depth; i++) {
+ for (int i = 1; i < ((DynamicParameters.Node) value).depth; i++) {
buf.append(' ');
}
buf.append(o.getOptionID().getName());
@@ -165,27 +180,24 @@ public class ParameterTable extends JTable {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
- if(row < parameters.size()) {
- BitSet flags = parameters.getNode(row).flags;
- // TODO: don't hardcode black - maybe mix the other colors, too?
- c.setForeground(Color.BLACK);
- if((flags.get(DynamicParameters.BIT_INVALID))) {
- c.setBackground(COLOR_SYNTAX_ERROR);
- }
- else if((flags.get(DynamicParameters.BIT_SYNTAX_ERROR))) {
- c.setBackground(COLOR_SYNTAX_ERROR);
- }
- else if((flags.get(DynamicParameters.BIT_INCOMPLETE))) {
- c.setBackground(COLOR_INCOMPLETE);
- }
- else if((flags.get(DynamicParameters.BIT_DEFAULT_VALUE))) {
- c.setBackground(COLOR_DEFAULT_VALUE);
- }
- else if((flags.get(DynamicParameters.BIT_OPTIONAL))) {
- c.setBackground(COLOR_OPTIONAL);
- }
- else {
- c.setBackground(null);
+ if (!hasFocus) {
+ if (row < parameters.size()) {
+ BitSet flags = parameters.getNode(row).flags;
+ // TODO: don't hardcode black - maybe mix the other colors, too?
+ c.setForeground(Color.BLACK);
+ if ((flags.get(DynamicParameters.BIT_INVALID))) {
+ c.setBackground(COLOR_SYNTAX_ERROR);
+ } else if ((flags.get(DynamicParameters.BIT_SYNTAX_ERROR))) {
+ c.setBackground(COLOR_SYNTAX_ERROR);
+ } else if ((flags.get(DynamicParameters.BIT_INCOMPLETE))) {
+ c.setBackground(COLOR_INCOMPLETE);
+ } else if ((flags.get(DynamicParameters.BIT_DEFAULT_VALUE))) {
+ c.setBackground(COLOR_DEFAULT_VALUE);
+ } else if ((flags.get(DynamicParameters.BIT_OPTIONAL))) {
+ c.setBackground(COLOR_OPTIONAL);
+ } else {
+ c.setBackground(null);
+ }
}
}
return c;
@@ -204,75 +216,89 @@ public class ParameterTable extends JTable {
private static final long serialVersionUID = 1L;
/**
+ * We need a panel to ensure focusing.
+ */
+ final JPanel panel;
+
+ /**
* Combo box to use
*/
- private final JComboBox comboBox;
+ private final JComboBox<String> comboBox;
/**
* Constructor.
*
* @param comboBox Combo box we're going to use
*/
- public DropdownEditor(JComboBox comboBox) {
+ public DropdownEditor(JComboBox<String> comboBox) {
super(comboBox);
this.comboBox = comboBox;
+ panel = new DispatchingPanel((JComponent) comboBox.getEditor().getEditorComponent());
+ panel.setLayout(new BorderLayout());
+ panel.add(comboBox, BorderLayout.CENTER);
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
- Component c = super.getTableCellEditorComponent(table, value, isSelected, row, column);
// remove old contents
comboBox.removeAllItems();
// Put the current value in first.
Object val = table.getValueAt(row, column);
- if(val != null) {
- comboBox.addItem(val);
- comboBox.setSelectedIndex(0);
+ if (val != null && val instanceof String) {
+ String sval = (String) val;
+ if (sval.equals(DynamicParameters.STRING_OPTIONAL)) {
+ sval = "";
+ }
+ if (sval.startsWith(DynamicParameters.STRING_USE_DEFAULT)) {
+ sval = "";
+ }
+ if (sval != "") {
+ comboBox.addItem(sval);
+ comboBox.setSelectedIndex(0);
+ }
}
- if(row < parameters.size()) {
+ if (row < parameters.size()) {
Parameter<?> option = parameters.getNode(row).param;
// We can do dropdown choices for class parameters
- if(option instanceof ClassParameter<?>) {
+ if (option instanceof ClassParameter<?>) {
ClassParameter<?> cp = (ClassParameter<?>) option;
// For parameters with a default value, offer using the default
// For optional parameters, offer not specifying them.
- if(cp.hasDefaultValue()) {
+ if (cp.hasDefaultValue()) {
comboBox.addItem(DynamicParameters.STRING_USE_DEFAULT + cp.getDefaultValueAsString());
- }
- else if(cp.isOptional()) {
+ } else if (cp.isOptional()) {
comboBox.addItem(DynamicParameters.STRING_OPTIONAL);
}
// Offer the shorthand version of class names.
- for(Class<?> impl : cp.getKnownImplementations()) {
+ for (Class<?> impl : cp.getKnownImplementations()) {
comboBox.addItem(ClassParameter.canonicalClassName(impl, cp.getRestrictionClass()));
}
}
// and for Flag parameters.
- else if(option instanceof Flag) {
- if(!Flag.SET.equals(val)) {
+ else if (option instanceof Flag) {
+ if (!Flag.SET.equals(val)) {
comboBox.addItem(Flag.SET);
}
- if(!Flag.NOT_SET.equals(val)) {
+ if (!Flag.NOT_SET.equals(val)) {
comboBox.addItem(Flag.NOT_SET);
}
}
// and for Enum parameters.
- else if(option instanceof EnumParameter<?>) {
+ else if (option instanceof EnumParameter<?>) {
EnumParameter<?> ep = (EnumParameter<?>) option;
- for(String s : ep.getPossibleValues()) {
- if(ep.hasDefaultValue() && ep.getDefaultValueAsString().equals(s)) {
- if(!(DynamicParameters.STRING_USE_DEFAULT + ep.getDefaultValueAsString()).equals(val)) {
+ for (String s : ep.getPossibleValues()) {
+ if (ep.hasDefaultValue() && ep.getDefaultValueAsString().equals(s)) {
+ if (!(DynamicParameters.STRING_USE_DEFAULT + ep.getDefaultValueAsString()).equals(val)) {
comboBox.addItem(DynamicParameters.STRING_USE_DEFAULT + s);
}
- }
- else if(!s.equals(val)) {
+ } else if (!s.equals(val)) {
comboBox.addItem(s);
}
}
}
// No completion for others
}
- return c;
+ return panel;
}
}
@@ -290,7 +316,7 @@ public class ParameterTable extends JTable {
/**
* We need a panel to put our components on.
*/
- final JPanel panel = new JPanel();
+ final JPanel panel;
/**
* Text field to store the name
@@ -303,10 +329,16 @@ public class ParameterTable extends JTable {
final JButton button = new JButton("...");
/**
+ * File selector mode.
+ */
+ int mode = FileDialog.LOAD;
+
+ /**
* Constructor.
*/
public FileNameEditor() {
button.addActionListener(this);
+ panel = new DispatchingPanel(textfield);
panel.setLayout(new BorderLayout());
panel.add(textfield, BorderLayout.CENTER);
panel.add(button, BorderLayout.EAST);
@@ -317,19 +349,35 @@ public class ParameterTable extends JTable {
*/
@Override
public void actionPerformed(ActionEvent e) {
- final JFileChooser fc = new JFileChooser(new File("."));
+ final FileDialog fc = new FileDialog(frame);
+ fc.setDirectory((new File(".")).getAbsolutePath());
+ fc.setMode(mode);
final String curr = textfield.getText();
if (curr != null && curr.length() > 0) {
- fc.setSelectedFile(new File(curr));
+ fc.setFile(curr);
}
- int returnVal = fc.showOpenDialog(button);
-
- if(returnVal == JFileChooser.APPROVE_OPTION) {
- textfield.setText(fc.getSelectedFile().getPath());
- }
- else {
- // Do nothing on cancel.
+ fc.setVisible(true);
+ String filename = fc.getFile();
+ if (filename != null) {
+ textfield.setText(new File(fc.getDirectory(), filename).getPath());
}
+ fc.dispose();
+ textfield.requestFocus();
+
+ // Swing file chooser. Currently much worse on Linux/GTK.
+ // final JFileChooser fc = new JFileChooser(new File("."));
+ // final String curr = textfield.getText();
+ // if (curr != null && curr.length() > 0) {
+ // fc.setSelectedFile(new File(curr));
+ // }
+ // int returnVal = fc.showOpenDialog(button);
+ //
+ // if(returnVal == JFileChooser.APPROVE_OPTION) {
+ // textfield.setText(fc.getSelectedFile().getPath());
+ // }
+ // else {
+ // // Do nothing on cancel.
+ // }
fireEditingStopped();
}
@@ -346,23 +394,24 @@ public class ParameterTable extends JTable {
*/
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
- if(row < parameters.size()) {
+ if (row < parameters.size()) {
Parameter<?> option = parameters.getNode(row).param;
- if(option instanceof FileParameter) {
+ if (option instanceof FileParameter) {
FileParameter fp = (FileParameter) option;
File f = null;
- if(fp.isDefined()) {
+ mode = FileParameter.FileType.INPUT_FILE.equals(fp.getFileType()) ? FileDialog.LOAD : FileDialog.SAVE;
+ if (fp.isDefined()) {
f = fp.getValue();
}
- if(f != null) {
+ if (f != null) {
String fn = f.getPath();
textfield.setText(fn);
- }
- else {
+ } else {
textfield.setText("");
}
}
}
+ textfield.requestFocus();
return panel;
}
}
@@ -381,7 +430,7 @@ public class ParameterTable extends JTable {
/**
* We need a panel to put our components on.
*/
- final JPanel panel = new JPanel();
+ final JPanel panel;
/**
* Text field to store the name
@@ -396,7 +445,7 @@ public class ParameterTable extends JTable {
/**
* The combobox we are abusing to produce the popup
*/
- final JComboBox combo = new JComboBox();
+ final JComboBox<String> combo = new JComboBox<>();
/**
* The popup menu.
@@ -413,6 +462,8 @@ public class ParameterTable extends JTable {
combo.addActionListener(this);
popup = new SuperPopup(combo);
+ panel = new DispatchingPanel(textfield);
+
panel.setLayout(new BorderLayout());
panel.add(textfield, BorderLayout.CENTER);
panel.add(button, BorderLayout.EAST);
@@ -423,31 +474,28 @@ public class ParameterTable extends JTable {
*/
@Override
public void actionPerformed(ActionEvent e) {
- if(e.getSource() == button) {
+ if (e.getSource() == button) {
popup.show(panel);
- }
- else if(e.getSource() == combo) {
+ } else if (e.getSource() == combo) {
String newClass = (String) combo.getSelectedItem();
- if(newClass != null && newClass.length() > 0) {
+ if (newClass != null && newClass.length() > 0) {
String val = textfield.getText();
- if(val.equals(DynamicParameters.STRING_OPTIONAL)) {
+ if (val.equals(DynamicParameters.STRING_OPTIONAL)) {
val = "";
}
- if(val.startsWith(DynamicParameters.STRING_USE_DEFAULT)) {
+ if (val.startsWith(DynamicParameters.STRING_USE_DEFAULT)) {
val = "";
}
- if(val.length() > 0) {
+ if (val.length() > 0) {
val = val + ClassListParameter.LIST_SEP + newClass;
- }
- else {
+ } else {
val = newClass;
}
textfield.setText(val);
popup.hide();
}
fireEditingStopped();
- }
- else {
+ } else {
LoggingUtil.warning("Unrecognized action event in ClassListEditor: " + e);
}
}
@@ -470,7 +518,7 @@ public class ParameterTable extends JTable {
*
* @param combo Combo box used for data storage.
*/
- public SuperPopup(JComboBox combo) {
+ public SuperPopup(JComboBox<String> combo) {
super(combo);
}
@@ -516,30 +564,28 @@ public class ParameterTable extends JTable {
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
combo.removeAllItems();
- if(row < parameters.size()) {
+ if (row < parameters.size()) {
Parameter<?> option = parameters.getNode(row).param;
// We can do dropdown choices for class parameters
- if(option instanceof ClassListParameter<?>) {
+ if (option instanceof ClassListParameter<?>) {
ClassListParameter<?> cp = (ClassListParameter<?>) option;
// Offer the shorthand version of class names.
String prefix = cp.getRestrictionClass().getPackage().getName() + ".";
- for(Class<?> impl : cp.getKnownImplementations()) {
+ for (Class<?> impl : cp.getKnownImplementations()) {
String name = impl.getName();
- if(name.startsWith(prefix)) {
+ if (name.startsWith(prefix)) {
name = name.substring(prefix.length());
}
combo.addItem(name);
}
}
- if(option.isDefined()) {
- if(option.tookDefaultValue()) {
+ if (option.isDefined()) {
+ if (option.tookDefaultValue()) {
textfield.setText(DynamicParameters.STRING_USE_DEFAULT + option.getDefaultValueAsString());
- }
- else {
+ } else {
textfield.setText(option.getValueAsString());
}
- }
- else {
+ } else {
textfield.setText("");
}
}
@@ -593,7 +639,7 @@ public class ParameterTable extends JTable {
* Constructor.
*/
public AdjustingEditor() {
- final JComboBox combobox = new JComboBox();
+ final JComboBox<String> combobox = new JComboBox<>();
combobox.setEditable(true);
this.dropdownEditor = new DropdownEditor(combobox);
this.plaintextEditor = new DefaultCellEditor(new JTextField());
@@ -603,7 +649,7 @@ public class ParameterTable extends JTable {
@Override
public Object getCellEditorValue() {
- if(activeEditor == null) {
+ if (activeEditor == null) {
return null;
}
return activeEditor.getCellEditorValue();
@@ -611,31 +657,31 @@ public class ParameterTable extends JTable {
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
- if(value instanceof String) {
+ if (value instanceof String) {
String s = (String) value;
- if(s.startsWith(DynamicParameters.STRING_USE_DEFAULT)) {
+ if (s.startsWith(DynamicParameters.STRING_USE_DEFAULT)) {
value = s.substring(DynamicParameters.STRING_USE_DEFAULT.length());
}
}
- if(row < parameters.size()) {
+ if (row < parameters.size()) {
Parameter<?> option = parameters.getNode(row).param;
- if(option instanceof Flag) {
+ if (option instanceof Flag) {
activeEditor = dropdownEditor;
return dropdownEditor.getTableCellEditorComponent(table, value, isSelected, row, column);
}
- if(option instanceof ClassListParameter<?>) {
+ if (option instanceof ClassListParameter<?>) {
activeEditor = classListEditor;
return classListEditor.getTableCellEditorComponent(table, value, isSelected, row, column);
}
- if(option instanceof ClassParameter<?>) {
+ if (option instanceof ClassParameter<?>) {
activeEditor = dropdownEditor;
return dropdownEditor.getTableCellEditorComponent(table, value, isSelected, row, column);
}
- if(option instanceof FileParameter) {
+ if (option instanceof FileParameter) {
activeEditor = fileNameEditor;
return fileNameEditor.getTableCellEditorComponent(table, value, isSelected, row, column);
}
- if(option instanceof EnumParameter<?>) {
+ if (option instanceof EnumParameter<?>) {
activeEditor = dropdownEditor;
return dropdownEditor.getTableCellEditorComponent(table, value, isSelected, row, column);
}
@@ -644,4 +690,57 @@ public class ParameterTable extends JTable {
return plaintextEditor.getTableCellEditorComponent(table, value, isSelected, row, column);
}
}
-} \ No newline at end of file
+
+ /**
+ * This is a panel that will dispatch keystrokes to a particular component.
+ *
+ * This makes the tabular GUI much more user friendly.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ private class DispatchingPanel extends JPanel {
+ /**
+ * Serial version.
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Component to dispatch to.
+ */
+ protected JComponent component;
+
+ /**
+ * Constructor.
+ *
+ * @param component Component to dispatch to.
+ */
+ public DispatchingPanel(JComponent component) {
+ super();
+ this.component = component;
+ setRequestFocusEnabled(true);
+ }
+
+ @Override
+ public void addNotify() {
+ super.addNotify();
+ component.requestFocus();
+ }
+
+ @Override
+ protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) {
+ InputMap map = component.getInputMap(condition);
+ ActionMap am = component.getActionMap();
+
+ if (map != null && am != null && isEnabled()) {
+ Object binding = map.get(ks);
+ Action action = (binding == null) ? null : am.get(binding);
+ if (action != null) {
+ return SwingUtilities.notifyAction(action, ks, e, component, e.getModifiers());
+ }
+ }
+ return false;
+ }
+ };
+}
diff --git a/src/de/lmu/ifi/dbs/elki/gui/util/ParametersModel.java b/src/de/lmu/ifi/dbs/elki/gui/util/ParametersModel.java
index 2f910977..42f0a1af 100644
--- a/src/de/lmu/ifi/dbs/elki/gui/util/ParametersModel.java
+++ b/src/de/lmu/ifi/dbs/elki/gui/util/ParametersModel.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.gui.util;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/gui/util/SavedSettingsFile.java b/src/de/lmu/ifi/dbs/elki/gui/util/SavedSettingsFile.java
index cf9f5d62..a99b7414 100644
--- a/src/de/lmu/ifi/dbs/elki/gui/util/SavedSettingsFile.java
+++ b/src/de/lmu/ifi/dbs/elki/gui/util/SavedSettingsFile.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.gui.util;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -64,7 +64,7 @@ public class SavedSettingsFile implements Iterable<Pair<String, ArrayList<String
public SavedSettingsFile(String filename) {
super();
this.file = new File(filename);
- this.store = new ArrayList<Pair<String, ArrayList<String>>>();
+ this.store = new ArrayList<>();
}
/**
@@ -93,7 +93,7 @@ public class SavedSettingsFile implements Iterable<Pair<String, ArrayList<String
*/
public void load() throws FileNotFoundException, IOException {
BufferedReader is = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
- ArrayList<String> buf = new ArrayList<String>();
+ ArrayList<String> buf = new ArrayList<>();
while (is.ready()) {
String line = is.readLine();
// skip comments
@@ -102,17 +102,18 @@ public class SavedSettingsFile implements Iterable<Pair<String, ArrayList<String
}
if (line.length() == 0 && buf.size() > 0) {
String title = buf.remove(0);
- store.add(new Pair<String,ArrayList<String>>(title, buf));
- buf = new ArrayList<String>();
+ store.add(new Pair<>(title, buf));
+ buf = new ArrayList<>();
} else {
buf.add(line);
}
}
if (buf.size() > 0) {
String title = buf.remove(0);
- store.add(new Pair<String,ArrayList<String>>(title, buf));
- buf = new ArrayList<String>();
+ store.add(new Pair<>(title, buf));
+ buf = new ArrayList<>();
}
+ is.close();
}
@Override
@@ -175,7 +176,7 @@ public class SavedSettingsFile implements Iterable<Pair<String, ArrayList<String
return;
}
}
- store.add(new Pair<String, ArrayList<String>>(key, value));
+ store.add(new Pair<>(key, value));
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/gui/util/package-info.java b/src/de/lmu/ifi/dbs/elki/gui/util/package-info.java
index de9f582a..706f587a 100644
--- a/src/de/lmu/ifi/dbs/elki/gui/util/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/gui/util/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/AbstractIndex.java b/src/de/lmu/ifi/dbs/elki/index/AbstractIndex.java
index 44418a3e..c9dbf3a0 100644
--- a/src/de/lmu/ifi/dbs/elki/index/AbstractIndex.java
+++ b/src/de/lmu/ifi/dbs/elki/index/AbstractIndex.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,15 +23,14 @@ package de.lmu.ifi.dbs.elki.index;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
-import de.lmu.ifi.dbs.elki.persistent.PageFileStatistics;
/**
* Abstract base class for indexes with some implementation defaults.
*
* @author Erich Schubert
+ *
+ * @apiviz.excludeSubtypes
*
* @param <O> Object type stored in the index
*/
@@ -56,31 +55,4 @@ public abstract class AbstractIndex<O> implements Index {
@Override
abstract public String getShortName();
-
- @Override
- public PageFileStatistics getPageFileStatistics() {
- // TODO: move this into a separate interface?
- // By default, we are not file based - no statistics available
- return null;
- }
-
- @Override
- public void insert(DBIDRef id) {
- throw new UnsupportedOperationException("This index does not allow dynamic updates.");
- }
-
- @Override
- public void insertAll(DBIDs ids) {
- throw new UnsupportedOperationException("This index does not allow dynamic updates.");
- }
-
- @Override
- public boolean delete(DBIDRef id) {
- throw new UnsupportedOperationException("This index does not allow dynamic updates.");
- }
-
- @Override
- public void deleteAll(DBIDs id) {
- throw new UnsupportedOperationException("This index does not allow dynamic updates.");
- }
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/index/AbstractRefiningIndex.java b/src/de/lmu/ifi/dbs/elki/index/AbstractRefiningIndex.java
index 33c9b341..b266824a 100644
--- a/src/de/lmu/ifi/dbs/elki/index/AbstractRefiningIndex.java
+++ b/src/de/lmu/ifi/dbs/elki/index/AbstractRefiningIndex.java
@@ -1,9 +1,10 @@
package de.lmu.ifi.dbs.elki.index;
+
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -22,20 +23,15 @@ package de.lmu.ifi.dbs.elki.index;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.List;
-
-import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.AbstractDistanceKNNQuery;
import de.lmu.ifi.dbs.elki.database.query.range.AbstractDistanceRangeQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
-import de.lmu.ifi.dbs.elki.persistent.PageFileStatistics;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.statistics.Counter;
/**
* Abstract base class for Filter-refinement indexes.
@@ -44,16 +40,17 @@ import de.lmu.ifi.dbs.elki.persistent.PageFileStatistics;
*
* @author Erich Schubert
*
+ * @apiviz.excludeSubtypes
* @apiviz.has AbstractRangeQuery
* @apiviz.has AbstractKNNQuery
*
* @param <O> Object type
*/
-public abstract class AbstractRefiningIndex<O> extends AbstractIndex<O> implements PageFileStatistics {
+public abstract class AbstractRefiningIndex<O> extends AbstractIndex<O> {
/**
* Refinement counter.
*/
- private int refinements;
+ private Counter refinements;
/**
* Constructor.
@@ -62,81 +59,61 @@ public abstract class AbstractRefiningIndex<O> extends AbstractIndex<O> implemen
*/
public AbstractRefiningIndex(Relation<O> relation) {
super(relation);
+ Logging log = getLogger();
+ refinements = log.isStatistics() ? log.newCounter(this.getClass().getName() + ".refinements") : null;
}
/**
- * Initialize the index.
+ * Get the class logger.
*
- * @param relation Relation to index
- * @param ids database ids
+ * @return Logger
*/
- protected abstract void initialize(Relation<O> relation, DBIDs ids);
+ abstract public Logging getLogger();
/**
- * Refine a given object (and count the refinement!).
+ * Increment the refinement counter, if in use.
*
- * @param id Object id
- * @return refined object
+ * @param i Increment.
*/
- protected O refine(DBID id) {
- refinements++;
- return relation.get(id);
- }
-
- @Override
- public PageFileStatistics getPageFileStatistics() {
- return this;
- }
-
- @Override
- public long getReadOperations() {
- return refinements;
- }
-
- @Override
- public long getWriteOperations() {
- return 0;
- }
-
- @Override
- public void resetPageAccess() {
- refinements = 0;
+ protected void countRefinements(int i) {
+ if (refinements != null) {
+ refinements.increment(i);
+ }
}
@Override
- public PageFileStatistics getInnerStatistics() {
- return null;
+ public void logStatistics() {
+ if (refinements != null) {
+ getLogger().statistics(refinements);
+ }
}
- @Override
- public void insertAll(DBIDs ids) {
- initialize(relation, ids);
+ /**
+ * Refine a given object (and count the refinement!).
+ *
+ * @param id Object id
+ * @return refined object
+ */
+ protected O refine(DBID id) {
+ countRefinements(1);
+ return relation.get(id);
}
/**
* Range query for this index.
*
* @author Erich Schubert
+ *
+ * @apiviz.excludeSubtypes
*/
public abstract class AbstractRangeQuery<D extends Distance<D>> extends AbstractDistanceRangeQuery<O, D> {
/**
- * Hold the distance function to be used.
- */
- private DistanceQuery<O, D> distanceQuery;
-
- /**
* Constructor.
*
* @param distanceQuery Distance query object
*/
public AbstractRangeQuery(DistanceQuery<O, D> distanceQuery) {
super(distanceQuery);
- this.distanceQuery = distanceQuery;
- }
-
- @Override
- public DistanceDBIDResult<D> getRangeForDBID(DBIDRef id, D range) {
- return getRangeForObject(relation.get(id), range);
}
/**
@@ -147,7 +124,7 @@ public abstract class AbstractRefiningIndex<O> extends AbstractIndex<O> implemen
* @return Distance
*/
protected D refine(DBIDRef id, O q) {
- AbstractRefiningIndex.this.refinements++;
+ AbstractRefiningIndex.this.countRefinements(1);
return distanceQuery.distance(q, id);
}
@@ -157,7 +134,7 @@ public abstract class AbstractRefiningIndex<O> extends AbstractIndex<O> implemen
* @param c Refinements
*/
protected void incRefinements(int c) {
- AbstractRefiningIndex.this.refinements += c;
+ AbstractRefiningIndex.this.countRefinements(c);
}
}
@@ -165,6 +142,8 @@ public abstract class AbstractRefiningIndex<O> extends AbstractIndex<O> implemen
* KNN query for this index.
*
* @author Erich Schubert
+ *
+ * @apiviz.excludeSubtypes
*/
public abstract class AbstractKNNQuery<D extends Distance<D>> extends AbstractDistanceKNNQuery<O, D> {
/**
@@ -176,16 +155,6 @@ public abstract class AbstractRefiningIndex<O> extends AbstractIndex<O> implemen
super(distanceQuery);
}
- @Override
- public List<KNNResult<D>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) {
- throw new UnsupportedOperationException("Not yet implemented.");
- }
-
- @Override
- public KNNResult<D> getKNNForDBID(DBIDRef id, int k) {
- return getKNNForObject(relation.get(id), k);
- }
-
/**
* Refinement distance computation.
*
@@ -194,7 +163,7 @@ public abstract class AbstractRefiningIndex<O> extends AbstractIndex<O> implemen
* @return Distance
*/
protected D refine(DBID id, O q) {
- AbstractRefiningIndex.this.refinements++;
+ AbstractRefiningIndex.this.countRefinements(1);
return distanceQuery.distance(q, id);
}
@@ -204,7 +173,7 @@ public abstract class AbstractRefiningIndex<O> extends AbstractIndex<O> implemen
* @param c Refinements
*/
protected void incRefinements(int c) {
- AbstractRefiningIndex.this.refinements += c;
+ AbstractRefiningIndex.this.countRefinements(c);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/DynamicIndex.java b/src/de/lmu/ifi/dbs/elki/index/DynamicIndex.java
new file mode 100644
index 00000000..53f6d5fe
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/DynamicIndex.java
@@ -0,0 +1,66 @@
+package de.lmu.ifi.dbs.elki.index;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+
+/**
+ * Index that supports dynamic insertions and removals.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.excludeSubtypes
+ */
+public interface DynamicIndex extends Index {
+ /**
+ * Deletes the specified object from this index.
+ *
+ * @param id Object to remove
+ * @return true if this index did contain the object, false otherwise
+ */
+ public boolean delete(DBIDRef id);
+
+ /**
+ * Inserts the specified object into this index.
+ *
+ * @param id the object to be inserted
+ */
+ public void insert(DBIDRef id);
+
+ /**
+ * Deletes the specified objects from this index.
+ *
+ * @param ids Objects to remove
+ */
+ public void deleteAll(DBIDs ids);
+
+ /**
+ * Inserts the specified objects into this index. If a bulk load mode is
+ * implemented, the objects are inserted in one bulk.
+ *
+ * @param ids the objects to be inserted
+ */
+ public void insertAll(DBIDs ids);
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/Index.java b/src/de/lmu/ifi/dbs/elki/index/Index.java
index 1b866f5e..e2156a04 100644
--- a/src/de/lmu/ifi/dbs/elki/index/Index.java
+++ b/src/de/lmu/ifi/dbs/elki/index/Index.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,53 +23,30 @@ package de.lmu.ifi.dbs.elki.index;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
-import de.lmu.ifi.dbs.elki.persistent.PageFileStatistics;
import de.lmu.ifi.dbs.elki.result.Result;
/**
* Interface defining the minimum requirements for all index classes.
*
+ * See also: {@link IndexFactory}, {@link DynamicIndex}
+ *
* @author Elke Achtert
*
- * @apiviz.landmark
+ * @apiviz.excludeSubtypes
*/
public interface Index extends Result {
/**
- * Get the underlying page file (or a proxy), for access counts.
- *
- * @return page file
- */
- public PageFileStatistics getPageFileStatistics();
-
- /**
- * Inserts the specified object into this index.
- *
- * @param id the object to be inserted
- */
- public void insert(DBIDRef id);
-
- /**
- * Inserts the specified objects into this index. If a bulk load mode is
- * implemented, the objects are inserted in one bulk.
- *
- * @param ids the objects to be inserted
- */
- public void insertAll(DBIDs ids);
-
- /**
- * Deletes the specified object from this index.
- *
- * @param id Object to remove
- * @return true if this index did contain the object, false otherwise
+ * Initialize the index. For static indexes, this is the moment the index is
+ * bulk loaded.
*/
- public boolean delete(DBIDRef id);
+ public void initialize();
/**
- * Deletes the specified objects from this index.
+ * Send statistics to the logger, if enabled.
*
- * @param ids Objects to remove
+ * Note: you must have set the logging level appropriately before initializing
+ * the index! Otherwise, the index might not have collected the desired
+ * statistics.
*/
- public void deleteAll(DBIDs ids);
-} \ No newline at end of file
+ public void logStatistics();
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/IndexFactory.java b/src/de/lmu/ifi/dbs/elki/index/IndexFactory.java
index ac34c53f..80ac2ef5 100644
--- a/src/de/lmu/ifi/dbs/elki/index/IndexFactory.java
+++ b/src/de/lmu/ifi/dbs/elki/index/IndexFactory.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -34,6 +34,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable;
*
* @apiviz.stereotype factory,interface
* @apiviz.has Index oneway - - «create»
+ * @apiviz.excludeSubtypes
*
* @param <V> Input object type
* @param <I> Index type
diff --git a/src/de/lmu/ifi/dbs/elki/index/KNNIndex.java b/src/de/lmu/ifi/dbs/elki/index/KNNIndex.java
index 83a37f88..0384a437 100644
--- a/src/de/lmu/ifi/dbs/elki/index/KNNIndex.java
+++ b/src/de/lmu/ifi/dbs/elki/index/KNNIndex.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -33,6 +33,7 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
* @author Erich Schubert
*
* @apiviz.landmark
+ * @apiviz.excludeSubtypes
* @apiviz.has KNNQuery oneway - - «provides»
*
* @param <O> Object type
diff --git a/src/de/lmu/ifi/dbs/elki/index/PagedIndexFactory.java b/src/de/lmu/ifi/dbs/elki/index/PagedIndexFactory.java
new file mode 100644
index 00000000..211a0fb3
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/PagedIndexFactory.java
@@ -0,0 +1,110 @@
+package de.lmu.ifi.dbs.elki.index;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.persistent.ExternalizablePage;
+import de.lmu.ifi.dbs.elki.persistent.MemoryPageFileFactory;
+import de.lmu.ifi.dbs.elki.persistent.PageFile;
+import de.lmu.ifi.dbs.elki.persistent.PageFileFactory;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
+
+/**
+ * Abstract base class for tree-based indexes.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.stereotype factory,interface
+ * @apiviz.excludeSubtypes
+ * @apiviz.composedOf PageFileFactory
+ *
+ * @param <O> Object type
+ * @param <I> Index type
+ */
+public abstract class PagedIndexFactory<O, I extends Index> implements IndexFactory<O, I> {
+ /**
+ * Page file factory.
+ */
+ private PageFileFactory<?> pageFileFactory;
+
+ /**
+ * Constructor.
+ *
+ * @param pageFileFactory Page file factory
+ */
+ public PagedIndexFactory(PageFileFactory<?> pageFileFactory) {
+ super();
+ this.pageFileFactory = pageFileFactory;
+ }
+
+ /**
+ * Make the page file for this index.
+ *
+ * @param <N> page type
+ * @param cls Class information
+ * @return Page file
+ */
+ protected <N extends ExternalizablePage> PageFile<N> makePageFile(Class<N> cls) {
+ @SuppressWarnings("unchecked")
+ final PageFileFactory<N> castFactory = (PageFileFactory<N>) pageFileFactory;
+ return castFactory.newPageFile(cls);
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public abstract static class Parameterizer<O> extends AbstractParameterizer {
+ /**
+ * Optional parameter that specifies the factory type of pagefile to use for
+ * the index.
+ * <p>
+ * Key: {@code -index.pagefile}
+ * </p>
+ */
+ public static final OptionID PAGEFILE_ID = new OptionID("index.pagefile", "The pagefile factory for storing the index.");
+
+ /**
+ * Page file factory.
+ */
+ protected PageFileFactory<?> pageFileFactory;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ ObjectParameter<PageFileFactory<?>> pffP = new ObjectParameter<>(PAGEFILE_ID, PageFileFactory.class, MemoryPageFileFactory.class);
+ if (config.grab(pffP)) {
+ pageFileFactory = pffP.instantiateClass(config);
+ }
+ }
+
+ @Override
+ protected abstract PagedIndexFactory<O, ?> makeInstance();
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/RKNNIndex.java b/src/de/lmu/ifi/dbs/elki/index/RKNNIndex.java
index 6c990cd8..5a1f0f84 100644
--- a/src/de/lmu/ifi/dbs/elki/index/RKNNIndex.java
+++ b/src/de/lmu/ifi/dbs/elki/index/RKNNIndex.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -33,6 +33,7 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
* @author Erich Schubert
*
* @apiviz.landmark
+ * @apiviz.excludeSubtypes
* @apiviz.has RKNNQuery oneway - - «provides»
*
* @param <O> Database Object type
diff --git a/src/de/lmu/ifi/dbs/elki/index/RangeIndex.java b/src/de/lmu/ifi/dbs/elki/index/RangeIndex.java
index 5d64a8fa..cc5b7493 100644
--- a/src/de/lmu/ifi/dbs/elki/index/RangeIndex.java
+++ b/src/de/lmu/ifi/dbs/elki/index/RangeIndex.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -33,6 +33,7 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
* @author Erich Schubert
*
* @apiviz.landmark
+ * @apiviz.excludeSubtypes
* @apiviz.has RangeQuery oneway - - «provides»
*
* @param <O> Database Object type
diff --git a/src/de/lmu/ifi/dbs/elki/index/lsh/InMemoryLSHIndex.java b/src/de/lmu/ifi/dbs/elki/index/lsh/InMemoryLSHIndex.java
new file mode 100644
index 00000000..c1bd43be
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/lsh/InMemoryLSHIndex.java
@@ -0,0 +1,418 @@
+package de.lmu.ifi.dbs.elki.index.lsh;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import gnu.trove.iterator.TIntObjectIterator;
+import gnu.trove.map.TIntObjectMap;
+import gnu.trove.map.hash.TIntObjectHashMap;
+
+import java.util.ArrayList;
+
+import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNHeap;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
+import de.lmu.ifi.dbs.elki.database.ids.generic.GenericDistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery;
+import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
+import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
+import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.index.AbstractRefiningIndex;
+import de.lmu.ifi.dbs.elki.index.IndexFactory;
+import de.lmu.ifi.dbs.elki.index.KNNIndex;
+import de.lmu.ifi.dbs.elki.index.RangeIndex;
+import de.lmu.ifi.dbs.elki.index.lsh.hashfamilies.LocalitySensitiveHashFunctionFamily;
+import de.lmu.ifi.dbs.elki.index.lsh.hashfunctions.LocalitySensitiveHashFunction;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
+import de.lmu.ifi.dbs.elki.logging.statistics.LongStatistic;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
+
+/**
+ * Locality Sensitive Hashing.
+ *
+ * @author Erich Schubert
+ *
+ * @param <V> Object type to index
+ */
+public class InMemoryLSHIndex<V> implements IndexFactory<V, InMemoryLSHIndex<V>.Instance> {
+ /**
+ * Class logger
+ */
+ private static final Logging LOG = Logging.getLogger(InMemoryLSHIndex.class);
+
+ /**
+ * LSH hash function family to use.
+ */
+ LocalitySensitiveHashFunctionFamily<? super V> family;
+
+ /**
+ * Number of hash functions for each table.
+ */
+ int l;
+
+ /**
+ * Number of buckets to use.
+ */
+ int numberOfBuckets;
+
+ /**
+ * Constructor.
+ *
+ * @param family Projection family
+ * @param l Number of hash tables to use
+ * @param numberOfBuckets Number of buckets to use.
+ */
+ public InMemoryLSHIndex(LocalitySensitiveHashFunctionFamily<? super V> family, int l, int numberOfBuckets) {
+ super();
+ this.family = family;
+ this.l = l;
+ this.numberOfBuckets = numberOfBuckets;
+ }
+
+ @Override
+ public Instance instantiate(Relation<V> relation) {
+ return new Instance(relation, family.generateHashFunctions(relation, l), numberOfBuckets);
+ }
+
+ @Override
+ public TypeInformation getInputTypeRestriction() {
+ return family.getInputTypeRestriction();
+ }
+
+ /**
+ * Instance of a LSH index for a single relation.
+ *
+ * @author Erich Schubert
+ */
+ public class Instance extends AbstractRefiningIndex<V> implements KNNIndex<V>, RangeIndex<V> {
+ /**
+ * Hash functions to use.
+ */
+ ArrayList<? extends LocalitySensitiveHashFunction<? super V>> hashfunctions;
+
+ /**
+ * The actual table
+ */
+ ArrayList<TIntObjectMap<DBIDs>> hashtables;
+
+ /**
+ * Number of buckets to use.
+ */
+ private int numberOfBuckets;
+
+ /**
+ * Constructor.
+ *
+ * @param relation Relation to index.
+ * @param hashfunctions Hash functions.
+ */
+ public Instance(Relation<V> relation, ArrayList<? extends LocalitySensitiveHashFunction<? super V>> hashfunctions, int numberOfBuckets) {
+ super(relation);
+ this.hashfunctions = hashfunctions;
+ this.numberOfBuckets = numberOfBuckets;
+ }
+
+ @Override
+ public String getLongName() {
+ return "LSH index";
+ }
+
+ @Override
+ public String getShortName() {
+ return "lsh-index";
+ }
+
+ @Override
+ public void initialize() {
+ final int numhash = hashfunctions.size();
+ hashtables = new ArrayList<>(numhash);
+ for (int i = 0; i < numhash; i++) {
+ hashtables.add(new TIntObjectHashMap<DBIDs>(numberOfBuckets));
+ }
+
+ FiniteProgress progress = LOG.isVerbose() ? new FiniteProgress("Building LSH index.", relation.size(), LOG) : null;
+ int expect = Math.max(2, (int) Math.ceil(relation.size() / (double) numberOfBuckets));
+ for (DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) {
+ V obj = relation.get(iter);
+ for (int i = 0; i < numhash; i++) {
+ final TIntObjectMap<DBIDs> table = hashtables.get(i);
+ final LocalitySensitiveHashFunction<? super V> hashfunc = hashfunctions.get(i);
+ // Get the initial (unbounded) hash code:
+ int hash = hashfunc.hashObject(obj);
+ // Reduce to hash table size
+ int bucket = hash % numberOfBuckets;
+ DBIDs cur = table.get(bucket);
+ if (cur == null) {
+ table.put(bucket, DBIDUtil.deref(iter));
+ } else if (cur.size() > 1) {
+ ((ModifiableDBIDs) cur).add(iter);
+ } else {
+ ModifiableDBIDs newbuck = DBIDUtil.newArray(expect);
+ newbuck.addDBIDs(cur);
+ newbuck.add(iter);
+ table.put(bucket, newbuck);
+ }
+ }
+ if (progress != null) {
+ progress.incrementProcessed(LOG);
+ }
+ }
+ if (progress != null) {
+ progress.ensureCompleted(LOG);
+ }
+ if (LOG.isStatistics()) {
+ int min = Integer.MAX_VALUE, max = 0;
+ for (int i = 0; i < numhash; i++) {
+ final TIntObjectMap<DBIDs> table = hashtables.get(i);
+ for (TIntObjectIterator<DBIDs> iter = table.iterator(); iter.hasNext();) {
+ iter.advance();
+ int size = iter.value().size();
+ if (size < min) {
+ min = size;
+ }
+ if (size > max) {
+ max = size;
+ }
+ }
+ }
+ LOG.statistics(new LongStatistic(this.getClass().getName() + ".fill.min", max));
+ LOG.statistics(new LongStatistic(this.getClass().getName() + ".fill.max", min));
+ LOG.statistics(new LongStatistic(this.getClass().getName() + ".hashtables", hashtables.size()));
+ }
+ }
+
+ @Override
+ public Logging getLogger() {
+ return LOG;
+ }
+
+ @Override
+ public <D extends Distance<D>> KNNQuery<V, D> getKNNQuery(DistanceQuery<V, D> distanceQuery, Object... hints) {
+ for (Object hint : hints) {
+ if (DatabaseQuery.HINT_EXACT.equals(hint)) {
+ return null;
+ }
+ }
+ DistanceFunction<? super V, D> df = distanceQuery.getDistanceFunction();
+ if (!family.isCompatible(df)) {
+ return null;
+ }
+ return (KNNQuery<V, D>) new LSHKNNQuery<>(distanceQuery);
+ }
+
+ @Override
+ public <D extends Distance<D>> RangeQuery<V, D> getRangeQuery(DistanceQuery<V, D> distanceQuery, Object... hints) {
+ for (Object hint : hints) {
+ if (DatabaseQuery.HINT_EXACT.equals(hint)) {
+ return null;
+ }
+ }
+ DistanceFunction<? super V, D> df = distanceQuery.getDistanceFunction();
+ if (!family.isCompatible(df)) {
+ return null;
+ }
+ return (RangeQuery<V, D>) new LSHRangeQuery<>(distanceQuery);
+ }
+
+ /**
+ * Class for handling kNN queries against the LSH index.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ *
+ * @param <D> Distance type
+ */
+ protected class LSHKNNQuery<D extends Distance<D>> extends AbstractKNNQuery<D> {
+ /**
+ * Constructor.
+ *
+ * @param distanceQuery
+ */
+ public LSHKNNQuery(DistanceQuery<V, D> distanceQuery) {
+ super(distanceQuery);
+ }
+
+ @Override
+ public KNNList<D> getKNNForObject(V obj, int k) {
+ ModifiableDBIDs candidates = null;
+ final int numhash = hashtables.size();
+ for (int i = 0; i < numhash; i++) {
+ final TIntObjectMap<DBIDs> table = hashtables.get(i);
+ final LocalitySensitiveHashFunction<? super V> hashfunc = hashfunctions.get(i);
+ // Get the initial (unbounded) hash code:
+ int hash = hashfunc.hashObject(obj);
+ // Reduce to hash table size
+ int bucket = hash % numberOfBuckets;
+ DBIDs cur = table.get(bucket);
+ if (cur != null) {
+ if (candidates == null) {
+ candidates = DBIDUtil.newHashSet(cur.size() * numhash + k);
+ }
+ candidates.addDBIDs(cur);
+ }
+ }
+ if (candidates == null) {
+ candidates = DBIDUtil.newArray();
+ }
+
+ // Refine.
+ KNNHeap<D> heap = DBIDUtil.newHeap(distanceQuery.getDistanceFactory(), k);
+ for (DBIDIter iter = candidates.iter(); iter.valid(); iter.advance()) {
+ final D dist = distanceQuery.distance(obj, iter);
+ super.incRefinements(1);
+ heap.add(dist, iter);
+ }
+ return heap.toKNNList();
+ }
+ }
+
+ /**
+ * Class for handling kNN queries against the LSH index.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ *
+ * @param <D> Distance type
+ */
+ protected class LSHRangeQuery<D extends Distance<D>> extends AbstractRangeQuery<D> {
+ /**
+ * Constructor.
+ *
+ * @param distanceQuery
+ */
+ public LSHRangeQuery(DistanceQuery<V, D> distanceQuery) {
+ super(distanceQuery);
+ }
+
+ @Override
+ public DistanceDBIDList<D> getRangeForObject(V obj, D range) {
+ ModifiableDBIDs candidates = DBIDUtil.newHashSet();
+ final int numhash = hashtables.size();
+ for (int i = 0; i < numhash; i++) {
+ final TIntObjectMap<DBIDs> table = hashtables.get(i);
+ final LocalitySensitiveHashFunction<? super V> hashfunc = hashfunctions.get(i);
+ // Get the initial (unbounded) hash code:
+ int hash = hashfunc.hashObject(obj);
+ // Reduce to hash table size
+ int bucket = hash % numberOfBuckets;
+ DBIDs cur = table.get(bucket);
+ if (cur != null) {
+ candidates.addDBIDs(cur);
+ }
+ }
+
+ // Refine.
+ GenericDistanceDBIDList<D> result = new GenericDistanceDBIDList<>();
+ for (DBIDIter iter = candidates.iter(); iter.valid(); iter.advance()) {
+ final D dist = distanceQuery.distance(obj, iter);
+ super.incRefinements(1);
+ if (range.compareTo(dist) >= 0) {
+ result.add(dist, iter);
+ }
+ }
+ return result;
+ }
+ }
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer<V> extends AbstractParameterizer {
+ /**
+ * Hash function family parameter.
+ */
+ public static final OptionID FAMILY_ID = new OptionID("lsh.family", "Hash function family to use for LSH.");
+
+ /**
+ * Number of hash tables to use for LSH.
+ */
+ public static final OptionID L_ID = new OptionID("lsh.tables", "Number of hash tables to use.");
+
+ /**
+ * Number of hash tables to use for LSH.
+ */
+ public static final OptionID BUCKETS_ID = new OptionID("lsh.buckets", "Number of hash buckets to use.");
+
+ /**
+ * LSH hash function family to use.
+ */
+ LocalitySensitiveHashFunctionFamily<? super V> family;
+
+ /**
+ * Number of hash functions for each table.
+ */
+ int l;
+
+ /**
+ * Number of buckets to use.
+ */
+ int numberOfBuckets;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ ObjectParameter<LocalitySensitiveHashFunctionFamily<? super V>> familyP = new ObjectParameter<>(FAMILY_ID, LocalitySensitiveHashFunctionFamily.class);
+ if (config.grab(familyP)) {
+ family = familyP.instantiateClass(config);
+ }
+
+ IntParameter lP = new IntParameter(L_ID);
+ lP.addConstraint(new GreaterConstraint(0));
+ if (config.grab(lP)) {
+ l = lP.intValue();
+ }
+
+ IntParameter bucketsP = new IntParameter(BUCKETS_ID);
+ bucketsP.setDefaultValue(7919); // Primes work best, apparently.
+ bucketsP.addConstraint(new GreaterConstraint(1));
+ if (config.grab(bucketsP)) {
+ numberOfBuckets = bucketsP.intValue();
+ }
+ }
+
+ @Override
+ protected InMemoryLSHIndex<V> makeInstance() {
+ return new InMemoryLSHIndex<>(family, l, numberOfBuckets);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/AbstractHashFunctionFamily.java b/src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/AbstractHashFunctionFamily.java
new file mode 100644
index 00000000..1ed350f0
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/AbstractHashFunctionFamily.java
@@ -0,0 +1,164 @@
+package de.lmu.ifi.dbs.elki.index.lsh.hashfamilies;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.ArrayList;
+import java.util.Random;
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
+import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.database.relation.RelationUtil;
+import de.lmu.ifi.dbs.elki.index.lsh.hashfunctions.LocalitySensitiveHashFunction;
+import de.lmu.ifi.dbs.elki.index.lsh.hashfunctions.MultipleProjectionsLocalitySensitiveHashFunction;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.randomprojections.RandomProjectionFamily;
+import de.lmu.ifi.dbs.elki.utilities.RandomFactory;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleParameter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.RandomParameter;
+
+/**
+ * Abstract base class for projection based hash functions.
+ *
+ * @author Erich Schubert
+ */
+public abstract class AbstractHashFunctionFamily implements LocalitySensitiveHashFunctionFamily<NumberVector<?>> {
+ /**
+ * Random generator to use.
+ */
+ protected RandomFactory random;
+
+ /**
+ * Projection family to use.
+ */
+ protected RandomProjectionFamily proj;
+
+ /**
+ * Width of each bin.
+ */
+ protected double width;
+
+ /**
+ * The number of projections to use for each hash function.
+ */
+ protected int k;
+
+ /**
+ * Constructor.
+ *
+ * @param random Random generator
+ * @param proj Projection family
+ * @param width Bin width
+ * @param k Number of projections for each hash function.
+ */
+ public AbstractHashFunctionFamily(RandomFactory random, RandomProjectionFamily proj, double width, int k) {
+ super();
+ this.random = random;
+ this.proj = proj;
+ this.width = width;
+ this.k = k;
+ }
+
+ @Override
+ public ArrayList<? extends LocalitySensitiveHashFunction<? super NumberVector<?>>> generateHashFunctions(Relation<? extends NumberVector<?>> relation, int l) {
+ int dim = RelationUtil.dimensionality(relation);
+ ArrayList<LocalitySensitiveHashFunction<? super NumberVector<?>>> ps = new ArrayList<>(l);
+ final Random rnd = random.getRandom();
+ for (int i = 0; i < l; i++) {
+ RandomProjectionFamily.Projection mat = proj.generateProjection(dim, k);
+ ps.add(new MultipleProjectionsLocalitySensitiveHashFunction(mat, width, rnd));
+ }
+ return ps;
+ }
+
+ @Override
+ public TypeInformation getInputTypeRestriction() {
+ return TypeUtil.NUMBER_VECTOR_FIELD;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public abstract static class Parameterizer extends AbstractParameterizer {
+ /**
+ * Parameter for fixing the random seed.
+ */
+ public static final OptionID RANDOM_ID = new OptionID("lsh.projection.random", "Random seed for generating the projections.");
+
+ /**
+ * Parameter for choosing the bin width.
+ */
+ public static final OptionID WIDTH_ID = new OptionID("lsh.projection.width", "Bin width for random projections.");
+
+ /**
+ * Number of projections to use in each hash function.
+ */
+ public static final OptionID NUMPROJ_ID = new OptionID("lsh.projection.projections", "Number of projections to use for each hash function.");
+
+ /**
+ * Random generator to use.
+ */
+ RandomFactory random;
+
+ /**
+ * Width of each bin.
+ */
+ double width;
+
+ /**
+ * The number of projections to use for each hash function.
+ */
+ int k;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ RandomParameter randP = new RandomParameter(RANDOM_ID, RandomFactory.DEFAULT);
+ if (config.grab(randP)) {
+ random = randP.getValue();
+ }
+
+ DoubleParameter widthP = new DoubleParameter(WIDTH_ID);
+ widthP.addConstraint(new GreaterConstraint(0.0));
+ if (config.grab(widthP)) {
+ width = widthP.doubleValue();
+ }
+
+ IntParameter lP = new IntParameter(NUMPROJ_ID);
+ lP.addConstraint(new GreaterConstraint(0));
+ if (config.grab(lP)) {
+ k = lP.intValue();
+ }
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/EuclideanHashFunctionFamily.java b/src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/EuclideanHashFunctionFamily.java
new file mode 100644
index 00000000..0aa983e5
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/EuclideanHashFunctionFamily.java
@@ -0,0 +1,74 @@
+package de.lmu.ifi.dbs.elki.index.lsh.hashfamilies;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.randomprojections.GaussianRandomProjectionFamily;
+import de.lmu.ifi.dbs.elki.utilities.RandomFactory;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+
+/**
+ * 2-stable hash function family for Euclidean distances.
+ *
+ * Reference:
+ * <p>
+ * Locality-sensitive hashing scheme based on p-stable distributions<br />
+ * M. Datar and N. Immorlica and P. Indyk and V. S. Mirrokni<br />
+ * Proc. 20th annual symposium on Computational geometry<br />
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@Reference(authors = "M. Datar and N. Immorlica and P. Indyk and V. S. Mirrokni", title = "Locality-sensitive hashing scheme based on p-stable distributions", booktitle = "Proc. 20th annual symposium on Computational geometry", url = "http://dx.doi.org/10.1145/997817.997857")
+public class EuclideanHashFunctionFamily extends AbstractHashFunctionFamily {
+ /**
+ * Constructor.
+ *
+ * @param random Random generator
+ * @param width Bin width
+ * @param k Number of projections to combine.
+ */
+ public EuclideanHashFunctionFamily(RandomFactory random, double width, int k) {
+ super(random, new GaussianRandomProjectionFamily(random), width, k);
+ }
+
+ @Override
+ public boolean isCompatible(DistanceFunction<?, ?> df) {
+ return EuclideanDistanceFunction.class.isInstance(df);
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractHashFunctionFamily.Parameterizer {
+ @Override
+ protected EuclideanHashFunctionFamily makeInstance() {
+ return new EuclideanHashFunctionFamily(random, width, k);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/LocalitySensitiveHashFunctionFamily.java b/src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/LocalitySensitiveHashFunctionFamily.java
new file mode 100644
index 00000000..4d3468bb
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/LocalitySensitiveHashFunctionFamily.java
@@ -0,0 +1,65 @@
+package de.lmu.ifi.dbs.elki.index.lsh.hashfamilies;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.ArrayList;
+
+import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
+import de.lmu.ifi.dbs.elki.index.lsh.hashfunctions.LocalitySensitiveHashFunction;
+
+/**
+ * LSH family of hash functions.
+ *
+ * @author Erich Schubert
+ *
+ * @param <V> Object type
+ */
+public interface LocalitySensitiveHashFunctionFamily<V> {
+ /**
+ * Get the input type information.
+ *
+ * @return Input type information.
+ */
+ TypeInformation getInputTypeRestriction();
+
+ /**
+ * Generate hash functions for the given relation.
+ *
+ * @param relation Relation to index
+ * @param k number of hash functions per table.
+ * @return Family of hash functions
+ */
+ ArrayList<? extends LocalitySensitiveHashFunction<? super V>> generateHashFunctions(Relation<? extends V> relation, int k);
+
+ /**
+ * Check whether the given distance function can be accelerated using this
+ * hash family.
+ *
+ * @param df Distance function.
+ * @return {@code true} when appropriate.
+ */
+ boolean isCompatible(DistanceFunction<?, ?> df);
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/ManhattanHashFunctionFamily.java b/src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/ManhattanHashFunctionFamily.java
new file mode 100644
index 00000000..a117c44c
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/ManhattanHashFunctionFamily.java
@@ -0,0 +1,76 @@
+package de.lmu.ifi.dbs.elki.index.lsh.hashfamilies;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.ManhattanDistanceFunction;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.randomprojections.CauchyRandomProjectionFamily;
+import de.lmu.ifi.dbs.elki.utilities.RandomFactory;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+
+/**
+ * 2-stable hash function family for Euclidean distances.
+ *
+ * Reference:
+ * <p>
+ * Locality-sensitive hashing scheme based on p-stable distributions<br />
+ * M. Datar and N. Immorlica and P. Indyk and V. S. Mirrokni<br />
+ * Proc. 20th annual symposium on Computational geometry<br />
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@Reference(authors = "M. Datar and N. Immorlica and P. Indyk and V. S. Mirrokni", title = "Locality-sensitive hashing scheme based on p-stable distributions", booktitle = "Proc. 20th annual symposium on Computational geometry", url = "http://dx.doi.org/10.1145/997817.997857")
+public class ManhattanHashFunctionFamily extends AbstractHashFunctionFamily {
+ /**
+ * Constructor.
+ *
+ * @param random Random generator
+ * @param width Bin width
+ * @param k Number of projections to combine.
+ */
+ public ManhattanHashFunctionFamily(RandomFactory random, double width, int k) {
+ super(random, new CauchyRandomProjectionFamily(random), width, k);
+ }
+
+ @Override
+ public boolean isCompatible(DistanceFunction<?, ?> df) {
+ // TODO: also allow HistogramIntersectionDistance?
+ return ManhattanDistanceFunction.class.isInstance(df);
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractHashFunctionFamily.Parameterizer {
+ @Override
+ protected ManhattanHashFunctionFamily makeInstance() {
+ return new ManhattanHashFunctionFamily(random, width, k);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/package-info.java b/src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/package-info.java
new file mode 100644
index 00000000..5afa0489
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/package-info.java
@@ -0,0 +1,27 @@
+/**
+ * <p>Hash function families for LSH.</p>
+ */
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package de.lmu.ifi.dbs.elki.index.lsh.hashfamilies;
+
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/designpattern/Observer.java b/src/de/lmu/ifi/dbs/elki/index/lsh/hashfunctions/LocalitySensitiveHashFunction.java
index 6afec037..c43f60a5 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/designpattern/Observer.java
+++ b/src/de/lmu/ifi/dbs/elki/index/lsh/hashfunctions/LocalitySensitiveHashFunction.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.utilities.designpattern;
+package de.lmu.ifi.dbs.elki.index.lsh.hashfunctions;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,19 +23,19 @@ package de.lmu.ifi.dbs.elki.utilities.designpattern;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
/**
- * Simple Observer design pattern.
+ * Hash functions as used by locality sensitive hashing.
*
* @author Erich Schubert
*
- * @param T object type to observe
+ * @param <V> Data type to hash.
*/
-public interface Observer<T> {
+public interface LocalitySensitiveHashFunction<V> {
/**
- * This method is called when an observed object was updated.
+ * Compute the hash value of an object
*
- * @param o Observable
+ * @param obj Object to hash
+ * @return Hash value
*/
- public void update(T o);
-} \ No newline at end of file
+ int hashObject(V obj);
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/lsh/hashfunctions/MultipleProjectionsLocalitySensitiveHashFunction.java b/src/de/lmu/ifi/dbs/elki/index/lsh/hashfunctions/MultipleProjectionsLocalitySensitiveHashFunction.java
new file mode 100644
index 00000000..59f31b0a
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/lsh/hashfunctions/MultipleProjectionsLocalitySensitiveHashFunction.java
@@ -0,0 +1,119 @@
+package de.lmu.ifi.dbs.elki.index.lsh.hashfunctions;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import java.util.Random;
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.randomprojections.RandomProjectionFamily;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+
+/**
+ * LSH hash function for vector space data. Depending on the choice of random
+ * vectors, it can be appropriate for Manhattan and Euclidean distances.
+ *
+ * Reference:
+ * <p>
+ * Locality-sensitive hashing scheme based on p-stable distributions<br />
+ * M. Datar and N. Immorlica and P. Indyk and V. S. Mirrokni<br />
+ * Proc. 20th annual symposium on Computational geometry<br />
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@Reference(authors = "M. Datar and N. Immorlica and P. Indyk and V. S. Mirrokni", title = "Locality-sensitive hashing scheme based on p-stable distributions", booktitle = "Proc. 20th annual symposium on Computational geometry", url = "http://dx.doi.org/10.1145/997817.997857")
+public class MultipleProjectionsLocalitySensitiveHashFunction implements LocalitySensitiveHashFunction<NumberVector<?>> {
+ /**
+ * Projection matrix.
+ */
+ RandomProjectionFamily.Projection projection;
+
+ /**
+ * Shift offset.
+ */
+ double[] shift;
+
+ /**
+ * Scaling factor.
+ */
+ double width;
+
+ /**
+ * Random numbers for mixing the hash codes of the individual functions
+ */
+ int[] randoms1;
+
+ /**
+ * Constructor.
+ *
+ * @param projection Projection vectors
+ * @param width Width of bins
+ * @param rnd Random number generator
+ */
+ public MultipleProjectionsLocalitySensitiveHashFunction(RandomProjectionFamily.Projection projection, double width, Random rnd) {
+ super();
+ this.projection = projection;
+ this.width = width;
+ // Generate random shifts:
+ final int num = projection.getOutputDimensionality();
+ this.shift = new double[num];
+ this.randoms1 = new int[num];
+ for (int i = 0; i < num; i++) {
+ shift[i] = rnd.nextDouble() * width;
+ // Produce a large random number; although 7FFFFFFF would likely be large
+ // enough, we try to stick to the suggested approach (which assumes
+ // unsigned integers).
+ randoms1[i] = (rnd.nextInt(0x7FFFFFFD) << 1) + rnd.nextInt(1) + 1;
+ }
+ }
+
+ @Override
+ public int hashObject(NumberVector<?> vec) {
+ long t1sum = 0L;
+ // Project the vector:
+ final double[] proj = projection.project(vec);
+ for (int i = 0; i < shift.length; i++) {
+ int ai = (int) Math.floor((proj[i] + shift[i]) / width);
+ t1sum += randoms1[i] * (long) ai;
+ }
+ return fastModPrime(t1sum);
+ }
+
+ /**
+ * Fast modulo operation for the largest unsigned integer prime.
+ *
+ * @param data Long input
+ * @return {@code data % (2^32 - 5)}.
+ */
+ public static int fastModPrime(long data) {
+ // Mix high and low 32 bit:
+ int high = (int) (data >>> 32);
+ // Use fast multiplication with 5 for high:
+ int alpha = ((int) data) + (high << 2 + high);
+ // Note that in Java, PRIME will be negative.
+ if (alpha < 0 && alpha > -5) {
+ alpha = alpha + 5;
+ }
+ return alpha;
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/lsh/hashfunctions/package-info.java b/src/de/lmu/ifi/dbs/elki/index/lsh/hashfunctions/package-info.java
new file mode 100644
index 00000000..e30550f6
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/lsh/hashfunctions/package-info.java
@@ -0,0 +1,27 @@
+/**
+ * <p>Hash functions for LSH</p>
+ */
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package de.lmu.ifi.dbs.elki.index.lsh.hashfunctions;
+
diff --git a/src/de/lmu/ifi/dbs/elki/index/lsh/package-info.java b/src/de/lmu/ifi/dbs/elki/index/lsh/package-info.java
new file mode 100644
index 00000000..78eb59f7
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/lsh/package-info.java
@@ -0,0 +1,27 @@
+/**
+ * <p>Locality Sensitive Hashing</p>
+ */
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package de.lmu.ifi.dbs.elki.index.lsh;
+
diff --git a/src/de/lmu/ifi/dbs/elki/index/package-info.java b/src/de/lmu/ifi/dbs/elki/index/package-info.java
index 003a25bb..f985629d 100644
--- a/src/de/lmu/ifi/dbs/elki/index/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/index/package-info.java
@@ -8,7 +8,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/AbstractPreprocessorIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/AbstractPreprocessorIndex.java
index 95d0878d..720efc56 100644
--- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/AbstractPreprocessorIndex.java
+++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/AbstractPreprocessorIndex.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/LocalProjectionIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/LocalProjectionIndex.java
index 7373646f..0229c4e5 100644
--- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/LocalProjectionIndex.java
+++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/LocalProjectionIndex.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/AbstractMaterializeKNNPreprocessor.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/AbstractMaterializeKNNPreprocessor.java
index 7a64f294..570bd660 100644
--- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/AbstractMaterializeKNNPreprocessor.java
+++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/AbstractMaterializeKNNPreprocessor.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.knn;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,14 +28,13 @@ import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
import de.lmu.ifi.dbs.elki.database.datastore.WritableDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.PreprocessorKNNQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.index.IndexFactory;
import de.lmu.ifi.dbs.elki.index.KNNIndex;
@@ -56,7 +55,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
* @param <D> Distance type
* @param <T> Result type
*/
-public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D>, T extends KNNResult<D>> extends AbstractPreprocessorIndex<O, T> implements KNNIndex<O> {
+public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D>, T extends KNNList<D>> extends AbstractPreprocessorIndex<O, T> implements KNNIndex<O> {
/**
* The query k value.
*/
@@ -124,7 +123,7 @@ public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D
* @param id Object ID
* @return Neighbors
*/
- public KNNResult<D> get(DBIDRef id) {
+ public KNNList<D> get(DBIDRef id) {
if(storage == null) {
if(getLogger().isDebugging()) {
getLogger().debug("Running kNN preprocessor: " + this.getClass());
@@ -138,14 +137,14 @@ public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D
* Create the default storage.
*/
void createStorage() {
- WritableDataStore<T> s = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT, KNNResult.class);
+ WritableDataStore<T> s = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT, KNNList.class);
storage = s;
}
@Override
- public void insertAll(DBIDs ids) {
+ public void initialize() {
if(storage == null) {
- if(ids.size() > 0) {
+ if(relation.size() > 0) {
preprocess();
}
}
@@ -171,7 +170,7 @@ public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D
}
// To make compilers happy:
AbstractMaterializeKNNPreprocessor<?, ?, ?> tmp = this;
- return new PreprocessorKNNQuery<O, S, KNNResult<S>>(relation, (AbstractMaterializeKNNPreprocessor<O, S, KNNResult<S>>) tmp);
+ return new PreprocessorKNNQuery<>(relation, (AbstractMaterializeKNNPreprocessor<O, S, KNNList<S>>) tmp);
}
/**
@@ -186,7 +185,7 @@ public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D
* @param <O> The object type
* @param <D> The distance type
*/
- public abstract static class Factory<O, D extends Distance<D>, T extends KNNResult<D>> implements IndexFactory<O, KNNIndex<O>> {
+ public abstract static class Factory<O, D extends Distance<D>, T extends KNNList<D>> implements IndexFactory<O, KNNIndex<O>> {
/**
* Parameter to specify the number of nearest neighbors of an object to be
* materialized. must be an integer greater than 1.
@@ -287,7 +286,7 @@ public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D
}
// distance function
- final ObjectParameter<DistanceFunction<? super O, D>> distanceFunctionP = new ObjectParameter<DistanceFunction<? super O, D>>(DISTANCE_FUNCTION_ID, DistanceFunction.class, EuclideanDistanceFunction.class);
+ final ObjectParameter<DistanceFunction<? super O, D>> distanceFunctionP = new ObjectParameter<>(DISTANCE_FUNCTION_ID, DistanceFunction.class, EuclideanDistanceFunction.class);
if(config.grab(distanceFunctionP)) {
distanceFunction = distanceFunctionP.instantiateClass(config);
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/CachedDoubleDistanceKNNPreprocessor.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/CachedDoubleDistanceKNNPreprocessor.java
new file mode 100644
index 00000000..c36948be
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/CachedDoubleDistanceKNNPreprocessor.java
@@ -0,0 +1,205 @@
+package de.lmu.ifi.dbs.elki.index.preprocessed.knn;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileChannel.MapMode;
+import java.util.ArrayList;
+
+import de.lmu.ifi.dbs.elki.application.cache.CacheDoubleDistanceKNNLists;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNList;
+import de.lmu.ifi.dbs.elki.database.ids.generic.DoubleDistanceDBIDPairKNNList;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.persistent.ByteArrayUtil;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.FileParameter;
+
+/**
+ * Preprocessor that loads an existing cached kNN result.
+ *
+ * @author Erich Schubert
+ *
+ * @param <O> Object type
+ */
+public class CachedDoubleDistanceKNNPreprocessor<O> extends AbstractMaterializeKNNPreprocessor<O, DoubleDistance, DoubleDistanceKNNList> {
+ /**
+ * File to load.
+ */
+ private File filename;
+
+ /**
+ * Constructor.
+ *
+ * @param relation Relation to index
+ * @param distanceFunction Distance function
+ * @param k K
+ * @param file File to load
+ */
+ public CachedDoubleDistanceKNNPreprocessor(Relation<O> relation, DistanceFunction<? super O, DoubleDistance> distanceFunction, int k, File file) {
+ super(relation, distanceFunction, k);
+ this.filename = file;
+ }
+
+ /**
+ * Class logger.
+ */
+ private static final Logging LOG = Logging.getLogger(CachedDoubleDistanceKNNPreprocessor.class);
+
+ @Override
+ protected void preprocess() {
+ createStorage();
+ // open file.
+ try (RandomAccessFile file = new RandomAccessFile(filename, "rw");
+ FileChannel channel = file.getChannel()) {
+ // check magic header
+ int header = file.readInt();
+ if (header != CacheDoubleDistanceKNNLists.KNN_CACHE_MAGIC) {
+ throw new AbortException("Cache magic number does not match.");
+ }
+ MappedByteBuffer buffer = channel.map(MapMode.READ_ONLY, 4, file.length() - 4);
+ for (DBIDIter iter = relation.iterDBIDs(); iter.valid(); iter.advance()) {
+ int dbid = ByteArrayUtil.readUnsignedVarint(buffer);
+ int nnsize = ByteArrayUtil.readUnsignedVarint(buffer);
+ if (nnsize < k) {
+ throw new AbortException("kNN cache contains fewer than k objects!");
+ }
+ ArrayList<DoubleDistanceDBIDPair> col = new ArrayList<>(nnsize);
+ for (int i = 0; i < nnsize; i++) {
+ int nid = ByteArrayUtil.readUnsignedVarint(buffer);
+ double dist = buffer.getDouble();
+ col.add(DBIDUtil.newDistancePair(dist, DBIDUtil.importInteger(nid)));
+ }
+ storage.put(DBIDUtil.importInteger(dbid), new DoubleDistanceDBIDPairKNNList(col, nnsize));
+ }
+ if (buffer.hasRemaining()) {
+ LOG.warning("kNN cache has " + buffer.remaining() + " bytes remaining!");
+ }
+ } catch (IOException e) {
+ throw new AbortException("I/O error in loading kNN cache: " + e.getMessage(), e);
+ }
+ }
+
+ @Override
+ protected Logging getLogger() {
+ return LOG;
+ }
+
+ @Override
+ public String getLongName() {
+ return "cached-knn";
+ }
+
+ @Override
+ public String getShortName() {
+ return "cached-knn";
+ }
+
+ @Override
+ public void logStatistics() {
+ // No statistics to log.
+ }
+
+ /**
+ * The parameterizable factory.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.landmark
+ * @apiviz.stereotype factory
+ * @apiviz.uses MaterializeKNNPreprocessor oneway - - «create»
+ *
+ * @param <O> The object type
+ */
+ public static class Factory<O> extends AbstractMaterializeKNNPreprocessor.Factory<O, DoubleDistance, DoubleDistanceKNNList> {
+ /**
+ * Filename to load.
+ */
+ private File filename;
+
+ /**
+ * Index factory.
+ *
+ * @param k k parameter
+ * @param distanceFunction distance function
+ * @param filename Cache file
+ */
+ public Factory(int k, DistanceFunction<? super O, DoubleDistance> distanceFunction, File filename) {
+ super(k, distanceFunction);
+ this.filename = filename;
+ }
+
+ @Override
+ public CachedDoubleDistanceKNNPreprocessor<O> instantiate(Relation<O> relation) {
+ CachedDoubleDistanceKNNPreprocessor<O> instance = new CachedDoubleDistanceKNNPreprocessor<>(relation, distanceFunction, k, filename);
+ return instance;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer<O> extends AbstractMaterializeKNNPreprocessor.Factory.Parameterizer<O, DoubleDistance> {
+ /**
+ * Option ID for the kNN file.
+ */
+ public static final OptionID CACHE_ID = new OptionID("external.knnfile", "Filename with the precomputed k nearest neighbors.");
+
+ /**
+ * Filename to load.
+ */
+ private File filename;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+
+ // Input file parameter
+ final FileParameter cpar = new FileParameter(CACHE_ID, FileParameter.FileType.INPUT_FILE);
+ if (config.grab(cpar)) {
+ filename = cpar.getValue();
+ }
+ }
+
+ @Override
+ protected Factory<O> makeInstance() {
+ return new Factory<>(k, distanceFunction, filename);
+ }
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/KNNChangeEvent.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/KNNChangeEvent.java
index 6c677fda..275c1c97 100644
--- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/KNNChangeEvent.java
+++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/KNNChangeEvent.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.knn;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/KNNJoinMaterializeKNNPreprocessor.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/KNNJoinMaterializeKNNPreprocessor.java
index bb947348..44100604 100644
--- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/KNNJoinMaterializeKNNPreprocessor.java
+++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/KNNJoinMaterializeKNNPreprocessor.java
@@ -2,9 +2,9 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.knn;
import de.lmu.ifi.dbs.elki.algorithm.KNNJoin;
import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry;
import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rstar.RStarTreeNode;
@@ -14,7 +14,7 @@ import de.lmu.ifi.dbs.elki.logging.Logging;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -41,7 +41,7 @@ import de.lmu.ifi.dbs.elki.logging.Logging;
* @param <V> vector type
* @param <D> distance type
*/
-public class KNNJoinMaterializeKNNPreprocessor<V extends NumberVector<?>, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor<V, D, KNNResult<D>> {
+public class KNNJoinMaterializeKNNPreprocessor<V extends NumberVector<?>, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor<V, D, KNNList<D>> {
/**
* Logging class.
*/
@@ -80,6 +80,11 @@ public class KNNJoinMaterializeKNNPreprocessor<V extends NumberVector<?>, D exte
return "knn-join";
}
+ @Override
+ public void logStatistics() {
+ // No statistics to log.
+ }
+
/**
* The parameterizable factory.
*
@@ -92,7 +97,7 @@ public class KNNJoinMaterializeKNNPreprocessor<V extends NumberVector<?>, D exte
* @param <O> The object type
* @param <D> The distance type
*/
- public static class Factory<O extends NumberVector<?>, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor.Factory<O, D, KNNResult<D>> {
+ public static class Factory<O extends NumberVector<?>, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor.Factory<O, D, KNNList<D>> {
/**
* Constructor.
*
@@ -105,7 +110,7 @@ public class KNNJoinMaterializeKNNPreprocessor<V extends NumberVector<?>, D exte
@Override
public KNNJoinMaterializeKNNPreprocessor<O, D> instantiate(Relation<O> relation) {
- return new KNNJoinMaterializeKNNPreprocessor<O, D>(relation, distanceFunction, k);
+ return new KNNJoinMaterializeKNNPreprocessor<>(relation, distanceFunction, k);
}
/**
@@ -121,7 +126,7 @@ public class KNNJoinMaterializeKNNPreprocessor<V extends NumberVector<?>, D exte
public static class Parameterizer<O extends NumberVector<?>, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor.Factory.Parameterizer<O, D> {
@Override
protected KNNJoinMaterializeKNNPreprocessor.Factory<O, D> makeInstance() {
- return new KNNJoinMaterializeKNNPreprocessor.Factory<O, D>(k, distanceFunction);
+ return new KNNJoinMaterializeKNNPreprocessor.Factory<>(k, distanceFunction);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/KNNListener.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/KNNListener.java
index 4a726ad0..8c78cdc0 100644
--- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/KNNListener.java
+++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/KNNListener.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.knn;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/MaterializeKNNAndRKNNPreprocessor.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/MaterializeKNNAndRKNNPreprocessor.java
index b52b15af..06375d51 100644
--- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/MaterializeKNNAndRKNNPreprocessor.java
+++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/MaterializeKNNAndRKNNPreprocessor.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.knn;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -40,22 +40,21 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
-import de.lmu.ifi.dbs.elki.database.ids.DistanceDBIDPair;
-import de.lmu.ifi.dbs.elki.database.ids.DoubleDistanceDBIDPair;
import de.lmu.ifi.dbs.elki.database.ids.HashSetModifiableDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.SetDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNHeap;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
+import de.lmu.ifi.dbs.elki.database.ids.generic.GenericDistanceDBIDList;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.rknn.PreprocessorRKNNQuery;
import de.lmu.ifi.dbs.elki.database.query.rknn.RKNNQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.DistanceUtil;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultIter;
import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultUtil;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.GenericDistanceDBIDList;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNHeap;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNUtil;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.index.RKNNIndex;
import de.lmu.ifi.dbs.elki.logging.Logging;
@@ -119,20 +118,20 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends
*/
private void materializeKNNAndRKNNs(ArrayDBIDs ids, FiniteProgress progress) {
// add an empty list to each rknn
- Comparator<DistanceDBIDPair<D>> comp = DistanceDBIDResultUtil.distanceComparator();
+ Comparator<? super DistanceDBIDPair<D>> comp = DistanceDBIDResultUtil.distanceComparator();
for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
if(materialized_RkNN.get(iter) == null) {
- materialized_RkNN.put(iter, new TreeSet<DistanceDBIDPair<D>>(comp));
+ materialized_RkNN.put(iter, new TreeSet<>(comp));
}
}
// knn query
- List<? extends KNNResult<D>> kNNList = knnQuery.getKNNForBulkDBIDs(ids, k);
+ List<? extends KNNList<D>> kNNList = knnQuery.getKNNForBulkDBIDs(ids, k);
int i = 0;
for(DBIDIter id = ids.iter(); id.valid(); id.advance(), i++) {
- KNNResult<D> kNNs = kNNList.get(i);
+ KNNList<D> kNNs = kNNList.get(i);
storage.put(id, kNNs);
- for(DistanceDBIDResultIter<D> iter = kNNs.iter(); iter.valid(); iter.advance()) {
+ for(DistanceDBIDListIter<D> iter = kNNs.iter(); iter.valid(); iter.advance()) {
TreeSet<DistanceDBIDPair<D>> rknns = materialized_RkNN.get(iter);
rknns.add(makePair(iter, id));
}
@@ -147,7 +146,7 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends
}
@SuppressWarnings("unchecked")
- private DistanceDBIDPair<D> makePair(DistanceDBIDResultIter<D> iter, DBIDIter id) {
+ private DistanceDBIDPair<D> makePair(DistanceDBIDListIter<D> iter, DBIDIter id) {
if(doubleOptimize) {
return (DistanceDBIDPair<D>) DBIDUtil.newDistancePair(((DoubleDistanceDBIDPair) iter.getDistancePair()).doubleDistance(), id);
}
@@ -194,7 +193,7 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends
ArrayModifiableDBIDs rkNN_ids = DBIDUtil.newArray();
DBIDs oldids = DBIDUtil.difference(relation.getDBIDs(), ids);
for(DBIDIter id = oldids.iter(); id.valid(); id.advance()) {
- KNNResult<D> oldkNNs = storage.get(id);
+ KNNList<D> oldkNNs = storage.get(id);
D knnDist = oldkNNs.getKNNDistance();
// look for new kNNs
KNNHeap<D> heap = null;
@@ -203,21 +202,21 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends
if(dist.compareTo(knnDist) <= 0) {
// New id changes the kNNs of oldid.
if(heap == null) {
- heap = KNNUtil.newHeap(oldkNNs);
+ heap = DBIDUtil.newHeap(oldkNNs);
}
heap.add(dist, newid);
}
}
// kNNs for oldid have changed:
if(heap != null) {
- KNNResult<D> newkNNs = heap.toKNNList();
+ KNNList<D> newkNNs = heap.toKNNList();
storage.put(id, newkNNs);
// get the difference
int i = 0;
int j = 0;
- GenericDistanceDBIDList<D> added = new GenericDistanceDBIDList<D>();
- GenericDistanceDBIDList<D> removed = new GenericDistanceDBIDList<D>();
+ GenericDistanceDBIDList<D> added = new GenericDistanceDBIDList<>();
+ GenericDistanceDBIDList<D> removed = new GenericDistanceDBIDList<>();
// TODO: use iterators.
while(i < oldkNNs.size() && j < newkNNs.size()) {
DistanceDBIDPair<D> drp1 = oldkNNs.get(i);
@@ -241,12 +240,12 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends
}
}
// add new RkNN
- for(DistanceDBIDResultIter<D> newnn = added.iter(); newnn.valid(); newnn.advance()) {
+ for(DistanceDBIDListIter<D> newnn = added.iter(); newnn.valid(); newnn.advance()) {
TreeSet<DistanceDBIDPair<D>> rknns = materialized_RkNN.get(newnn);
rknns.add(makePair(newnn, id));
}
// remove old RkNN
- for(DistanceDBIDResultIter<D> oldnn = removed.iter(); oldnn.valid(); oldnn.advance()) {
+ for(DistanceDBIDListIter<D> oldnn = removed.iter(); oldnn.valid(); oldnn.advance()) {
TreeSet<DistanceDBIDPair<D>> rknns = materialized_RkNN.get(oldnn);
rknns.remove(makePair(oldnn, id));
}
@@ -267,8 +266,8 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends
stepprog.beginStep(1, "New deletions ocurred, remove their materialized kNNs and RkNNs.", getLogger());
}
// Temporary storage of removed lists
- List<KNNResult<D>> kNNs = new ArrayList<KNNResult<D>>(ids.size());
- List<TreeSet<DistanceDBIDPair<D>>> rkNNs = new ArrayList<TreeSet<DistanceDBIDPair<D>>>(ids.size());
+ List<KNNList<D>> kNNs = new ArrayList<>(ids.size());
+ List<TreeSet<DistanceDBIDPair<D>>> rkNNs = new ArrayList<>(ids.size());
for(DBIDIter iter = aids.iter(); iter.valid(); iter.advance()) {
kNNs.add(storage.get(iter));
storage.delete(iter);
@@ -285,11 +284,11 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends
}
// Recompute the kNN for affected objects (in rkNN lists)
{
- List<? extends KNNResult<D>> kNNList = knnQuery.getKNNForBulkDBIDs(rkNN_ids, k);
+ List<? extends KNNList<D>> kNNList = knnQuery.getKNNForBulkDBIDs(rkNN_ids, k);
int i = 0;
for(DBIDIter reknn = rkNN_ids.iter(); reknn.valid(); reknn.advance(), i++) {
storage.put(reknn, kNNList.get(i));
- for(DistanceDBIDResultIter<D> it = kNNList.get(i).iter(); it.valid(); it.advance()) {
+ for(DistanceDBIDListIter<D> it = kNNList.get(i).iter(); it.valid(); it.advance()) {
materialized_RkNN.get(it).add(makePair(it, reknn));
}
}
@@ -325,9 +324,9 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends
* @param remove the ids to remove
* @return the DBIDs in the given collection
*/
- protected ArrayDBIDs affectedkNN(List<? extends KNNResult<D>> extraxt, DBIDs remove) {
+ protected ArrayDBIDs affectedkNN(List<? extends KNNList<D>> extraxt, DBIDs remove) {
HashSetModifiableDBIDs ids = DBIDUtil.newHashSet();
- for(KNNResult<D> drps : extraxt) {
+ for(KNNList<D> drps : extraxt) {
for(DBIDIter iter = drps.iter(); iter.valid(); iter.advance()) {
ids.add(iter);
}
@@ -362,7 +361,7 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends
* @param id the query id
* @return the kNNs
*/
- public KNNResult<D> getKNN(DBID id) {
+ public KNNList<D> getKNN(DBID id) {
return storage.get(id);
}
@@ -377,7 +376,7 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends
if(rKNN == null) {
return null;
}
- GenericDistanceDBIDList<D> ret = new GenericDistanceDBIDList<D>(rKNN.size());
+ GenericDistanceDBIDList<D> ret = new GenericDistanceDBIDList<>(rKNN.size());
for(DistanceDBIDPair<D> pair : rKNN) {
ret.add(pair);
}
@@ -400,7 +399,7 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends
break;
}
}
- return new PreprocessorRKNNQuery<O, S>(relation, (MaterializeKNNAndRKNNPreprocessor<O, S>) this);
+ return new PreprocessorRKNNQuery<>(relation, (MaterializeKNNAndRKNNPreprocessor<O, S>) this);
}
@Override
@@ -439,7 +438,7 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends
@Override
public MaterializeKNNAndRKNNPreprocessor<O, D> instantiate(Relation<O> relation) {
- MaterializeKNNAndRKNNPreprocessor<O, D> instance = new MaterializeKNNAndRKNNPreprocessor<O, D>(relation, distanceFunction, k);
+ MaterializeKNNAndRKNNPreprocessor<O, D> instance = new MaterializeKNNAndRKNNPreprocessor<>(relation, distanceFunction, k);
return instance;
}
@@ -453,7 +452,7 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends
public static class Parameterizer<O, D extends Distance<D>> extends MaterializeKNNPreprocessor.Factory.Parameterizer<O, D> {
@Override
protected Factory<O, D> makeInstance() {
- return new Factory<O, D>(k, distanceFunction);
+ return new Factory<>(k, distanceFunction);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/MaterializeKNNPreprocessor.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/MaterializeKNNPreprocessor.java
index f792833e..3f79d748 100644
--- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/MaterializeKNNPreprocessor.java
+++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/MaterializeKNNPreprocessor.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.knn;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -34,17 +34,19 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.ids.SetDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNHeap;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNHeap;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNUtil;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.index.DynamicIndex;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
import de.lmu.ifi.dbs.elki.logging.progress.StepProgress;
+import de.lmu.ifi.dbs.elki.logging.statistics.Duration;
+import de.lmu.ifi.dbs.elki.logging.statistics.LongStatistic;
import de.lmu.ifi.dbs.elki.utilities.documentation.Description;
import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
@@ -52,7 +54,7 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
* A preprocessor for annotation of the k nearest neighbors (and their
* distances) to each database object.
*
- * Used for example by {@link de.lmu.ifi.dbs.elki.algorithm.outlier.LOF}.
+ * Used for example by {@link de.lmu.ifi.dbs.elki.algorithm.outlier.lof.LOF}.
*
* @author Erich Schubert
*
@@ -65,7 +67,7 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
*/
@Title("Materialize kNN Neighborhood preprocessor")
@Description("Materializes the k nearest neighbors of objects of a database.")
-public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor<O, D, KNNResult<D>> {
+public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor<O, D, KNNList<D>> implements DynamicIndex {
/**
* Logger to use.
*/
@@ -108,35 +110,44 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra
createStorage();
ArrayDBIDs ids = DBIDUtil.ensureArray(relation.getDBIDs());
- FiniteProgress progress = getLogger().isVerbose() ? new FiniteProgress("Materializing k nearest neighbors (k=" + k + ")", ids.size(), getLogger()) : null;
+ if (LOG.isStatistics()) {
+ LOG.statistics(new LongStatistic(this.getClass().getName() + ".k", k));
+ }
+ Duration duration = LOG.isStatistics() ? LOG.newDuration(this.getClass().getName() + ".precomputation-time") : null;
+ if (duration != null) {
+ duration.begin();
+ }
+ FiniteProgress progress = getLogger().isVerbose() ? new FiniteProgress("Materializing k nearest neighbors (k=" + k + ")", ids.size(), getLogger()) : null;
// Try bulk
- List<? extends KNNResult<D>> kNNList = null;
- if(usebulk) {
+ List<? extends KNNList<D>> kNNList = null;
+ if (usebulk) {
kNNList = knnQuery.getKNNForBulkDBIDs(ids, k);
- if(kNNList != null) {
+ if (kNNList != null) {
int i = 0;
- for(DBIDIter id = ids.iter(); id.valid(); id.advance(), i++) {
+ for (DBIDIter id = ids.iter(); id.valid(); id.advance(), i++) {
storage.put(id, kNNList.get(i));
- if(progress != null) {
+ if (progress != null) {
progress.incrementProcessed(getLogger());
}
}
}
- }
- else {
- for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
- KNNResult<D> knn = knnQuery.getKNNForDBID(iter, k);
+ } else {
+ for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
+ KNNList<D> knn = knnQuery.getKNNForDBID(iter, k);
storage.put(iter, knn);
- if(progress != null) {
+ if (progress != null) {
progress.incrementProcessed(getLogger());
}
}
}
-
- if(progress != null) {
+ if (progress != null) {
progress.ensureCompleted(getLogger());
}
+ if (duration != null) {
+ duration.end();
+ LOG.statistics(duration);
+ }
}
@Override
@@ -146,10 +157,9 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra
@Override
public void insertAll(DBIDs ids) {
- if(storage == null && ids.size() > 0) {
+ if (storage == null && ids.size() > 0) {
preprocess();
- }
- else {
+ } else {
objectsInserted(ids);
}
}
@@ -176,30 +186,30 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra
ArrayDBIDs aids = DBIDUtil.ensureArray(ids);
// materialize the new kNNs
- if(stepprog != null) {
+ if (stepprog != null) {
stepprog.beginStep(1, "New insertions ocurred, materialize their new kNNs.", getLogger());
}
// Bulk-query kNNs
- List<? extends KNNResult<D>> kNNList = knnQuery.getKNNForBulkDBIDs(aids, k);
+ List<? extends KNNList<D>> kNNList = knnQuery.getKNNForBulkDBIDs(aids, k);
// Store in storage
DBIDIter iter = aids.iter();
- for(int i = 0; i < aids.size(); i++, iter.advance()) {
+ for (int i = 0; i < aids.size(); i++, iter.advance()) {
storage.put(iter, kNNList.get(i));
}
// update the affected kNNs
- if(stepprog != null) {
+ if (stepprog != null) {
stepprog.beginStep(2, "New insertions ocurred, update the affected kNNs.", getLogger());
}
ArrayDBIDs rkNN_ids = updateKNNsAfterInsertion(ids);
// inform listener
- if(stepprog != null) {
+ if (stepprog != null) {
stepprog.beginStep(3, "New insertions ocurred, inform listeners.", getLogger());
}
fireKNNsInserted(ids, rkNN_ids);
- if(stepprog != null) {
+ if (stepprog != null) {
stepprog.setCompleted(getLogger());
}
}
@@ -215,21 +225,21 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra
private ArrayDBIDs updateKNNsAfterInsertion(DBIDs ids) {
ArrayModifiableDBIDs rkNN_ids = DBIDUtil.newArray();
DBIDs oldids = DBIDUtil.difference(relation.getDBIDs(), ids);
- for(DBIDIter iter = oldids.iter(); iter.valid(); iter.advance()) {
- KNNResult<D> kNNs = storage.get(iter);
+ for (DBIDIter iter = oldids.iter(); iter.valid(); iter.advance()) {
+ KNNList<D> kNNs = storage.get(iter);
D knnDist = kNNs.get(kNNs.size() - 1).getDistance();
// look for new kNNs
KNNHeap<D> heap = null;
- for(DBIDIter iter2 = ids.iter(); iter2.valid(); iter2.advance()) {
+ for (DBIDIter iter2 = ids.iter(); iter2.valid(); iter2.advance()) {
D dist = distanceQuery.distance(iter, iter2);
- if(dist.compareTo(knnDist) <= 0) {
- if(heap == null) {
- heap = KNNUtil.newHeap(kNNs);
+ if (dist.compareTo(knnDist) <= 0) {
+ if (heap == null) {
+ heap = DBIDUtil.newHeap(kNNs);
}
heap.add(dist, iter2);
}
}
- if(heap != null) {
+ if (heap != null) {
kNNs = heap.toKNNList();
storage.put(iter, kNNs);
rkNN_ids.add(iter);
@@ -248,10 +258,10 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra
private ArrayDBIDs updateKNNsAfterDeletion(DBIDs ids) {
SetDBIDs idsSet = DBIDUtil.ensureSet(ids);
ArrayModifiableDBIDs rkNN_ids = DBIDUtil.newArray();
- for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
- KNNResult<D> kNNs = storage.get(iditer);
- for(DBIDIter it = kNNs.iter(); it.valid(); it.advance()) {
- if(idsSet.contains(it)) {
+ for (DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
+ KNNList<D> kNNs = storage.get(iditer);
+ for (DBIDIter it = kNNs.iter(); it.valid(); it.advance()) {
+ if (idsSet.contains(it)) {
rkNN_ids.add(iditer);
break;
}
@@ -259,9 +269,9 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra
}
// update the kNNs of the RkNNs
- List<? extends KNNResult<D>> kNNList = knnQuery.getKNNForBulkDBIDs(rkNN_ids, k);
+ List<? extends KNNList<D>> kNNList = knnQuery.getKNNForBulkDBIDs(rkNN_ids, k);
DBIDIter iter = rkNN_ids.iter();
- for(int i = 0; i < rkNN_ids.size(); i++, iter.advance()) {
+ for (int i = 0; i < rkNN_ids.size(); i++, iter.advance()) {
storage.put(iter, kNNList.get(i));
}
@@ -278,26 +288,26 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra
StepProgress stepprog = getLogger().isVerbose() ? new StepProgress(3) : null;
// delete the materialized (old) kNNs
- if(stepprog != null) {
+ if (stepprog != null) {
stepprog.beginStep(1, "New deletions ocurred, remove their materialized kNNs.", getLogger());
}
- for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
+ for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
storage.delete(iter);
}
// update the affected kNNs
- if(stepprog != null) {
+ if (stepprog != null) {
stepprog.beginStep(2, "New deletions ocurred, update the affected kNNs.", getLogger());
}
ArrayDBIDs rkNN_ids = updateKNNsAfterDeletion(ids);
// inform listener
- if(stepprog != null) {
+ if (stepprog != null) {
stepprog.beginStep(3, "New deletions ocurred, inform listeners.", getLogger());
}
fireKNNsRemoved(ids, rkNN_ids);
- if(stepprog != null) {
+ if (stepprog != null) {
stepprog.ensureCompleted(getLogger());
}
}
@@ -314,8 +324,8 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra
protected void fireKNNsInserted(DBIDs insertions, DBIDs updates) {
KNNChangeEvent e = new KNNChangeEvent(this, KNNChangeEvent.Type.INSERT, insertions, updates);
Object[] listeners = listenerList.getListenerList();
- for(int i = listeners.length - 2; i >= 0; i -= 2) {
- if(listeners[i] == KNNListener.class) {
+ for (int i = listeners.length - 2; i >= 0; i -= 2) {
+ if (listeners[i] == KNNListener.class) {
((KNNListener) listeners[i + 1]).kNNsChanged(e);
}
}
@@ -332,8 +342,8 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra
protected void fireKNNsRemoved(DBIDs removals, DBIDs updates) {
KNNChangeEvent e = new KNNChangeEvent(this, KNNChangeEvent.Type.DELETE, removals, updates);
Object[] listeners = listenerList.getListenerList();
- for(int i = listeners.length - 2; i >= 0; i -= 2) {
- if(listeners[i] == KNNListener.class) {
+ for (int i = listeners.length - 2; i >= 0; i -= 2) {
+ if (listeners[i] == KNNListener.class) {
((KNNListener) listeners[i + 1]).kNNsChanged(e);
}
}
@@ -374,6 +384,11 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra
}
@Override
+ public void logStatistics() {
+ // TODO: can we log some sensible statistics?
+ }
+
+ @Override
protected Logging getLogger() {
return LOG;
}
@@ -390,7 +405,7 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra
* @param <O> The object type
* @param <D> The distance type
*/
- public static class Factory<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor.Factory<O, D, KNNResult<D>> {
+ public static class Factory<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor.Factory<O, D, KNNList<D>> {
/**
* Index factory.
*
@@ -403,7 +418,7 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra
@Override
public MaterializeKNNPreprocessor<O, D> instantiate(Relation<O> relation) {
- MaterializeKNNPreprocessor<O, D> instance = new MaterializeKNNPreprocessor<O, D>(relation, distanceFunction, k);
+ MaterializeKNNPreprocessor<O, D> instance = new MaterializeKNNPreprocessor<>(relation, distanceFunction, k);
return instance;
}
@@ -417,8 +432,8 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra
public static class Parameterizer<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor.Factory.Parameterizer<O, D> {
@Override
protected Factory<O, D> makeInstance() {
- return new Factory<O, D>(k, distanceFunction);
+ return new Factory<>(k, distanceFunction);
}
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/MetricalIndexApproximationMaterializeKNNPreprocessor.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/MetricalIndexApproximationMaterializeKNNPreprocessor.java
index b82e9c77..1f17e6b4 100644
--- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/MetricalIndexApproximationMaterializeKNNPreprocessor.java
+++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/MetricalIndexApproximationMaterializeKNNPreprocessor.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.knn;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -32,12 +32,11 @@ import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDPair;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNHeap;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNHeap;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNUtil;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.index.tree.LeafEntry;
import de.lmu.ifi.dbs.elki.index.tree.Node;
@@ -55,7 +54,7 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
* A preprocessor for annotation of the k nearest neighbors (and their
* distances) to each database object.
*
- * Used for example by {@link de.lmu.ifi.dbs.elki.algorithm.outlier.LOF}.
+ * Used for example by {@link de.lmu.ifi.dbs.elki.algorithm.outlier.lof.LOF}.
*
* TODO correct handling of datastore events
*
@@ -70,7 +69,7 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
*/
@Title("Spatial Approximation Materialize kNN Preprocessor")
@Description("Caterializes the (approximate) k nearest neighbors of objects of a database using a spatial approximation.")
-public class MetricalIndexApproximationMaterializeKNNPreprocessor<O extends NumberVector<?>, D extends Distance<D>, N extends Node<E>, E extends MTreeEntry<D>> extends AbstractMaterializeKNNPreprocessor<O, D, KNNResult<D>> {
+public class MetricalIndexApproximationMaterializeKNNPreprocessor<O extends NumberVector<?>, D extends Distance<D>, N extends Node<E>, E extends MTreeEntry> extends AbstractMaterializeKNNPreprocessor<O, D, KNNList<D>> {
/**
* Logger to use
*/
@@ -114,9 +113,9 @@ public class MetricalIndexApproximationMaterializeKNNPreprocessor<O extends Numb
for(int i = 0; i < size; i++) {
ids.add(((LeafEntry) node.getEntry(i)).getDBID());
}
- HashMap<DBIDPair, D> cache = new HashMap<DBIDPair, D>((size * size * 3) >> 2);
+ HashMap<DBIDPair, D> cache = new HashMap<>((size * size * 3) >> 2);
for(DBIDIter id = ids.iter(); id.valid(); id.advance()) {
- KNNHeap<D> kNN = KNNUtil.newHeap(distanceFunction, k);
+ KNNHeap<D> kNN = DBIDUtil.newHeap(distanceFunction.getDistanceFactory(), k);
for(DBIDIter id2 = ids.iter(); id2.valid(); id2.advance()) {
DBIDPair key = DBIDUtil.newPair(id, id2);
D d = cache.remove(key);
@@ -190,6 +189,11 @@ public class MetricalIndexApproximationMaterializeKNNPreprocessor<O extends Numb
return LOG;
}
+ @Override
+ public void logStatistics() {
+ // No statistics to log.
+ }
+
/**
* The parameterizable factory.
*
@@ -204,7 +208,7 @@ public class MetricalIndexApproximationMaterializeKNNPreprocessor<O extends Numb
* @param <N> the type of spatial nodes in the spatial index
* @param <E> the type of spatial entries in the spatial index
*/
- public static class Factory<O extends NumberVector<?>, D extends Distance<D>, N extends Node<E>, E extends MTreeEntry<D>> extends AbstractMaterializeKNNPreprocessor.Factory<O, D, KNNResult<D>> {
+ public static class Factory<O extends NumberVector<?>, D extends Distance<D>, N extends Node<E>, E extends MTreeEntry> extends AbstractMaterializeKNNPreprocessor.Factory<O, D, KNNList<D>> {
/**
* Constructor.
*
@@ -217,7 +221,7 @@ public class MetricalIndexApproximationMaterializeKNNPreprocessor<O extends Numb
@Override
public MetricalIndexApproximationMaterializeKNNPreprocessor<O, D, N, E> instantiate(Relation<O> relation) {
- MetricalIndexApproximationMaterializeKNNPreprocessor<O, D, N, E> instance = new MetricalIndexApproximationMaterializeKNNPreprocessor<O, D, N, E>(relation, distanceFunction, k);
+ MetricalIndexApproximationMaterializeKNNPreprocessor<O, D, N, E> instance = new MetricalIndexApproximationMaterializeKNNPreprocessor<>(relation, distanceFunction, k);
return instance;
}
@@ -228,10 +232,10 @@ public class MetricalIndexApproximationMaterializeKNNPreprocessor<O extends Numb
*
* @apiviz.exclude
*/
- public static class Parameterizer<O extends NumberVector<?>, D extends Distance<D>, N extends Node<E>, E extends MTreeEntry<D>> extends AbstractMaterializeKNNPreprocessor.Factory.Parameterizer<O, D> {
+ public static class Parameterizer<O extends NumberVector<?>, D extends Distance<D>, N extends Node<E>, E extends MTreeEntry> extends AbstractMaterializeKNNPreprocessor.Factory.Parameterizer<O, D> {
@Override
protected Factory<O, D, N, E> makeInstance() {
- return new Factory<O, D, N, E>(k, distanceFunction);
+ return new Factory<>(k, distanceFunction);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/PartitionApproximationMaterializeKNNPreprocessor.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/PartitionApproximationMaterializeKNNPreprocessor.java
index 353e227d..1d2a2a1b 100644
--- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/PartitionApproximationMaterializeKNNPreprocessor.java
+++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/PartitionApproximationMaterializeKNNPreprocessor.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.knn;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -32,12 +32,11 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDArrayIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDPair;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNHeap;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNHeap;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNUtil;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
@@ -55,7 +54,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.RandomParameter;
* A preprocessor for annotation of the k nearest neighbors (and their
* distances) to each database object.
*
- * Used for example by {@link de.lmu.ifi.dbs.elki.algorithm.outlier.LOF}.
+ * Used for example by {@link de.lmu.ifi.dbs.elki.algorithm.outlier.lof.LOF}.
*
* @author Erich Schubert
*
@@ -64,7 +63,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.RandomParameter;
*/
@Title("Partitioning Approximate kNN Preprocessor")
@Description("Caterializes the (approximate) k nearest neighbors of objects of a database by partitioning and only computing kNN within each partition.")
-public class PartitionApproximationMaterializeKNNPreprocessor<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor<O, D, KNNResult<D>> {
+public class PartitionApproximationMaterializeKNNPreprocessor<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor<O, D, KNNList<D>> {
/**
* Logger to use
*/
@@ -98,7 +97,7 @@ public class PartitionApproximationMaterializeKNNPreprocessor<O, D extends Dista
@Override
protected void preprocess() {
DistanceQuery<O, D> distanceQuery = relation.getDatabase().getDistanceQuery(relation, distanceFunction);
- storage = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, KNNResult.class);
+ storage = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, KNNList.class);
MeanVariance ksize = new MeanVariance();
if (LOG.isVerbose()) {
LOG.verbose("Approximating nearest neighbor lists to database objects");
@@ -126,9 +125,9 @@ public class PartitionApproximationMaterializeKNNPreprocessor<O, D extends Dista
ids.add(iter);
}
}
- HashMap<DBIDPair, D> cache = new HashMap<DBIDPair, D>((size * size * 3) >> 3);
+ HashMap<DBIDPair, D> cache = new HashMap<>((size * size * 3) >> 3);
for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
- KNNHeap<D> kNN = KNNUtil.newHeap(distanceFunction, k);
+ KNNHeap<D> kNN = DBIDUtil.newHeap(distanceFunction.getDistanceFactory(), k);
for (DBIDIter iter2 = ids.iter(); iter2.valid(); iter2.advance()) {
DBIDPair key = DBIDUtil.newPair(iter, iter2);
D d = cache.remove(key);
@@ -179,6 +178,11 @@ public class PartitionApproximationMaterializeKNNPreprocessor<O, D extends Dista
return "random-partition-knn";
}
+ @Override
+ public void logStatistics() {
+ // No statistics to log.
+ }
+
/**
* The parameterizable factory.
*
@@ -191,7 +195,7 @@ public class PartitionApproximationMaterializeKNNPreprocessor<O, D extends Dista
* @param <O> The object type
* @param <D> The distance type
*/
- public static class Factory<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor.Factory<O, D, KNNResult<D>> {
+ public static class Factory<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor.Factory<O, D, KNNList<D>> {
/**
* The number of partitions to use
*/
@@ -218,7 +222,7 @@ public class PartitionApproximationMaterializeKNNPreprocessor<O, D extends Dista
@Override
public PartitionApproximationMaterializeKNNPreprocessor<O, D> instantiate(Relation<O> relation) {
- PartitionApproximationMaterializeKNNPreprocessor<O, D> instance = new PartitionApproximationMaterializeKNNPreprocessor<O, D>(relation, distanceFunction, k, partitions, rnd);
+ PartitionApproximationMaterializeKNNPreprocessor<O, D> instance = new PartitionApproximationMaterializeKNNPreprocessor<>(relation, distanceFunction, k, partitions, rnd);
return instance;
}
@@ -273,7 +277,7 @@ public class PartitionApproximationMaterializeKNNPreprocessor<O, D extends Dista
@Override
protected Factory<O, D> makeInstance() {
- return new Factory<O, D>(k, distanceFunction, partitions, rnd);
+ return new Factory<>(k, distanceFunction, partitions, rnd);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/RandomSampleKNNPreprocessor.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/RandomSampleKNNPreprocessor.java
index 592a1206..cb3f1638 100644
--- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/RandomSampleKNNPreprocessor.java
+++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/RandomSampleKNNPreprocessor.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.knn;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,16 +29,16 @@ import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNHeap;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNHeap;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNUtil;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
import de.lmu.ifi.dbs.elki.utilities.RandomFactory;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.LessConstraint;
@@ -49,12 +49,22 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.RandomParameter;
/**
* Class that computed the kNN only on a random sample.
*
+ * Used in:
+ * <p>
+ * Subsampling for Efficient and Effective Unsupervised Outlier Detection
+ * Ensembles<br />
+ * A. Zimek and M. Gaudet and R. J. G. B. Campello and J. Sander<br />
+ * In: Proc. 19th ACM SIGKDD International Conference on Knowledge Discovery and
+ * Data Mining, KDD '13
+ * </p>
+ *
* @author Erich Schubert
*
* @param <O> Object type
* @param <D> Distance type
*/
-public class RandomSampleKNNPreprocessor<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor<O, D, KNNResult<D>> {
+@Reference(title = "Subsampling for Efficient and Effective Unsupervised Outlier Detection Ensembles", authors = "A. Zimek and M. Gaudet and R. J. G. B. Campello and J. Sander", booktitle = "Proc. 19th ACM SIGKDD International Conference on Knowledge Discovery and Data Mining, KDD '13")
+public class RandomSampleKNNPreprocessor<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor<O, D, KNNList<D>> {
/**
* Logger
*/
@@ -88,14 +98,14 @@ public class RandomSampleKNNPreprocessor<O, D extends Distance<D>> extends Abstr
@Override
protected void preprocess() {
DistanceQuery<O, D> distanceQuery = relation.getDatabase().getDistanceQuery(relation, distanceFunction);
- storage = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, KNNResult.class);
+ storage = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, KNNList.class);
FiniteProgress progress = getLogger().isVerbose() ? new FiniteProgress("Materializing random-sample k nearest neighbors (k=" + k + ")", relation.size(), getLogger()) : null;
final ArrayDBIDs ids = DBIDUtil.ensureArray(relation.getDBIDs());
final int samplesize = (int) (ids.size() * share);
for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
- KNNHeap<D> kNN = KNNUtil.newHeap(distanceFunction, k);
+ KNNHeap<D> kNN = DBIDUtil.newHeap(distanceFunction.getDistanceFactory(), k);
DBIDs rsamp = DBIDUtil.randomSample(ids, samplesize, rnd);
for (DBIDIter iter2 = rsamp.iter(); iter2.valid(); iter2.advance()) {
@@ -129,6 +139,11 @@ public class RandomSampleKNNPreprocessor<O, D extends Distance<D>> extends Abstr
return "random-sample-knn";
}
+ @Override
+ public void logStatistics() {
+ // No statistics to log.
+ }
+
/**
* The parameterizable factory.
*
@@ -141,7 +156,7 @@ public class RandomSampleKNNPreprocessor<O, D extends Distance<D>> extends Abstr
* @param <O> The object type
* @param <D> The distance type
*/
- public static class Factory<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor.Factory<O, D, KNNResult<D>> {
+ public static class Factory<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor.Factory<O, D, KNNList<D>> {
/**
* Relative share of objects to get
*/
@@ -168,7 +183,7 @@ public class RandomSampleKNNPreprocessor<O, D extends Distance<D>> extends Abstr
@Override
public RandomSampleKNNPreprocessor<O, D> instantiate(Relation<O> relation) {
- return new RandomSampleKNNPreprocessor<O, D>(relation, distanceFunction, k, share, rnd);
+ return new RandomSampleKNNPreprocessor<>(relation, distanceFunction, k, share, rnd);
}
/**
@@ -228,7 +243,7 @@ public class RandomSampleKNNPreprocessor<O, D extends Distance<D>> extends Abstr
@Override
protected RandomSampleKNNPreprocessor.Factory<O, D> makeInstance() {
- return new RandomSampleKNNPreprocessor.Factory<O, D>(k, distanceFunction, share, rnd);
+ return new RandomSampleKNNPreprocessor.Factory<>(k, distanceFunction, share, rnd);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/SpatialApproximationMaterializeKNNPreprocessor.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/SpatialApproximationMaterializeKNNPreprocessor.java
index c7963e14..739dcc7c 100644
--- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/SpatialApproximationMaterializeKNNPreprocessor.java
+++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/SpatialApproximationMaterializeKNNPreprocessor.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.knn;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -34,12 +34,11 @@ import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDPair;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNHeap;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNHeap;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNUtil;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.index.tree.LeafEntry;
import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry;
@@ -57,7 +56,7 @@ import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
* A preprocessor for annotation of the k nearest neighbors (and their
* distances) to each database object.
*
- * Used for example by {@link de.lmu.ifi.dbs.elki.algorithm.outlier.LOF}.
+ * Used for example by {@link de.lmu.ifi.dbs.elki.algorithm.outlier.lof.LOF}.
*
* TODO correct handling of datastore events
*
@@ -71,7 +70,7 @@ import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
*/
@Title("Spatial Approximation Materialize kNN Preprocessor")
@Description("Caterializes the (approximate) k nearest neighbors of objects of a database using a spatial approximation.")
-public class SpatialApproximationMaterializeKNNPreprocessor<O extends NumberVector<?>, D extends Distance<D>, N extends SpatialNode<N, E>, E extends SpatialEntry> extends AbstractMaterializeKNNPreprocessor<O, D, KNNResult<D>> {
+public class SpatialApproximationMaterializeKNNPreprocessor<O extends NumberVector<?>, D extends Distance<D>, N extends SpatialNode<N, E>, E extends SpatialEntry> extends AbstractMaterializeKNNPreprocessor<O, D, KNNList<D>> {
/**
* Logger to use
*/
@@ -98,7 +97,7 @@ public class SpatialApproximationMaterializeKNNPreprocessor<O extends NumberVect
}
SpatialIndexTree<N, E> index = indexes.iterator().next();
- storage = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, KNNResult.class);
+ storage = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, KNNList.class);
MeanVariance pagesize = new MeanVariance();
MeanVariance ksize = new MeanVariance();
if(getLogger().isVerbose()) {
@@ -119,9 +118,9 @@ public class SpatialApproximationMaterializeKNNPreprocessor<O extends NumberVect
for(int i = 0; i < size; i++) {
ids.add(((LeafEntry) node.getEntry(i)).getDBID());
}
- HashMap<DBIDPair, D> cache = new HashMap<DBIDPair, D>((size * size * 3) >> 3);
+ HashMap<DBIDPair, D> cache = new HashMap<>((size * size * 3) >> 3);
for(DBIDIter id = ids.iter(); id.valid(); id.advance()) {
- KNNHeap<D> kNN = KNNUtil.newHeap(distanceFunction, k);
+ KNNHeap<D> kNN = DBIDUtil.newHeap(distanceFunction.getDistanceFactory(), k);
for(DBIDIter id2 = ids.iter(); id2.valid(); id2.advance()) {
DBIDPair key = DBIDUtil.newPair(id, id2);
D d = cache.remove(key);
@@ -174,6 +173,11 @@ public class SpatialApproximationMaterializeKNNPreprocessor<O extends NumberVect
return "spatial-approximate-knn";
}
+ @Override
+ public void logStatistics() {
+ // No statistics to log.
+ }
+
/**
* The actual preprocessor instance.
*
@@ -187,7 +191,7 @@ public class SpatialApproximationMaterializeKNNPreprocessor<O extends NumberVect
* @param <N> the type of spatial nodes in the spatial index
* @param <E> the type of spatial entries in the spatial index
*/
- public static class Factory<D extends Distance<D>, N extends SpatialNode<N, E>, E extends SpatialEntry> extends AbstractMaterializeKNNPreprocessor.Factory<NumberVector<?>, D, KNNResult<D>> {
+ public static class Factory<D extends Distance<D>, N extends SpatialNode<N, E>, E extends SpatialEntry> extends AbstractMaterializeKNNPreprocessor.Factory<NumberVector<?>, D, KNNList<D>> {
/**
* Constructor.
*
@@ -200,7 +204,7 @@ public class SpatialApproximationMaterializeKNNPreprocessor<O extends NumberVect
@Override
public SpatialApproximationMaterializeKNNPreprocessor<NumberVector<?>, D, N, E> instantiate(Relation<NumberVector<?>> relation) {
- SpatialApproximationMaterializeKNNPreprocessor<NumberVector<?>, D, N, E> instance = new SpatialApproximationMaterializeKNNPreprocessor<NumberVector<?>, D, N, E>(relation, distanceFunction, k);
+ SpatialApproximationMaterializeKNNPreprocessor<NumberVector<?>, D, N, E> instance = new SpatialApproximationMaterializeKNNPreprocessor<>(relation, distanceFunction, k);
return instance;
}
@@ -214,7 +218,7 @@ public class SpatialApproximationMaterializeKNNPreprocessor<O extends NumberVect
public static class Parameterizer<D extends Distance<D>, N extends SpatialNode<N, E>, E extends SpatialEntry> extends AbstractMaterializeKNNPreprocessor.Factory.Parameterizer<NumberVector<?>, D> {
@Override
protected Factory<D, N, E> makeInstance() {
- return new Factory<D, N, E>(k, distanceFunction);
+ return new Factory<>(k, distanceFunction);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/package-info.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/package-info.java
index 1780cdc0..47339bb4 100644
--- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/AbstractFilteredPCAIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/AbstractFilteredPCAIndex.java
index 371dbca6..67a2effc 100644
--- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/AbstractFilteredPCAIndex.java
+++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/AbstractFilteredPCAIndex.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.localpca;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,10 +29,10 @@ import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.index.preprocessed.AbstractPreprocessorIndex;
import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
@@ -78,10 +78,8 @@ public abstract class AbstractFilteredPCAIndex<NV extends NumberVector<?>> exten
this.pca = pca;
}
- /**
- * Preprocessing step.
- */
- protected void preprocess() {
+ @Override
+ public void initialize() {
if(relation == null || relation.size() <= 0) {
throw new IllegalArgumentException(ExceptionMessages.DATABASE_EMPTY);
}
@@ -99,7 +97,7 @@ public abstract class AbstractFilteredPCAIndex<NV extends NumberVector<?>> exten
// TODO: use a bulk operation?
for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
- DistanceDBIDResult<DoubleDistance> objects = objectsForPCA(iditer);
+ DistanceDBIDList<DoubleDistance> objects = objectsForPCA(iditer);
PCAFilteredResult pcares = pca.processQueryResult(objects, relation);
@@ -123,7 +121,7 @@ public abstract class AbstractFilteredPCAIndex<NV extends NumberVector<?>> exten
@Override
public PCAFilteredResult getLocalProjection(DBIDRef objid) {
if(storage == null) {
- preprocess();
+ initialize();
}
return storage.get(objid);
}
@@ -136,7 +134,7 @@ public abstract class AbstractFilteredPCAIndex<NV extends NumberVector<?>> exten
* @return the list of the objects (i.e. the ids and the distances to the
* query object) to be considered within the PCA
*/
- protected abstract DistanceDBIDResult<DoubleDistance> objectsForPCA(DBIDRef id);
+ protected abstract DistanceDBIDList<DoubleDistance> objectsForPCA(DBIDRef id);
/**
* Factory class.
@@ -207,7 +205,7 @@ public abstract class AbstractFilteredPCAIndex<NV extends NumberVector<?>> exten
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- final ObjectParameter<DistanceFunction<NV, DoubleDistance>> pcaDistanceFunctionP = new ObjectParameter<DistanceFunction<NV, DoubleDistance>>(PCA_DISTANCE_ID, DistanceFunction.class, EuclideanDistanceFunction.class);
+ final ObjectParameter<DistanceFunction<NV, DoubleDistance>> pcaDistanceFunctionP = new ObjectParameter<>(PCA_DISTANCE_ID, DistanceFunction.class, EuclideanDistanceFunction.class);
if(config.grab(pcaDistanceFunctionP)) {
pcaDistanceFunction = pcaDistanceFunctionP.instantiateClass(config);
diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/FilteredLocalPCAIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/FilteredLocalPCAIndex.java
index d0780751..2d64cbc0 100644
--- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/FilteredLocalPCAIndex.java
+++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/FilteredLocalPCAIndex.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.localpca;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/KNNQueryFilteredPCAIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/KNNQueryFilteredPCAIndex.java
index 00ce11b8..e6320833 100644
--- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/KNNQueryFilteredPCAIndex.java
+++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/KNNQueryFilteredPCAIndex.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.localpca;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,10 +26,11 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.localpca;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.database.QueryUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.database.relation.RelationUtil;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.math.linearalgebra.pca.PCAFilteredRunner;
@@ -74,19 +75,24 @@ public class KNNQueryFilteredPCAIndex<NV extends NumberVector<?>> extends Abstra
/**
* Constructor.
*
- * @param database Database to use
+ * @param relation Database to use
* @param pca PCA Runner to use
* @param knnQuery KNN Query to use
* @param k k value
*/
- public KNNQueryFilteredPCAIndex(Relation<NV> database, PCAFilteredRunner<NV> pca, KNNQuery<NV, DoubleDistance> knnQuery, int k) {
- super(database, pca);
+ public KNNQueryFilteredPCAIndex(Relation<NV> relation, PCAFilteredRunner<NV> pca, KNNQuery<NV, DoubleDistance> knnQuery, int k) {
+ super(relation, pca);
this.knnQuery = knnQuery;
this.k = k;
+ // Sanity check:
+ int dim = RelationUtil.dimensionality(relation);
+ if (dim > 0 && k <= dim) {
+ LOG.warning("PCA results with k < dim are meaningless. Choose k much larger than the dimensionality.");
+ }
}
@Override
- protected KNNResult<DoubleDistance> objectsForPCA(DBIDRef id) {
+ protected KNNList<DoubleDistance> objectsForPCA(DBIDRef id) {
return knnQuery.getKNNForDBID(id, k);
}
@@ -105,6 +111,11 @@ public class KNNQueryFilteredPCAIndex<NV extends NumberVector<?>> extends Abstra
return LOG;
}
+ @Override
+ public void logStatistics() {
+ // No statistics to log.
+ }
+
/**
* Factory class.
*
@@ -150,7 +161,7 @@ public class KNNQueryFilteredPCAIndex<NV extends NumberVector<?>> extends Abstra
public KNNQueryFilteredPCAIndex<V> instantiate(Relation<V> relation) {
// TODO: set bulk flag, once the parent class supports bulk.
KNNQuery<V, DoubleDistance> knnquery = QueryUtil.getKNNQuery(relation, pcaDistanceFunction, k);
- return new KNNQueryFilteredPCAIndex<V>(relation, pca, knnquery, k);
+ return new KNNQueryFilteredPCAIndex<>(relation, pca, knnquery, k);
}
/**
@@ -168,16 +179,15 @@ public class KNNQueryFilteredPCAIndex<NV extends NumberVector<?>> extends Abstra
super.makeOptions(config);
final IntParameter kP = new IntParameter(K_ID);
kP.addConstraint(new GreaterConstraint(0));
- kP.setOptional(true);
- if(config.grab(kP)) {
+ if (config.grab(kP)) {
k = kP.getValue();
}
}
@Override
protected Factory<NV> makeInstance() {
- return new Factory<NV>(pcaDistanceFunction, pca, k);
+ return new Factory<>(pcaDistanceFunction, pca, k);
}
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/RangeQueryFilteredPCAIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/RangeQueryFilteredPCAIndex.java
index bbc00c64..03b49df3 100644
--- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/RangeQueryFilteredPCAIndex.java
+++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/RangeQueryFilteredPCAIndex.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.localpca;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,10 +26,10 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.localpca;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.database.QueryUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.math.linearalgebra.pca.PCAFilteredRunner;
@@ -84,7 +84,7 @@ public class RangeQueryFilteredPCAIndex<NV extends NumberVector<?>> extends Abst
}
@Override
- protected DistanceDBIDResult<DoubleDistance> objectsForPCA(DBIDRef id) {
+ protected DistanceDBIDList<DoubleDistance> objectsForPCA(DBIDRef id) {
return rangeQuery.getRangeForDBID(id, epsilon);
}
@@ -99,10 +99,15 @@ public class RangeQueryFilteredPCAIndex<NV extends NumberVector<?>> extends Abst
}
@Override
- public Logging getLogger() {
+ protected Logging getLogger() {
return LOG;
}
+ @Override
+ public void logStatistics() {
+ // No statistics to log.
+ }
+
/**
* Factory class.
*
@@ -142,7 +147,7 @@ public class RangeQueryFilteredPCAIndex<NV extends NumberVector<?>> extends Abst
public RangeQueryFilteredPCAIndex<V> instantiate(Relation<V> relation) {
// TODO: set bulk flag, once the parent class supports bulk.
RangeQuery<V, DoubleDistance> rangequery = QueryUtil.getRangeQuery(relation, pcaDistanceFunction);
- return new RangeQueryFilteredPCAIndex<V>(relation, pca, rangequery, epsilon);
+ return new RangeQueryFilteredPCAIndex<>(relation, pca, rangequery, epsilon);
}
/**
@@ -158,7 +163,7 @@ public class RangeQueryFilteredPCAIndex<NV extends NumberVector<?>> extends Abst
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- DistanceParameter<DoubleDistance> epsilonP = new DistanceParameter<DoubleDistance>(EPSILON_ID, pcaDistanceFunction != null ? pcaDistanceFunction.getDistanceFactory() : null);
+ DistanceParameter<DoubleDistance> epsilonP = new DistanceParameter<>(EPSILON_ID, pcaDistanceFunction != null ? pcaDistanceFunction.getDistanceFactory() : null);
if(config.grab(epsilonP)) {
epsilon = epsilonP.getValue();
}
@@ -166,7 +171,7 @@ public class RangeQueryFilteredPCAIndex<NV extends NumberVector<?>> extends Abst
@Override
protected Factory<NV> makeInstance() {
- return new Factory<NV>(pcaDistanceFunction, pca, epsilon);
+ return new Factory<>(pcaDistanceFunction, pca, epsilon);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/package-info.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/package-info.java
index 2bd9cc7d..536dbb3c 100644
--- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/package-info.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/package-info.java
index 98a55d88..2edb1244 100644
--- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/AbstractPreferenceVectorIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/AbstractPreferenceVectorIndex.java
index 56b09dba..dd43e027 100644
--- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/AbstractPreferenceVectorIndex.java
+++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/AbstractPreferenceVectorIndex.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.preference;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -50,15 +50,10 @@ public abstract class AbstractPreferenceVectorIndex<NV extends NumberVector<?>>
super(relation);
}
- /**
- * Preprocessing step.
- */
- protected abstract void preprocess();
-
@Override
public BitSet getPreferenceVector(DBIDRef objid) {
if(storage == null) {
- preprocess();
+ initialize();
}
return storage.get(objid);
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/DiSHPreferenceVectorIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/DiSHPreferenceVectorIndex.java
index 2b02e7d6..1d1662a7 100644
--- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/DiSHPreferenceVectorIndex.java
+++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/DiSHPreferenceVectorIndex.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.preference;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -44,13 +44,13 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
import de.lmu.ifi.dbs.elki.database.query.distance.PrimitiveDistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.database.relation.RelationUtil;
import de.lmu.ifi.dbs.elki.datasource.bundle.SingleObjectBundle;
import de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.DimensionSelectingDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
@@ -131,7 +131,7 @@ public class DiSHPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra
}
@Override
- protected void preprocess() {
+ public void initialize() {
if(relation == null || relation.size() == 0) {
throw new IllegalArgumentException(ExceptionMessages.DATABASE_EMPTY);
}
@@ -172,7 +172,7 @@ public class DiSHPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra
// determine neighbors in each dimension
ModifiableDBIDs[] allNeighbors = new ModifiableDBIDs[dim];
for(int d = 0; d < dim; d++) {
- DistanceDBIDResult<DoubleDistance> qrList = rangeQueries[d].getRangeForDBID(it, epsilon[d]);
+ DistanceDBIDList<DoubleDistance> qrList = rangeQueries[d].getRangeForDBID(it, epsilon[d]);
allNeighbors[d] = DBIDUtil.newHashSet(qrList);
}
@@ -249,7 +249,7 @@ public class DiSHPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra
// database for apriori
UpdatableDatabase apriori_db = new HashmapDatabase();
- SimpleTypeInformation<?> bitmeta = new VectorFieldTypeInformation<BitVector>(BitVector.class, dimensionality);
+ SimpleTypeInformation<?> bitmeta = new VectorFieldTypeInformation<>(BitVector.class, dimensionality);
for(DBIDIter it = relation.iterDBIDs(); it.valid(); it.advance()) {
Bit[] bits = new Bit[dimensionality];
boolean allFalse = true;
@@ -311,7 +311,7 @@ public class DiSHPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra
int dimensionality = neighborIDs.length;
BitSet preferenceVector = new BitSet(dimensionality);
- Map<Integer, ModifiableDBIDs> candidates = new HashMap<Integer, ModifiableDBIDs>(dimensionality);
+ Map<Integer, ModifiableDBIDs> candidates = new HashMap<>(dimensionality);
for(int i = 0; i < dimensionality; i++) {
ModifiableDBIDs s_i = neighborIDs[i];
if(s_i.size() > minpts) {
@@ -409,7 +409,7 @@ public class DiSHPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra
Class<RangeQuery<V, DoubleDistance>> rqcls = ClassGenericsUtil.uglyCastIntoSubclass(RangeQuery.class);
RangeQuery<V, DoubleDistance>[] rangeQueries = ClassGenericsUtil.newArrayOfNull(dimensionality, rqcls);
for(int d = 0; d < dimensionality; d++) {
- rangeQueries[d] = relation.getDatabase().getRangeQuery(new PrimitiveDistanceQuery<V, DoubleDistance>(relation, new DimensionSelectingDistanceFunction(d)));
+ rangeQueries[d] = relation.getDatabase().getRangeQuery(new PrimitiveDistanceQuery<>(relation, new DimensionSelectingDistanceFunction(d)));
}
return rangeQueries;
}
@@ -429,6 +429,11 @@ public class DiSHPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra
return "dish-pref";
}
+ @Override
+ public void logStatistics() {
+ // No statistics to log.
+ }
+
/**
* Factory class.
*
@@ -532,7 +537,7 @@ public class DiSHPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra
@Override
public DiSHPreferenceVectorIndex<V> instantiate(Relation<V> relation) {
- return new DiSHPreferenceVectorIndex<V>(relation, epsilon, minpts, strategy);
+ return new DiSHPreferenceVectorIndex<>(relation, epsilon, minpts, strategy);
}
/**
@@ -578,7 +583,7 @@ public class DiSHPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra
// parameter epsilon
// todo: constraint auf positive werte
- List<Double> defaultEps = new ArrayList<Double>();
+ List<Double> defaultEps = new ArrayList<>();
defaultEps.add(DEFAULT_EPSILON.doubleValue());
final DoubleListParameter epsilonP = new DoubleListParameter(EPSILON_ID, true);
epsilonP.setDefaultValue(defaultEps);
@@ -595,7 +600,7 @@ public class DiSHPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra
}
// parameter strategy
- final EnumParameter<Strategy> strategyP = new EnumParameter<Strategy>(STRATEGY_ID, Strategy.class, DEFAULT_STRATEGY);
+ final EnumParameter<Strategy> strategyP = new EnumParameter<>(STRATEGY_ID, Strategy.class, DEFAULT_STRATEGY);
if(config.grab(strategyP)) {
strategy = strategyP.getValue();
}
@@ -603,7 +608,7 @@ public class DiSHPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra
@Override
protected Factory<V> makeInstance() {
- return new Factory<V>(epsilon, minpts, strategy);
+ return new Factory<>(epsilon, minpts, strategy);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/HiSCPreferenceVectorIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/HiSCPreferenceVectorIndex.java
index fd6aa0bf..e5dcf2f4 100644
--- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/HiSCPreferenceVectorIndex.java
+++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/HiSCPreferenceVectorIndex.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.preference;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -34,11 +34,11 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.database.relation.RelationUtil;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
@@ -97,7 +97,7 @@ public class HiSCPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra
}
@Override
- protected void preprocess() {
+ public void initialize() {
if (relation == null || relation.size() <= 0) {
throw new IllegalArgumentException(ExceptionMessages.DATABASE_EMPTY);
}
@@ -118,7 +118,7 @@ public class HiSCPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra
msg.append("\n knns: ");
}
- KNNResult<DoubleDistance> knns = knnQuery.getKNNForDBID(it, k);
+ KNNList<DoubleDistance> knns = knnQuery.getKNNForDBID(it, k);
BitSet preferenceVector = determinePreferenceVector(relation, it, knns, msg);
storage.put(it, preferenceVector);
@@ -190,6 +190,11 @@ public class HiSCPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra
return "hisc-pref";
}
+ @Override
+ public void logStatistics() {
+ // No statistics to log.
+ }
+
/**
* Factory class.
*
@@ -261,7 +266,7 @@ public class HiSCPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra
} else {
usek = k;
}
- return new HiSCPreferenceVectorIndex<V>(relation, alpha, usek);
+ return new HiSCPreferenceVectorIndex<>(relation, alpha, usek);
}
/**
@@ -302,7 +307,7 @@ public class HiSCPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra
@Override
protected Factory<V> makeInstance() {
- return new Factory<V>(alpha, k);
+ return new Factory<>(alpha, k);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/PreferenceVectorIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/PreferenceVectorIndex.java
index a212c2cd..87a9d3dd 100644
--- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/PreferenceVectorIndex.java
+++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/PreferenceVectorIndex.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.preference;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/package-info.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/package-info.java
index 69d0855b..e840bfd0 100644
--- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/snn/SharedNearestNeighborIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/snn/SharedNearestNeighborIndex.java
index 3aa0c523..cdb1d0bb 100644
--- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/snn/SharedNearestNeighborIndex.java
+++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/snn/SharedNearestNeighborIndex.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.snn;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/snn/SharedNearestNeighborPreprocessor.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/snn/SharedNearestNeighborPreprocessor.java
index d57aeb8f..9b1aee0f 100644
--- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/snn/SharedNearestNeighborPreprocessor.java
+++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/snn/SharedNearestNeighborPreprocessor.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.snn;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -32,11 +32,11 @@ import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.index.preprocessed.AbstractPreprocessorIndex;
import de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNPreprocessor;
@@ -102,10 +102,8 @@ public class SharedNearestNeighborPreprocessor<O, D extends Distance<D>> extends
this.distanceFunction = distanceFunction;
}
- /**
- * Preprocessing step.
- */
- protected void preprocess() {
+ @Override
+ public void initialize() {
if(getLogger().isVerbose()) {
getLogger().verbose("Assigning nearest neighbor lists to database objects");
}
@@ -115,7 +113,7 @@ public class SharedNearestNeighborPreprocessor<O, D extends Distance<D>> extends
FiniteProgress progress = getLogger().isVerbose() ? new FiniteProgress("assigning nearest neighbor lists", relation.size(), getLogger()) : null;
for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
ArrayModifiableDBIDs neighbors = DBIDUtil.newArray(numberOfNeighbors);
- KNNResult<D> kNN = knnquery.getKNNForDBID(iditer, numberOfNeighbors);
+ KNNList<D> kNN = knnquery.getKNNForDBID(iditer, numberOfNeighbors);
for (DBIDIter iter = kNN.iter(); iter.valid(); iter.advance()) {
// if(!id.equals(nid)) {
neighbors.add(iter);
@@ -139,7 +137,7 @@ public class SharedNearestNeighborPreprocessor<O, D extends Distance<D>> extends
@Override
public ArrayDBIDs getNearestNeighborSet(DBIDRef objid) {
if(storage == null) {
- preprocess();
+ initialize();
}
return storage.get(objid);
}
@@ -159,6 +157,11 @@ public class SharedNearestNeighborPreprocessor<O, D extends Distance<D>> extends
return "SNN-index";
}
+ @Override
+ public void logStatistics() {
+ // No statistics to log.
+ }
+
/**
* Get the number of neighbors
*
@@ -228,7 +231,7 @@ public class SharedNearestNeighborPreprocessor<O, D extends Distance<D>> extends
@Override
public SharedNearestNeighborPreprocessor<O, D> instantiate(Relation<O> relation) {
- return new SharedNearestNeighborPreprocessor<O, D>(relation, numberOfNeighbors, distanceFunction);
+ return new SharedNearestNeighborPreprocessor<>(relation, numberOfNeighbors, distanceFunction);
}
/**
@@ -273,7 +276,7 @@ public class SharedNearestNeighborPreprocessor<O, D extends Distance<D>> extends
numberOfNeighbors = numberOfNeighborsP.getValue();
}
- final ObjectParameter<DistanceFunction<O, D>> distanceFunctionP = new ObjectParameter<DistanceFunction<O, D>>(DISTANCE_FUNCTION_ID, DistanceFunction.class, EuclideanDistanceFunction.class);
+ final ObjectParameter<DistanceFunction<O, D>> distanceFunctionP = new ObjectParameter<>(DISTANCE_FUNCTION_ID, DistanceFunction.class, EuclideanDistanceFunction.class);
if(config.grab(distanceFunctionP)) {
distanceFunction = distanceFunctionP.instantiateClass(config);
}
@@ -281,7 +284,7 @@ public class SharedNearestNeighborPreprocessor<O, D extends Distance<D>> extends
@Override
protected Factory<O, D> makeInstance() {
- return new Factory<O, D>(numberOfNeighbors, distanceFunction);
+ return new Factory<>(numberOfNeighbors, distanceFunction);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/snn/package-info.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/snn/package-info.java
index 98065df6..5612f655 100644
--- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/snn/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/snn/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/AbstractSubspaceProjectionIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/AbstractSubspaceProjectionIndex.java
index 1d23681d..1bad7db0 100644
--- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/AbstractSubspaceProjectionIndex.java
+++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/AbstractSubspaceProjectionIndex.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.subspaceproj;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -32,13 +32,13 @@ import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
-import de.lmu.ifi.dbs.elki.database.ids.DistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.generic.GenericDistanceDBIDList;
import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.GenericDistanceDBIDList;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.index.preprocessed.AbstractPreprocessorIndex;
import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
@@ -97,10 +97,8 @@ public abstract class AbstractSubspaceProjectionIndex<NV extends NumberVector<?>
this.minpts = minpts;
}
- /**
- * Preprocessing step.
- */
- protected void preprocess() {
+ @Override
+ public void initialize() {
if(relation == null || relation.size() <= 0) {
throw new IllegalArgumentException(ExceptionMessages.DATABASE_EMPTY);
}
@@ -115,7 +113,7 @@ public abstract class AbstractSubspaceProjectionIndex<NV extends NumberVector<?>
FiniteProgress progress = getLogger().isVerbose() ? new FiniteProgress(this.getClass().getName(), relation.size(), getLogger()) : null;
for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
- DistanceDBIDResult<D> neighbors = rangeQuery.getRangeForDBID(iditer, epsilon);
+ DistanceDBIDList<D> neighbors = rangeQuery.getRangeForDBID(iditer, epsilon);
final P pres;
if(neighbors.size() >= minpts) {
@@ -123,7 +121,7 @@ public abstract class AbstractSubspaceProjectionIndex<NV extends NumberVector<?>
}
else {
DistanceDBIDPair<D> firstQR = neighbors.iter().getDistancePair();
- GenericDistanceDBIDList<D> newne = new GenericDistanceDBIDList<D>();
+ GenericDistanceDBIDList<D> newne = new GenericDistanceDBIDList<>();
newne.add(firstQR);
pres = computeProjection(iditer, newne, relation);
}
@@ -148,7 +146,7 @@ public abstract class AbstractSubspaceProjectionIndex<NV extends NumberVector<?>
@Override
public P getLocalProjection(DBIDRef objid) {
if(storage == null) {
- preprocess();
+ initialize();
}
return storage.get(objid);
}
@@ -167,7 +165,7 @@ public abstract class AbstractSubspaceProjectionIndex<NV extends NumberVector<?>
*
* @return local subspace projection
*/
- protected abstract P computeProjection(DBIDRef id, DistanceDBIDResult<D> neighbors, Relation<NV> relation);
+ protected abstract P computeProjection(DBIDRef id, DistanceDBIDList<D> neighbors, Relation<NV> relation);
/**
* Factory class
@@ -247,7 +245,7 @@ public abstract class AbstractSubspaceProjectionIndex<NV extends NumberVector<?>
}
protected void configRangeQueryDistanceFunction(Parameterization config) {
- ObjectParameter<DistanceFunction<NV, D>> rangeQueryDistanceP = new ObjectParameter<DistanceFunction<NV, D>>(AbstractProjectedDBSCAN.INNER_DISTANCE_FUNCTION_ID, DistanceFunction.class, EuclideanDistanceFunction.class);
+ ObjectParameter<DistanceFunction<NV, D>> rangeQueryDistanceP = new ObjectParameter<>(AbstractProjectedDBSCAN.INNER_DISTANCE_FUNCTION_ID, DistanceFunction.class, EuclideanDistanceFunction.class);
if(config.grab(rangeQueryDistanceP)) {
rangeQueryDistanceFunction = rangeQueryDistanceP.instantiateClass(config);
}
@@ -255,7 +253,7 @@ public abstract class AbstractSubspaceProjectionIndex<NV extends NumberVector<?>
protected void configEpsilon(Parameterization config, DistanceFunction<NV, D> rangeQueryDistanceFunction) {
D distanceParser = rangeQueryDistanceFunction != null ? rangeQueryDistanceFunction.getDistanceFactory() : null;
- DistanceParameter<D> epsilonP = new DistanceParameter<D>(AbstractProjectedDBSCAN.EPSILON_ID, distanceParser);
+ DistanceParameter<D> epsilonP = new DistanceParameter<>(AbstractProjectedDBSCAN.EPSILON_ID, distanceParser);
// parameter epsilon
if(config.grab(epsilonP)) {
epsilon = epsilonP.getValue();
diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/FourCSubspaceIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/FourCSubspaceIndex.java
index 80212981..a6e59f3f 100644
--- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/FourCSubspaceIndex.java
+++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/FourCSubspaceIndex.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.subspaceproj;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -30,9 +30,9 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
@@ -93,7 +93,7 @@ public class FourCSubspaceIndex<V extends NumberVector<?>, D extends Distance<D>
}
@Override
- protected PCAFilteredResult computeProjection(DBIDRef id, DistanceDBIDResult<D> neighbors, Relation<V> database) {
+ protected PCAFilteredResult computeProjection(DBIDRef id, DistanceDBIDList<D> neighbors, Relation<V> database) {
ModifiableDBIDs ids = DBIDUtil.newArray(neighbors.size());
for (DBIDIter neighbor = neighbors.iter(); neighbor.valid(); neighbor.advance()) {
ids.add(neighbor);
@@ -124,6 +124,11 @@ public class FourCSubspaceIndex<V extends NumberVector<?>, D extends Distance<D>
return "4C-subspaces";
}
+ @Override
+ public void logStatistics() {
+ // No statistics to log.
+ }
+
/**
* Factory class for 4C preprocessors.
*
@@ -161,7 +166,7 @@ public class FourCSubspaceIndex<V extends NumberVector<?>, D extends Distance<D>
@Override
public FourCSubspaceIndex<V, D> instantiate(Relation<V> relation) {
- return new FourCSubspaceIndex<V, D>(relation, epsilon, rangeQueryDistanceFunction, minpts, pca);
+ return new FourCSubspaceIndex<>(relation, epsilon, rangeQueryDistanceFunction, minpts, pca);
}
/**
@@ -236,20 +241,20 @@ public class FourCSubspaceIndex<V extends NumberVector<?>, D extends Distance<D>
LoggingUtil.warning("Error in internal parameterization: " + e.getMessage());
}
- final ArrayList<ParameterConstraint<? super Double>> deltaCons = new ArrayList<ParameterConstraint<? super Double>>();
+ final ArrayList<ParameterConstraint<? super Double>> deltaCons = new ArrayList<>();
// TODO: this constraint is already set in the parameter itself, since
// it
// also applies to the relative case, right? -- erich
// deltaCons.add(new GreaterEqualConstraint(0));
deltaCons.add(new LessEqualConstraint(1));
- GlobalParameterConstraint gpc = new ParameterFlagGlobalConstraint<Double>(deltaP, deltaCons, absoluteF, false);
+ GlobalParameterConstraint gpc = new ParameterFlagGlobalConstraint<>(deltaP, deltaCons, absoluteF, false);
config.checkConstraint(gpc);
}
@Override
protected Factory<V, D> makeInstance() {
- return new Factory<V, D>(epsilon, rangeQueryDistanceFunction, minpts, pca);
+ return new Factory<>(epsilon, rangeQueryDistanceFunction, minpts, pca);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/PreDeConSubspaceIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/PreDeConSubspaceIndex.java
index 17590804..69882c50 100644
--- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/PreDeConSubspaceIndex.java
+++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/PreDeConSubspaceIndex.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.subspaceproj;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,9 +26,9 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.subspaceproj;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Matrix;
@@ -86,7 +86,7 @@ public class PreDeConSubspaceIndex<V extends NumberVector<?>, D extends Distance
}
@Override
- protected SubspaceProjectionResult computeProjection(DBIDRef id, DistanceDBIDResult<D> neighbors, Relation<V> database) {
+ protected SubspaceProjectionResult computeProjection(DBIDRef id, DistanceDBIDList<D> neighbors, Relation<V> database) {
StringBuilder msg = null;
int referenceSetSize = neighbors.size();
@@ -170,6 +170,11 @@ public class PreDeConSubspaceIndex<V extends NumberVector<?>, D extends Distance
return LOG;
}
+ @Override
+ public void logStatistics() {
+ // No statistics to log.
+ }
+
/**
* Factory.
*
@@ -212,7 +217,7 @@ public class PreDeConSubspaceIndex<V extends NumberVector<?>, D extends Distance
@Override
public PreDeConSubspaceIndex<V, D> instantiate(Relation<V> relation) {
- return new PreDeConSubspaceIndex<V, D>(relation, epsilon, rangeQueryDistanceFunction, minpts, delta);
+ return new PreDeConSubspaceIndex<>(relation, epsilon, rangeQueryDistanceFunction, minpts, delta);
}
/**
@@ -241,7 +246,7 @@ public class PreDeConSubspaceIndex<V extends NumberVector<?>, D extends Distance
@Override
protected Factory<V, D> makeInstance() {
- return new Factory<V, D>(epsilon, rangeQueryDistanceFunction, minpts, delta);
+ return new Factory<>(epsilon, rangeQueryDistanceFunction, minpts, delta);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/SubspaceProjectionIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/SubspaceProjectionIndex.java
index 67cc1701..f0fbbd35 100644
--- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/SubspaceProjectionIndex.java
+++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/SubspaceProjectionIndex.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.subspaceproj;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/package-info.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/package-info.java
index f6e5e925..4c529c66 100644
--- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/projected/LatLngAsECEFIndex.java b/src/de/lmu/ifi/dbs/elki/index/projected/LatLngAsECEFIndex.java
new file mode 100644
index 00000000..8449996b
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/projected/LatLngAsECEFIndex.java
@@ -0,0 +1,292 @@
+package de.lmu.ifi.dbs.elki.index.projected;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.projection.LatLngToECEFProjection;
+import de.lmu.ifi.dbs.elki.data.projection.Projection;
+import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory;
+import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
+import de.lmu.ifi.dbs.elki.database.datastore.WritableDataStore;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery;
+import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
+import de.lmu.ifi.dbs.elki.database.query.distance.SpatialPrimitiveDistanceQuery;
+import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
+import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery;
+import de.lmu.ifi.dbs.elki.database.query.rknn.RKNNQuery;
+import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
+import de.lmu.ifi.dbs.elki.database.relation.ProjectedView;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.geo.LatLngDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+import de.lmu.ifi.dbs.elki.index.Index;
+import de.lmu.ifi.dbs.elki.index.IndexFactory;
+import de.lmu.ifi.dbs.elki.index.KNNIndex;
+import de.lmu.ifi.dbs.elki.index.RKNNIndex;
+import de.lmu.ifi.dbs.elki.index.RangeIndex;
+import de.lmu.ifi.dbs.elki.math.geodesy.EarthModel;
+import de.lmu.ifi.dbs.elki.math.geodesy.SphericalVincentyEarthModel;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Flag;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
+
+/**
+ * Index a 2d data set (consisting of Lat/Lng pairs) by using a projection to 3D
+ * coordinates (WGS-86 to ECEF).
+ *
+ * Earth-Centered, Earth-Fixed (ECEF) is a 3D coordinate system, sometimes also
+ * referred to as XYZ, that uses 3 cartesian axes. The center is at the earths
+ * center of mass, the z axis points to the north pole. X axis is to the prime
+ * meridan at the equator (so latitude 0, longitude 0), and the Y axis is
+ * orthogonal going to the east (latitude 0, longitude 90°E).
+ *
+ * The Euclidean distance in this coordinate system is a lower bound for the
+ * great-circle distance, and Euclidean coordinates are supposedly easier to
+ * index.
+ *
+ * Note: this index will <b>only</b> support the distance function
+ * {@link LatLngDistanceFunction}, as it uses a projection that will map data
+ * according to this great circle distance. If the query hint
+ * {@link DatabaseQuery#HINT_EXACT} is set, it will not be used.
+ *
+ * @author Erich Schubert
+ *
+ * @param <O> Object type
+ */
+public class LatLngAsECEFIndex<O extends NumberVector<?>> extends ProjectedIndex<O, O> {
+ /**
+ * Constructor.
+ *
+ * @param relation Relation to index.
+ * @param proj Projection to use.
+ * @param view View to use.
+ * @param inner Index to wrap.
+ * @param norefine Refinement disable flag.
+ */
+ public LatLngAsECEFIndex(Relation<O> relation, Projection<O, O> proj, Relation<O> view, Index inner, boolean norefine) {
+ super(relation, proj, view, inner, norefine, 1.0);
+ }
+
+ @Override
+ public String getLongName() {
+ return "projected " + inner.getLongName();
+ }
+
+ @Override
+ public String getShortName() {
+ return "proj-" + inner.getShortName();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <D extends Distance<D>> KNNQuery<O, D> getKNNQuery(DistanceQuery<O, D> distanceQuery, Object... hints) {
+ if (!(inner instanceof KNNIndex)) {
+ return null;
+ }
+ if (distanceQuery.getRelation() != relation) {
+ return null;
+ }
+ if (!LatLngDistanceFunction.class.isInstance(distanceQuery.getDistanceFunction())) {
+ return null;
+ }
+ for (Object o : hints) {
+ if (o == DatabaseQuery.HINT_EXACT) {
+ return null;
+ }
+ }
+ SpatialPrimitiveDistanceQuery<O, DoubleDistance> innerQuery = EuclideanDistanceFunction.STATIC.instantiate(view);
+ KNNQuery<O, DoubleDistance> innerq = ((KNNIndex<O>) inner).getKNNQuery(innerQuery, hints);
+ if (innerq == null) {
+ return null;
+ }
+ return (KNNQuery<O, D>) new ProjectedKNNQuery<DoubleDistance>((DistanceQuery<O, DoubleDistance>) distanceQuery, innerq);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <D extends Distance<D>> RangeQuery<O, D> getRangeQuery(DistanceQuery<O, D> distanceQuery, Object... hints) {
+ if (!(inner instanceof RangeIndex)) {
+ return null;
+ }
+ if (distanceQuery.getRelation() != relation) {
+ return null;
+ }
+ if (!LatLngDistanceFunction.class.isInstance(distanceQuery.getDistanceFunction())) {
+ return null;
+ }
+ for (Object o : hints) {
+ if (o == DatabaseQuery.HINT_EXACT) {
+ return null;
+ }
+ }
+ SpatialPrimitiveDistanceQuery<O, DoubleDistance> innerQuery = EuclideanDistanceFunction.STATIC.instantiate(view);
+ RangeQuery<O, DoubleDistance> innerq = ((RangeIndex<O>) inner).getRangeQuery(innerQuery, hints);
+ if (innerq == null) {
+ return null;
+ }
+ return (RangeQuery<O, D>) new ProjectedRangeQuery<DoubleDistance>((DistanceQuery<O, DoubleDistance>) distanceQuery, innerq);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <D extends Distance<D>> RKNNQuery<O, D> getRKNNQuery(DistanceQuery<O, D> distanceQuery, Object... hints) {
+ if (!(inner instanceof RKNNIndex)) {
+ return null;
+ }
+ if (distanceQuery.getRelation() != relation) {
+ return null;
+ }
+ if (!LatLngDistanceFunction.class.isInstance(distanceQuery.getDistanceFunction())) {
+ return null;
+ }
+ for (Object o : hints) {
+ if (o == DatabaseQuery.HINT_EXACT) {
+ return null;
+ }
+ }
+ SpatialPrimitiveDistanceQuery<O, DoubleDistance> innerQuery = EuclideanDistanceFunction.STATIC.instantiate(view);
+ RKNNQuery<O, DoubleDistance> innerq = ((RKNNIndex<O>) inner).getRKNNQuery(innerQuery, hints);
+ if (innerq == null) {
+ return null;
+ }
+ return (RKNNQuery<O, D>) new ProjectedRKNNQuery<DoubleDistance>((DistanceQuery<O, DoubleDistance>) distanceQuery, innerq);
+ }
+
+ /**
+ * Index factory.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has LatLngAsECEFIndex
+ *
+ * @param <O> Data type.
+ */
+ public static class Factory<O extends NumberVector<?>> extends ProjectedIndex.Factory<O, O> {
+ /**
+ * Disable refinement of distances.
+ */
+ boolean norefine = false;
+
+ /**
+ * Constructor.
+ *
+ * @param inner Inner index
+ * @param materialize Flag to materialize the projection
+ * @param norefine Flag to disable refinement of distances
+ * @param model Earth model
+ */
+ public Factory(IndexFactory<O, ?> inner, boolean materialize, boolean norefine, EarthModel model) {
+ super(new LatLngToECEFProjection<O>(model), inner, materialize, norefine, 1.0);
+ }
+
+ @Override
+ public ProjectedIndex<O, O> instantiate(Relation<O> relation) {
+ if (!proj.getInputDataTypeInformation().isAssignableFromType(relation.getDataTypeInformation())) {
+ return null;
+ }
+ proj.initialize(relation.getDataTypeInformation());
+ final Relation<O> view;
+ if (materialize) {
+ DBIDs ids = relation.getDBIDs();
+ WritableDataStore<O> content = DataStoreUtil.makeStorage(ids, DataStoreFactory.HINT_DB, proj.getOutputDataTypeInformation().getRestrictionClass());
+ for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
+ content.put(iter, proj.project(relation.get(iter)));
+ }
+ view = new MaterializedRelation<>("ECEF Projection", "ecef-projection", proj.getOutputDataTypeInformation(), content, ids);
+ } else {
+ view = new ProjectedView<>(relation, proj);
+ }
+ Index inneri = inner.instantiate(view);
+ if (inneri == null) {
+ return null;
+ }
+ return new LatLngAsECEFIndex<>(relation, proj, view, inneri, norefine);
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ *
+ * @param <O> Outer object type.
+ */
+ public static class Parameterizer<O extends NumberVector<?>> extends AbstractParameterizer {
+ /**
+ * Inner index factory.
+ */
+ IndexFactory<O, ?> inner;
+
+ /**
+ * Whether to use a materialized view, or a virtual view.
+ */
+ boolean materialize = false;
+
+ /**
+ * Disable refinement of distances.
+ */
+ boolean norefine = false;
+
+ /**
+ * Earth model to use.
+ */
+ EarthModel model;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ ObjectParameter<EarthModel> modelP = new ObjectParameter<>(EarthModel.MODEL_ID, EarthModel.class, SphericalVincentyEarthModel.class);
+ if (config.grab(modelP)) {
+ model = modelP.instantiateClass(config);
+ }
+
+ ObjectParameter<IndexFactory<O, ?>> innerP = new ObjectParameter<>(ProjectedIndex.Factory.Parameterizer.INDEX_ID, IndexFactory.class);
+ if (config.grab(innerP)) {
+ inner = innerP.instantiateClass(config);
+ }
+
+ Flag materializeF = new Flag(ProjectedIndex.Factory.Parameterizer.MATERIALIZE_FLAG);
+ if (config.grab(materializeF)) {
+ materialize = materializeF.isTrue();
+ }
+
+ Flag norefineF = new Flag(ProjectedIndex.Factory.Parameterizer.DISABLE_REFINE_FLAG);
+ if (config.grab(norefineF)) {
+ norefine = norefineF.isTrue();
+ }
+ }
+
+ @Override
+ protected Factory<O> makeInstance() {
+ return new Factory<>(inner, materialize, norefine, model);
+ }
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/projected/LngLatAsECEFIndex.java b/src/de/lmu/ifi/dbs/elki/index/projected/LngLatAsECEFIndex.java
new file mode 100644
index 00000000..4bf97659
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/projected/LngLatAsECEFIndex.java
@@ -0,0 +1,287 @@
+package de.lmu.ifi.dbs.elki.index.projected;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.projection.LngLatToECEFProjection;
+import de.lmu.ifi.dbs.elki.data.projection.Projection;
+import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory;
+import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
+import de.lmu.ifi.dbs.elki.database.datastore.WritableDataStore;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery;
+import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
+import de.lmu.ifi.dbs.elki.database.query.distance.SpatialPrimitiveDistanceQuery;
+import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
+import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery;
+import de.lmu.ifi.dbs.elki.database.query.rknn.RKNNQuery;
+import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
+import de.lmu.ifi.dbs.elki.database.relation.ProjectedView;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.geo.LngLatDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+import de.lmu.ifi.dbs.elki.index.Index;
+import de.lmu.ifi.dbs.elki.index.IndexFactory;
+import de.lmu.ifi.dbs.elki.index.KNNIndex;
+import de.lmu.ifi.dbs.elki.index.RKNNIndex;
+import de.lmu.ifi.dbs.elki.index.RangeIndex;
+import de.lmu.ifi.dbs.elki.math.geodesy.EarthModel;
+import de.lmu.ifi.dbs.elki.math.geodesy.SphericalVincentyEarthModel;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Flag;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
+
+/**
+ * Index a 2d data set (consisting of Lng/Lat pairs) by using a projection to 3D
+ * coordinates (WGS-86 to ECEF).
+ *
+ * Earth-Centered, Earth-Fixed (ECEF) is a 3D coordinate system, sometimes also
+ * referred to as XYZ, that uses 3 cartesian axes. The center is at the earths
+ * center of mass, the z axis points to the north pole. X axis is to the prime
+ * meridan at the equator (so latitude 0, longitude 0), and the Y axis is
+ * orthogonal going to the east (latitude 0, longitude 90°E).
+ *
+ * The Euclidean distance in this coordinate system is a lower bound for the
+ * great-circle distance, and Euclidean coordinates are supposedly easier to
+ * index.
+ *
+ * Note: this index will <b>only</b> support the distance function
+ * {@link LngLatDistanceFunction}, as it uses a projection that will map data
+ * according to this great circle distance. If the query hint
+ * {@link DatabaseQuery#HINT_EXACT} is set, it will not be used.
+ *
+ * @author Erich Schubert
+ *
+ * @param <O> Object type
+ */
+public class LngLatAsECEFIndex<O extends NumberVector<?>> extends ProjectedIndex<O, O> {
+ /**
+ * Constructor.
+ *
+ * @param relation Relation to index.
+ * @param proj Projection to use.
+ * @param view View to use.
+ * @param inner Index to wrap.
+ * @param norefine Refinement disable flag.
+ */
+ public LngLatAsECEFIndex(Relation<O> relation, Projection<O, O> proj, Relation<O> view, Index inner, boolean norefine) {
+ super(relation, proj, view, inner, norefine, 1.0);
+ }
+
+ @Override
+ public String getLongName() {
+ return "projected " + inner.getLongName();
+ }
+
+ @Override
+ public String getShortName() {
+ return "proj-" + inner.getShortName();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <D extends Distance<D>> KNNQuery<O, D> getKNNQuery(DistanceQuery<O, D> distanceQuery, Object... hints) {
+ if (!(inner instanceof KNNIndex)) {
+ return null;
+ }
+ if (distanceQuery.getRelation() != relation) {
+ return null;
+ }
+ if (!LngLatDistanceFunction.class.isInstance(distanceQuery.getDistanceFunction())) {
+ return null;
+ }
+ for (Object o : hints) {
+ if (o == DatabaseQuery.HINT_EXACT) {
+ return null;
+ }
+ }
+ SpatialPrimitiveDistanceQuery<O, DoubleDistance> innerQuery = EuclideanDistanceFunction.STATIC.instantiate(view);
+ KNNQuery<O, DoubleDistance> innerq = ((KNNIndex<O>) inner).getKNNQuery(innerQuery, hints);
+ if (innerq == null) {
+ return null;
+ }
+ return (KNNQuery<O, D>) new ProjectedKNNQuery<DoubleDistance>((DistanceQuery<O, DoubleDistance>) distanceQuery, innerq);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <D extends Distance<D>> RangeQuery<O, D> getRangeQuery(DistanceQuery<O, D> distanceQuery, Object... hints) {
+ if (!(inner instanceof RangeIndex)) {
+ return null;
+ }
+ if (distanceQuery.getRelation() != relation) {
+ return null;
+ }
+ if (!LngLatDistanceFunction.class.isInstance(distanceQuery.getDistanceFunction())) {
+ return null;
+ }
+ for (Object o : hints) {
+ if (o == DatabaseQuery.HINT_EXACT) {
+ return null;
+ }
+ }
+ SpatialPrimitiveDistanceQuery<O, DoubleDistance> innerQuery = EuclideanDistanceFunction.STATIC.instantiate(view);
+ RangeQuery<O, DoubleDistance> innerq = ((RangeIndex<O>) inner).getRangeQuery(innerQuery, hints);
+ if (innerq == null) {
+ return null;
+ }
+ return (RangeQuery<O, D>) new ProjectedRangeQuery<DoubleDistance>((DistanceQuery<O, DoubleDistance>) distanceQuery, innerq);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <D extends Distance<D>> RKNNQuery<O, D> getRKNNQuery(DistanceQuery<O, D> distanceQuery, Object... hints) {
+ if (!(inner instanceof RKNNIndex)) {
+ return null;
+ }
+ if (distanceQuery.getRelation() != relation) {
+ return null;
+ }
+ if (!LngLatDistanceFunction.class.isInstance(distanceQuery.getDistanceFunction())) {
+ return null;
+ }
+ for (Object o : hints) {
+ if (o == DatabaseQuery.HINT_EXACT) {
+ return null;
+ }
+ }
+ SpatialPrimitiveDistanceQuery<O, DoubleDistance> innerQuery = EuclideanDistanceFunction.STATIC.instantiate(view);
+ RKNNQuery<O, DoubleDistance> innerq = ((RKNNIndex<O>) inner).getRKNNQuery(innerQuery, hints);
+ if (innerq == null) {
+ return null;
+ }
+ return (RKNNQuery<O, D>) new ProjectedRKNNQuery<DoubleDistance>((DistanceQuery<O, DoubleDistance>) distanceQuery, innerq);
+ }
+
+ /**
+ * Index factory.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has LngLatAsECEFIndex
+ *
+ * @param <O> Data type.
+ */
+ public static class Factory<O extends NumberVector<?>> extends ProjectedIndex.Factory<O, O> {
+ /**
+ * Constructor.
+ *
+ * @param inner Inner index
+ * @param materialize Flag to materialize the projection
+ * @param norefine Flag to disable refinement of distances
+ * @param model Earth model
+ */
+ public Factory(IndexFactory<O, ?> inner, boolean materialize, boolean norefine, EarthModel model) {
+ super(new LngLatToECEFProjection<O>(model), inner, materialize, norefine, 1.0);
+ }
+
+ @Override
+ public ProjectedIndex<O, O> instantiate(Relation<O> relation) {
+ if (!proj.getInputDataTypeInformation().isAssignableFromType(relation.getDataTypeInformation())) {
+ return null;
+ }
+ proj.initialize(relation.getDataTypeInformation());
+ final Relation<O> view;
+ if (materialize) {
+ DBIDs ids = relation.getDBIDs();
+ WritableDataStore<O> content = DataStoreUtil.makeStorage(ids, DataStoreFactory.HINT_DB, proj.getOutputDataTypeInformation().getRestrictionClass());
+ for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
+ content.put(iter, proj.project(relation.get(iter)));
+ }
+ view = new MaterializedRelation<>("ECEF Projection", "ecef-projection", proj.getOutputDataTypeInformation(), content, ids);
+ } else {
+ view = new ProjectedView<>(relation, proj);
+ }
+ Index inneri = inner.instantiate(view);
+ if (inneri == null) {
+ return null;
+ }
+ return new LngLatAsECEFIndex<>(relation, proj, view, inneri, norefine);
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ *
+ * @param <O> Outer object type.
+ */
+ public static class Parameterizer<O extends NumberVector<?>> extends AbstractParameterizer {
+ /**
+ * Inner index factory.
+ */
+ IndexFactory<O, ?> inner;
+
+ /**
+ * Whether to use a materialized view, or a virtual view.
+ */
+ boolean materialize = false;
+
+ /**
+ * Disable refinement of distances.
+ */
+ boolean norefine = false;
+
+ /**
+ * Earth model to use.
+ */
+ EarthModel model;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ ObjectParameter<EarthModel> modelP = new ObjectParameter<>(EarthModel.MODEL_ID, EarthModel.class, SphericalVincentyEarthModel.class);
+ if (config.grab(modelP)) {
+ model = modelP.instantiateClass(config);
+ }
+
+ ObjectParameter<IndexFactory<O, ?>> innerP = new ObjectParameter<>(ProjectedIndex.Factory.Parameterizer.INDEX_ID, IndexFactory.class);
+ if (config.grab(innerP)) {
+ inner = innerP.instantiateClass(config);
+ }
+
+ Flag materializeF = new Flag(ProjectedIndex.Factory.Parameterizer.MATERIALIZE_FLAG);
+ if (config.grab(materializeF)) {
+ materialize = materializeF.isTrue();
+ }
+
+ Flag norefineF = new Flag(ProjectedIndex.Factory.Parameterizer.DISABLE_REFINE_FLAG);
+ if (config.grab(norefineF)) {
+ norefine = norefineF.isTrue();
+ }
+ }
+
+ @Override
+ protected Factory<O> makeInstance() {
+ return new Factory<>(inner, materialize, norefine, model);
+ }
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/projected/PINN.java b/src/de/lmu/ifi/dbs/elki/index/projected/PINN.java
new file mode 100644
index 00000000..bfb18fa8
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/projected/PINN.java
@@ -0,0 +1,166 @@
+package de.lmu.ifi.dbs.elki.index.projected;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.projection.RandomProjection;
+import de.lmu.ifi.dbs.elki.index.IndexFactory;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.randomprojections.AchlioptasRandomProjectionFamily;
+import de.lmu.ifi.dbs.elki.utilities.RandomFactory;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterEqualConstraint;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleParameter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.RandomParameter;
+
+/**
+ * Projection-Indexed nearest-neighbors (PINN) is an index to retrieve the
+ * nearest neighbors in high dimensional spaces by using a random projection
+ * based index.
+ *
+ * Reference:
+ * <p>
+ * Finding local anomalies in very high dimensional space<br />
+ * T. de Vries, S. Chawla, M. E. Houle<br />
+ * In: Proc. IEEE 10th International Conference on Data Mining (ICDM)
+ * </p>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.composedOf AchlioptasRandomProjection
+ *
+ * @param <O> Object type
+ */
+@Reference(title = "Finding local anomalies in very high dimensional space", authors = "T. de Vries, S. Chawla, M. E. Houle", booktitle = "Proc. IEEE 10th International Conference on Data Mining (ICDM)", url = "http://dx.doi.org/10.1109/ICDM.2010.151")
+public class PINN<O extends NumberVector<?>> extends ProjectedIndex.Factory<O, O> {
+ /**
+ * Constructor.
+ *
+ * @param inner Inner index
+ * @param t Target dimensionality
+ * @param s Sparsity
+ * @param h Neighborhood size multiplicator
+ * @param random Random generator factory
+ */
+ public PINN(IndexFactory<O, ?> inner, int t, double s, double h, RandomFactory random) {
+ super(new RandomProjection<O>(t, new AchlioptasRandomProjectionFamily(s, random)), inner, true, false, h);
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ *
+ * @param <O> Outer object type.
+ */
+ public static class Parameterizer<O extends NumberVector<?>> extends AbstractParameterizer {
+ /**
+ * Target dimensionality.
+ */
+ public static final OptionID T_ID = new OptionID("pinn.t", "Target dimensionality.");
+
+ /**
+ * Sparsity option.
+ */
+ public static final OptionID S_ID = new OptionID("pinn.s", "Sparsity of the random projection.");
+
+ /**
+ * Neighborhood size.
+ */
+ public static final OptionID H_ID = new OptionID("pinn.hmult", "Multiplicator for neighborhood size.");
+
+ /**
+ * Random generator.
+ */
+ public static final OptionID RANDOM_ID = new OptionID("pinn.seed", "Random generator seed.");
+
+ /**
+ * Inner index factory.
+ */
+ IndexFactory<O, ?> inner;
+
+ /**
+ * Dimensionality.
+ */
+ int t;
+
+ /**
+ * Sparsity.
+ */
+ double s;
+
+ /**
+ * Multiplicator.
+ */
+ double h;
+
+ /**
+ * Random generator.
+ */
+ RandomFactory random;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ ObjectParameter<IndexFactory<O, ?>> innerP = new ObjectParameter<>(ProjectedIndex.Factory.Parameterizer.INDEX_ID, IndexFactory.class);
+ if (config.grab(innerP)) {
+ inner = innerP.instantiateClass(config);
+ }
+
+ IntParameter tP = new IntParameter(T_ID);
+ tP.addConstraint(new GreaterEqualConstraint(1));
+ if (config.grab(tP)) {
+ t = tP.intValue();
+ }
+
+ DoubleParameter sP = new DoubleParameter(S_ID, 1.);
+ sP.addConstraint(new GreaterEqualConstraint(1.));
+ if (config.grab(sP)) {
+ s = sP.doubleValue();
+ }
+
+ DoubleParameter hP = new DoubleParameter(H_ID, 3.);
+ hP.addConstraint(new GreaterEqualConstraint(1.));
+ if (config.grab(hP)) {
+ h = hP.doubleValue();
+ }
+
+ RandomParameter randomP = new RandomParameter(RANDOM_ID);
+ if (config.grab(randomP)) {
+ random = randomP.getValue();
+ }
+ }
+
+ @Override
+ protected PINN<O> makeInstance() {
+ return new PINN<>(inner, t, s, h, random);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/projected/ProjectedIndex.java b/src/de/lmu/ifi/dbs/elki/index/projected/ProjectedIndex.java
new file mode 100644
index 00000000..d5dc86f9
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/projected/ProjectedIndex.java
@@ -0,0 +1,648 @@
+package de.lmu.ifi.dbs.elki.index.projected;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.List;
+
+import de.lmu.ifi.dbs.elki.data.projection.Projection;
+import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
+import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory;
+import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
+import de.lmu.ifi.dbs.elki.database.datastore.WritableDataStore;
+import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPairList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNHeap;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNHeap;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.ModifiableDistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.ModifiableDoubleDistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.generic.GenericDistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery;
+import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
+import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
+import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery;
+import de.lmu.ifi.dbs.elki.database.query.rknn.RKNNQuery;
+import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
+import de.lmu.ifi.dbs.elki.database.relation.ProjectedView;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+import de.lmu.ifi.dbs.elki.index.Index;
+import de.lmu.ifi.dbs.elki.index.IndexFactory;
+import de.lmu.ifi.dbs.elki.index.KNNIndex;
+import de.lmu.ifi.dbs.elki.index.RKNNIndex;
+import de.lmu.ifi.dbs.elki.index.RangeIndex;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.statistics.Counter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterEqualConstraint;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleParameter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Flag;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
+
+/**
+ * Class to index data in an arbitrary projection only.
+ *
+ * Note: be <b>careful</b> when using this class, as it may/will yield incorrect
+ * distances, depending on your projection! It may be desirable to use a
+ * modified index that corrects for this error, or supports specific
+ * combiantions only.
+ *
+ * See {@link LatLngAsECEFIndex} and {@link LngLatAsECEFIndex} for example
+ * indexes that support only a specific (good) combination.
+ *
+ * FIXME: add refinement to bulk queries!
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.composedOf ProjectedKNNQuery
+ * @apiviz.composedOf ProjectedRangeQuery
+ * @apiviz.composedOf ProjectedRKNNQuery
+ *
+ * @param <O> Outer object type.
+ * @param <I> Inner object type.
+ */
+public class ProjectedIndex<O, I> implements KNNIndex<O>, RKNNIndex<O>, RangeIndex<O> {
+ /**
+ * Class logger
+ */
+ private static final Logging LOG = Logging.getLogger(ProjectedIndex.class);
+
+ /**
+ * Inner index.
+ */
+ Index inner;
+
+ /**
+ * Projection.
+ */
+ Projection<O, I> proj;
+
+ /**
+ * The relation we predend to index.
+ */
+ Relation<O> relation;
+
+ /**
+ * The view that we really index.
+ */
+ Relation<I> view;
+
+ /**
+ * Refinement disable flag.
+ */
+ boolean norefine;
+
+ /**
+ * Multiplier for k.
+ */
+ double kmulti = 1.0;
+
+ /**
+ * Count the number of distance refinements computed.
+ */
+ final Counter refinements;
+
+ /**
+ * Constructor.
+ *
+ * @param relation Relation to index.
+ * @param proj Projection to use.
+ * @param view View to use.
+ * @param inner Index to wrap.
+ * @param norefine Refinement disable flag.
+ * @param kmulti Multiplicator for k
+ */
+ public ProjectedIndex(Relation<O> relation, Projection<O, I> proj, Relation<I> view, Index inner, boolean norefine, double kmulti) {
+ super();
+ this.relation = relation;
+ this.view = view;
+ this.inner = inner;
+ this.proj = proj;
+ this.norefine = norefine;
+ this.kmulti = kmulti;
+ this.refinements = LOG.isStatistics() ? LOG.newCounter(this.getClass().getName() + ".refinements") : null;
+ }
+
+ /**
+ * Count a single distance refinement.
+ */
+ private void countRefinement() {
+ if(refinements != null) {
+ refinements.increment();
+ }
+ }
+
+ @Override
+ public void initialize() {
+ inner.initialize();
+ }
+
+ @Override
+ public String getLongName() {
+ return "projected " + inner.getLongName();
+ }
+
+ @Override
+ public String getShortName() {
+ return "proj-" + inner.getShortName();
+ }
+
+ @Override
+ public void logStatistics() {
+ if(refinements != null) {
+ LOG.statistics(refinements);
+ }
+ inner.logStatistics();
+ }
+
+ @Override
+ public <D extends Distance<D>> KNNQuery<O, D> getKNNQuery(DistanceQuery<O, D> distanceQuery, Object... hints) {
+ if(!(inner instanceof KNNIndex)) {
+ return null;
+ }
+ if(distanceQuery.getRelation() != relation) {
+ return null;
+ }
+ for(Object o : hints) {
+ if(o == DatabaseQuery.HINT_EXACT) {
+ return null;
+ }
+ }
+ @SuppressWarnings("unchecked")
+ DistanceQuery<I, D> innerQuery = ((DistanceFunction<? super I, D>) distanceQuery.getDistanceFunction()).instantiate(view);
+ @SuppressWarnings("unchecked")
+ KNNQuery<I, D> innerq = ((KNNIndex<I>) inner).getKNNQuery(innerQuery, hints);
+ if(innerq == null) {
+ return null;
+ }
+ return new ProjectedKNNQuery<>(distanceQuery, innerq);
+ }
+
+ @Override
+ public <D extends Distance<D>> RangeQuery<O, D> getRangeQuery(DistanceQuery<O, D> distanceQuery, Object... hints) {
+ if(!(inner instanceof RangeIndex)) {
+ return null;
+ }
+ if(distanceQuery.getRelation() != relation) {
+ return null;
+ }
+ for(Object o : hints) {
+ if(o == DatabaseQuery.HINT_EXACT) {
+ return null;
+ }
+ }
+ @SuppressWarnings("unchecked")
+ DistanceQuery<I, D> innerQuery = ((DistanceFunction<? super I, D>) distanceQuery.getDistanceFunction()).instantiate(view);
+ @SuppressWarnings("unchecked")
+ RangeQuery<I, D> innerq = ((RangeIndex<I>) inner).getRangeQuery(innerQuery, hints);
+ if(innerq == null) {
+ return null;
+ }
+ return new ProjectedRangeQuery<>(distanceQuery, innerq);
+ }
+
+ @Override
+ public <D extends Distance<D>> RKNNQuery<O, D> getRKNNQuery(DistanceQuery<O, D> distanceQuery, Object... hints) {
+ if(!(inner instanceof RKNNIndex)) {
+ return null;
+ }
+ if(distanceQuery.getRelation() != relation) {
+ return null;
+ }
+ for(Object o : hints) {
+ if(o == DatabaseQuery.HINT_EXACT) {
+ return null;
+ }
+ }
+ @SuppressWarnings("unchecked")
+ DistanceQuery<I, D> innerQuery = ((DistanceFunction<? super I, D>) distanceQuery.getDistanceFunction()).instantiate(view);
+ @SuppressWarnings("unchecked")
+ RKNNQuery<I, D> innerq = ((RKNNIndex<I>) inner).getRKNNQuery(innerQuery, hints);
+ if(innerq == null) {
+ return null;
+ }
+ return new ProjectedRKNNQuery<>(distanceQuery, innerq);
+ }
+
+ /**
+ * Class to proxy kNN queries.
+ *
+ * @author Erich Schubert
+ *
+ * @param <D> Distance type
+ */
+ class ProjectedKNNQuery<D extends Distance<D>> implements KNNQuery<O, D> {
+ /**
+ * Inner kNN query.
+ */
+ KNNQuery<I, D> inner;
+
+ /**
+ * Distance query for refinement.
+ */
+ DistanceQuery<O, D> distq;
+
+ /**
+ * Constructor.
+ *
+ * @param inner Inner kNN query.
+ */
+ public ProjectedKNNQuery(DistanceQuery<O, D> distanceQuery, KNNQuery<I, D> inner) {
+ super();
+ this.inner = inner;
+ this.distq = distanceQuery;
+ }
+
+ @Override
+ public KNNList<D> getKNNForDBID(DBIDRef id, int k) {
+ // So we have to project the query point only once:
+ return getKNNForObject(relation.get(id), k);
+ }
+
+ @Override
+ public List<? extends KNNList<D>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) {
+ return inner.getKNNForBulkDBIDs(ids, k);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public KNNList<D> getKNNForObject(O obj, int k) {
+ final I pobj = proj.project(obj);
+ if(norefine) {
+ return inner.getKNNForObject(pobj, k);
+ }
+ KNNList<D> ilist = inner.getKNNForObject(pobj, (int) Math.ceil(k * kmulti));
+ if(distq.getDistanceFunction() instanceof PrimitiveDoubleDistanceFunction) {
+ PrimitiveDoubleDistanceFunction<? super O> df = (PrimitiveDoubleDistanceFunction<? super O>) distq.getDistanceFunction();
+ DoubleDistanceKNNHeap heap = (DoubleDistanceKNNHeap) DBIDUtil.newHeap(DoubleDistance.FACTORY, k);
+ for(DistanceDBIDListIter<D> iter = ilist.iter(); iter.valid(); iter.advance()) {
+ heap.add(df.doubleDistance(obj, distq.getRelation().get(iter)), iter);
+ countRefinement();
+ }
+ return (KNNList<D>) heap.toKNNList();
+ }
+ else {
+ KNNHeap<D> heap = DBIDUtil.newHeap(distq.getDistanceFactory(), k);
+ for(DistanceDBIDListIter<D> iter = ilist.iter(); iter.valid(); iter.advance()) {
+ heap.add(distq.distance(obj, iter), iter);
+ countRefinement();
+ }
+ return heap.toKNNList();
+ }
+ }
+ }
+
+ /**
+ * Class to proxy range queries.
+ *
+ * @author Erich Schubert
+ *
+ * @param <D> Distance type
+ */
+ class ProjectedRangeQuery<D extends Distance<D>> implements RangeQuery<O, D> {
+ /**
+ * Inner range query.
+ */
+ RangeQuery<I, D> inner;
+
+ /**
+ * Distance query for refinement.
+ */
+ DistanceQuery<O, D> distq;
+
+ /**
+ * Constructor.
+ *
+ * @param inner Inner range query.
+ */
+ public ProjectedRangeQuery(DistanceQuery<O, D> distanceQuery, RangeQuery<I, D> inner) {
+ super();
+ this.inner = inner;
+ this.distq = distanceQuery;
+ }
+
+ @Override
+ public DistanceDBIDList<D> getRangeForDBID(DBIDRef id, D range) {
+ // So we have to project the query point only once:
+ return getRangeForObject(relation.get(id), range);
+ }
+
+ @SuppressWarnings({ "unchecked" })
+ @Override
+ public DistanceDBIDList<D> getRangeForObject(O obj, D range) {
+ final I pobj = proj.project(obj);
+ DistanceDBIDList<D> ilist = inner.getRangeForObject(pobj, range);
+ if(norefine) {
+ return ilist;
+ }
+ if(distq.getDistanceFunction() instanceof PrimitiveDoubleDistanceFunction) {
+ PrimitiveDoubleDistanceFunction<? super O> df = (PrimitiveDoubleDistanceFunction<? super O>) distq.getDistanceFunction();
+ double drange = ((DoubleDistance) range).doubleValue();
+ ModifiableDoubleDistanceDBIDList olist = new DoubleDistanceDBIDPairList(ilist.size());
+ for(DistanceDBIDListIter<D> iter = ilist.iter(); iter.valid(); iter.advance()) {
+ final double dist = df.doubleDistance(obj, distq.getRelation().get(iter));
+ countRefinement();
+ if(dist <= drange) {
+ olist.add(dist, iter);
+ }
+ }
+ return (DistanceDBIDList<D>) olist;
+ }
+ else {
+ ModifiableDistanceDBIDList<D> olist = new GenericDistanceDBIDList<>(ilist.size());
+ for(DistanceDBIDListIter<D> iter = ilist.iter(); iter.valid(); iter.advance()) {
+ D dist = distq.distance(obj, iter);
+ countRefinement();
+ if(range.compareTo(dist) <= 0) {
+ olist.add(dist, iter);
+ }
+ }
+ return olist;
+ }
+ }
+ }
+
+ /**
+ * Class to proxy RkNN queries.
+ *
+ * @author Erich Schubert
+ *
+ * @param <D> Distance type
+ */
+ class ProjectedRKNNQuery<D extends Distance<D>> implements RKNNQuery<O, D> {
+ /**
+ * Inner RkNN query.
+ */
+ RKNNQuery<I, D> inner;
+
+ /**
+ * Distance query for refinement.
+ */
+ DistanceQuery<O, D> distq;
+
+ /**
+ * Constructor.
+ *
+ * @param inner Inner RkNN query.
+ */
+ public ProjectedRKNNQuery(DistanceQuery<O, D> distanceQuery, RKNNQuery<I, D> inner) {
+ super();
+ this.inner = inner;
+ this.distq = distanceQuery;
+ }
+
+ @Override
+ public DistanceDBIDList<D> getRKNNForDBID(DBIDRef id, int k) {
+ // So we have to project the query point only once:
+ return getRKNNForObject(relation.get(id), k);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public DistanceDBIDList<D> getRKNNForObject(O obj, int k) {
+ final I pobj = proj.project(obj);
+ if(norefine) {
+ return inner.getRKNNForObject(pobj, k);
+ }
+ DistanceDBIDList<D> ilist = inner.getRKNNForObject(pobj, (int) Math.ceil(k * kmulti));
+ if(distq.getDistanceFunction() instanceof PrimitiveDoubleDistanceFunction) {
+ PrimitiveDoubleDistanceFunction<? super O> df = (PrimitiveDoubleDistanceFunction<? super O>) distq.getDistanceFunction();
+ ModifiableDoubleDistanceDBIDList olist = new DoubleDistanceDBIDPairList(ilist.size());
+ for(DistanceDBIDListIter<D> iter = ilist.iter(); iter.valid(); iter.advance()) {
+ final double dist = df.doubleDistance(obj, distq.getRelation().get(iter));
+ countRefinement();
+ olist.add(dist, iter);
+ }
+ return (DistanceDBIDList<D>) olist;
+ }
+ else {
+ ModifiableDistanceDBIDList<D> olist = new GenericDistanceDBIDList<>(ilist.size());
+ for(DistanceDBIDListIter<D> iter = ilist.iter(); iter.valid(); iter.advance()) {
+ D dist = distq.distance(obj, iter);
+ countRefinement();
+ olist.add(dist, iter);
+ }
+ return olist;
+ }
+ }
+
+ @Override
+ public List<? extends DistanceDBIDList<D>> getRKNNForBulkDBIDs(ArrayDBIDs ids, int k) {
+ return inner.getRKNNForBulkDBIDs(ids, k);
+ }
+ }
+
+ /**
+ * Index factory.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has ProjectedIndex
+ *
+ * @param <O> Outer object type.
+ * @param <I> Inner object type.
+ */
+ public static class Factory<O, I> implements IndexFactory<O, ProjectedIndex<O, I>> {
+ /**
+ * Projection to use.
+ */
+ Projection<O, I> proj;
+
+ /**
+ * Inner index factory.
+ */
+ IndexFactory<I, ?> inner;
+
+ /**
+ * Whether to use a materialized view, or a virtual view.
+ */
+ boolean materialize = false;
+
+ /**
+ * Disable refinement of distances.
+ */
+ boolean norefine = false;
+
+ /**
+ * Multiplier for k.
+ */
+ double kmulti = 1.0;
+
+ /**
+ * Constructor.
+ *
+ * @param proj Projection
+ * @param inner Inner index
+ * @param materialize Flag for materializing
+ * @param norefine Disable refinement of distances
+ * @param kmulti Multiplicator for k.
+ */
+ public Factory(Projection<O, I> proj, IndexFactory<I, ?> inner, boolean materialize, boolean norefine, double kmulti) {
+ super();
+ this.proj = proj;
+ this.inner = inner;
+ this.materialize = materialize;
+ this.kmulti = kmulti;
+ }
+
+ @Override
+ public ProjectedIndex<O, I> instantiate(Relation<O> relation) {
+ if(!proj.getInputDataTypeInformation().isAssignableFromType(relation.getDataTypeInformation())) {
+ return null;
+ }
+ // FIXME: non re-entrant!
+ proj.initialize(relation.getDataTypeInformation());
+ Index inneri = null;
+ Relation<I> view = null;
+ if(materialize) {
+ DBIDs ids = relation.getDBIDs();
+ WritableDataStore<I> content = DataStoreUtil.makeStorage(ids, DataStoreFactory.HINT_DB, proj.getOutputDataTypeInformation().getRestrictionClass());
+ for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
+ content.put(iter, proj.project(relation.get(iter)));
+ }
+ view = new MaterializedRelation<>("Projected Index", "projected-index", proj.getOutputDataTypeInformation(), content, ids);
+ }
+ else {
+ view = new ProjectedView<>(relation, proj);
+ }
+ inneri = inner.instantiate(view);
+ if(inneri == null) {
+ return null;
+ }
+ return new ProjectedIndex<>(relation, proj, view, inneri, norefine, kmulti);
+ }
+
+ @Override
+ public TypeInformation getInputTypeRestriction() {
+ return proj.getInputDataTypeInformation();
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ *
+ * @param <O> Outer object type.
+ * @param <I> Inner object type.
+ */
+ public static class Parameterizer<O, I> extends AbstractParameterizer {
+ /**
+ * Option ID for the projection to use.
+ */
+ public static final OptionID PROJ_ID = new OptionID("projindex.proj", "Projection to use for the projected index.");
+
+ /**
+ * Option ID for the inner index to use.
+ */
+ public static final OptionID INDEX_ID = new OptionID("projindex.inner", "Index to use on the projected data.");
+
+ /**
+ * Option ID for materialization.
+ */
+ public static final OptionID MATERIALIZE_FLAG = new OptionID("projindex.materialize", "Flag to materialize the projected data.");
+
+ /**
+ * Option ID for disabling refinement.
+ */
+ public static final OptionID DISABLE_REFINE_FLAG = new OptionID("projindex.disable-refine", "Flag to disable refinement of distances.");
+
+ /**
+ * Option ID for querying a larger k.
+ */
+ public static final OptionID K_MULTIPLIER_ID = new OptionID("projindex.kmulti", "Multiplier for k.");
+
+ /**
+ * Projection to use.
+ */
+ Projection<O, I> proj;
+
+ /**
+ * Inner index factory.
+ */
+ IndexFactory<I, ?> inner;
+
+ /**
+ * Whether to use a materialized view, or a virtual view.
+ */
+ boolean materialize = false;
+
+ /**
+ * Disable refinement of distances.
+ */
+ boolean norefine = false;
+
+ /**
+ * Multiplier for k.
+ */
+ double kmulti = 1.0;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ ObjectParameter<Projection<O, I>> projP = new ObjectParameter<>(PROJ_ID, Projection.class);
+ if(config.grab(projP)) {
+ proj = projP.instantiateClass(config);
+ }
+ ObjectParameter<IndexFactory<I, ?>> innerP = new ObjectParameter<>(INDEX_ID, IndexFactory.class);
+ if(config.grab(innerP)) {
+ inner = innerP.instantiateClass(config);
+ }
+ Flag materializeF = new Flag(MATERIALIZE_FLAG);
+ if(config.grab(materializeF)) {
+ materialize = materializeF.isTrue();
+ }
+ Flag norefineF = new Flag(DISABLE_REFINE_FLAG);
+ if(config.grab(norefineF)) {
+ norefine = norefineF.isTrue();
+ }
+ if(!norefine) {
+ DoubleParameter kmultP = new DoubleParameter(K_MULTIPLIER_ID);
+ kmultP.setDefaultValue(1.0);
+ kmultP.addConstraint(new GreaterEqualConstraint(1.0));
+ if(config.grab(kmultP)) {
+ kmulti = kmultP.doubleValue();
+ }
+ }
+ }
+
+ @Override
+ protected Factory<O, I> makeInstance() {
+ return new Factory<>(proj, inner, materialize, norefine, kmulti);
+ }
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/projected/package-info.java b/src/de/lmu/ifi/dbs/elki/index/projected/package-info.java
new file mode 100644
index 00000000..8a311292
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/projected/package-info.java
@@ -0,0 +1,26 @@
+/**
+ * <p>Projected indexes for data.</p>
+ */
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package de.lmu.ifi.dbs.elki.index.projected;
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/AbstractDirectoryEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/AbstractDirectoryEntry.java
index 03572b35..a75a49eb 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/AbstractDirectoryEntry.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/AbstractDirectoryEntry.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/AbstractLeafEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/AbstractLeafEntry.java
index ea5fd6de..15c8c589 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/AbstractLeafEntry.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/AbstractLeafEntry.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/AbstractNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/AbstractNode.java
index 4f2c6d04..2748b76e 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/AbstractNode.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/AbstractNode.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -98,7 +98,7 @@ public abstract class AbstractNode<E extends Entry> extends AbstractExternalizab
public IndexTreePath<E> nextElement() {
synchronized(AbstractNode.this) {
if(count < numEntries) {
- return parentPath.pathByAddingChild(new TreeIndexPathComponent<E>(entries[count], count++));
+ return parentPath.pathByAddingChild(new TreeIndexPathComponent<>(entries[count], count++));
}
}
throw new NoSuchElementException();
@@ -284,7 +284,7 @@ public abstract class AbstractNode<E extends Entry> extends AbstractExternalizab
*/
@Deprecated
public final List<E> getEntries() {
- List<E> result = new ArrayList<E>(numEntries);
+ List<E> result = new ArrayList<>(numEntries);
for(E entry : entries) {
if(entry != null) {
result.add(entry);
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/BreadthFirstEnumeration.java b/src/de/lmu/ifi/dbs/elki/index/tree/BreadthFirstEnumeration.java
index 6f43de11..ec33050b 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/BreadthFirstEnumeration.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/BreadthFirstEnumeration.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -74,7 +74,7 @@ public class BreadthFirstEnumeration<N extends Node<E>, E extends Entry> impleme
*/
public BreadthFirstEnumeration(final IndexTree<N, E> index, final IndexTreePath<E> rootPath) {
super();
- this.queue = new LinkedList<Enumeration<IndexTreePath<E>>>();
+ this.queue = new LinkedList<>();
this.index = index;
Enumeration<IndexTreePath<E>> root_enum = new Enumeration<IndexTreePath<E>>() {
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/DirectoryEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/DirectoryEntry.java
index 68924cae..c7d74f13 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/DirectoryEntry.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/DirectoryEntry.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,11 +23,12 @@ package de.lmu.ifi.dbs.elki.index.tree;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
/**
* Directory Entry
*
* @author Erich Schubert
+ *
+ * @apiviz.excludeSubtypes
*/
public interface DirectoryEntry extends Entry {
/**
@@ -42,4 +43,4 @@ public interface DirectoryEntry extends Entry {
* Get the page ID of this leaf entry.
*/
public Integer getPageID();
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/Entry.java b/src/de/lmu/ifi/dbs/elki/index/tree/Entry.java
index 77c13d8e..c9c5e90a 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/Entry.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/Entry.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -30,6 +30,7 @@ import java.io.Externalizable;
* represent a node or a data object.
*
* @author Elke Achtert
+ * @apiviz.excludeSubtypes
*/
public interface Entry extends Externalizable {
/**
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/IndexTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/IndexTree.java
index 13e91151..ee3bd5d6 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/IndexTree.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/IndexTree.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,8 +24,8 @@ package de.lmu.ifi.dbs.elki.index.tree;
*/
import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.statistics.LongStatistic;
import de.lmu.ifi.dbs.elki.persistent.PageFile;
-import de.lmu.ifi.dbs.elki.persistent.PageFileStatistics;
import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
/**
@@ -36,6 +36,7 @@ import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
* @apiviz.composedOf PageFile
* @apiviz.has Node oneway - - contains
* @apiviz.has TreeIndexHeader oneway
+ * @apiviz.excludeSubtypes
*
* @param <N> the type of Node used in the index
* @param <E> the type of Entry used in the index
@@ -91,10 +92,9 @@ public abstract class IndexTree<N extends Node<E>, E extends Entry> {
/**
* Initialize the tree if the page file already existed.
*/
- // FIXME: ensure this is called in all the appropriate places!
public void initialize() {
TreeIndexHeader header = createHeader();
- if(this.file.initialize(header)) {
+ if (this.file.initialize(header)) {
initializeFromFile(header, file);
}
rootEntry = createRootEntry();
@@ -115,7 +115,7 @@ public abstract class IndexTree<N extends Node<E>, E extends Entry> {
public final E getRootEntry() {
return rootEntry;
}
-
+
/**
* Page ID of the root entry.
*
@@ -124,7 +124,7 @@ public abstract class IndexTree<N extends Node<E>, E extends Entry> {
public final int getRootID() {
return getPageID(rootEntry);
}
-
+
/**
* Reads the root node of this index from the file.
*
@@ -133,7 +133,7 @@ public abstract class IndexTree<N extends Node<E>, E extends Entry> {
public N getRoot() {
return file.readPage(getPageID(rootEntry));
}
-
+
/**
* Test if a given ID is the root.
*
@@ -154,7 +154,7 @@ public abstract class IndexTree<N extends Node<E>, E extends Entry> {
if (entry.isLeafEntry()) {
throw new AbortException("Leafs do not have page ids!");
}
- return ((DirectoryEntry)entry).getPageID();
+ return ((DirectoryEntry) entry).getPageID();
}
/**
@@ -164,10 +164,9 @@ public abstract class IndexTree<N extends Node<E>, E extends Entry> {
* @return the node with the specified id
*/
public N getNode(int nodeID) {
- if(nodeID == getPageID(rootEntry)) {
+ if (nodeID == getPageID(rootEntry)) {
return getRoot();
- }
- else {
+ } else {
return file.readPage(nodeID);
}
}
@@ -181,7 +180,7 @@ public abstract class IndexTree<N extends Node<E>, E extends Entry> {
public final N getNode(E entry) {
return getNode(getPageID(entry));
}
-
+
/**
* Write a node to the backing storage.
*
@@ -223,7 +222,7 @@ public abstract class IndexTree<N extends Node<E>, E extends Entry> {
this.dirMinimum = header.getDirMinimum();
this.leafMinimum = header.getLeafMinimum();
- if(getLogger().isDebugging()) {
+ if (getLogger().isDebugging()) {
StringBuilder msg = new StringBuilder();
msg.append(getClass());
msg.append("\n file = ").append(file.getClass());
@@ -244,16 +243,13 @@ public abstract class IndexTree<N extends Node<E>, E extends Entry> {
// create empty root
createEmptyRoot(exampleLeaf);
- if(getLogger().isDebugging()) {
- StringBuilder msg = new StringBuilder();
- msg.append(getClass()).append("\n");
- msg.append(" file = ").append(file.getClass()).append("\n");
- msg.append(" maximum number of dir entries = ").append((dirCapacity - 1)).append("\n");
- msg.append(" minimum number of dir entries = ").append(dirMinimum).append("\n");
- msg.append(" maximum number of leaf entries = ").append((leafCapacity - 1)).append("\n");
- msg.append(" minimum number of leaf entries = ").append(leafMinimum).append("\n");
- msg.append(" root = ").append(getRoot());
- getLogger().debugFine(msg.toString());
+ final Logging log = getLogger();
+ if (log.isStatistics()) {
+ String cls = this.getClass().getName();
+ log.statistics(new LongStatistic(cls + ".directory.capacity", dirCapacity));
+ log.statistics(new LongStatistic(cls + ".directory.minfill", dirMinimum));
+ log.statistics(new LongStatistic(cls + ".leaf.capacity", leafCapacity));
+ log.statistics(new LongStatistic(cls + ".leaf.minfill", leafMinimum));
}
initialized = true;
@@ -265,7 +261,7 @@ public abstract class IndexTree<N extends Node<E>, E extends Entry> {
* @return the path to the root of this tree
*/
public final IndexTreePath<E> getRootPath() {
- return new IndexTreePath<E>(new TreeIndexPathComponent<E>(rootEntry, null));
+ return new IndexTreePath<>(new TreeIndexPathComponent<>(rootEntry, null));
}
/**
@@ -322,14 +318,12 @@ public abstract class IndexTree<N extends Node<E>, E extends Entry> {
}
/**
- * Get the index file page access statistics.
- *
- * @return access statistics
+ * Log some statistics, if enabled.
*/
- public PageFileStatistics getPageFileStatistics() {
- return file;
+ public void logStatistics() {
+ file.logStatistics();
}
-
+
/**
* Get the page size of the backing storage.
*
@@ -348,4 +342,4 @@ public abstract class IndexTree<N extends Node<E>, E extends Entry> {
protected PageFile<N> getFile() {
return file;
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/IndexTreePath.java b/src/de/lmu/ifi/dbs/elki/index/tree/IndexTreePath.java
index 2634ae07..d9534e91 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/IndexTreePath.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/IndexTreePath.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -63,7 +63,7 @@ public class IndexTreePath<E extends Entry> {
}
lastPathComponent = path.get(path.size() - 1);
if(path.size() > 1) {
- parentPath = new IndexTreePath<E>(path, path.size() - 1);
+ parentPath = new IndexTreePath<>(path, path.size() - 1);
}
}
@@ -106,7 +106,7 @@ public class IndexTreePath<E extends Entry> {
protected IndexTreePath(List<TreeIndexPathComponent<E>> path, int length) {
lastPathComponent = path.get(length - 1);
if(length > 1) {
- parentPath = new IndexTreePath<E>(path, length - 1);
+ parentPath = new IndexTreePath<>(path, length - 1);
}
}
@@ -117,7 +117,7 @@ public class IndexTreePath<E extends Entry> {
* @return an array of IndexPathComponent representing the IndexPath
*/
public List<TreeIndexPathComponent<E>> getPath() {
- List<TreeIndexPathComponent<E>> result = new ArrayList<TreeIndexPathComponent<E>>();
+ List<TreeIndexPathComponent<E>> result = new ArrayList<>();
for(IndexTreePath<E> path = this; path != null; path = path.parentPath) {
result.add(path.lastPathComponent);
@@ -262,8 +262,7 @@ public class IndexTreePath<E extends Entry> {
if(child == null) {
throw new NullPointerException("Null child not allowed");
}
-
- return new IndexTreePath<E>(this, child);
+ return new IndexTreePath<>(this, child);
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/LeafEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/LeafEntry.java
index c6eb1269..d020c8b1 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/LeafEntry.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/LeafEntry.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,6 +29,8 @@ import de.lmu.ifi.dbs.elki.database.ids.DBID;
* Leaf entry
*
* @author Erich Schubert
+ *
+ * @apiviz.excludeSubtypes
*/
public interface LeafEntry extends Entry {
/**
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/Node.java b/src/de/lmu/ifi/dbs/elki/index/tree/Node.java
index c288a1fe..9f393f52 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/Node.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/Node.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -35,6 +35,7 @@ import de.lmu.ifi.dbs.elki.persistent.Page;
* @author Elke Achtert
*
* @apiviz.composedOf Entry
+ * @apiviz.excludeSubtypes
*
* @param <E> the type of Entry used in the index
*/
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexFactory.java
deleted file mode 100644
index c40effe5..00000000
--- a/src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexFactory.java
+++ /dev/null
@@ -1,184 +0,0 @@
-package de.lmu.ifi.dbs.elki.index.tree;
-
-/*
- This file is part of ELKI:
- Environment for Developing KDD-Applications Supported by Index-Structures
-
- Copyright (C) 2012
- Ludwig-Maximilians-Universität München
- Lehr- und Forschungseinheit für Datenbanksysteme
- ELKI Development Team
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-import de.lmu.ifi.dbs.elki.database.relation.Relation;
-import de.lmu.ifi.dbs.elki.index.Index;
-import de.lmu.ifi.dbs.elki.index.IndexFactory;
-import de.lmu.ifi.dbs.elki.persistent.ExternalizablePage;
-import de.lmu.ifi.dbs.elki.persistent.LRUCache;
-import de.lmu.ifi.dbs.elki.persistent.MemoryPageFile;
-import de.lmu.ifi.dbs.elki.persistent.PageFile;
-import de.lmu.ifi.dbs.elki.persistent.PersistentPageFile;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterEqualConstraint;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.FileParameter;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.LongParameter;
-
-/**
- * Abstract base class for tree-based indexes.
- *
- * @author Erich Schubert
- *
- * @apiviz.stereotype factory,interface
- * @apiviz.has Index oneway - - «create»
- *
- * @param <O> Object type
- * @param <I> Index type
- */
-// TODO: actually, this class should be called PagedIndexFactory?
-public abstract class TreeIndexFactory<O, I extends Index> implements IndexFactory<O, I> {
- /**
- * Optional parameter that specifies the name of the file storing the index.
- * If this parameter is not set the index is hold in the main memory.
- * <p>
- * Key: {@code -treeindex.file}
- * </p>
- */
- public static final OptionID FILE_ID = new OptionID("treeindex.file", "The name of the file storing the index. " + "If this parameter is not set the index is hold in the main memory.");
-
- /**
- * Parameter to specify the size of a page in bytes, must be an integer
- * greater than 0.
- * <p>
- * Default value: {@code 4000}
- * </p>
- * <p>
- * Key: {@code -treeindex.pagesize}
- * </p>
- */
- public static final OptionID PAGE_SIZE_ID = new OptionID("treeindex.pagesize", "The size of a page in bytes.");
-
- /**
- * Parameter to specify the size of the cache in bytes, must be an integer
- * equal to or greater than 0.
- * <p>
- * Default value: {@link Integer#MAX_VALUE}
- * </p>
- * <p>
- * Key: {@code -treeindex.cachesize}
- * </p>
- */
- public static final OptionID CACHE_SIZE_ID = new OptionID("treeindex.cachesize", "The size of the cache in bytes.");
-
- /**
- * Holds the name of the file storing the index specified by {@link #FILE_ID},
- * null if {@link #FILE_ID} is not specified.
- */
- protected String fileName = null;
-
- /**
- * Holds the value of {@link #PAGE_SIZE_ID}.
- */
- protected int pageSize;
-
- /**
- * Holds the value of {@link #CACHE_SIZE_ID}.
- */
- protected long cacheSize;
-
- /**
- * Constructor.
- *
- * @param fileName
- * @param pageSize
- * @param cacheSize
- */
- public TreeIndexFactory(String fileName, int pageSize, long cacheSize) {
- super();
- this.fileName = fileName;
- this.pageSize = pageSize;
- this.cacheSize = cacheSize;
- }
-
- /**
- * Make the page file for this index.
- *
- * @param <N> page type
- * @param cls Class information
- * @return Page file
- */
- // FIXME: make this single-shot when filename is set!
- protected <N extends ExternalizablePage> PageFile<N> makePageFile(Class<N> cls) {
- final PageFile<N> inner;
- if (fileName == null) {
- inner = new MemoryPageFile<N>(pageSize);
- } else {
- inner = new PersistentPageFile<N>(pageSize, fileName, cls);
- }
- if (cacheSize >= Integer.MAX_VALUE) {
- return inner;
- }
- return new LRUCache<N>(cacheSize, inner);
- }
-
- @Override
- abstract public I instantiate(Relation<O> relation);
-
- /**
- * Parameterization class.
- *
- * @author Erich Schubert
- *
- * @apiviz.exclude
- */
- public abstract static class Parameterizer<O> extends AbstractParameterizer {
- protected String fileName = null;
-
- protected int pageSize;
-
- protected long cacheSize;
-
- @Override
- protected void makeOptions(Parameterization config) {
- super.makeOptions(config);
- FileParameter fileNameP = new FileParameter(FILE_ID, FileParameter.FileType.OUTPUT_FILE, true);
- if (config.grab(fileNameP)) {
- fileName = fileNameP.getValue().getPath();
- } else {
- fileName = null;
- }
-
- final IntParameter pageSizeP = new IntParameter(PAGE_SIZE_ID, 4000);
- pageSizeP.addConstraint(new GreaterConstraint(0));
- if (config.grab(pageSizeP)) {
- pageSize = pageSizeP.getValue();
- }
-
- // FIXME: long, but limited to int values?!?
- LongParameter cacheSizeP = new LongParameter(CACHE_SIZE_ID, Integer.MAX_VALUE);
- cacheSizeP.addConstraint(new GreaterEqualConstraint(0));
- if (config.grab(cacheSizeP)) {
- cacheSize = cacheSizeP.getValue();
- }
- }
-
- @Override
- protected abstract TreeIndexFactory<O, ?> makeInstance();
- }
-}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexHeader.java b/src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexHeader.java
index 017c3571..42688ef0 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexHeader.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexHeader.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -250,7 +250,7 @@ public class TreeIndexHeader extends DefaultPageHeader {
@SuppressWarnings("unchecked")
public Stack<Integer> readEmptyPages(RandomAccessFile file) throws IOException, ClassNotFoundException {
if(emptyPagesSize == 0) {
- return new Stack<Integer>();
+ return new Stack<>();
}
byte[] bytes = new byte[emptyPagesSize];
file.seek(file.length() - emptyPagesSize);
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexPathComponent.java b/src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexPathComponent.java
index d2800d54..1ef146cf 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexPathComponent.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexPathComponent.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/MetricalIndexTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/MetricalIndexTree.java
index b98841aa..2494eb39 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/MetricalIndexTree.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/MetricalIndexTree.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,7 +25,6 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical;
import java.util.List;
-import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.index.tree.Entry;
@@ -61,13 +60,6 @@ public abstract class MetricalIndexTree<O, D extends Distance<D>, N extends Node
public abstract DistanceFunction<? super O, D> getDistanceFunction();
/**
- * Returns the distance function of this metrical index.
- *
- * @return the distance function of this metrical index
- */
- public abstract DistanceQuery<O, D> getDistanceQuery();
-
- /**
* Returns a list of entries pointing to the leaf nodes of this spatial index.
*
* @return a list of entries pointing to the leaf nodes of this spatial index
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTree.java
index a7a063bd..61ca9116 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTree.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTree.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,73 +28,67 @@ import java.util.Collections;
import java.util.List;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
-import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
-import de.lmu.ifi.dbs.elki.distance.DistanceUtil;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.tree.BreadthFirstEnumeration;
-import de.lmu.ifi.dbs.elki.index.tree.DistanceEntry;
import de.lmu.ifi.dbs.elki.index.tree.IndexTreePath;
import de.lmu.ifi.dbs.elki.index.tree.TreeIndexPathComponent;
import de.lmu.ifi.dbs.elki.index.tree.metrical.MetricalIndexTree;
-import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.split.Assignments;
-import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.split.MLBDistSplit;
-import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.split.MTreeSplit;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.split.Assignments;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.split.DistanceEntry;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.statistics.Counter;
+import de.lmu.ifi.dbs.elki.logging.statistics.LongStatistic;
import de.lmu.ifi.dbs.elki.persistent.PageFile;
-import de.lmu.ifi.dbs.elki.persistent.PageFileUtil;
+import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleIntPair;
/**
* Abstract super class for all M-Tree variants.
*
* @author Elke Achtert
*
- * @apiviz.has SplitResult oneway - - computes
+ * @apiviz.composedOf MTreeSettings
+ * @apiviz.composedOf Statistics
* @apiviz.has AbstractMTreeNode oneway - - contains
+ * @apiviz.excludeSubtypes
*
* @param <O> the type of DatabaseObject to be stored in the metrical index
* @param <D> the type of Distance used in the metrical index
* @param <N> the type of MetricalNode used in the metrical index
* @param <E> the type of MetricalEntry used in the metrical index
+ * @param <S> the type to store settings in.
*/
-public abstract class AbstractMTree<O, D extends Distance<D>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry<D>> extends MetricalIndexTree<O, D, N, E> {
+public abstract class AbstractMTree<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry, S extends MTreeSettings<O, D, N, E>> extends MetricalIndexTree<O, D, N, E> {
/**
* Debugging flag: do extra integrity checks.
*/
protected static final boolean EXTRA_INTEGRITY_CHECKS = false;
/**
- * Holds the instance of the trees distance function.
+ * Tree settings.
*/
- protected DistanceFunction<O, D> distanceFunction;
+ protected S settings;
/**
- * The distance query.
+ * For counting the number of distance computations.
*/
- protected DistanceQuery<O, D> distanceQuery;
+ public Statistics statistics = new Statistics();
/**
* Constructor.
*
* @param pagefile Page file
- * @param distanceQuery Distance query
- * @param distanceFunction Distance function
+ * @param settings Tree settings
*/
- public AbstractMTree(PageFile<N> pagefile, DistanceQuery<O, D> distanceQuery, DistanceFunction<O, D> distanceFunction) {
+ public AbstractMTree(PageFile<N> pagefile, S settings) {
super(pagefile);
- this.distanceQuery = distanceQuery;
- this.distanceFunction = distanceFunction;
+ this.settings = settings;
}
@Override
- public final DistanceFunction<O, D> getDistanceFunction() {
- return distanceFunction;
- }
-
- @Override
- public final DistanceQuery<O, D> getDistanceQuery() {
- return distanceQuery;
+ public final DistanceFunction<? super O, D> getDistanceFunction() {
+ return settings.distanceFunction;
}
/**
@@ -103,7 +97,7 @@ public abstract class AbstractMTree<O, D extends Distance<D>, N extends Abstract
* @return the distance factory used
*/
public final D getDistanceFactory() {
- return distanceFunction.getDistanceFactory();
+ return settings.distanceFunction.getDistanceFactory();
}
/**
@@ -131,7 +125,7 @@ public abstract class AbstractMTree<O, D extends Distance<D>, N extends Abstract
}
}
- BreadthFirstEnumeration<N, E> enumeration = new BreadthFirstEnumeration<N, E>(this, getRootPath());
+ BreadthFirstEnumeration<N, E> enumeration = new BreadthFirstEnumeration<>(this, getRootPath());
while (enumeration.hasMoreElements()) {
IndexTreePath<E> path = enumeration.nextElement();
E entry = path.getLastPathComponent().getEntry();
@@ -158,7 +152,7 @@ public abstract class AbstractMTree<O, D extends Distance<D>, N extends Abstract
result.append(leafNodes).append(" Leaf Nodes \n");
result.append(objects).append(" Objects \n");
- PageFileUtil.appendPageFileStatistics(result, getPageFileStatistics());
+ // PageFileUtil.appendPageFileStatistics(result, getPageFileStatistics());
return result.toString();
}
@@ -180,14 +174,14 @@ public abstract class AbstractMTree<O, D extends Distance<D>, N extends Abstract
}
// choose subtree for insertion
- IndexTreePath<E> subtree = choosePath(entry, getRootPath());
+ IndexTreePath<E> subtree = settings.insertStrategy.choosePath(this, entry);
if (getLogger().isDebugging()) {
getLogger().debugFine("insertion-subtree " + subtree + "\n");
}
// determine parent distance
E parentEntry = subtree.getLastPathComponent().getEntry();
- D parentDistance = distance(parentEntry.getRoutingObjectID(), entry.getRoutingObjectID());
+ double parentDistance = distance(parentEntry.getRoutingObjectID(), entry.getRoutingObjectID()).doubleValue();
entry.setParentDistance(parentDistance);
// create leaf entry and do pre insert
@@ -232,63 +226,6 @@ public abstract class AbstractMTree<O, D extends Distance<D>, N extends Abstract
}
/**
- * Chooses the best path of the specified subtree for insertion of the given
- * object.
- *
- * @param object the entry to search
- * @param subtree the subtree to be tested for insertion
- * @return the path of the appropriate subtree to insert the given object
- */
- private IndexTreePath<E> choosePath(E object, IndexTreePath<E> subtree) {
- N node = getNode(subtree.getLastPathComponent().getEntry());
-
- // leaf
- if (node.isLeaf()) {
- return subtree;
- }
-
- DistanceEntry<D, E> bestCandidate;
- D enlarge; // Track best enlargement - null for no enlargement needed.
- // Initialize from first:
- {
- E entry = node.getEntry(0);
- D distance = distance(object.getRoutingObjectID(), entry.getRoutingObjectID());
- bestCandidate = new DistanceEntry<D, E>(entry, distance, 0);
- if (distance.compareTo(entry.getCoveringRadius()) <= 0) {
- enlarge = null;
- } else {
- enlarge = distance.minus(entry.getCoveringRadius());
- }
- }
-
- // Iterate over remaining
- for (int i = 1; i < node.getNumEntries(); i++) {
- E entry = node.getEntry(i);
- D distance = distance(object.getRoutingObjectID(), entry.getRoutingObjectID());
-
- if (distance.compareTo(entry.getCoveringRadius()) <= 0) {
- if (enlarge != null || distance.compareTo(bestCandidate.getDistance()) < 0) {
- bestCandidate = new DistanceEntry<D, E>(entry, distance, i);
- enlarge = null;
- }
- } else if (enlarge != null) {
- D enlrg = distance.minus(entry.getCoveringRadius());
- if (enlrg.compareTo(enlarge) < 0) {
- bestCandidate = new DistanceEntry<D, E>(entry, distance, i);
- enlarge = enlrg;
- }
- }
- }
-
- // Apply enlargement
- if (enlarge != null) {
- bestCandidate.getEntry().setCoveringRadius(enlarge);
- }
-
- return choosePath(object, subtree.pathByAddingChild(new TreeIndexPathComponent<E>(bestCandidate.getEntry(), bestCandidate.getIndex())));
- }
-
- /**
* Sorts the entries of the specified node according to their minimum distance
* to the specified object.
*
@@ -296,44 +233,16 @@ public abstract class AbstractMTree<O, D extends Distance<D>, N extends Abstract
* @param q the id of the object
* @return a list of the sorted entries
*/
- protected final List<DistanceEntry<D, E>> getSortedEntries(N node, DBID q) {
- List<DistanceEntry<D, E>> result = new ArrayList<DistanceEntry<D, E>>();
-
- for (int i = 0; i < node.getNumEntries(); i++) {
- E entry = node.getEntry(i);
- D distance = distance(entry.getRoutingObjectID(), q);
- D radius = entry.getCoveringRadius();
- D minDist = radius.compareTo(distance) > 0 ? getDistanceFactory().nullDistance() : distance.minus(radius);
-
- result.add(new DistanceEntry<D, E>(entry, minDist, i));
- }
-
- Collections.sort(result);
- return result;
- }
-
- /**
- * Sorts the entries of the specified node according to their minimum distance
- * to the specified objects.
- *
- * @param node the node
- * @param ids the ids of the objects
- * @return a list of the sorted entries
- */
- protected final List<DistanceEntry<D, E>> getSortedEntries(N node, DBIDs ids) {
- List<DistanceEntry<D, E>> result = new ArrayList<DistanceEntry<D, E>>();
+ protected final List<DoubleIntPair> getSortedEntries(N node, DBID q) {
+ List<DoubleIntPair> result = new ArrayList<>();
for (int i = 0; i < node.getNumEntries(); i++) {
E entry = node.getEntry(i);
- D radius = entry.getCoveringRadius();
+ double distance = distance(entry.getRoutingObjectID(), q).doubleValue();
+ double radius = entry.getCoveringRadius();
+ double minDist = (radius > distance) ? 0.0 : distance - radius;
- D minMinDist = getDistanceFactory().infiniteDistance();
- for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
- D distance = distanceQuery.distance(entry.getRoutingObjectID(), iter);
- D minDist = radius.compareTo(distance) > 0 ? getDistanceFactory().nullDistance() : distance.minus(radius);
- minMinDist = DistanceUtil.min(minMinDist, minDist);
- }
- result.add(new DistanceEntry<D, E>(entry, minMinDist, i));
+ result.add(new DoubleIntPair(minDist, i));
}
Collections.sort(result);
@@ -347,11 +256,17 @@ public abstract class AbstractMTree<O, D extends Distance<D>, N extends Abstract
* @param id2 the second id
* @return the distance between the two specified ids
*/
- protected final D distance(DBID id1, DBID id2) {
- if (id1 == null || id2 == null) {
- return getDistanceFactory().undefinedDistance();
- }
- return distanceQuery.distance(id1, id2);
+ public abstract D distance(DBIDRef id1, DBIDRef id2);
+
+ /**
+ * Returns the distance between the routing object of two entries.
+ *
+ * @param e1 First entry
+ * @param e2 Second entry
+ * @return the distance between the two routing objects
+ */
+ public final D distance(E e1, E e2) {
+ return distance(e1.getRoutingObjectID(), e2.getRoutingObjectID());
}
/**
@@ -363,38 +278,7 @@ public abstract class AbstractMTree<O, D extends Distance<D>, N extends Abstract
* the routing object of the parent node
* @return the newly created directory entry
*/
- protected abstract E createNewDirectoryEntry(N node, DBID routingObjectID, D parentDistance);
-
- /**
- * Splits the specified node and returns the split result.
- *
- * @param node the node to be split
- * @return the split result
- */
- private SplitResult split(N node) {
- // do the split
- // todo split stratgey
- MTreeSplit<O, D, N, E> split = new MLBDistSplit<O, D, N, E>(node, distanceQuery);
- Assignments<D, E> assignments = split.getAssignments();
- final N newNode;
- if (node.isLeaf()) {
- newNode = createNewLeafNode();
- } else {
- newNode = createNewDirectoryNode();
- }
- node.splitTo(newNode, assignments.getFirstAssignments(), assignments.getSecondAssignments());
-
- // write changes to file
- writeNode(node);
- writeNode(newNode);
-
- if (getLogger().isDebugging()) {
- String msg = "Split Node " + node.getPageID() + " (" + this.getClass() + ")\n" + " newNode " + newNode.getPageID() + "\n" + " firstPromoted " + assignments.getFirstRoutingObject() + "\n" + " firstAssignments(" + node.getPageID() + ") " + assignments.getFirstAssignments() + "\n" + " firstCR " + assignments.getFirstCoveringRadius() + "\n" + " secondPromoted " + assignments.getSecondRoutingObject() + "\n" + " secondAssignments(" + newNode.getPageID() + ") " + assignments.getSecondAssignments() + "\n" + " secondCR " + assignments.getSecondCoveringRadius() + "\n";
- getLogger().debugFine(msg);
- }
-
- return new SplitResult(split, newNode);
- }
+ protected abstract E createNewDirectoryEntry(N node, DBID routingObjectID, double parentDistance);
/**
* Adjusts the tree after insertion of some nodes.
@@ -412,15 +296,39 @@ public abstract class AbstractMTree<O, D extends Distance<D>, N extends Abstract
// overflow in node; split the node
if (hasOverflow(node)) {
- SplitResult splitResult = split(node);
- N splitNode = splitResult.newNode;
- Assignments<D, E> assignments = splitResult.split.getAssignments();
+ // do the split
+ Assignments<E> assignments = settings.splitStrategy.split(this, node);
+ final N newNode = node.isLeaf() ? createNewLeafNode() : createNewDirectoryNode();
+
+ List<E> entries1 = new ArrayList<>(assignments.getFirstAssignments().size());
+ List<E> entries2 = new ArrayList<>(assignments.getSecondAssignments().size());
+ // Store final parent distances:
+ for (DistanceEntry<E> ent : assignments.getFirstAssignments()) {
+ final E e = ent.getEntry();
+ e.setParentDistance(ent.getDistance());
+ entries1.add(e);
+ }
+ for (DistanceEntry<E> ent : assignments.getSecondAssignments()) {
+ final E e = ent.getEntry();
+ e.setParentDistance(ent.getDistance());
+ entries2.add(e);
+ }
+ node.splitTo(newNode, entries1, entries2);
+
+ // write changes to file
+ writeNode(node);
+ writeNode(newNode);
+
+ if (getLogger().isDebugging()) {
+ String msg = "Split Node " + node.getPageID() + " (" + this.getClass() + ")\n" + " newNode " + newNode.getPageID() + "\n" + " firstPromoted " + assignments.getFirstRoutingObject() + "\n" + " firstAssignments(" + node.getPageID() + ") " + assignments.getFirstAssignments() + "\n" + " firstCR " + assignments.getFirstCoveringRadius() + "\n" + " secondPromoted " + assignments.getSecondRoutingObject() + "\n" + " secondAssignments(" + newNode.getPageID() + ") " + assignments.getSecondAssignments() + "\n" + " secondCR " + assignments.getSecondCoveringRadius() + "\n";
+ getLogger().debugFine(msg);
+ }
// if root was split: create a new root that points the two split
// nodes
if (isRoot(node)) {
// FIXME: stimmen die parentDistance der Kinder in node & splitNode?
- IndexTreePath<E> newRootPath = createNewRoot(node, splitNode, assignments.getFirstRoutingObject(), assignments.getSecondRoutingObject());
+ IndexTreePath<E> newRootPath = createNewRoot(node, newNode, assignments.getFirstRoutingObject(), assignments.getSecondRoutingObject());
adjustTree(newRootPath);
}
// node is not root
@@ -431,13 +339,13 @@ public abstract class AbstractMTree<O, D extends Distance<D>, N extends Abstract
if (getLogger().isDebugging()) {
getLogger().debugFine("parent " + parent);
}
- D parentDistance2 = distance(parentEntry.getRoutingObjectID(), assignments.getSecondRoutingObject());
+ double parentDistance2 = distance(parentEntry.getRoutingObjectID(), assignments.getSecondRoutingObject()).doubleValue();
// logger.warning("parent: "+parent.toString()+" split: " +
// splitNode.toString()+ " dist:"+parentDistance2);
- parent.addDirectoryEntry(createNewDirectoryEntry(splitNode, assignments.getSecondRoutingObject(), parentDistance2));
+ parent.addDirectoryEntry(createNewDirectoryEntry(newNode, assignments.getSecondRoutingObject(), parentDistance2));
// adjust the entry representing the (old) node, that has been split
- D parentDistance1 = distance(parentEntry.getRoutingObjectID(), assignments.getFirstRoutingObject());
+ double parentDistance1 = distance(parentEntry.getRoutingObjectID(), assignments.getFirstRoutingObject()).doubleValue();
// logger.warning("parent: "+parent.toString()+" node: " +
// node.toString()+ " dist:"+parentDistance1);
node.adjustEntry(parent.getEntry(nodeIndex), assignments.getFirstRoutingObject(), parentDistance1, this);
@@ -517,8 +425,8 @@ public abstract class AbstractMTree<O, D extends Distance<D>, N extends Abstract
// firstRoutingObjectID);
// D parentDistance2 = distance(getRootEntry().getRoutingObjectID(),
// secondRoutingObjectID);
- E oldRootEntry = createNewDirectoryEntry(oldRoot, firstRoutingObjectID, null);
- E newRootEntry = createNewDirectoryEntry(newNode, secondRoutingObjectID, null);
+ E oldRootEntry = createNewDirectoryEntry(oldRoot, firstRoutingObjectID, 0.);
+ E newRootEntry = createNewDirectoryEntry(newNode, secondRoutingObjectID, 0.);
root.addDirectoryEntry(oldRootEntry);
root.addDirectoryEntry(newRootEntry);
@@ -536,41 +444,13 @@ public abstract class AbstractMTree<O, D extends Distance<D>, N extends Abstract
getLogger().debugFine(msg);
}
- return new IndexTreePath<E>(new TreeIndexPathComponent<E>(getRootEntry(), null));
- }
-
- /**
- * Encapsulates a split object and the newly created node.
- *
- * @apiviz.composedOf MTreeSplit
- */
- private class SplitResult {
- /**
- * Split used
- */
- protected MTreeSplit<O, D, N, E> split;
-
- /**
- * New sibling
- */
- protected N newNode;
-
- /**
- * Constructor.
- *
- * @param split Split that was used
- * @param newNode New sibling
- */
- public SplitResult(MTreeSplit<O, D, N, E> split, N newNode) {
- this.split = split;
- this.newNode = newNode;
- }
+ return new IndexTreePath<>(new TreeIndexPathComponent<>(getRootEntry(), null));
}
@Override
public List<E> getLeaves() {
- List<E> result = new ArrayList<E>();
- BreadthFirstEnumeration<N, E> enumeration = new BreadthFirstEnumeration<N, E>(this, getRootPath());
+ List<E> result = new ArrayList<>();
+ BreadthFirstEnumeration<N, E> enumeration = new BreadthFirstEnumeration<>(this, getRootPath());
while (enumeration.hasMoreElements()) {
IndexTreePath<E> path = enumeration.nextElement();
E entry = path.getLastPathComponent().getEntry();
@@ -603,4 +483,93 @@ public abstract class AbstractMTree<O, D extends Distance<D>, N extends Abstract
}
return levels;
}
+
+ @Override
+ public void logStatistics() {
+ super.logStatistics();
+ Logging log = getLogger();
+ if (log.isStatistics()) {
+ log.statistics(new LongStatistic(this.getClass().getName() + ".height", getHeight()));
+ statistics.logStatistics();
+ }
+ }
+
+ /**
+ * Class for tracking some statistics.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.composedOf Counter
+ */
+ public class Statistics {
+ /**
+ * For counting the number of distance computations.
+ */
+ protected final Counter distanceCalcs;
+
+ /**
+ * For counting the number of knn queries answered.
+ */
+ protected final Counter knnQueries;
+
+ /**
+ * For counting the number of range queries answered.
+ */
+ protected final Counter rangeQueries;
+
+ /**
+ * Constructor.
+ */
+ public Statistics() {
+ super();
+ Logging log = getLogger();
+ distanceCalcs = log.isStatistics() ? log.newCounter(this.getClass().getName() + ".distancecalcs") : null;
+ knnQueries = log.isStatistics() ? log.newCounter(this.getClass().getName() + ".knnqueries") : null;
+ rangeQueries = log.isStatistics() ? log.newCounter(this.getClass().getName() + ".rangequeries") : null;
+ }
+
+ /**
+ * Count a distance computation.
+ */
+ public void countDistanceCalculation() {
+ if (distanceCalcs != null) {
+ distanceCalcs.increment();
+ }
+ }
+
+ /**
+ * Count a knn query invocation.
+ */
+ public void countKNNQuery() {
+ if (knnQueries != null) {
+ knnQueries.increment();
+ }
+ }
+
+ /**
+ * Count a range query invocation.
+ */
+ public void countRangeQuery() {
+ if (rangeQueries != null) {
+ rangeQueries.increment();
+ }
+ }
+
+ /**
+ * Log the statistics.
+ */
+ public void logStatistics() {
+ Logging log = getLogger();
+ if (statistics.distanceCalcs != null) {
+ log.statistics(statistics.distanceCalcs);
+ }
+ if (statistics.knnQueries != null) {
+ log.statistics(statistics.knnQueries);
+ }
+ if (statistics.rangeQueries != null) {
+ log.statistics(statistics.rangeQueries);
+ }
+ }
+ }
+
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTreeFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTreeFactory.java
index 3769a562..7a0baa8a 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTreeFactory.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTreeFactory.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,10 +25,15 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants;
import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.Index;
-import de.lmu.ifi.dbs.elki.index.tree.TreeIndexFactory;
+import de.lmu.ifi.dbs.elki.index.PagedIndexFactory;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.insert.MTreeInsert;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.insert.MinimumEnlargementInsert;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.split.MMRadSplit;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.split.MTreeSplit;
+import de.lmu.ifi.dbs.elki.persistent.PageFileFactory;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
@@ -40,6 +45,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
*
* @apiviz.stereotype factory
* @apiviz.uses AbstractMTree oneway - - «create»
+ * @apiviz.excludeSubtypes
*
* @param <O> Object type
* @param <D> Distance type
@@ -47,43 +53,26 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
* @param <E> Entry type
* @param <I> Index type
*/
-public abstract class AbstractMTreeFactory<O, D extends Distance<D>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry<D>, I extends AbstractMTree<O, D, N, E> & Index> extends TreeIndexFactory<O, I> {
+public abstract class AbstractMTreeFactory<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry, I extends AbstractMTree<O, D, N, E, S> & Index, S extends MTreeSettings<O, D, N, E>> extends PagedIndexFactory<O, I> {
/**
- * Parameter to specify the distance function to determine the distance
- * between database objects, must extend
- * {@link de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction}.
- * <p>
- * Key: {@code -mtree.distancefunction}
- * </p>
- * <p>
- * Default value:
- * {@link de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction}
- * </p>
+ * Tree settings.
*/
- public static final OptionID DISTANCE_FUNCTION_ID = new OptionID("mtree.distancefunction", "Distance function to determine the distance between database objects.");
-
- /**
- * Holds the instance of the distance function specified by
- * {@link #DISTANCE_FUNCTION_ID}.
- */
- protected DistanceFunction<O, D> distanceFunction;
+ protected S settings;
/**
* Constructor.
*
- * @param fileName
- * @param pageSize
- * @param cacheSize
- * @param distanceFunction
+ * @param pageFileFactory Data storage
+ * @param settings Tree settings
*/
- public AbstractMTreeFactory(String fileName, int pageSize, long cacheSize, DistanceFunction<O, D> distanceFunction) {
- super(fileName, pageSize, cacheSize);
- this.distanceFunction = distanceFunction;
+ public AbstractMTreeFactory(PageFileFactory<?> pageFileFactory, S settings) {
+ super(pageFileFactory);
+ this.settings = settings;
}
@Override
public TypeInformation getInputTypeRestriction() {
- return distanceFunction.getInputTypeRestriction();
+ return settings.distanceFunction.getInputTypeRestriction();
}
/**
@@ -93,19 +82,63 @@ public abstract class AbstractMTreeFactory<O, D extends Distance<D>, N extends A
*
* @apiviz.exclude
*/
- public abstract static class Parameterizer<O, D extends Distance<D>> extends TreeIndexFactory.Parameterizer<O> {
- protected DistanceFunction<O, D> distanceFunction = null;
+ public abstract static class Parameterizer<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry, S extends MTreeSettings<O, D, N, E>> extends PagedIndexFactory.Parameterizer<O> {
+ /**
+ * Parameter to specify the distance function to determine the distance
+ * between database objects, must extend
+ * {@link de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction}.
+ * <p>
+ * Key: {@code -mtree.distancefunction}
+ * </p>
+ * <p>
+ * Default value:
+ * {@link de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction}
+ * </p>
+ */
+ public static final OptionID DISTANCE_FUNCTION_ID = new OptionID("mtree.distancefunction", "Distance function to determine the distance between database objects.");
+
+ /**
+ * Parameter to specify the splitting strategy to construct the tree.
+ * <p>
+ * Key: {@code -mtree.split}
+ * </p>
+ */
+ public static final OptionID SPLIT_STRATEGY_ID = new OptionID("mtree.split", "Split strategy to use for constructing the M-tree.");
+
+ /**
+ * Parameter to specify the insertion strategy to construct the tree.
+ * <p>
+ * Key: {@code -mtree.insert}
+ * </p>
+ */
+ public static final OptionID INSERT_STRATEGY_ID = new OptionID("mtree.insert", "Insertion strategy to use for constructing the M-tree.");
+
+ /**
+ * Tree settings.
+ */
+ protected S settings;
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- ObjectParameter<DistanceFunction<O, D>> distanceFunctionP = new ObjectParameter<DistanceFunction<O, D>>(DISTANCE_FUNCTION_ID, DistanceFunction.class, EuclideanDistanceFunction.class);
- if(config.grab(distanceFunctionP)) {
- distanceFunction = distanceFunctionP.instantiateClass(config);
+ settings = makeSettings();
+ ObjectParameter<DistanceFunction<O, D>> distanceFunctionP = new ObjectParameter<>(DISTANCE_FUNCTION_ID, DistanceFunction.class, EuclideanDistanceFunction.class);
+ if (config.grab(distanceFunctionP)) {
+ settings.distanceFunction = distanceFunctionP.instantiateClass(config);
+ }
+ ObjectParameter<MTreeSplit<O, D, N, E>> splitStrategyP = new ObjectParameter<>(SPLIT_STRATEGY_ID, MTreeSplit.class, MMRadSplit.class);
+ if (config.grab(splitStrategyP)) {
+ settings.splitStrategy = splitStrategyP.instantiateClass(config);
+ }
+ ObjectParameter<MTreeInsert<O, D, N, E>> insertStrategyP = new ObjectParameter<>(INSERT_STRATEGY_ID, MTreeInsert.class, MinimumEnlargementInsert.class);
+ if (config.grab(insertStrategyP)) {
+ settings.insertStrategy = insertStrategyP.instantiateClass(config);
}
}
+ abstract protected S makeSettings();
+
@Override
- protected abstract AbstractMTreeFactory<O, D, ?, ?, ?> makeInstance();
+ protected abstract AbstractMTreeFactory<O, D, N, E, ?, ?> makeInstance();
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTreeNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTreeNode.java
index 85a9571d..1c1f486c 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTreeNode.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTreeNode.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,8 +26,6 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants;
import java.util.logging.Logger;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.distance.DistanceUtil;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.tree.AbstractNode;
import de.lmu.ifi.dbs.elki.logging.LoggingConfiguration;
@@ -38,13 +36,14 @@ import de.lmu.ifi.dbs.elki.logging.LoggingConfiguration;
* @author Elke Achtert
*
* @apiviz.has MTreeEntry oneway - - contains
+ * @apiviz.excludeSubtypes
*
* @param <O> the type of DatabaseObject to be stored in the M-Tree
* @param <D> the type of Distance used in the M-Tree
* @param <N> the type of AbstractMTreeNode used in the M-Tree
* @param <E> the type of MetricalEntry used in the M-Tree
*/
-public abstract class AbstractMTreeNode<O, D extends Distance<D>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry<D>> extends AbstractNode<E> {
+public abstract class AbstractMTreeNode<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry> extends AbstractNode<E> {
/**
* Empty constructor for Externalizable interface.
*/
@@ -74,14 +73,14 @@ public abstract class AbstractMTreeNode<O, D extends Distance<D>, N extends Abst
* the routing object of the parent node
* @param mTree the M-Tree object holding this node
*/
- public void adjustEntry(E entry, DBID routingObjectID, D parentDistance, AbstractMTree<O, D, N, E> mTree) {
+ public void adjustEntry(E entry, DBID routingObjectID, double parentDistance, AbstractMTree<O, D, N, E, ?> mTree) {
entry.setRoutingObjectID(routingObjectID);
entry.setParentDistance(parentDistance);
entry.setCoveringRadius(coveringRadius(entry.getRoutingObjectID(), mTree));
- for(int i = 0; i < getNumEntries(); i++) {
+ for (int i = 0; i < getNumEntries(); i++) {
E childEntry = getEntry(i);
- D dist = mTree.distance(routingObjectID, childEntry.getRoutingObjectID());
+ double dist = mTree.distance(routingObjectID, childEntry.getRoutingObjectID()).doubleValue();
childEntry.setParentDistance(dist);
}
}
@@ -93,17 +92,12 @@ public abstract class AbstractMTreeNode<O, D extends Distance<D>, N extends Abst
* @param mTree the M-Tree
* @return the covering radius of this node
*/
- public D coveringRadius(DBID routingObjectID, AbstractMTree<O, D, N, E> mTree) {
- D coveringRadius = mTree.getDistanceFactory().nullDistance();
- for(int i = 0; i < getNumEntries(); i++) {
+ public double coveringRadius(DBID routingObjectID, AbstractMTree<O, D, N, E, ?> mTree) {
+ double coveringRadius = 0.;
+ for (int i = 0; i < getNumEntries(); i++) {
E entry = getEntry(i);
- D distance = mTree.distance(entry.getRoutingObjectID(), routingObjectID);
- // extend by the other objects covering radius, if non-null
- D d2 = entry.getCoveringRadius();
- if(d2 != null) {
- distance = distance.plus(d2);
- }
- coveringRadius = DistanceUtil.max(coveringRadius, distance);
+ double distance = mTree.distance(entry.getRoutingObjectID(), routingObjectID).doubleValue() + entry.getCoveringRadius();
+ coveringRadius = Math.max(coveringRadius, distance);
}
return coveringRadius;
}
@@ -115,48 +109,47 @@ public abstract class AbstractMTreeNode<O, D extends Distance<D>, N extends Abst
* @param entry the entry representing this node
*/
@SuppressWarnings("unchecked")
- public final void integrityCheck(AbstractMTree<O, D, N, E> mTree, E entry) {
+ public final void integrityCheck(AbstractMTree<O, D, N, E, ?> mTree, E entry) {
// leaf node
- if(isLeaf()) {
- for(int i = 0; i < getCapacity(); i++) {
+ if (isLeaf()) {
+ for (int i = 0; i < getCapacity(); i++) {
E e = getEntry(i);
- if(i < getNumEntries() && e == null) {
+ if (i < getNumEntries() && e == null) {
throw new RuntimeException("i < numEntries && entry == null");
}
- if(i >= getNumEntries() && e != null) {
+ if (i >= getNumEntries() && e != null) {
throw new RuntimeException("i >= numEntries && entry != null");
}
}
}
-
// dir node
else {
N tmp = mTree.getNode(getEntry(0));
boolean childIsLeaf = tmp.isLeaf();
- for(int i = 0; i < getCapacity(); i++) {
+ for (int i = 0; i < getCapacity(); i++) {
E e = getEntry(i);
- if(i < getNumEntries() && e == null) {
+ if (i < getNumEntries() && e == null) {
throw new RuntimeException("i < numEntries && entry == null");
}
- if(i >= getNumEntries() && e != null) {
+ if (i >= getNumEntries() && e != null) {
throw new RuntimeException("i >= numEntries && entry != null");
}
- if(e != null) {
+ if (e != null) {
N node = mTree.getNode(e);
- if(childIsLeaf && !node.isLeaf()) {
- for(int k = 0; k < getNumEntries(); k++) {
+ if (childIsLeaf && !node.isLeaf()) {
+ for (int k = 0; k < getNumEntries(); k++) {
mTree.getNode(getEntry(k));
}
throw new RuntimeException("Wrong Child in " + this + " at " + i);
}
- if(!childIsLeaf && node.isLeaf()) {
+ if (!childIsLeaf && node.isLeaf()) {
throw new RuntimeException("Wrong Child: child id no leaf, but node is leaf!");
}
@@ -166,7 +159,7 @@ public abstract class AbstractMTreeNode<O, D extends Distance<D>, N extends Abst
}
}
- if(LoggingConfiguration.DEBUG) {
+ if (LoggingConfiguration.DEBUG) {
Logger.getLogger(this.getClass().getName()).fine("DirNode " + getPageID() + " ok!");
}
}
@@ -181,30 +174,19 @@ public abstract class AbstractMTreeNode<O, D extends Distance<D>, N extends Abst
* @param index the index of the entry in the parents child arry
* @param mTree the M-Tree holding this node
*/
- protected void integrityCheckParameters(E parentEntry, N parent, int index, AbstractMTree<O, D, N, E> mTree) {
+ protected void integrityCheckParameters(E parentEntry, N parent, int index, AbstractMTree<O, D, N, E, ?> mTree) {
// test if parent distance is correctly set
E entry = parent.getEntry(index);
- D parentDistance = mTree.distance(entry.getRoutingObjectID(), parentEntry.getRoutingObjectID());
- if(!entry.getParentDistance().equals(parentDistance)) {
- String soll = parentDistance.toString();
- String ist = entry.getParentDistance().toString();
- throw new RuntimeException("Wrong parent distance in node " + parent.getPageID() + " at index " + index + " (child " + entry + ")" + "\nsoll: " + soll + ",\n ist: " + ist);
+ double parentDistance = mTree.distance(entry.getRoutingObjectID(), parentEntry.getRoutingObjectID()).doubleValue();
+ if (Math.abs(entry.getParentDistance() - parentDistance) > 1E-10) {
+ throw new RuntimeException("Wrong parent distance in node " + parent.getPageID() + " at index " + index + " (child " + entry + ")" + "\nsoll: " + parentDistance + ",\n ist: " + entry.getParentDistance());
}
// test if covering radius is correctly set
- D mincover = parentDistance.plus(entry.getCoveringRadius());
- if(parentEntry.getCoveringRadius().compareTo(mincover) < 0) {
- String msg = "pcr < pd + cr \n" + parentEntry.getCoveringRadius() + " < " + parentDistance + " + " + entry.getCoveringRadius() + "in node " + parent.getPageID() + " at index " + index + " (child " + entry + "):\n" + "dist(" + entry.getRoutingObjectID() + " - " + parentEntry.getRoutingObjectID() + ")" + " > cr(" + entry + ")";
-
- // throw new RuntimeException(msg);
- if(parentDistance instanceof NumberDistance<?, ?>) {
- double d1 = Double.parseDouble(parentDistance.toString());
- double d2 = Double.parseDouble(entry.getCoveringRadius().toString());
- if(Math.abs(d1 - d2) > 0.000000001) {
- throw new RuntimeException(msg);
- }
- }
- else {
+ double mincover = parentDistance + entry.getCoveringRadius();
+ if (parentEntry.getCoveringRadius() < mincover) {
+ if (Math.abs(parentDistance - entry.getCoveringRadius()) > 1e-10) {
+ String msg = "pcr < pd + cr \n" + parentEntry.getCoveringRadius() + " < " + parentDistance + " + " + entry.getCoveringRadius() + "in node " + parent.getPageID() + " at index " + index + " (child " + entry + "):\n" + "dist(" + entry.getRoutingObjectID() + " - " + parentEntry.getRoutingObjectID() + ")" + " > cr(" + entry + ")";
throw new RuntimeException(msg);
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeDirectoryEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeDirectoryEntry.java
index 3902973f..92d0a7ea 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeDirectoryEntry.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeDirectoryEntry.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,7 +29,6 @@ import java.io.ObjectOutput;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.index.tree.AbstractDirectoryEntry;
/**
@@ -39,10 +38,9 @@ import de.lmu.ifi.dbs.elki.index.tree.AbstractDirectoryEntry;
* the routing object of the entry to its parent's routing object in the M-Tree.
*
* @author Elke Achtert
- * @param <D> the type of Distance used in the M-Tree
*/
-public class MTreeDirectoryEntry<D extends Distance<D>> extends AbstractDirectoryEntry implements MTreeEntry<D> {
- private static final long serialVersionUID = 1;
+public class MTreeDirectoryEntry extends AbstractDirectoryEntry implements MTreeEntry {
+ private static final long serialVersionUID = 2;
/**
* The id of routing object of this entry.
@@ -53,12 +51,12 @@ public class MTreeDirectoryEntry<D extends Distance<D>> extends AbstractDirector
* The distance from the routing object of this entry to its parent's routing
* object.
*/
- private D parentDistance;
+ private double parentDistance;
/**
* The covering radius of the entry.
*/
- private D coveringRadius;
+ private double coveringRadius;
/**
* Empty constructor for serialization purposes.
@@ -76,7 +74,7 @@ public class MTreeDirectoryEntry<D extends Distance<D>> extends AbstractDirector
* @param nodeID the id of the underlying node
* @param coveringRadius the covering radius of the entry
*/
- public MTreeDirectoryEntry(DBID objectID, D parentDistance, Integer nodeID, D coveringRadius) {
+ public MTreeDirectoryEntry(DBID objectID, double parentDistance, Integer nodeID, double coveringRadius) {
super(nodeID);
this.routingObjectID = objectID;
this.parentDistance = parentDistance;
@@ -89,7 +87,7 @@ public class MTreeDirectoryEntry<D extends Distance<D>> extends AbstractDirector
* @return the covering radius of this entry
*/
@Override
- public final D getCoveringRadius() {
+ public final double getCoveringRadius() {
return coveringRadius;
}
@@ -99,7 +97,7 @@ public class MTreeDirectoryEntry<D extends Distance<D>> extends AbstractDirector
* @param coveringRadius the covering radius to be set
*/
@Override
- public final void setCoveringRadius(D coveringRadius) {
+ public final void setCoveringRadius(double coveringRadius) {
this.coveringRadius = coveringRadius;
}
@@ -131,7 +129,7 @@ public class MTreeDirectoryEntry<D extends Distance<D>> extends AbstractDirector
* routing object.
*/
@Override
- public final D getParentDistance() {
+ public final double getParentDistance() {
return parentDistance;
}
@@ -141,7 +139,7 @@ public class MTreeDirectoryEntry<D extends Distance<D>> extends AbstractDirector
* @param parentDistance the distance to be set
*/
@Override
- public final void setParentDistance(D parentDistance) {
+ public final void setParentDistance(double parentDistance) {
this.parentDistance = parentDistance;
}
@@ -153,8 +151,8 @@ public class MTreeDirectoryEntry<D extends Distance<D>> extends AbstractDirector
public void writeExternal(ObjectOutput out) throws IOException {
super.writeExternal(out);
out.writeInt(DBIDUtil.asInteger(routingObjectID));
- out.writeObject(parentDistance);
- out.writeObject(coveringRadius);
+ out.writeDouble(parentDistance);
+ out.writeDouble(coveringRadius);
}
/**
@@ -162,12 +160,11 @@ public class MTreeDirectoryEntry<D extends Distance<D>> extends AbstractDirector
* and the coveringRadius of this entry from the specified input stream.
*/
@Override
- @SuppressWarnings( { "unchecked" })
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in);
this.routingObjectID = DBIDUtil.importInteger(in.readInt());
- this.parentDistance = (D) in.readObject();
- this.coveringRadius = (D) in.readObject();
+ this.parentDistance = in.readDouble();
+ this.coveringRadius = in.readDouble();
}
/**
@@ -189,24 +186,23 @@ public class MTreeDirectoryEntry<D extends Distance<D>> extends AbstractDirector
* and routingObjectID as this entry.
*/
@Override
- @SuppressWarnings("unchecked")
public boolean equals(Object o) {
- if(this == o) {
+ if (this == o) {
return true;
}
- if(o == null || getClass() != o.getClass()) {
+ if (o == null || getClass() != o.getClass()) {
return false;
}
- if(!super.equals(o)) {
+ if (!super.equals(o)) {
return false;
}
- final MTreeDirectoryEntry<D> that = (MTreeDirectoryEntry<D>) o;
+ final MTreeDirectoryEntry that = (MTreeDirectoryEntry) o;
- if(coveringRadius != null ? !coveringRadius.equals(that.coveringRadius) : that.coveringRadius != null) {
+ if (Math.abs(coveringRadius - that.coveringRadius) < Double.MIN_NORMAL) {
return false;
}
- if(parentDistance != null ? !parentDistance.equals(that.parentDistance) : that.parentDistance != null) {
+ if (Math.abs(parentDistance - that.parentDistance) < Double.MIN_NORMAL) {
return false;
}
return !(routingObjectID != null ? !DBIDUtil.equal(routingObjectID, that.routingObjectID) : that.routingObjectID != null);
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeEntry.java
index f6969b92..66628087 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeEntry.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeEntry.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,16 +24,14 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants;
*/
import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.index.tree.Entry;
/**
* Defines the requirements for an entry in an M-Tree node.
*
* @author Elke Achtert
- * @param <D> the type of Distance used in the M-Tree
*/
-public interface MTreeEntry<D extends Distance<D>> extends Entry {
+public interface MTreeEntry extends Entry {
/**
* Returns the id of the underlying database object of this entry, if this
* entry is a leaf entry, the id of the routing object, otherwise.
@@ -57,14 +55,14 @@ public interface MTreeEntry<D extends Distance<D>> extends Entry {
*
* @return the distance from the object to its parent object
*/
- D getParentDistance();
+ double getParentDistance();
/**
* Sets the distance from the routing object to routing object of its parent.
*
* @param parentDistance the distance to be set
*/
- void setParentDistance(D parentDistance);
+ void setParentDistance(double parentDistance);
/**
* Returns the covering radius if this entry is a directory entry, null
@@ -72,7 +70,7 @@ public interface MTreeEntry<D extends Distance<D>> extends Entry {
*
* @return the covering radius of this entry
*/
- D getCoveringRadius();
+ double getCoveringRadius();
/**
* Sets the covering radius of this entry if this entry is a directory entry,
@@ -80,5 +78,5 @@ public interface MTreeEntry<D extends Distance<D>> extends Entry {
*
* @param coveringRadius the covering radius to be set
*/
- void setCoveringRadius(D coveringRadius);
+ void setCoveringRadius(double coveringRadius);
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeLeafEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeLeafEntry.java
index 27fbc1ba..cfb22bac 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeLeafEntry.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeLeafEntry.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,7 +28,6 @@ import java.io.ObjectInput;
import java.io.ObjectOutput;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.index.tree.AbstractLeafEntry;
/**
@@ -38,16 +37,18 @@ import de.lmu.ifi.dbs.elki.index.tree.AbstractLeafEntry;
* M-Tree.
*
* @author Elke Achtert
- * @param <D> the type of Distance used in the M-Tree
*/
-public class MTreeLeafEntry<D extends Distance<D>> extends AbstractLeafEntry implements MTreeEntry<D> {
- private static final long serialVersionUID = 1;
+public class MTreeLeafEntry extends AbstractLeafEntry implements MTreeEntry {
+ /**
+ * Serialization version ID.
+ */
+ private static final long serialVersionUID = 2;
/**
* The distance from the underlying data object to its parent's routing
* object.
*/
- private D parentDistance;
+ private double parentDistance;
/**
* Empty constructor for serialization purposes.
@@ -63,7 +64,7 @@ public class MTreeLeafEntry<D extends Distance<D>> extends AbstractLeafEntry imp
* @param parentDistance the distance from the underlying data object to its
* parent's routing object
*/
- public MTreeLeafEntry(DBID objectID, D parentDistance) {
+ public MTreeLeafEntry(DBID objectID, double parentDistance) {
super(objectID);
this.parentDistance = parentDistance;
}
@@ -87,7 +88,6 @@ public class MTreeLeafEntry<D extends Distance<D>> extends AbstractLeafEntry imp
@Override
public final void setRoutingObjectID(DBID objectID) {
throw new UnsupportedOperationException("Leaf entries should not be assigned a routing object.");
- // super.setEntryID(objectID.getIntegerID());
}
/**
@@ -98,7 +98,7 @@ public class MTreeLeafEntry<D extends Distance<D>> extends AbstractLeafEntry imp
* routing object
*/
@Override
- public final D getParentDistance() {
+ public final double getParentDistance() {
return parentDistance;
}
@@ -109,18 +109,18 @@ public class MTreeLeafEntry<D extends Distance<D>> extends AbstractLeafEntry imp
* @param parentDistance the distance to be set
*/
@Override
- public final void setParentDistance(D parentDistance) {
+ public final void setParentDistance(double parentDistance) {
this.parentDistance = parentDistance;
}
/**
- * Returns null, since a leaf entry has no covering radius.
+ * Returns zero, since a leaf entry has no covering radius.
*
- * @return null
+ * @return Zero
*/
@Override
- public D getCoveringRadius() {
- return null;
+ public double getCoveringRadius() {
+ return 0.0;
}
/**
@@ -131,7 +131,7 @@ public class MTreeLeafEntry<D extends Distance<D>> extends AbstractLeafEntry imp
* radius
*/
@Override
- public void setCoveringRadius(D coveringRadius) {
+ public void setCoveringRadius(double coveringRadius) {
throw new UnsupportedOperationException("This entry is not a directory entry!");
}
@@ -142,18 +142,17 @@ public class MTreeLeafEntry<D extends Distance<D>> extends AbstractLeafEntry imp
@Override
public void writeExternal(ObjectOutput out) throws IOException {
super.writeExternal(out);
- out.writeObject(parentDistance);
+ out.writeDouble(parentDistance);
}
/**
* Calls the super method and reads the parentDistance of this entry from the
* specified input stream.
*/
- @SuppressWarnings("unchecked")
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in);
- this.parentDistance = (D) in.readObject();
+ this.parentDistance = in.readDouble();
}
/**
@@ -164,20 +163,19 @@ public class MTreeLeafEntry<D extends Distance<D>> extends AbstractLeafEntry imp
* and has the same parentDistance as this entry.
*/
@Override
- @SuppressWarnings("unchecked")
public boolean equals(Object o) {
- if(this == o) {
+ if (this == o) {
return true;
}
- if(o == null || getClass() != o.getClass()) {
+ if (o == null || getClass() != o.getClass()) {
return false;
}
- if(!super.equals(o)) {
+ if (!super.equals(o)) {
return false;
}
- final MTreeLeafEntry<D> that = (MTreeLeafEntry<D>) o;
+ final MTreeLeafEntry that = (MTreeLeafEntry) o;
- return !(parentDistance != null ? !parentDistance.equals(that.parentDistance) : that.parentDistance != null);
+ return Math.abs(parentDistance - that.parentDistance) < Double.MIN_NORMAL;
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeSettings.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeSettings.java
new file mode 100644
index 00000000..59f6e598
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeSettings.java
@@ -0,0 +1,56 @@
+package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.insert.MTreeInsert;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.split.MTreeSplit;
+
+/**
+ * Class to store the MTree settings.
+ *
+ * @author Erich Schubert
+ *
+ * @param <O> Object type
+ * @param <D> Distance type
+ * @param <N> Node type
+ * @param <E> Entry type
+ */
+public class MTreeSettings<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry> {
+ /**
+ * Holds the instance of the trees distance function.
+ */
+ protected DistanceFunction<? super O, D> distanceFunction;
+
+ /**
+ * Splitting strategy.
+ */
+ protected MTreeSplit<O, D, N, E> splitStrategy;
+
+ /**
+ * Insertion strategy.
+ */
+ protected MTreeInsert<O, D, N, E> insertStrategy;
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTree.java
index f3c440b5..aec4410e 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTree.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTree.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -31,15 +31,16 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeSettings;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query.MTreeQueryUtil;
import de.lmu.ifi.dbs.elki.persistent.PageFile;
@@ -53,25 +54,42 @@ import de.lmu.ifi.dbs.elki.persistent.PageFile;
* @param <D> the type of Distance used in the metrical index
* @param <N> the type of MetricalNode used in the metrical index
* @param <E> the type of MetricalEntry used in the metrical index
+ * @param <S> the type of Settings kept.
*/
-public abstract class AbstractMkTree<O, D extends Distance<D>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry<D>> extends AbstractMTree<O, D, N, E> {
+public abstract class AbstractMkTree<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry, S extends MTreeSettings<O, D, N, E>> extends AbstractMTree<O, D, N, E, S> {
/**
* Internal class for performing knn queries
*/
protected KNNQuery<O, D> knnq;
/**
+ * Distance query to use.
+ */
+ private DistanceQuery<O, D> distanceQuery;
+
+ /**
* Constructor.
*
+ * @param relation Relation to index
* @param pagefile Page file
- * @param distanceQuery Distance query
- * @param distanceFunction Distance function
+ * @param settings Settings class
*/
- public AbstractMkTree(PageFile<N> pagefile, DistanceQuery<O, D> distanceQuery, DistanceFunction<O, D> distanceFunction) {
- super(pagefile, distanceQuery, distanceFunction);
+ public AbstractMkTree(Relation<O> relation, PageFile<N> pagefile, S settings) {
+ super(pagefile, settings);
+ // TODO: any way to un-tie MkTrees from relations?
+ this.distanceQuery = getDistanceFunction().instantiate(relation);
this.knnq = MTreeQueryUtil.getKNNQuery(this, distanceQuery);
}
+ @Override
+ public D distance(DBIDRef id1, DBIDRef id2) {
+ if (id1 == null || id2 == null) {
+ return getDistanceFactory().undefinedDistance();
+ }
+ statistics.countDistanceCalculation();
+ return distanceQuery.distance(id1, id2);
+ }
+
/**
* Performs a reverse k-nearest neighbor query for the given object ID. The
* query result is in ascending order to the distance to the query object.
@@ -80,7 +98,7 @@ public abstract class AbstractMkTree<O, D extends Distance<D>, N extends Abstrac
* @param k the number of nearest neighbors to be returned
* @return a List of the query results
*/
- public abstract DistanceDBIDResult<D> reverseKNNQuery(final DBIDRef id, int k);
+ public abstract DistanceDBIDList<D> reverseKNNQuery(final DBIDRef id, int k);
/**
* Performs a batch k-nearest neighbor query for a list of query objects.
@@ -93,8 +111,8 @@ public abstract class AbstractMkTree<O, D extends Distance<D>, N extends Abstrac
* @deprecated Change to use by-object NN lookups instead.
*/
@Deprecated
- protected final Map<DBID, KNNResult<D>> batchNN(N node, DBIDs ids, int kmax) {
- Map<DBID, KNNResult<D>> res = new HashMap<DBID, KNNResult<D>>(ids.size());
+ protected final Map<DBID, KNNList<D>> batchNN(N node, DBIDs ids, int kmax) {
+ Map<DBID, KNNList<D>> res = new HashMap<>(ids.size());
for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
DBID id = DBIDUtil.deref(iter);
res.put(id, knnq.getKNNForDBID(id, kmax));
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTreeUnified.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTreeUnified.java
index 34507479..455d372a 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTreeUnified.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTreeUnified.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,10 +29,9 @@ import java.util.Map;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
-import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.tree.TreeIndexHeader;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry;
@@ -46,29 +45,24 @@ import de.lmu.ifi.dbs.elki.persistent.PageFile;
* @author Elke Achtert
*
* @apiviz.has MkTreeHeader oneway
+ * @apiviz.composedOf MkTreeSettings
*
* @param <O> the type of DatabaseObject to be stored in the metrical index
* @param <D> the type of Distance used in the metrical index
* @param <N> the type of MetricalNode used in the metrical index
* @param <E> the type of MetricalEntry used in the metrical index
+ * @param <S> the type of Settings used.
*/
-public abstract class AbstractMkTreeUnified<O, D extends Distance<D>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry<D>> extends AbstractMkTree<O, D, N, E> {
- /**
- * Holds the maximum value of k to support.
- */
- private int k_max;
-
+public abstract class AbstractMkTreeUnified<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry, S extends MkTreeSettings<O, D, N, E>> extends AbstractMkTree<O, D, N, E, S> {
/**
* Constructor.
*
+ * @param relation Relation to index
* @param pagefile Page file
- * @param distanceQuery Distance query
- * @param distanceFunction Distance function
- * @param k_max Maximum value for k
+ * @param settings Settings file
*/
- public AbstractMkTreeUnified(PageFile<N> pagefile, DistanceQuery<O, D> distanceQuery, DistanceFunction<O, D> distanceFunction, int k_max) {
- super(pagefile, distanceQuery, distanceFunction);
- this.k_max = k_max;
+ public AbstractMkTreeUnified(Relation<O> relation, PageFile<N> pagefile, S settings) {
+ super(relation, pagefile, settings);
}
/**
@@ -76,7 +70,7 @@ public abstract class AbstractMkTreeUnified<O, D extends Distance<D>, N extends
*/
@Override
protected TreeIndexHeader createHeader() {
- return new MkTreeHeader(getPageSize(), dirCapacity, leafCapacity, k_max);
+ return new MkTreeHeader(getPageSize(), dirCapacity, leafCapacity, settings.k_max);
}
@Override
@@ -98,7 +92,7 @@ public abstract class AbstractMkTreeUnified<O, D extends Distance<D>, N extends
}
// do batch nn
- Map<DBID, KNNResult<D>> knnLists = batchNN(getRoot(), ids, k_max);
+ Map<DBID, KNNList<D>> knnLists = batchNN(getRoot(), ids, settings.k_max);
// adjust the knn distances
kNNdistanceAdjustment(getRootEntry(), knnLists);
@@ -114,7 +108,7 @@ public abstract class AbstractMkTreeUnified<O, D extends Distance<D>, N extends
* @param entry the root entry of the current subtree
* @param knnLists a map of knn lists for each leaf entry
*/
- protected abstract void kNNdistanceAdjustment(E entry, Map<DBID, KNNResult<D>> knnLists);
+ protected abstract void kNNdistanceAdjustment(E entry, Map<DBID, KNNList<D>> knnLists);
/**
* Get the value of k_max.
@@ -122,6 +116,6 @@ public abstract class AbstractMkTreeUnified<O, D extends Distance<D>, N extends
* @return k_max value.
*/
public int getKmax() {
- return k_max;
+ return settings.k_max;
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTreeUnifiedFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTreeUnifiedFactory.java
index 9570995d..fe408035 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTreeUnifiedFactory.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTreeUnifiedFactory.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,12 +23,12 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.Index;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeFactory;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry;
+import de.lmu.ifi.dbs.elki.persistent.PageFileFactory;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
@@ -36,44 +36,27 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
/**
* Abstract factory for various Mk-Trees
+ *
* @author Erich Schubert
*
* @apiviz.stereotype factory
- * @apiviz.uses AbstractMkTree oneway - - «create»
- *
+ * @apiviz.uses AbstractMkTreeUnified oneway - - «create»
+ *
* @param <O> Object type
* @param <D> Distance type
* @param <N> Node type
* @param <E> Entry type
* @param <I> Index type
*/
-public abstract class AbstractMkTreeUnifiedFactory<O, D extends Distance<D>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry<D>, I extends AbstractMkTree<O, D, N, E> & Index> extends AbstractMTreeFactory<O, D, N, E, I> {
- /**
- * Parameter specifying the maximal number k of reverse k nearest neighbors to
- * be supported, must be an integer greater than 0.
- * <p>
- * Key: {@code -mktree.kmax}
- * </p>
- */
- public static final OptionID K_MAX_ID = new OptionID("mktree.kmax", "Specifies the maximal number k of reverse k nearest neighbors to be supported.");
-
- /**
- * Holds the value of parameter {@link #K_MAX_ID}.
- */
- protected int k_max;
-
+public abstract class AbstractMkTreeUnifiedFactory<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry, I extends AbstractMkTree<O, D, N, E, S> & Index, S extends MkTreeSettings<O, D, N, E>> extends AbstractMTreeFactory<O, D, N, E, I, S> {
/**
* Constructor.
- *
- * @param fileName
- * @param pageSize
- * @param cacheSize
- * @param distanceFunction
- * @param k_max
+ *
+ * @param pageFileFactory Data storage
+ * @param settings Tree settings
*/
- public AbstractMkTreeUnifiedFactory(String fileName, int pageSize, long cacheSize, DistanceFunction<O, D> distanceFunction, int k_max) {
- super(fileName, pageSize, cacheSize, distanceFunction);
- this.k_max = k_max;
+ public AbstractMkTreeUnifiedFactory(PageFileFactory<?> pageFileFactory, S settings) {
+ super(pageFileFactory, settings);
}
/**
@@ -83,8 +66,15 @@ public abstract class AbstractMkTreeUnifiedFactory<O, D extends Distance<D>, N e
*
* @apiviz.exclude
*/
- public abstract static class Parameterizer<O, D extends Distance<D>> extends AbstractMTreeFactory.Parameterizer<O, D> {
- protected int k_max;
+ public abstract static class Parameterizer<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry, S extends MkTreeSettings<O, D, N, E>> extends AbstractMTreeFactory.Parameterizer<O, D, N, E, S> {
+ /**
+ * Parameter specifying the maximal number k of reverse k nearest neighbors
+ * to be supported, must be an integer greater than 0.
+ * <p>
+ * Key: {@code -mktree.kmax}
+ * </p>
+ */
+ public static final OptionID K_MAX_ID = new OptionID("mktree.kmax", "Specifies the maximal number k of reverse k nearest neighbors to be supported.");
@Override
protected void makeOptions(Parameterization config) {
@@ -93,11 +83,11 @@ public abstract class AbstractMkTreeUnifiedFactory<O, D extends Distance<D>, N e
k_maxP.addConstraint(new GreaterConstraint(0));
if (config.grab(k_maxP)) {
- k_max = k_maxP.getValue();
+ settings.k_max = k_maxP.getValue();
}
}
@Override
- protected abstract AbstractMkTreeUnifiedFactory<O, D, ?, ?, ?> makeInstance();
+ protected abstract AbstractMkTreeUnifiedFactory<O, D, N, E, ?, S> makeInstance();
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/MkTreeHeader.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/MkTreeHeader.java
index c067a86c..ff49d789 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/MkTreeHeader.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/MkTreeHeader.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,11 +23,11 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import de.lmu.ifi.dbs.elki.index.tree.TreeIndexHeader;
-
import java.io.IOException;
import java.io.RandomAccessFile;
+import de.lmu.ifi.dbs.elki.index.tree.TreeIndexHeader;
+
/**
* Encapsulates the header information for subclasses of
* {@link de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.AbstractMkTreeUnified}.
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/MkTreeSettings.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/MkTreeSettings.java
new file mode 100644
index 00000000..6a957bd7
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/MkTreeSettings.java
@@ -0,0 +1,46 @@
+package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeSettings;
+
+/**
+ * Class with settings for MkTrees.
+ *
+ * @author Erich Schubert
+ *
+ * @param <O> Object type
+ * @param <D> Distance type
+ * @param <N> Node type
+ * @param <E> Entry type
+ */
+public class MkTreeSettings<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry> extends MTreeSettings<O, D, N, E> {
+ /**
+ * Holds the maximum value of k to support.
+ */
+ public int k_max;
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppDirectoryEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppDirectoryEntry.java
index ce7cf104..fd6f6bab 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppDirectoryEntry.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppDirectoryEntry.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkapp;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,7 +28,6 @@ import java.io.ObjectInput;
import java.io.ObjectOutput;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeDirectoryEntry;
/**
@@ -38,11 +37,11 @@ import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeDirectoryEntry
*
* @author Elke Achtert
*/
-class MkAppDirectoryEntry<D extends NumberDistance<D, ?>> extends MTreeDirectoryEntry<D> implements MkAppEntry<D> {
+class MkAppDirectoryEntry extends MTreeDirectoryEntry implements MkAppEntry {
/**
* Serial version UID
- */
- private static final long serialVersionUID = 1;
+ */
+ private static final long serialVersionUID = 2;
/**
* The polynomial approximation.
@@ -65,7 +64,7 @@ class MkAppDirectoryEntry<D extends NumberDistance<D, ?>> extends MTreeDirectory
* @param coveringRadius the covering radius of the entry
* @param approximation the polynomial approximation of the knn distances
*/
- public MkAppDirectoryEntry(DBID objectID, D parentDistance, Integer nodeID, D coveringRadius, PolynomialApproximation approximation) {
+ public MkAppDirectoryEntry(DBID objectID, double parentDistance, Integer nodeID, double coveringRadius, PolynomialApproximation approximation) {
super(objectID, parentDistance, nodeID, coveringRadius);
this.approximation = approximation;
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppEntry.java
index b6eabf7e..5424f6f1 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppEntry.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppEntry.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkapp;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,7 +23,6 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkapp;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry;
/**
@@ -35,7 +34,7 @@ import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry;
*
* @apiviz.composedOf PolynomialApproximation
*/
-interface MkAppEntry<D extends NumberDistance<D, ?>> extends MTreeEntry<D> {
+interface MkAppEntry extends MTreeEntry {
/**
* Returns the approximated value at the specified k.
*
@@ -57,4 +56,4 @@ interface MkAppEntry<D extends NumberDistance<D, ?>> extends MTreeEntry<D> {
* @param approximation the polynomial approximation to be set
*/
public void setKnnDistanceApproximation(PolynomialApproximation approximation);
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppLeafEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppLeafEntry.java
index 4dbf0244..e1f2305a 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppLeafEntry.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppLeafEntry.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkapp;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,7 +28,6 @@ import java.io.ObjectInput;
import java.io.ObjectOutput;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeLeafEntry;
/**
@@ -38,11 +37,11 @@ import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeLeafEntry;
*
* @author Elke Achtert
*/
-class MkAppLeafEntry<D extends NumberDistance<D, ?>> extends MTreeLeafEntry<D> implements MkAppEntry<D> {
+class MkAppLeafEntry extends MTreeLeafEntry implements MkAppEntry {
/**
* Serial Version UID
*/
- private static final long serialVersionUID = 1;
+ private static final long serialVersionUID = 2;
/**
* The polynomial approximation.
@@ -64,7 +63,7 @@ class MkAppLeafEntry<D extends NumberDistance<D, ?>> extends MTreeLeafEntry<D> i
* parent's routing object
* @param approximation the polynomial approximation of the knn distances
*/
- public MkAppLeafEntry(DBID objectID, D parentDistance, PolynomialApproximation approximation) {
+ public MkAppLeafEntry(DBID objectID, double parentDistance, PolynomialApproximation approximation) {
super(objectID, parentDistance);
this.approximation = approximation;
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTree.java
index 51d59e73..1ff0a030 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTree.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTree.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkapp;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -34,18 +34,18 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
-import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultIter;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.GenericDistanceDBIDList;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
+import de.lmu.ifi.dbs.elki.database.ids.generic.GenericDistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.tree.LeafEntry;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.AbstractMkTree;
import de.lmu.ifi.dbs.elki.index.tree.query.GenericMTreeDistanceSearchCandidate;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.math.statistics.PolynomialRegression;
+import de.lmu.ifi.dbs.elki.persistent.ByteArrayUtil;
import de.lmu.ifi.dbs.elki.persistent.PageFile;
import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.Heap;
import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.UpdatableHeap;
@@ -57,54 +57,34 @@ import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.UpdatableHeap;
*
* @author Elke Achtert
*
+ * @apiviz.composedOf MkAppTreeSettings
* @apiviz.has MkAppTreeNode oneway - - contains
*
* @param <O> the type of DatabaseObject to be stored in the metrical index
* @param <D> the type of NumberDistance used in the metrical index
*/
-public class MkAppTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree<O, D, MkAppTreeNode<O, D>, MkAppEntry<D>> {
+public class MkAppTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree<O, D, MkAppTreeNode<O, D>, MkAppEntry, MkAppTreeSettings<O, D>> {
/**
* The logger for this class.
*/
private static final Logging LOG = Logging.getLogger(MkAppTree.class);
/**
- * Parameter k.
- */
- private int k_max;
-
- /**
- * Parameter p.
- */
- private int p;
-
- /**
- * Flag log.
- */
- private boolean log;
-
- /**
* Constructor.
*
+ * @param relation Relation to index
* @param pageFile Page file
- * @param distanceQuery Distance query
- * @param distanceFunction Distance function
- * @param k_max Maximum value of k supported
- * @param p Parameter p
- * @param log Logspace flag
+ * @param settings Tree settings
*/
- public MkAppTree(PageFile<MkAppTreeNode<O, D>> pageFile, DistanceQuery<O, D> distanceQuery, DistanceFunction<O, D> distanceFunction, int k_max, int p, boolean log) {
- super(pageFile, distanceQuery, distanceFunction);
- this.k_max = k_max;
- this.p = p;
- this.log = log;
+ public MkAppTree(Relation<O> relation, PageFile<MkAppTreeNode<O, D>> pageFile, MkAppTreeSettings<O, D> settings) {
+ super(relation, pageFile, settings);
}
/**
* @throws UnsupportedOperationException since this operation is not supported
*/
@Override
- public void insert(MkAppEntry<D> id, boolean withPreInsert) {
+ public void insert(MkAppEntry id, boolean withPreInsert) {
throw new UnsupportedOperationException("Insertion of single objects is not supported!");
}
@@ -112,7 +92,7 @@ public class MkAppTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
* @throws UnsupportedOperationException since this operation is not supported
*/
@Override
- protected void preInsert(MkAppEntry<D> entry) {
+ protected void preInsert(MkAppEntry entry) {
throw new UnsupportedOperationException("Insertion of single objects is not supported!");
}
@@ -122,35 +102,35 @@ public class MkAppTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
* @param entries the entries to be inserted
*/
@Override
- public void insertAll(List<MkAppEntry<D>> entries) {
- if(entries.isEmpty()) {
+ public void insertAll(List<MkAppEntry> entries) {
+ if (entries.isEmpty()) {
return;
}
- if(LOG.isDebugging()) {
+ if (LOG.isDebugging()) {
LOG.debugFine("insert " + entries + "\n");
}
- if(!initialized) {
+ if (!initialized) {
initialize(entries.get(0));
}
ModifiableDBIDs ids = DBIDUtil.newArray(entries.size());
// insert
- for(MkAppEntry<D> entry : entries) {
+ for (MkAppEntry entry : entries) {
ids.add(entry.getRoutingObjectID());
// insert the object
super.insert(entry, false);
}
// do batch nn
- Map<DBID, KNNResult<D>> knnLists = batchNN(getRoot(), ids, k_max + 1);
-
+ Map<DBID, KNNList<D>> knnLists = batchNN(getRoot(), ids, settings.k_max + 1);
+
// adjust the knn distances
adjustApproximatedKNNDistances(getRootEntry(), knnLists);
- if(EXTRA_INTEGRITY_CHECKS) {
+ if (EXTRA_INTEGRITY_CHECKS) {
getRoot().integrityCheck(this, getRootEntry());
}
}
@@ -164,50 +144,49 @@ public class MkAppTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
* @return a List of the query results
*/
@Override
- public DistanceDBIDResult<D> reverseKNNQuery(DBIDRef id, int k) {
- GenericDistanceDBIDList<D> result = new GenericDistanceDBIDList<D>();
- final Heap<GenericMTreeDistanceSearchCandidate<D>> pq = new UpdatableHeap<GenericMTreeDistanceSearchCandidate<D>>();
+ public DistanceDBIDList<D> reverseKNNQuery(DBIDRef id, int k) {
+ GenericDistanceDBIDList<D> result = new GenericDistanceDBIDList<>();
+ final Heap<GenericMTreeDistanceSearchCandidate> pq = new UpdatableHeap<>();
// push root
- pq.add(new GenericMTreeDistanceSearchCandidate<D>(getDistanceQuery().nullDistance(), getRootID(), null, null));
+ pq.add(new GenericMTreeDistanceSearchCandidate(0., getRootID(), null));
// search in tree
- while(!pq.isEmpty()) {
- GenericMTreeDistanceSearchCandidate<D> pqNode = pq.poll();
+ while (!pq.isEmpty()) {
+ GenericMTreeDistanceSearchCandidate pqNode = pq.poll();
// FIXME: cache the distance to the routing object in the queue node!
MkAppTreeNode<O, D> node = getNode(pqNode.nodeID);
// directory node
- if(!node.isLeaf()) {
- for(int i = 0; i < node.getNumEntries(); i++) {
- MkAppEntry<D> entry = node.getEntry(i);
- D distance = getDistanceQuery().distance(entry.getRoutingObjectID(), id);
- D minDist = entry.getCoveringRadius().compareTo(distance) > 0 ? getDistanceQuery().nullDistance() : distance.minus(entry.getCoveringRadius());
-
- double approxValue = log ? Math.exp(entry.approximatedValueAt(k)) : entry.approximatedValueAt(k);
- if(approxValue < 0) {
+ if (!node.isLeaf()) {
+ for (int i = 0; i < node.getNumEntries(); i++) {
+ MkAppEntry entry = node.getEntry(i);
+ double distance = distance(entry.getRoutingObjectID(), id).doubleValue();
+ double minDist = (entry.getCoveringRadius() > distance) ? 0. : distance - entry.getCoveringRadius();
+
+ double approxValue = settings.log ? Math.exp(entry.approximatedValueAt(k)) : entry.approximatedValueAt(k);
+ if (approxValue < 0) {
approxValue = 0;
}
- D approximatedKnnDist = getDistanceQuery().getDistanceFactory().fromDouble(approxValue);
- if(minDist.compareTo(approximatedKnnDist) <= 0) {
- pq.add(new GenericMTreeDistanceSearchCandidate<D>(minDist, getPageID(entry), entry.getRoutingObjectID(), null));
+ if (minDist <= approxValue) {
+ pq.add(new GenericMTreeDistanceSearchCandidate(minDist, getPageID(entry), entry.getRoutingObjectID()));
}
}
}
// data node
else {
- for(int i = 0; i < node.getNumEntries(); i++) {
- MkAppLeafEntry<D> entry = (MkAppLeafEntry<D>) node.getEntry(i);
- D distance = getDistanceQuery().distance(entry.getRoutingObjectID(), id);
- double approxValue = log ? StrictMath.exp(entry.approximatedValueAt(k)) : entry.approximatedValueAt(k);
- if(approxValue < 0) {
+ for (int i = 0; i < node.getNumEntries(); i++) {
+ MkAppLeafEntry entry = (MkAppLeafEntry) node.getEntry(i);
+ D distance = distance(entry.getRoutingObjectID(), id);
+ double approxValue = settings.log ? StrictMath.exp(entry.approximatedValueAt(k)) : entry.approximatedValueAt(k);
+ if (approxValue < 0) {
approxValue = 0;
}
- D approximatedKnnDist = getDistanceQuery().getDistanceFactory().fromDouble(approxValue);
+ D approximatedKnnDist = getDistanceFactory().fromDouble(approxValue);
- if(distance.compareTo(approximatedKnnDist) <= 0) {
+ if (distance.compareTo(approximatedKnnDist) <= 0) {
result.add(distance, entry.getRoutingObjectID());
}
}
@@ -222,69 +201,69 @@ public class MkAppTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
* @return the value of the k_max parameter
*/
public int getK_max() {
- return k_max;
+ return settings.k_max;
}
/**
* Determines the maximum and minimum number of entries in a node.
*/
@Override
- protected void initializeCapacities(MkAppEntry<D> exampleLeaf) {
- int distanceSize = exampleLeaf.getParentDistance().externalizableSize();
+ protected void initializeCapacities(MkAppEntry exampleLeaf) {
+ int distanceSize = ByteArrayUtil.SIZE_DOUBLE; // exampleLeaf.getParentDistance().externalizableSize();
// overhead = index(4), numEntries(4), id(4), isLeaf(0.125)
double overhead = 12.125;
- if(getPageSize() - overhead < 0) {
+ if (getPageSize() - overhead < 0) {
throw new RuntimeException("Node size of " + getPageSize() + " Bytes is chosen too small!");
}
// dirCapacity = (file.getPageSize() - overhead) / (nodeID + objectID +
// coveringRadius + parentDistance + approx) + 1
- dirCapacity = (int) (getPageSize() - overhead) / (4 + 4 + distanceSize + distanceSize + (p + 1) * 4 + 2) + 1;
+ dirCapacity = (int) (getPageSize() - overhead) / (4 + 4 + distanceSize + distanceSize + (settings.p + 1) * 4 + 2) + 1;
- if(dirCapacity <= 1) {
+ if (dirCapacity <= 1) {
throw new RuntimeException("Node size of " + getPageSize() + " Bytes is chosen too small!");
}
- if(dirCapacity < 10) {
+ if (dirCapacity < 10) {
LOG.warning("Page size is choosen too small! Maximum number of entries " + "in a directory node = " + (dirCapacity - 1));
}
// leafCapacity = (file.getPageSize() - overhead) / (objectID +
// parentDistance +
// approx) + 1
- leafCapacity = (int) (getPageSize() - overhead) / (4 + distanceSize + (p + 1) * 4 + 2) + 1;
+ leafCapacity = (int) (getPageSize() - overhead) / (4 + distanceSize + (settings.p + 1) * 4 + 2) + 1;
- if(leafCapacity <= 1) {
+ if (leafCapacity <= 1) {
throw new RuntimeException("Node size of " + getPageSize() + " Bytes is chosen too small!");
}
- if(leafCapacity < 10) {
+ if (leafCapacity < 10) {
LOG.warning("Page size is choosen too small! Maximum number of entries " + "in a leaf node = " + (leafCapacity - 1));
}
initialized = true;
- if(LOG.isVerbose()) {
+ if (LOG.isVerbose()) {
LOG.verbose("Directory Capacity: " + (dirCapacity - 1) + "\nLeaf Capacity: " + (leafCapacity - 1));
}
}
- private List<D> getMeanKNNList(DBIDs ids, Map<DBID, KNNResult<D>> knnLists) {
- double[] means = new double[k_max];
- for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
+ private List<D> getMeanKNNList(DBIDs ids, Map<DBID, KNNList<D>> knnLists) {
+ double[] means = new double[settings.k_max];
+ for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
DBID id = DBIDUtil.deref(iter);
- KNNResult<D> knns = knnLists.get(id);
+ KNNList<D> knns = knnLists.get(id);
int k = 0;
- for(DistanceDBIDResultIter<D> it = knns.iter(); k < k_max && it.valid(); it.advance(), k++) {
+ for (DistanceDBIDListIter<D> it = knns.iter(); k < settings.k_max && it.valid(); it.advance(), k++) {
means[k] += it.getDistance().doubleValue();
}
}
- List<D> result = new ArrayList<D>();
- for(int k = 0; k < k_max; k++) {
+ List<D> result = new ArrayList<>();
+ for (int k = 0; k < settings.k_max; k++) {
means[k] /= ids.size();
- result.add(getDistanceQuery().getDistanceFactory().fromDouble(means[k]));
+ result.add(getDistanceFactory().fromDouble(means[k]));
}
return result;
@@ -296,21 +275,20 @@ public class MkAppTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
* @param entry the root entry of the current subtree
* @param knnLists a map of knn lists for each leaf entry
*/
- private void adjustApproximatedKNNDistances(MkAppEntry<D> entry, Map<DBID, KNNResult<D>> knnLists) {
+ private void adjustApproximatedKNNDistances(MkAppEntry entry, Map<DBID, KNNList<D>> knnLists) {
MkAppTreeNode<O, D> node = getNode(entry);
- if(node.isLeaf()) {
- for(int i = 0; i < node.getNumEntries(); i++) {
- MkAppLeafEntry<D> leafEntry = (MkAppLeafEntry<D>) node.getEntry(i);
+ if (node.isLeaf()) {
+ for (int i = 0; i < node.getNumEntries(); i++) {
+ MkAppLeafEntry leafEntry = (MkAppLeafEntry) node.getEntry(i);
// approximateKnnDistances(leafEntry,
// getKNNList(leafEntry.getRoutingObjectID(), knnLists));
PolynomialApproximation approx = approximateKnnDistances(getMeanKNNList(leafEntry.getDBID(), knnLists));
leafEntry.setKnnDistanceApproximation(approx);
}
- }
- else {
- for(int i = 0; i < node.getNumEntries(); i++) {
- MkAppEntry<D> dirEntry = node.getEntry(i);
+ } else {
+ for (int i = 0; i < node.getNumEntries(); i++) {
+ MkAppEntry dirEntry = node.getEntry(i);
adjustApproximatedKNNDistances(dirEntry, knnLists);
}
}
@@ -330,14 +308,13 @@ public class MkAppTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
* in the specified subtree
*/
private void leafEntryIDs(MkAppTreeNode<O, D> node, ModifiableDBIDs result) {
- if(node.isLeaf()) {
- for(int i = 0; i < node.getNumEntries(); i++) {
- MkAppEntry<D> entry = node.getEntry(i);
+ if (node.isLeaf()) {
+ for (int i = 0; i < node.getNumEntries(); i++) {
+ MkAppEntry entry = node.getEntry(i);
result.add(((LeafEntry) entry).getDBID());
}
- }
- else {
- for(int i = 0; i < node.getNumEntries(); i++) {
+ } else {
+ for (int i = 0; i < node.getNumEntries(); i++) {
MkAppTreeNode<O, D> childNode = getNode(node.getEntry(i));
leafEntryIDs(childNode, result);
}
@@ -355,36 +332,34 @@ public class MkAppTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
// count the zero distances (necessary of log-log space is used)
int k_0 = 0;
- if(log) {
- for(int i = 0; i < k_max; i++) {
+ if (settings.log) {
+ for (int i = 0; i < settings.k_max; i++) {
double dist = knnDistances.get(i).doubleValue();
- if(dist == 0) {
+ if (dist == 0) {
k_0++;
- }
- else {
+ } else {
break;
}
}
}
- de.lmu.ifi.dbs.elki.math.linearalgebra.Vector x = new de.lmu.ifi.dbs.elki.math.linearalgebra.Vector(k_max - k_0);
- de.lmu.ifi.dbs.elki.math.linearalgebra.Vector y = new de.lmu.ifi.dbs.elki.math.linearalgebra.Vector(k_max - k_0);
+ de.lmu.ifi.dbs.elki.math.linearalgebra.Vector x = new de.lmu.ifi.dbs.elki.math.linearalgebra.Vector(settings.k_max - k_0);
+ de.lmu.ifi.dbs.elki.math.linearalgebra.Vector y = new de.lmu.ifi.dbs.elki.math.linearalgebra.Vector(settings.k_max - k_0);
- for(int k = 0; k < k_max - k_0; k++) {
- if(log) {
+ for (int k = 0; k < settings.k_max - k_0; k++) {
+ if (settings.log) {
x.set(k, Math.log(k + k_0));
y.set(k, Math.log(knnDistances.get(k + k_0).doubleValue()));
- }
- else {
+ } else {
x.set(k, k + k_0);
y.set(k, knnDistances.get(k + k_0).doubleValue());
}
}
- PolynomialRegression regression = new PolynomialRegression(y, x, p);
+ PolynomialRegression regression = new PolynomialRegression(y, x, settings.p);
PolynomialApproximation approximation = new PolynomialApproximation(regression.getEstimatedCoefficients().getArrayCopy());
- if(LOG.isDebugging()) {
+ if (LOG.isDebugging()) {
msg.append("approximation ").append(approximation);
LOG.debugFine(msg.toString());
}
@@ -399,7 +374,7 @@ public class MkAppTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
*/
@Override
protected MkAppTreeNode<O, D> createNewLeafNode() {
- return new MkAppTreeNode<O, D>(leafCapacity, true);
+ return new MkAppTreeNode<>(leafCapacity, true);
}
/**
@@ -409,7 +384,7 @@ public class MkAppTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
*/
@Override
protected MkAppTreeNode<O, D> createNewDirectoryNode() {
- return new MkAppTreeNode<O, D>(dirCapacity, false);
+ return new MkAppTreeNode<>(dirCapacity, false);
}
/**
@@ -421,8 +396,8 @@ public class MkAppTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
* the routing object of the parent node
*/
@Override
- protected MkAppEntry<D> createNewDirectoryEntry(MkAppTreeNode<O, D> node, DBID routingObjectID, D parentDistance) {
- return new MkAppDirectoryEntry<D>(routingObjectID, parentDistance, node.getPageID(), node.coveringRadius(routingObjectID, this), null);
+ protected MkAppEntry createNewDirectoryEntry(MkAppTreeNode<O, D> node, DBID routingObjectID, double parentDistance) {
+ return new MkAppDirectoryEntry(routingObjectID, parentDistance, node.getPageID(), node.coveringRadius(routingObjectID, this), null);
}
/**
@@ -431,12 +406,12 @@ public class MkAppTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
* @return an entry representing the root node
*/
@Override
- protected MkAppEntry<D> createRootEntry() {
- return new MkAppDirectoryEntry<D>(null, null, 0, null, null);
+ protected MkAppEntry createRootEntry() {
+ return new MkAppDirectoryEntry(null, 0., 0, 0., null);
}
@Override
protected Logging getLogger() {
return LOG;
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeFactory.java
index c0f12895..45a2e85f 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeFactory.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeFactory.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkapp;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,10 +24,10 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkapp;
*/
import de.lmu.ifi.dbs.elki.database.relation.Relation;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeFactory;
import de.lmu.ifi.dbs.elki.persistent.PageFile;
+import de.lmu.ifi.dbs.elki.persistent.PageFileFactory;
import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
@@ -46,7 +46,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
* @param <O> Object type
* @param <D> Distance type
*/
-public class MkAppTreeFactory<O, D extends NumberDistance<D, ?>> extends AbstractMTreeFactory<O, D, MkAppTreeNode<O, D>, MkAppEntry<D>, MkAppTreeIndex<O, D>> {
+public class MkAppTreeFactory<O, D extends NumberDistance<D, ?>> extends AbstractMTreeFactory<O, D, MkAppTreeNode<O, D>, MkAppEntry, MkAppTreeIndex<O, D>, MkAppTreeSettings<O, D>> {
/**
* Parameter for nolog
*/
@@ -63,42 +63,19 @@ public class MkAppTreeFactory<O, D extends NumberDistance<D, ?>> extends Abstrac
public static final OptionID P_ID = new OptionID("mkapp.p", "positive integer specifying the order of the polynomial approximation.");
/**
- * Parameter k.
- */
- private int k_max;
-
- /**
- * Parameter p.
- */
- private int p;
-
- /**
- * Flag log.
- */
- private boolean log;
-
- /**
* Constructor.
*
- * @param fileName
- * @param pageSize
- * @param cacheSize
- * @param distanceFunction
- * @param k_max
- * @param p
- * @param log
+ * @param pageFileFactory Data storage
+ * @param settings Tree settings
*/
- public MkAppTreeFactory(String fileName, int pageSize, long cacheSize, DistanceFunction<O, D> distanceFunction, int k_max, int p, boolean log) {
- super(fileName, pageSize, cacheSize, distanceFunction);
- this.k_max = k_max;
- this.p = p;
- this.log = log;
+ public MkAppTreeFactory(PageFileFactory<?> pageFileFactory, MkAppTreeSettings<O, D> settings) {
+ super(pageFileFactory, settings);
}
@Override
public MkAppTreeIndex<O, D> instantiate(Relation<O> relation) {
PageFile<MkAppTreeNode<O, D>> pagefile = makePageFile(getNodeClass());
- return new MkAppTreeIndex<O, D>(relation, pagefile, distanceFunction.instantiate(relation), distanceFunction, k_max, p, log);
+ return new MkAppTreeIndex<>(relation, pagefile, settings);
}
protected Class<MkAppTreeNode<O, D>> getNodeClass() {
@@ -112,46 +89,36 @@ public class MkAppTreeFactory<O, D extends NumberDistance<D, ?>> extends Abstrac
*
* @apiviz.exclude
*/
- public static class Parameterizer<O, D extends NumberDistance<D, ?>> extends AbstractMTreeFactory.Parameterizer<O, D> {
- /**
- * Parameter k.
- */
- protected int k_max;
-
- /**
- * Parameter p.
- */
- protected int p;
-
- /**
- * Flag log.
- */
- protected boolean log;
-
+ public static class Parameterizer<O, D extends NumberDistance<D, ?>> extends AbstractMTreeFactory.Parameterizer<O, D, MkAppTreeNode<O, D>, MkAppEntry, MkAppTreeSettings<O, D>> {
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
IntParameter kP = new IntParameter(K_ID);
kP.addConstraint(new GreaterConstraint(0));
- if(config.grab(kP)) {
- k_max = kP.getValue();
+ if (config.grab(kP)) {
+ settings.k_max = kP.getValue();
}
IntParameter pP = new IntParameter(P_ID);
pP.addConstraint(new GreaterConstraint(0));
- if(config.grab(pP)) {
- p = pP.getValue();
+ if (config.grab(pP)) {
+ settings.p = pP.getValue();
}
Flag nologF = new Flag(NOLOG_ID);
- if(config.grab(nologF)) {
- log = !nologF.getValue();
+ if (config.grab(nologF)) {
+ settings.log = !nologF.getValue();
}
}
@Override
protected MkAppTreeFactory<O, D> makeInstance() {
- return new MkAppTreeFactory<O, D>(fileName, pageSize, cacheSize, distanceFunction, k_max, p, log);
+ return new MkAppTreeFactory<>(pageFileFactory, settings);
+ }
+
+ @Override
+ protected MkAppTreeSettings<O, D> makeSettings() {
+ return new MkAppTreeSettings<>();
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeIndex.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeIndex.java
index 9776de63..2a630bf0 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeIndex.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeIndex.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkapp;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,9 +28,7 @@ import java.util.List;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
@@ -43,12 +41,9 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.KNNIndex;
import de.lmu.ifi.dbs.elki.index.RKNNIndex;
import de.lmu.ifi.dbs.elki.index.RangeIndex;
-import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree;
-import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.AbstractMkTree;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query.MTreeQueryUtil;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query.MkTreeRKNNQuery;
import de.lmu.ifi.dbs.elki.persistent.PageFile;
-import de.lmu.ifi.dbs.elki.utilities.exceptions.ExceptionMessages;
/**
* MkAppTree used as database index.
@@ -69,16 +64,11 @@ public class MkAppTreeIndex<O, D extends NumberDistance<D, ?>> extends MkAppTree
*
* @param relation Relation to index
* @param pageFile Page file
- * @param distanceQuery Distance query
- * @param distanceFunction Distance function
- * @param k_max Maximum value of k supported
- * @param p Parameter p
- * @param log Logspace flag
+ * @param settings Tree settings
*/
- public MkAppTreeIndex(Relation<O> relation, PageFile<MkAppTreeNode<O, D>> pageFile, DistanceQuery<O, D> distanceQuery, DistanceFunction<O, D> distanceFunction, int k_max, int p, boolean log) {
- super(pageFile, distanceQuery, distanceFunction, k_max, p, log);
+ public MkAppTreeIndex(Relation<O> relation, PageFile<MkAppTreeNode<O, D>> pageFile, MkAppTreeSettings<O, D> settings) {
+ super(relation, pageFile, settings);
this.relation = relation;
- this.initialize();
}
/**
@@ -89,119 +79,88 @@ public class MkAppTreeIndex<O, D extends NumberDistance<D, ?>> extends MkAppTree
* @param parentDistance the distance from the object to the routing object of
* the parent node
*/
- protected MkAppEntry<D> createNewLeafEntry(DBID id, O object, D parentDistance) {
- return new MkAppLeafEntry<D>(id, parentDistance, null);
+ protected MkAppEntry createNewLeafEntry(DBID id, O object, double parentDistance) {
+ return new MkAppLeafEntry(id, parentDistance, null);
}
@Override
- public void insert(DBIDRef id) {
- throw new UnsupportedOperationException("Insertion of single objects is not supported!");
- }
-
- @Override
- public void insertAll(DBIDs ids) {
- List<MkAppEntry<D>> objs = new ArrayList<MkAppEntry<D>>(ids.size());
- for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
+ public void initialize() {
+ super.initialize();
+ List<MkAppEntry> objs = new ArrayList<>(relation.size());
+ for (DBIDIter iter = relation.iterDBIDs(); iter.valid(); iter.advance()) {
DBID id = DBIDUtil.deref(iter);
final O object = relation.get(id);
- objs.add(createNewLeafEntry(id, object, getDistanceFactory().undefinedDistance()));
+ objs.add(createNewLeafEntry(id, object, Double.NaN));
}
insertAll(objs);
}
- /**
- * Throws an UnsupportedOperationException since deletion of objects is not
- * yet supported by an M-Tree.
- *
- * @throws UnsupportedOperationException thrown, since deletions aren't
- * implemented yet.
- */
- @Override
- public final boolean delete(DBIDRef id) {
- throw new UnsupportedOperationException(ExceptionMessages.UNSUPPORTED_NOT_YET);
- }
-
- /**
- * Throws an UnsupportedOperationException since deletion of objects is not
- * yet supported by an M-Tree.
- *
- * @throws UnsupportedOperationException thrown, since deletions aren't
- * implemented yet.
- */
- @Override
- public void deleteAll(DBIDs ids) {
- throw new UnsupportedOperationException(ExceptionMessages.UNSUPPORTED_NOT_YET);
- }
-
@SuppressWarnings("unchecked")
@Override
public <S extends Distance<S>> KNNQuery<O, S> getKNNQuery(DistanceQuery<O, S> distanceQuery, Object... hints) {
// Query on the relation we index
- if(distanceQuery.getRelation() != relation) {
+ if (distanceQuery.getRelation() != relation) {
return null;
}
- DistanceFunction<? super O, S> distanceFunction = distanceQuery.getDistanceFunction();
- if(!this.distanceFunction.equals(distanceFunction)) {
- if(getLogger().isDebugging()) {
+ DistanceFunction<? super O, D> distanceFunction = (DistanceFunction<? super O, D>) distanceQuery.getDistanceFunction();
+ if (!this.getDistanceFunction().equals(distanceFunction)) {
+ if (getLogger().isDebugging()) {
getLogger().debug("Distance function not supported by index - or 'equals' not implemented right!");
}
return null;
}
// Bulk is not yet supported
- for(Object hint : hints) {
- if(hint == DatabaseQuery.HINT_BULK) {
+ for (Object hint : hints) {
+ if (hint == DatabaseQuery.HINT_BULK) {
return null;
}
}
- AbstractMTree<O, S, ?, ?> idx = (AbstractMTree<O, S, ?, ?>) this;
- DistanceQuery<O, S> dq = distanceFunction.instantiate(relation);
- return MTreeQueryUtil.getKNNQuery(idx, dq, hints);
+ DistanceQuery<O, D> dq = distanceFunction.instantiate(relation);
+ return (KNNQuery<O, S>) MTreeQueryUtil.getKNNQuery(this, dq, hints);
}
@SuppressWarnings("unchecked")
@Override
public <S extends Distance<S>> RangeQuery<O, S> getRangeQuery(DistanceQuery<O, S> distanceQuery, Object... hints) {
// Query on the relation we index
- if(distanceQuery.getRelation() != relation) {
+ if (distanceQuery.getRelation() != relation) {
return null;
}
- DistanceFunction<? super O, S> distanceFunction = distanceQuery.getDistanceFunction();
- if(!this.distanceFunction.equals(distanceFunction)) {
- if(getLogger().isDebugging()) {
+ DistanceFunction<? super O, D> distanceFunction = (DistanceFunction<? super O, D>) distanceQuery.getDistanceFunction();
+ if (!this.getDistanceFunction().equals(distanceFunction)) {
+ if (getLogger().isDebugging()) {
getLogger().debug("Distance function not supported by index - or 'equals' not implemented right!");
}
return null;
}
// Bulk is not yet supported
- for(Object hint : hints) {
- if(hint == DatabaseQuery.HINT_BULK) {
+ for (Object hint : hints) {
+ if (hint == DatabaseQuery.HINT_BULK) {
return null;
}
}
- AbstractMTree<O, S, ?, ?> idx = (AbstractMTree<O, S, ?, ?>) this;
- DistanceQuery<O, S> dq = distanceFunction.instantiate(relation);
- return MTreeQueryUtil.getRangeQuery(idx, dq, hints);
+ DistanceQuery<O, D> dq = distanceFunction.instantiate(relation);
+ return (RangeQuery<O, S>) MTreeQueryUtil.getRangeQuery(this, dq, hints);
}
@SuppressWarnings("unchecked")
@Override
public <S extends Distance<S>> RKNNQuery<O, S> getRKNNQuery(DistanceQuery<O, S> distanceQuery, Object... hints) {
- DistanceFunction<? super O, S> distanceFunction = distanceQuery.getDistanceFunction();
- if(!this.getDistanceFunction().equals(distanceFunction)) {
- if(getLogger().isDebugging()) {
+ DistanceFunction<? super O, D> distanceFunction = (DistanceFunction<? super O, D>) distanceQuery.getDistanceFunction();
+ if (!this.getDistanceFunction().equals(distanceFunction)) {
+ if (getLogger().isDebugging()) {
getLogger().debug("Distance function not supported by index - or 'equals' not implemented right!");
}
return null;
}
// Bulk is not yet supported
- for(Object hint : hints) {
- if(hint == DatabaseQuery.HINT_BULK) {
+ for (Object hint : hints) {
+ if (hint == DatabaseQuery.HINT_BULK) {
return null;
}
}
- AbstractMkTree<O, S, ?, ?> idx = (AbstractMkTree<O, S, ?, ?>) this;
- DistanceQuery<O, S> dq = distanceFunction.instantiate(relation);
- return new MkTreeRKNNQuery<O, S>(idx, dq);
+ DistanceQuery<O, D> dq = distanceFunction.instantiate(relation);
+ return (RKNNQuery<O, S>) new MkTreeRKNNQuery<>(this, dq);
}
@Override
@@ -213,4 +172,4 @@ public class MkAppTreeIndex<O, D extends NumberDistance<D, ?>> extends MkAppTree
public String getShortName() {
return "mkapptree";
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeNode.java
index c730eb4f..29609274 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeNode.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeNode.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkapp;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -43,8 +43,8 @@ import de.lmu.ifi.dbs.elki.utilities.FormatUtil;
* @param <O> object type
* @param <D> distance type
*/
-class MkAppTreeNode<O, D extends NumberDistance<D, ?>> extends AbstractMTreeNode<O, D, MkAppTreeNode<O, D>, MkAppEntry<D>> {
- private static final long serialVersionUID = 1;
+class MkAppTreeNode<O, D extends NumberDistance<D, ?>> extends AbstractMTreeNode<O, D, MkAppTreeNode<O, D>, MkAppEntry> {
+ private static final long serialVersionUID = 2;
/**
* Empty constructor for Externalizable interface.
@@ -75,7 +75,7 @@ class MkAppTreeNode<O, D extends NumberDistance<D, ?>> extends AbstractMTreeNode
int p_max = 0;
double[] b = null;
for(int i = 0; i < getNumEntries(); i++) {
- MkAppEntry<D> entry = getEntry(i);
+ MkAppEntry entry = getEntry(i);
PolynomialApproximation approximation = entry.getKnnDistanceApproximation();
if(b == null) {
p_max = approximation.getPolynomialOrder();
@@ -109,16 +109,16 @@ class MkAppTreeNode<O, D extends NumberDistance<D, ?>> extends AbstractMTreeNode
* @param mTree the M-Tree object holding this node
*/
@Override
- public void adjustEntry(MkAppEntry<D> entry, DBID routingObjectID, D parentDistance, AbstractMTree<O, D, MkAppTreeNode<O, D>, MkAppEntry<D>> mTree) {
+ public void adjustEntry(MkAppEntry entry, DBID routingObjectID, double parentDistance, AbstractMTree<O, D, MkAppTreeNode<O, D>, MkAppEntry, ?> mTree) {
super.adjustEntry(entry, routingObjectID, parentDistance, mTree);
// entry.setKnnDistanceApproximation(knnDistanceApproximation());
}
@Override
- protected void integrityCheckParameters(MkAppEntry<D> parentEntry, MkAppTreeNode<O, D> parent, int index, AbstractMTree<O, D, MkAppTreeNode<O, D>, MkAppEntry<D>> mTree) {
+ protected void integrityCheckParameters(MkAppEntry parentEntry, MkAppTreeNode<O, D> parent, int index, AbstractMTree<O, D, MkAppTreeNode<O, D>, MkAppEntry, ?> mTree) {
super.integrityCheckParameters(parentEntry, parent, index, mTree);
- MkAppEntry<D> entry = parent.getEntry(index);
+ MkAppEntry entry = parent.getEntry(index);
PolynomialApproximation approximation_soll = knnDistanceApproximation();
PolynomialApproximation approximation_ist = entry.getKnnDistanceApproximation();
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeSettings.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeSettings.java
new file mode 100644
index 00000000..b9e0b8aa
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeSettings.java
@@ -0,0 +1,47 @@
+package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkapp;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.MkTreeSettings;
+
+/**
+ * Settings class for the MkApp Tree.
+ *
+ * @author Erich Schubert
+ *
+ * @param <O> Object type
+ * @param <D> Distance type
+ */
+public class MkAppTreeSettings<O, D extends NumberDistance<D, ?>> extends MkTreeSettings<O, D, MkAppTreeNode<O, D>, MkAppEntry> {
+ /**
+ * Parameter p.
+ */
+ protected int p;
+
+ /**
+ * Flag log.
+ */
+ protected boolean log;
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/PolynomialApproximation.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/PolynomialApproximation.java
index 2ad3558e..dc28b7c3 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/PolynomialApproximation.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/PolynomialApproximation.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkapp;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/package-info.java
index 0f3cfde9..7b897fe3 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/ApproximationLine.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/ApproximationLine.java
index 7f2aa3fe..318c437b 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/ApproximationLine.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/ApproximationLine.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkcop;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,9 +28,6 @@ import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
-import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
-
/**
* Provides an approximation for knn-distances line consisting of incline m,
* axes intercept t and a start value for k.
@@ -111,7 +108,7 @@ public class ApproximationLine implements Externalizable {
* @return the function value of the approximation line at the specified k
*/
public double getValueAt(int k) {
- if(k < k_0) {
+ if (k < k_0) {
return Double.POSITIVE_INFINITY;
}
return m * StrictMath.log(k) + t;
@@ -120,17 +117,14 @@ public class ApproximationLine implements Externalizable {
/**
* Returns the approximated knn-distance at the specified k.
*
- * @param <O> Object type
- * @param <D> Distance type
* @param k the value for which the knn-distance should be returned
- * @param distanceFunction the distance function
* @return the approximated knn-distance at the specified k
*/
- public <O, D extends NumberDistance<D, ?>> D getApproximatedKnnDistance(int k, DistanceQuery<O, D> distanceFunction) {
- if(k < k_0) {
- return distanceFunction.nullDistance();
+ public double getApproximatedKnnDistance(int k) {
+ if (k < k_0) {
+ return 0.;
}
- return distanceFunction.getDistanceFactory().parseString("" + StrictMath.exp(getValueAt(k)));
+ return Math.exp(getValueAt(k));
}
/**
@@ -171,10 +165,10 @@ public class ApproximationLine implements Externalizable {
*/
@Override
public boolean equals(Object o) {
- if(this == o) {
+ if (this == o) {
return true;
}
- if(o == null || getClass() != o.getClass()) {
+ if (o == null || getClass() != o.getClass()) {
return false;
}
@@ -208,4 +202,4 @@ public class ApproximationLine implements Externalizable {
public String toString() {
return "m = " + m + ", t = " + t + " k_0 " + k_0;
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/ConvexHull.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/ConvexHull.java
index 6787aa9c..fe0e20b0 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/ConvexHull.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/ConvexHull.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkcop;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPDirectoryEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPDirectoryEntry.java
index 22b4efa4..8b6282a3 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPDirectoryEntry.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPDirectoryEntry.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkcop;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,8 +28,6 @@ import java.io.ObjectInput;
import java.io.ObjectOutput;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeDirectoryEntry;
/**
@@ -39,8 +37,11 @@ import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeDirectoryEntry
*
* @author Elke Achtert
*/
-class MkCoPDirectoryEntry<D extends NumberDistance<D, ?>> extends MTreeDirectoryEntry<D> implements MkCoPEntry<D> {
- private static final long serialVersionUID = 1;
+class MkCoPDirectoryEntry extends MTreeDirectoryEntry implements MkCoPEntry {
+ /**
+ * Serialization version number.
+ */
+ private static final long serialVersionUID = 2;
/**
* The conservative approximation.
@@ -64,7 +65,7 @@ class MkCoPDirectoryEntry<D extends NumberDistance<D, ?>> extends MTreeDirectory
* @param conservativeApproximation the conservative approximation of the knn
* distances
*/
- public MkCoPDirectoryEntry(DBID objectID, D parentDistance, Integer nodeID, D coveringRadius, ApproximationLine conservativeApproximation) {
+ public MkCoPDirectoryEntry(DBID objectID, double parentDistance, Integer nodeID, double coveringRadius, ApproximationLine conservativeApproximation) {
super(objectID, parentDistance, nodeID, coveringRadius);
this.conservativeApproximation = conservativeApproximation;
}
@@ -73,12 +74,11 @@ class MkCoPDirectoryEntry<D extends NumberDistance<D, ?>> extends MTreeDirectory
* Returns the conservative approximated knn distance of the entry.
*
* @param k the parameter k of the knn distance
- * @param distanceFunction the distance function
* @return the conservative approximated knn distance of the entry
*/
@Override
- public <O> D approximateConservativeKnnDistance(int k, DistanceQuery<O, D> distanceFunction) {
- return conservativeApproximation.getApproximatedKnnDistance(k, distanceFunction);
+ public double approximateConservativeKnnDistance(int k) {
+ return conservativeApproximation.getApproximatedKnnDistance(k);
}
/**
@@ -138,20 +138,19 @@ class MkCoPDirectoryEntry<D extends NumberDistance<D, ?>> extends MTreeDirectory
* and has the same conservative approximation as this entry.
*/
@Override
- @SuppressWarnings("unchecked")
public boolean equals(Object o) {
- if(this == o) {
+ if (this == o) {
return true;
}
- if(o == null || getClass() != o.getClass()) {
+ if (o == null || getClass() != o.getClass()) {
return false;
}
- if(!super.equals(o)) {
+ if (!super.equals(o)) {
return false;
}
- final MkCoPDirectoryEntry<D> that = (MkCoPDirectoryEntry<D>) o;
+ final MkCoPDirectoryEntry that = (MkCoPDirectoryEntry) o;
return !(conservativeApproximation != null ? !conservativeApproximation.equals(that.conservativeApproximation) : that.conservativeApproximation != null);
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPEntry.java
index 077fb1ec..ae569d03 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPEntry.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPEntry.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkcop;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,8 +23,6 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkcop;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry;
/**
@@ -36,17 +34,14 @@ import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry;
*
* @apiviz.composedOf ApproximationLine
*/
-interface MkCoPEntry<D extends NumberDistance<D, ?>> extends MTreeEntry<D> {
-
+interface MkCoPEntry extends MTreeEntry {
/**
* Returns the conservative approximated knn distance of the entry.
*
- * @param <O> Object type
* @param k the parameter k of the knn distance
- * @param distanceFunction the distance function
* @return the conservative approximated knn distance of the entry
*/
- public <O> D approximateConservativeKnnDistance(int k, DistanceQuery<O, D> distanceFunction);
+ public double approximateConservativeKnnDistance(int k);
/**
* Returns the conservative approximation line.
@@ -62,4 +57,4 @@ interface MkCoPEntry<D extends NumberDistance<D, ?>> extends MTreeEntry<D> {
* set
*/
public void setConservativeKnnDistanceApproximation(ApproximationLine conservativeApproximation);
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPLeafEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPLeafEntry.java
index 0daf7950..7d241eba 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPLeafEntry.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPLeafEntry.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkcop;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,8 +28,6 @@ import java.io.ObjectInput;
import java.io.ObjectOutput;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeLeafEntry;
/**
@@ -39,8 +37,11 @@ import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeLeafEntry;
*
* @author Elke Achtert
*/
-class MkCoPLeafEntry<D extends NumberDistance<D, ?>> extends MTreeLeafEntry<D> implements MkCoPEntry<D> {
- private static final long serialVersionUID = 1;
+class MkCoPLeafEntry extends MTreeLeafEntry implements MkCoPEntry {
+ /**
+ * Serialization version ID.
+ */
+ private static final long serialVersionUID = 2;
/**
* The conservative approximation.
@@ -70,7 +71,7 @@ class MkCoPLeafEntry<D extends NumberDistance<D, ?>> extends MTreeLeafEntry<D> i
* @param progressiveApproximation the progressive approximation of the knn
* distances
*/
- public MkCoPLeafEntry(DBID objectID, D parentDistance, ApproximationLine conservativeApproximation, ApproximationLine progressiveApproximation) {
+ public MkCoPLeafEntry(DBID objectID, double parentDistance, ApproximationLine conservativeApproximation, ApproximationLine progressiveApproximation) {
super(objectID, parentDistance);
this.conservativeApproximation = conservativeApproximation;
this.progressiveApproximation = progressiveApproximation;
@@ -80,24 +81,21 @@ class MkCoPLeafEntry<D extends NumberDistance<D, ?>> extends MTreeLeafEntry<D> i
* Returns the conservative approximated knn distance of the entry.
*
* @param k the parameter k of the knn distance
- * @param distanceFunction the distance function
* @return the conservative approximated knn distance of the entry
*/
@Override
- public <O> D approximateConservativeKnnDistance(int k, DistanceQuery<O, D> distanceFunction) {
- return conservativeApproximation.getApproximatedKnnDistance(k, distanceFunction);
+ public double approximateConservativeKnnDistance(int k) {
+ return conservativeApproximation.getApproximatedKnnDistance(k);
}
/**
* Returns the progressive approximated knn distance of the entry.
*
- * @param <O> Object type
* @param k the parameter k of the knn distance
- * @param distanceFunction the distance function
* @return the progressive approximated knn distance of the entry
*/
- public <O> D approximateProgressiveKnnDistance(int k, DistanceQuery<O, D> distanceFunction) {
- return progressiveApproximation.getApproximatedKnnDistance(k, distanceFunction);
+ public double approximateProgressiveKnnDistance(int k) {
+ return progressiveApproximation.getApproximatedKnnDistance(k);
}
/**
@@ -180,21 +178,20 @@ class MkCoPLeafEntry<D extends NumberDistance<D, ?>> extends MTreeLeafEntry<D> i
* entry.
*/
@Override
- @SuppressWarnings("unchecked")
public boolean equals(Object o) {
- if(this == o) {
+ if (this == o) {
return true;
}
- if(o == null || getClass() != o.getClass()) {
+ if (o == null || getClass() != o.getClass()) {
return false;
}
- if(!super.equals(o)) {
+ if (!super.equals(o)) {
return false;
}
- final MkCoPLeafEntry<D> that = (MkCoPLeafEntry<D>) o;
+ final MkCoPLeafEntry that = (MkCoPLeafEntry) o;
- if(conservativeApproximation != null ? !conservativeApproximation.equals(that.conservativeApproximation) : that.conservativeApproximation != null) {
+ if (conservativeApproximation != null ? !conservativeApproximation.equals(that.conservativeApproximation) : that.conservativeApproximation != null) {
return false;
}
@@ -211,4 +208,4 @@ class MkCoPLeafEntry<D extends NumberDistance<D, ?>> extends MTreeLeafEntry<D> i
return super.toString() + "\ncons " + conservativeApproximation + "\n";
// "prog " + progressiveApproximation;
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTree.java
index 562f7f4a..b98d6821 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTree.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTree.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkcop;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -32,20 +32,20 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
-import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultIter;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.GenericDistanceDBIDList;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
+import de.lmu.ifi.dbs.elki.database.ids.generic.GenericDistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.AbstractMkTree;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.MkTreeSettings;
import de.lmu.ifi.dbs.elki.index.tree.query.GenericMTreeDistanceSearchCandidate;
import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.persistent.ByteArrayUtil;
import de.lmu.ifi.dbs.elki.persistent.PageFile;
import de.lmu.ifi.dbs.elki.utilities.FormatUtil;
-import de.lmu.ifi.dbs.elki.utilities.QueryStatistic;
-import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.Heap;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.ComparableMinHeap;
/**
* MkCopTree is a metrical index structure based on the concepts of the M-Tree
@@ -55,46 +55,34 @@ import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.Heap;
* @author Elke Achtert
*
* @apiviz.has MkCoPTreeNode oneway - - contains
- * @apiviz.uses ConvexHull
+ * @apiviz.has ConvexHull
*
* @param <O> Object type
* @param <D> Distance type
*/
-public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree<O, D, MkCoPTreeNode<O, D>, MkCoPEntry<D>> {
+public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree<O, D, MkCoPTreeNode<O, D>, MkCoPEntry, MkTreeSettings<O, D, MkCoPTreeNode<O, D>, MkCoPEntry>> {
/**
* The logger for this class.
*/
private static final Logging LOG = Logging.getLogger(MkCoPTree.class);
/**
- * Parameter k.
- */
- int k_max;
-
- /**
* The values of log(1),..,log(k_max)
*/
private double[] log_k;
/**
- * Provides some statistics about performed reverse knn-queries.
- */
- private QueryStatistic rkNNStatistics = new QueryStatistic();
-
- /**
* Constructor.
*
+ * @param relation Relation to index
* @param pagefile Page file
- * @param distanceQuery Distance query
- * @param distanceFunction Distance function
- * @param k_max Maximum value of k supported
+ * @param settings Tree settings
*/
- public MkCoPTree(PageFile<MkCoPTreeNode<O, D>> pagefile, DistanceQuery<O, D> distanceQuery, DistanceFunction<O, D> distanceFunction, int k_max) {
- super(pagefile, distanceQuery, distanceFunction);
- this.k_max = k_max;
+ public MkCoPTree(Relation<O> relation, PageFile<MkCoPTreeNode<O, D>> pagefile, MkTreeSettings<O, D, MkCoPTreeNode<O, D>, MkCoPEntry> settings) {
+ super(relation, pagefile, settings);
// init log k
- log_k = new double[k_max];
- for(int k = 1; k <= k_max; k++) {
+ log_k = new double[settings.k_max];
+ for (int k = 1; k <= settings.k_max; k++) {
log_k[k - 1] = Math.log(k);
}
}
@@ -103,7 +91,7 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
* @throws UnsupportedOperationException since this operation is not supported
*/
@Override
- protected void preInsert(MkCoPEntry<D> entry) {
+ protected void preInsert(MkCoPEntry entry) {
throw new UnsupportedOperationException("Insertion of single objects is not supported!");
}
@@ -111,40 +99,40 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
* @throws UnsupportedOperationException since this operation is not supported
*/
@Override
- public void insert(MkCoPEntry<D> entry, boolean withPreInsert) {
+ public void insert(MkCoPEntry entry, boolean withPreInsert) {
throw new UnsupportedOperationException("Insertion of single objects is not supported!");
}
@Override
- public void insertAll(List<MkCoPEntry<D>> entries) {
- if(entries.isEmpty()) {
+ public void insertAll(List<MkCoPEntry> entries) {
+ if (entries.isEmpty()) {
return;
}
- if(LOG.isDebugging()) {
+ if (LOG.isDebugging()) {
LOG.debugFine("insert " + entries + "\n");
}
- if(!initialized) {
+ if (!initialized) {
initialize(entries.get(0));
}
ModifiableDBIDs ids = DBIDUtil.newArray(entries.size());
// insert
- for(MkCoPEntry<D> entry : entries) {
+ for (MkCoPEntry entry : entries) {
ids.add(entry.getRoutingObjectID());
// insert the object
super.insert(entry, false);
}
// perform nearest neighbor queries
- Map<DBID, KNNResult<D>> knnLists = batchNN(getRoot(), ids, k_max);
+ Map<DBID, KNNList<D>> knnLists = batchNN(getRoot(), ids, settings.k_max);
// adjust the knn distances
adjustApproximatedKNNDistances(getRootEntry(), knnLists);
- if(EXTRA_INTEGRITY_CHECKS) {
+ if (EXTRA_INTEGRITY_CHECKS) {
getRoot().integrityCheck(this, getRootEntry());
}
}
@@ -158,29 +146,30 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
* @return a List of the query results
*/
@Override
- public DistanceDBIDResult<D> reverseKNNQuery(DBIDRef id, int k) {
- if(k > this.k_max) {
+ public DistanceDBIDList<D> reverseKNNQuery(DBIDRef id, int k) {
+ if (k > settings.k_max) {
throw new IllegalArgumentException("Parameter k has to be less or equal than " + "parameter kmax of the MCop-Tree!");
}
- GenericDistanceDBIDList<D> result = new GenericDistanceDBIDList<D>();
+ GenericDistanceDBIDList<D> result = new GenericDistanceDBIDList<>();
ModifiableDBIDs candidates = DBIDUtil.newArray();
doReverseKNNQuery(k, id, result, candidates);
// refinement of candidates
- Map<DBID, KNNResult<D>> knnLists = batchNN(getRoot(), candidates, k);
+ Map<DBID, KNNList<D>> knnLists = batchNN(getRoot(), candidates, k);
result.sort();
// Collections.sort(candidates);
- rkNNStatistics.addCandidates(candidates.size());
- rkNNStatistics.addTrueHits(result.size());
+ // FIXME: re-add statistics.
+ // rkNNStatistics.addCandidates(candidates.size());
+ // rkNNStatistics.addTrueHits(result.size());
- for(DBIDIter iter = candidates.iter(); iter.valid(); iter.advance()) {
+ for (DBIDIter iter = candidates.iter(); iter.valid(); iter.advance()) {
DBID cid = DBIDUtil.deref(iter);
- KNNResult<D> cands = knnLists.get(cid);
- for (DistanceDBIDResultIter<D> iter2 = cands.iter(); iter2.valid(); iter2.advance()) {
- if(DBIDUtil.equal(id, iter2)) {
+ KNNList<D> cands = knnLists.get(cid);
+ for (DistanceDBIDListIter<D> iter2 = cands.iter(); iter2.valid(); iter2.advance()) {
+ if (DBIDUtil.equal(id, iter2)) {
result.add(iter2.getDistance(), cid);
break;
}
@@ -188,45 +177,30 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
}
result.sort();
- rkNNStatistics.addResults(result.size());
+ // FIXME: re-add statistics.
+ // rkNNStatistics.addResults(result.size());
return result;
}
/**
- * Returns the statistic for performed rknn queries.
- *
- * @return the statistic for performed rknn queries
- */
- public QueryStatistic getRkNNStatistics() {
- return rkNNStatistics;
- }
-
- /**
- * Clears the values of the statistic for performed rknn queries
- */
- public void clearRkNNStatistics() {
- rkNNStatistics.clear();
- }
-
- /**
* Returns the value of the k_max parameter.
*
* @return the value of the k_max parameter
*/
public int getK_max() {
- return k_max;
+ return settings.k_max;
}
/**
* Determines the maximum and minimum number of entries in a node.
*/
@Override
- protected void initializeCapacities(MkCoPEntry<D> exampleLeaf) {
- int distanceSize = exampleLeaf.getParentDistance().externalizableSize();
+ protected void initializeCapacities(MkCoPEntry exampleLeaf) {
+ int distanceSize = ByteArrayUtil.SIZE_DOUBLE; // exampleLeaf.getParentDistance().externalizableSize();
// overhead = index(4), numEntries(4), id(4), isLeaf(0.125)
double overhead = 12.125;
- if(getPageSize() - overhead < 0) {
+ if (getPageSize() - overhead < 0) {
throw new RuntimeException("Node size of " + getPageSize() + " Bytes is chosen too small!");
}
@@ -234,11 +208,11 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
// coveringRadius + parentDistance + consApprox) + 1
dirCapacity = (int) (getPageSize() - overhead) / (4 + 4 + distanceSize + distanceSize + 10) + 1;
- if(dirCapacity <= 1) {
+ if (dirCapacity <= 1) {
throw new RuntimeException("Node size of " + getPageSize() + " Bytes is chosen too small!");
}
- if(dirCapacity < 10) {
+ if (dirCapacity < 10) {
LOG.warning("Page size is choosen too small! Maximum number of entries " + "in a directory node = " + (dirCapacity - 1));
}
@@ -247,17 +221,17 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
// consApprox + progrApprox) + 1
leafCapacity = (int) (getPageSize() - overhead) / (4 + distanceSize + 2 * 10) + 1;
- if(leafCapacity <= 1) {
+ if (leafCapacity <= 1) {
throw new RuntimeException("Node size of " + getPageSize() + " Bytes is chosen too small!");
}
- if(leafCapacity < 10) {
+ if (leafCapacity < 10) {
LOG.warning("Page size is choosen too small! Maximum number of entries " + "in a leaf node = " + (leafCapacity - 1));
}
initialized = true;
- if(LOG.isVerbose()) {
+ if (LOG.isVerbose()) {
LOG.verbose("Directory Capacity: " + (dirCapacity - 1) + "\nLeaf Capacity: " + (leafCapacity - 1));
}
}
@@ -272,45 +246,44 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
* refinement)
*/
private void doReverseKNNQuery(int k, DBIDRef q, GenericDistanceDBIDList<D> result, ModifiableDBIDs candidates) {
- final Heap<GenericMTreeDistanceSearchCandidate<D>> pq = new Heap<GenericMTreeDistanceSearchCandidate<D>>();
+ final ComparableMinHeap<GenericMTreeDistanceSearchCandidate> pq = new ComparableMinHeap<>();
// push root
- pq.add(new GenericMTreeDistanceSearchCandidate<D>(getDistanceQuery().nullDistance(), getRootID(), null, null));
+ pq.add(new GenericMTreeDistanceSearchCandidate(0., getRootID(), null));
// search in tree
- while(!pq.isEmpty()) {
- GenericMTreeDistanceSearchCandidate<D> pqNode = pq.poll();
+ while (!pq.isEmpty()) {
+ GenericMTreeDistanceSearchCandidate pqNode = pq.poll();
// FIXME: cache the distance to the routing object in the queue node!
MkCoPTreeNode<O, D> node = getNode(pqNode.nodeID);
// directory node
- if(!node.isLeaf()) {
- for(int i = 0; i < node.getNumEntries(); i++) {
- MkCoPEntry<D> entry = node.getEntry(i);
- D distance = getDistanceQuery().distance(entry.getRoutingObjectID(), q);
- D minDist = entry.getCoveringRadius().compareTo(distance) > 0 ? getDistanceQuery().nullDistance() : distance.minus(entry.getCoveringRadius());
- D approximatedKnnDist_cons = entry.approximateConservativeKnnDistance(k, getDistanceQuery());
-
- if(minDist.compareTo(approximatedKnnDist_cons) <= 0) {
- pq.add(new GenericMTreeDistanceSearchCandidate<D>(minDist, getPageID(entry), entry.getRoutingObjectID(), null));
+ if (!node.isLeaf()) {
+ for (int i = 0; i < node.getNumEntries(); i++) {
+ MkCoPEntry entry = node.getEntry(i);
+ double distance = distance(entry.getRoutingObjectID(), q).doubleValue();
+ double minDist = entry.getCoveringRadius() > distance ? 0. : distance - entry.getCoveringRadius();
+ double approximatedKnnDist_cons = entry.approximateConservativeKnnDistance(k);
+
+ if (minDist <= approximatedKnnDist_cons) {
+ pq.add(new GenericMTreeDistanceSearchCandidate(minDist, getPageID(entry), entry.getRoutingObjectID()));
}
}
}
// data node
else {
- for(int i = 0; i < node.getNumEntries(); i++) {
- MkCoPLeafEntry<D> entry = (MkCoPLeafEntry<D>) node.getEntry(i);
- D distance = getDistanceQuery().distance(entry.getRoutingObjectID(), q);
- D approximatedKnnDist_prog = entry.approximateProgressiveKnnDistance(k, getDistanceQuery());
+ for (int i = 0; i < node.getNumEntries(); i++) {
+ MkCoPLeafEntry entry = (MkCoPLeafEntry) node.getEntry(i);
+ D distance = distance(entry.getRoutingObjectID(), q);
+ double approximatedKnnDist_prog = entry.approximateProgressiveKnnDistance(k);
- if(distance.compareTo(approximatedKnnDist_prog) <= 0) {
+ if (distance.doubleValue() <= approximatedKnnDist_prog) {
result.add(distance, entry.getRoutingObjectID());
- }
- else {
- D approximatedKnnDist_cons = entry.approximateConservativeKnnDistance(k, getDistanceQuery());
- double diff = distance.doubleValue() - approximatedKnnDist_cons.doubleValue();
- if(diff <= 0.0000000001) {
+ } else {
+ double approximatedKnnDist_cons = entry.approximateConservativeKnnDistance(k);
+ double diff = distance.doubleValue() - approximatedKnnDist_cons;
+ if (diff <= 1E-10) {
candidates.add(entry.getRoutingObjectID());
}
}
@@ -325,23 +298,22 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
* @param entry the root entry of the current subtree
* @param knnLists a map of knn lists for each leaf entry
*/
- private void adjustApproximatedKNNDistances(MkCoPEntry<D> entry, Map<DBID, KNNResult<D>> knnLists) {
+ private void adjustApproximatedKNNDistances(MkCoPEntry entry, Map<DBID, KNNList<D>> knnLists) {
MkCoPTreeNode<O, D> node = getNode(entry);
- if(node.isLeaf()) {
- for(int i = 0; i < node.getNumEntries(); i++) {
- MkCoPLeafEntry<D> leafEntry = (MkCoPLeafEntry<D>) node.getEntry(i);
+ if (node.isLeaf()) {
+ for (int i = 0; i < node.getNumEntries(); i++) {
+ MkCoPLeafEntry leafEntry = (MkCoPLeafEntry) node.getEntry(i);
approximateKnnDistances(leafEntry, knnLists.get(leafEntry.getRoutingObjectID()));
}
- }
- else {
- for(int i = 0; i < node.getNumEntries(); i++) {
- MkCoPEntry<D> dirEntry = node.getEntry(i);
+ } else {
+ for (int i = 0; i < node.getNumEntries(); i++) {
+ MkCoPEntry dirEntry = node.getEntry(i);
adjustApproximatedKNNDistances(dirEntry, knnLists);
}
}
- ApproximationLine approx = node.conservativeKnnDistanceApproximation(k_max);
+ ApproximationLine approx = node.conservativeKnnDistanceApproximation(settings.k_max);
entry.setConservativeKnnDistanceApproximation(approx);
}
@@ -351,7 +323,7 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
private double ssqerr(int k0, int kmax, double[] logk, double[] log_kDist, double m, double t) {
int k = kmax - k0;
double result = 0;
- for(int i = 0; i < k; i++) {
+ for (int i = 0; i < k; i++) {
// double h = log_kDist[i] - (m * (logk[i] - logk[0]) + t); ???
double h = log_kDist[i] - m * logk[i] - t;
result += h * h;
@@ -377,33 +349,32 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
* @param knnDistances TODO: Spezialbehandlung fuer identische Punkte in DB
* (insbes. Distanz 0)
*/
- private void approximateKnnDistances(MkCoPLeafEntry<D> entry, KNNResult<D> knnDistances) {
+ private void approximateKnnDistances(MkCoPLeafEntry entry, KNNList<D> knnDistances) {
StringBuilder msg = LOG.isDebugging() ? new StringBuilder() : null;
- if(msg != null) {
+ if (msg != null) {
msg.append("\nknnDistances ").append(knnDistances);
}
// count the zero distances
int k_0 = 0;
- for(int i = 0; i < k_max; i++) {
+ for (int i = 0; i < settings.k_max; i++) {
double dist = knnDistances.get(i).getDistance().doubleValue();
- if(dist == 0) {
+ if (dist == 0) {
k_0++;
- }
- else {
+ } else {
break;
}
}
// init variables
- double[] log_k = new double[k_max - k_0];
- System.arraycopy(this.log_k, k_0, log_k, 0, k_max - k_0);
+ double[] log_k = new double[settings.k_max - k_0];
+ System.arraycopy(this.log_k, k_0, log_k, 0, settings.k_max - k_0);
double sum_log_kDist = 0;
double sum_log_k_kDist = 0;
- double[] log_kDist = new double[k_max - k_0];
+ double[] log_kDist = new double[settings.k_max - k_0];
- for(int i = 0; i < k_max - k_0; i++) {
+ for (int i = 0; i < settings.k_max - k_0; i++) {
double dist = knnDistances.get(i + k_0).getDistance().doubleValue();
log_kDist[i] = Math.log(dist);
sum_log_kDist += log_kDist[i];
@@ -413,14 +384,14 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
double sum_log_k = 0;
double sum_log_k2 = 0;
// noinspection ForLoopReplaceableByForEach
- for(int i = 0; i < log_k.length; i++) {
+ for (int i = 0; i < log_k.length; i++) {
sum_log_k += log_k[i];
sum_log_k2 += (log_k[i] * log_k[i]);
}
- if(msg != null) {
+ if (msg != null) {
msg.append("\nk_0 ").append(k_0);
- msg.append("\nk_max ").append(k_max);
+ msg.append("\nk_max ").append(settings.k_max);
msg.append("\nlog_k(").append(log_k.length).append(") ").append(FormatUtil.format(log_k));
msg.append("\nsum_log_k ").append(sum_log_k);
msg.append("\nsum_log_k^2 ").append(sum_log_k2);
@@ -438,15 +409,15 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
ApproximationLine c2 = approximateUpperHull_PAPER(convexHull, log_k, sum_log_k, sum_log_k2, log_kDist, sum_log_kDist, sum_log_k_kDist);
- double err1 = ssqerr(k_0, k_max, log_k, log_kDist, conservative.getM(), conservative.getT());
- double err2 = ssqerr(k_0, k_max, log_k, log_kDist, c2.getM(), c2.getT());
+ double err1 = ssqerr(k_0, settings.k_max, log_k, log_kDist, conservative.getM(), conservative.getT());
+ double err2 = ssqerr(k_0, settings.k_max, log_k, log_kDist, c2.getM(), c2.getT());
- if(msg != null) {
+ if (msg != null) {
msg.append("err1 ").append(err1);
msg.append("err2 ").append(err2);
}
- if(err1 > err2 && err1 - err2 > 0.000000001) {
+ if (err1 > err2 && err1 - err2 > 0.000000001) {
// if (err1 > err2) {
StringBuilder warning = new StringBuilder();
@@ -460,7 +431,7 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
warning.append("\nconservative1 ").append(conservative);
warning.append("\nconservative2 ").append(c2);
- for(int i = 0; i < u; i++) {
+ for (int i = 0; i < u; i++) {
warning.append("\nlog_k[").append(upperHull[i]).append("] = ").append(log_k[upperHull[i]]);
warning.append("\nlog_kDist[").append(upperHull[i]).append("] = ").append(log_kDist[upperHull[i]]);
}
@@ -473,7 +444,7 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
entry.setConservativeKnnDistanceApproximation(conservative);
entry.setProgressiveKnnDistanceApproximation(progressive);
- if(msg != null) {
+ if (msg != null) {
LOG.debugFine(msg.toString());
}
}
@@ -491,7 +462,7 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
StringBuilder msg = new StringBuilder();
int[] lowerHull = convexHull.getLowerHull();
int l = convexHull.getNumberOfPointsInLowerHull();
- int k_0 = k_max - lowerHull.length + 1;
+ int k_0 = settings.k_max - lowerHull.length + 1;
// linear search on all line segments on the lower convex hull
msg.append("lower hull l = ").append(l).append("\n");
@@ -499,12 +470,12 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
double low_m = 0.0;
double low_t = 0.0;
- for(int i = 1; i < l; i++) {
+ for (int i = 1; i < l; i++) {
double cur_m = (log_kDist[lowerHull[i]] - log_kDist[lowerHull[i - 1]]) / (log_k[lowerHull[i]] - log_k[lowerHull[i - 1]]);
double cur_t = log_kDist[lowerHull[i]] - cur_m * log_k[lowerHull[i]];
- double cur_error = ssqerr(k_0, k_max, log_k, log_kDist, cur_m, cur_t);
+ double cur_error = ssqerr(k_0, settings.k_max, log_k, log_kDist, cur_m, cur_t);
msg.append(" Segment = ").append(i).append(" m = ").append(cur_m).append(" t = ").append(cur_t).append(" lowerror = ").append(cur_error).append("\n");
- if(cur_error < low_error) {
+ if (cur_error < low_error) {
low_error = cur_error;
low_m = cur_m;
low_t = cur_t;
@@ -513,13 +484,13 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
// linear search on all points of the lower convex hull
boolean is_right = true; // NEEDED FOR PROOF CHECK
- for(int i = 0; i < l; i++) {
- double cur_m = optimize(k_0, k_max, sum_log_k, sum_log_k2, log_k[lowerHull[i]], log_kDist[lowerHull[i]], sum_log_k_kDist, sum_log_kDist);
+ for (int i = 0; i < l; i++) {
+ double cur_m = optimize(k_0, settings.k_max, sum_log_k, sum_log_k2, log_k[lowerHull[i]], log_kDist[lowerHull[i]], sum_log_k_kDist, sum_log_kDist);
double cur_t = log_kDist[lowerHull[i]] - cur_m * log_k[lowerHull[i]];
// only valid if both neighboring points are underneath y=mx+t
- if((i == 0 || log_kDist[lowerHull[i - 1]] >= log_kDist[lowerHull[i]] - cur_m * (log_k[lowerHull[i]] - log_k[lowerHull[i - 1]])) && (i == l - 1 || log_kDist[lowerHull[i + 1]] >= log_kDist[lowerHull[i]] + cur_m * (log_k[lowerHull[i + 1]] - log_k[lowerHull[i]]))) {
- double cur_error = ssqerr(k_0, k_max, log_k, log_kDist, cur_m, cur_t);
- if(cur_error < low_error) {
+ if ((i == 0 || log_kDist[lowerHull[i - 1]] >= log_kDist[lowerHull[i]] - cur_m * (log_k[lowerHull[i]] - log_k[lowerHull[i - 1]])) && (i == l - 1 || log_kDist[lowerHull[i + 1]] >= log_kDist[lowerHull[i]] + cur_m * (log_k[lowerHull[i + 1]] - log_k[lowerHull[i]]))) {
+ double cur_error = ssqerr(k_0, settings.k_max, log_k, log_kDist, cur_m, cur_t);
+ if (cur_error < low_error) {
low_error = cur_error;
low_m = cur_m;
low_t = cur_t;
@@ -527,9 +498,9 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
}
// check proof of bisection search
- if(!(i > 0 && log_kDist[lowerHull[i - 1]] < log_kDist[lowerHull[i]] - cur_m * (log_k[lowerHull[i]] - log_k[lowerHull[i - 1]])) && !is_right) {
+ if (!(i > 0 && log_kDist[lowerHull[i - 1]] < log_kDist[lowerHull[i]] - cur_m * (log_k[lowerHull[i]] - log_k[lowerHull[i - 1]])) && !is_right) {
// warning("ERROR lower: The bisection search will not work properly !");
- if(!(i < l - 1 && log_kDist[lowerHull[i + 1]] < log_kDist[lowerHull[i]] + cur_m * (log_k[lowerHull[i + 1]] - log_k[lowerHull[i]]))) {
+ if (!(i < l - 1 && log_kDist[lowerHull[i + 1]] < log_kDist[lowerHull[i]] + cur_m * (log_k[lowerHull[i + 1]] - log_k[lowerHull[i]]))) {
is_right = false;
}
}
@@ -544,18 +515,18 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
int[] upperHull = convexHull.getUpperHull();
int u = convexHull.getNumberOfPointsInUpperHull();
- int k_0 = k_max - upperHull.length + 1;
+ int k_0 = settings.k_max - upperHull.length + 1;
ApproximationLine approx = null;
double error = Double.POSITIVE_INFINITY;
- for(int i = 0; i < u - 1; i++) {
+ for (int i = 0; i < u - 1; i++) {
int ii = upperHull[i];
int jj = upperHull[i + 1];
double current_m = (log_kDist[jj] - log_kDist[ii]) / (log_k[jj] - log_k[ii]);
double current_t = log_kDist[ii] - current_m * log_k[ii];
ApproximationLine current_approx = new ApproximationLine(k_0, current_m, current_t);
- if(LOG.isDebugging()) {
+ if (LOG.isDebugging()) {
msg.append("\nlog_kDist[").append(jj).append("] ").append(log_kDist[jj]);
msg.append("\nlog_kDist[").append(ii).append("] ").append(log_kDist[ii]);
msg.append("\nlog_k[").append(jj).append("] ").append(log_k[jj]);
@@ -566,22 +537,22 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
boolean ok = true;
double currentError = 0;
- for(int k = k_0; k <= k_max; k++) {
+ for (int k = k_0; k <= settings.k_max; k++) {
double appDist = current_approx.getValueAt(k);
- if(appDist < log_kDist[k - k_0] && log_kDist[k - k_0] - appDist > 0.000000001) {
+ if (appDist < log_kDist[k - k_0] && log_kDist[k - k_0] - appDist > 0.000000001) {
ok = false;
break;
}
currentError += (appDist - log_kDist[k - k_0]);
}
- if(ok && currentError < error) {
+ if (ok && currentError < error) {
approx = current_approx;
error = currentError;
}
}
- if(LOG.isDebugging()) {
+ if (LOG.isDebugging()) {
msg.append("\nupper Approx ").append(approx);
LOG.debugFine(msg.toString());
}
@@ -594,22 +565,22 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
int[] upperHull = convexHull.getUpperHull();
int u = convexHull.getNumberOfPointsInUpperHull();
- List<Integer> marked = new ArrayList<Integer>();
+ List<Integer> marked = new ArrayList<>();
- int k_0 = k_max - upperHull.length + 1;
+ int k_0 = settings.k_max - upperHull.length + 1;
int a = u / 2;
- while(marked.size() != u) {
+ while (marked.size() != u) {
marked.add(a);
double x_a = log_k[upperHull[a]];
double y_a = log_kDist[upperHull[a]];
- double m_a = optimize(k_0, k_max, sum_log_k, sum_log_k2, x_a, y_a, sum_log_k_kDist, sum_log_kDist);
+ double m_a = optimize(k_0, settings.k_max, sum_log_k, sum_log_k2, x_a, y_a, sum_log_k_kDist, sum_log_kDist);
double t_a = y_a - m_a * x_a;
- if(msg != null) {
+ if (msg != null) {
msg.append("\na=").append(a).append(" m_a=").append(m_a).append(", t_a=").append(t_a);
- msg.append("\n err ").append(ssqerr(k_0, k_max, log_k, log_kDist, m_a, m_a));
+ msg.append("\n err ").append(ssqerr(k_0, settings.k_max, log_k, log_kDist, m_a, m_a));
}
double x_p = a == 0 ? Double.NaN : log_k[upperHull[a - 1]];
@@ -620,24 +591,23 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
boolean lessThanPre = a == 0 || y_p <= m_a * x_p + t_a;
boolean lessThanSuc = a == u || y_s <= m_a * x_s + t_a;
- if(lessThanPre && lessThanSuc) {
+ if (lessThanPre && lessThanSuc) {
ApproximationLine appr = new ApproximationLine(k_0, m_a, t_a);
- if(msg != null) {
+ if (msg != null) {
msg.append("\n1 anchor = ").append(a);
LOG.debugFine(msg.toString());
}
return appr;
- }
- else if(!lessThanPre) {
- if(marked.contains(a - 1)) {
+ } else if (!lessThanPre) {
+ if (marked.contains(a - 1)) {
m_a = (y_a - y_p) / (x_a - x_p);
- if(y_a == y_p) {
+ if (y_a == y_p) {
m_a = 0;
}
t_a = y_a - m_a * x_a;
ApproximationLine appr = new ApproximationLine(k_0, m_a, t_a);
- if(msg != null) {
+ if (msg != null) {
msg.append("2 anchor = ").append(a);
msg.append(" appr1 ").append(appr);
msg.append(" x_a ").append(x_a).append(", y_a ").append(y_a);
@@ -647,28 +617,25 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
LOG.debugFine(msg.toString());
}
return appr;
- }
- else {
+ } else {
a = a - 1;
}
- }
- else {
- if(marked.contains(a + 1)) {
+ } else {
+ if (marked.contains(a + 1)) {
m_a = (y_a - y_s) / (x_a - x_s);
- if(y_a == y_p) {
+ if (y_a == y_p) {
m_a = 0;
}
t_a = y_a - m_a * x_a;
ApproximationLine appr = new ApproximationLine(k_0, m_a, t_a);
- if(msg != null) {
+ if (msg != null) {
msg.append("3 anchor = ").append(a).append(" -- ").append((a + 1));
msg.append(" appr2 ").append(appr);
LOG.debugFine(msg.toString());
}
return appr;
- }
- else {
+ } else {
a = a + 1;
}
}
@@ -683,18 +650,18 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
StringBuilder msg = new StringBuilder();
int[] upperHull = convexHull.getUpperHull();
int u = convexHull.getNumberOfPointsInUpperHull();
- int k_0 = k_max - upperHull.length + 1;
+ int k_0 = settings.k_max - upperHull.length + 1;
// linear search on all line segments on the upper convex hull
msg.append("upper hull:").append(u);
double upp_error = Double.MAX_VALUE;
double upp_m = 0.0;
double upp_t = 0.0;
- for(int i = 1; i < u; i++) {
+ for (int i = 1; i < u; i++) {
double cur_m = (log_kDist[upperHull[i]] - log_kDist[upperHull[i - 1]]) / (log_k[upperHull[i]] - log_k[upperHull[i - 1]]);
double cur_t = log_kDist[upperHull[i]] - cur_m * log_k[upperHull[i]];
- double cur_error = ssqerr(k_0, k_max, log_k, log_kDist, cur_m, cur_t);
- if(cur_error < upp_error) {
+ double cur_error = ssqerr(k_0, settings.k_max, log_k, log_kDist, cur_m, cur_t);
+ if (cur_error < upp_error) {
upp_error = cur_error;
upp_m = cur_m;
upp_t = cur_t;
@@ -702,13 +669,13 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
}
// linear search on all points of the upper convex hull
boolean is_left = true; // NEEDED FOR PROOF CHECK
- for(int i = 0; i < u; i++) {
- double cur_m = optimize(k_0, k_max, sum_log_k, sum_log_k2, log_k[upperHull[i]], log_kDist[upperHull[i]], sum_log_k_kDist, sum_log_kDist);
+ for (int i = 0; i < u; i++) {
+ double cur_m = optimize(k_0, settings.k_max, sum_log_k, sum_log_k2, log_k[upperHull[i]], log_kDist[upperHull[i]], sum_log_k_kDist, sum_log_kDist);
double cur_t = log_kDist[upperHull[i]] - cur_m * log_k[upperHull[i]];
// only valid if both neighboring points are underneath y=mx+t
- if((i == 0 || log_kDist[upperHull[i - 1]] <= log_kDist[upperHull[i]] - cur_m * (log_k[upperHull[i]] - log_k[upperHull[i - 1]])) && (i == u - 1 || log_kDist[upperHull[i + 1]] <= log_kDist[upperHull[i]] + cur_m * (log_k[upperHull[i + 1]] - log_k[upperHull[i]]))) {
- double cur_error = ssqerr(k_0, k_max, log_k, log_kDist, cur_m, cur_t);
- if(cur_error < upp_error) {
+ if ((i == 0 || log_kDist[upperHull[i - 1]] <= log_kDist[upperHull[i]] - cur_m * (log_k[upperHull[i]] - log_k[upperHull[i - 1]])) && (i == u - 1 || log_kDist[upperHull[i + 1]] <= log_kDist[upperHull[i]] + cur_m * (log_k[upperHull[i + 1]] - log_k[upperHull[i]]))) {
+ double cur_error = ssqerr(k_0, settings.k_max, log_k, log_kDist, cur_m, cur_t);
+ if (cur_error < upp_error) {
upp_error = cur_error;
upp_m = cur_m;
upp_t = cur_t;
@@ -716,12 +683,12 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
}
// check proof of bisection search
- if(!(i > 0 && log_kDist[upperHull[i - 1]] > log_kDist[upperHull[i]] - cur_m * (log_k[upperHull[i]] - log_k[upperHull[i - 1]])) && !is_left) {
+ if (!(i > 0 && log_kDist[upperHull[i - 1]] > log_kDist[upperHull[i]] - cur_m * (log_k[upperHull[i]] - log_k[upperHull[i - 1]])) && !is_left) {
// warning("ERROR upper: The bisection search will not work properly !"
// +
// "\n" + Util.format(log_kDist));
}
- if(!(i < u - 1 && log_kDist[upperHull[i + 1]] > log_kDist[upperHull[i]] + cur_m * (log_k[upperHull[i + 1]] - log_k[upperHull[i]]))) {
+ if (!(i < u - 1 && log_kDist[upperHull[i + 1]] > log_kDist[upperHull[i]] + cur_m * (log_k[upperHull[i + 1]] - log_k[upperHull[i]]))) {
is_left = false;
}
}
@@ -737,7 +704,7 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
*/
@Override
protected MkCoPTreeNode<O, D> createNewLeafNode() {
- return new MkCoPTreeNode<O, D>(leafCapacity, true);
+ return new MkCoPTreeNode<>(leafCapacity, true);
}
/**
@@ -747,7 +714,7 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
*/
@Override
protected MkCoPTreeNode<O, D> createNewDirectoryNode() {
- return new MkCoPTreeNode<O, D>(dirCapacity, false);
+ return new MkCoPTreeNode<>(dirCapacity, false);
}
/**
@@ -759,8 +726,8 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
* the routing object of the parent node
*/
@Override
- protected MkCoPEntry<D> createNewDirectoryEntry(MkCoPTreeNode<O, D> node, DBID routingObjectID, D parentDistance) {
- return new MkCoPDirectoryEntry<D>(routingObjectID, parentDistance, node.getPageID(), node.coveringRadius(routingObjectID, this), null);
+ protected MkCoPEntry createNewDirectoryEntry(MkCoPTreeNode<O, D> node, DBID routingObjectID, double parentDistance) {
+ return new MkCoPDirectoryEntry(routingObjectID, parentDistance, node.getPageID(), node.coveringRadius(routingObjectID, this), null);
// node.conservativeKnnDistanceApproximation(k_max));
}
@@ -770,12 +737,12 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree
* @return an entry representing the root node
*/
@Override
- protected MkCoPEntry<D> createRootEntry() {
- return new MkCoPDirectoryEntry<D>(null, null, 0, null, null);
+ protected MkCoPEntry createRootEntry() {
+ return new MkCoPDirectoryEntry(null, 0., 0, 0., null);
}
@Override
protected Logging getLogger() {
return LOG;
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTreeIndex.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTreeIndex.java
index d3e45f8c..96def76b 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTreeIndex.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTreeIndex.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkcop;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,9 +28,7 @@ import java.util.List;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
@@ -43,12 +41,10 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.KNNIndex;
import de.lmu.ifi.dbs.elki.index.RKNNIndex;
import de.lmu.ifi.dbs.elki.index.RangeIndex;
-import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree;
-import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.AbstractMkTree;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.MkTreeSettings;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query.MTreeQueryUtil;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query.MkTreeRKNNQuery;
import de.lmu.ifi.dbs.elki.persistent.PageFile;
-import de.lmu.ifi.dbs.elki.utilities.exceptions.ExceptionMessages;
/**
* MkCoPTree used as database index.
@@ -69,14 +65,11 @@ public class MkCoPTreeIndex<O, D extends NumberDistance<D, ?>> extends MkCoPTree
*
* @param relation Relation to index.
* @param pageFile Page file
- * @param distanceQuery Distance query
- * @param distanceFunction Distance function
- * @param k_max Maximum value of k supported
+ * @param settings Tree settings
*/
- public MkCoPTreeIndex(Relation<O> relation, PageFile<MkCoPTreeNode<O, D>> pageFile, DistanceQuery<O, D> distanceQuery, DistanceFunction<O, D> distanceFunction, int k_max) {
- super(pageFile, distanceQuery, distanceFunction, k_max);
+ public MkCoPTreeIndex(Relation<O> relation, PageFile<MkCoPTreeNode<O, D>> pageFile, MkTreeSettings<O, D, MkCoPTreeNode<O, D>, MkCoPEntry> settings) {
+ super(relation, pageFile, settings);
this.relation = relation;
- this.initialize();
}
/**
@@ -87,120 +80,89 @@ public class MkCoPTreeIndex<O, D extends NumberDistance<D, ?>> extends MkCoPTree
* @param parentDistance the distance from the object to the routing object of
* the parent node
*/
- protected MkCoPEntry<D> createNewLeafEntry(DBID id, O object, D parentDistance) {
- MkCoPLeafEntry<D> leafEntry = new MkCoPLeafEntry<D>(id, parentDistance, null, null);
+ protected MkCoPEntry createNewLeafEntry(DBID id, O object, double parentDistance) {
+ MkCoPLeafEntry leafEntry = new MkCoPLeafEntry(id, parentDistance, null, null);
return leafEntry;
}
@Override
- public void insert(DBIDRef id) {
- throw new UnsupportedOperationException("Insertion of single objects is not supported!");
- }
-
- @Override
- public void insertAll(DBIDs ids) {
- List<MkCoPEntry<D>> objs = new ArrayList<MkCoPEntry<D>>(ids.size());
- for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
- DBID id = DBIDUtil.deref(iter);
+ public void initialize() {
+ super.initialize();
+ List<MkCoPEntry> objs = new ArrayList<>(relation.size());
+ for (DBIDIter iter = relation.iterDBIDs(); iter.valid(); iter.advance()) {
+ DBID id = DBIDUtil.deref(iter); // FIXME: expensive
final O object = relation.get(id);
- objs.add(createNewLeafEntry(id, object, getDistanceFactory().undefinedDistance()));
+ objs.add(createNewLeafEntry(id, object, Double.NaN));
}
insertAll(objs);
}
- /**
- * Throws an UnsupportedOperationException since deletion of objects is not
- * yet supported by an M-Tree.
- *
- * @throws UnsupportedOperationException thrown, since deletions aren't
- * implemented yet.
- */
- @Override
- public final boolean delete(DBIDRef id) {
- throw new UnsupportedOperationException(ExceptionMessages.UNSUPPORTED_NOT_YET);
- }
-
- /**
- * Throws an UnsupportedOperationException since deletion of objects is not
- * yet supported by an M-Tree.
- *
- * @throws UnsupportedOperationException thrown, since deletions aren't
- * implemented yet.
- */
- @Override
- public void deleteAll(DBIDs ids) {
- throw new UnsupportedOperationException(ExceptionMessages.UNSUPPORTED_NOT_YET);
- }
-
@SuppressWarnings("unchecked")
@Override
public <S extends Distance<S>> KNNQuery<O, S> getKNNQuery(DistanceQuery<O, S> distanceQuery, Object... hints) {
// Query on the relation we index
- if(distanceQuery.getRelation() != relation) {
+ if (distanceQuery.getRelation() != relation) {
return null;
}
- DistanceFunction<? super O, S> distanceFunction = distanceQuery.getDistanceFunction();
- if(!this.distanceFunction.equals(distanceFunction)) {
- if(getLogger().isDebugging()) {
+ DistanceFunction<? super O, D> distanceFunction = (DistanceFunction<? super O, D>) distanceQuery.getDistanceFunction();
+ if (!this.getDistanceFunction().equals(distanceFunction)) {
+ if (getLogger().isDebugging()) {
getLogger().debug("Distance function not supported by index - or 'equals' not implemented right!");
}
return null;
}
// Bulk is not yet supported
- for(Object hint : hints) {
- if(hint == DatabaseQuery.HINT_BULK) {
+ for (Object hint : hints) {
+ if (hint == DatabaseQuery.HINT_BULK) {
return null;
}
}
- AbstractMTree<O, S, ?, ?> idx = (AbstractMTree<O, S, ?, ?>) this;
- DistanceQuery<O, S> dq = distanceFunction.instantiate(relation);
- return MTreeQueryUtil.getKNNQuery(idx, dq, hints);
+ DistanceQuery<O, D> dq = distanceFunction.instantiate(relation);
+ return (KNNQuery<O, S>) MTreeQueryUtil.getKNNQuery(this, dq, hints);
}
@SuppressWarnings("unchecked")
@Override
public <S extends Distance<S>> RangeQuery<O, S> getRangeQuery(DistanceQuery<O, S> distanceQuery, Object... hints) {
// Query on the relation we index
- if(distanceQuery.getRelation() != relation) {
+ if (distanceQuery.getRelation() != relation) {
return null;
}
- DistanceFunction<? super O, S> distanceFunction = distanceQuery.getDistanceFunction();
- if(!this.distanceFunction.equals(distanceFunction)) {
- if(getLogger().isDebugging()) {
+ DistanceFunction<? super O, D> distanceFunction = (DistanceFunction<? super O, D>) distanceQuery.getDistanceFunction();
+ if (!this.getDistanceFunction().equals(distanceFunction)) {
+ if (getLogger().isDebugging()) {
getLogger().debug("Distance function not supported by index - or 'equals' not implemented right!");
}
return null;
}
// Bulk is not yet supported
- for(Object hint : hints) {
- if(hint == DatabaseQuery.HINT_BULK) {
+ for (Object hint : hints) {
+ if (hint == DatabaseQuery.HINT_BULK) {
return null;
}
}
- AbstractMTree<O, S, ?, ?> idx = (AbstractMTree<O, S, ?, ?>) this;
- DistanceQuery<O, S> dq = distanceFunction.instantiate(relation);
- return MTreeQueryUtil.getRangeQuery(idx, dq, hints);
+ DistanceQuery<O, D> dq = distanceFunction.instantiate(relation);
+ return (RangeQuery<O, S>) MTreeQueryUtil.getRangeQuery(this, dq, hints);
}
@SuppressWarnings("unchecked")
@Override
public <S extends Distance<S>> RKNNQuery<O, S> getRKNNQuery(DistanceQuery<O, S> distanceQuery, Object... hints) {
- DistanceFunction<? super O, S> distanceFunction = distanceQuery.getDistanceFunction();
- if(!this.getDistanceFunction().equals(distanceFunction)) {
- if(getLogger().isDebugging()) {
+ DistanceFunction<? super O, D> distanceFunction = (DistanceFunction<? super O, D>) distanceQuery.getDistanceFunction();
+ if (!this.getDistanceFunction().equals(distanceFunction)) {
+ if (getLogger().isDebugging()) {
getLogger().debug("Distance function not supported by index - or 'equals' not implemented right!");
}
return null;
}
// Bulk is not yet supported
- for(Object hint : hints) {
- if(hint == DatabaseQuery.HINT_BULK) {
+ for (Object hint : hints) {
+ if (hint == DatabaseQuery.HINT_BULK) {
return null;
}
}
- AbstractMkTree<O, S, ?, ?> idx = (AbstractMkTree<O, S, ?, ?>) this;
- DistanceQuery<O, S> dq = distanceFunction.instantiate(relation);
- return new MkTreeRKNNQuery<O, S>(idx, dq);
+ DistanceQuery<O, D> dq = distanceFunction.instantiate(relation);
+ return (RKNNQuery<O, S>) new MkTreeRKNNQuery<>(this, dq);
}
@Override
@@ -212,4 +174,4 @@ public class MkCoPTreeIndex<O, D extends NumberDistance<D, ?>> extends MkCoPTree
public String getShortName() {
return "mkcoptree";
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTreeNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTreeNode.java
index f2e4a114..79a9c6cc 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTreeNode.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTreeNode.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkcop;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -38,7 +38,7 @@ import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode;
* @param <O> object type
* @param <D> distance type
*/
-class MkCoPTreeNode<O, D extends NumberDistance<D, ?>> extends AbstractMTreeNode<O, D, MkCoPTreeNode<O, D>, MkCoPEntry<D>> {
+class MkCoPTreeNode<O, D extends NumberDistance<D, ?>> extends AbstractMTreeNode<O, D, MkCoPTreeNode<O, D>, MkCoPEntry> {
/**
* Serial version UID
*/
@@ -77,13 +77,13 @@ class MkCoPTreeNode<O, D extends NumberDistance<D, ?>> extends AbstractMTreeNode
double y_kmax = Double.NEGATIVE_INFINITY;
for(int i = 0; i < getNumEntries(); i++) {
- MkCoPEntry<D> entry = getEntry(i);
+ MkCoPEntry entry = getEntry(i);
ApproximationLine approx = entry.getConservativeKnnDistanceApproximation();
k_0 = Math.min(approx.getK_0(), k_0);
}
for(int i = 0; i < getNumEntries(); i++) {
- MkCoPEntry<D> entry = getEntry(i);
+ MkCoPEntry entry = getEntry(i);
ApproximationLine approx = entry.getConservativeKnnDistanceApproximation();
double entry_y_1 = approx.getValueAt(k_0);
double entry_y_kmax = approx.getValueAt(k_max);
@@ -122,13 +122,13 @@ class MkCoPTreeNode<O, D extends NumberDistance<D, ?>> extends AbstractMTreeNode
double y_kmax = Double.POSITIVE_INFINITY;
for(int i = 0; i < getNumEntries(); i++) {
- MkCoPLeafEntry<D> entry = (MkCoPLeafEntry<D>) getEntry(i);
+ MkCoPLeafEntry entry = (MkCoPLeafEntry) getEntry(i);
ApproximationLine approx = entry.getProgressiveKnnDistanceApproximation();
k_0 = Math.max(approx.getK_0(), k_0);
}
for(int i = 0; i < getNumEntries(); i++) {
- MkCoPLeafEntry<D> entry = (MkCoPLeafEntry<D>) getEntry(i);
+ MkCoPLeafEntry entry = (MkCoPLeafEntry) getEntry(i);
ApproximationLine approx = entry.getProgressiveKnnDistanceApproximation();
y_1 = Math.min(approx.getValueAt(k_0), y_1);
y_kmax = Math.min(approx.getValueAt(k_max), y_kmax);
@@ -142,7 +142,7 @@ class MkCoPTreeNode<O, D extends NumberDistance<D, ?>> extends AbstractMTreeNode
}
@Override
- public void adjustEntry(MkCoPEntry<D> entry, DBID routingObjectID, D parentDistance, AbstractMTree<O, D, MkCoPTreeNode<O, D>, MkCoPEntry<D>> mTree) {
+ public void adjustEntry(MkCoPEntry entry, DBID routingObjectID, double parentDistance, AbstractMTree<O, D, MkCoPTreeNode<O, D>, MkCoPEntry, ?> mTree) {
super.adjustEntry(entry, routingObjectID, parentDistance, mTree);
// adjust conservative distance approximation
// int k_max = ((MkCoPTree<O,D>) mTree).getK_max();
@@ -150,10 +150,10 @@ class MkCoPTreeNode<O, D extends NumberDistance<D, ?>> extends AbstractMTreeNode
}
@Override
- protected void integrityCheckParameters(MkCoPEntry<D> parentEntry, MkCoPTreeNode<O, D> parent, int index, AbstractMTree<O, D, MkCoPTreeNode<O, D>, MkCoPEntry<D>> mTree) {
+ protected void integrityCheckParameters(MkCoPEntry parentEntry, MkCoPTreeNode<O, D> parent, int index, AbstractMTree<O, D, MkCoPTreeNode<O, D>, MkCoPEntry, ?> mTree) {
super.integrityCheckParameters(parentEntry, parent, index, mTree);
// test conservative approximation
- MkCoPEntry<D> entry = parent.getEntry(index);
+ MkCoPEntry entry = parent.getEntry(index);
int k_max = ((MkCoPTree<O, D>) mTree).getK_max();
ApproximationLine approx = conservativeKnnDistanceApproximation(k_max);
if(!entry.getConservativeKnnDistanceApproximation().equals(approx)) {
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCopTreeFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCopTreeFactory.java
index 4ac96df3..6a39e92f 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCopTreeFactory.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCopTreeFactory.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkcop;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,10 +24,11 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkcop;
*/
import de.lmu.ifi.dbs.elki.database.relation.Relation;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeFactory;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.MkTreeSettings;
import de.lmu.ifi.dbs.elki.persistent.PageFile;
+import de.lmu.ifi.dbs.elki.persistent.PageFileFactory;
import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
@@ -45,35 +46,26 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
* @param <O> Object type
* @param <D> Distance type
*/
-public class MkCopTreeFactory<O, D extends NumberDistance<D, ?>> extends AbstractMTreeFactory<O, D, MkCoPTreeNode<O, D>, MkCoPEntry<D>, MkCoPTreeIndex<O, D>> {
+public class MkCopTreeFactory<O, D extends NumberDistance<D, ?>> extends AbstractMTreeFactory<O, D, MkCoPTreeNode<O, D>, MkCoPEntry, MkCoPTreeIndex<O, D>, MkTreeSettings<O, D, MkCoPTreeNode<O, D>, MkCoPEntry>> {
/**
* Parameter for k
*/
public static final OptionID K_ID = new OptionID("mkcop.k", "positive integer specifying the maximum number k of reverse k nearest neighbors to be supported.");
/**
- * Parameter k.
- */
- int k_max;
-
- /**
* Constructor.
- *
- * @param fileName
- * @param pageSize
- * @param cacheSize
- * @param distanceFunction
- * @param k_max
+ *
+ * @param pageFileFactory Data storage
+ * @param settings Tree settings
*/
- public MkCopTreeFactory(String fileName, int pageSize, long cacheSize, DistanceFunction<O, D> distanceFunction, int k_max) {
- super(fileName, pageSize, cacheSize, distanceFunction);
- this.k_max = k_max;
+ public MkCopTreeFactory(PageFileFactory<?> pageFileFactory, MkTreeSettings<O, D, MkCoPTreeNode<O, D>, MkCoPEntry> settings) {
+ super(pageFileFactory, settings);
}
@Override
public MkCoPTreeIndex<O, D> instantiate(Relation<O> relation) {
PageFile<MkCoPTreeNode<O, D>> pagefile = makePageFile(getNodeClass());
- return new MkCoPTreeIndex<O, D>(relation, pagefile, distanceFunction.instantiate(relation), distanceFunction, k_max);
+ return new MkCoPTreeIndex<>(relation, pagefile, settings);
}
protected Class<MkCoPTreeNode<O, D>> getNodeClass() {
@@ -87,22 +79,25 @@ public class MkCopTreeFactory<O, D extends NumberDistance<D, ?>> extends Abstrac
*
* @apiviz.exclude
*/
- public static class Parameterizer<O, D extends NumberDistance<D, ?>> extends AbstractMTreeFactory.Parameterizer<O, D> {
- protected int k_max = 0;
-
+ public static class Parameterizer<O, D extends NumberDistance<D, ?>> extends AbstractMTreeFactory.Parameterizer<O, D, MkCoPTreeNode<O, D>, MkCoPEntry, MkTreeSettings<O, D, MkCoPTreeNode<O, D>, MkCoPEntry>> {
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
IntParameter k_maxP = new IntParameter(K_ID);
k_maxP.addConstraint(new GreaterConstraint(0));
if (config.grab(k_maxP)) {
- k_max = k_maxP.intValue();
+ settings.k_max = k_maxP.intValue();
}
}
@Override
protected MkCopTreeFactory<O, D> makeInstance() {
- return new MkCopTreeFactory<O, D>(fileName, pageSize, cacheSize, distanceFunction, k_max);
+ return new MkCopTreeFactory<>(pageFileFactory, settings);
+ }
+
+ @Override
+ protected MkTreeSettings<O, D, MkCoPTreeNode<O, D>, MkCoPEntry> makeSettings() {
+ return new MkTreeSettings<>();
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/package-info.java
index 516af071..c767c565 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxDirectoryEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxDirectoryEntry.java
index 0781dcb1..b3e39ca0 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxDirectoryEntry.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxDirectoryEntry.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkmax;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,7 +28,6 @@ import java.io.ObjectInput;
import java.io.ObjectOutput;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeDirectoryEntry;
/**
@@ -37,19 +36,18 @@ import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeDirectoryEntry
* the underlying MkMax-Tree node.
*
* @author Elke Achtert
- * @param <D> the type of Distance used in the MkMaxTree
*/
-class MkMaxDirectoryEntry<D extends Distance<D>> extends MTreeDirectoryEntry<D> implements MkMaxEntry<D> {
+class MkMaxDirectoryEntry extends MTreeDirectoryEntry implements MkMaxEntry {
/**
* Serial version UID
*/
- private static final long serialVersionUID = 1;
+ private static final long serialVersionUID = 2;
/**
* The aggregated k-nearest neighbor distance of the underlying MkMax-Tree
* node.
*/
- private D knnDistance;
+ private double knnDistance;
/**
* Empty constructor for serialization purposes.
@@ -69,18 +67,18 @@ class MkMaxDirectoryEntry<D extends Distance<D>> extends MTreeDirectoryEntry<D>
* @param knnDistance the aggregated knn distance of the underlying MkMax-Tree
* node
*/
- public MkMaxDirectoryEntry(DBID objectID, D parentDistance, Integer nodeID, D coveringRadius, D knnDistance) {
+ public MkMaxDirectoryEntry(DBID objectID, double parentDistance, Integer nodeID, double coveringRadius, double knnDistance) {
super(objectID, parentDistance, nodeID, coveringRadius);
this.knnDistance = knnDistance;
}
@Override
- public D getKnnDistance() {
+ public double getKnnDistance() {
return knnDistance;
}
@Override
- public void setKnnDistance(D knnDistance) {
+ public void setKnnDistance(double knnDistance) {
this.knnDistance = knnDistance;
}
@@ -91,7 +89,7 @@ class MkMaxDirectoryEntry<D extends Distance<D>> extends MTreeDirectoryEntry<D>
@Override
public void writeExternal(ObjectOutput out) throws IOException {
super.writeExternal(out);
- out.writeObject(knnDistance);
+ out.writeDouble(knnDistance);
}
/**
@@ -99,10 +97,9 @@ class MkMaxDirectoryEntry<D extends Distance<D>> extends MTreeDirectoryEntry<D>
* specified input stream.
*/
@Override
- @SuppressWarnings("unchecked")
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in);
- this.knnDistance = (D) in.readObject();
+ this.knnDistance = in.readDouble();
}
/**
@@ -113,20 +110,19 @@ class MkMaxDirectoryEntry<D extends Distance<D>> extends MTreeDirectoryEntry<D>
* MkMaxDirectoryEntry and has the same knnDistance as this entry.
*/
@Override
- @SuppressWarnings("unchecked")
public boolean equals(Object o) {
- if(this == o) {
+ if (this == o) {
return true;
}
- if(o == null || getClass() != o.getClass()) {
+ if (o == null || getClass() != o.getClass()) {
return false;
}
- if(!super.equals(o)) {
+ if (!super.equals(o)) {
return false;
}
- final MkMaxDirectoryEntry<D> that = (MkMaxDirectoryEntry<D>) o;
+ final MkMaxDirectoryEntry that = (MkMaxDirectoryEntry) o;
- return !(knnDistance != null ? !knnDistance.equals(that.knnDistance) : that.knnDistance != null);
+ return Double.compare(knnDistance, that.knnDistance) == 0;
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxEntry.java
index 0a7032f3..9e5133c9 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxEntry.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxEntry.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkmax;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,30 +23,28 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkmax;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry;
/**
* Defines the requirements for an entry in an
- * {@link de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkmax.MkMaxTreeNode}.
- * Additionally to an entry in an M-Tree an MkMaxEntry holds the k-nearest neighbor distance of the underlying
- * data object or MkMax-Tree node.
- *
+ * {@link de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkmax.MkMaxTreeNode}
+ * . Additionally to an entry in an M-Tree an MkMaxEntry holds the k-nearest
+ * neighbor distance of the underlying data object or MkMax-Tree node.
+ *
* @author Elke Achtert
- * @param <D> the type of Distance used in the MkMaxTree
*/
-interface MkMaxEntry<D extends Distance<D>> extends MTreeEntry<D> {
+interface MkMaxEntry extends MTreeEntry {
/**
* Returns the knn distance of the entry.
- *
+ *
* @return the knn distance of the entry
*/
- public D getKnnDistance();
+ public double getKnnDistance();
/**
* Sets the knn distance of the entry.
- *
+ *
* @param knnDistance the knn distance to be set
*/
- public void setKnnDistance(D knnDistance);
+ public void setKnnDistance(double knnDistance);
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxLeafEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxLeafEntry.java
index 29221fdc..d49f18ec 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxLeafEntry.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxLeafEntry.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkmax;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,7 +28,6 @@ import java.io.ObjectInput;
import java.io.ObjectOutput;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeLeafEntry;
/**
@@ -37,9 +36,8 @@ import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeLeafEntry;
* the underlying data object.
*
* @author Elke Achtert
- * @param <D> the type of Distance used in the MkMaxTree
*/
-class MkMaxLeafEntry<D extends Distance<D>> extends MTreeLeafEntry<D> implements MkMaxEntry<D> {
+class MkMaxLeafEntry extends MTreeLeafEntry implements MkMaxEntry {
/**
* Serial version number
*/
@@ -48,7 +46,7 @@ class MkMaxLeafEntry<D extends Distance<D>> extends MTreeLeafEntry<D> implements
/**
* The k-nearest neighbor distance of the underlying data object.
*/
- private D knnDistance;
+ private double knnDistance;
/**
* Empty constructor for serialization purposes.
@@ -65,18 +63,18 @@ class MkMaxLeafEntry<D extends Distance<D>> extends MTreeLeafEntry<D> implements
* parent's routing object
* @param knnDistance the knn distance of the underlying data object
*/
- public MkMaxLeafEntry(DBID objectID, D parentDistance, D knnDistance) {
+ public MkMaxLeafEntry(DBID objectID, double parentDistance, double knnDistance) {
super(objectID, parentDistance);
this.knnDistance = knnDistance;
}
@Override
- public D getKnnDistance() {
+ public double getKnnDistance() {
return knnDistance;
}
@Override
- public void setKnnDistance(D knnDistance) {
+ public void setKnnDistance(double knnDistance) {
this.knnDistance = knnDistance;
}
@@ -95,10 +93,9 @@ class MkMaxLeafEntry<D extends Distance<D>> extends MTreeLeafEntry<D> implements
* specified input stream.
*/
@Override
- @SuppressWarnings("unchecked")
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in);
- this.knnDistance = (D) in.readObject();
+ this.knnDistance = in.readDouble();
}
/**
@@ -109,20 +106,19 @@ class MkMaxLeafEntry<D extends Distance<D>> extends MTreeLeafEntry<D> implements
* and has the same knnDistance as this entry.
*/
@Override
- @SuppressWarnings("unchecked")
public boolean equals(Object o) {
- if(this == o) {
+ if (this == o) {
return true;
}
- if(o == null || getClass() != o.getClass()) {
+ if (o == null || getClass() != o.getClass()) {
return false;
}
- if(!super.equals(o)) {
+ if (!super.equals(o)) {
return false;
}
- final MkMaxLeafEntry<D> that = (MkMaxLeafEntry<D>) o;
+ final MkMaxLeafEntry that = (MkMaxLeafEntry) o;
- return !(knnDistance != null ? !knnDistance.equals(that.knnDistance) : that.knnDistance != null);
+ return Double.compare(knnDistance, that.knnDistance) == 0;
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTree.java
index 36f9bbf1..c1f87f20 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTree.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTree.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkmax;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -31,27 +31,25 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
-import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
-import de.lmu.ifi.dbs.elki.distance.DistanceUtil;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultIter;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.GenericDistanceDBIDList;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNHeap;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNUtil;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.ModifiableDistanceDBIDResult;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
-import de.lmu.ifi.dbs.elki.index.tree.DistanceEntry;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNHeap;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.ModifiableDistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.generic.GenericDistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.AbstractMkTreeUnified;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.MkTreeSettings;
import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.persistent.ByteArrayUtil;
import de.lmu.ifi.dbs.elki.persistent.PageFile;
-import de.lmu.ifi.dbs.elki.utilities.QueryStatistic;
+import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleIntPair;
/**
* MkMaxTree is a metrical index structure based on the concepts of the M-Tree
* supporting efficient processing of reverse k nearest neighbor queries for
- * parameter k <= k_max. The k-nearest neigbor distance for k = k_max is stored
+ * parameter k <= k_max. The k-nearest neighbor distance for k = k_max is stored
* in each entry of a node.
*
* @author Elke Achtert
@@ -61,49 +59,44 @@ import de.lmu.ifi.dbs.elki.utilities.QueryStatistic;
* @param <O> the type of DatabaseObject to be stored in the MkMaxTree
* @param <D> the type of Distance used in the MkMaxTree
*/
-public class MkMaxTree<O, D extends Distance<D>> extends AbstractMkTreeUnified<O, D, MkMaxTreeNode<O, D>, MkMaxEntry<D>> {
+public class MkMaxTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTreeUnified<O, D, MkMaxTreeNode<O, D>, MkMaxEntry, MkTreeSettings<O, D, MkMaxTreeNode<O, D>, MkMaxEntry>> {
/**
* The logger for this class.
*/
private static final Logging LOG = Logging.getLogger(MkMaxTree.class);
/**
- * Provides some statistics about performed reverse knn-queries.
- */
- private QueryStatistic rkNNStatistics = new QueryStatistic();
-
- /**
* Constructor.
*
+ * @param relation Relation to index
* @param pagefile Page file
- * @param distanceQuery Distance query
- * @param distanceFunction Distance function
- * @param k_max Maximum value for k
+ * @param settings Tree settings
*/
- public MkMaxTree(PageFile<MkMaxTreeNode<O, D>> pagefile, DistanceQuery<O, D> distanceQuery, DistanceFunction<O, D> distanceFunction, int k_max) {
- super(pagefile, distanceQuery, distanceFunction, k_max);
+ public MkMaxTree(Relation<O> relation, PageFile<MkMaxTreeNode<O, D>> pagefile, MkTreeSettings<O, D, MkMaxTreeNode<O, D>, MkMaxEntry> settings) {
+ super(relation, pagefile, settings);
}
/**
* Performs a reverse k-nearest neighbor query for the given object ID. In the
* first step the candidates are chosen by performing a reverse k-nearest
- * neighbor query with k = {@link #k_max}. Then these candidates are refined
+ * neighbor query with k = {@link #getKmax()}. Then these candidates are refined
* in a second step.
*/
@Override
- public DistanceDBIDResult<D> reverseKNNQuery(DBIDRef id, int k) {
- if(k > this.getKmax()) {
+ public DistanceDBIDList<D> reverseKNNQuery(DBIDRef id, int k) {
+ if (k > this.getKmax()) {
throw new IllegalArgumentException("Parameter k has to be equal or less than " + "parameter k of the MkMax-Tree!");
}
// get the candidates
- GenericDistanceDBIDList<D> candidates = new GenericDistanceDBIDList<D>();
+ GenericDistanceDBIDList<D> candidates = new GenericDistanceDBIDList<>();
doReverseKNNQuery(id, getRoot(), null, candidates);
- if(k == this.getKmax()) {
+ if (k == this.getKmax()) {
candidates.sort();
- rkNNStatistics.addTrueHits(candidates.size());
- rkNNStatistics.addResults(candidates.size());
+ // FIXME: re-add statistics.
+ // rkNNStatistics.addTrueHits(candidates.size());
+ // rkNNStatistics.addResults(candidates.size());
return candidates;
}
@@ -112,49 +105,34 @@ public class MkMaxTree<O, D extends Distance<D>> extends AbstractMkTreeUnified<O
for (DBIDIter candidate = candidates.iter(); candidate.valid(); candidate.advance()) {
candidateIDs.add(candidate);
}
- Map<DBID, KNNResult<D>> knnLists = batchNN(getRoot(), candidateIDs, k);
+ Map<DBID, KNNList<D>> knnLists = batchNN(getRoot(), candidateIDs, k);
- GenericDistanceDBIDList<D> result = new GenericDistanceDBIDList<D>();
+ GenericDistanceDBIDList<D> result = new GenericDistanceDBIDList<>();
for (DBIDIter iter = candidateIDs.iter(); iter.valid(); iter.advance()) {
DBID cid = DBIDUtil.deref(iter);
- KNNResult<D> cands = knnLists.get(cid);
- for (DistanceDBIDResultIter<D> iter2 = cands.iter(); iter2.valid(); iter2.advance()) {
- if(DBIDUtil.equal(id, iter2)) {
+ KNNList<D> cands = knnLists.get(cid);
+ for (DistanceDBIDListIter<D> iter2 = cands.iter(); iter2.valid(); iter2.advance()) {
+ if (DBIDUtil.equal(id, iter2)) {
result.add(iter2.getDistance(), cid);
break;
}
}
}
- rkNNStatistics.addResults(result.size());
- rkNNStatistics.addCandidates(candidates.size());
+ // FIXME: re-add statistics.
+ // rkNNStatistics.addResults(result.size());
+ // rkNNStatistics.addCandidates(candidates.size());
result.sort();
return result;
}
/**
- * Returns the statistic for performed rknn queries.
- *
- * @return the statistic for performed rknn queries
- */
- public QueryStatistic getRkNNStatistics() {
- return rkNNStatistics;
- }
-
- /**
- * Clears the values of the statistic for performed rknn queries
- */
- public void clearRkNNStatistics() {
- rkNNStatistics.clear();
- }
-
- /**
* Adapts the knn distances before insertion of the specified entry.
*
*/
@Override
- protected void preInsert(MkMaxEntry<D> entry) {
- KNNHeap<D> knns_o = KNNUtil.newHeap(distanceFunction, getKmax());
+ protected void preInsert(MkMaxEntry entry) {
+ KNNHeap<D> knns_o = DBIDUtil.newHeap(getDistanceFactory(), getKmax());
preInsert(entry, getRootEntry(), knns_o);
}
@@ -162,21 +140,20 @@ public class MkMaxTree<O, D extends Distance<D>> extends AbstractMkTreeUnified<O
* Adjusts the knn distance in the subtree of the specified root entry.
*/
@Override
- protected void kNNdistanceAdjustment(MkMaxEntry<D> entry, Map<DBID, KNNResult<D>> knnLists) {
+ protected void kNNdistanceAdjustment(MkMaxEntry entry, Map<DBID, KNNList<D>> knnLists) {
MkMaxTreeNode<O, D> node = getNode(entry);
- D knnDist_node = getDistanceQuery().nullDistance();
- if(node.isLeaf()) {
- for(int i = 0; i < node.getNumEntries(); i++) {
- MkMaxEntry<D> leafEntry = node.getEntry(i);
- leafEntry.setKnnDistance(knnLists.get(leafEntry.getRoutingObjectID()).getKNNDistance());
- knnDist_node = DistanceUtil.max(knnDist_node, leafEntry.getKnnDistance());
+ double knnDist_node = 0.;
+ if (node.isLeaf()) {
+ for (int i = 0; i < node.getNumEntries(); i++) {
+ MkMaxEntry leafEntry = node.getEntry(i);
+ leafEntry.setKnnDistance(knnLists.get(leafEntry.getRoutingObjectID()).getKNNDistance().doubleValue());
+ knnDist_node = Math.max(knnDist_node, leafEntry.getKnnDistance());
}
- }
- else {
- for(int i = 0; i < node.getNumEntries(); i++) {
- MkMaxEntry<D> dirEntry = node.getEntry(i);
+ } else {
+ for (int i = 0; i < node.getNumEntries(); i++) {
+ MkMaxEntry dirEntry = node.getEntry(i);
kNNdistanceAdjustment(dirEntry, knnLists);
- knnDist_node = DistanceUtil.max(knnDist_node, dirEntry.getKnnDistance());
+ knnDist_node = Math.max(knnDist_node, dirEntry.getKnnDistance());
}
}
entry.setKnnDistance(knnDist_node);
@@ -184,22 +161,22 @@ public class MkMaxTree<O, D extends Distance<D>> extends AbstractMkTreeUnified<O
/**
* Performs a reverse k-nearest neighbor query in the specified subtree for
- * the given query object with k = {@link #k_max}. It recursively traverses
+ * the given query object with k = {@link #getKmax()}. It recursively traverses
* all paths from the specified node, which cannot be excluded from leading to
- * qualififying objects.
+ * qualifying objects.
*
* @param q the id of the query object
* @param node the node of the subtree on which the query is performed
* @param node_entry the entry representing the node
* @param result the list for the query result
*/
- private void doReverseKNNQuery(DBIDRef q, MkMaxTreeNode<O, D> node, MkMaxEntry<D> node_entry, ModifiableDistanceDBIDResult<D> result) {
+ private void doReverseKNNQuery(DBIDRef q, MkMaxTreeNode<O, D> node, MkMaxEntry node_entry, ModifiableDistanceDBIDList<D> result) {
// data node
- if(node.isLeaf()) {
- for(int i = 0; i < node.getNumEntries(); i++) {
- MkMaxEntry<D> entry = node.getEntry(i);
- D distance = getDistanceQuery().distance(entry.getRoutingObjectID(), q);
- if(distance.compareTo(entry.getKnnDistance()) <= 0) {
+ if (node.isLeaf()) {
+ for (int i = 0; i < node.getNumEntries(); i++) {
+ MkMaxEntry entry = node.getEntry(i);
+ D distance = distance(entry.getRoutingObjectID(), q);
+ if (distance.doubleValue() <= entry.getKnnDistance()) {
result.add(distance, entry.getRoutingObjectID());
}
}
@@ -207,14 +184,14 @@ public class MkMaxTree<O, D extends Distance<D>> extends AbstractMkTreeUnified<O
// directory node
else {
- for(int i = 0; i < node.getNumEntries(); i++) {
- MkMaxEntry<D> entry = node.getEntry(i);
- D node_knnDist = node_entry != null ? node_entry.getKnnDistance() : getDistanceQuery().infiniteDistance();
+ for (int i = 0; i < node.getNumEntries(); i++) {
+ MkMaxEntry entry = node.getEntry(i);
+ double node_knnDist = node_entry != null ? node_entry.getKnnDistance() : Double.POSITIVE_INFINITY;
- D distance = getDistanceQuery().distance(entry.getRoutingObjectID(), q);
- D minDist = entry.getCoveringRadius().compareTo(distance) > 0 ? getDistanceQuery().nullDistance() : distance.minus(entry.getCoveringRadius());
+ double distance = distance(entry.getRoutingObjectID(), q).doubleValue();
+ double minDist = (entry.getCoveringRadius() > distance) ? 0.0 : distance - entry.getCoveringRadius();
- if(minDist.compareTo(node_knnDist) <= 0) {
+ if (minDist <= node_knnDist) {
MkMaxTreeNode<O, D> childNode = getNode(entry);
doReverseKNNQuery(q, childNode, entry, result);
}
@@ -226,77 +203,76 @@ public class MkMaxTree<O, D extends Distance<D>> extends AbstractMkTreeUnified<O
* Adapts the knn distances before insertion of entry q.
*
* @param q the entry to be inserted
- * @param nodeEntry the entry representing the root of thge current subtree
+ * @param nodeEntry the entry representing the root of the current subtree
* @param knns_q the knns of q
*/
- private void preInsert(MkMaxEntry<D> q, MkMaxEntry<D> nodeEntry, KNNHeap<D> knns_q) {
- if(LOG.isDebugging()) {
+ private void preInsert(MkMaxEntry q, MkMaxEntry nodeEntry, KNNHeap<D> knns_q) {
+ if (LOG.isDebugging()) {
LOG.debugFine("preInsert " + q + " - " + nodeEntry + "\n");
}
- D knnDist_q = knns_q.getKNNDistance();
+ double knnDist_q = knns_q.getKNNDistance().doubleValue();
MkMaxTreeNode<O, D> node = getNode(nodeEntry);
- D knnDist_node = getDistanceQuery().nullDistance();
+ double knnDist_node = 0.;
// leaf node
- if(node.isLeaf()) {
- for(int i = 0; i < node.getNumEntries(); i++) {
- MkMaxEntry<D> p = node.getEntry(i);
- D dist_pq = getDistanceQuery().distance(p.getRoutingObjectID(), q.getRoutingObjectID());
+ if (node.isLeaf()) {
+ for (int i = 0; i < node.getNumEntries(); i++) {
+ MkMaxEntry p = node.getEntry(i);
+ D dist_pq = distance(p.getRoutingObjectID(), q.getRoutingObjectID());
// p is nearer to q than the farthest kNN-candidate of q
// ==> p becomes a knn-candidate
- if(dist_pq.compareTo(knnDist_q) <= 0) {
+ if (dist_pq.doubleValue() <= knnDist_q) {
knns_q.add(dist_pq, p.getRoutingObjectID());
- if(knns_q.size() >= getKmax()) {
- knnDist_q = knns_q.getKNNDistance();
+ if (knns_q.size() >= getKmax()) {
+ knnDist_q = knns_q.getKNNDistance().doubleValue();
q.setKnnDistance(knnDist_q);
}
}
// p is nearer to q than to its farthest knn-candidate
// q becomes knn of p
- if(dist_pq.compareTo(p.getKnnDistance()) <= 0) {
- KNNResult<D> knns_p = knnq.getKNNForDBID(p.getRoutingObjectID(), getKmax() - 1);
+ if (dist_pq.doubleValue() <= p.getKnnDistance()) {
+ KNNList<D> knns_p = knnq.getKNNForDBID(p.getRoutingObjectID(), getKmax() - 1);
- if(knns_p.size() + 1 < getKmax()) {
- p.setKnnDistance(getDistanceQuery().undefinedDistance());
- }
- else {
- D knnDist_p = DistanceUtil.max(dist_pq, knns_p.getKNNDistance());
+ if (knns_p.size() + 1 < getKmax()) {
+ p.setKnnDistance(Double.NaN);
+ } else {
+ double knnDist_p = Math.max(dist_pq.doubleValue(), knns_p.getKNNDistance().doubleValue());
p.setKnnDistance(knnDist_p);
}
}
- knnDist_node = DistanceUtil.max(knnDist_node, p.getKnnDistance());
+ knnDist_node = Math.max(knnDist_node, p.getKnnDistance());
}
}
// directory node
else {
- List<DistanceEntry<D, MkMaxEntry<D>>> entries = getSortedEntries(node, q.getRoutingObjectID());
- for(DistanceEntry<D, MkMaxEntry<D>> distEntry : entries) {
- MkMaxEntry<D> dirEntry = distEntry.getEntry();
- D entry_knnDist = dirEntry.getKnnDistance();
+ List<DoubleIntPair> entries = getSortedEntries(node, q.getRoutingObjectID());
+ for (DoubleIntPair distEntry : entries) {
+ MkMaxEntry dirEntry = node.getEntry(distEntry.second);
+ double entry_knnDist = dirEntry.getKnnDistance();
- if(distEntry.getDistance().compareTo(entry_knnDist) < 0 || distEntry.getDistance().compareTo(knnDist_q) < 0) {
+ if (distEntry.second < entry_knnDist || distEntry.second < knnDist_q) {
preInsert(q, dirEntry, knns_q);
- knnDist_q = knns_q.getKNNDistance();
+ knnDist_q = knns_q.getKNNDistance().doubleValue();
}
- knnDist_node = DistanceUtil.max(knnDist_node, dirEntry.getKnnDistance());
+ knnDist_node = Math.max(knnDist_node, dirEntry.getKnnDistance());
}
}
- if(LOG.isDebugging()) {
+ if (LOG.isDebugging()) {
LOG.debugFine(nodeEntry + "set knn dist " + knnDist_node);
}
nodeEntry.setKnnDistance(knnDist_node);
}
@Override
- protected void initializeCapacities(MkMaxEntry<D> exampleLeaf) {
- int distanceSize = exampleLeaf.getParentDistance().externalizableSize();
+ protected void initializeCapacities(MkMaxEntry exampleLeaf) {
+ int distanceSize = ByteArrayUtil.SIZE_DOUBLE; // exampleLeaf.getParentDistance().externalizableSize();
// overhead = index(4), numEntries(4), id(4), isLeaf(0.125)
double overhead = 12.125;
- if(getPageSize() - overhead < 0) {
+ if (getPageSize() - overhead < 0) {
throw new RuntimeException("Node size of " + getPageSize() + " Bytes is chosen too small!");
}
@@ -304,11 +280,11 @@ public class MkMaxTree<O, D extends Distance<D>> extends AbstractMkTreeUnified<O
// coveringRadius + parentDistance + knnDistance) + 1
dirCapacity = (int) (getPageSize() - overhead) / (4 + 4 + 3 * distanceSize) + 1;
- if(dirCapacity <= 1) {
+ if (dirCapacity <= 1) {
throw new RuntimeException("Node size of " + getPageSize() + " Bytes is chosen too small!");
}
- if(dirCapacity < 10) {
+ if (dirCapacity < 10) {
LOG.warning("Page size is choosen too small! Maximum number of entries " + "in a directory node = " + (dirCapacity - 1));
}
@@ -317,11 +293,11 @@ public class MkMaxTree<O, D extends Distance<D>> extends AbstractMkTreeUnified<O
// knnDistance) + 1
leafCapacity = (int) (getPageSize() - overhead) / (4 + 2 * distanceSize) + 1;
- if(leafCapacity <= 1) {
+ if (leafCapacity <= 1) {
throw new RuntimeException("Node size of " + getPageSize() + " Bytes is chosen too small!");
}
- if(leafCapacity < 10) {
+ if (leafCapacity < 10) {
LOG.warning("Page size is choosen too small! Maximum number of entries " + "in a leaf node = " + (leafCapacity - 1));
}
}
@@ -331,7 +307,7 @@ public class MkMaxTree<O, D extends Distance<D>> extends AbstractMkTreeUnified<O
*/
@Override
protected MkMaxTreeNode<O, D> createNewLeafNode() {
- return new MkMaxTreeNode<O, D>(leafCapacity, true);
+ return new MkMaxTreeNode<>(leafCapacity, true);
}
/**
@@ -339,28 +315,28 @@ public class MkMaxTree<O, D extends Distance<D>> extends AbstractMkTreeUnified<O
*/
@Override
protected MkMaxTreeNode<O, D> createNewDirectoryNode() {
- return new MkMaxTreeNode<O, D>(dirCapacity, false);
+ return new MkMaxTreeNode<>(dirCapacity, false);
}
/**
* @return a new MkMaxDirectoryEntry representing the specified node
*/
@Override
- protected MkMaxEntry<D> createNewDirectoryEntry(MkMaxTreeNode<O, D> node, DBID routingObjectID, D parentDistance) {
- return new MkMaxDirectoryEntry<D>(routingObjectID, parentDistance, node.getPageID(), node.coveringRadius(routingObjectID, this), node.kNNDistance(getDistanceQuery()));
+ protected MkMaxEntry createNewDirectoryEntry(MkMaxTreeNode<O, D> node, DBID routingObjectID, double parentDistance) {
+ return new MkMaxDirectoryEntry(routingObjectID, parentDistance, node.getPageID(), node.coveringRadius(routingObjectID, this), node.kNNDistance());
}
/**
* @return a new MkMaxDirectoryEntry by calling
- * <code>new MkMaxDirectoryEntry<D>(null, null, 0, null)</code>
+ * <code>new MkMaxDirectoryEntry(null, null, 0, null)</code>
*/
@Override
- protected MkMaxEntry<D> createRootEntry() {
- return new MkMaxDirectoryEntry<D>(null, null, 0, null, null);
+ protected MkMaxEntry createRootEntry() {
+ return new MkMaxDirectoryEntry(null, 0., 0, 0., 0.);
}
@Override
protected Logging getLogger() {
return LOG;
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeFactory.java
index 7e9a7753..a03006f4 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeFactory.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeFactory.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkmax;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,10 +24,11 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkmax;
*/
import de.lmu.ifi.dbs.elki.database.relation.Relation;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.AbstractMkTreeUnifiedFactory;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.MkTreeSettings;
import de.lmu.ifi.dbs.elki.persistent.PageFile;
+import de.lmu.ifi.dbs.elki.persistent.PageFileFactory;
import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
/**
@@ -37,28 +38,25 @@ import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
*
* @apiviz.stereotype factory
* @apiviz.uses MkMaxTreeIndex oneway - - «create»
- *
+ *
* @param <O> Object type
* @param <D> Distance type
*/
-public class MkMaxTreeFactory<O, D extends Distance<D>> extends AbstractMkTreeUnifiedFactory<O, D, MkMaxTreeNode<O, D>, MkMaxEntry<D>, MkMaxTreeIndex<O, D>> {
+public class MkMaxTreeFactory<O, D extends NumberDistance<D, ?>> extends AbstractMkTreeUnifiedFactory<O, D, MkMaxTreeNode<O, D>, MkMaxEntry, MkMaxTreeIndex<O, D>, MkTreeSettings<O, D, MkMaxTreeNode<O, D>, MkMaxEntry>> {
/**
* Constructor.
- *
- * @param fileName
- * @param pageSize
- * @param cacheSize
- * @param distanceFunction
- * @param k_max
+ *
+ * @param pageFileFactory Data storage
+ * @param settings Tree settings
*/
- public MkMaxTreeFactory(String fileName, int pageSize, long cacheSize, DistanceFunction<O, D> distanceFunction, int k_max) {
- super(fileName, pageSize, cacheSize, distanceFunction, k_max);
+ public MkMaxTreeFactory(PageFileFactory<?> pageFileFactory, MkTreeSettings<O, D, MkMaxTreeNode<O, D>, MkMaxEntry> settings) {
+ super(pageFileFactory, settings);
}
@Override
public MkMaxTreeIndex<O, D> instantiate(Relation<O> relation) {
PageFile<MkMaxTreeNode<O, D>> pagefile = makePageFile(getNodeClass());
- return new MkMaxTreeIndex<O, D>(relation, pagefile, distanceFunction.instantiate(relation), distanceFunction, k_max);
+ return new MkMaxTreeIndex<>(relation, pagefile, settings);
}
protected Class<MkMaxTreeNode<O, D>> getNodeClass() {
@@ -72,10 +70,15 @@ public class MkMaxTreeFactory<O, D extends Distance<D>> extends AbstractMkTreeUn
*
* @apiviz.exclude
*/
- public static class Parameterizer<O, D extends Distance<D>> extends AbstractMkTreeUnifiedFactory.Parameterizer<O, D> {
+ public static class Parameterizer<O, D extends NumberDistance<D, ?>> extends AbstractMkTreeUnifiedFactory.Parameterizer<O, D, MkMaxTreeNode<O, D>, MkMaxEntry, MkTreeSettings<O, D, MkMaxTreeNode<O, D>, MkMaxEntry>> {
@Override
protected MkMaxTreeFactory<O, D> makeInstance() {
- return new MkMaxTreeFactory<O, D>(fileName, pageSize, cacheSize, distanceFunction, k_max);
+ return new MkMaxTreeFactory<>(pageFileFactory, settings);
+ }
+
+ @Override
+ protected MkTreeSettings<O, D, MkMaxTreeNode<O, D>, MkMaxEntry> makeSettings() {
+ return new MkTreeSettings<>();
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeIndex.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeIndex.java
index 0bd31dca..482c86eb 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeIndex.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeIndex.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkmax;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -31,6 +31,7 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
@@ -38,68 +39,72 @@ import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery;
import de.lmu.ifi.dbs.elki.database.query.rknn.RKNNQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
+import de.lmu.ifi.dbs.elki.index.DynamicIndex;
import de.lmu.ifi.dbs.elki.index.KNNIndex;
import de.lmu.ifi.dbs.elki.index.RKNNIndex;
import de.lmu.ifi.dbs.elki.index.RangeIndex;
-import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree;
-import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.AbstractMkTreeUnified;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.MkTreeSettings;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query.MTreeQueryUtil;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query.MkTreeRKNNQuery;
import de.lmu.ifi.dbs.elki.persistent.PageFile;
import de.lmu.ifi.dbs.elki.utilities.exceptions.ExceptionMessages;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.NotImplementedException;
/**
* MkMax tree
*
* @author Elke Achtert
- *
+ *
* @param <O> Object type
* @param <D> Distance type
*/
-public class MkMaxTreeIndex<O, D extends Distance<D>> extends MkMaxTree<O, D> implements RangeIndex<O>, KNNIndex<O>, RKNNIndex<O> {
+public class MkMaxTreeIndex<O, D extends NumberDistance<D, ?>> extends MkMaxTree<O, D> implements RangeIndex<O>, KNNIndex<O>, RKNNIndex<O>, DynamicIndex {
/**
* Relation indexed.
*/
private Relation<O> relation;
-
+
/**
* Constructor.
*
* @param relation Relation
* @param pagefile Page file
- * @param distanceQuery Distance query
- * @param distanceFunction Distance function
- * @param k_max Maximum value for k
+ * @param settings Tree settings
*/
- public MkMaxTreeIndex(Relation<O> relation, PageFile<MkMaxTreeNode<O, D>> pagefile, DistanceQuery<O, D> distanceQuery, DistanceFunction<O, D> distanceFunction, int k_max) {
- super(pagefile, distanceQuery, distanceFunction, k_max);
+ public MkMaxTreeIndex(Relation<O> relation, PageFile<MkMaxTreeNode<O, D>> pagefile, MkTreeSettings<O, D, MkMaxTreeNode<O, D>, MkMaxEntry> settings) {
+ super(relation, pagefile, settings);
this.relation = relation;
- this.initialize();
}
/**
* @return a new MkMaxLeafEntry representing the specified data object
*/
- protected MkMaxLeafEntry<D> createNewLeafEntry(DBID id, O object, D parentDistance) {
- KNNResult<D> knns = knnq.getKNNForObject(object, getKmax() - 1);
- D knnDistance = knns.getKNNDistance();
- return new MkMaxLeafEntry<D>(id, parentDistance, knnDistance);
+ protected MkMaxLeafEntry createNewLeafEntry(DBID id, O object, double parentDistance) {
+ KNNList<D> knns = knnq.getKNNForObject(object, getKmax() - 1);
+ double knnDistance = knns.getKNNDistance().doubleValue();
+ return new MkMaxLeafEntry(id, parentDistance, knnDistance);
+ }
+
+ @Override
+ public void initialize() {
+ super.initialize();
+ insertAll(relation.getDBIDs());
}
@Override
public void insert(DBIDRef id) {
- insert(createNewLeafEntry(DBIDUtil.deref(id), relation.get(id), getDistanceFactory().undefinedDistance()), false);
+ insert(createNewLeafEntry(DBIDUtil.deref(id), relation.get(id), Double.NaN), false);
}
@Override
public void insertAll(DBIDs ids) {
- List<MkMaxEntry<D>> objs = new ArrayList<MkMaxEntry<D>>(ids.size());
+ List<MkMaxEntry> objs = new ArrayList<>(ids.size());
for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
DBID id = DBIDUtil.deref(iter);
final O object = relation.get(id);
- objs.add(createNewLeafEntry(id, object, getDistanceFactory().undefinedDistance()));
+ objs.add(createNewLeafEntry(id, object, Double.NaN));
}
insertAll(objs);
}
@@ -113,7 +118,7 @@ public class MkMaxTreeIndex<O, D extends Distance<D>> extends MkMaxTree<O, D> im
*/
@Override
public final boolean delete(DBIDRef id) {
- throw new UnsupportedOperationException(ExceptionMessages.UNSUPPORTED_NOT_YET);
+ throw new NotImplementedException(ExceptionMessages.UNSUPPORTED_NOT_YET);
}
/**
@@ -125,78 +130,75 @@ public class MkMaxTreeIndex<O, D extends Distance<D>> extends MkMaxTree<O, D> im
*/
@Override
public void deleteAll(DBIDs ids) {
- throw new UnsupportedOperationException(ExceptionMessages.UNSUPPORTED_NOT_YET);
+ throw new NotImplementedException(ExceptionMessages.UNSUPPORTED_NOT_YET);
}
@SuppressWarnings("unchecked")
@Override
public <S extends Distance<S>> KNNQuery<O, S> getKNNQuery(DistanceQuery<O, S> distanceQuery, Object... hints) {
// Query on the relation we index
- if(distanceQuery.getRelation() != relation) {
+ if (distanceQuery.getRelation() != relation) {
return null;
}
- DistanceFunction<? super O, S> distanceFunction = distanceQuery.getDistanceFunction();
- if(!this.distanceFunction.equals(distanceFunction)) {
- if(getLogger().isDebugging()) {
+ DistanceFunction<? super O, D> distanceFunction = (DistanceFunction<? super O, D>) distanceQuery.getDistanceFunction();
+ if (!this.getDistanceFunction().equals(distanceFunction)) {
+ if (getLogger().isDebugging()) {
getLogger().debug("Distance function not supported by index - or 'equals' not implemented right!");
}
return null;
}
// Bulk is not yet supported
- for(Object hint : hints) {
- if(hint == DatabaseQuery.HINT_BULK) {
+ for (Object hint : hints) {
+ if (hint == DatabaseQuery.HINT_BULK) {
return null;
}
}
- AbstractMTree<O, S, ?, ?> idx = (AbstractMTree<O, S, ?, ?>) this;
- DistanceQuery<O, S> dq = distanceFunction.instantiate(relation);
- return MTreeQueryUtil.getKNNQuery(idx, dq, hints);
+ DistanceQuery<O, D> dq = distanceFunction.instantiate(relation);
+ return (KNNQuery<O, S>) MTreeQueryUtil.getKNNQuery(this, dq, hints);
}
@SuppressWarnings("unchecked")
@Override
public <S extends Distance<S>> RangeQuery<O, S> getRangeQuery(DistanceQuery<O, S> distanceQuery, Object... hints) {
// Query on the relation we index
- if(distanceQuery.getRelation() != relation) {
+ if (distanceQuery.getRelation() != relation) {
return null;
}
- DistanceFunction<? super O, S> distanceFunction = distanceQuery.getDistanceFunction();
- if(!this.distanceFunction.equals(distanceFunction)) {
- if(getLogger().isDebugging()) {
+ DistanceFunction<? super O, D> distanceFunction = (DistanceFunction<? super O, D>) distanceQuery.getDistanceFunction();
+ if (!this.getDistanceFunction().equals(distanceFunction)) {
+ if (getLogger().isDebugging()) {
getLogger().debug("Distance function not supported by index - or 'equals' not implemented right!");
}
return null;
}
// Bulk is not yet supported
- for(Object hint : hints) {
- if(hint == DatabaseQuery.HINT_BULK) {
+ for (Object hint : hints) {
+ if (hint == DatabaseQuery.HINT_BULK) {
return null;
}
}
- AbstractMTree<O, S, ?, ?> idx = (AbstractMTree<O, S, ?, ?>) this;
- DistanceQuery<O, S> dq = distanceFunction.instantiate(relation);
- return MTreeQueryUtil.getRangeQuery(idx, dq);
+ DistanceQuery<O, D> dq = distanceFunction.instantiate(relation);
+ return (RangeQuery<O, S>) MTreeQueryUtil.getRangeQuery(this, dq);
}
@SuppressWarnings("unchecked")
@Override
public <S extends Distance<S>> RKNNQuery<O, S> getRKNNQuery(DistanceQuery<O, S> distanceQuery, Object... hints) {
- DistanceFunction<? super O, S> distanceFunction = distanceQuery.getDistanceFunction();
- if(!this.getDistanceFunction().equals(distanceFunction)) {
- if(getLogger().isDebugging()) {
+ DistanceFunction<? super O, D> distanceFunction = (DistanceFunction<? super O, D>) distanceQuery.getDistanceFunction();
+ if (!this.getDistanceFunction().equals(distanceFunction)) {
+ if (getLogger().isDebugging()) {
getLogger().debug("Distance function not supported by index - or 'equals' not implemented right!");
}
return null;
}
// Bulk is not yet supported
- for(Object hint : hints) {
- if(hint == DatabaseQuery.HINT_BULK) {
+ for (Object hint : hints) {
+ if (hint == DatabaseQuery.HINT_BULK) {
return null;
}
}
- AbstractMkTreeUnified<O, S, ?, ?> idx = (AbstractMkTreeUnified<O, S, ?, ?>) this;
- DistanceQuery<O, S> dq = distanceFunction.instantiate(relation);
- return new MkTreeRKNNQuery<O, S>(idx, dq);
+ DistanceQuery<O, D> dq = distanceFunction.instantiate(relation);
+ return (RKNNQuery<O, S>) new MkTreeRKNNQuery<>(this, dq);
}
@Override
@@ -208,4 +210,4 @@ public class MkMaxTreeIndex<O, D extends Distance<D>> extends MkMaxTree<O, D> im
public String getShortName() {
return "mkmaxtree";
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeNode.java
index 17f85498..84c8bdc4 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeNode.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeNode.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkmax;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,9 +24,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkmax;
*/
import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
-import de.lmu.ifi.dbs.elki.distance.DistanceUtil;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode;
@@ -40,7 +38,7 @@ import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode;
* @param <O> the type of DatabaseObject to be stored in the MkMaxTree
* @param <D> the type of Distance used in the MkMaxTree
*/
-class MkMaxTreeNode<O, D extends Distance<D>> extends AbstractMTreeNode<O, D, MkMaxTreeNode<O, D>, MkMaxEntry<D>> {
+class MkMaxTreeNode<O, D extends NumberDistance<D, ?>> extends AbstractMTreeNode<O, D, MkMaxTreeNode<O, D>, MkMaxEntry> {
/**
* Serial version
*/
@@ -68,14 +66,13 @@ class MkMaxTreeNode<O, D extends Distance<D>> extends AbstractMTreeNode<O, D, Mk
* Determines and returns the k-nearest neighbor distance of this node as the
* maximum of the k-nearest neighbor distances of all entries.
*
- * @param distanceFunction the distance function
* @return the knn distance of this node
*/
- protected D kNNDistance(DistanceQuery<O, D> distanceFunction) {
- D knnDist = distanceFunction.nullDistance();
- for(int i = 0; i < getNumEntries(); i++) {
- MkMaxEntry<D> entry = getEntry(i);
- knnDist = DistanceUtil.max(knnDist, entry.getKnnDistance());
+ protected double kNNDistance() {
+ double knnDist = 0.;
+ for (int i = 0; i < getNumEntries(); i++) {
+ MkMaxEntry entry = getEntry(i);
+ knnDist = Math.max(knnDist, entry.getKnnDistance());
}
return knnDist;
}
@@ -86,10 +83,10 @@ class MkMaxTreeNode<O, D extends Distance<D>> extends AbstractMTreeNode<O, D, Mk
* all its entries.
*/
@Override
- public void adjustEntry(MkMaxEntry<D> entry, DBID routingObjectID, D parentDistance, AbstractMTree<O, D, MkMaxTreeNode<O, D>, MkMaxEntry<D>> mTree) {
+ public void adjustEntry(MkMaxEntry entry, DBID routingObjectID, double parentDistance, AbstractMTree<O, D, MkMaxTreeNode<O, D>, MkMaxEntry, ?> mTree) {
super.adjustEntry(entry, routingObjectID, parentDistance, mTree);
// adjust knn distance
- entry.setKnnDistance(kNNDistance(mTree.getDistanceQuery()));
+ entry.setKnnDistance(kNNDistance());
}
/**
@@ -97,15 +94,13 @@ class MkMaxTreeNode<O, D extends Distance<D>> extends AbstractMTreeNode<O, D, Mk
* node is correctly set.
*/
@Override
- protected void integrityCheckParameters(MkMaxEntry<D> parentEntry, MkMaxTreeNode<O, D> parent, int index, AbstractMTree<O, D, MkMaxTreeNode<O, D>, MkMaxEntry<D>> mTree) {
+ protected void integrityCheckParameters(MkMaxEntry parentEntry, MkMaxTreeNode<O, D> parent, int index, AbstractMTree<O, D, MkMaxTreeNode<O, D>, MkMaxEntry, ?> mTree) {
super.integrityCheckParameters(parentEntry, parent, index, mTree);
// test if knn distance is correctly set
- MkMaxEntry<D> entry = parent.getEntry(index);
- D knnDistance = kNNDistance(mTree.getDistanceQuery());
- if(!entry.getKnnDistance().equals(knnDistance)) {
- String soll = knnDistance.toString();
- String ist = entry.getKnnDistance().toString();
- throw new RuntimeException("Wrong knnDistance in node " + parent.getPageID() + " at index " + index + " (child " + entry + ")" + "\nsoll: " + soll + ",\n ist: " + ist);
+ MkMaxEntry entry = parent.getEntry(index);
+ double knnDistance = kNNDistance();
+ if (Math.abs(entry.getKnnDistance() - knnDistance) > 0) {
+ throw new RuntimeException("Wrong knnDistance in node " + parent.getPageID() + " at index " + index + " (child " + entry + ")" + "\nsoll: " + knnDistance + ",\n ist: " + entry.getKnnDistance());
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/package-info.java
index bcde11b4..7bd90d66 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabDirectoryEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabDirectoryEntry.java
index f8410ad9..9f088448 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabDirectoryEntry.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabDirectoryEntry.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mktab;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,11 +26,8 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mktab;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
-import java.util.ArrayList;
-import java.util.List;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeDirectoryEntry;
/**
@@ -39,20 +36,14 @@ import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeDirectoryEntry
* parameters k <= k_max.
*
* @author Elke Achtert
- *
*/
-class MkTabDirectoryEntry<D extends Distance<D>> extends MTreeDirectoryEntry<D> implements MkTabEntry<D> {
- private static final long serialVersionUID = 1;
-
- /**
- * The maximal number of knn distances to be stored.
- */
- private int k_max;
+class MkTabDirectoryEntry extends MTreeDirectoryEntry implements MkTabEntry {
+ private static final long serialVersionUID = 2;
/**
* The aggregated knn distances of the underlying node.
*/
- private List<D> knnDistances;
+ private double[] knnDistances;
/**
* Empty constructor for serialization purposes.
@@ -71,34 +62,28 @@ class MkTabDirectoryEntry<D extends Distance<D>> extends MTreeDirectoryEntry<D>
* @param coveringRadius the covering radius of the entry
* @param knnDistances the aggregated knn distances of the underlying node
*/
- public MkTabDirectoryEntry(DBID objectID, D parentDistance, Integer nodeID, D coveringRadius, List<D> knnDistances) {
+ public MkTabDirectoryEntry(DBID objectID, double parentDistance, Integer nodeID, double coveringRadius, double[] knnDistances) {
super(objectID, parentDistance, nodeID, coveringRadius);
this.knnDistances = knnDistances;
- this.k_max = knnDistances.size();
}
@Override
- public List<D> getKnnDistances() {
+ public double[] getKnnDistances() {
return knnDistances;
}
@Override
- public void setKnnDistances(List<D> knnDistances) {
+ public void setKnnDistances(double[] knnDistances) {
this.knnDistances = knnDistances;
}
@Override
- public D getKnnDistance(int k) {
- if(k > this.k_max) {
+ public double getKnnDistance(int k) {
+ if (k >= this.knnDistances.length) {
throw new IllegalArgumentException("Parameter k = " + k + " is not supported!");
}
- return knnDistances.get(k - 1);
- }
-
- @Override
- public int getK_max() {
- return k_max;
+ return knnDistances[k - 1];
}
/**
@@ -111,9 +96,10 @@ class MkTabDirectoryEntry<D extends Distance<D>> extends MTreeDirectoryEntry<D>
@Override
public void writeExternal(ObjectOutput out) throws IOException {
super.writeExternal(out);
+ int k_max = knnDistances.length;
out.writeInt(k_max);
- for(int i = 0; i < k_max; i++) {
- out.writeObject(knnDistances.get(i));
+ for (int i = 0; i < k_max; i++) {
+ out.writeDouble(knnDistances[i]);
}
}
@@ -130,10 +116,10 @@ class MkTabDirectoryEntry<D extends Distance<D>> extends MTreeDirectoryEntry<D>
@SuppressWarnings("unchecked")
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in);
- k_max = in.readInt();
- knnDistances = new ArrayList<D>();
- for(int i = 0; i < k_max; i++) {
- knnDistances.add((D) in.readObject());
+ int k_max = in.readInt();
+ knnDistances = new double[k_max];
+ for (int i = 0; i < k_max; i++) {
+ knnDistances[i] = in.readDouble();
}
}
@@ -148,21 +134,21 @@ class MkTabDirectoryEntry<D extends Distance<D>> extends MTreeDirectoryEntry<D>
@Override
@SuppressWarnings("unchecked")
public boolean equals(Object o) {
- if(this == o) {
+ if (this == o) {
return true;
}
- if(o == null || getClass() != o.getClass()) {
+ if (o == null || getClass() != o.getClass()) {
return false;
}
- if(!super.equals(o)) {
+ if (!super.equals(o)) {
return false;
}
- final MkTabDirectoryEntry<D> that = (MkTabDirectoryEntry<D>) o;
+ final MkTabDirectoryEntry that = (MkTabDirectoryEntry) o;
- if(k_max != that.k_max) {
+ if (knnDistances.length != that.knnDistances.length) {
return false;
}
return !(knnDistances != null ? !knnDistances.equals(that.knnDistances) : that.knnDistances != null);
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabEntry.java
index ba938fd3..a741ed5b 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabEntry.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabEntry.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mktab;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,46 +23,35 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mktab;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.List;
-
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry;
/**
- * Defines the requirements for an entry in an MkCop-Tree node.
- * Additionally to an entry in an M-Tree an MkTabEntry holds a list of knn distances
- * for for parameters k <= k_max of the underlying data object or MkTab-Tree node.
- *
+ * Defines the requirements for an entry in an MkCop-Tree node. Additionally to
+ * an entry in an M-Tree an MkTabEntry holds a list of knn distances for for
+ * parameters k <= k_max of the underlying data object or MkTab-Tree node.
+ *
* @author Elke Achtert
*/
-interface MkTabEntry<D extends Distance<D>> extends MTreeEntry<D> {
+interface MkTabEntry extends MTreeEntry {
/**
* Returns the list of knn distances of the entry.
- *
- * @return the list of knn distances of the entry
+ *
+ * @return the list of knn distances of the entry
*/
- public List<D> getKnnDistances();
+ public double[] getKnnDistances();
/**
* Sets the knn distances of the entry.
- *
+ *
* @param knnDistances the knn distances to be set
*/
- public void setKnnDistances(List<D> knnDistances);
+ public void setKnnDistances(double[] knnDistances);
/**
* Returns the knn distance of the entry for the specified parameter k.
- *
+ *
* @param k the parameter k of the knn distance
* @return the knn distance of the entry
*/
- public D getKnnDistance(int k);
-
- /**
- * Returns the parameter k_max.
- *
- * @return the parameter k_max
- */
- public int getK_max();
-
+ public double getKnnDistance(int k);
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabLeafEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabLeafEntry.java
index 81446718..969ba781 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabLeafEntry.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabLeafEntry.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mktab;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,11 +26,8 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mktab;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
-import java.util.ArrayList;
-import java.util.List;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeLeafEntry;
/**
@@ -40,18 +37,13 @@ import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeLeafEntry;
*
* @author Elke Achtert
*/
-class MkTabLeafEntry<D extends Distance<D>> extends MTreeLeafEntry<D> implements MkTabEntry<D> {
- private static final long serialVersionUID = 1;
-
- /**
- * The maximal number of knn distances to be stored.
- */
- private int k_max;
+class MkTabLeafEntry extends MTreeLeafEntry implements MkTabEntry {
+ private static final long serialVersionUID = 2;
/**
* The knn distances of the underlying data object.
*/
- private List<D> knnDistances;
+ private double[] knnDistances;
/**
* Empty constructor for serialization purposes.
@@ -68,38 +60,32 @@ class MkTabLeafEntry<D extends Distance<D>> extends MTreeLeafEntry<D> implements
* parent's routing object
* @param knnDistances the knn distances of the underlying data object
*/
- public MkTabLeafEntry(DBID objectID, D parentDistance, List<D> knnDistances) {
+ public MkTabLeafEntry(DBID objectID, double parentDistance, double[] knnDistances) {
super(objectID, parentDistance);
this.knnDistances = knnDistances;
- this.k_max = knnDistances.size();
}
@Override
- public List<D> getKnnDistances() {
+ public double[] getKnnDistances() {
return knnDistances;
}
@Override
- public void setKnnDistances(List<D> knnDistances) {
- if(knnDistances.size() != this.k_max) {
- throw new IllegalArgumentException("Wrong length of knn distances: " + knnDistances.size());
+ public void setKnnDistances(double[] knnDistances) {
+ if (knnDistances.length != this.knnDistances.length) {
+ throw new IllegalArgumentException("Wrong length of knn distances: " + knnDistances.length);
}
this.knnDistances = knnDistances;
}
@Override
- public D getKnnDistance(int k) {
- if(k > this.k_max) {
+ public double getKnnDistance(int k) {
+ if (k >= this.knnDistances.length) {
throw new IllegalArgumentException("Parameter k = " + k + " is not supported!");
}
- return knnDistances.get(k - 1);
- }
-
- @Override
- public int getK_max() {
- return k_max;
+ return knnDistances[k - 1];
}
/**
@@ -112,9 +98,10 @@ class MkTabLeafEntry<D extends Distance<D>> extends MTreeLeafEntry<D> implements
@Override
public void writeExternal(ObjectOutput out) throws IOException {
super.writeExternal(out);
+ int k_max = knnDistances.length;
out.writeInt(k_max);
- for(int i = 0; i < k_max; i++) {
- out.writeObject(knnDistances.get(i));
+ for (int i = 0; i < k_max; i++) {
+ out.writeDouble(knnDistances[i]);
}
}
@@ -131,10 +118,10 @@ class MkTabLeafEntry<D extends Distance<D>> extends MTreeLeafEntry<D> implements
@SuppressWarnings("unchecked")
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in);
- k_max = in.readInt();
- knnDistances = new ArrayList<D>();
- for(int i = 0; i < k_max; i++) {
- knnDistances.add((D) in.readObject());
+ int k_max = in.readInt();
+ knnDistances = new double[k_max];
+ for (int i = 0; i < k_max; i++) {
+ knnDistances[i] = in.readDouble();
}
}
@@ -148,21 +135,21 @@ class MkTabLeafEntry<D extends Distance<D>> extends MTreeLeafEntry<D> implements
@Override
@SuppressWarnings("unchecked")
public boolean equals(Object o) {
- if(this == o) {
+ if (this == o) {
return true;
}
- if(o == null || getClass() != o.getClass()) {
+ if (o == null || getClass() != o.getClass()) {
return false;
}
- if(!super.equals(o)) {
+ if (!super.equals(o)) {
return false;
}
- final MkTabLeafEntry<D> that = (MkTabLeafEntry<D>) o;
+ final MkTabLeafEntry that = (MkTabLeafEntry) o;
- if(k_max != that.k_max) {
+ if (knnDistances.length != that.knnDistances.length) {
return false;
}
return !(knnDistances != null ? !knnDistances.equals(that.knnDistances) : that.knnDistances != null);
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTree.java
index f5410839..481392cb 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTree.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTree.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mktab;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,22 +23,20 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mktab;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.ArrayList;
-import java.util.List;
import java.util.Map;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
-import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
-import de.lmu.ifi.dbs.elki.distance.DistanceUtil;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.GenericDistanceDBIDList;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNUtil;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
+import de.lmu.ifi.dbs.elki.database.ids.generic.GenericDistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.AbstractMkTreeUnified;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.MkTreeSettings;
import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.persistent.ByteArrayUtil;
import de.lmu.ifi.dbs.elki.persistent.PageFile;
/**
@@ -54,22 +52,21 @@ import de.lmu.ifi.dbs.elki.persistent.PageFile;
* @param <O> Object type
* @param <D> Distance type
*/
-public class MkTabTree<O, D extends Distance<D>> extends AbstractMkTreeUnified<O, D, MkTabTreeNode<O, D>, MkTabEntry<D>> {
+public class MkTabTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTreeUnified<O, D, MkTabTreeNode<O, D>, MkTabEntry, MkTreeSettings<O, D, MkTabTreeNode<O, D>, MkTabEntry>> {
/**
* The logger for this class.
*/
private static final Logging LOG = Logging.getLogger(MkTabTree.class);
-
+
/**
* Constructor.
*
+ * @param relation Relation
* @param pagefile Page file
- * @param distanceQuery Distance query
- * @param distanceFunction Distance function
- * @param k_max Maximum value for k
+ * @param settings Settings
*/
- public MkTabTree(PageFile<MkTabTreeNode<O, D>> pagefile, DistanceQuery<O, D> distanceQuery, DistanceFunction<O, D> distanceFunction, int k_max) {
- super(pagefile, distanceQuery, distanceFunction, k_max);
+ public MkTabTree(Relation<O> relation, PageFile<MkTabTreeNode<O, D>> pagefile, MkTreeSettings<O, D, MkTabTreeNode<O, D>, MkTabEntry> settings) {
+ super(relation, pagefile, settings);
}
/**
@@ -77,7 +74,7 @@ public class MkTabTree<O, D extends Distance<D>> extends AbstractMkTreeUnified<O
* not supported
*/
@Override
- protected void preInsert(MkTabEntry<D> entry) {
+ protected void preInsert(MkTabEntry entry) {
throw new UnsupportedOperationException("Insertion of single objects is not supported!");
}
@@ -86,17 +83,17 @@ public class MkTabTree<O, D extends Distance<D>> extends AbstractMkTreeUnified<O
* not supported
*/
@Override
- public void insert(MkTabEntry<D> entry, boolean withPreInsert) {
+ public void insert(MkTabEntry entry, boolean withPreInsert) {
throw new UnsupportedOperationException("Insertion of single objects is not supported!");
}
@Override
- public DistanceDBIDResult<D> reverseKNNQuery(DBIDRef id, int k) {
- if(k > this.getKmax()) {
+ public DistanceDBIDList<D> reverseKNNQuery(DBIDRef id, int k) {
+ if (k > this.getKmax()) {
throw new IllegalArgumentException("Parameter k has to be less or equal than " + "parameter kmax of the MkTab-Tree!");
}
- GenericDistanceDBIDList<D> result = new GenericDistanceDBIDList<D>();
+ GenericDistanceDBIDList<D> result = new GenericDistanceDBIDList<>();
doReverseKNNQuery(k, id, null, getRoot(), result);
result.sort();
@@ -104,12 +101,12 @@ public class MkTabTree<O, D extends Distance<D>> extends AbstractMkTreeUnified<O
}
@Override
- protected void initializeCapacities(MkTabEntry<D> exampleLeaf) {
- int distanceSize = exampleLeaf.getParentDistance().externalizableSize();
+ protected void initializeCapacities(MkTabEntry exampleLeaf) {
+ int distanceSize = ByteArrayUtil.SIZE_DOUBLE; // exampleLeaf.getParentDistance().externalizableSize();
// overhead = index(4), numEntries(4), id(4), isLeaf(0.125)
double overhead = 12.125;
- if(getPageSize() - overhead < 0) {
+ if (getPageSize() - overhead < 0) {
throw new RuntimeException("Node size of " + getPageSize() + " Bytes is chosen too small!");
}
@@ -117,11 +114,11 @@ public class MkTabTree<O, D extends Distance<D>> extends AbstractMkTreeUnified<O
// coveringRadius + parentDistance + kmax + kmax * knnDistance) + 1
dirCapacity = (int) (getPageSize() - overhead) / (4 + 4 + distanceSize + distanceSize + 4 + getKmax() * distanceSize) + 1;
- if(dirCapacity <= 1) {
+ if (dirCapacity <= 1) {
throw new RuntimeException("Node size of " + getPageSize() + " Bytes is chosen too small!");
}
- if(dirCapacity < 10) {
+ if (dirCapacity < 10) {
LOG.warning("Page size is choosen too small! Maximum number of entries " + "in a directory node = " + (dirCapacity - 1));
}
@@ -129,30 +126,37 @@ public class MkTabTree<O, D extends Distance<D>> extends AbstractMkTreeUnified<O
// kmax + kmax * knnDistance) + 1
leafCapacity = (int) (getPageSize() - overhead) / (4 + distanceSize + 4 + getKmax() * distanceSize) + 1;
- if(leafCapacity <= 1) {
+ if (leafCapacity <= 1) {
throw new RuntimeException("Node size of " + getPageSize() + " Bytes is chosen too small!");
}
- if(leafCapacity < 10) {
+ if (leafCapacity < 10) {
LOG.warning("Page size is choosen too small! Maximum number of entries " + "in a leaf node = " + (leafCapacity - 1));
}
}
-
+
@Override
- protected void kNNdistanceAdjustment(MkTabEntry<D> entry, Map<DBID, KNNResult<D>> knnLists) {
+ protected void kNNdistanceAdjustment(MkTabEntry entry, Map<DBID, KNNList<D>> knnLists) {
MkTabTreeNode<O, D> node = getNode(entry);
- List<D> knnDistances_node = initKnnDistanceList();
- if(node.isLeaf()) {
- for(int i = 0; i < node.getNumEntries(); i++) {
- MkTabEntry<D> leafEntry = node.getEntry(i);
- leafEntry.setKnnDistances(KNNUtil.asDistanceList(knnLists.get(getPageID(leafEntry))));
+ double[] knnDistances_node = initKnnDistanceList();
+ if (node.isLeaf()) {
+ for (int i = 0; i < node.getNumEntries(); i++) {
+ MkTabEntry leafEntry = node.getEntry(i);
+ KNNList<D> knns = knnLists.get(getPageID(leafEntry));
+ double[] distances = new double[knns.size()];
+ int j = 0;
+ for (DistanceDBIDListIter<D> iter = knns.iter(); iter.valid(); iter.advance(), j++) {
+ distances[i] = iter.getDistance().doubleValue();
+ }
+ leafEntry.setKnnDistances(distances);
+ // FIXME: save copy
knnDistances_node = max(knnDistances_node, leafEntry.getKnnDistances());
}
- }
- else {
- for(int i = 0; i < node.getNumEntries(); i++) {
- MkTabEntry<D> dirEntry = node.getEntry(i);
+ } else {
+ for (int i = 0; i < node.getNumEntries(); i++) {
+ MkTabEntry dirEntry = node.getEntry(i);
kNNdistanceAdjustment(dirEntry, knnLists);
+ // FIXME: save copy
knnDistances_node = max(knnDistances_node, dirEntry.getKnnDistances());
}
}
@@ -161,7 +165,7 @@ public class MkTabTree<O, D extends Distance<D>> extends AbstractMkTreeUnified<O
@Override
protected MkTabTreeNode<O, D> createNewLeafNode() {
- return new MkTabTreeNode<O, D>(leafCapacity, true);
+ return new MkTabTreeNode<>(leafCapacity, true);
}
/**
@@ -171,7 +175,7 @@ public class MkTabTree<O, D extends Distance<D>> extends AbstractMkTreeUnified<O
*/
@Override
protected MkTabTreeNode<O, D> createNewDirectoryNode() {
- return new MkTabTreeNode<O, D>(dirCapacity, false);
+ return new MkTabTreeNode<>(dirCapacity, false);
}
/**
@@ -183,8 +187,8 @@ public class MkTabTree<O, D extends Distance<D>> extends AbstractMkTreeUnified<O
* the routing object of the parent node
*/
@Override
- protected MkTabEntry<D> createNewDirectoryEntry(MkTabTreeNode<O, D> node, DBID routingObjectID, D parentDistance) {
- return new MkTabDirectoryEntry<D>(routingObjectID, parentDistance, node.getPageID(), node.coveringRadius(routingObjectID, this), node.kNNDistances(getDistanceQuery()));
+ protected MkTabEntry createNewDirectoryEntry(MkTabTreeNode<O, D> node, DBID routingObjectID, double parentDistance) {
+ return new MkTabDirectoryEntry(routingObjectID, parentDistance, node.getPageID(), node.coveringRadius(routingObjectID, this), node.kNNDistances());
}
/**
@@ -193,8 +197,8 @@ public class MkTabTree<O, D extends Distance<D>> extends AbstractMkTreeUnified<O
* @return an entry representing the root node
*/
@Override
- protected MkTabEntry<D> createRootEntry() {
- return new MkTabDirectoryEntry<D>(null, null, 0, null, initKnnDistanceList());
+ protected MkTabEntry createRootEntry() {
+ return new MkTabDirectoryEntry(null, 0., 0, 0., initKnnDistanceList());
}
/**
@@ -209,13 +213,13 @@ public class MkTabTree<O, D extends Distance<D>> extends AbstractMkTreeUnified<O
* @param node the root of the subtree
* @param result the list holding the query result
*/
- private void doReverseKNNQuery(int k, DBIDRef q, MkTabEntry<D> node_entry, MkTabTreeNode<O, D> node, GenericDistanceDBIDList<D> result) {
+ private void doReverseKNNQuery(int k, DBIDRef q, MkTabEntry node_entry, MkTabTreeNode<O, D> node, GenericDistanceDBIDList<D> result) {
// data node
- if(node.isLeaf()) {
- for(int i = 0; i < node.getNumEntries(); i++) {
- MkTabEntry<D> entry = node.getEntry(i);
- D distance = getDistanceQuery().distance(entry.getRoutingObjectID(), q);
- if(distance.compareTo(entry.getKnnDistance(k)) <= 0) {
+ if (node.isLeaf()) {
+ for (int i = 0; i < node.getNumEntries(); i++) {
+ MkTabEntry entry = node.getEntry(i);
+ D distance = distance(entry.getRoutingObjectID(), q);
+ if (distance.doubleValue() <= entry.getKnnDistance(k)) {
result.add(distance, entry.getRoutingObjectID());
}
}
@@ -223,14 +227,14 @@ public class MkTabTree<O, D extends Distance<D>> extends AbstractMkTreeUnified<O
// directory node
else {
- for(int i = 0; i < node.getNumEntries(); i++) {
- MkTabEntry<D> entry = node.getEntry(i);
- D node_knnDist = node_entry != null ? node_entry.getKnnDistance(k) : getDistanceQuery().infiniteDistance();
+ for (int i = 0; i < node.getNumEntries(); i++) {
+ MkTabEntry entry = node.getEntry(i);
+ double node_knnDist = node_entry != null ? node_entry.getKnnDistance(k) : Double.POSITIVE_INFINITY;
- D distance = getDistanceQuery().distance(entry.getRoutingObjectID(), q);
- D minDist = entry.getCoveringRadius().compareTo(distance) > 0 ? getDistanceQuery().nullDistance() : distance.minus(entry.getCoveringRadius());
+ double distance = distance(entry.getRoutingObjectID(), q).doubleValue();
+ double minDist = (entry.getCoveringRadius() > distance) ? 0. : distance - entry.getCoveringRadius();
- if(minDist.compareTo(node_knnDist) <= 0) {
+ if (minDist <= node_knnDist) {
MkTabTreeNode<O, D> childNode = getNode(entry);
doReverseKNNQuery(k, q, entry, childNode, result);
}
@@ -247,17 +251,14 @@ public class MkTabTree<O, D extends Distance<D>> extends AbstractMkTreeUnified<O
* @return an array that holds the maximum values of the both specified arrays
* in each index
*/
- private List<D> max(List<D> distances1, List<D> distances2) {
- if(distances1.size() != distances2.size()) {
+ private double[] max(double[] distances1, double[] distances2) {
+ if (distances1.length != distances2.length) {
throw new RuntimeException("different lengths!");
}
- List<D> result = new ArrayList<D>();
-
- for(int i = 0; i < distances1.size(); i++) {
- D d1 = distances1.get(i);
- D d2 = distances2.get(i);
- result.add(DistanceUtil.max(d1, d2));
+ double[] result = new double[distances1.length];
+ for (int i = 0; i < distances1.length; i++) {
+ result[i] = Math.max(distances1[i], distances2[i]);
}
return result;
}
@@ -267,16 +268,13 @@ public class MkTabTree<O, D extends Distance<D>> extends AbstractMkTreeUnified<O
*
* @return a knn distance list with all distances set to null distance
*/
- private List<D> initKnnDistanceList() {
- List<D> knnDistances = new ArrayList<D>(getKmax());
- for(int i = 0; i < getKmax(); i++) {
- knnDistances.add(getDistanceQuery().nullDistance());
- }
+ private double[] initKnnDistanceList() {
+ double[] knnDistances = new double[getKmax()];
return knnDistances;
}
-
+
@Override
protected Logging getLogger() {
return LOG;
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTreeFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTreeFactory.java
index 2bc6c256..9ede76ad 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTreeFactory.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTreeFactory.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mktab;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,10 +24,11 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mktab;
*/
import de.lmu.ifi.dbs.elki.database.relation.Relation;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.AbstractMkTreeUnifiedFactory;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.MkTreeSettings;
import de.lmu.ifi.dbs.elki.persistent.PageFile;
+import de.lmu.ifi.dbs.elki.persistent.PageFileFactory;
import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
/**
@@ -41,24 +42,21 @@ import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
* @param <O> Object type
* @param <D> Distance type
*/
-public class MkTabTreeFactory<O, D extends Distance<D>> extends AbstractMkTreeUnifiedFactory<O, D, MkTabTreeNode<O, D>, MkTabEntry<D>, MkTabTreeIndex<O, D>> {
+public class MkTabTreeFactory<O, D extends NumberDistance<D, ?>> extends AbstractMkTreeUnifiedFactory<O, D, MkTabTreeNode<O, D>, MkTabEntry, MkTabTreeIndex<O, D>, MkTreeSettings<O, D, MkTabTreeNode<O, D>, MkTabEntry>> {
/**
* Constructor.
*
- * @param fileName
- * @param pageSize
- * @param cacheSize
- * @param distanceFunction
- * @param k_max
+ * @param pageFileFactory Data storage
+ * @param settings Tree settings
*/
- public MkTabTreeFactory(String fileName, int pageSize, long cacheSize, DistanceFunction<O, D> distanceFunction, int k_max) {
- super(fileName, pageSize, cacheSize, distanceFunction, k_max);
+ public MkTabTreeFactory(PageFileFactory<?> pageFileFactory, MkTreeSettings<O, D, MkTabTreeNode<O, D>, MkTabEntry> settings) {
+ super(pageFileFactory, settings);
}
@Override
public MkTabTreeIndex<O, D> instantiate(Relation<O> relation) {
PageFile<MkTabTreeNode<O, D>> pagefile = makePageFile(getNodeClass());
- return new MkTabTreeIndex<O, D>(relation, pagefile, distanceFunction.instantiate(relation), distanceFunction, k_max);
+ return new MkTabTreeIndex<>(relation, pagefile, settings);
}
protected Class<MkTabTreeNode<O, D>> getNodeClass() {
@@ -72,10 +70,15 @@ public class MkTabTreeFactory<O, D extends Distance<D>> extends AbstractMkTreeUn
*
* @apiviz.exclude
*/
- public static class Parameterizer<O, D extends Distance<D>> extends AbstractMkTreeUnifiedFactory.Parameterizer<O, D> {
+ public static class Parameterizer<O, D extends NumberDistance<D, ?>> extends AbstractMkTreeUnifiedFactory.Parameterizer<O, D, MkTabTreeNode<O, D>, MkTabEntry, MkTreeSettings<O, D, MkTabTreeNode<O, D>, MkTabEntry>> {
@Override
protected MkTabTreeFactory<O, D> makeInstance() {
- return new MkTabTreeFactory<O, D>(fileName, pageSize, cacheSize, distanceFunction, k_max);
+ return new MkTabTreeFactory<>(pageFileFactory, settings);
+ }
+
+ @Override
+ protected MkTreeSettings<O, D, MkTabTreeNode<O, D>, MkTabEntry> makeSettings() {
+ return new MkTreeSettings<>();
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTreeIndex.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTreeIndex.java
index b12ac059..150f03e8 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTreeIndex.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTreeIndex.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mktab;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,9 +28,9 @@ import java.util.List;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
@@ -38,18 +38,15 @@ import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery;
import de.lmu.ifi.dbs.elki.database.query.rknn.RKNNQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNUtil;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.KNNIndex;
import de.lmu.ifi.dbs.elki.index.RKNNIndex;
import de.lmu.ifi.dbs.elki.index.RangeIndex;
-import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree;
-import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.AbstractMkTreeUnified;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.MkTreeSettings;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query.MTreeQueryUtil;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query.MkTreeRKNNQuery;
import de.lmu.ifi.dbs.elki.persistent.PageFile;
-import de.lmu.ifi.dbs.elki.utilities.exceptions.ExceptionMessages;
/**
* MkTabTree used as database index.
@@ -59,12 +56,7 @@ import de.lmu.ifi.dbs.elki.utilities.exceptions.ExceptionMessages;
* @param <O> Object type
* @param <D> Distance type
*/
-public class MkTabTreeIndex<O, D extends Distance<D>> extends MkTabTree<O, D> implements RangeIndex<O>, KNNIndex<O>, RKNNIndex<O> {
- /**
- * The knn query we use internally.
- */
- private final KNNQuery<O, D> knnQuery;
-
+public class MkTabTreeIndex<O, D extends NumberDistance<D, ?>> extends MkTabTree<O, D> implements RangeIndex<O>, KNNIndex<O>, RKNNIndex<O> {
/**
* The relation indexed.
*/
@@ -75,15 +67,11 @@ public class MkTabTreeIndex<O, D extends Distance<D>> extends MkTabTree<O, D> im
*
* @param relation Relation indexed
* @param pagefile Page file
- * @param distanceQuery Distance query
- * @param distanceFunction Distance function
- * @param k_max Maximum value for k
+ * @param settings Tree settings
*/
- public MkTabTreeIndex(Relation<O> relation, PageFile<MkTabTreeNode<O, D>> pagefile, DistanceQuery<O, D> distanceQuery, DistanceFunction<O, D> distanceFunction, int k_max) {
- super(pagefile, distanceQuery, distanceFunction, k_max);
+ public MkTabTreeIndex(Relation<O> relation, PageFile<MkTabTreeNode<O, D>> pagefile, MkTreeSettings<O, D, MkTabTreeNode<O, D>, MkTabEntry> settings) {
+ super(relation, pagefile, settings);
this.relation = relation;
- this.knnQuery = this.getKNNQuery(getDistanceQuery());
- this.initialize();
}
/**
@@ -94,8 +82,8 @@ public class MkTabTreeIndex<O, D extends Distance<D>> extends MkTabTree<O, D> im
* @param parentDistance the distance from the object to the routing object of
* the parent node
*/
- protected MkTabEntry<D> createNewLeafEntry(DBID id, O object, D parentDistance) {
- return new MkTabLeafEntry<D>(id, parentDistance, knnDistances(object));
+ protected MkTabEntry createNewLeafEntry(DBID id, O object, double parentDistance) {
+ return new MkTabLeafEntry(id, parentDistance, knnDistances(object));
}
/**
@@ -104,120 +92,94 @@ public class MkTabTreeIndex<O, D extends Distance<D>> extends MkTabTree<O, D> im
* @param object the query object
* @return the knn distance of the object with the specified id
*/
- private List<D> knnDistances(O object) {
- KNNResult<D> knns = knnQuery.getKNNForObject(object, getKmax() - 1);
- return KNNUtil.asDistanceList(knns);
- }
-
- @Override
- public void insert(DBIDRef id) {
- throw new UnsupportedOperationException("Insertion of single objects is not supported!");
+ private double[] knnDistances(O object) {
+ KNNList<D> knns = knnq.getKNNForObject(object, getKmax() - 1);
+ double[] distances = new double[getKmax()];
+ int i = 0;
+ for (DistanceDBIDListIter<D> iter = knns.iter(); iter.valid() && i < getKmax(); iter.advance(), i++) {
+ distances[i] = iter.getDistance().doubleValue();
+ }
+ return distances;
}
@Override
- public void insertAll(DBIDs ids) {
- List<MkTabEntry<D>> objs = new ArrayList<MkTabEntry<D>>(ids.size());
- for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
- DBID id = DBIDUtil.deref(iter);
+ public void initialize() {
+ super.initialize();
+ List<MkTabEntry> objs = new ArrayList<>(relation.size());
+ for (DBIDIter iter = relation.iterDBIDs(); iter.valid(); iter.advance()) {
+ DBID id = DBIDUtil.deref(iter); // FIXME: expensive
final O object = relation.get(id);
- objs.add(createNewLeafEntry(id, object, getDistanceFactory().undefinedDistance()));
+ objs.add(createNewLeafEntry(id, object, Double.NaN));
}
insertAll(objs);
}
- /**
- * Throws an UnsupportedOperationException since deletion of objects is not
- * yet supported by an M-Tree.
- *
- * @throws UnsupportedOperationException thrown, since deletions aren't
- * implemented yet.
- */
- @Override
- public final boolean delete(DBIDRef id) {
- throw new UnsupportedOperationException(ExceptionMessages.UNSUPPORTED_NOT_YET);
- }
-
- /**
- * Throws an UnsupportedOperationException since deletion of objects is not
- * yet supported by an M-Tree.
- *
- * @throws UnsupportedOperationException thrown, since deletions aren't
- * implemented yet.
- */
- @Override
- public void deleteAll(DBIDs ids) {
- throw new UnsupportedOperationException(ExceptionMessages.UNSUPPORTED_NOT_YET);
- }
-
@SuppressWarnings("unchecked")
@Override
public <S extends Distance<S>> KNNQuery<O, S> getKNNQuery(DistanceQuery<O, S> distanceQuery, Object... hints) {
// Query on the relation we index
- if(distanceQuery.getRelation() != relation) {
+ if (distanceQuery.getRelation() != relation) {
return null;
}
- DistanceFunction<? super O, S> distanceFunction = distanceQuery.getDistanceFunction();
- if(!this.distanceFunction.equals(distanceFunction)) {
- if(getLogger().isDebugging()) {
+ DistanceFunction<? super O, D> distanceFunction = (DistanceFunction<? super O, D>) distanceQuery.getDistanceFunction();
+ if (!this.getDistanceFunction().equals(distanceFunction)) {
+ if (getLogger().isDebugging()) {
getLogger().debug("Distance function not supported by index - or 'equals' not implemented right!");
}
return null;
}
// Bulk is not yet supported
- for(Object hint : hints) {
- if(hint == DatabaseQuery.HINT_BULK) {
+ for (Object hint : hints) {
+ if (hint == DatabaseQuery.HINT_BULK) {
return null;
}
}
- AbstractMTree<O, S, ?, ?> idx = (AbstractMTree<O, S, ?, ?>) this;
- DistanceQuery<O, S> dq = distanceFunction.instantiate(relation);
- return MTreeQueryUtil.getKNNQuery(idx, dq, hints);
+ DistanceQuery<O, D> dq = distanceFunction.instantiate(relation);
+ return (KNNQuery<O, S>) MTreeQueryUtil.getKNNQuery(this, dq, hints);
}
@SuppressWarnings("unchecked")
@Override
public <S extends Distance<S>> RangeQuery<O, S> getRangeQuery(DistanceQuery<O, S> distanceQuery, Object... hints) {
// Query on the relation we index
- if(distanceQuery.getRelation() != relation) {
+ if (distanceQuery.getRelation() != relation) {
return null;
}
- DistanceFunction<? super O, S> distanceFunction = distanceQuery.getDistanceFunction();
- if(!this.distanceFunction.equals(distanceFunction)) {
- if(getLogger().isDebugging()) {
+ DistanceFunction<? super O, D> distanceFunction = (DistanceFunction<? super O, D>) distanceQuery.getDistanceFunction();
+ if (!this.getDistanceFunction().equals(distanceFunction)) {
+ if (getLogger().isDebugging()) {
getLogger().debug("Distance function not supported by index - or 'equals' not implemented right!");
}
return null;
}
// Bulk is not yet supported
- for(Object hint : hints) {
- if(hint == DatabaseQuery.HINT_BULK) {
+ for (Object hint : hints) {
+ if (hint == DatabaseQuery.HINT_BULK) {
return null;
}
}
- AbstractMTree<O, S, ?, ?> idx = (AbstractMTree<O, S, ?, ?>) this;
- DistanceQuery<O, S> dq = distanceFunction.instantiate(relation);
- return MTreeQueryUtil.getRangeQuery(idx, dq);
+ DistanceQuery<O, D> dq = distanceFunction.instantiate(relation);
+ return (RangeQuery<O, S>) MTreeQueryUtil.getRangeQuery(this, dq);
}
@SuppressWarnings("unchecked")
@Override
public <S extends Distance<S>> RKNNQuery<O, S> getRKNNQuery(DistanceQuery<O, S> distanceQuery, Object... hints) {
- DistanceFunction<? super O, S> distanceFunction = distanceQuery.getDistanceFunction();
- if(!this.getDistanceFunction().equals(distanceFunction)) {
- if(getLogger().isDebugging()) {
+ DistanceFunction<? super O, D> distanceFunction = (DistanceFunction<? super O, D>) distanceQuery.getDistanceFunction();
+ if (!this.getDistanceFunction().equals(distanceFunction)) {
+ if (getLogger().isDebugging()) {
getLogger().debug("Distance function not supported by index - or 'equals' not implemented right!");
}
return null;
}
// Bulk is not yet supported
- for(Object hint : hints) {
- if(hint == DatabaseQuery.HINT_BULK) {
+ for (Object hint : hints) {
+ if (hint == DatabaseQuery.HINT_BULK) {
return null;
}
}
- AbstractMkTreeUnified<O, S, ?, ?> idx = (AbstractMkTreeUnified<O, S, ?, ?>) this;
- DistanceQuery<O, S> dq = distanceFunction.instantiate(relation);
- return new MkTreeRKNNQuery<O, S>(idx, dq);
+ DistanceQuery<O, D> dq = distanceFunction.instantiate(relation);
+ return (RKNNQuery<O, S>) new MkTreeRKNNQuery<>(this, dq);
}
@Override
@@ -229,4 +191,4 @@ public class MkTabTreeIndex<O, D extends Distance<D>> extends MkTabTree<O, D> im
public String getShortName() {
return "mktabtree";
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTreeNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTreeNode.java
index b09ac314..1942a78b 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTreeNode.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTreeNode.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mktab;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,13 +23,8 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mktab;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.ArrayList;
-import java.util.List;
-
import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
-import de.lmu.ifi.dbs.elki.distance.DistanceUtil;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode;
@@ -43,8 +38,8 @@ import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode;
* @param <O> object type
* @param <D> distance type
*/
-class MkTabTreeNode<O, D extends Distance<D>> extends AbstractMTreeNode<O, D, MkTabTreeNode<O, D>, MkTabEntry<D>> {
- private static final long serialVersionUID = 1;
+class MkTabTreeNode<O, D extends NumberDistance<D, ?>> extends AbstractMTreeNode<O, D, MkTabTreeNode<O, D>, MkTabEntry> {
+ private static final long serialVersionUID = 2;
/**
* Empty constructor for Externalizable interface.
@@ -68,22 +63,17 @@ class MkTabTreeNode<O, D extends Distance<D>> extends AbstractMTreeNode<O, D, Mk
* Determines and returns the knn distance of this node as the maximum knn
* distance of all entries.
*
- * @param distanceFunction the distance function
* @return the knn distance of this node
*/
- protected List<D> kNNDistances(DistanceQuery<O, D> distanceFunction) {
- int k = getEntry(0).getK_max();
+ protected double[] kNNDistances() {
+ int k = getEntry(0).getKnnDistances().length;
- List<D> result = new ArrayList<D>();
- for(int i = 0; i < k; i++) {
- result.add(distanceFunction.nullDistance());
- }
+ double[] result = new double[k];
- for(int i = 0; i < getNumEntries(); i++) {
- for(int j = 0; j < k; j++) {
- MkTabEntry<D> entry = getEntry(i);
- D kDist = result.remove(j);
- result.add(j, DistanceUtil.max(kDist, entry.getKnnDistance(j + 1)));
+ for (int i = 0; i < getNumEntries(); i++) {
+ for (int j = 0; j < k; j++) {
+ MkTabEntry entry = getEntry(i);
+ result[j] = Math.max(result[j], entry.getKnnDistance(j + 1));
}
}
@@ -91,10 +81,10 @@ class MkTabTreeNode<O, D extends Distance<D>> extends AbstractMTreeNode<O, D, Mk
}
@Override
- public void adjustEntry(MkTabEntry<D> entry, DBID routingObjectID, D parentDistance, AbstractMTree<O, D, MkTabTreeNode<O, D>, MkTabEntry<D>> mTree) {
+ public void adjustEntry(MkTabEntry entry, DBID routingObjectID, double parentDistance, AbstractMTree<O, D, MkTabTreeNode<O, D>, MkTabEntry, ?> mTree) {
super.adjustEntry(entry, routingObjectID, parentDistance, mTree);
// adjust knn distances
- entry.setKnnDistances(kNNDistances(mTree.getDistanceQuery()));
+ entry.setKnnDistances(kNNDistances());
}
/**
@@ -106,12 +96,12 @@ class MkTabTreeNode<O, D extends Distance<D>> extends AbstractMTreeNode<O, D, Mk
* @param mTree the underlying M-Tree
*/
@Override
- protected void integrityCheckParameters(MkTabEntry<D> parentEntry, MkTabTreeNode<O, D> parent, int index, AbstractMTree<O, D, MkTabTreeNode<O, D>, MkTabEntry<D>> mTree) {
+ protected void integrityCheckParameters(MkTabEntry parentEntry, MkTabTreeNode<O, D> parent, int index, AbstractMTree<O, D, MkTabTreeNode<O, D>, MkTabEntry, ?> mTree) {
super.integrityCheckParameters(parentEntry, parent, index, mTree);
// test knn distances
- MkTabEntry<D> entry = parent.getEntry(index);
- List<D> knnDistances = kNNDistances(mTree.getDistanceQuery());
- if(!entry.getKnnDistances().equals(knnDistances)) {
+ MkTabEntry entry = parent.getEntry(index);
+ double[] knnDistances = kNNDistances();
+ if (!entry.getKnnDistances().equals(knnDistances)) {
String soll = knnDistances.toString();
String ist = entry.getKnnDistances().toString();
throw new RuntimeException("Wrong knnDistances in node " + parent.getPageID() + " at index " + index + " (child " + entry + ")" + "\nsoll: " + soll + ",\n ist: " + ist);
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/package-info.java
index 353acaa5..ed3e24d3 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/package-info.java
index 201d57c3..13b23e16 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/package-info.java
@@ -7,7 +7,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTree.java
index 4276329c..1b3d1481 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTree.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTree.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mtree;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,12 +24,11 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mtree;
*/
import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeDirectoryEntry;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeSettings;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.persistent.PageFile;
import de.lmu.ifi.dbs.elki.utilities.documentation.Description;
@@ -41,6 +40,14 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
* Apart from organizing the objects it also provides several methods to search
* for certain object in the structure. Persistence is not yet ensured.
*
+ * Reference:
+ * <p>
+ * P. Ciaccia, M. Patella, P. Zezula<br />
+ * M-tree: An Efficient Access Method for Similarity Search in Metric Spaces<br />
+ * In Proceedings of 23rd International Conference on Very Large Data Bases
+ * (VLDB'97), August 25-29, 1997, Athens, Greece
+ * </p>
+ *
* @author Elke Achtert
*
* @apiviz.has MTreeNode oneway - - contains
@@ -51,7 +58,7 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
@Title("M-Tree")
@Description("Efficient Access Method for Similarity Search in Metric Spaces")
@Reference(authors = "P. Ciaccia, M. Patella, P. Zezula", title = "M-tree: An Efficient Access Method for Similarity Search in Metric Spaces", booktitle = "VLDB'97, Proceedings of 23rd International Conference on Very Large Data Bases, August 25-29, 1997, Athens, Greece", url = "http://www.vldb.org/conf/1997/P426.PDF")
-public class MTree<O, D extends Distance<D>> extends AbstractMTree<O, D, MTreeNode<O, D>, MTreeEntry<D>> {
+abstract public class MTree<O, D extends NumberDistance<D, ?>> extends AbstractMTree<O, D, MTreeNode<O, D>, MTreeEntry, MTreeSettings<O, D, MTreeNode<O, D>, MTreeEntry>> {
/**
* The logger for this class.
*/
@@ -61,77 +68,26 @@ public class MTree<O, D extends Distance<D>> extends AbstractMTree<O, D, MTreeNo
* Constructor.
*
* @param pagefile Page file
- * @param distanceQuery Distance query
- * @param distanceFunction Distance function
+ * @param settings Tree settings
*/
- public MTree(PageFile<MTreeNode<O, D>> pagefile, DistanceQuery<O, D> distanceQuery, DistanceFunction<O, D> distanceFunction) {
- super(pagefile, distanceQuery, distanceFunction);
+ public MTree(PageFile<MTreeNode<O, D>> pagefile, MTreeSettings<O, D, MTreeNode<O, D>, MTreeEntry> settings) {
+ super(pagefile, settings);
}
/**
* Does nothing because no operations are necessary before inserting an entry.
*/
@Override
- protected void preInsert(MTreeEntry<D> entry) {
+ protected void preInsert(MTreeEntry entry) {
// do nothing
}
- @Override
- protected void initializeCapacities(MTreeEntry<D> exampleLeaf) {
- int distanceSize = exampleLeaf.getParentDistance().externalizableSize();
-
- // FIXME: simulate a proper feature size!
- int featuresize = 0; // RelationUtil.dimensionality(relation);
-
- // overhead = index(4), numEntries(4), id(4), isLeaf(0.125)
- double overhead = 12.125;
- if(getPageSize() - overhead < 0) {
- throw new RuntimeException("Node size of " + getPageSize() + " Bytes is chosen too small!");
- }
-
- // dirCapacity = (pageSize - overhead) / (nodeID + objectID +
- // coveringRadius + parentDistance) + 1
- // dirCapacity = (int) (pageSize - overhead) / (4 + 4 + distanceSize +
- // distanceSize) + 1;
-
- // dirCapacity = (pageSize - overhead) / (nodeID + **object feature size** +
- // coveringRadius + parentDistance) + 1
- dirCapacity = (int) (getPageSize() - overhead) / (4 + featuresize + distanceSize + distanceSize) + 1;
-
- if(dirCapacity <= 2) {
- throw new RuntimeException("Node size of " + getPageSize() + " Bytes is chosen too small!");
- }
-
- if(dirCapacity < 10) {
- LOG.warning("Page size is choosen too small! Maximum number of entries " + "in a directory node = " + (dirCapacity - 1));
- }
- // leafCapacity = (pageSize - overhead) / (objectID + parentDistance) +
- // 1
- // leafCapacity = (int) (pageSize - overhead) / (4 + distanceSize) + 1;
- // leafCapacity = (pageSize - overhead) / (objectID + ** object size ** +
- // parentDistance) +
- // 1
- leafCapacity = (int) (getPageSize() - overhead) / (4 + featuresize + distanceSize) + 1;
-
- if(leafCapacity <= 1) {
- throw new RuntimeException("Node size of " + getPageSize() + " Bytes is chosen too small!");
- }
-
- if(leafCapacity < 10) {
- LOG.warning("Page size is choosen too small! Maximum number of entries " + "in a leaf node = " + (leafCapacity - 1));
- }
-
- if(LOG.isVerbose()) {
- LOG.verbose("Directory Capacity: " + (dirCapacity - 1) + "\nLeaf Capacity: " + (leafCapacity - 1));
- }
- }
-
/**
* @return a new MTreeDirectoryEntry representing the specified node
*/
@Override
- protected MTreeEntry<D> createNewDirectoryEntry(MTreeNode<O, D> node, DBID routingObjectID, D parentDistance) {
- return new MTreeDirectoryEntry<D>(routingObjectID, parentDistance, node.getPageID(), node.coveringRadius(routingObjectID, this));
+ protected MTreeEntry createNewDirectoryEntry(MTreeNode<O, D> node, DBID routingObjectID, double parentDistance) {
+ return new MTreeDirectoryEntry(routingObjectID, parentDistance, node.getPageID(), node.coveringRadius(routingObjectID, this));
}
/**
@@ -139,8 +95,8 @@ public class MTree<O, D extends Distance<D>> extends AbstractMTree<O, D, MTreeNo
* <code>new MTreeDirectoryEntry<D>(null, null, 0, null)</code>
*/
@Override
- protected MTreeEntry<D> createRootEntry() {
- return new MTreeDirectoryEntry<D>(null, null, 0, null);
+ protected MTreeEntry createRootEntry() {
+ return new MTreeDirectoryEntry(null, 0., 0, 0.);
}
/**
@@ -148,7 +104,7 @@ public class MTree<O, D extends Distance<D>> extends AbstractMTree<O, D, MTreeNo
*/
@Override
protected MTreeNode<O, D> createNewLeafNode() {
- return new MTreeNode<O, D>(leafCapacity, true);
+ return new MTreeNode<>(leafCapacity, true);
}
/**
@@ -156,11 +112,11 @@ public class MTree<O, D extends Distance<D>> extends AbstractMTree<O, D, MTreeNo
*/
@Override
protected MTreeNode<O, D> createNewDirectoryNode() {
- return new MTreeNode<O, D>(dirCapacity, false);
+ return new MTreeNode<>(dirCapacity, false);
}
@Override
protected Logging getLogger() {
return LOG;
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeFactory.java
index 5c5aac04..dbc27511 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeFactory.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeFactory.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mtree;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,11 +24,13 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mtree;
*/
import de.lmu.ifi.dbs.elki.database.relation.Relation;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeFactory;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeSettings;
import de.lmu.ifi.dbs.elki.persistent.PageFile;
+import de.lmu.ifi.dbs.elki.persistent.PageFileFactory;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
/**
@@ -42,23 +44,22 @@ import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
* @param <O> Object type
* @param <D> Distance type
*/
-public class MTreeFactory<O, D extends Distance<D>> extends AbstractMTreeFactory<O, D, MTreeNode<O, D>, MTreeEntry<D>, MTreeIndex<O, D>> {
+@Alias({ "mtree", "m" })
+public class MTreeFactory<O, D extends NumberDistance<D, ?>> extends AbstractMTreeFactory<O, D, MTreeNode<O, D>, MTreeEntry, MTreeIndex<O, D>, MTreeSettings<O, D, MTreeNode<O, D>, MTreeEntry>> {
/**
* Constructor.
*
- * @param fileName file name
- * @param pageSize page size
- * @param cacheSize cache size
- * @param distanceFunction Distance function
+ * @param pageFileFactory Data storage
+ * @param settings Tree settings
*/
- public MTreeFactory(String fileName, int pageSize, long cacheSize, DistanceFunction<O, D> distanceFunction) {
- super(fileName, pageSize, cacheSize, distanceFunction);
+ public MTreeFactory(PageFileFactory<?> pageFileFactory, MTreeSettings<O, D, MTreeNode<O, D>, MTreeEntry> settings) {
+ super(pageFileFactory, settings);
}
@Override
public MTreeIndex<O, D> instantiate(Relation<O> relation) {
PageFile<MTreeNode<O, D>> pagefile = makePageFile(getNodeClass());
- return new MTreeIndex<O, D>(relation, pagefile, distanceFunction.instantiate(relation), distanceFunction);
+ return new MTreeIndex<>(relation, pagefile, settings);
}
protected Class<MTreeNode<O, D>> getNodeClass() {
@@ -72,10 +73,15 @@ public class MTreeFactory<O, D extends Distance<D>> extends AbstractMTreeFactory
*
* @apiviz.exclude
*/
- public static class Parameterizer<O, D extends Distance<D>> extends AbstractMTreeFactory.Parameterizer<O, D> {
+ public static class Parameterizer<O, D extends NumberDistance<D, ?>> extends AbstractMTreeFactory.Parameterizer<O, D, MTreeNode<O, D>, MTreeEntry, MTreeSettings<O, D, MTreeNode<O, D>, MTreeEntry>> {
@Override
protected MTreeFactory<O, D> makeInstance() {
- return new MTreeFactory<O, D>(fileName, pageSize, cacheSize, distanceFunction);
+ return new MTreeFactory<>(pageFileFactory, settings);
+ }
+
+ @Override
+ protected MTreeSettings<O, D, MTreeNode<O, D>, MTreeEntry> makeSettings() {
+ return new MTreeSettings<>();
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeIndex.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeIndex.java
index 8afe1f2a..32908a1e 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeIndex.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeIndex.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mtree;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,6 +26,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mtree;
import java.util.ArrayList;
import java.util.List;
+import de.lmu.ifi.dbs.elki.data.FeatureVector;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
@@ -36,64 +37,137 @@ import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.database.relation.RelationUtil;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
+import de.lmu.ifi.dbs.elki.index.DynamicIndex;
import de.lmu.ifi.dbs.elki.index.KNNIndex;
import de.lmu.ifi.dbs.elki.index.RangeIndex;
-import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeLeafEntry;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeSettings;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query.MTreeQueryUtil;
+import de.lmu.ifi.dbs.elki.persistent.ByteArrayUtil;
import de.lmu.ifi.dbs.elki.persistent.PageFile;
import de.lmu.ifi.dbs.elki.utilities.exceptions.ExceptionMessages;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.NotImplementedException;
/**
* Class for using an m-tree as database index.
*
* @author Erich Schubert
- *
+ *
* @param <O> Object type
* @param <D> Distance type
*/
-public class MTreeIndex<O, D extends Distance<D>> extends MTree<O, D> implements RangeIndex<O>, KNNIndex<O> {
+public class MTreeIndex<O, D extends NumberDistance<D, ?>> extends MTree<O, D> implements RangeIndex<O>, KNNIndex<O>, DynamicIndex {
/**
* The relation indexed.
*/
private Relation<O> relation;
/**
+ * The distance query.
+ */
+ protected DistanceQuery<O, D> distanceQuery;
+
+ /**
* Constructor.
- *
+ *
* @param relation Relation indexed
* @param pagefile Page file
- * @param distanceQuery Distance query
- * @param distanceFunction Distance function
+ * @param settings Tree settings
*/
- public MTreeIndex(Relation<O> relation, PageFile<MTreeNode<O, D>> pagefile, DistanceQuery<O, D> distanceQuery, DistanceFunction<O, D> distanceFunction) {
- super(pagefile, distanceQuery, distanceFunction);
+ public MTreeIndex(Relation<O> relation, PageFile<MTreeNode<O, D>> pagefile, MTreeSettings<O, D, MTreeNode<O, D>, MTreeEntry> settings) {
+ super(pagefile, settings);
this.relation = relation;
- this.initialize();
+ this.distanceQuery = getDistanceFunction().instantiate(relation);
+ }
+
+ @Override
+ public D distance(DBIDRef id1, DBIDRef id2) {
+ if (id1 == null || id2 == null) {
+ return getDistanceFactory().undefinedDistance();
+ }
+ statistics.countDistanceCalculation();
+ return distanceQuery.distance(id1, id2);
+ }
+
+ @Override
+ protected void initializeCapacities(MTreeEntry exampleLeaf) {
+ int distanceSize = ByteArrayUtil.SIZE_DOUBLE; // exampleLeaf.getParentDistance().externalizableSize();
+
+ // FIXME: simulate a proper feature size!
+ @SuppressWarnings("unchecked")
+ int featuresize = 8 * RelationUtil.dimensionality((Relation<? extends FeatureVector<?>>) relation);
+ if (featuresize <= 0) {
+ getLogger().warning("Relation does not have a dimensionality -- simulating M-tree as external index!");
+ featuresize = 0;
+ }
+
+ // overhead = index(4), numEntries(4), id(4), isLeaf(0.125)
+ double overhead = 12.125;
+ if (getPageSize() - overhead < 0) {
+ throw new RuntimeException("Node size of " + getPageSize() + " Bytes is chosen too small!");
+ }
+
+ // dirCapacity = (pageSize - overhead) / (nodeID + objectID + coveringRadius
+ // + parentDistance) + 1
+ // dirCapacity = (int) (pageSize - overhead) / (4 + 4 + distanceSize +
+ // distanceSize) + 1;
+
+ // dirCapacity = (pageSize - overhead) / (nodeID + **object feature size** +
+ // coveringRadius + parentDistance) + 1
+ dirCapacity = (int) (getPageSize() - overhead) / (4 + featuresize + distanceSize + distanceSize) + 1;
+
+ if (dirCapacity <= 2) {
+ throw new RuntimeException("Node size of " + getPageSize() + " Bytes is chosen too small!");
+ }
+
+ if (dirCapacity < 10) {
+ getLogger().warning("Page size is choosen too small! Maximum number of entries " + "in a directory node = " + (dirCapacity - 1));
+ }
+ // leafCapacity = (pageSize - overhead) / (objectID + parentDistance) + 1
+ // leafCapacity = (int) (pageSize - overhead) / (4 + distanceSize) + 1;
+ // leafCapacity = (pageSize - overhead) / (objectID + ** object size ** +
+ // parentDistance) + 1
+ leafCapacity = (int) (getPageSize() - overhead) / (4 + featuresize + distanceSize) + 1;
+
+ if (leafCapacity <= 1) {
+ throw new RuntimeException("Node size of " + getPageSize() + " Bytes is chosen too small!");
+ }
+
+ if (leafCapacity < 10) {
+ getLogger().warning("Page size is choosen too small! Maximum number of entries " + "in a leaf node = " + (leafCapacity - 1));
+ }
}
/**
* @return a new MTreeLeafEntry representing the specified data object
*/
- protected MTreeEntry<D> createNewLeafEntry(DBID id, O object, D parentDistance) {
- return new MTreeLeafEntry<D>(id, parentDistance);
+ protected MTreeEntry createNewLeafEntry(DBID id, O object, double parentDistance) {
+ return new MTreeLeafEntry(id, parentDistance);
+ }
+
+ @Override
+ public void initialize() {
+ super.initialize();
+ insertAll(relation.getDBIDs());
}
@Override
public void insert(DBIDRef id) {
- insert(createNewLeafEntry(DBIDUtil.deref(id), relation.get(id), getDistanceFactory().undefinedDistance()), false);
+ insert(createNewLeafEntry(DBIDUtil.deref(id), relation.get(id), Double.NaN), false);
}
@Override
public void insertAll(DBIDs ids) {
- List<MTreeEntry<D>> objs = new ArrayList<MTreeEntry<D>>(ids.size());
+ List<MTreeEntry> objs = new ArrayList<>(ids.size());
for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
DBID id = DBIDUtil.deref(iter);
final O object = relation.get(id);
- objs.add(createNewLeafEntry(id, object, getDistanceFactory().undefinedDistance()));
+ objs.add(createNewLeafEntry(id, object, Double.NaN));
}
insertAll(objs);
}
@@ -107,7 +181,7 @@ public class MTreeIndex<O, D extends Distance<D>> extends MTree<O, D> implements
*/
@Override
public final boolean delete(DBIDRef id) {
- throw new UnsupportedOperationException(ExceptionMessages.UNSUPPORTED_NOT_YET);
+ throw new NotImplementedException(ExceptionMessages.UNSUPPORTED_NOT_YET);
}
/**
@@ -119,57 +193,55 @@ public class MTreeIndex<O, D extends Distance<D>> extends MTree<O, D> implements
*/
@Override
public void deleteAll(DBIDs ids) {
- throw new UnsupportedOperationException(ExceptionMessages.UNSUPPORTED_NOT_YET);
+ throw new NotImplementedException(ExceptionMessages.UNSUPPORTED_NOT_YET);
}
@SuppressWarnings("unchecked")
@Override
public <S extends Distance<S>> KNNQuery<O, S> getKNNQuery(DistanceQuery<O, S> distanceQuery, Object... hints) {
// Query on the relation we index
- if(distanceQuery.getRelation() != relation) {
+ if (distanceQuery.getRelation() != relation) {
return null;
}
- DistanceFunction<? super O, S> distanceFunction = distanceQuery.getDistanceFunction();
- if(!this.distanceFunction.equals(distanceFunction)) {
- if(getLogger().isDebugging()) {
+ DistanceFunction<? super O, D> distanceFunction = (DistanceFunction<? super O, D>) distanceQuery.getDistanceFunction();
+ if (!this.getDistanceFunction().equals(distanceFunction)) {
+ if (getLogger().isDebugging()) {
getLogger().debug("Distance function not supported by index - or 'equals' not implemented right!");
}
return null;
}
// Bulk is not yet supported
- for(Object hint : hints) {
- if(hint == DatabaseQuery.HINT_BULK) {
+ for (Object hint : hints) {
+ if (hint == DatabaseQuery.HINT_BULK) {
return null;
}
}
- AbstractMTree<O, S, ?, ?> idx = (AbstractMTree<O, S, ?, ?>) this;
- DistanceQuery<O, S> dq = distanceFunction.instantiate(relation);
- return MTreeQueryUtil.getKNNQuery(idx, dq, hints);
+ DistanceQuery<O, D> dq = distanceFunction.instantiate(relation);
+ return (KNNQuery<O, S>) MTreeQueryUtil.getKNNQuery(this, dq, hints);
}
@SuppressWarnings("unchecked")
@Override
public <S extends Distance<S>> RangeQuery<O, S> getRangeQuery(DistanceQuery<O, S> distanceQuery, Object... hints) {
// Query on the relation we index
- if(distanceQuery.getRelation() != relation) {
+ if (distanceQuery.getRelation() != relation) {
return null;
}
- DistanceFunction<? super O, S> distanceFunction = distanceQuery.getDistanceFunction();
- if(!this.distanceFunction.equals(distanceFunction)) {
- if(getLogger().isDebugging()) {
+ DistanceFunction<? super O, D> distanceFunction = (DistanceFunction<? super O, D>) distanceQuery.getDistanceFunction();
+ if (!this.getDistanceFunction().equals(distanceFunction)) {
+ if (getLogger().isDebugging()) {
getLogger().debug("Distance function not supported by index - or 'equals' not implemented right!");
}
return null;
}
// Bulk is not yet supported
- for(Object hint : hints) {
- if(hint == DatabaseQuery.HINT_BULK) {
+ for (Object hint : hints) {
+ if (hint == DatabaseQuery.HINT_BULK) {
return null;
}
}
- AbstractMTree<O, S, ?, ?> idx = (AbstractMTree<O, S, ?, ?>) this;
- DistanceQuery<O, S> dq = distanceFunction.instantiate(relation);
- return MTreeQueryUtil.getRangeQuery(idx, dq);
+ DistanceQuery<O, D> dq = distanceFunction.instantiate(relation);
+ return (RangeQuery<O, S>) MTreeQueryUtil.getRangeQuery(this, dq);
}
@Override
@@ -181,4 +253,4 @@ public class MTreeIndex<O, D extends Distance<D>> extends MTree<O, D> implements
public String getShortName() {
return "mtree";
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeNode.java
index 017e7d6c..b3aa77fb 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeNode.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeNode.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mtree;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,7 +23,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mtree;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry;
@@ -34,7 +34,7 @@ import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry;
* @param <O> Object type
* @param <D> Distance type
*/
-public class MTreeNode<O, D extends Distance<D>> extends AbstractMTreeNode<O, D, MTreeNode<O, D>, MTreeEntry<D>> {
+public class MTreeNode<O, D extends NumberDistance<D, ?>> extends AbstractMTreeNode<O, D, MTreeNode<O, D>, MTreeEntry> {
/**
* Serial version
*/
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/package-info.java
index a34162a8..c10d683b 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/package-info.java
index b30d1193..03a4a4d6 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/DoubleDistanceMetricalIndexKNNQuery.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/DoubleDistanceMetricalIndexKNNQuery.java
index 52f777ba..9eb72178 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/DoubleDistanceMetricalIndexKNNQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/DoubleDistanceMetricalIndexKNNQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,24 +23,20 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.List;
-
-import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNHeap;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.AbstractDistanceKNNQuery;
import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceKNNHeap;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.index.tree.DirectoryEntry;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry;
import de.lmu.ifi.dbs.elki.index.tree.query.DoubleMTreeDistanceSearchCandidate;
-import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.Heap;
-import de.lmu.ifi.dbs.elki.utilities.exceptions.ExceptionMessages;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.ComparableMinHeap;
/**
* Instance of a KNN query for a particular spatial index.
@@ -55,7 +51,7 @@ public class DoubleDistanceMetricalIndexKNNQuery<O> extends AbstractDistanceKNNQ
/**
* The index to use
*/
- protected final AbstractMTree<O, DoubleDistance, ?, ?> index;
+ protected final AbstractMTree<O, DoubleDistance, ?, ?, ?> index;
/**
* Distance function
@@ -69,22 +65,23 @@ public class DoubleDistanceMetricalIndexKNNQuery<O> extends AbstractDistanceKNNQ
* @param distanceQuery Distance query used
* @param distf Distance function
*/
- public DoubleDistanceMetricalIndexKNNQuery(AbstractMTree<O, DoubleDistance, ?, ?> index, DistanceQuery<O, DoubleDistance> distanceQuery, PrimitiveDoubleDistanceFunction<? super O> distf) {
+ public DoubleDistanceMetricalIndexKNNQuery(AbstractMTree<O, DoubleDistance, ?, ?, ?> index, DistanceQuery<O, DoubleDistance> distanceQuery, PrimitiveDoubleDistanceFunction<? super O> distf) {
super(distanceQuery);
this.index = index;
this.distf = distf;
}
@Override
- public KNNResult<DoubleDistance> getKNNForObject(O q, int k) {
+ public KNNList<DoubleDistance> getKNNForObject(O q, int k) {
if (k < 1) {
throw new IllegalArgumentException("At least one object has to be requested!");
}
+ index.statistics.countKNNQuery();
- DoubleDistanceKNNHeap knnList = new DoubleDistanceKNNHeap(k);
+ DoubleDistanceKNNHeap knnList = (DoubleDistanceKNNHeap) DBIDUtil.newHeap(DoubleDistance.FACTORY, k);
double d_k = Double.POSITIVE_INFINITY;
- final Heap<DoubleMTreeDistanceSearchCandidate> pq = new Heap<DoubleMTreeDistanceSearchCandidate>();
+ final ComparableMinHeap<DoubleMTreeDistanceSearchCandidate> pq = new ComparableMinHeap<>();
// Push the root node
pq.add(new DoubleMTreeDistanceSearchCandidate(0, index.getRootID(), null, 0));
@@ -104,15 +101,16 @@ public class DoubleDistanceMetricalIndexKNNQuery<O> extends AbstractDistanceKNNQ
// directory node
if (!node.isLeaf()) {
for (int i = 0; i < node.getNumEntries(); i++) {
- final MTreeEntry<DoubleDistance> entry = node.getEntry(i);
+ final MTreeEntry entry = node.getEntry(i);
final DBID id_i = entry.getRoutingObjectID();
- double or_i = entry.getCoveringRadius().doubleValue();
- double d2 = id_p != null ? entry.getParentDistance().doubleValue() : 0;
+ double or_i = entry.getCoveringRadius();
+ double d2 = id_p != null ? entry.getParentDistance() : 0;
double diff = Math.abs(d1 - d2);
if (diff <= d_k + or_i) {
final O ob_i = relation.get(id_i);
double d3 = distf.doubleDistance(ob_i, q);
+ index.statistics.countDistanceCalculation();
double d_min = Math.max(d3 - or_i, 0);
if (d_min <= d_k) {
pq.add(new DoubleMTreeDistanceSearchCandidate(d_min, ((DirectoryEntry) entry).getPageID(), id_i, d3));
@@ -123,14 +121,15 @@ public class DoubleDistanceMetricalIndexKNNQuery<O> extends AbstractDistanceKNNQ
// data node
else {
for (int i = 0; i < node.getNumEntries(); i++) {
- final MTreeEntry<DoubleDistance> entry = node.getEntry(i);
+ final MTreeEntry entry = node.getEntry(i);
final DBID id_i = entry.getRoutingObjectID();
- double d2 = id_p != null ? entry.getParentDistance().doubleValue() : 0;
+ double d2 = id_p != null ? entry.getParentDistance() : 0;
double diff = Math.abs(d1 - d2);
if (diff <= d_k) {
final O o_i = relation.get(id_i);
double d3 = distf.doubleDistance(o_i, q);
+ index.statistics.countDistanceCalculation();
if (d3 <= d_k) {
knnList.add(d3, id_i);
d_k = knnList.doubleKNNDistance();
@@ -141,15 +140,4 @@ public class DoubleDistanceMetricalIndexKNNQuery<O> extends AbstractDistanceKNNQ
}
return knnList.toKNNList();
}
-
- @Override
- public KNNResult<DoubleDistance> getKNNForDBID(DBIDRef id, int k) {
- return getKNNForObject(relation.get(id), k);
- }
-
- @Override
- public List<KNNResult<DoubleDistance>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) {
- // TODO: implement
- throw new UnsupportedOperationException(ExceptionMessages.UNSUPPORTED_NOT_YET);
- }
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/DoubleDistanceMetricalIndexRangeQuery.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/DoubleDistanceMetricalIndexRangeQuery.java
index c3680111..714498d4 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/DoubleDistanceMetricalIndexRangeQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/DoubleDistanceMetricalIndexRangeQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,12 +24,12 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query;
*/
import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPairList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.ModifiableDoubleDistanceDBIDList;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.range.AbstractDistanceRangeQuery;
import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceDBIDList;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.index.tree.DirectoryEntry;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree;
@@ -47,7 +47,7 @@ public class DoubleDistanceMetricalIndexRangeQuery<O> extends AbstractDistanceRa
/**
* The index to use
*/
- protected final AbstractMTree<O, DoubleDistance, ?, ?> index;
+ protected final AbstractMTree<O, DoubleDistance, ?, ?, ?> index;
/**
* Distance function
@@ -61,7 +61,7 @@ public class DoubleDistanceMetricalIndexRangeQuery<O> extends AbstractDistanceRa
* @param distanceQuery Distance query used
* @param distf Distance function
*/
- public DoubleDistanceMetricalIndexRangeQuery(AbstractMTree<O, DoubleDistance, ?, ?> index, DistanceQuery<O, DoubleDistance> distanceQuery, PrimitiveDoubleDistanceFunction<? super O> distf) {
+ public DoubleDistanceMetricalIndexRangeQuery(AbstractMTree<O, DoubleDistance, ?, ?, ?> index, DistanceQuery<O, DoubleDistance> distanceQuery, PrimitiveDoubleDistanceFunction<? super O> distf) {
super(distanceQuery);
this.index = index;
this.distf = distf;
@@ -78,15 +78,19 @@ public class DoubleDistanceMetricalIndexRangeQuery<O> extends AbstractDistanceRa
* @param r_q the query range
* @param result the list holding the query results
*/
- private void doRangeQuery(DBID id_p, AbstractMTreeNode<O, DoubleDistance, ?, ?> node, O q, double r_q, DoubleDistanceDBIDList result) {
+ private void doRangeQuery(DBID id_p, AbstractMTreeNode<O, DoubleDistance, ?, ?> node, O q, double r_q, ModifiableDoubleDistanceDBIDList result) {
final O o_p = id_p != null ? relation.get(id_p) : null;
- double d1 = id_p != null ? distf.doubleDistance(o_p, q) : 0;
+ double d1 = 0.;
+ if (id_p != null) {
+ d1 = distf.doubleDistance(o_p, q);
+ index.statistics.countDistanceCalculation();
+ }
if (!node.isLeaf()) {
for (int i = 0; i < node.getNumEntries(); i++) {
- MTreeEntry<DoubleDistance> entry = node.getEntry(i);
+ MTreeEntry entry = node.getEntry(i);
- double r_or = entry.getCoveringRadius().doubleValue();
- double d2 = id_p != null ? entry.getParentDistance().doubleValue() : 0;
+ double r_or = entry.getCoveringRadius();
+ double d2 = id_p != null ? entry.getParentDistance() : 0;
double diff = Math.abs(d1 - d2);
double sum = r_q + r_or;
@@ -94,6 +98,7 @@ public class DoubleDistanceMetricalIndexRangeQuery<O> extends AbstractDistanceRa
if (diff <= sum) {
DBID id_r = entry.getRoutingObjectID();
double d3 = distf.doubleDistance(relation.get(id_r), q);
+ index.statistics.countDistanceCalculation();
if (d3 <= sum) {
AbstractMTreeNode<O, DoubleDistance, ?, ?> child = index.getNode(((DirectoryEntry) entry).getPageID());
doRangeQuery(id_r, child, q, r_q, result);
@@ -102,15 +107,16 @@ public class DoubleDistanceMetricalIndexRangeQuery<O> extends AbstractDistanceRa
}
} else {
for (int i = 0; i < node.getNumEntries(); i++) {
- MTreeEntry<DoubleDistance> entry = node.getEntry(i);
+ MTreeEntry entry = node.getEntry(i);
- double d2 = id_p != null ? entry.getParentDistance().doubleValue() : 0;
+ double d2 = id_p != null ? entry.getParentDistance() : 0;
double diff = Math.abs(d1 - d2);
if (diff <= r_q) {
DBID id_j = entry.getRoutingObjectID();
O o_j = relation.get(id_j);
double d3 = distf.doubleDistance(o_j, q);
+ index.statistics.countDistanceCalculation();
if (d3 <= r_q) {
result.add(d3, id_j);
}
@@ -120,16 +126,12 @@ public class DoubleDistanceMetricalIndexRangeQuery<O> extends AbstractDistanceRa
}
@Override
- public DistanceDBIDResult<DoubleDistance> getRangeForObject(O obj, DoubleDistance range) {
- final DoubleDistanceDBIDList result = new DoubleDistanceDBIDList();
+ public DistanceDBIDList<DoubleDistance> getRangeForObject(O obj, DoubleDistance range) {
+ final DoubleDistanceDBIDPairList result = new DoubleDistanceDBIDPairList();
doRangeQuery(null, index.getRoot(), obj, range.doubleValue(), result);
+ index.statistics.countRangeQuery();
result.sort();
return result;
}
-
- @Override
- public DistanceDBIDResult<DoubleDistance> getRangeForDBID(DBIDRef id, DoubleDistance range) {
- return getRangeForObject(relation.get(id), range);
- }
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MTreeQueryUtil.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MTreeQueryUtil.java
index 34980542..cc27b383 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MTreeQueryUtil.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MTreeQueryUtil.java
@@ -5,15 +5,15 @@ import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -50,17 +50,17 @@ public final class MTreeQueryUtil {
* @return Query object
*/
@SuppressWarnings({ "cast", "unchecked" })
- public static <O, D extends Distance<D>> KNNQuery<O, D> getKNNQuery(AbstractMTree<O, D, ?, ?> tree, DistanceQuery<O, D> distanceQuery, Object... hints) {
+ public static <O, D extends NumberDistance<D, ?>> KNNQuery<O, D> getKNNQuery(AbstractMTree<O, D, ?, ?, ?> tree, DistanceQuery<O, D> distanceQuery, Object... hints) {
DistanceFunction<? super O, D> df = distanceQuery.getDistanceFunction();
// Can we use an optimized query?
- if(df instanceof PrimitiveDoubleDistanceFunction) {
+ if (df instanceof PrimitiveDoubleDistanceFunction) {
PrimitiveDoubleDistanceFunction<? super O> dfc = (PrimitiveDoubleDistanceFunction<? super O>) df;
- AbstractMTree<O, DoubleDistance, ?, ?> treec = (AbstractMTree<O, DoubleDistance, ?, ?>) tree;
+ AbstractMTree<O, DoubleDistance, ?, ?, ?> treec = (AbstractMTree<O, DoubleDistance, ?, ?, ?>) tree;
DistanceQuery<O, DoubleDistance> dqc = (DistanceQuery<O, DoubleDistance>) distanceQuery;
- KNNQuery<O, ?> q = new DoubleDistanceMetricalIndexKNNQuery<O>(treec, dqc, dfc);
+ KNNQuery<O, ?> q = new DoubleDistanceMetricalIndexKNNQuery<>(treec, dqc, dfc);
return (KNNQuery<O, D>) q;
}
- return new MetricalIndexKNNQuery<O, D>(tree, distanceQuery);
+ return new MetricalIndexKNNQuery<>(tree, distanceQuery);
}
/**
@@ -75,16 +75,16 @@ public final class MTreeQueryUtil {
* @return Query object
*/
@SuppressWarnings({ "cast", "unchecked" })
- public static <O, D extends Distance<D>> RangeQuery<O, D> getRangeQuery(AbstractMTree<O, D, ?, ?> tree, DistanceQuery<O, D> distanceQuery, Object... hints) {
+ public static <O, D extends NumberDistance<D, ?>> RangeQuery<O, D> getRangeQuery(AbstractMTree<O, D, ?, ?, ?> tree, DistanceQuery<O, D> distanceQuery, Object... hints) {
DistanceFunction<? super O, D> df = distanceQuery.getDistanceFunction();
// Can we use an optimized query?
- if(df instanceof PrimitiveDoubleDistanceFunction) {
+ if (df instanceof PrimitiveDoubleDistanceFunction) {
PrimitiveDoubleDistanceFunction<? super O> dfc = (PrimitiveDoubleDistanceFunction<? super O>) df;
- AbstractMTree<O, DoubleDistance, ?, ?> treec = (AbstractMTree<O, DoubleDistance, ?, ?>) tree;
+ AbstractMTree<O, DoubleDistance, ?, ?, ?> treec = (AbstractMTree<O, DoubleDistance, ?, ?, ?>) tree;
DistanceQuery<O, DoubleDistance> dqc = (DistanceQuery<O, DoubleDistance>) distanceQuery;
- RangeQuery<O, ?> q = new DoubleDistanceMetricalIndexRangeQuery<O>(treec, dqc, dfc);
+ RangeQuery<O, ?> q = new DoubleDistanceMetricalIndexRangeQuery<>(treec, dqc, dfc);
return (RangeQuery<O, D>) q;
}
- return new MetricalIndexRangeQuery<O, D>(tree, distanceQuery);
+ return new MetricalIndexRangeQuery<>(tree, distanceQuery);
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MetricalIndexKNNQuery.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MetricalIndexKNNQuery.java
index c2fafdae..f40e001b 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MetricalIndexKNNQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MetricalIndexKNNQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,25 +23,19 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.List;
-
-import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNHeap;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.AbstractDistanceKNNQuery;
-import de.lmu.ifi.dbs.elki.distance.DistanceUtil;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNHeap;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNUtil;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.tree.DirectoryEntry;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry;
-import de.lmu.ifi.dbs.elki.index.tree.query.GenericMTreeDistanceSearchCandidate;
-import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.Heap;
-import de.lmu.ifi.dbs.elki.utilities.exceptions.ExceptionMessages;
+import de.lmu.ifi.dbs.elki.index.tree.query.DoubleMTreeDistanceSearchCandidate;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.ComparableMinHeap;
/**
* Instance of a KNN query for a particular spatial index.
@@ -53,11 +47,11 @@ import de.lmu.ifi.dbs.elki.utilities.exceptions.ExceptionMessages;
* @param <O> Object type
* @param <D> Distance type
*/
-public class MetricalIndexKNNQuery<O, D extends Distance<D>> extends AbstractDistanceKNNQuery<O, D> {
+public class MetricalIndexKNNQuery<O, D extends NumberDistance<D, ?>> extends AbstractDistanceKNNQuery<O, D> {
/**
* The index to use
*/
- protected final AbstractMTree<O, D, ?, ?> index;
+ protected final AbstractMTree<O, D, ?, ?, ?> index;
/**
* Constructor.
@@ -65,55 +59,56 @@ public class MetricalIndexKNNQuery<O, D extends Distance<D>> extends AbstractDis
* @param index Index to use
* @param distanceQuery Distance query used
*/
- public MetricalIndexKNNQuery(AbstractMTree<O, D, ?, ?> index, DistanceQuery<O, D> distanceQuery) {
+ public MetricalIndexKNNQuery(AbstractMTree<O, D, ?, ?, ?> index, DistanceQuery<O, D> distanceQuery) {
super(distanceQuery);
this.index = index;
}
@Override
- public KNNResult<D> getKNNForObject(O q, int k) {
+ public KNNList<D> getKNNForObject(O q, int k) {
if (k < 1) {
throw new IllegalArgumentException("At least one object has to be requested!");
}
+ index.statistics.countKNNQuery();
- final D nullDistance = index.getDistanceFactory().nullDistance();
- KNNHeap<D> knnList = KNNUtil.newHeap(distanceQuery.getDistanceFactory(), k);
+ KNNHeap<D> knnList = DBIDUtil.newHeap(distanceQuery.getDistanceFactory(), k);
D d_k = knnList.getKNNDistance();
- final Heap<GenericMTreeDistanceSearchCandidate<D>> pq = new Heap<GenericMTreeDistanceSearchCandidate<D>>();
+ final ComparableMinHeap<DoubleMTreeDistanceSearchCandidate> pq = new ComparableMinHeap<>();
// push root
- pq.add(new GenericMTreeDistanceSearchCandidate<D>(nullDistance, index.getRootID(), null, nullDistance));
+ pq.add(new DoubleMTreeDistanceSearchCandidate(0., index.getRootID(), null, 0.));
// search in tree
while (!pq.isEmpty()) {
- GenericMTreeDistanceSearchCandidate<D> pqNode = pq.poll();
+ DoubleMTreeDistanceSearchCandidate pqNode = pq.poll();
- if (knnList.size() >= k && pqNode.mindist.compareTo(d_k) > 0) {
+ if (knnList.size() >= k && pqNode.mindist > d_k.doubleValue()) {
break;
}
AbstractMTreeNode<?, D, ?, ?> node = index.getNode(pqNode.nodeID);
DBID id_p = pqNode.routingObjectID;
- D d1 = pqNode.routingDistance;
+ double d1 = pqNode.routingDistance;
// directory node
if (!node.isLeaf()) {
for (int i = 0; i < node.getNumEntries(); i++) {
- MTreeEntry<D> entry = node.getEntry(i);
+ MTreeEntry entry = node.getEntry(i);
DBID o_r = entry.getRoutingObjectID();
- D r_or = entry.getCoveringRadius();
- D d2 = id_p != null ? entry.getParentDistance() : nullDistance;
+ double r_or = entry.getCoveringRadius();
+ double d2 = id_p != null ? entry.getParentDistance() : 0.;
- D diff = d1.compareTo(d2) > 0 ? d1.minus(d2) : d2.minus(d1);
+ double diff = Math.abs(d1 - d2);
- D sum = d_k.plus(r_or);
+ double sum = d_k.doubleValue() + r_or;
- if (diff.compareTo(sum) <= 0) {
- D d3 = distanceQuery.distance(o_r, q);
- D d_min = DistanceUtil.max(d3.minus(r_or), index.getDistanceFactory().nullDistance());
- if (d_min.compareTo(d_k) <= 0) {
- pq.add(new GenericMTreeDistanceSearchCandidate<D>(d_min, ((DirectoryEntry) entry).getPageID(), o_r, d3));
+ if (diff <= sum) {
+ double d3 = distanceQuery.distance(o_r, q).doubleValue();
+ index.statistics.countDistanceCalculation();
+ double d_min = Math.max(d3 - r_or, 0.);
+ if (d_min <= d_k.doubleValue()) {
+ pq.add(new DoubleMTreeDistanceSearchCandidate(d_min, ((DirectoryEntry) entry).getPageID(), o_r, d3));
}
}
}
@@ -121,15 +116,16 @@ public class MetricalIndexKNNQuery<O, D extends Distance<D>> extends AbstractDis
// data node
else {
for (int i = 0; i < node.getNumEntries(); i++) {
- MTreeEntry<D> entry = node.getEntry(i);
+ MTreeEntry entry = node.getEntry(i);
DBID o_j = entry.getRoutingObjectID();
- D d2 = id_p != null ? entry.getParentDistance() : nullDistance;
+ double d2 = id_p != null ? entry.getParentDistance() : 0.;
- D diff = (d1.compareTo(d2) > 0) ? d1.minus(d2) : d2.minus(d1);
+ double diff = Math.abs(d1 - d2);
- if (diff.compareTo(d_k) <= 0) {
+ if (diff <= d_k.doubleValue()) {
D d3 = distanceQuery.distance(o_j, q);
+ index.statistics.countDistanceCalculation();
if (d3.compareTo(d_k) <= 0) {
knnList.add(d3, o_j);
d_k = knnList.getKNNDistance();
@@ -140,15 +136,4 @@ public class MetricalIndexKNNQuery<O, D extends Distance<D>> extends AbstractDis
}
return knnList.toKNNList();
}
-
- @Override
- public KNNResult<D> getKNNForDBID(DBIDRef id, int k) {
- return getKNNForObject(relation.get(id), k);
- }
-
- @Override
- public List<KNNResult<D>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) {
- // TODO: implement
- throw new UnsupportedOperationException(ExceptionMessages.UNSUPPORTED_NOT_YET);
- }
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MetricalIndexRangeQuery.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MetricalIndexRangeQuery.java
index 2ca19877..fedf8ddb 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MetricalIndexRangeQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MetricalIndexRangeQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,12 +24,11 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query;
*/
import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.generic.GenericDistanceDBIDList;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.range.AbstractDistanceRangeQuery;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.GenericDistanceDBIDList;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.tree.DirectoryEntry;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode;
@@ -42,11 +41,11 @@ import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry;
*
* @apiviz.uses AbstractMTree
*/
-public class MetricalIndexRangeQuery<O, D extends Distance<D>> extends AbstractDistanceRangeQuery<O, D> {
+public class MetricalIndexRangeQuery<O, D extends NumberDistance<D, ?>> extends AbstractDistanceRangeQuery<O, D> {
/**
* The index to use
*/
- protected final AbstractMTree<O, D, ?, ?> index;
+ protected final AbstractMTree<O, D, ?, ?, ?> index;
/**
* Constructor.
@@ -54,7 +53,7 @@ public class MetricalIndexRangeQuery<O, D extends Distance<D>> extends AbstractD
* @param index Index to use
* @param distanceQuery Distance query used
*/
- public MetricalIndexRangeQuery(AbstractMTree<O, D, ?, ?> index, DistanceQuery<O, D> distanceQuery) {
+ public MetricalIndexRangeQuery(AbstractMTree<O, D, ?, ?, ?> index, DistanceQuery<O, D> distanceQuery) {
super(distanceQuery);
this.index = index;
}
@@ -71,22 +70,26 @@ public class MetricalIndexRangeQuery<O, D extends Distance<D>> extends AbstractD
* @param result the list holding the query results
*/
private void doRangeQuery(DBID o_p, AbstractMTreeNode<O, D, ?, ?> node, O q, D r_q, GenericDistanceDBIDList<D> result) {
- final D nullDistance = distanceQuery.nullDistance();
- D d1 = o_p != null ? distanceQuery.distance(o_p, q) : nullDistance;
+ double d1 = 0.;
+ if (o_p != null) {
+ d1 = distanceQuery.distance(o_p, q).doubleValue();
+ index.statistics.countDistanceCalculation();
+ }
if (!node.isLeaf()) {
for (int i = 0; i < node.getNumEntries(); i++) {
- MTreeEntry<D> entry = node.getEntry(i);
+ MTreeEntry entry = node.getEntry(i);
DBID o_r = entry.getRoutingObjectID();
- D r_or = entry.getCoveringRadius();
- D d2 = o_p != null ? entry.getParentDistance() : nullDistance;
- D diff = d1.compareTo(d2) > 0 ? d1.minus(d2) : d2.minus(d1);
+ double r_or = entry.getCoveringRadius();
+ double d2 = o_p != null ? entry.getParentDistance() : 0.;
+ double diff = Math.abs(d1 - d2);
- D sum = r_q.plus(r_or);
+ double sum = r_q.doubleValue() + r_or;
- if (diff.compareTo(sum) <= 0) {
+ if (diff <= sum) {
D d3 = distanceQuery.distance(o_r, q);
- if (d3.compareTo(sum) <= 0) {
+ index.statistics.countDistanceCalculation();
+ if (d3.doubleValue() <= sum) {
AbstractMTreeNode<O, D, ?, ?> child = index.getNode(((DirectoryEntry) entry).getPageID());
doRangeQuery(o_r, child, q, r_q, result);
}
@@ -94,15 +97,16 @@ public class MetricalIndexRangeQuery<O, D extends Distance<D>> extends AbstractD
}
} else {
for (int i = 0; i < node.getNumEntries(); i++) {
- MTreeEntry<D> entry = node.getEntry(i);
+ MTreeEntry entry = node.getEntry(i);
DBID o_j = entry.getRoutingObjectID();
- D d2 = o_p != null ? entry.getParentDistance() : nullDistance;
+ double d2 = o_p != null ? entry.getParentDistance() : 0.;
- D diff = d1.compareTo(d2) > 0 ? d1.minus(d2) : d2.minus(d1);
+ double diff = Math.abs(d1 - d2);
- if (diff.compareTo(r_q) <= 0) {
+ if (diff <= r_q.doubleValue()) {
D d3 = distanceQuery.distance(o_j, q);
+ index.statistics.countDistanceCalculation();
if (d3.compareTo(r_q) <= 0) {
result.add(d3, o_j);
}
@@ -112,18 +116,14 @@ public class MetricalIndexRangeQuery<O, D extends Distance<D>> extends AbstractD
}
@Override
- public DistanceDBIDResult<D> getRangeForObject(O obj, D range) {
- final GenericDistanceDBIDList<D> result = new GenericDistanceDBIDList<D>();
+ public DistanceDBIDList<D> getRangeForObject(O obj, D range) {
+ final GenericDistanceDBIDList<D> result = new GenericDistanceDBIDList<>();
doRangeQuery(null, index.getRoot(), obj, range, result);
+ index.statistics.countRangeQuery();
// sort the result according to the distances
result.sort();
return result;
}
-
- @Override
- public DistanceDBIDResult<D> getRangeForDBID(DBIDRef id, D range) {
- return getRangeForObject(relation.get(id), range);
- }
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MkTreeRKNNQuery.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MkTreeRKNNQuery.java
index e3f35c50..c8cec69f 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MkTreeRKNNQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MkTreeRKNNQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,13 +27,14 @@ import java.util.List;
import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.rknn.AbstractRKNNQuery;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.AbstractMkTree;
import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
import de.lmu.ifi.dbs.elki.utilities.exceptions.ExceptionMessages;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.NotImplementedException;
/**
* Instance of a rKNN query for a particular spatial index.
@@ -42,11 +43,11 @@ import de.lmu.ifi.dbs.elki.utilities.exceptions.ExceptionMessages;
*
* @apiviz.uses AbstractMkTree
*/
-public class MkTreeRKNNQuery<O, D extends Distance<D>> extends AbstractRKNNQuery<O, D> {
+public class MkTreeRKNNQuery<O, D extends NumberDistance<D, ?>> extends AbstractRKNNQuery<O, D> {
/**
* The index to use
*/
- protected final AbstractMkTree<O, D, ?, ?> index;
+ protected final AbstractMkTree<O, D, ?, ?, ?> index;
/**
* Constructor.
@@ -54,24 +55,24 @@ public class MkTreeRKNNQuery<O, D extends Distance<D>> extends AbstractRKNNQuery
* @param index Index to use
* @param distanceQuery Distance query used
*/
- public MkTreeRKNNQuery(AbstractMkTree<O, D, ?, ?> index, DistanceQuery<O, D> distanceQuery) {
+ public MkTreeRKNNQuery(AbstractMkTree<O, D, ?, ?, ?> index, DistanceQuery<O, D> distanceQuery) {
super(distanceQuery);
this.index = index;
}
@Override
- public DistanceDBIDResult<D> getRKNNForObject(O obj, int k) {
+ public DistanceDBIDList<D> getRKNNForObject(O obj, int k) {
throw new AbortException("Preprocessor KNN query only supports ID queries.");
}
@Override
- public DistanceDBIDResult<D> getRKNNForDBID(DBIDRef id, int k) {
+ public DistanceDBIDList<D> getRKNNForDBID(DBIDRef id, int k) {
return index.reverseKNNQuery(id, k);
}
@Override
- public List<? extends DistanceDBIDResult<D>> getRKNNForBulkDBIDs(ArrayDBIDs ids, int k) {
+ public List<? extends DistanceDBIDList<D>> getRKNNForBulkDBIDs(ArrayDBIDs ids, int k) {
// TODO: implement
- throw new UnsupportedOperationException(ExceptionMessages.UNSUPPORTED_NOT_YET);
+ throw new NotImplementedException(ExceptionMessages.UNSUPPORTED_NOT_YET);
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/package-info.java
index fa7e6248..a975fdff 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/package-info.java
@@ -6,7 +6,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/MTreeSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/MTreeSplit.java
deleted file mode 100644
index f9a3c248..00000000
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/MTreeSplit.java
+++ /dev/null
@@ -1,138 +0,0 @@
-package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.split;
-
-/*
- This file is part of ELKI:
- Environment for Developing KDD-Applications Supported by Index-Structures
-
- Copyright (C) 2012
- Ludwig-Maximilians-Universität München
- Lehr- und Forschungseinheit für Datenbanksysteme
- ELKI Development Team
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
-import de.lmu.ifi.dbs.elki.distance.DistanceUtil;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
-import de.lmu.ifi.dbs.elki.index.tree.DistanceEntry;
-import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode;
-import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry;
-
-/**
- * Abstract super class for splitting a node in an M-Tree.
- *
- * @author Elke Achtert
- *
- * @apiviz.composedOf Assignments
- *
- * @param <O> the type of DatabaseObject to be stored in the M-Tree
- * @param <D> the type of Distance used in the M-Tree
- * @param <N> the type of AbstractMTreeNode used in the M-Tree
- * @param <E> the type of MetricalEntry used in the M-Tree
- */
-public abstract class MTreeSplit<O, D extends Distance<D>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry<D>> {
- /**
- * Encapsulates the two promotion objects and their assignments.
- */
- Assignments<D, E> assignments;
-
- /**
- * Creates a balanced partition of the entries of the specified node.
- *
- * @param node the node to be split
- * @param routingObject1 the id of the first routing object
- * @param routingObject2 the id of the second routing object
- * @param distanceFunction the distance function to compute the distances
- * @return an assignment that holds a balanced partition of the entries of the
- * specified node
- */
- Assignments<D, E> balancedPartition(N node, DBID routingObject1, DBID routingObject2, DistanceQuery<O, D> distanceFunction) {
- HashSet<E> assigned1 = new HashSet<E>();
- HashSet<E> assigned2 = new HashSet<E>();
-
- D currentCR1 = distanceFunction.nullDistance();
- D currentCR2 = distanceFunction.nullDistance();
-
- // determine the nearest neighbors
- List<DistanceEntry<D, E>> list1 = new ArrayList<DistanceEntry<D, E>>();
- List<DistanceEntry<D, E>> list2 = new ArrayList<DistanceEntry<D, E>>();
- for(int i = 0; i < node.getNumEntries(); i++) {
- DBID id = node.getEntry(i).getRoutingObjectID();
- // determine the distance of o to o1 / o2
- D d1 = distanceFunction.distance(routingObject1, id);
- D d2 = distanceFunction.distance(routingObject2, id);
-
- list1.add(new DistanceEntry<D, E>(node.getEntry(i), d1, i));
- list2.add(new DistanceEntry<D, E>(node.getEntry(i), d2, i));
- }
- Collections.sort(list1);
- Collections.sort(list2);
-
- for(int i = 0; i < node.getNumEntries(); i++) {
- if(i % 2 == 0) {
- currentCR1 = assignNN(assigned1, assigned2, list1, currentCR1, node.isLeaf());
- }
- else {
- currentCR2 = assignNN(assigned2, assigned1, list2, currentCR2, node.isLeaf());
- }
- }
- return new Assignments<D, E>(routingObject1, routingObject2, currentCR1, currentCR2, assigned1, assigned2);
- }
-
- /**
- * Assigns the first object of the specified list to the first assignment that
- * it is not yet assigned to the second assignment.
- *
- * @param assigned1 the first assignment
- * @param assigned2 the second assignment
- * @param list the list, the first object should be assigned
- * @param currentCR the current covering radius
- * @param isLeaf true, if the node of the entries to be assigned is a leaf,
- * false otherwise
- * @return the new covering radius
- */
- private D assignNN(Set<E> assigned1, Set<E> assigned2, List<DistanceEntry<D, E>> list, D currentCR, boolean isLeaf) {
- DistanceEntry<D, E> distEntry = list.remove(0);
- while(assigned2.contains(distEntry.getEntry())) {
- distEntry = list.remove(0);
- }
- // Update the parent distance.
- distEntry.getEntry().setParentDistance(distEntry.getDistance());
- assigned1.add(distEntry.getEntry());
-
- if(isLeaf) {
- return DistanceUtil.max(currentCR, distEntry.getDistance());
- }
- else {
- return DistanceUtil.max(currentCR, distEntry.getDistance().plus((distEntry.getEntry()).getCoveringRadius()));
- }
- }
-
- /**
- * Returns the assignments of this split.
- *
- * @return the assignments of this split
- */
- public Assignments<D, E> getAssignments() {
- return assignments;
- }
-}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/package-info.java
deleted file mode 100644
index ed13ae73..00000000
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/package-info.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- * <p>Splitting strategies of nodes in an M-Tree (and variants).</p>
- */
-/*
-This file is part of ELKI:
-Environment for Developing KDD-Applications Supported by Index-Structures
-
-Copyright (C) 2012
-Ludwig-Maximilians-Universität München
-Lehr- und Forschungseinheit für Datenbanksysteme
-ELKI Development Team
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.split; \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/insert/MTreeInsert.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/insert/MTreeInsert.java
new file mode 100644
index 00000000..65fc3768
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/insert/MTreeInsert.java
@@ -0,0 +1,50 @@
+package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.insert;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
+import de.lmu.ifi.dbs.elki.index.tree.IndexTreePath;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry;
+
+/**
+ * Default insertion strategy for the M-tree.
+ *
+ * <b>Warning:</b> as of now, insertion strategies <b>will already modify the
+ * tree</b>, i.e. adjust cover radiuses.
+ *
+ * FIXME: move this to the actual insert.
+ *
+ * @author Erich Schubert
+ */
+public interface MTreeInsert<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry> {
+ /**
+ * Choose the subpath to insert into.
+ *
+ * @param tree Tree to process
+ * @param object Object to insert
+ * @return Path to insertion node
+ */
+ IndexTreePath<E> choosePath(AbstractMTree<O, D, N, E, ?> tree, E object);
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/insert/MinimumEnlargementInsert.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/insert/MinimumEnlargementInsert.java
new file mode 100644
index 00000000..f848f5f4
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/insert/MinimumEnlargementInsert.java
@@ -0,0 +1,117 @@
+package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.insert;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
+import de.lmu.ifi.dbs.elki.index.tree.IndexTreePath;
+import de.lmu.ifi.dbs.elki.index.tree.TreeIndexPathComponent;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+
+/**
+ * Default insertion strategy for the M-tree.
+ *
+ * Reference:
+ * <p>
+ * P. Ciaccia, M. Patella, P. Zezula<br />
+ * M-tree: An Efficient Access Method for Similarity Search in Metric Spaces<br />
+ * In Proceedings of 23rd International Conference on Very Large Data Bases
+ * (VLDB'97), August 25-29, 1997, Athens, Greece
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@Reference(authors = "P. Ciaccia, M. Patella, P. Zezula", title = "M-tree: An Efficient Access Method for Similarity Search in Metric Spaces", booktitle = "VLDB'97, Proceedings of 23rd International Conference on Very Large Data Bases, August 25-29, 1997, Athens, Greece", url = "http://www.vldb.org/conf/1997/P426.PDF")
+public class MinimumEnlargementInsert<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry> implements MTreeInsert<O, D, N, E> {
+ @Override
+ public IndexTreePath<E> choosePath(AbstractMTree<O, D, N, E, ?> tree, E object) {
+ return choosePath(tree, object, tree.getRootPath());
+ }
+
+ /**
+ * Chooses the best path of the specified subtree for insertion of the given
+ * object.
+ *
+ * @param tree the tree to insert into
+ * @param object the entry to search
+ * @param subtree the subtree to be tested for insertion
+ * @return the path of the appropriate subtree to insert the given object
+ */
+ private IndexTreePath<E> choosePath(AbstractMTree<O, D, N, E, ?> tree, E object, IndexTreePath<E> subtree) {
+ N node = tree.getNode(subtree.getLastPathComponent().getEntry());
+
+ // leaf
+ if (node.isLeaf()) {
+ return subtree;
+ }
+
+ double bestDistance;
+ int bestIdx;
+ E bestEntry;
+ double enlarge; // Track best enlargement - null for no enlargement needed.
+ // Initialize from first:
+ {
+ bestIdx = 0;
+ bestEntry = node.getEntry(0);
+ bestDistance = tree.distance(object.getRoutingObjectID(), bestEntry.getRoutingObjectID()).doubleValue();
+ if (bestDistance <= bestEntry.getCoveringRadius()) {
+ enlarge = 0.;
+ } else {
+ enlarge = bestDistance - bestEntry.getCoveringRadius();
+ }
+ }
+
+ // Iterate over remaining
+ for (int i = 1; i < node.getNumEntries(); i++) {
+ E entry = node.getEntry(i);
+ double distance = tree.distance(object.getRoutingObjectID(), entry.getRoutingObjectID()).doubleValue();
+
+ if (distance <= entry.getCoveringRadius()) {
+ if (enlarge > 0. || distance < bestDistance) {
+ bestIdx = i;
+ bestEntry = entry;
+ bestDistance = distance;
+ enlarge = 0.;
+ }
+ } else if (enlarge > 0.) {
+ double enlrg = distance - entry.getCoveringRadius();
+ if (enlrg < enlarge) {
+ bestIdx = i;
+ bestEntry = entry;
+ bestDistance = distance;
+ enlarge = enlrg;
+ }
+ }
+ }
+
+ // FIXME: move this to the actual insertion procedure!
+ // Apply enlargement
+ if (enlarge > 0) {
+ bestEntry.setCoveringRadius(bestEntry.getCoveringRadius() + enlarge);
+ }
+
+ return choosePath(tree, object, subtree.pathByAddingChild(new TreeIndexPathComponent<>(bestEntry, bestIdx)));
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/insert/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/insert/package-info.java
new file mode 100644
index 00000000..64a85c2d
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/insert/package-info.java
@@ -0,0 +1,26 @@
+/**
+ * <p>Insertion (choose path) strategies of nodes in an M-Tree (and variants).</p>
+ */
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.insert; \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/package-info.java
new file mode 100644
index 00000000..0d019cf3
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/package-info.java
@@ -0,0 +1,26 @@
+/**
+ * <p>Strategies for M-Trees (and variants).</p>
+ */
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies; \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/Assignments.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/Assignments.java
index 5cb6c794..1079a141 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/Assignments.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/Assignments.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.split;
+package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.split;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,22 +23,21 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.split;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import java.util.List;
+
import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
/**
* Encapsulates the attributes of an assignment during a split.
*
* @author Elke Achtert
- * @param <D> the type of Distance used in the M-Tree
+ *
+ * @apiviz.composedOf DistanceEntry
+ *
* @param <E> the type of MetricalEntry used in the M-Tree
*/
-public class Assignments<D extends Distance<D>, E extends MTreeEntry<D>> {
+public class Assignments<E extends MTreeEntry> {
/**
* The id of the first routing object.
*/
@@ -52,22 +51,22 @@ public class Assignments<D extends Distance<D>, E extends MTreeEntry<D>> {
/**
* The first covering radius.
*/
- private D firstCoveringRadius;
+ private double firstCoveringRadius;
/**
* The second covering radius.
*/
- private D secondCoveringRadius;
+ private double secondCoveringRadius;
/**
* The assignments to the first routing object.
*/
- private List<E> firstAssignments;
+ private List<DistanceEntry<E>> firstAssignments;
/**
* The assignments to the second routing object.
*/
- private List<E> secondAssignments;
+ private List<DistanceEntry<E>> secondAssignments;
/**
* Provides an assignment during a split of an MTree node.
@@ -79,13 +78,13 @@ public class Assignments<D extends Distance<D>, E extends MTreeEntry<D>> {
* @param firstAssignments the assignments to the first routing object
* @param secondAssignments the assignments to the second routing object
*/
- public Assignments(DBID id1, DBID id2, D firstCoveringRadius, D secondCoveringRadius, Set<E> firstAssignments, Set<E> secondAssignments) {
+ public Assignments(DBID id1, DBID id2, double firstCoveringRadius, double secondCoveringRadius, List<DistanceEntry<E>> firstAssignments, List<DistanceEntry<E>> secondAssignments) {
this.id1 = id1;
this.id2 = id2;
this.firstCoveringRadius = firstCoveringRadius;
this.secondCoveringRadius = secondCoveringRadius;
- this.firstAssignments = new ArrayList<E>(firstAssignments);
- this.secondAssignments = new ArrayList<E>(secondAssignments);
+ this.firstAssignments = firstAssignments;
+ this.secondAssignments = secondAssignments;
}
/**
@@ -111,7 +110,7 @@ public class Assignments<D extends Distance<D>, E extends MTreeEntry<D>> {
*
* @return the first covering radius
*/
- public D getFirstCoveringRadius() {
+ public double getFirstCoveringRadius() {
return firstCoveringRadius;
}
@@ -120,7 +119,7 @@ public class Assignments<D extends Distance<D>, E extends MTreeEntry<D>> {
*
* @return the second covering radius
*/
- public D getSecondCoveringRadius() {
+ public double getSecondCoveringRadius() {
return secondCoveringRadius;
}
@@ -129,7 +128,7 @@ public class Assignments<D extends Distance<D>, E extends MTreeEntry<D>> {
*
* @return the assignments to the first routing object
*/
- public List<E> getFirstAssignments() {
+ public List<DistanceEntry<E>> getFirstAssignments() {
return firstAssignments;
}
@@ -138,7 +137,7 @@ public class Assignments<D extends Distance<D>, E extends MTreeEntry<D>> {
*
* @return the assignments to the second routing object
*/
- public List<E> getSecondAssignments() {
+ public List<DistanceEntry<E>> getSecondAssignments() {
return secondAssignments;
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/DistanceEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/DistanceEntry.java
index 3cf6dfb9..642e5a63 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/DistanceEntry.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/DistanceEntry.java
@@ -1,10 +1,12 @@
-package de.lmu.ifi.dbs.elki.index.tree;
+package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.split;
+
+import de.lmu.ifi.dbs.elki.index.tree.Entry;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,21 +25,17 @@ package de.lmu.ifi.dbs.elki.index.tree;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
-
/**
* Helper class: encapsulates an entry in an Index and a distance value
* belonging to this entry.
*
* @author Elke Achtert
*
- * @apiviz.composedOf Distance
* @apiviz.uses Entry
*
* @param <E> the type of Entry used in the index
- * @param <D> the type of Distance used
*/
-public class DistanceEntry<D extends Distance<D>, E extends Entry> implements Comparable<DistanceEntry<D, E>> {
+public class DistanceEntry<E extends Entry> implements Comparable<DistanceEntry<E>> {
/**
* The entry of the Index.
*/
@@ -46,7 +44,7 @@ public class DistanceEntry<D extends Distance<D>, E extends Entry> implements Co
/**
* The distance value belonging to the entry.
*/
- private D distance;
+ private double distance;
/**
* The index of the entry in its parent's child array.
@@ -60,7 +58,7 @@ public class DistanceEntry<D extends Distance<D>, E extends Entry> implements Co
* @param distance the distance value belonging to the entry
* @param index the index of the entry in its parent' child array
*/
- public DistanceEntry(E entry, D distance, int index) {
+ public DistanceEntry(E entry, double distance, int index) {
this.entry = entry;
this.distance = distance;
this.index = index;
@@ -80,7 +78,7 @@ public class DistanceEntry<D extends Distance<D>, E extends Entry> implements Co
*
* @return the distance value belonging to the entry
*/
- public D getDistance() {
+ public double getDistance() {
return distance;
}
@@ -103,13 +101,13 @@ public class DistanceEntry<D extends Distance<D>, E extends Entry> implements Co
* being compared to this Object.
*/
@Override
- public int compareTo(DistanceEntry<D, E> o) {
- int comp = distance.compareTo(o.distance);
- if(comp != 0) {
+ public int compareTo(DistanceEntry<E> o) {
+ int comp = Double.compare(distance, o.distance);
+ if (comp != 0) {
return comp;
}
- //return entry.getEntryID().compareTo(o.entry.getEntryID());
+ // return entry.getEntryID().compareTo(o.entry.getEntryID());
return 0;
}
@@ -122,4 +120,4 @@ public class DistanceEntry<D extends Distance<D>, E extends Entry> implements Co
public String toString() {
return "" + entry.toString() + "(" + distance + ")";
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/MLBDistSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/MLBDistSplit.java
index f4da4a1a..d294d5b3 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/MLBDistSplit.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/MLBDistSplit.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.split;
+package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.split;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,37 +23,39 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.split;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
-import de.lmu.ifi.dbs.elki.index.tree.DistanceEntry;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
/**
* Encapsulates the required methods for a split of a node in an M-Tree. The
* routing objects are chosen according to the M_LB_DIST strategy.
*
+ * Reference:
+ * <p>
+ * P. Ciaccia, M. Patella, P. Zezula<br />
+ * M-tree: An Efficient Access Method for Similarity Search in Metric Spaces<br />
+ * In Proceedings of 23rd International Conference on Very Large Data Bases
+ * (VLDB'97), August 25-29, 1997, Athens, Greece
+ * </p>
+ *
* @author Elke Achtert
+ *
* @param <O> the type of DatabaseObject to be stored in the M-Tree
* @param <D> the type of Distance used in the M-Tree
* @param <N> the type of AbstractMTreeNode used in the M-Tree
* @param <E> the type of MetricalEntry used in the M-Tree
*/
-public class MLBDistSplit<O, D extends Distance<D>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry<D>> extends MTreeSplit<O, D, N, E> {
+@Reference(authors = "P. Ciaccia, M. Patella, P. Zezula", title = "M-tree: An Efficient Access Method for Similarity Search in Metric Spaces", booktitle = "VLDB'97, Proceedings of 23rd International Conference on Very Large Data Bases, August 25-29, 1997, Athens, Greece", url = "http://www.vldb.org/conf/1997/P426.PDF")
+public class MLBDistSplit<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry> extends MTreeSplit<O, D, N, E> {
/**
* Creates a new split object.
- *
- * @param node the node to be split
- * @param distanceFunction the distance function
*/
- public MLBDistSplit(N node, DistanceQuery<O, D> distanceFunction) {
+ public MLBDistSplit() {
super();
- promote(node, distanceFunction);
}
/**
@@ -64,22 +66,23 @@ public class MLBDistSplit<O, D extends Distance<D>, N extends AbstractMTreeNode<
* This strategy considers all possible pairs of objects and chooses the pair
* of objects for which the distance is maximum.
*
+ * @param tree Tree to use
* @param node the node to be split
- * @param distanceFunction the distance function
*/
- private void promote(N node, DistanceQuery<O, D> distanceFunction) {
+ @Override
+ public Assignments<E> split(AbstractMTree<O, D, N, E, ?> tree, N node) {
DBID firstPromoted = null;
DBID secondPromoted = null;
// choose first and second routing object
- D currentMaxDist = distanceFunction.nullDistance();
- for(int i = 0; i < node.getNumEntries(); i++) {
+ double currentMaxDist = 0.;
+ for (int i = 0; i < node.getNumEntries(); i++) {
DBID id1 = node.getEntry(i).getRoutingObjectID();
- for(int j = i + 1; j < node.getNumEntries(); j++) {
+ for (int j = i + 1; j < node.getNumEntries(); j++) {
DBID id2 = node.getEntry(j).getRoutingObjectID();
- D distance = distanceFunction.distance(id1, id2);
- if(distance.compareTo(currentMaxDist) >= 0) {
+ double distance = tree.distance(id1, id2).doubleValue();
+ if (distance >= currentMaxDist) {
firstPromoted = id1;
secondPromoted = id2;
currentMaxDist = distance;
@@ -87,20 +90,6 @@ public class MLBDistSplit<O, D extends Distance<D>, N extends AbstractMTreeNode<
}
}
- // partition the entries
- List<DistanceEntry<D, E>> list1 = new ArrayList<DistanceEntry<D, E>>();
- List<DistanceEntry<D, E>> list2 = new ArrayList<DistanceEntry<D, E>>();
- for(int i = 0; i < node.getNumEntries(); i++) {
- DBID id = node.getEntry(i).getRoutingObjectID();
- D d1 = distanceFunction.distance(firstPromoted, id);
- D d2 = distanceFunction.distance(secondPromoted, id);
-
- list1.add(new DistanceEntry<D, E>(node.getEntry(i), d1, i));
- list2.add(new DistanceEntry<D, E>(node.getEntry(i), d2, i));
- }
- Collections.sort(list1);
- Collections.sort(list2);
-
- assignments = balancedPartition(node, firstPromoted, secondPromoted, distanceFunction);
+ return balancedPartition(tree, node, firstPromoted, secondPromoted);
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/MMRadSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/MMRadSplit.java
new file mode 100644
index 00000000..232df088
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/MMRadSplit.java
@@ -0,0 +1,88 @@
+package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.split;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+
+/**
+ * Encapsulates the required methods for a split of a node in an M-Tree. The
+ * routing objects are chosen according to the mM_rad strategy.
+ *
+ * Reference:
+ * <p>
+ * P. Ciaccia, M. Patella, P. Zezula<br />
+ * M-tree: An Efficient Access Method for Similarity Search in Metric Spaces<br />
+ * In Proceedings of 23rd International Conference on Very Large Data Bases
+ * (VLDB'97), August 25-29, 1997, Athens, Greece
+ * </p>
+ *
+ * @author Elke Achtert
+ *
+ * @param <O> the type of DatabaseObject to be stored in the M-Tree
+ * @param <D> the type of Distance used in the M-Tree
+ * @param <N> the type of AbstractMTreeNode used in the M-Tree
+ * @param <E> the type of MetricalEntry used in the M-Tree
+ */
+@Reference(authors = "P. Ciaccia, M. Patella, P. Zezula", title = "M-tree: An Efficient Access Method for Similarity Search in Metric Spaces", booktitle = "VLDB'97, Proceedings of 23rd International Conference on Very Large Data Bases, August 25-29, 1997, Athens, Greece", url = "http://www.vldb.org/conf/1997/P426.PDF")
+public class MMRadSplit<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry> extends MTreeSplit<O, D, N, E> {
+ /**
+ * Creates a new split object.
+ */
+ public MMRadSplit() {
+ super();
+ }
+
+ /**
+ * Selects two objects of the specified node to be promoted and stored into
+ * the parent node. The mM-RAD strategy considers all possible pairs of
+ * objects and, after partitioning the set of entries, promotes the pair of
+ * objects for which the larger of the two covering radiuses is minimum.
+ *
+ * @param tree Tree to use
+ * @param node the node to be split
+ */
+ @Override
+ public Assignments<E> split(AbstractMTree<O, D, N, E, ?> tree, N node) {
+ double miSumCR = Double.POSITIVE_INFINITY;
+ double[] distanceMatrix = computeDistanceMatrix(tree, node);
+
+ Assignments<E> bestAssignment = null;
+ for (int i = 0; i < node.getNumEntries(); i++) {
+ for (int j = i + 1; j < node.getNumEntries(); j++) {
+ Assignments<E> currentAssignments = balancedPartition(tree, node, i, j, distanceMatrix);
+
+ double maxCR = Math.max(currentAssignments.getFirstCoveringRadius(), currentAssignments.getSecondCoveringRadius());
+ if (maxCR < miSumCR) {
+ miSumCR = maxCR;
+ bestAssignment = currentAssignments;
+ }
+ }
+ }
+ return bestAssignment;
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/MRadSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/MRadSplit.java
index 5d6c985c..5de15356 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/MRadSplit.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/MRadSplit.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.split;
+package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.split;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,32 +23,38 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.split;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
/**
* Encapsulates the required methods for a split of a node in an M-Tree. The
* routing objects are chosen according to the M_rad strategy.
*
+ * Reference:
+ * <p>
+ * P. Ciaccia, M. Patella, P. Zezula<br />
+ * M-tree: An Efficient Access Method for Similarity Search in Metric Spaces<br />
+ * In Proceedings of 23rd International Conference on Very Large Data Bases
+ * (VLDB'97), August 25-29, 1997, Athens, Greece
+ * </p>
+ *
* @author Elke Achtert
+ *
* @param <O> the type of DatabaseObject to be stored in the M-Tree
* @param <D> the type of Distance used in the M-Tree
* @param <N> the type of AbstractMTreeNode used in the M-Tree
* @param <E> the type of MetricalEntry used in the M-Tree
*/
-public class MRadSplit<O, D extends Distance<D>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry<D>> extends MTreeSplit<O, D, N, E> {
+@Reference(authors = "P. Ciaccia, M. Patella, P. Zezula", title = "M-tree: An Efficient Access Method for Similarity Search in Metric Spaces", booktitle = "VLDB'97, Proceedings of 23rd International Conference on Very Large Data Bases, August 25-29, 1997, Athens, Greece", url = "http://www.vldb.org/conf/1997/P426.PDF")
+public class MRadSplit<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry> extends MTreeSplit<O, D, N, E> {
/**
* Creates a new split object.
- *
- * @param node the node to be split
- * @param distanceFunction the distance function
*/
- public MRadSplit(N node, DistanceQuery<O, D> distanceFunction) {
+ public MRadSplit() {
super();
- promote(node, distanceFunction);
}
/**
@@ -57,26 +63,26 @@ public class MRadSplit<O, D extends Distance<D>, N extends AbstractMTreeNode<O,
* and, after partitioning the set of entries, promotes the pair of objects
* for which the sum of covering radiuses is minimum.
*
+ * @param tree Tree to use
* @param node the node to be split
- * @param distanceFunction the distance function
*/
- private void promote(N node, DistanceQuery<O, D> distanceFunction) {
- D miSumCR = distanceFunction.infiniteDistance();
-
- for(int i = 0; i < node.getNumEntries(); i++) {
- DBID id1 = node.getEntry(i).getRoutingObjectID();
+ @Override
+ public Assignments<E> split(AbstractMTree<O, D, N, E, ?> tree, N node) {
+ double miSumCR = Double.POSITIVE_INFINITY;
+ double[] distanceMatrix = computeDistanceMatrix(tree, node);
- for(int j = i + 1; j < node.getNumEntries(); j++) {
- DBID id2 = node.getEntry(i).getRoutingObjectID();
- // ... for each pair do testPartition...
- Assignments<D, E> currentAssignments = balancedPartition(node, id1, id2, distanceFunction);
+ Assignments<E> bestAssignment = null;
+ for (int i = 0; i < node.getNumEntries(); i++) {
+ for (int j = i + 1; j < node.getNumEntries(); j++) {
+ Assignments<E> currentAssignments = balancedPartition(tree, node, i, j, distanceMatrix);
- D sumCR = currentAssignments.getFirstCoveringRadius().plus(currentAssignments.getSecondCoveringRadius());
- if(sumCR.compareTo(miSumCR) < 0) {
+ double sumCR = currentAssignments.getFirstCoveringRadius() + currentAssignments.getSecondCoveringRadius();
+ if (sumCR < miSumCR) {
miSumCR = sumCR;
- assignments = currentAssignments;
+ bestAssignment = currentAssignments;
}
}
}
+ return bestAssignment;
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/MTreeSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/MTreeSplit.java
new file mode 100644
index 00000000..167b5368
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/MTreeSplit.java
@@ -0,0 +1,223 @@
+package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.split;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.Collections;
+import java.util.List;
+
+import de.lmu.ifi.dbs.elki.database.ids.DBID;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry;
+
+/**
+ * Abstract super class for splitting a node in an M-Tree.
+ *
+ * @author Elke Achtert
+ *
+ * @apiviz.composedOf Assignments
+ *
+ * @param <O> the type of DatabaseObject to be stored in the M-Tree
+ * @param <D> the type of Distance used in the M-Tree
+ * @param <N> the type of AbstractMTreeNode used in the M-Tree
+ * @param <E> the type of MetricalEntry used in the M-Tree
+ */
+public abstract class MTreeSplit<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry> {
+ /**
+ * Compute the pairwise distances in the given node.
+ *
+ * @param tree Tree
+ * @param node Node
+ * @return Distance matrix
+ */
+ protected double[] computeDistanceMatrix(AbstractMTree<O, D, N, E, ?> tree, N node) {
+ final int n = node.getNumEntries();
+ double[] distancematrix = new double[n * n];
+ // Build distance matrix
+ for (int i = 0; i < n; i++) {
+ E ei = node.getEntry(i);
+ for (int j = 0; j < n; j++) {
+ if (i == j) {
+ distancematrix[i * n + j] = 0.0;
+ } else if (i < j) {
+ distancematrix[i * n + j] = tree.distance(ei, node.getEntry(j)).doubleValue();
+ } else { // i > j
+ distancematrix[i * n + j] = distancematrix[j * n + i];
+ }
+ }
+ }
+ return distancematrix;
+ }
+
+ /**
+ * Creates a balanced partition of the entries of the specified node.
+ *
+ * @param tree the tree to perform the split in
+ * @param node the node to be split
+ * @param routingObject1 the id of the first routing object
+ * @param routingObject2 the id of the second routing object
+ * @return an assignment that holds a balanced partition of the entries of the
+ * specified node
+ */
+ Assignments<E> balancedPartition(AbstractMTree<O, D, N, E, ?> tree, N node, DBID routingObject1, DBID routingObject2) {
+ BitSet assigned = new BitSet(node.getNumEntries());
+ List<DistanceEntry<E>> assigned1 = new ArrayList<>(node.getCapacity());
+ List<DistanceEntry<E>> assigned2 = new ArrayList<>(node.getCapacity());
+
+ double currentCR1 = 0.;
+ double currentCR2 = 0.;
+
+ List<DistanceEntry<E>> list1 = new ArrayList<>();
+ List<DistanceEntry<E>> list2 = new ArrayList<>();
+
+ // determine the nearest neighbors
+ for (int i = 0; i < node.getNumEntries(); i++) {
+ final E ent = node.getEntry(i);
+ DBID id = ent.getRoutingObjectID();
+ if (DBIDUtil.equal(id, routingObject1)) {
+ assigned1.add(new DistanceEntry<>(ent, 0., i));
+ continue;
+ }
+ if (DBIDUtil.equal(id, routingObject2)) {
+ assigned2.add(new DistanceEntry<>(ent, 0., i));
+ continue;
+ }
+ // determine the distance of o to o1 / o2
+ double d1 = tree.distance(routingObject1, id).doubleValue();
+ double d2 = tree.distance(routingObject2, id).doubleValue();
+
+ list1.add(new DistanceEntry<>(ent, d1, i));
+ list2.add(new DistanceEntry<>(ent, d2, i));
+ }
+ Collections.sort(list1, Collections.reverseOrder());
+ Collections.sort(list2, Collections.reverseOrder());
+
+ for (int i = 2; i < node.getNumEntries(); i++) {
+ currentCR1 = assignNN(assigned, assigned1, list1, currentCR1, node.isLeaf());
+ i++;
+ if (i < node.getNumEntries()) {
+ currentCR2 = assignNN(assigned, assigned2, list2, currentCR2, node.isLeaf());
+ }
+ }
+ return new Assignments<>(routingObject1, routingObject2, currentCR1, currentCR2, assigned1, assigned2);
+ }
+
+ /**
+ * Creates a balanced partition of the entries of the specified node.
+ *
+ * @param tree the tree to perform the split in
+ * @param node the node to be split
+ * @param routingEntNum1 the entry number of the first routing object
+ * @param routingEntNum2 the entry number of the second routing object
+ * @param distanceMatrix precomputed distance matrix to use
+ * @return an assignment that holds a balanced partition of the entries of the
+ * specified node
+ */
+ Assignments<E> balancedPartition(AbstractMTree<O, D, N, E, ?> tree, N node, int routingEntNum1, int routingEntNum2, double[] distanceMatrix) {
+ final int n = node.getNumEntries();
+ BitSet assigned = new BitSet(node.getNumEntries());
+ List<DistanceEntry<E>> assigned1 = new ArrayList<>(node.getCapacity());
+ List<DistanceEntry<E>> assigned2 = new ArrayList<>(node.getCapacity());
+
+ double currentCR1 = 0.;
+ double currentCR2 = 0.;
+
+ List<DistanceEntry<E>> list1 = new ArrayList<>();
+ List<DistanceEntry<E>> list2 = new ArrayList<>();
+
+ DBID routingObject1 = null, routingObject2 = null;
+ // determine the nearest neighbors
+ for (int i = 0; i < node.getNumEntries(); i++) {
+ final E ent = node.getEntry(i);
+ if (i == routingEntNum1) {
+ routingObject1 = ent.getRoutingObjectID();
+ assigned1.add(new DistanceEntry<>(ent, 0., i));
+ continue;
+ }
+ if (i == routingEntNum2) {
+ routingObject2 = ent.getRoutingObjectID();
+ assigned2.add(new DistanceEntry<>(ent, 0., i));
+ continue;
+ }
+ // Look up the distances of o to o1 / o2
+ double d1 = distanceMatrix[i * n + routingEntNum1];
+ double d2 = distanceMatrix[i * n + routingEntNum2];
+
+ list1.add(new DistanceEntry<>(ent, d1, i));
+ list2.add(new DistanceEntry<>(ent, d2, i));
+ }
+ Collections.sort(list1, Collections.reverseOrder());
+ Collections.sort(list2, Collections.reverseOrder());
+
+ for (int i = 2; i < node.getNumEntries(); i++) {
+ currentCR1 = assignNN(assigned, assigned1, list1, currentCR1, node.isLeaf());
+ i++;
+ if (i < node.getNumEntries()) {
+ currentCR2 = assignNN(assigned, assigned2, list2, currentCR2, node.isLeaf());
+ }
+ }
+ return new Assignments<>(routingObject1, routingObject2, currentCR1, currentCR2, assigned1, assigned2);
+ }
+
+ /**
+ * Assigns the first object of the specified list to the first assignment that
+ * it is not yet assigned to the second assignment.
+ *
+ * @param assigned List of already assigned objects
+ * @param assigned1 the first assignment
+ * @param list the list, the first object should be assigned
+ * @param currentCR the current covering radius
+ * @param isLeaf true, if the node of the entries to be assigned is a leaf,
+ * false otherwise
+ * @return the new covering radius
+ */
+ private double assignNN(BitSet assigned, List<DistanceEntry<E>> assigned1, List<DistanceEntry<E>> list, double currentCR, boolean isLeaf) {
+ // Remove last unassigned:
+ DistanceEntry<E> distEntry = list.remove(list.size() - 1);
+ while (assigned.get(distEntry.getIndex())) {
+ distEntry = list.remove(list.size() - 1);
+ }
+ assigned1.add(distEntry);
+ assigned.set(distEntry.getIndex());
+
+ if (isLeaf) {
+ return Math.max(currentCR, distEntry.getDistance());
+ } else {
+ return Math.max(currentCR, distEntry.getDistance() + (distEntry.getEntry()).getCoveringRadius());
+ }
+ }
+
+ /**
+ * Returns the assignments of this split.
+ *
+ * @param tree Tree to use
+ * @param node Node to split
+ * @return the assignments of this split
+ */
+ abstract public Assignments<E> split(AbstractMTree<O, D, N, E, ?> tree, N node);
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/RandomSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/RandomSplit.java
new file mode 100644
index 00000000..faf2acc2
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/RandomSplit.java
@@ -0,0 +1,136 @@
+package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.split;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.Random;
+
+import de.lmu.ifi.dbs.elki.database.ids.DBID;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode;
+import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry;
+import de.lmu.ifi.dbs.elki.utilities.RandomFactory;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.RandomParameter;
+
+/**
+ * Encapsulates the required methods for a split of a node in an M-Tree. The
+ * routing objects are chosen according to the RANDOM strategy.
+ *
+ * Note: only the routing objects are chosen at random, this is not a random
+ * assignment!
+ *
+ * Reference:
+ * <p>
+ * P. Ciaccia, M. Patella, P. Zezula<br />
+ * M-tree: An Efficient Access Method for Similarity Search in Metric Spaces<br />
+ * In Proceedings of 23rd International Conference on Very Large Data Bases
+ * (VLDB'97), August 25-29, 1997, Athens, Greece
+ * </p>
+ *
+ * @author Elke Achtert
+ *
+ * @param <O> the type of DatabaseObject to be stored in the M-Tree
+ * @param <D> the type of Distance used in the M-Tree
+ * @param <N> the type of AbstractMTreeNode used in the M-Tree
+ * @param <E> the type of MetricalEntry used in the M-Tree
+ */
+@Reference(authors = "P. Ciaccia, M. Patella, P. Zezula", title = "M-tree: An Efficient Access Method for Similarity Search in Metric Spaces", booktitle = "VLDB'97, Proceedings of 23rd International Conference on Very Large Data Bases, August 25-29, 1997, Athens, Greece", url = "http://www.vldb.org/conf/1997/P426.PDF")
+public class RandomSplit<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry> extends MTreeSplit<O, D, N, E> {
+ /**
+ * Random generator.
+ */
+ private Random random;
+
+ /**
+ * Creates a new split object.
+ */
+ public RandomSplit(RandomFactory rnd) {
+ super();
+ this.random = rnd.getRandom();
+ }
+
+ /**
+ * Selects two objects of the specified node to be promoted and stored into
+ * the parent node. The m-RAD strategy considers all possible pairs of objects
+ * and, after partitioning the set of entries, promotes the pair of objects
+ * for which the sum of covering radiuses is minimum.
+ *
+ * @param tree Tree to use
+ * @param node the node to be split
+ */
+ @Override
+ public Assignments<E> split(AbstractMTree<O, D, N, E, ?> tree, N node) {
+ int pos1 = random.nextInt(node.getNumEntries());
+ int pos2 = random.nextInt(node.getNumEntries() - 1);
+ if (pos2 >= pos1) {
+ ++pos2;
+ }
+ DBID id1 = node.getEntry(pos1).getRoutingObjectID();
+ DBID id2 = node.getEntry(pos2).getRoutingObjectID();
+
+ return balancedPartition(tree, node, id1, id2);
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ *
+ * @param <O> the type of DatabaseObject to be stored in the M-Tree
+ * @param <D> the type of Distance used in the M-Tree
+ * @param <N> the type of AbstractMTreeNode used in the M-Tree
+ * @param <E> the type of MetricalEntry used in the M-Tree
+ */
+ public static class Parameterizer<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry> extends AbstractParameterizer {
+ /**
+ * Option ID for the random generator.
+ */
+ public static final OptionID RANDOM_ID = new OptionID("mtree.randomsplit.random", "Random generator / seed for the randomized split.");
+
+ /**
+ * Random generator
+ */
+ RandomFactory rnd = RandomFactory.DEFAULT;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ RandomParameter rndP = new RandomParameter(RANDOM_ID);
+ if (config.grab(rndP)) {
+ rnd = rndP.getValue();
+ }
+ }
+
+ @Override
+ protected RandomSplit<O, D, N, E> makeInstance() {
+ return new RandomSplit<>(rnd);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/package-info.java
new file mode 100644
index 00000000..ed0fd729
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/package-info.java
@@ -0,0 +1,26 @@
+/**
+ * <p>Splitting strategies of nodes in an M-Tree (and variants).</p>
+ */
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.split; \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/package-info.java
index 2ca4396c..b1a76d8b 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/package-info.java
index 3ba785f2..6c34473f 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/query/DoubleDistanceSearchCandidate.java b/src/de/lmu/ifi/dbs/elki/index/tree/query/DoubleDistanceSearchCandidate.java
index 1a3fc948..fd9ee2f9 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/query/DoubleDistanceSearchCandidate.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/query/DoubleDistanceSearchCandidate.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.query;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -38,7 +38,7 @@ public class DoubleDistanceSearchCandidate implements Comparable<DoubleDistanceS
/**
* Page id
*/
- public Integer nodeID;
+ public int nodeID;
/**
* Constructor.
@@ -46,7 +46,7 @@ public class DoubleDistanceSearchCandidate implements Comparable<DoubleDistanceS
* @param mindist The minimum distance to this candidate
* @param pagenr The page number of this candidate
*/
- public DoubleDistanceSearchCandidate(final double mindist, final Integer pagenr) {
+ public DoubleDistanceSearchCandidate(final double mindist, final int pagenr) {
super();
this.mindist = mindist;
this.nodeID = pagenr;
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/query/DoubleMTreeDistanceSearchCandidate.java b/src/de/lmu/ifi/dbs/elki/index/tree/query/DoubleMTreeDistanceSearchCandidate.java
index c26ac801..3be9ff09 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/query/DoubleMTreeDistanceSearchCandidate.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/query/DoubleMTreeDistanceSearchCandidate.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.query;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -54,7 +54,7 @@ public class DoubleMTreeDistanceSearchCandidate extends DoubleDistanceSearchCand
* @param routingDistance the distance from the query object to the query
* object
*/
- public DoubleMTreeDistanceSearchCandidate(final double mindist, final Integer nodeID, final DBID routingObjectID, double routingDistance) {
+ public DoubleMTreeDistanceSearchCandidate(final double mindist, final int nodeID, final DBID routingObjectID, double routingDistance) {
super(mindist, nodeID);
this.routingObjectID = routingObjectID;
this.routingDistance = routingDistance;
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/query/GenericDistanceSearchCandidate.java b/src/de/lmu/ifi/dbs/elki/index/tree/query/GenericDistanceSearchCandidate.java
index dd764990..278dec60 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/query/GenericDistanceSearchCandidate.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/query/GenericDistanceSearchCandidate.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.query;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -41,7 +41,7 @@ public class GenericDistanceSearchCandidate<D extends Distance<D>> implements Co
/**
* Page id
*/
- public Integer nodeID;
+ public int nodeID;
/**
* Constructor.
@@ -49,7 +49,7 @@ public class GenericDistanceSearchCandidate<D extends Distance<D>> implements Co
* @param mindist The minimum distance to this candidate
* @param pagenr The page number of this candidate
*/
- public GenericDistanceSearchCandidate(final D mindist, final Integer pagenr) {
+ public GenericDistanceSearchCandidate(final D mindist, final int pagenr) {
super();
this.mindist = mindist;
this.nodeID = pagenr;
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/query/GenericMTreeDistanceSearchCandidate.java b/src/de/lmu/ifi/dbs/elki/index/tree/query/GenericMTreeDistanceSearchCandidate.java
index 94335860..cbe0451e 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/query/GenericMTreeDistanceSearchCandidate.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/query/GenericMTreeDistanceSearchCandidate.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.query;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,7 +24,6 @@ package de.lmu.ifi.dbs.elki.index.tree.query;
*/
import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
/**
* Encapsulates the attributes for a object that can be stored in a heap. The
@@ -33,20 +32,25 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
* holds the id of the routing object of the underlying M-Tree node and its
* covering radius.
*
- * @author Elke Achtert
+ * FIXME: Class naming in this package is inconsistent.
*
- * @param <D> the type of Distance used in the M-Tree
+ * @author Elke Achtert
*/
-public class GenericMTreeDistanceSearchCandidate<D extends Distance<D>> extends GenericDistanceSearchCandidate<D> {
+public class GenericMTreeDistanceSearchCandidate implements Comparable<GenericMTreeDistanceSearchCandidate> {
/**
* The id of the routing object.
*/
public DBID routingObjectID;
-
+
+ /**
+ * Minimum distance.
+ */
+ public double mindist;
+
/**
- * The distance from the query to the routing object.
+ * Node ID.
*/
- public D routingDistance;
+ public int nodeID;
/**
* Creates a new heap node with the specified parameters.
@@ -54,11 +58,35 @@ public class GenericMTreeDistanceSearchCandidate<D extends Distance<D>> extends
* @param mindist the minimum distance of the node
* @param nodeID the id of the node
* @param routingObjectID the id of the routing object of the node
- * @param routingDistance the distance from query to routing object
*/
- public GenericMTreeDistanceSearchCandidate(final D mindist, final Integer nodeID, final DBID routingObjectID, final D routingDistance) {
- super(mindist, nodeID);
+ public GenericMTreeDistanceSearchCandidate(final double mindist, final int nodeID, final DBID routingObjectID) {
+ this.mindist = mindist;
+ this.nodeID = nodeID;
this.routingObjectID = routingObjectID;
- this.routingDistance = routingDistance;
}
-} \ No newline at end of file
+
+ @Override
+ public int hashCode() {
+ return nodeID;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ GenericMTreeDistanceSearchCandidate other = (GenericMTreeDistanceSearchCandidate) obj;
+ return nodeID == other.nodeID;
+ }
+
+ @Override
+ public int compareTo(GenericMTreeDistanceSearchCandidate o) {
+ return Double.compare(this.mindist, o.mindist);
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/query/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/query/package-info.java
index 5b8f56f6..29976738 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/query/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/query/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialDirectoryEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialDirectoryEntry.java
index 9833e5b5..4a131cbf 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialDirectoryEntry.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialDirectoryEntry.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialEntry.java
index c50a5ebf..4fe55adf 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialEntry.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialEntry.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialIndexTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialIndexTree.java
index 3b9eaa6b..b4bd5208 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialIndexTree.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialIndexTree.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialNode.java
index 8bf25766..449992a2 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialNode.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialNode.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialPair.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialPair.java
index f29680e7..f69b1dd1 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialPair.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialPair.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialPointLeafEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialPointLeafEntry.java
index 60981677..d79893b0 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialPointLeafEntry.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialPointLeafEntry.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -30,6 +30,7 @@ import java.io.ObjectOutput;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.index.tree.AbstractLeafEntry;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
/**
* Represents an entry in a leaf node of a spatial index. A SpatialLeafEntry
@@ -38,7 +39,7 @@ import de.lmu.ifi.dbs.elki.index.tree.AbstractLeafEntry;
*
* @author Elke Achtert
*/
-public class SpatialPointLeafEntry extends AbstractLeafEntry implements SpatialEntry {
+public class SpatialPointLeafEntry extends AbstractLeafEntry implements SpatialEntry, NumberVector<Double> {
/**
* Serial version.
*/
@@ -69,7 +70,7 @@ public class SpatialPointLeafEntry extends AbstractLeafEntry implements SpatialE
/**
* Constructor from number vector.
- *
+ *
* @param id Object id
* @param vector Number vector
*/
@@ -77,7 +78,7 @@ public class SpatialPointLeafEntry extends AbstractLeafEntry implements SpatialE
super(id);
int dim = vector.getDimensionality();
this.values = new double[dim];
- for(int i = 0; i < dim; i++) {
+ for (int i = 0; i < dim; i++) {
values[i] = vector.doubleValue(i);
}
}
@@ -117,7 +118,7 @@ public class SpatialPointLeafEntry extends AbstractLeafEntry implements SpatialE
public void writeExternal(ObjectOutput out) throws IOException {
super.writeExternal(out);
out.writeInt(values.length);
- for(double v : values) {
+ for (double v : values) {
out.writeDouble(v);
}
}
@@ -135,8 +136,49 @@ public class SpatialPointLeafEntry extends AbstractLeafEntry implements SpatialE
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in);
values = new double[in.readInt()];
- for(int d = 0; d < values.length; d++) {
+ for (int d = 0; d < values.length; d++) {
values[d] = in.readDouble();
}
}
-} \ No newline at end of file
+
+ @Override
+ @Deprecated
+ public Double getValue(int dimension) {
+ return values[dimension];
+ }
+
+ @Override
+ public double doubleValue(int dimension) {
+ return values[dimension];
+ }
+
+ @Override
+ public float floatValue(int dimension) {
+ return (float) values[dimension];
+ }
+
+ @Override
+ public int intValue(int dimension) {
+ return (int) values[dimension];
+ }
+
+ @Override
+ public long longValue(int dimension) {
+ return (long) values[dimension];
+ }
+
+ @Override
+ public short shortValue(int dimension) {
+ return (short) values[dimension];
+ }
+
+ @Override
+ public byte byteValue(int dimension) {
+ return (byte) values[dimension];
+ }
+
+ @Override
+ public Vector getColumnVector() {
+ return new Vector(values.clone());
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/kd/MinimalisticMemoryKDTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/kd/MinimalisticMemoryKDTree.java
new file mode 100644
index 00000000..28f19a25
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/kd/MinimalisticMemoryKDTree.java
@@ -0,0 +1,443 @@
+package de.lmu.ifi.dbs.elki.index.tree.spatial.kd;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.VectorUtil;
+import de.lmu.ifi.dbs.elki.data.VectorUtil.SortDBIDsBySingleDimension;
+import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
+import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDArrayIter;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPairList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNHeap;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.ModifiableDoubleDistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
+import de.lmu.ifi.dbs.elki.database.query.knn.AbstractDistanceKNNQuery;
+import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
+import de.lmu.ifi.dbs.elki.database.query.range.AbstractDistanceRangeQuery;
+import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.database.relation.RelationUtil;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.DoubleNorm;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.LPNormDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SparseLPNormDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SquaredEuclideanDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+import de.lmu.ifi.dbs.elki.index.AbstractIndex;
+import de.lmu.ifi.dbs.elki.index.IndexFactory;
+import de.lmu.ifi.dbs.elki.index.KNNIndex;
+import de.lmu.ifi.dbs.elki.index.RangeIndex;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.statistics.Counter;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.QuickSelect;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+
+/**
+ * Simple implementation of a static in-memory K-D-tree. Does not support
+ * dynamic updates or anything, but also is very simple and memory efficient:
+ * all it uses is one {@link ArrayModifiableDBIDs} to sort the data in a
+ * serialized tree.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has KDTreeKNNQuery
+ * @apiviz.has KDTreeRangeQuery
+ *
+ * @param <O> Vector type
+ */
+@Reference(authors = "J. L. Bentley", title = "Multidimensional binary search trees used for associative searching", booktitle = "Communications of the ACM, Vol. 18 Issue 9, Sept. 1975", url = "http://dx.doi.org/10.1145/361002.361007")
+public class MinimalisticMemoryKDTree<O extends NumberVector<?>> extends AbstractIndex<O> implements KNNIndex<O>, RangeIndex<O> {
+ /**
+ * Class logger
+ */
+ private static final Logging LOG = Logging.getLogger(MinimalisticMemoryKDTree.class);
+
+ /**
+ * The actual "tree" as a sorted array.
+ */
+ ArrayModifiableDBIDs sorted = null;
+
+ /**
+ * The number of dimensions.
+ */
+ int dims = -1;
+
+ /**
+ * Counter for comparisons.
+ */
+ final Counter objaccess;
+
+ /**
+ * Counter for distance computations.
+ */
+ final Counter distcalc;
+
+ /**
+ * Constructor.
+ *
+ * @param relation Relation to index
+ */
+ public MinimalisticMemoryKDTree(Relation<O> relation) {
+ super(relation);
+ if(LOG.isStatistics()) {
+ String prefix = this.getClass().getName();
+ this.objaccess = LOG.newCounter(prefix + ".objaccess");
+ this.distcalc = LOG.newCounter(prefix + ".distancecalcs");
+ }
+ else {
+ this.objaccess = null;
+ this.distcalc = null;
+ }
+ }
+
+ @Override
+ public void initialize() {
+ sorted = DBIDUtil.newArray(relation.getDBIDs());
+ dims = RelationUtil.dimensionality(relation);
+ SortDBIDsBySingleDimension comp = new VectorUtil.SortDBIDsBySingleDimension(relation);
+ buildTree(0, sorted.size(), 0, comp);
+ }
+
+ /**
+ * Recursively build the tree by partial sorting. O(n log n) complexity.
+ * Apparently there exists a variant in only O(n log log n)? Please
+ * contribute!
+ *
+ * @param left Interval minimum
+ * @param right Interval maximum
+ * @param axis Current splitting axis
+ * @param comp Comparator
+ */
+ private void buildTree(int left, int right, int axis, SortDBIDsBySingleDimension comp) {
+ final int middle = (left + right) >>> 1;
+ comp.setDimension(axis);
+
+ QuickSelect.quickSelect(sorted, comp, left, right, middle);
+ final int next = (axis + 1) % dims;
+ if(left < middle) {
+ buildTree(left, middle, next, comp);
+ }
+ if(middle + 1 < right) {
+ buildTree(middle + 1, right, next, comp);
+ }
+ }
+
+ @Override
+ public String getLongName() {
+ return "kd-tree";
+ }
+
+ @Override
+ public String getShortName() {
+ return "kd-tree";
+ }
+
+ @Override
+ public void logStatistics() {
+ if(objaccess != null) {
+ LOG.statistics(objaccess);
+ }
+ if(distcalc != null) {
+ LOG.statistics(distcalc);
+ }
+ }
+
+ /**
+ * Count a single object access.
+ */
+ protected void countObjectAccess() {
+ if(objaccess != null) {
+ objaccess.increment();
+ }
+ }
+
+ /**
+ * Count a distance computation.
+ */
+ protected void countDistanceComputation() {
+ if(distcalc != null) {
+ distcalc.increment();
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <D extends Distance<D>> KNNQuery<O, D> getKNNQuery(DistanceQuery<O, D> distanceQuery, Object... hints) {
+ DistanceFunction<? super O, D> df = distanceQuery.getDistanceFunction();
+ // TODO: if we know this works for other distance functions, add them, too!
+ if(df instanceof LPNormDistanceFunction) {
+ return (KNNQuery<O, D>) new KDTreeKNNQuery((DistanceQuery<O, DoubleDistance>) distanceQuery, (DoubleNorm<? super O>) df);
+ }
+ if(df instanceof SquaredEuclideanDistanceFunction) {
+ return (KNNQuery<O, D>) new KDTreeKNNQuery((DistanceQuery<O, DoubleDistance>) distanceQuery, (DoubleNorm<? super O>) df);
+ }
+ if(df instanceof SparseLPNormDistanceFunction) {
+ return (KNNQuery<O, D>) new KDTreeKNNQuery((DistanceQuery<O, DoubleDistance>) distanceQuery, (DoubleNorm<? super O>) df);
+ }
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <D extends Distance<D>> RangeQuery<O, D> getRangeQuery(DistanceQuery<O, D> distanceQuery, Object... hints) {
+ DistanceFunction<? super O, D> df = distanceQuery.getDistanceFunction();
+ // TODO: if we know this works for other distance functions, add them, too!
+ if(df instanceof LPNormDistanceFunction) {
+ return (RangeQuery<O, D>) new KDTreeRangeQuery((DistanceQuery<O, DoubleDistance>) distanceQuery, (DoubleNorm<? super O>) df);
+ }
+ if(df instanceof SquaredEuclideanDistanceFunction) {
+ return (RangeQuery<O, D>) new KDTreeRangeQuery((DistanceQuery<O, DoubleDistance>) distanceQuery, (DoubleNorm<? super O>) df);
+ }
+ if(df instanceof SparseLPNormDistanceFunction) {
+ return (RangeQuery<O, D>) new KDTreeRangeQuery((DistanceQuery<O, DoubleDistance>) distanceQuery, (DoubleNorm<? super O>) df);
+ }
+ return null;
+ }
+
+ /**
+ * kNN query for the k-d-tree.
+ *
+ * @author Erich Schubert
+ */
+ public class KDTreeKNNQuery extends AbstractDistanceKNNQuery<O, DoubleDistance> {
+ /**
+ * Norm to use.
+ */
+ private DoubleNorm<? super O> norm;
+
+ /**
+ * Constructor.
+ *
+ * @param distanceQuery Distance query
+ * @param norm Norm to use
+ */
+ public KDTreeKNNQuery(DistanceQuery<O, DoubleDistance> distanceQuery, DoubleNorm<? super O> norm) {
+ super(distanceQuery);
+ this.norm = norm;
+ }
+
+ @Override
+ public KNNList<DoubleDistance> getKNNForObject(O obj, int k) {
+ final DoubleDistanceKNNHeap knns = (DoubleDistanceKNNHeap) DBIDUtil.newHeap(DoubleDistance.FACTORY, k);
+ kdKNNSearch(0, sorted.size(), 0, obj, knns, sorted.iter(), Double.POSITIVE_INFINITY);
+ return knns.toKNNList();
+ }
+
+ /**
+ * Perform a kNN search on the kd-tree.
+ *
+ * @param left Subtree begin
+ * @param right Subtree end (exclusive)
+ * @param axis Current splitting axis
+ * @param query Query object
+ * @param knns kNN heap
+ * @param iter Iterator variable (reduces memory footprint!)
+ * @param maxdist Current upper bound of kNN distance.
+ * @return New upper bound of kNN distance.
+ */
+ private double kdKNNSearch(int left, int right, int axis, O query, DoubleDistanceKNNHeap knns, DBIDArrayIter iter, double maxdist) {
+ // Look at current node:
+ final int middle = (left + right) >>> 1;
+ iter.seek(middle);
+ O split = relation.get(iter);
+ countObjectAccess();
+
+ // Distance to axis:
+ final double delta = split.doubleValue(axis) - query.doubleValue(axis);
+ final boolean onleft = (delta >= 0);
+ final boolean onright = (delta <= 0);
+
+ // Next axis:
+ final int next = (axis + 1) % dims;
+
+ // Exact match chance (delta == 0)!
+ // process first, then descend both sides.
+ if(onleft && onright) {
+ double dist = norm.doubleDistance(query, split);
+ countDistanceComputation();
+ if(dist <= maxdist) {
+ iter.seek(middle);
+ knns.add(dist, iter);
+ maxdist = knns.doubleKNNDistance();
+ }
+ if(left < middle) {
+ maxdist = kdKNNSearch(left, middle, next, query, knns, iter, maxdist);
+ }
+ if(middle + 1 < right) {
+ maxdist = kdKNNSearch(middle + 1, right, next, query, knns, iter, maxdist);
+ }
+ }
+ else {
+ if(onleft) {
+ if(left < middle) {
+ maxdist = kdKNNSearch(left, middle, next, query, knns, iter, maxdist);
+ }
+ // Look at splitting element (unless already above):
+ if(Math.abs(delta) <= maxdist) {
+ double dist = norm.doubleDistance(query, split);
+ countDistanceComputation();
+ if(dist <= maxdist) {
+ iter.seek(middle);
+ knns.add(dist, iter);
+ maxdist = knns.doubleKNNDistance();
+ }
+ }
+ if((middle + 1 < right) && (Math.abs(delta) <= maxdist)) {
+ maxdist = kdKNNSearch(middle + 1, right, next, query, knns, iter, maxdist);
+ }
+ }
+ else { // onright
+ if(middle + 1 < right) {
+ maxdist = kdKNNSearch(middle + 1, right, next, query, knns, iter, maxdist);
+ }
+ // Look at splitting element (unless already above):
+ if(Math.abs(delta) <= maxdist) {
+ double dist = norm.doubleDistance(query, split);
+ countDistanceComputation();
+ if(dist <= maxdist) {
+ iter.seek(middle);
+ knns.add(dist, iter);
+ maxdist = knns.doubleKNNDistance();
+ }
+ }
+ if((left < middle) && (Math.abs(delta) <= maxdist)) {
+ maxdist = kdKNNSearch(left, middle, next, query, knns, iter, maxdist);
+ }
+ }
+ }
+ return maxdist;
+ }
+ }
+
+ /**
+ * kNN query for the k-d-tree.
+ *
+ * @author Erich Schubert
+ */
+ public class KDTreeRangeQuery extends AbstractDistanceRangeQuery<O, DoubleDistance> {
+ /**
+ * Norm to use.
+ */
+ private DoubleNorm<? super O> norm;
+
+ /**
+ * Constructor.
+ *
+ * @param distanceQuery Distance query
+ * @param norm Norm to use
+ */
+ public KDTreeRangeQuery(DistanceQuery<O, DoubleDistance> distanceQuery, DoubleNorm<? super O> norm) {
+ super(distanceQuery);
+ this.norm = norm;
+ }
+
+ @Override
+ public DoubleDistanceDBIDPairList getRangeForObject(O obj, DoubleDistance range) {
+ final DoubleDistanceDBIDPairList res = new DoubleDistanceDBIDPairList();
+ kdRangeSearch(0, sorted.size(), 0, obj, res, sorted.iter(), range.doubleValue());
+ res.sort();
+ return res;
+ }
+
+ /**
+ * Perform a kNN search on the kd-tree.
+ *
+ * @param left Subtree begin
+ * @param right Subtree end (exclusive)
+ * @param axis Current splitting axis
+ * @param query Query object
+ * @param res kNN heap
+ * @param iter Iterator variable (reduces memory footprint!)
+ * @param radius Query radius
+ */
+ private void kdRangeSearch(int left, int right, int axis, O query, ModifiableDoubleDistanceDBIDList res, DBIDArrayIter iter, double radius) {
+ // Look at current node:
+ final int middle = (left + right) >>> 1;
+ iter.seek(middle);
+ O split = relation.get(iter);
+ countObjectAccess();
+
+ // Distance to axis:
+ final double delta = split.doubleValue(axis) - query.doubleValue(axis);
+ final boolean onleft = (delta >= 0);
+ final boolean onright = (delta <= 0);
+ final boolean close = (Math.abs(delta) <= radius);
+
+ // Next axis:
+ final int next = (axis + 1) % dims;
+
+ // Current object:
+ if(close) {
+ double dist = norm.doubleDistance(query, split);
+ countDistanceComputation();
+ if(dist <= radius) {
+ iter.seek(middle);
+ res.add(dist, iter);
+ }
+ }
+ if(left < middle && (onleft || close)) {
+ kdRangeSearch(left, middle, next, query, res, iter, radius);
+ }
+ if(middle + 1 < right && (onright || close)) {
+ kdRangeSearch(middle + 1, right, next, query, res, iter, radius);
+ }
+ }
+ }
+
+ /**
+ * Factory class
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.stereotype factory
+ * @apiviz.has MinimalisticMemoryKDTree
+ *
+ * @param <O> Vector type
+ */
+ @Alias({"minikd", "kd"})
+ public static class Factory<O extends NumberVector<?>> implements IndexFactory<O, MinimalisticMemoryKDTree<O>> {
+ /**
+ * Constructor. Trivial parameterizable.
+ */
+ public Factory() {
+ super();
+ }
+
+ @Override
+ public MinimalisticMemoryKDTree<O> instantiate(Relation<O> relation) {
+ return new MinimalisticMemoryKDTree<>(relation);
+ }
+
+ @Override
+ public TypeInformation getInputTypeRestriction() {
+ return TypeUtil.NUMBER_VECTOR_FIELD;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/application/visualization/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/kd/package-info.java
index 717a80f9..88a42c2d 100644
--- a/src/de/lmu/ifi/dbs/elki/application/visualization/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/kd/package-info.java
@@ -1,12 +1,11 @@
/**
- * <p>Visualization applications in ELKI.</p>
- *
+ * <p>K-d-tree and variants.</p>
*/
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,4 +23,4 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-package de.lmu.ifi.dbs.elki.application.visualization; \ No newline at end of file
+package de.lmu.ifi.dbs.elki.index.tree.spatial.kd; \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/package-info.java
index fb5c67ee..7fbdd2ac 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRStarTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRStarTree.java
index 8ede52d7..63c8e8fa 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRStarTree.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRStarTree.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -46,16 +46,11 @@ import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialDirectoryEntry;
import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry;
import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialIndexTree;
import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialPointLeafEntry;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk.BulkSplit;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert.InsertionStrategy;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert.LeastOverlapInsertionStrategy;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.overflow.LimitedReinsertOverflowTreatment;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.overflow.OverflowTreatment;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split.SplitStrategy;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split.TopologicalSplitter;
import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.NodeArrayAdapter;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.statistics.Counter;
+import de.lmu.ifi.dbs.elki.logging.statistics.LongStatistic;
import de.lmu.ifi.dbs.elki.persistent.PageFile;
-import de.lmu.ifi.dbs.elki.persistent.PageFileUtil;
import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
/**
@@ -68,15 +63,13 @@ import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
*
* @apiviz.landmark
* @apiviz.has AbstractRStarTreeNode oneway - - contains
- * @apiviz.composedOf BulkSplit
- * @apiviz.composedOf SplitStrategy
- * @apiviz.composedOf InsertionStrategy
- * @apiviz.composedOf OverflowTreatment
+ * @apiviz.composedOf AbstractRTreeSettings
+ * @apiviz.composedOf Statistics
*
* @param <N> Node type
* @param <E> Entry type
*/
-public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E extends SpatialEntry> extends SpatialIndexTree<N, E> {
+public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E extends SpatialEntry, S extends AbstractRTreeSettings> extends SpatialIndexTree<N, E> {
/**
* Development flag: This will enable some extra integrity checks on the tree.
*/
@@ -90,7 +83,7 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
/**
* For counting the number of distance computations.
*/
- public int distanceCalcs = 0;
+ public Statistics statistics = new Statistics();
/**
* The last inserted entry.
@@ -98,92 +91,19 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
E lastInsertedEntry = null;
/**
- * The strategy for bulk load.
+ * Settings class.
*/
- protected BulkSplit bulkSplitter;
-
- /**
- * The split strategy.
- */
- protected SplitStrategy nodeSplitter = TopologicalSplitter.STATIC;
-
- /**
- * The insertion strategy to use.
- */
- protected InsertionStrategy insertionStrategy = LeastOverlapInsertionStrategy.STATIC;
-
- /**
- * Overflow treatment.
- */
- protected OverflowTreatment overflowTreatment = LimitedReinsertOverflowTreatment.RSTAR_OVERFLOW;
-
- /**
- * Relative minimum fill.
- */
- protected double relativeMinFill = 0.4;
+ protected S settings;
/**
* Constructor.
*
* @param pagefile Page file
+ * @param settings Settings
*/
- public AbstractRStarTree(PageFile<N> pagefile) {
+ public AbstractRStarTree(PageFile<N> pagefile, S settings) {
super(pagefile);
- }
-
- /**
- * Set the bulk loading strategy.
- *
- * @param bulkSplitter Bulk loading strategy
- */
- public void setBulkStrategy(BulkSplit bulkSplitter) {
- this.bulkSplitter = bulkSplitter;
- }
-
- /**
- * Set the node splitting strategy.
- *
- * @param nodeSplitter the split strategy to set
- */
- public void setNodeSplitStrategy(SplitStrategy nodeSplitter) {
- if(nodeSplitter != null) {
- this.nodeSplitter = nodeSplitter;
- }
- else {
- getLogger().warning("Ignoring setNodeSplitStrategy(null)");
- }
- }
-
- /**
- * Set insertion strategy.
- *
- * @param insertionStrategy the insertion strategy to set
- */
- public void setInsertionStrategy(InsertionStrategy insertionStrategy) {
- if(insertionStrategy != null) {
- this.insertionStrategy = insertionStrategy;
- }
- else {
- getLogger().warning("Ignoring setInsertionStrategy(null)");
- }
- }
-
- /**
- * Set the overflow treatment strategy.
- *
- * @param overflowTreatment overflow treatment strategy
- */
- public void setOverflowTreatment(OverflowTreatment overflowTreatment) {
- this.overflowTreatment = overflowTreatment;
- }
-
- /**
- * Set the relative minimum fill. (Only supported before the tree was used!)
- *
- * @param relative Relative minimum fill
- */
- public void setMinimumFill(double relative) {
- this.relativeMinFill = relative;
+ this.settings = settings;
}
/**
@@ -198,20 +118,20 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
*/
protected IndexTreePath<E> findPathToObject(IndexTreePath<E> subtree, SpatialComparable mbr, DBIDRef id) {
N node = getNode(subtree.getLastPathComponent().getEntry());
- if(node.isLeaf()) {
- for(int i = 0; i < node.getNumEntries(); i++) {
- if(DBIDUtil.equal(((LeafEntry) node.getEntry(i)).getDBID(), id)) {
- return subtree.pathByAddingChild(new TreeIndexPathComponent<E>(node.getEntry(i), i));
+ if (node.isLeaf()) {
+ for (int i = 0; i < node.getNumEntries(); i++) {
+ if (DBIDUtil.equal(((LeafEntry) node.getEntry(i)).getDBID(), id)) {
+ return subtree.pathByAddingChild(new TreeIndexPathComponent<>(node.getEntry(i), i));
}
}
}
// directory node
else {
- for(int i = 0; i < node.getNumEntries(); i++) {
- if(SpatialUtil.intersects(node.getEntry(i), mbr)) {
- IndexTreePath<E> childSubtree = subtree.pathByAddingChild(new TreeIndexPathComponent<E>(node.getEntry(i), i));
+ for (int i = 0; i < node.getNumEntries(); i++) {
+ if (SpatialUtil.intersects(node.getEntry(i), mbr)) {
+ IndexTreePath<E> childSubtree = subtree.pathByAddingChild(new TreeIndexPathComponent<>(node.getEntry(i), i));
IndexTreePath<E> path = findPathToObject(childSubtree, mbr, id);
- if(path != null) {
+ if (path != null) {
return path;
}
}
@@ -222,10 +142,10 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
@Override
public void insertLeaf(E leaf) {
- if(!initialized) {
+ if (!initialized) {
initialize(leaf);
}
- overflowTreatment.reinitialize();
+ settings.getOverflowTreatment().reinitialize();
preInsert(leaf);
insertLeafEntry(leaf);
@@ -243,7 +163,7 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
// choose subtree for insertion
IndexTreePath<E> subtree = choosePath(getRootPath(), entry, 1);
- if(getLogger().isDebugging()) {
+ if (getLogger().isDebugging()) {
getLogger().debugFine("insertion-subtree " + subtree);
}
@@ -266,7 +186,7 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
lastInsertedEntry = entry;
// choose node for insertion of o
IndexTreePath<E> subtree = choosePath(getRootPath(), entry, level);
- if(getLogger().isDebugging()) {
+ if (getLogger().isDebugging()) {
getLogger().debugFine("subtree " + subtree);
}
@@ -293,20 +213,19 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
writeNode(leaf);
// condense the tree
- Stack<N> stack = new Stack<N>();
+ Stack<N> stack = new Stack<>();
condenseTree(deletionPath.getParentPath(), stack);
// reinsert underflow nodes
- while(!stack.empty()) {
+ while (!stack.empty()) {
N node = stack.pop();
- if(node.isLeaf()) {
- for(int i = 0; i < node.getNumEntries(); i++) {
- overflowTreatment.reinitialize(); // Intended?
+ if (node.isLeaf()) {
+ for (int i = 0; i < node.getNumEntries(); i++) {
+ settings.getOverflowTreatment().reinitialize(); // Intended?
this.insertLeafEntry(node.getEntry(i));
}
- }
- else {
- for(int i = 0; i < node.getNumEntries(); i++) {
+ } else {
+ for (int i = 0; i < node.getNumEntries(); i++) {
stack.push(getNode(node.getEntry(i)));
}
}
@@ -328,7 +247,7 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
// compute height
this.height = computeHeight();
- if(getLogger().isDebugging()) {
+ if (getLogger().isDebugging()) {
StringBuilder msg = new StringBuilder();
msg.append(getClass());
msg.append("\n height = ").append(height);
@@ -344,15 +263,14 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
SpatialPointLeafEntry sl = new SpatialPointLeafEntry(DBIDUtil.importInteger(0), new double[exampleLeaf.getDimensionality()]);
- while(baos.size() <= getPageSize()) {
+ while (baos.size() <= getPageSize()) {
sl.writeExternal(oos);
oos.flush();
cap++;
}
// the last one caused the page to overflow.
leafCapacity = cap - 1;
- }
- catch(IOException e) {
+ } catch (IOException e) {
throw new AbortException("Error determining page sizes.", e);
}
@@ -363,47 +281,43 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
ObjectOutputStream oos = new ObjectOutputStream(baos);
ModifiableHyperBoundingBox hb = new ModifiableHyperBoundingBox(new double[exampleLeaf.getDimensionality()], new double[exampleLeaf.getDimensionality()]);
SpatialDirectoryEntry sl = new SpatialDirectoryEntry(0, hb);
- while(baos.size() <= getPageSize()) {
+ while (baos.size() <= getPageSize()) {
sl.writeExternal(oos);
oos.flush();
cap++;
}
dirCapacity = cap - 1;
- }
- catch(IOException e) {
+ } catch (IOException e) {
throw new AbortException("Error determining page sizes.", e);
}
- if(dirCapacity <= 1) {
- throw new IllegalArgumentException("Node size of " + getPageSize() + " Bytes is chosen too small!");
+ if (dirCapacity <= 2) {
+ throw new IllegalArgumentException("Node size of " + getPageSize() + " bytes is chosen too small!");
}
- if(dirCapacity < 10) {
- getLogger().warning("Page size is choosen very small! Maximum number of entries " + "in a directory node = " + (dirCapacity - 1));
+ final Logging log = getLogger();
+ if (dirCapacity < 10) {
+ log.warning("Page size is choosen very small! Maximum number of entries in a directory node = " + dirCapacity);
}
// minimum entries per directory node
- dirMinimum = (int) Math.round((dirCapacity - 1) * relativeMinFill);
- if(dirMinimum < 2) {
- dirMinimum = 2;
+ dirMinimum = (int) Math.floor(dirCapacity * settings.relativeMinFill);
+ if (dirMinimum < 1) {
+ dirMinimum = 1;
}
- if(leafCapacity <= 1) {
- throw new IllegalArgumentException("Node size of " + getPageSize() + " Bytes is chosen too small!");
+ if (leafCapacity <= 2) {
+ throw new IllegalArgumentException("Node size of " + getPageSize() + " bytes is chosen too small!");
}
- if(leafCapacity < 10) {
- getLogger().warning("Page size is choosen very small! Maximum number of entries " + "in a leaf node = " + (leafCapacity - 1));
+ if (leafCapacity < 10) {
+ log.warning("Page size is choosen very small! Maximum number of entries in a leaf node = " + leafCapacity);
}
// minimum entries per leaf node
- leafMinimum = (int) Math.round((leafCapacity - 1) * relativeMinFill);
- if(leafMinimum < 2) {
- leafMinimum = 2;
- }
-
- if(getLogger().isVerbose()) {
- getLogger().verbose("Directory Capacity: " + (dirCapacity - 1) + "\nDirectory minimum: " + dirMinimum + "\nLeaf Capacity: " + (leafCapacity - 1) + "\nLeaf Minimum: " + leafMinimum);
+ leafMinimum = (int) Math.floor(leafCapacity * settings.relativeMinFill);
+ if (leafMinimum < 1) {
+ leafMinimum = 1;
}
}
@@ -413,7 +327,7 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
* @return Success code
*/
public boolean canBulkLoad() {
- return (bulkSplitter != null && !initialized);
+ return (settings.bulkSplitter != null && !initialized);
}
/**
@@ -424,17 +338,17 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
*/
protected List<E> createBulkLeafNodes(List<E> objects) {
int minEntries = leafMinimum;
- int maxEntries = leafCapacity - 1;
+ int maxEntries = leafCapacity;
- ArrayList<E> result = new ArrayList<E>();
- List<List<E>> partitions = bulkSplitter.partition(objects, minEntries, maxEntries);
+ ArrayList<E> result = new ArrayList<>();
+ List<List<E>> partitions = settings.bulkSplitter.partition(objects, minEntries, maxEntries);
- for(List<E> partition : partitions) {
+ for (List<E> partition : partitions) {
// create leaf node
N leafNode = createNewLeafNode();
// insert data
- for(E o : partition) {
+ for (E o : partition) {
leafNode.addLeafEntry(o);
}
// write to file
@@ -442,12 +356,12 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
result.add(createNewDirectoryEntry(leafNode));
- if(getLogger().isDebugging()) {
- getLogger().debugFine("Created leaf page "+leafNode.getPageID());
+ if (getLogger().isDebugging()) {
+ getLogger().debugFine("Created leaf page " + leafNode.getPageID());
}
}
- if(getLogger().isDebugging()) {
+ if (getLogger().isDebugging()) {
getLogger().debugFine("numDataPages = " + result.size());
}
return result;
@@ -528,8 +442,8 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
// switch the ids
oldRoot.setPageID(root.getPageID());
- if(!oldRoot.isLeaf()) {
- for(int i = 0; i < oldRoot.getNumEntries(); i++) {
+ if (!oldRoot.isLeaf()) {
+ for (int i = 0; i < oldRoot.getNumEntries(); i++) {
N node = getNode(oldRoot.getEntry(i));
writeNode(node);
}
@@ -544,7 +458,7 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
writeNode(root);
writeNode(oldRoot);
writeNode(newNode);
- if(getLogger().isDebugging()) {
+ if (getLogger().isDebugging()) {
String msg = "Create new Root: ID=" + root.getPageID();
msg += "\nchild1 " + oldRoot + " " + new HyperBoundingBox(oldRootEntry);
msg += "\nchild2 " + newNode + " " + new HyperBoundingBox(newNodeEntry);
@@ -552,7 +466,7 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
getLogger().debugFine(msg);
}
- return new IndexTreePath<E>(new TreeIndexPathComponent<E>(getRootEntry(), null));
+ return new IndexTreePath<>(new TreeIndexPathComponent<>(getRootEntry(), null));
}
/**
@@ -570,21 +484,20 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
int index = -1;
double cEVol = Double.NaN;
E ei;
- for(int i = 0; i < node.getNumEntries(); i++) {
+ for (int i = 0; i < node.getNumEntries(); i++) {
ei = node.getEntry(i);
// skip test on pairwise overlaps
- if(SpatialUtil.contains(ei, mbr)) {
- if(containingEntry == null) {
+ if (SpatialUtil.contains(ei, mbr)) {
+ if (containingEntry == null) {
containingEntry = ei;
index = i;
- }
- else {
+ } else {
double tempVol = SpatialUtil.volume(ei);
- if(Double.isNaN(cEVol)) { // calculate volume of currently best
+ if (Double.isNaN(cEVol)) { // calculate volume of currently best
cEVol = SpatialUtil.volume(containingEntry);
}
// take containing node with lowest volume
- if(tempVol < cEVol) {
+ if (tempVol < cEVol) {
cEVol = tempVol;
containingEntry = ei;
index = i;
@@ -592,7 +505,7 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
}
}
}
- return (containingEntry == null ? null : new TreeIndexPathComponent<E>(containingEntry, index));
+ return (containingEntry == null ? null : new TreeIndexPathComponent<>(containingEntry, index));
}
/**
@@ -606,38 +519,36 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
* @return the path of the appropriate subtree to insert the given mbr
*/
protected IndexTreePath<E> choosePath(IndexTreePath<E> subtree, SpatialComparable mbr, int level) {
- if(getLogger().isDebuggingFiner()) {
+ if (getLogger().isDebuggingFiner()) {
getLogger().debugFiner("node " + subtree + ", level " + level);
}
N node = getNode(subtree.getLastPathComponent().getEntry());
- if(node == null) {
+ if (node == null) {
throw new RuntimeException("Page file did not return node for node id: " + getPageID(subtree.getLastPathComponent().getEntry()));
}
- if(node.isLeaf()) {
+ if (node.isLeaf()) {
return subtree;
}
// first test on containment
TreeIndexPathComponent<E> containingEntry = containedTest(node, mbr);
- if(containingEntry != null) {
+ if (containingEntry != null) {
IndexTreePath<E> newSubtree = subtree.pathByAddingChild(containingEntry);
- if(height - subtree.getPathCount() == level) {
+ if (height - subtree.getPathCount() == level) {
return newSubtree;
- }
- else {
+ } else {
return choosePath(newSubtree, mbr, level);
}
}
N childNode = getNode(node.getEntry(0));
- int num = insertionStrategy.choose(node, NodeArrayAdapter.STATIC, mbr, height, subtree.getPathCount());
- TreeIndexPathComponent<E> comp = new TreeIndexPathComponent<E>(node.getEntry(num), num);
+ int num = settings.insertionStrategy.choose(node, NodeArrayAdapter.STATIC, mbr, height, subtree.getPathCount());
+ TreeIndexPathComponent<E> comp = new TreeIndexPathComponent<>(node.getEntry(num), num);
// children are leafs
- if(childNode.isLeaf()) {
- if(height - subtree.getPathCount() == level) {
+ if (childNode.isLeaf()) {
+ if (height - subtree.getPathCount() == level) {
return subtree.pathByAddingChild(comp);
- }
- else {
+ } else {
throw new IllegalArgumentException("childNode is leaf, but currentLevel != level: " + (height - subtree.getPathCount()) + " != " + level);
}
}
@@ -645,10 +556,9 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
else {
IndexTreePath<E> newSubtree = subtree.pathByAddingChild(comp);
// desired level is reached
- if(height - subtree.getPathCount() == level) {
+ if (height - subtree.getPathCount() == level) {
return newSubtree;
- }
- else {
+ } else {
return choosePath(newSubtree, mbr, level);
}
}
@@ -666,7 +576,7 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
* reinsertion
*/
private N overflowTreatment(N node, IndexTreePath<E> path) {
- if(overflowTreatment.handleOverflow(this, node, path)) {
+ if (settings.getOverflowTreatment().handleOverflow(this, node, path)) {
return null;
}
return split(node);
@@ -681,14 +591,13 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
private N split(N node) {
// choose the split dimension and the split point
int minimum = node.isLeaf() ? leafMinimum : dirMinimum;
- BitSet split = nodeSplitter.split(node, NodeArrayAdapter.STATIC, minimum);
+ BitSet split = settings.nodeSplitter.split(node, NodeArrayAdapter.STATIC, minimum);
// New node
final N newNode;
- if(node.isLeaf()) {
+ if (node.isLeaf()) {
newNode = createNewLeafNode();
- }
- else {
+ } else {
newNode = createNewDirectoryNode();
}
// do the split
@@ -712,8 +621,8 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
final int level = height - (path.getPathCount() - 1);
BitSet remove = new BitSet();
- List<E> reInsertEntries = new ArrayList<E>(offs.length);
- for(int i = 0; i < offs.length; i++) {
+ List<E> reInsertEntries = new ArrayList<>(offs.length);
+ for (int i = 0; i < offs.length; i++) {
reInsertEntries.add(node.getEntry(offs[i]));
remove.set(offs[i]);
}
@@ -724,30 +633,28 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
// and adapt the mbrs
IndexTreePath<E> childPath = path;
N child = node;
- while(childPath.getParentPath() != null) {
+ while (childPath.getParentPath() != null) {
N parent = getNode(childPath.getParentPath().getLastPathComponent().getEntry());
int indexOfChild = childPath.getLastPathComponent().getIndex();
- if(child.adjustEntry(parent.getEntry(indexOfChild))) {
+ if (child.adjustEntry(parent.getEntry(indexOfChild))) {
writeNode(parent);
childPath = childPath.getParentPath();
child = parent;
- }
- else {
+ } else {
break;
// TODO: stop writing when MBR didn't change!
}
}
// reinsert the first entries
- for(E entry : reInsertEntries) {
- if(node.isLeaf()) {
- if(getLogger().isDebugging()) {
+ for (E entry : reInsertEntries) {
+ if (node.isLeaf()) {
+ if (getLogger().isDebugging()) {
getLogger().debug("reinsert " + entry);
}
insertLeafEntry(entry);
- }
- else {
- if(getLogger().isDebugging()) {
+ } else {
+ if (getLogger().isDebugging()) {
getLogger().debug("reinsert " + entry + " at " + level);
}
insertDirectoryEntry(entry, level);
@@ -761,7 +668,7 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
* @param subtree the subtree to be adjusted
*/
protected void adjustTree(IndexTreePath<E> subtree) {
- if(getLogger().isDebugging()) {
+ if (getLogger().isDebugging()) {
getLogger().debugFine("Adjust tree " + subtree);
}
@@ -769,15 +676,15 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
N node = getNode(subtree.getLastPathComponent().getEntry());
// overflow in node
- if(hasOverflow(node)) {
+ if (hasOverflow(node)) {
// treatment of overflow: reinsertion or split
N split = overflowTreatment(node, subtree);
// node was split
- if(split != null) {
+ if (split != null) {
// if root was split: create a new root that points the two
// split nodes
- if(isRoot(node)) {
+ if (isRoot(node)) {
IndexTreePath<E> newRootPath = createNewRoot(node, split);
height++;
adjustTree(newRootPath);
@@ -786,7 +693,7 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
else {
// get the parent and add the new split node
N parent = getNode(subtree.getParentPath().getLastPathComponent().getEntry());
- if(getLogger().isDebugging()) {
+ if (getLogger().isDebugging()) {
getLogger().debugFine("parent " + parent);
}
parent.addDirectoryEntry(createNewDirectoryEntry(split));
@@ -807,11 +714,11 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
// no overflow, only adjust parameters of the entry representing the
// node
else {
- if(!isRoot(node)) {
+ if (!isRoot(node)) {
N parent = getNode(subtree.getParentPath().getLastPathComponent().getEntry());
E entry = parent.getEntry(subtree.getLastPathComponent().getIndex());
boolean changed = node.adjustEntryIncremental(entry, lastInsertedEntry);
- if(changed) {
+ if (changed) {
// node.adjustEntry(parent.getEntry(index));
// write changes in parent to file
writeNode(parent);
@@ -835,18 +742,16 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
private void condenseTree(IndexTreePath<E> subtree, Stack<N> stack) {
N node = getNode(subtree.getLastPathComponent().getEntry());
// node is not root
- if(!isRoot(node)) {
+ if (!isRoot(node)) {
N parent = getNode(subtree.getParentPath().getLastPathComponent().getEntry());
int index = subtree.getLastPathComponent().getIndex();
- if(hasUnderflow(node)) {
- if(parent.deleteEntry(index)) {
+ if (hasUnderflow(node)) {
+ if (parent.deleteEntry(index)) {
stack.push(node);
- }
- else {
+ } else {
node.adjustEntry(parent.getEntry(index));
}
- }
- else {
+ } else {
node.adjustEntry(parent.getEntry(index));
}
writeNode(parent);
@@ -856,20 +761,19 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
// node is root
else {
- if(hasUnderflow(node) && node.getNumEntries() == 1 && !node.isLeaf()) {
+ if (hasUnderflow(node) && node.getNumEntries() == 1 && !node.isLeaf()) {
N child = getNode(node.getEntry(0));
N newRoot;
- if(child.isLeaf()) {
+ if (child.isLeaf()) {
newRoot = createNewLeafNode();
newRoot.setPageID(getRootID());
- for(int i = 0; i < child.getNumEntries(); i++) {
+ for (int i = 0; i < child.getNumEntries(); i++) {
newRoot.addLeafEntry(child.getEntry(i));
}
- }
- else {
+ } else {
newRoot = createNewDirectoryNode();
newRoot.setPageID(getRootID());
- for(int i = 0; i < child.getNumEntries(); i++) {
+ for (int i = 0; i < child.getNumEntries(); i++) {
newRoot.addDirectoryEntry(child.getEntry(i));
}
}
@@ -881,9 +785,9 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
@Override
public final List<E> getLeaves() {
- List<E> result = new ArrayList<E>();
+ List<E> result = new ArrayList<>();
- if(height == 1) {
+ if (height == 1) {
result.add(getRootEntry());
return result;
}
@@ -901,13 +805,12 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
*/
private void getLeafNodes(N node, List<E> result, int currentLevel) {
// Level 1 are the leaf nodes, Level 2 is the one atop!
- if(currentLevel == 2) {
- for(int i = 0; i < node.getNumEntries(); i++) {
+ if (currentLevel == 2) {
+ for (int i = 0; i < node.getNumEntries(); i++) {
result.add(node.getEntry(i));
}
- }
- else {
- for(int i = 0; i < node.getNumEntries(); i++) {
+ } else {
+ for (int i = 0; i < node.getNumEntries(); i++) {
N child = getNode(node.getEntry(i));
getLeafNodes(child, result, (currentLevel - 1));
}
@@ -918,11 +821,100 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
* Perform additional integrity checks.
*/
public void doExtraIntegrityChecks() {
- if(EXTRA_INTEGRITY_CHECKS) {
+ if (EXTRA_INTEGRITY_CHECKS) {
getRoot().integrityCheck(this);
}
}
+ @Override
+ public void logStatistics() {
+ super.logStatistics();
+ Logging log = getLogger();
+ if (log.isStatistics()) {
+ log.statistics(new LongStatistic(this.getClass().getName() + ".height", height));
+ statistics.logStatistics();
+ }
+ }
+
+ /**
+ * Class for tracking some statistics.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.composedOf Counter
+ */
+ public class Statistics {
+ /**
+ * For counting the number of distance computations.
+ */
+ protected final Counter distanceCalcs;
+
+ /**
+ * For counting the number of knn queries answered.
+ */
+ protected final Counter knnQueries;
+
+ /**
+ * For counting the number of range queries answered.
+ */
+ protected final Counter rangeQueries;
+
+ /**
+ * Constructor.
+ */
+ public Statistics() {
+ super();
+ Logging log = getLogger();
+ final String prefix = AbstractRStarTree.this.getClass().getName();
+ distanceCalcs = log.isStatistics() ? log.newCounter(prefix + ".distancecalcs") : null;
+ knnQueries = log.isStatistics() ? log.newCounter(prefix + ".knnqueries") : null;
+ rangeQueries = log.isStatistics() ? log.newCounter(prefix + ".rangequeries") : null;
+ }
+
+ /**
+ * Count a distance computation.
+ */
+ public void countDistanceCalculation() {
+ if (distanceCalcs != null) {
+ distanceCalcs.increment();
+ }
+ }
+
+ /**
+ * Count a knn query invocation.
+ */
+ public void countKNNQuery() {
+ if (knnQueries != null) {
+ knnQueries.increment();
+ }
+ }
+
+ /**
+ * Count a range query invocation.
+ */
+ public void countRangeQuery() {
+ if (rangeQueries != null) {
+ rangeQueries.increment();
+ }
+ }
+
+ /**
+ * Log the statistics.
+ */
+ public void logStatistics() {
+ Logging log = getLogger();
+ if (statistics.distanceCalcs != null) {
+ log.statistics(statistics.distanceCalcs);
+ }
+ if (statistics.knnQueries != null) {
+ log.statistics(statistics.knnQueries);
+ }
+ if (statistics.rangeQueries != null) {
+ log.statistics(statistics.rangeQueries);
+ }
+ }
+ }
+
/**
* Returns a string representation of this R*-Tree.
*
@@ -936,45 +928,42 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
int objects = 0;
int levels = 0;
- if(initialized) {
+ if (initialized) {
N node = getRoot();
int dim = getRootEntry().getDimensionality();
- while(!node.isLeaf()) {
- if(node.getNumEntries() > 0) {
+ while (!node.isLeaf()) {
+ if (node.getNumEntries() > 0) {
E entry = node.getEntry(0);
node = getNode(entry);
levels++;
}
}
- BreadthFirstEnumeration<N, E> enumeration = new BreadthFirstEnumeration<N, E>(this, getRootPath());
- while(enumeration.hasMoreElements()) {
+ BreadthFirstEnumeration<N, E> enumeration = new BreadthFirstEnumeration<>(this, getRootPath());
+ while (enumeration.hasMoreElements()) {
IndexTreePath<E> indexPath = enumeration.nextElement();
E entry = indexPath.getLastPathComponent().getEntry();
- if(entry.isLeafEntry()) {
+ if (entry.isLeafEntry()) {
objects++;
- }
- else {
+ } else {
node = getNode(entry);
- if(node.isLeaf()) {
+ if (node.isLeaf()) {
leafNodes++;
- }
- else {
+ } else {
dirNodes++;
}
}
}
result.append(getClass().getName()).append(" has ").append((levels + 1)).append(" levels.\n");
- result.append(dirNodes).append(" Directory Knoten (max = ").append(dirCapacity - 1).append(", min = ").append(dirMinimum).append(")\n");
- result.append(leafNodes).append(" Daten Knoten (max = ").append(leafCapacity - 1).append(", min = ").append(leafMinimum).append(")\n");
+ result.append(dirNodes).append(" Directory Knoten (max = ").append(dirCapacity).append(", min = ").append(dirMinimum).append(")\n");
+ result.append(leafNodes).append(" Daten Knoten (max = ").append(leafCapacity).append(", min = ").append(leafMinimum).append(")\n");
result.append(objects).append(' ').append(dim).append("-dim. Punkte im Baum \n");
- PageFileUtil.appendPageFileStatistics(result, getPageFileStatistics());
- }
- else {
+ // PageFileUtil.appendPageFileStatistics(result, getPageFileStatistics());
+ } else {
result.append(getClass().getName()).append(" is empty!\n");
}
return result.toString();
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRStarTreeFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRStarTreeFactory.java
index ace5ad41..48b84302 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRStarTreeFactory.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRStarTreeFactory.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,7 +27,7 @@ import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
import de.lmu.ifi.dbs.elki.index.Index;
-import de.lmu.ifi.dbs.elki.index.tree.TreeIndexFactory;
+import de.lmu.ifi.dbs.elki.index.PagedIndexFactory;
import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry;
import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk.BulkSplit;
import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert.CombinedInsertionStrategy;
@@ -36,6 +36,7 @@ import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.overflow.
import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.overflow.OverflowTreatment;
import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split.SplitStrategy;
import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split.TopologicalSplitter;
+import de.lmu.ifi.dbs.elki.persistent.PageFileFactory;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.LessConstraint;
@@ -56,76 +57,21 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
* @param <E> Entry type
* @param <I> Index type
*/
-public abstract class AbstractRStarTreeFactory<O extends NumberVector<?>, N extends AbstractRStarTreeNode<N, E>, E extends SpatialEntry, I extends AbstractRStarTree<N, E> & Index> extends TreeIndexFactory<O, I> {
+public abstract class AbstractRStarTreeFactory<O extends NumberVector<?>, N extends AbstractRStarTreeNode<N, E>, E extends SpatialEntry, I extends AbstractRStarTree<N, E, S> & Index, S extends AbstractRTreeSettings> extends PagedIndexFactory<O, I> {
/**
- * Fast-insertion parameter. Optional.
+ * Tree settings
*/
- public static OptionID INSERTION_STRATEGY_ID = new OptionID("rtree.insertionstrategy", "The strategy to use for object insertion.");
-
- /**
- * Split strategy parameter. Optional.
- */
- public static OptionID SPLIT_STRATEGY_ID = new OptionID("rtree.splitstrategy", "The strategy to use for node splitting.");
-
- /**
- * Parameter for bulk strategy
- */
- public static final OptionID BULK_SPLIT_ID = new OptionID("spatial.bulkstrategy", "The class to perform the bulk split with.");
-
- /**
- * Parameter for the relative minimum fill.
- */
- public static final OptionID MINIMUM_FILL_ID = new OptionID("rtree.minimum-fill", "Minimum relative fill required for data pages.");
-
- /**
- * Overflow treatment.
- */
- public static OptionID OVERFLOW_STRATEGY_ID = new OptionID("rtree.overflowtreatment", "The strategy to use for handling overflows.");
-
- /**
- * Strategy to find the insertion node with.
- */
- protected InsertionStrategy insertionStrategy;
-
- /**
- * The strategy for bulk load.
- */
- protected BulkSplit bulkSplitter;
-
- /**
- * The strategy for splitting nodes
- */
- protected SplitStrategy nodeSplitter;
-
- /**
- * Overflow treatment strategy
- */
- protected OverflowTreatment overflowTreatment;
-
- /**
- * Relative minimum fill
- */
- protected double minimumFill;
+ protected S settings;
/**
* Constructor.
*
- * @param fileName
- * @param pageSize
- * @param cacheSize
- * @param bulkSplitter the strategy to use for bulk splitting
- * @param insertionStrategy the strategy to find the insertion child
- * @param nodeSplitter the strategy to use for splitting nodes
- * @param overflowTreatment the strategy to use for overflow treatment
- * @param minimumFill the relative minimum fill
+ * @param pageFileFactory Page file factory
+ * @param settings Tree settings
*/
- public AbstractRStarTreeFactory(String fileName, int pageSize, long cacheSize, BulkSplit bulkSplitter, InsertionStrategy insertionStrategy, SplitStrategy nodeSplitter, OverflowTreatment overflowTreatment, double minimumFill) {
- super(fileName, pageSize, cacheSize);
- this.insertionStrategy = insertionStrategy;
- this.bulkSplitter = bulkSplitter;
- this.nodeSplitter = nodeSplitter;
- this.overflowTreatment = overflowTreatment;
- this.minimumFill = minimumFill;
+ public AbstractRStarTreeFactory(PageFileFactory<?> pageFileFactory, S settings) {
+ super(pageFileFactory);
+ this.settings = settings;
}
@Override
@@ -139,53 +85,69 @@ public abstract class AbstractRStarTreeFactory<O extends NumberVector<?>, N exte
* @author Erich Schubert
*
* @apiviz.exclude
+ *
+ * @param <O> Object type
+ * @param <S> Settings class
*/
- public abstract static class Parameterizer<O extends NumberVector<?>> extends TreeIndexFactory.Parameterizer<O> {
+ public abstract static class Parameterizer<O extends NumberVector<?>, S extends AbstractRTreeSettings> extends PagedIndexFactory.Parameterizer<O> {
+ /**
+ * Fast-insertion parameter. Optional.
+ */
+ public static OptionID INSERTION_STRATEGY_ID = new OptionID("rtree.insertionstrategy", "The strategy to use for object insertion.");
+
/**
- * Insertion strategy
+ * Split strategy parameter. Optional.
*/
- protected InsertionStrategy insertionStrategy = null;
+ public static OptionID SPLIT_STRATEGY_ID = new OptionID("rtree.splitstrategy", "The strategy to use for node splitting.");
/**
- * The strategy for splitting nodes
+ * Parameter for bulk strategy
*/
- protected SplitStrategy nodeSplitter = null;
+ public static final OptionID BULK_SPLIT_ID = new OptionID("spatial.bulkstrategy", "The class to perform the bulk split with.");
/**
- * Bulk loading strategy
+ * Parameter for the relative minimum fill.
*/
- protected BulkSplit bulkSplitter = null;
+ public static final OptionID MINIMUM_FILL_ID = new OptionID("rtree.minimum-fill", "Minimum relative fill required for data pages.");
/**
- * Overflow treatment strategy
+ * Overflow treatment.
*/
- protected OverflowTreatment overflowTreatment = null;
+ public static OptionID OVERFLOW_STRATEGY_ID = new OptionID("rtree.overflowtreatment", "The strategy to use for handling overflows.");
/**
- * Relative minimum fill
+ * Tree settings
+ */
+ protected S settings;
+
+ /**
+ * Create the settings object
+ *
+ * @return Settings instance.
*/
- protected double minimumFill;
+ abstract protected S createSettings();
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- ObjectParameter<InsertionStrategy> insertionStrategyP = new ObjectParameter<InsertionStrategy>(INSERTION_STRATEGY_ID, InsertionStrategy.class, CombinedInsertionStrategy.class);
+ settings = createSettings();
+ ObjectParameter<InsertionStrategy> insertionStrategyP = new ObjectParameter<>(INSERTION_STRATEGY_ID, InsertionStrategy.class, CombinedInsertionStrategy.class);
if (config.grab(insertionStrategyP)) {
- insertionStrategy = insertionStrategyP.instantiateClass(config);
+ settings.insertionStrategy = insertionStrategyP.instantiateClass(config);
}
- ObjectParameter<SplitStrategy> splitStrategyP = new ObjectParameter<SplitStrategy>(SPLIT_STRATEGY_ID, SplitStrategy.class, TopologicalSplitter.class);
+ ObjectParameter<SplitStrategy> splitStrategyP = new ObjectParameter<>(SPLIT_STRATEGY_ID, SplitStrategy.class, TopologicalSplitter.class);
if (config.grab(splitStrategyP)) {
- nodeSplitter = splitStrategyP.instantiateClass(config);
+ settings.nodeSplitter = splitStrategyP.instantiateClass(config);
}
DoubleParameter minimumFillP = new DoubleParameter(MINIMUM_FILL_ID, 0.4);
minimumFillP.addConstraint(new GreaterConstraint(0.0));
minimumFillP.addConstraint(new LessConstraint(0.5));
if (config.grab(minimumFillP)) {
- minimumFill = minimumFillP.getValue();
+ settings.relativeMinFill = minimumFillP.getValue();
}
- ObjectParameter<OverflowTreatment> overflowP = new ObjectParameter<OverflowTreatment>(OVERFLOW_STRATEGY_ID, OverflowTreatment.class, LimitedReinsertOverflowTreatment.class);
+ ObjectParameter<OverflowTreatment> overflowP = new ObjectParameter<>(OVERFLOW_STRATEGY_ID, OverflowTreatment.class, LimitedReinsertOverflowTreatment.class);
if (config.grab(overflowP)) {
- overflowTreatment = overflowP.instantiateClass(config);
+ settings.setOverflowTreatment(overflowP.instantiateClass(config));
}
configBulkLoad(config);
}
@@ -196,13 +158,13 @@ public abstract class AbstractRStarTreeFactory<O extends NumberVector<?>, N exte
* @param config Parameterization
*/
protected void configBulkLoad(Parameterization config) {
- ObjectParameter<BulkSplit> bulkSplitP = new ObjectParameter<BulkSplit>(BULK_SPLIT_ID, BulkSplit.class, true);
+ ObjectParameter<BulkSplit> bulkSplitP = new ObjectParameter<>(BULK_SPLIT_ID, BulkSplit.class, true);
if (config.grab(bulkSplitP)) {
- bulkSplitter = bulkSplitP.instantiateClass(config);
+ settings.bulkSplitter = bulkSplitP.instantiateClass(config);
}
}
@Override
- protected abstract AbstractRStarTreeFactory<O, ?, ?, ?> makeInstance();
+ protected abstract AbstractRStarTreeFactory<O, ?, ?, ?, ?> makeInstance();
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRStarTreeNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRStarTreeNode.java
index 80666ebb..6b5fc2f0 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRStarTreeNode.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRStarTreeNode.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -133,7 +133,7 @@ public abstract class AbstractRStarTreeNode<N extends AbstractRStarTreeNode<N, E
* Tests this node (for debugging purposes).
*/
@SuppressWarnings("unchecked")
- public final void integrityCheck(AbstractRStarTree<N, E> tree) {
+ public final void integrityCheck(AbstractRStarTree<N, E, ?> tree) {
// leaf node
if(isLeaf()) {
for(int i = 0; i < getCapacity(); i++) {
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRTreeSettings.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRTreeSettings.java
new file mode 100644
index 00000000..f876be13
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRTreeSettings.java
@@ -0,0 +1,121 @@
+package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants;
+
+import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk.BulkSplit;
+import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert.InsertionStrategy;
+import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert.LeastOverlapInsertionStrategy;
+import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.overflow.LimitedReinsertOverflowTreatment;
+import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.overflow.OverflowTreatment;
+import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split.SplitStrategy;
+import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split.TopologicalSplitter;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Class to wrap common Rtree settings.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.composedOf BulkSplit
+ * @apiviz.composedOf SplitStrategy
+ * @apiviz.composedOf InsertionStrategy
+ * @apiviz.composedOf OverflowTreatment
+ */
+public class AbstractRTreeSettings {
+ /**
+ * The strategy for bulk load.
+ */
+ protected BulkSplit bulkSplitter = null;
+
+ /**
+ * The split strategy.
+ */
+ protected SplitStrategy nodeSplitter = TopologicalSplitter.STATIC;
+
+ /**
+ * The insertion strategy to use.
+ */
+ protected InsertionStrategy insertionStrategy = LeastOverlapInsertionStrategy.STATIC;
+
+ /**
+ * Overflow treatment.
+ */
+ private OverflowTreatment overflowTreatment = LimitedReinsertOverflowTreatment.RSTAR_OVERFLOW;
+
+ /**
+ * Relative minimum fill.
+ */
+ protected double relativeMinFill = 0.4;
+
+ /**
+ * Set the bulk loading strategy.
+ *
+ * @param bulkSplitter Bulk loading strategy
+ */
+ public void setBulkStrategy(BulkSplit bulkSplitter) {
+ this.bulkSplitter = bulkSplitter;
+ }
+
+ /**
+ * Set the node splitting strategy.
+ *
+ * @param nodeSplitter the split strategy to set
+ */
+ public void setNodeSplitStrategy(SplitStrategy nodeSplitter) {
+ this.nodeSplitter = nodeSplitter;
+ }
+
+ /**
+ * Set insertion strategy.
+ *
+ * @param insertionStrategy the insertion strategy to set
+ */
+ public void setInsertionStrategy(InsertionStrategy insertionStrategy) {
+ this.insertionStrategy = insertionStrategy;
+ }
+
+ /**
+ * Set the overflow treatment strategy.
+ *
+ * @param overflowTreatment overflow treatment strategy
+ */
+ public void setOverflowTreatment(OverflowTreatment overflowTreatment) {
+ this.overflowTreatment = overflowTreatment;
+ }
+
+ /**
+ * Set the relative minimum fill. (Only supported before the tree was used!)
+ *
+ * @param relative Relative minimum fill
+ */
+ public void setMinimumFill(double relative) {
+ this.relativeMinFill = relative;
+ }
+
+ /**
+ * @return the overflowTreatment
+ */
+ public OverflowTreatment getOverflowTreatment() {
+ return overflowTreatment;
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/NonFlatRStarTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/NonFlatRStarTree.java
index fd7d3d8b..8a4f530f 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/NonFlatRStarTree.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/NonFlatRStarTree.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -38,14 +38,15 @@ import de.lmu.ifi.dbs.elki.persistent.PageFile;
* @param <N> Node type
* @param <E> Entry type
*/
-public abstract class NonFlatRStarTree<N extends AbstractRStarTreeNode<N, E>, E extends SpatialEntry> extends AbstractRStarTree<N, E> {
+public abstract class NonFlatRStarTree<N extends AbstractRStarTreeNode<N, E>, E extends SpatialEntry, S extends AbstractRTreeSettings> extends AbstractRStarTree<N, E, S> {
/**
* Constructor.
*
* @param pagefile Page file
+ * @param settings Settings
*/
- public NonFlatRStarTree(PageFile<N> pagefile) {
- super(pagefile);
+ public NonFlatRStarTree(PageFile<N> pagefile, S settings) {
+ super(pagefile, settings);
}
/**
@@ -180,8 +181,8 @@ public abstract class NonFlatRStarTree<N extends AbstractRStarTreeNode<N, E>, E
int minEntries = dirMinimum;
int maxEntries = dirCapacity - 1;
- ArrayList<E> result = new ArrayList<E>();
- List<List<E>> partitions = bulkSplitter.partition(nodes, minEntries, maxEntries);
+ ArrayList<E> result = new ArrayList<>();
+ List<List<E>> partitions = settings.bulkSplitter.partition(nodes, minEntries, maxEntries);
for(List<E> partition : partitions) {
// create node
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluDirectoryEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluDirectoryEntry.java
index 10f25ec0..510120c9 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluDirectoryEntry.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluDirectoryEntry.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.deliclu;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluEntry.java
index 8b279268..f72b7d8d 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluEntry.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluEntry.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.deliclu;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluLeafEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluLeafEntry.java
index bc701185..741ab840 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluLeafEntry.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluLeafEntry.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.deliclu;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluNode.java
index bf993c01..7b3221c3 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluNode.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluNode.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.deliclu;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluTree.java
index 0cd74a14..33366763 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluTree.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluTree.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.deliclu;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,19 +23,19 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.deliclu;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Set;
-
+import gnu.trove.map.hash.TIntObjectHashMap;
+import gnu.trove.set.TIntSet;
+import gnu.trove.set.hash.TIntHashSet;
import de.lmu.ifi.dbs.elki.index.tree.BreadthFirstEnumeration;
import de.lmu.ifi.dbs.elki.index.tree.Entry;
import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry;
+import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRTreeSettings;
import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.NonFlatRStarTree;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.persistent.PageFile;
/**
- * DeLiCluTree is a spatial index structure based on an R-TRee. DeLiCluTree is
+ * DeLiCluTree is a spatial index structure based on an R-Tree. DeLiCluTree is
* designed for the DeLiClu algorithm, having in each node a boolean array which
* indicates whether the child nodes are already handled by the DeLiClu
* algorithm.
@@ -44,7 +44,7 @@ import de.lmu.ifi.dbs.elki.persistent.PageFile;
*
* @apiviz.has DeLiCluNode oneway - - contains
*/
-public class DeLiCluTree extends NonFlatRStarTree<DeLiCluNode, DeLiCluEntry> {
+public class DeLiCluTree extends NonFlatRStarTree<DeLiCluNode, DeLiCluEntry, AbstractRTreeSettings> {
/**
* The logger for this class.
*/
@@ -53,15 +53,16 @@ public class DeLiCluTree extends NonFlatRStarTree<DeLiCluNode, DeLiCluEntry> {
/**
* Holds the ids of the expanded nodes.
*/
- private HashMap<Integer, HashSet<Integer>> expanded = new HashMap<Integer, HashSet<Integer>>();
+ private TIntObjectHashMap<TIntHashSet> expanded = new TIntObjectHashMap<>();
/**
* Constructor.
*
* @param pagefile Page file
+ * @param settings Settings
*/
- public DeLiCluTree(PageFile<DeLiCluNode> pagefile) {
- super(pagefile);
+ public DeLiCluTree(PageFile<DeLiCluNode> pagefile, AbstractRTreeSettings settings) {
+ super(pagefile, settings);
}
/**
@@ -71,9 +72,9 @@ public class DeLiCluTree extends NonFlatRStarTree<DeLiCluNode, DeLiCluEntry> {
* @param entry2 the second node
*/
public void setExpanded(SpatialEntry entry1, SpatialEntry entry2) {
- HashSet<Integer> exp1 = expanded.get(getPageID(entry1));
+ TIntHashSet exp1 = expanded.get(getPageID(entry1));
if(exp1 == null) {
- exp1 = new HashSet<Integer>();
+ exp1 = new TIntHashSet();
expanded.put(getPageID(entry1), exp1);
}
exp1.add(getPageID(entry2));
@@ -85,12 +86,12 @@ public class DeLiCluTree extends NonFlatRStarTree<DeLiCluNode, DeLiCluEntry> {
* @param entry the id of the node for which the expansions should be returned
* @return the nodes which are already expanded with the specified node
*/
- public Set<Integer> getExpanded(SpatialEntry entry) {
- HashSet<Integer> exp = expanded.get(getPageID(entry));
+ public TIntSet getExpanded(SpatialEntry entry) {
+ TIntHashSet exp = expanded.get(getPageID(entry));
if(exp != null) {
return exp;
}
- return new HashSet<Integer>();
+ return new TIntHashSet();
}
/**
@@ -99,12 +100,12 @@ public class DeLiCluTree extends NonFlatRStarTree<DeLiCluNode, DeLiCluEntry> {
* @param entry the id of the node for which the expansions should be returned
* @return the nodes which are already expanded with the specified node
*/
- public Set<Integer> getExpanded(DeLiCluNode entry) {
- HashSet<Integer> exp = expanded.get(entry.getPageID());
+ public TIntSet getExpanded(DeLiCluNode entry) {
+ TIntHashSet exp = expanded.get(entry.getPageID());
if(exp != null) {
return exp;
}
- return new HashSet<Integer>();
+ return new TIntHashSet();
}
/**
@@ -115,7 +116,7 @@ public class DeLiCluTree extends NonFlatRStarTree<DeLiCluNode, DeLiCluEntry> {
public int numNodes() {
int numNodes = 0;
- BreadthFirstEnumeration<DeLiCluNode, DeLiCluEntry> bfs = new BreadthFirstEnumeration<DeLiCluNode, DeLiCluEntry>(this, getRootPath());
+ BreadthFirstEnumeration<DeLiCluNode, DeLiCluEntry> bfs = new BreadthFirstEnumeration<>(this, getRootPath());
while(bfs.hasMoreElements()) {
Entry entry = bfs.nextElement().getLastPathComponent().getEntry();
if(!entry.isLeafEntry()) {
@@ -170,4 +171,4 @@ public class DeLiCluTree extends NonFlatRStarTree<DeLiCluNode, DeLiCluEntry> {
protected Logging getLogger() {
return LOG;
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluTreeFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluTreeFactory.java
index b64192c1..a63b8004 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluTreeFactory.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluTreeFactory.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.deliclu;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,11 +26,9 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.deliclu;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRStarTreeFactory;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk.BulkSplit;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert.InsertionStrategy;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.overflow.OverflowTreatment;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split.SplitStrategy;
+import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRTreeSettings;
import de.lmu.ifi.dbs.elki.persistent.PageFile;
+import de.lmu.ifi.dbs.elki.persistent.PageFileFactory;
/**
* Factory for DeLiClu R*-Trees.
@@ -42,32 +40,21 @@ import de.lmu.ifi.dbs.elki.persistent.PageFile;
*
* @param <O> Object type
*/
-public class DeLiCluTreeFactory<O extends NumberVector<?>> extends AbstractRStarTreeFactory<O, DeLiCluNode, DeLiCluEntry, DeLiCluTreeIndex<O>> {
+public class DeLiCluTreeFactory<O extends NumberVector<?>> extends AbstractRStarTreeFactory<O, DeLiCluNode, DeLiCluEntry, DeLiCluTreeIndex<O>, AbstractRTreeSettings> {
/**
* Constructor.
*
- * @param fileName
- * @param pageSize
- * @param cacheSize
- * @param bulkSplitter Bulk loading strategy
- * @param insertionStrategy the strategy to find the insertion child
- * @param nodeSplitter the strategy for splitting nodes.
- * @param overflowTreatment the strategy to use for overflow treatment
- * @param minimumFill the relative minimum fill
+ * @param pageFileFactory Page file factory
+ * @param settings Settings
*/
- public DeLiCluTreeFactory(String fileName, int pageSize, long cacheSize, BulkSplit bulkSplitter, InsertionStrategy insertionStrategy, SplitStrategy nodeSplitter, OverflowTreatment overflowTreatment, double minimumFill) {
- super(fileName, pageSize, cacheSize, bulkSplitter, insertionStrategy, nodeSplitter, overflowTreatment, minimumFill);
+ public DeLiCluTreeFactory(PageFileFactory<?> pageFileFactory, AbstractRTreeSettings settings) {
+ super(pageFileFactory, settings);
}
@Override
public DeLiCluTreeIndex<O> instantiate(Relation<O> relation) {
PageFile<DeLiCluNode> pagefile = makePageFile(getNodeClass());
- DeLiCluTreeIndex<O> index = new DeLiCluTreeIndex<O>(relation, pagefile);
- index.setBulkStrategy(bulkSplitter);
- index.setInsertionStrategy(insertionStrategy);
- index.setNodeSplitStrategy(nodeSplitter);
- index.setOverflowTreatment(overflowTreatment);
- index.setMinimumFill(minimumFill);
+ DeLiCluTreeIndex<O> index = new DeLiCluTreeIndex<>(relation, pagefile, settings);
return index;
}
@@ -82,10 +69,15 @@ public class DeLiCluTreeFactory<O extends NumberVector<?>> extends AbstractRStar
*
* @apiviz.exclude
*/
- public static class Parameterizer<O extends NumberVector<?>> extends AbstractRStarTreeFactory.Parameterizer<O> {
+ public static class Parameterizer<O extends NumberVector<?>> extends AbstractRStarTreeFactory.Parameterizer<O, AbstractRTreeSettings> {
@Override
protected DeLiCluTreeFactory<O> makeInstance() {
- return new DeLiCluTreeFactory<O>(fileName, pageSize, cacheSize, bulkSplitter, insertionStrategy, nodeSplitter, overflowTreatment, minimumFill);
+ return new DeLiCluTreeFactory<>(pageFileFactory, settings);
+ }
+
+ @Override
+ protected AbstractRTreeSettings createSettings() {
+ return new AbstractRTreeSettings();
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluTreeIndex.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluTreeIndex.java
index b1216a51..67c9c9e0 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluTreeIndex.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluTreeIndex.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.deliclu;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -38,10 +38,12 @@ import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.index.DynamicIndex;
import de.lmu.ifi.dbs.elki.index.KNNIndex;
import de.lmu.ifi.dbs.elki.index.RangeIndex;
import de.lmu.ifi.dbs.elki.index.tree.IndexTreePath;
import de.lmu.ifi.dbs.elki.index.tree.TreeIndexPathComponent;
+import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRTreeSettings;
import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.query.RStarTreeUtil;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.persistent.PageFile;
@@ -54,7 +56,7 @@ import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
*
* @param <O> Object type
*/
-public class DeLiCluTreeIndex<O extends NumberVector<?>> extends DeLiCluTree implements KNNIndex<O>, RangeIndex<O> {
+public class DeLiCluTreeIndex<O extends NumberVector<?>> extends DeLiCluTree implements KNNIndex<O>, RangeIndex<O>, DynamicIndex {
/**
* The relation we index.
*/
@@ -65,11 +67,11 @@ public class DeLiCluTreeIndex<O extends NumberVector<?>> extends DeLiCluTree imp
*
* @param relation Relation to index
* @param pagefile Page file
+ * @param settings Tree settings
*/
- public DeLiCluTreeIndex(Relation<O> relation, PageFile<DeLiCluNode> pagefile) {
- super(pagefile);
+ public DeLiCluTreeIndex(Relation<O> relation, PageFile<DeLiCluNode> pagefile, AbstractRTreeSettings settings) {
+ super(pagefile, settings);
this.relation = relation;
- this.initialize();
}
/**
@@ -128,6 +130,12 @@ public class DeLiCluTreeIndex<O extends NumberVector<?>> extends DeLiCluTree imp
return pathToObject.getPath();
}
+ @Override
+ public void initialize() {
+ super.initialize();
+ insertAll(relation.getDBIDs());
+ }
+
/**
* Inserts the specified real vector object into this index.
*
@@ -152,7 +160,7 @@ public class DeLiCluTreeIndex<O extends NumberVector<?>> extends DeLiCluTree imp
// Make an example leaf
if (canBulkLoad()) {
- List<DeLiCluEntry> leafs = new ArrayList<DeLiCluEntry>(ids.size());
+ List<DeLiCluEntry> leafs = new ArrayList<>(ids.size());
for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
leafs.add(createNewLeafEntry(DBIDUtil.deref(iter)));
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/package-info.java
index b6c0af9b..f8bec8cb 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/package-info.java
index 2774fbe1..e50cc513 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/DoubleDistanceRStarTreeKNNQuery.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/DoubleDistanceRStarTreeKNNQuery.java
index 6d539f25..b7769d45 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/DoubleDistanceRStarTreeKNNQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/DoubleDistanceRStarTreeKNNQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.query;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -34,15 +34,14 @@ import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNHeap;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNList;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.AbstractDistanceKNNQuery;
import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDoubleDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceKNNHeap;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceKNNList;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.index.tree.DirectoryEntry;
import de.lmu.ifi.dbs.elki.index.tree.LeafEntry;
@@ -50,7 +49,7 @@ import de.lmu.ifi.dbs.elki.index.tree.query.DoubleDistanceSearchCandidate;
import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry;
import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRStarTree;
import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRStarTreeNode;
-import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.Heap;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.ComparableMinHeap;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
/**
@@ -73,7 +72,7 @@ public class DoubleDistanceRStarTreeKNNQuery<O extends SpatialComparable> extend
/**
* The index to use
*/
- protected final AbstractRStarTree<?, ?> tree;
+ protected final AbstractRStarTree<?, ?, ?> tree;
/**
* Spatial primitive distance function
@@ -87,7 +86,7 @@ public class DoubleDistanceRStarTreeKNNQuery<O extends SpatialComparable> extend
* @param distanceQuery Distance query to use
* @param distanceFunction Distance function
*/
- public DoubleDistanceRStarTreeKNNQuery(AbstractRStarTree<?, ?> tree, DistanceQuery<O, DoubleDistance> distanceQuery, SpatialPrimitiveDoubleDistanceFunction<? super O> distanceFunction) {
+ public DoubleDistanceRStarTreeKNNQuery(AbstractRStarTree<?, ?, ?> tree, DistanceQuery<O, DoubleDistance> distanceQuery, SpatialPrimitiveDoubleDistanceFunction<? super O> distanceFunction) {
super(distanceQuery);
this.tree = tree;
this.distanceFunction = distanceFunction;
@@ -102,7 +101,8 @@ public class DoubleDistanceRStarTreeKNNQuery<O extends SpatialComparable> extend
* @param knnList the knn list containing the result
*/
protected void doKNNQuery(O object, DoubleDistanceKNNHeap knnList) {
- final Heap<DoubleDistanceSearchCandidate> pq = new Heap<DoubleDistanceSearchCandidate>(Math.min(knnList.getK() << 1, 20));
+ final ComparableMinHeap<DoubleDistanceSearchCandidate> pq = new ComparableMinHeap<>(Math.min(knnList.getK() << 1, 21));
+ tree.statistics.countKNNQuery();
// push root
pq.add(new DoubleDistanceSearchCandidate(0.0, tree.getRootID()));
@@ -119,14 +119,14 @@ public class DoubleDistanceRStarTreeKNNQuery<O extends SpatialComparable> extend
}
}
- private double expandNode(O object, DoubleDistanceKNNHeap knnList, final Heap<DoubleDistanceSearchCandidate> pq, double maxDist, final int nodeID) {
+ private double expandNode(O object, DoubleDistanceKNNHeap knnList, final ComparableMinHeap<DoubleDistanceSearchCandidate> pq, double maxDist, final int nodeID) {
AbstractRStarTreeNode<?, ?> node = tree.getNode(nodeID);
// data node
if(node.isLeaf()) {
for(int i = 0; i < node.getNumEntries(); i++) {
SpatialEntry entry = node.getEntry(i);
double distance = distanceFunction.doubleMinDist(entry, object);
- tree.distanceCalcs++;
+ tree.statistics.countDistanceCalculation();
if(distance <= maxDist) {
knnList.add(distance, ((LeafEntry) entry).getDBID());
maxDist = knnList.doubleKNNDistance();
@@ -138,7 +138,7 @@ public class DoubleDistanceRStarTreeKNNQuery<O extends SpatialComparable> extend
for(int i = 0; i < node.getNumEntries(); i++) {
SpatialEntry entry = node.getEntry(i);
double distance = distanceFunction.doubleMinDist(entry, object);
- tree.distanceCalcs++;
+ tree.statistics.countDistanceCalculation();
// Greedy expand, bypassing the queue
if(distance <= 0) {
expandNode(object, knnList, pq, maxDist, ((DirectoryEntry) entry).getPageID());
@@ -169,9 +169,10 @@ public class DoubleDistanceRStarTreeKNNQuery<O extends SpatialComparable> extend
double knn_q_maxDist = knns_q.doubleKNNDistance();
DBID pid = ((LeafEntry) p).getDBID();
- // FIXME: objects are NOT accessible by DBID in a plain rtree context!
+ // FIXME: objects are NOT accessible by DBID in a plain R-tree
+ // context!
double dist_pq = distanceFunction.doubleDistance(relation.get(pid), relation.get(q));
- tree.distanceCalcs++;
+ tree.statistics.countDistanceCalculation();
if(dist_pq <= knn_q_maxDist) {
knns_q.add(dist_pq, pid);
}
@@ -210,14 +211,14 @@ public class DoubleDistanceRStarTreeKNNQuery<O extends SpatialComparable> extend
* @return a list of the sorted entries
*/
protected List<DoubleDistanceEntry> getSortedEntries(AbstractRStarTreeNode<?, ?> node, DBIDs ids) {
- List<DoubleDistanceEntry> result = new ArrayList<DoubleDistanceEntry>();
+ List<DoubleDistanceEntry> result = new ArrayList<>();
for(int i = 0; i < node.getNumEntries(); i++) {
SpatialEntry entry = node.getEntry(i);
double minMinDist = Double.MAX_VALUE;
- for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
+ for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
double minDist = distanceFunction.doubleMinDist(entry, relation.get(iter));
- tree.distanceCalcs++;
+ tree.statistics.countDistanceCalculation();
minMinDist = Math.min(minDist, minMinDist);
}
result.add(new DoubleDistanceEntry(entry, minMinDist));
@@ -268,34 +269,30 @@ public class DoubleDistanceRStarTreeKNNQuery<O extends SpatialComparable> extend
throw new IllegalArgumentException("At least one enumeration has to be requested!");
}
- final DoubleDistanceKNNHeap knnList = new DoubleDistanceKNNHeap(k);
+ final DoubleDistanceKNNHeap knnList = (DoubleDistanceKNNHeap) DBIDUtil.newHeap(DoubleDistance.FACTORY, k);
doKNNQuery(obj, knnList);
return knnList.toKNNList();
}
@Override
- public DoubleDistanceKNNList getKNNForDBID(DBIDRef id, int k) {
- return getKNNForObject(relation.get(id), k);
- }
-
- @Override
public List<DoubleDistanceKNNList> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) {
if(k < 1) {
throw new IllegalArgumentException("At least one enumeration has to be requested!");
}
// While this works, it seems to be slow at least for large sets!
- final Map<DBID, DoubleDistanceKNNHeap> knnLists = new HashMap<DBID, DoubleDistanceKNNHeap>(ids.size());
- for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
+ final Map<DBID, DoubleDistanceKNNHeap> knnLists = new HashMap<>(ids.size());
+ for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
DBID id = DBIDUtil.deref(iter);
- knnLists.put(id, new DoubleDistanceKNNHeap(k));
+ knnLists.put(id, (DoubleDistanceKNNHeap) DBIDUtil.newHeap(DoubleDistance.FACTORY, k));
}
batchNN(tree.getRoot(), knnLists);
- List<DoubleDistanceKNNList> result = new ArrayList<DoubleDistanceKNNList>();
- for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
+ List<DoubleDistanceKNNList> result = new ArrayList<>();
+ for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
DBID id = DBIDUtil.deref(iter);
+ tree.statistics.countKNNQuery();
result.add(knnLists.get(id).toKNNList());
}
return result;
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/DoubleDistanceRStarTreeRangeQuery.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/DoubleDistanceRStarTreeRangeQuery.java
index 715b9552..eb85574f 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/DoubleDistanceRStarTreeRangeQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/DoubleDistanceRStarTreeRangeQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.query;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,19 +24,19 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.query;
*/
import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPairList;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.range.AbstractDistanceRangeQuery;
import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDoubleDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceDBIDList;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.index.tree.DirectoryEntry;
import de.lmu.ifi.dbs.elki.index.tree.LeafEntry;
import de.lmu.ifi.dbs.elki.index.tree.query.DoubleDistanceSearchCandidate;
import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRStarTree;
import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRStarTreeNode;
-import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.Heap;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.ComparableMinHeap;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
/**
@@ -60,7 +60,7 @@ public class DoubleDistanceRStarTreeRangeQuery<O extends SpatialComparable> exte
/**
* The index to use
*/
- protected final AbstractRStarTree<?, ?> tree;
+ protected final AbstractRStarTree<?, ?, ?> tree;
/**
* Spatial primitive distance function
@@ -74,7 +74,7 @@ public class DoubleDistanceRStarTreeRangeQuery<O extends SpatialComparable> exte
* @param distanceQuery Distance query to use
* @param distanceFunction Distance function
*/
- public DoubleDistanceRStarTreeRangeQuery(AbstractRStarTree<?, ?> tree, DistanceQuery<O, DoubleDistance> distanceQuery, SpatialPrimitiveDoubleDistanceFunction<? super O> distanceFunction) {
+ public DoubleDistanceRStarTreeRangeQuery(AbstractRStarTree<?, ?, ?> tree, DistanceQuery<O, DoubleDistance> distanceQuery, SpatialPrimitiveDoubleDistanceFunction<? super O> distanceFunction) {
super(distanceQuery);
this.tree = tree;
this.distanceFunction = distanceFunction;
@@ -88,8 +88,9 @@ public class DoubleDistanceRStarTreeRangeQuery<O extends SpatialComparable> exte
* @return Objects contained in query range.
*/
protected DoubleDistanceDBIDList doRangeQuery(O object, double epsilon) {
- final DoubleDistanceDBIDList result = new DoubleDistanceDBIDList();
- final Heap<DoubleDistanceSearchCandidate> pq = new Heap<DoubleDistanceSearchCandidate>();
+ tree.statistics.countRangeQuery();
+ final DoubleDistanceDBIDPairList result = new DoubleDistanceDBIDPairList();
+ final ComparableMinHeap<DoubleDistanceSearchCandidate> pq = new ComparableMinHeap<>();
// push root
pq.add(new DoubleDistanceSearchCandidate(0.0, tree.getRootID()));
@@ -101,12 +102,12 @@ public class DoubleDistanceRStarTreeRangeQuery<O extends SpatialComparable> exte
break;
}
- AbstractRStarTreeNode<?, ?> node = tree.getNode(pqNode.nodeID.intValue());
+ AbstractRStarTreeNode<?, ?> node = tree.getNode(pqNode.nodeID);
final int numEntries = node.getNumEntries();
for(int i = 0; i < numEntries; i++) {
double distance = distanceFunction.doubleMinDist(object, node.getEntry(i));
- tree.distanceCalcs++;
+ tree.statistics.countDistanceCalculation();
if(distance <= epsilon) {
if(node.isLeaf()) {
LeafEntry entry = (LeafEntry) node.getEntry(i);
@@ -126,12 +127,7 @@ public class DoubleDistanceRStarTreeRangeQuery<O extends SpatialComparable> exte
}
@Override
- public DistanceDBIDResult<DoubleDistance> getRangeForObject(O obj, DoubleDistance range) {
+ public DistanceDBIDList<DoubleDistance> getRangeForObject(O obj, DoubleDistance range) {
return doRangeQuery(obj, range.doubleValue());
}
-
- @Override
- public DistanceDBIDResult<DoubleDistance> getRangeForDBID(DBIDRef id, DoubleDistance range) {
- return getRangeForObject(relation.get(id), range);
- }
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/GenericRStarTreeKNNQuery.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/GenericRStarTreeKNNQuery.java
index ed7f5949..f520d52f 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/GenericRStarTreeKNNQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/GenericRStarTreeKNNQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.query;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -34,27 +34,25 @@ import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNHeap;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.distance.SpatialDistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.AbstractDistanceKNNQuery;
import de.lmu.ifi.dbs.elki.distance.DistanceUtil;
import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNHeap;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNUtil;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.index.tree.DirectoryEntry;
-import de.lmu.ifi.dbs.elki.index.tree.DistanceEntry;
import de.lmu.ifi.dbs.elki.index.tree.LeafEntry;
import de.lmu.ifi.dbs.elki.index.tree.query.GenericDistanceSearchCandidate;
import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry;
import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRStarTree;
import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRStarTreeNode;
-import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.Heap;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.ComparableMinHeap;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.pairs.FCPair;
/**
* Instance of a KNN query for a particular spatial index.
@@ -76,7 +74,7 @@ public class GenericRStarTreeKNNQuery<O extends SpatialComparable, D extends Dis
/**
* The index to use
*/
- protected final AbstractRStarTree<?, ?> tree;
+ protected final AbstractRStarTree<?, ?, ?> tree;
/**
* Spatial primitive distance function
@@ -89,7 +87,7 @@ public class GenericRStarTreeKNNQuery<O extends SpatialComparable, D extends Dis
* @param tree Index to use
* @param distanceQuery Distance query to use
*/
- public GenericRStarTreeKNNQuery(AbstractRStarTree<?, ?> tree, SpatialDistanceQuery<O, D> distanceQuery) {
+ public GenericRStarTreeKNNQuery(AbstractRStarTree<?, ?, ?> tree, SpatialDistanceQuery<O, D> distanceQuery) {
super(distanceQuery);
this.tree = tree;
this.distanceFunction = distanceQuery.getDistanceFunction();
@@ -104,32 +102,33 @@ public class GenericRStarTreeKNNQuery<O extends SpatialComparable, D extends Dis
* @param knnList the knn list containing the result
*/
protected void doKNNQuery(O object, KNNHeap<D> knnList) {
- final Heap<GenericDistanceSearchCandidate<D>> pq = new Heap<GenericDistanceSearchCandidate<D>>(Math.min(knnList.getK() << 1, 20));
+ final ComparableMinHeap<GenericDistanceSearchCandidate<D>> pq = new ComparableMinHeap<>(Math.min(knnList.getK() << 1, 20));
+ tree.statistics.countKNNQuery();
// push root
- pq.add(new GenericDistanceSearchCandidate<D>(distanceFunction.getDistanceFactory().nullDistance(), tree.getRootID()));
+ pq.add(new GenericDistanceSearchCandidate<>(distanceFunction.getDistanceFactory().nullDistance(), tree.getRootID()));
D maxDist = distanceFunction.getDistanceFactory().infiniteDistance();
// search in tree
- while(!pq.isEmpty()) {
+ while (!pq.isEmpty()) {
GenericDistanceSearchCandidate<D> pqNode = pq.poll();
- if(pqNode.mindist.compareTo(maxDist) > 0) {
+ if (pqNode.mindist.compareTo(maxDist) > 0) {
return;
}
maxDist = expandNode(object, knnList, pq, maxDist, pqNode.nodeID);
}
}
- private D expandNode(O object, KNNHeap<D> knnList, final Heap<GenericDistanceSearchCandidate<D>> pq, D maxDist, final int nodeID) {
+ private D expandNode(O object, KNNHeap<D> knnList, final ComparableMinHeap<GenericDistanceSearchCandidate<D>> pq, D maxDist, final int nodeID) {
AbstractRStarTreeNode<?, ?> node = tree.getNode(nodeID);
// data node
- if(node.isLeaf()) {
- for(int i = 0; i < node.getNumEntries(); i++) {
+ if (node.isLeaf()) {
+ for (int i = 0; i < node.getNumEntries(); i++) {
SpatialEntry entry = node.getEntry(i);
D distance = distanceFunction.minDist(entry, object);
- tree.distanceCalcs++;
- if(distance.compareTo(maxDist) <= 0) {
+ tree.statistics.countDistanceCalculation();
+ if (distance.compareTo(maxDist) <= 0) {
knnList.add(distance, ((LeafEntry) entry).getDBID());
maxDist = knnList.getKNNDistance();
}
@@ -137,17 +136,16 @@ public class GenericRStarTreeKNNQuery<O extends SpatialComparable, D extends Dis
}
// directory node
else {
- for(int i = 0; i < node.getNumEntries(); i++) {
+ for (int i = 0; i < node.getNumEntries(); i++) {
SpatialEntry entry = node.getEntry(i);
D distance = distanceFunction.minDist(entry, object);
- tree.distanceCalcs++;
+ tree.statistics.countDistanceCalculation();
// Greedy expand, bypassing the queue
- if(distance.isNullDistance()) {
+ if (distance.isNullDistance()) {
expandNode(object, knnList, pq, maxDist, ((DirectoryEntry) entry).getPageID());
- }
- else {
- if(distance.compareTo(maxDist) <= 0) {
- pq.add(new GenericDistanceSearchCandidate<D>(distance, ((DirectoryEntry) entry).getPageID()));
+ } else {
+ if (distance.compareTo(maxDist) <= 0) {
+ pq.add(new GenericDistanceSearchCandidate<>(distance, ((DirectoryEntry) entry).getPageID()));
}
}
}
@@ -162,10 +160,10 @@ public class GenericRStarTreeKNNQuery<O extends SpatialComparable, D extends Dis
* @param knnLists a map containing the knn lists for each query objects
*/
protected void batchNN(AbstractRStarTreeNode<?, ?> node, Map<DBID, KNNHeap<D>> knnLists) {
- if(node.isLeaf()) {
- for(int i = 0; i < node.getNumEntries(); i++) {
+ if (node.isLeaf()) {
+ for (int i = 0; i < node.getNumEntries(); i++) {
SpatialEntry p = node.getEntry(i);
- for(Entry<DBID, KNNHeap<D>> ent : knnLists.entrySet()) {
+ for (Entry<DBID, KNNHeap<D>> ent : knnLists.entrySet()) {
final DBID q = ent.getKey();
final KNNHeap<D> knns_q = ent.getValue();
D knn_q_maxDist = knns_q.getKNNDistance();
@@ -173,26 +171,26 @@ public class GenericRStarTreeKNNQuery<O extends SpatialComparable, D extends Dis
DBID pid = ((LeafEntry) p).getDBID();
// FIXME: objects are NOT accessible by DBID in a plain rtree context!
D dist_pq = distanceQuery.distance(pid, q);
- if(dist_pq.compareTo(knn_q_maxDist) <= 0) {
+ tree.statistics.countDistanceCalculation();
+ if (dist_pq.compareTo(knn_q_maxDist) <= 0) {
knns_q.add(dist_pq, pid);
}
}
}
- }
- else {
+ } else {
ModifiableDBIDs ids = DBIDUtil.newArray(knnLists.size());
- for(DBID id : knnLists.keySet()) {
+ for (DBID id : knnLists.keySet()) {
ids.add(id);
}
- List<DistanceEntry<D, SpatialEntry>> entries = getSortedEntries(node, ids);
- for(DistanceEntry<D, SpatialEntry> distEntry : entries) {
- D minDist = distEntry.getDistance();
- for(Entry<DBID, KNNHeap<D>> ent : knnLists.entrySet()) {
+ List<FCPair<D, SpatialEntry>> entries = getSortedEntries(node, ids);
+ for (FCPair<D, SpatialEntry> distEntry : entries) {
+ D minDist = distEntry.first;
+ for (Entry<DBID, KNNHeap<D>> ent : knnLists.entrySet()) {
final KNNHeap<D> knns_q = ent.getValue();
D knn_q_maxDist = knns_q.getKNNDistance();
- if(minDist.compareTo(knn_q_maxDist) <= 0) {
- SpatialEntry entry = distEntry.getEntry();
+ if (minDist.compareTo(knn_q_maxDist) <= 0) {
+ SpatialEntry entry = distEntry.second;
AbstractRStarTreeNode<?, ?> child = tree.getNode(((DirectoryEntry) entry).getPageID().intValue());
batchNN(child, knnLists);
break;
@@ -210,17 +208,18 @@ public class GenericRStarTreeKNNQuery<O extends SpatialComparable, D extends Dis
* @param ids the id of the objects
* @return a list of the sorted entries
*/
- protected List<DistanceEntry<D, SpatialEntry>> getSortedEntries(AbstractRStarTreeNode<?, ?> node, DBIDs ids) {
- List<DistanceEntry<D, SpatialEntry>> result = new ArrayList<DistanceEntry<D, SpatialEntry>>();
+ protected List<FCPair<D, SpatialEntry>> getSortedEntries(AbstractRStarTreeNode<?, ?> node, DBIDs ids) {
+ List<FCPair<D, SpatialEntry>> result = new ArrayList<>();
- for(int i = 0; i < node.getNumEntries(); i++) {
+ for (int i = 0; i < node.getNumEntries(); i++) {
SpatialEntry entry = node.getEntry(i);
D minMinDist = distanceQuery.getDistanceFactory().infiniteDistance();
for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
D minDist = distanceFunction.minDist(entry, relation.get(iter));
+ tree.statistics.countDistanceCalculation();
minMinDist = DistanceUtil.min(minDist, minMinDist);
}
- result.add(new DistanceEntry<D, SpatialEntry>(entry, minMinDist, i));
+ result.add(new FCPair<>(minMinDist, entry));
}
Collections.sort(result);
@@ -228,38 +227,27 @@ public class GenericRStarTreeKNNQuery<O extends SpatialComparable, D extends Dis
}
@Override
- public KNNResult<D> getKNNForObject(O obj, int k) {
- if(k < 1) {
- throw new IllegalArgumentException("At least one enumeration has to be requested!");
- }
-
- final KNNHeap<D> knnList = KNNUtil.newHeap(distanceFunction, k);
+ public KNNList<D> getKNNForObject(O obj, int k) {
+ final KNNHeap<D> knnList = DBIDUtil.newHeap(distanceFunction.getDistanceFactory(), k);
doKNNQuery(obj, knnList);
return knnList.toKNNList();
}
@Override
- public KNNResult<D> getKNNForDBID(DBIDRef id, int k) {
- return getKNNForObject(relation.get(id), k);
- }
-
- @Override
- public List<KNNResult<D>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) {
- if(k < 1) {
- throw new IllegalArgumentException("At least one enumeration has to be requested!");
- }
+ public List<KNNList<D>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) {
// While this works, it seems to be slow at least for large sets!
- final Map<DBID, KNNHeap<D>> knnLists = new HashMap<DBID, KNNHeap<D>>(ids.size());
+ final Map<DBID, KNNHeap<D>> knnLists = new HashMap<>(ids.size());
for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
- knnLists.put(DBIDUtil.deref(iter), KNNUtil.newHeap(distanceFunction, k));
+ knnLists.put(DBIDUtil.deref(iter), DBIDUtil.newHeap(distanceFunction.getDistanceFactory(), k));
}
batchNN(tree.getRoot(), knnLists);
- List<KNNResult<D>> result = new ArrayList<KNNResult<D>>();
+ List<KNNList<D>> result = new ArrayList<>();
for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
+ tree.statistics.countKNNQuery();
result.add(knnLists.get(DBIDUtil.deref(iter)).toKNNList());
}
return result;
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/GenericRStarTreeRangeQuery.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/GenericRStarTreeRangeQuery.java
index a5232b30..16a3393a 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/GenericRStarTreeRangeQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/GenericRStarTreeRangeQuery.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.query;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,19 +24,18 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.query;
*/
import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.generic.GenericDistanceDBIDList;
import de.lmu.ifi.dbs.elki.database.query.distance.SpatialDistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.range.AbstractDistanceRangeQuery;
import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.GenericDistanceDBIDList;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.index.tree.DirectoryEntry;
import de.lmu.ifi.dbs.elki.index.tree.LeafEntry;
import de.lmu.ifi.dbs.elki.index.tree.query.GenericDistanceSearchCandidate;
import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRStarTree;
import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRStarTreeNode;
-import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.Heap;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.ComparableMinHeap;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
/**
@@ -60,7 +59,7 @@ public class GenericRStarTreeRangeQuery<O extends SpatialComparable, D extends D
/**
* The index to use
*/
- protected final AbstractRStarTree<?, ?> tree;
+ protected final AbstractRStarTree<?, ?, ?> tree;
/**
* Spatial primitive distance function
@@ -73,7 +72,7 @@ public class GenericRStarTreeRangeQuery<O extends SpatialComparable, D extends D
* @param tree Index to use
* @param distanceQuery Distance query to use
*/
- public GenericRStarTreeRangeQuery(AbstractRStarTree<?, ?> tree, SpatialDistanceQuery<O, D> distanceQuery) {
+ public GenericRStarTreeRangeQuery(AbstractRStarTree<?, ?, ?> tree, SpatialDistanceQuery<O, D> distanceQuery) {
super(distanceQuery);
this.tree = tree;
this.distanceFunction = distanceQuery.getDistanceFunction();
@@ -86,12 +85,13 @@ public class GenericRStarTreeRangeQuery<O extends SpatialComparable, D extends D
* @param epsilon Query range
* @return Objects contained in query range.
*/
- protected DistanceDBIDResult<D> doRangeQuery(O object, D epsilon) {
- final GenericDistanceDBIDList<D> result = new GenericDistanceDBIDList<D>();
- final Heap<GenericDistanceSearchCandidate<D>> pq = new Heap<GenericDistanceSearchCandidate<D>>();
+ protected DistanceDBIDList<D> doRangeQuery(O object, D epsilon) {
+ final GenericDistanceDBIDList<D> result = new GenericDistanceDBIDList<>();
+ final ComparableMinHeap<GenericDistanceSearchCandidate<D>> pq = new ComparableMinHeap<>();
+ tree.statistics.countRangeQuery();
// push root
- pq.add(new GenericDistanceSearchCandidate<D>(distanceFunction.getDistanceFactory().nullDistance(), tree.getRootID()));
+ pq.add(new GenericDistanceSearchCandidate<>(distanceFunction.getDistanceFactory().nullDistance(), tree.getRootID()));
// search in tree
while(!pq.isEmpty()) {
@@ -100,11 +100,12 @@ public class GenericRStarTreeRangeQuery<O extends SpatialComparable, D extends D
break;
}
- AbstractRStarTreeNode<?, ?> node = tree.getNode(pqNode.nodeID.intValue());
+ AbstractRStarTreeNode<?, ?> node = tree.getNode(pqNode.nodeID);
final int numEntries = node.getNumEntries();
for(int i = 0; i < numEntries; i++) {
D distance = distanceFunction.minDist(node.getEntry(i), object);
+ tree.statistics.countDistanceCalculation();
if(distance.compareTo(epsilon) <= 0) {
if(node.isLeaf()) {
LeafEntry entry = (LeafEntry) node.getEntry(i);
@@ -112,7 +113,7 @@ public class GenericRStarTreeRangeQuery<O extends SpatialComparable, D extends D
}
else {
DirectoryEntry entry = (DirectoryEntry) node.getEntry(i);
- pq.add(new GenericDistanceSearchCandidate<D>(distance, entry.getEntryID()));
+ pq.add(new GenericDistanceSearchCandidate<>(distance, entry.getEntryID()));
}
}
}
@@ -124,12 +125,7 @@ public class GenericRStarTreeRangeQuery<O extends SpatialComparable, D extends D
}
@Override
- public DistanceDBIDResult<D> getRangeForObject(O obj, D range) {
+ public DistanceDBIDList<D> getRangeForObject(O obj, D range) {
return doRangeQuery(obj, range);
}
-
- @Override
- public DistanceDBIDResult<D> getRangeForDBID(DBIDRef id, D range) {
- return getRangeForObject(relation.get(id), range);
- }
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/RStarTreeUtil.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/RStarTreeUtil.java
index 477e3a36..46c814ee 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/RStarTreeUtil.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/RStarTreeUtil.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.query;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -62,17 +62,17 @@ public final class RStarTreeUtil {
* @return Query object
*/
@SuppressWarnings({ "cast", "unchecked" })
- public static <O extends SpatialComparable, D extends Distance<D>> RangeQuery<O, D> getRangeQuery(AbstractRStarTree<?, ?> tree, SpatialDistanceQuery<O, D> distanceQuery, Object... hints) {
+ public static <O extends SpatialComparable, D extends Distance<D>> RangeQuery<O, D> getRangeQuery(AbstractRStarTree<?, ?, ?> tree, SpatialDistanceQuery<O, D> distanceQuery, Object... hints) {
// Can we support this distance function - spatial distances only!
SpatialPrimitiveDistanceFunction<? super O, D> df = distanceQuery.getDistanceFunction();
// Can we use an optimized query?
if(df instanceof SpatialPrimitiveDoubleDistanceFunction) {
DistanceQuery<O, DoubleDistance> dqc = (DistanceQuery<O, DoubleDistance>) DistanceQuery.class.cast(distanceQuery);
SpatialPrimitiveDoubleDistanceFunction<? super O> dfc = (SpatialPrimitiveDoubleDistanceFunction<? super O>) SpatialPrimitiveDoubleDistanceFunction.class.cast(df);
- RangeQuery<O, ?> q = new DoubleDistanceRStarTreeRangeQuery<O>(tree, dqc, dfc);
+ RangeQuery<O, ?> q = new DoubleDistanceRStarTreeRangeQuery<>(tree, dqc, dfc);
return (RangeQuery<O, D>) q;
}
- return new GenericRStarTreeRangeQuery<O, D>(tree, distanceQuery);
+ return new GenericRStarTreeRangeQuery<>(tree, distanceQuery);
}
/**
@@ -87,16 +87,16 @@ public final class RStarTreeUtil {
* @return Query object
*/
@SuppressWarnings({ "cast", "unchecked" })
- public static <O extends SpatialComparable, D extends Distance<D>> KNNQuery<O, D> getKNNQuery(AbstractRStarTree<?, ?> tree, SpatialDistanceQuery<O, D> distanceQuery, Object... hints) {
+ public static <O extends SpatialComparable, D extends Distance<D>> KNNQuery<O, D> getKNNQuery(AbstractRStarTree<?, ?, ?> tree, SpatialDistanceQuery<O, D> distanceQuery, Object... hints) {
// Can we support this distance function - spatial distances only!
SpatialPrimitiveDistanceFunction<? super O, D> df = distanceQuery.getDistanceFunction();
// Can we use an optimized query?
if(df instanceof SpatialPrimitiveDoubleDistanceFunction) {
DistanceQuery<O, DoubleDistance> dqc = (DistanceQuery<O, DoubleDistance>) DistanceQuery.class.cast(distanceQuery);
SpatialPrimitiveDoubleDistanceFunction<? super O> dfc = (SpatialPrimitiveDoubleDistanceFunction<? super O>) SpatialPrimitiveDoubleDistanceFunction.class.cast(df);
- KNNQuery<O, ?> q = new DoubleDistanceRStarTreeKNNQuery<O>(tree, dqc, dfc);
+ KNNQuery<O, ?> q = new DoubleDistanceRStarTreeKNNQuery<>(tree, dqc, dfc);
return (KNNQuery<O, D>) q;
}
- return new GenericRStarTreeKNNQuery<O, D>(tree, distanceQuery);
+ return new GenericRStarTreeKNNQuery<>(tree, distanceQuery);
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/package-info.java
index 0b47cab0..69bcd3d0 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTree.java
index d63d77cb..1c2a7fe8 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTree.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTree.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rstar;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,6 +25,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rstar;
import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialDirectoryEntry;
import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry;
+import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRTreeSettings;
import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.NonFlatRStarTree;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.persistent.PageFile;
@@ -44,7 +45,7 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
@Title("R*-Tree")
@Description("Balanced index structure based on bounding rectangles.")
@Reference(authors = "N. Beckmann, H.-P. Kriegel, R. Schneider, B. Seeger", title = "The R*-tree: an efficient and robust access method for points and rectangles", booktitle = "Proceedings of the 1990 ACM SIGMOD International Conference on Management of Data, Atlantic City, NJ, May 23-25, 1990", url = "http://dx.doi.org/10.1145/93597.98741")
-public class RStarTree extends NonFlatRStarTree<RStarTreeNode, SpatialEntry> {
+public class RStarTree extends NonFlatRStarTree<RStarTreeNode, SpatialEntry, AbstractRTreeSettings> {
/**
* The logger for this class.
*/
@@ -54,9 +55,10 @@ public class RStarTree extends NonFlatRStarTree<RStarTreeNode, SpatialEntry> {
* Constructor.
*
* @param pagefile Page file
+ * @param settings Settings class
*/
- public RStarTree(PageFile<RStarTreeNode> pagefile) {
- super(pagefile);
+ public RStarTree(PageFile<RStarTreeNode> pagefile, AbstractRTreeSettings settings) {
+ super(pagefile, settings);
}
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTreeFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTreeFactory.java
index da7c03fd..72f7f7dd 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTreeFactory.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTreeFactory.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rstar;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,11 +27,10 @@ import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry;
import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRStarTreeFactory;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk.BulkSplit;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert.InsertionStrategy;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.overflow.OverflowTreatment;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split.SplitStrategy;
+import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRTreeSettings;
import de.lmu.ifi.dbs.elki.persistent.PageFile;
+import de.lmu.ifi.dbs.elki.persistent.PageFileFactory;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
/**
* Factory for regular R*-Trees.
@@ -43,33 +42,22 @@ import de.lmu.ifi.dbs.elki.persistent.PageFile;
*
* @param <O> Object type
*/
-public class RStarTreeFactory<O extends NumberVector<?>> extends AbstractRStarTreeFactory<O, RStarTreeNode, SpatialEntry, RStarTreeIndex<O>> {
+@Alias({"rstar", "r*"})
+public class RStarTreeFactory<O extends NumberVector<?>> extends AbstractRStarTreeFactory<O, RStarTreeNode, SpatialEntry, RStarTreeIndex<O>, AbstractRTreeSettings> {
/**
* Constructor.
*
- * @param fileName
- * @param pageSize
- * @param cacheSize
- * @param bulkSplitter Bulk loading strategy
- * @param insertionStrategy the strategy to find the insertion child
- * @param nodeSplitter the strategy for splitting nodes.
- * @param overflowTreatment the strategy to use for overflow treatment
- * @param minimumFill the relative minimum fill
+ * @param pageFileFactory Data storage
+ * @param settings Tree settings
*/
- public RStarTreeFactory(String fileName, int pageSize, long cacheSize, BulkSplit bulkSplitter, InsertionStrategy insertionStrategy, SplitStrategy nodeSplitter, OverflowTreatment overflowTreatment, double minimumFill) {
- super(fileName, pageSize, cacheSize, bulkSplitter, insertionStrategy, nodeSplitter, overflowTreatment, minimumFill);
+ public RStarTreeFactory(PageFileFactory<?> pageFileFactory, AbstractRTreeSettings settings) {
+ super(pageFileFactory, settings);
}
@Override
public RStarTreeIndex<O> instantiate(Relation<O> relation) {
PageFile<RStarTreeNode> pagefile = makePageFile(getNodeClass());
- RStarTreeIndex<O> index = new RStarTreeIndex<O>(relation, pagefile);
- index.setBulkStrategy(bulkSplitter);
- index.setInsertionStrategy(insertionStrategy);
- index.setNodeSplitStrategy(nodeSplitter);
- index.setOverflowTreatment(overflowTreatment);
- index.setMinimumFill(minimumFill);
- return index;
+ return new RStarTreeIndex<>(relation, pagefile, settings);
}
protected Class<RStarTreeNode> getNodeClass() {
@@ -82,11 +70,18 @@ public class RStarTreeFactory<O extends NumberVector<?>> extends AbstractRStarTr
* @author Erich Schubert
*
* @apiviz.exclude
+ *
+ * @param <O> Object type
*/
- public static class Parameterizer<O extends NumberVector<?>> extends AbstractRStarTreeFactory.Parameterizer<O> {
+ public static class Parameterizer<O extends NumberVector<?>> extends AbstractRStarTreeFactory.Parameterizer<O, AbstractRTreeSettings> {
@Override
protected RStarTreeFactory<O> makeInstance() {
- return new RStarTreeFactory<O>(fileName, pageSize, cacheSize, bulkSplitter, insertionStrategy, nodeSplitter, overflowTreatment, minimumFill);
+ return new RStarTreeFactory<>(pageFileFactory, settings);
+ }
+
+ @Override
+ protected AbstractRTreeSettings createSettings() {
+ return new AbstractRTreeSettings();
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTreeIndex.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTreeIndex.java
index 1946293f..15b43e64 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTreeIndex.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTreeIndex.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rstar;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -37,11 +37,13 @@ import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.index.DynamicIndex;
import de.lmu.ifi.dbs.elki.index.KNNIndex;
import de.lmu.ifi.dbs.elki.index.RangeIndex;
import de.lmu.ifi.dbs.elki.index.tree.IndexTreePath;
import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry;
import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialPointLeafEntry;
+import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRTreeSettings;
import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.query.RStarTreeUtil;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.persistent.PageFile;
@@ -53,7 +55,7 @@ import de.lmu.ifi.dbs.elki.persistent.PageFile;
*
* @param <O> Object type
*/
-public class RStarTreeIndex<O extends NumberVector<?>> extends RStarTree implements RangeIndex<O>, KNNIndex<O> {
+public class RStarTreeIndex<O extends NumberVector<?>> extends RStarTree implements RangeIndex<O>, KNNIndex<O>, DynamicIndex {
/**
* The appropriate logger for this index.
*/
@@ -69,11 +71,11 @@ public class RStarTreeIndex<O extends NumberVector<?>> extends RStarTree impleme
*
* @param relation Relation to index
* @param pagefile Page file
+ * @param settings Tree settings
*/
- public RStarTreeIndex(Relation<O> relation, PageFile<RStarTreeNode> pagefile) {
- super(pagefile);
+ public RStarTreeIndex(Relation<O> relation, PageFile<RStarTreeNode> pagefile, AbstractRTreeSettings settings) {
+ super(pagefile, settings);
this.relation = relation;
- this.initialize();
}
/**
@@ -86,6 +88,12 @@ public class RStarTreeIndex<O extends NumberVector<?>> extends RStarTree impleme
return new SpatialPointLeafEntry(DBIDUtil.deref(id), relation.get(id));
}
+ @Override
+ public void initialize() {
+ super.initialize();
+ insertAll(relation.getDBIDs()); // Will check for actual bulk load!
+ }
+
/**
* Inserts the specified reel vector object into this index.
*
@@ -110,7 +118,7 @@ public class RStarTreeIndex<O extends NumberVector<?>> extends RStarTree impleme
// Make an example leaf
if(canBulkLoad()) {
- List<SpatialEntry> leafs = new ArrayList<SpatialEntry>(ids.size());
+ List<SpatialEntry> leafs = new ArrayList<>(ids.size());
for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
leafs.add(createNewLeafEntry(iter));
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTreeNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTreeNode.java
index b51d191a..7226fa1c 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTreeNode.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTreeNode.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rstar;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/package-info.java
index e15569c5..7897fae1 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/AbstractBulkSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/AbstractBulkSplit.java
index 4a0304f1..7d463a03 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/AbstractBulkSplit.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/AbstractBulkSplit.java
@@ -7,7 +7,7 @@ import java.util.List;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -75,7 +75,7 @@ public abstract class AbstractBulkSplit implements BulkSplit {
// build partitions
final int size = objects.size();
final int numberPartitions = (int) Math.ceil(((double) size) / maxEntries);
- List<List<T>> partitions = new ArrayList<List<T>>(numberPartitions);
+ List<List<T>> partitions = new ArrayList<>(numberPartitions);
int start = 0;
for(int pnum = 0; pnum < numberPartitions; pnum++) {
int end = (int) ((pnum + 1.) * size / numberPartitions);
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/AdaptiveSortTileRecursiveBulkSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/AdaptiveSortTileRecursiveBulkSplit.java
new file mode 100644
index 00000000..fbbf7d8f
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/AdaptiveSortTileRecursiveBulkSplit.java
@@ -0,0 +1,151 @@
+package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialSingleMeanComparator;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.QuickSelect;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * This is variation of the original STR bulk load for non-rectangular data
+ * spaces. Instead of iterating through the dimensions and splitting each by
+ * (approximately) the same factor, this variation tries to adjust the factor to
+ * the extends of the data space. I.e. if the data set is twice as wide as high,
+ * this should produce twice as many partitions on the X than on the Y axis.
+ *
+ * Whether or not this offers benefits greatly depends on the distance queries
+ * used. But for symmetric distances, the resulting pages should be more
+ * rectangular, which often is beneficial.
+ *
+ * See {@link SortTileRecursiveBulkSplit} for the original STR bulk load.
+ *
+ * @author Erich Schubert
+ */
+public class AdaptiveSortTileRecursiveBulkSplit extends AbstractBulkSplit {
+ /**
+ * Static instance.
+ */
+ public static final AdaptiveSortTileRecursiveBulkSplit STATIC = new AdaptiveSortTileRecursiveBulkSplit();
+
+ @Override
+ public <T extends SpatialComparable> List<List<T>> partition(List<T> spatialObjects, int minEntries, int maxEntries) {
+ final int dims = spatialObjects.get(0).getDimensionality();
+ final int p = (int) Math.ceil(spatialObjects.size() / (double) maxEntries);
+ List<List<T>> ret = new ArrayList<>(p);
+ strPartition(spatialObjects, 0, spatialObjects.size(), 0, dims, maxEntries, new SpatialSingleMeanComparator(0), ret);
+ return ret;
+ }
+
+ /**
+ * Recursively partition.
+ *
+ * @param objs Object list
+ * @param start Subinterval start
+ * @param end Subinterval end
+ * @param depth Iteration depth (must be less than dimensionality!)
+ * @param dims Total number of dimensions
+ * @param maxEntries Maximum page size
+ * @param c Comparison helper
+ * @param ret Output list
+ * @param <T> data type
+ */
+ protected <T extends SpatialComparable> void strPartition(List<T> objs, int start, int end, int depth, int dims, int maxEntries, SpatialSingleMeanComparator c, List<List<T>> ret) {
+ final int p = (int) Math.ceil((end - start) / (double) maxEntries);
+
+ // Compute min and max:
+ double[] mm = new double[dims * 2];
+ for (int d = 0; d < mm.length; d += 2) {
+ mm[d] = Double.POSITIVE_INFINITY; // min <- +inf
+ mm[d + 1] = Double.NEGATIVE_INFINITY; // max <- -inf
+ }
+ for (int i = start; i < end; i++) {
+ T o = objs.get(i);
+ for (int d1 = 0, d2 = 0; d2 < mm.length; d1++, d2 += 2) {
+ mm[d2] = Math.min(mm[d2], o.getMin(d1));
+ mm[d2 + 1] = Math.max(mm[d2 + 1], o.getMax(d1));
+ }
+ }
+ // Find maximum and compute extends
+ double maxex = 0.0;
+ int sdim = depth;
+ double[] exts = new double[dims];
+ for (int d = 0; d < mm.length; d += 2) {
+ final double extend = mm[d + 1] - mm[d];
+ if (extend > maxex) {
+ maxex = extend;
+ sdim = d >>> 1;
+ }
+ exts[d >>> 1] = extend;
+ }
+ // Compute sum of the k largest extends:
+ Arrays.sort(exts);
+ double extsum = 0.;
+ for (int d = depth; d < exts.length; d++) {
+ extsum += exts[d];
+ }
+ // Chose the number of partitions:
+ final int s;
+ if (maxex > 0. && depth + 1 < dims) {
+ s = (int) Math.ceil(Math.pow(p, 1.0 / (dims - depth)) * (dims - depth) * maxex / extsum);
+ } else {
+ s = (int) Math.ceil(Math.pow(p, 1.0 / (dims - depth)));
+ }
+
+ final double len = end - start; // double intentional!
+ for (int i = 0; i < s; i++) {
+ // We don't completely sort, but only ensure the quantile is invariant.
+ int s2 = start + (int) ((i * len) / s);
+ int e2 = start + (int) (((i + 1) * len) / s);
+ // LoggingUtil.warning("STR " + dim + " s2:" + s2 + " e2:" + e2);
+ if (e2 < end) {
+ c.setDimension(sdim);
+ QuickSelect.quickSelect(objs, c, s2, end, e2);
+ }
+ if (depth + 1 == dims) {
+ ret.add(objs.subList(s2, e2));
+ } else {
+ // Descend
+ strPartition(objs, s2, e2, depth + 1, dims, maxEntries, c, ret);
+ }
+ }
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected AdaptiveSortTileRecursiveBulkSplit makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/BulkSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/BulkSplit.java
index 1eb88f7c..c32a512c 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/BulkSplit.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/BulkSplit.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/FileOrderBulkSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/FileOrderBulkSplit.java
index 308c70cb..8b0dfd77 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/FileOrderBulkSplit.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/FileOrderBulkSplit.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/MaxExtensionBulkSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/MaxExtensionBulkSplit.java
index 2fd69531..5251e18b 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/MaxExtensionBulkSplit.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/MaxExtensionBulkSplit.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,7 +29,7 @@ import java.util.Collections;
import java.util.List;
import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.SpatialComparator;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialSingleMinComparator;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
@@ -39,14 +39,14 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
*
* @author Elke Achtert
*
- * @apiviz.uses SpatialComparator
+ * @apiviz.composedOf SpatialSingleMinComparator
*/
public class MaxExtensionBulkSplit extends AbstractBulkSplit {
/**
* Logger.
*/
private static final Logging LOG = Logging.getLogger(MaxExtensionBulkSplit.class);
-
+
/**
* Static instance
*/
@@ -70,40 +70,40 @@ public class MaxExtensionBulkSplit extends AbstractBulkSplit {
*/
@Override
public <N extends SpatialComparable> List<List<N>> partition(List<N> spatialObjects, int minEntries, int maxEntries) {
- List<List<N>> partitions = new ArrayList<List<N>>();
- List<N> objects = new ArrayList<N>(spatialObjects);
+ List<List<N>> partitions = new ArrayList<>();
+ List<N> objects = new ArrayList<>(spatialObjects);
- while(objects.size() > 0) {
+ while (objects.size() > 0) {
StringBuilder msg = new StringBuilder();
// get the split axis and split point
int splitAxis = chooseMaximalExtendedSplitAxis(objects);
int splitPoint = chooseBulkSplitPoint(objects.size(), minEntries, maxEntries);
- if(LOG.isDebugging()) {
+ if (LOG.isDebugging()) {
msg.append("\nsplitAxis ").append(splitAxis);
msg.append("\nsplitPoint ").append(splitPoint);
}
// sort in the right dimension
- Collections.sort(objects, new SpatialComparator(splitAxis, SpatialComparator.MIN));
+ Collections.sort(objects, new SpatialSingleMinComparator(splitAxis));
// insert into partition
- List<N> partition1 = new ArrayList<N>();
- for(int i = 0; i < splitPoint; i++) {
+ List<N> partition1 = new ArrayList<>();
+ for (int i = 0; i < splitPoint; i++) {
N o = objects.remove(0);
partition1.add(o);
}
partitions.add(partition1);
// copy array
- if(LOG.isDebugging()) {
+ if (LOG.isDebugging()) {
msg.append("\ncurrent partition ").append(partition1);
msg.append("\nremaining objects # ").append(objects.size());
LOG.debugFine(msg.toString());
}
}
- if(LOG.isDebugging()) {
+ if (LOG.isDebugging()) {
LOG.debugFine("partitions " + partitions);
}
return partitions;
@@ -124,17 +124,17 @@ public class MaxExtensionBulkSplit extends AbstractBulkSplit {
Arrays.fill(minExtension, Double.MAX_VALUE);
// compute min and max value in each dimension
- for(SpatialComparable object : objects) {
- for(int d = 0; d < dimension; d++) {
+ for (SpatialComparable object : objects) {
+ for (int d = 0; d < dimension; d++) {
double min, max;
min = object.getMin(d);
max = object.getMax(d);
- if(maxExtension[d] < max) {
+ if (maxExtension[d] < max) {
maxExtension[d] = max;
}
- if(minExtension[d] > min) {
+ if (minExtension[d] > min) {
minExtension[d] = min;
}
}
@@ -143,9 +143,9 @@ public class MaxExtensionBulkSplit extends AbstractBulkSplit {
// set split axis to dim with maximal extension
int splitAxis = -1;
double max = 0;
- for(int d = 0; d < dimension; d++) {
+ for (int d = 0; d < dimension; d++) {
double currentExtension = maxExtension[d] - minExtension[d];
- if(max < currentExtension) {
+ if (max < currentExtension) {
max = currentExtension;
splitAxis = d;
}
@@ -166,4 +166,4 @@ public class MaxExtensionBulkSplit extends AbstractBulkSplit {
return MaxExtensionBulkSplit.STATIC;
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/MaxExtensionSortTileRecursiveBulkSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/MaxExtensionSortTileRecursiveBulkSplit.java
new file mode 100644
index 00000000..6bf37642
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/MaxExtensionSortTileRecursiveBulkSplit.java
@@ -0,0 +1,134 @@
+package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import java.util.ArrayList;
+import java.util.List;
+
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialSingleMeanComparator;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.QuickSelect;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * This is variation of the {@link SortTileRecursiveBulkSplit}, incorporating
+ * some ideas from {@link MaxExtensionBulkSplit}. Instead of iterating through
+ * the axes in order, it always chooses the axis with the largest extend. This
+ * may rarely lead to the data being split on the same axis twice, but most
+ * importantly it varies the splitting order compared to STR.
+ *
+ * {@link AdaptiveSortTileRecursiveBulkSplit} takes these ideas one step
+ * further, by also varying the fan-out degree.
+ *
+ * @author Erich Schubert
+ */
+public class MaxExtensionSortTileRecursiveBulkSplit extends AbstractBulkSplit {
+ /**
+ * Static instance.
+ */
+ public static final MaxExtensionSortTileRecursiveBulkSplit STATIC = new MaxExtensionSortTileRecursiveBulkSplit();
+
+ @Override
+ public <T extends SpatialComparable> List<List<T>> partition(List<T> spatialObjects, int minEntries, int maxEntries) {
+ final int dims = spatialObjects.get(0).getDimensionality();
+ final int p = (int) Math.ceil(spatialObjects.size() / (double) maxEntries);
+ List<List<T>> ret = new ArrayList<>(p);
+ strPartition(spatialObjects, 0, spatialObjects.size(), 0, dims, maxEntries, new SpatialSingleMeanComparator(0), ret);
+ return ret;
+ }
+
+ /**
+ * Recursively partition.
+ *
+ * @param objs Object list
+ * @param start Subinterval start
+ * @param end Subinterval end
+ * @param depth Iteration depth (must be less than dimensionality!)
+ * @param dims Total number of dimensions
+ * @param maxEntries Maximum page size
+ * @param c Comparison helper
+ * @param ret Output list
+ * @param <T> data type
+ */
+ protected <T extends SpatialComparable> void strPartition(List<T> objs, int start, int end, int depth, int dims, int maxEntries, SpatialSingleMeanComparator c, List<List<T>> ret) {
+ final int p = (int) Math.ceil((end - start) / (double) maxEntries);
+
+ // Compute min and max:
+ double[] mm = new double[dims * 2];
+ for (int d = 0; d < mm.length; d += 2) {
+ mm[d] = Double.POSITIVE_INFINITY; // min <- +inf
+ mm[d + 1] = Double.NEGATIVE_INFINITY; // max <- -inf
+ }
+ for (int i = start; i < end; i++) {
+ T o = objs.get(i);
+ for (int d1 = 0, d2 = 0; d2 < mm.length; d1++, d2 += 2) {
+ mm[d2] = Math.min(mm[d2], o.getMin(d1));
+ mm[d2 + 1] = Math.max(mm[d2 + 1], o.getMax(d1));
+ }
+ }
+ // Find maximum and compute extends
+ double maxex = 0.0;
+ int sdim = -1;
+ for (int d = 0; d < mm.length; d += 2) {
+ final double extend = mm[d + 1] - mm[d];
+ if (extend > maxex) {
+ maxex = extend;
+ sdim = d >> 1;
+ }
+ }
+ // Chose the number of partitions:
+ final int s = (int) Math.ceil(Math.pow(p, 1.0 / (dims - depth)));
+
+ final double len = end - start; // double intentional!
+ for (int i = 0; i < s; i++) {
+ // We don't completely sort, but only ensure the quantile is invariant.
+ int s2 = start + (int) ((i * len) / s);
+ int e2 = start + (int) (((i + 1) * len) / s);
+ // LoggingUtil.warning("STR " + dim + " s2:" + s2 + " e2:" + e2);
+ if (e2 < end) {
+ c.setDimension(sdim);
+ QuickSelect.quickSelect(objs, c, s2, end, e2);
+ }
+ if (depth + 1 == dims) {
+ ret.add(objs.subList(s2, e2));
+ } else {
+ // Descend
+ strPartition(objs, s2, e2, depth + 1, dims, maxEntries, c, ret);
+ }
+ }
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected MaxExtensionSortTileRecursiveBulkSplit makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/OneDimSortBulkSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/OneDimSortBulkSplit.java
index 2209ddef..5d2083b3 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/OneDimSortBulkSplit.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/OneDimSortBulkSplit.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,10 +23,10 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import java.util.Collections;
-import java.util.Comparator;
import java.util.List;
import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialSingleMeanComparator;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
@@ -47,7 +47,7 @@ public class OneDimSortBulkSplit extends AbstractBulkSplit {
/**
* Static instance.
*/
- public static final AbstractBulkSplit STATIC = new OneDimSortBulkSplit();
+ public static final OneDimSortBulkSplit STATIC = new OneDimSortBulkSplit();
/**
* Constructor.
@@ -59,14 +59,7 @@ public class OneDimSortBulkSplit extends AbstractBulkSplit {
@Override
public <T extends SpatialComparable> List<List<T>> partition(List<T> spatialObjects, int minEntries, int maxEntries) {
// Sort by first dimension
- Collections.sort(spatialObjects, new Comparator<SpatialComparable>() {
- @Override
- public int compare(SpatialComparable o1, SpatialComparable o2) {
- double min1 = (o1.getMax(0) + o1.getMin(0)) * .5;
- double min2 = (o2.getMax(0) + o2.getMin(0)) * .5;
- return Double.compare(min1, min2);
- }
- });
+ Collections.sort(spatialObjects, new SpatialSingleMeanComparator(0));
return trivialPartition(spatialObjects, minEntries, maxEntries);
}
@@ -79,8 +72,8 @@ public class OneDimSortBulkSplit extends AbstractBulkSplit {
*/
public static class Parameterizer extends AbstractParameterizer {
@Override
- protected AbstractBulkSplit makeInstance() {
+ protected OneDimSortBulkSplit makeInstance() {
return OneDimSortBulkSplit.STATIC;
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/SortTileRecursiveBulkSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/SortTileRecursiveBulkSplit.java
index e24ef3ce..6cd7a598 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/SortTileRecursiveBulkSplit.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/SortTileRecursiveBulkSplit.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,12 +23,14 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import java.util.ArrayList;
-import java.util.Comparator;
import java.util.List;
import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialSingleMeanComparator;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
import de.lmu.ifi.dbs.elki.utilities.datastructures.QuickSelect;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
/**
* Sort-Tile-Recursive aims at tiling the data space with a grid-like structure
@@ -44,13 +46,19 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
* @author Erich Schubert
*/
@Reference(authors = "Leutenegger, S.T. and Lopez, M.A. and Edgington, J.", title = "STR: A simple and efficient algorithm for R-tree packing", booktitle = "Proc. 13th International Conference on Data Engineering, 1997", url = "http://dx.doi.org/10.1109/ICDE.1997.582015")
+@Alias({"str", "STR"})
public class SortTileRecursiveBulkSplit extends AbstractBulkSplit {
+ /**
+ * Static instance.
+ */
+ public static final SortTileRecursiveBulkSplit STATIC = new SortTileRecursiveBulkSplit();
+
@Override
public <T extends SpatialComparable> List<List<T>> partition(List<T> spatialObjects, int minEntries, int maxEntries) {
final int dims = spatialObjects.get(0).getDimensionality();
final int p = (int) Math.ceil(spatialObjects.size() / (double) maxEntries);
- List<List<T>> ret = new ArrayList<List<T>>(p);
- strPartition(spatialObjects, 0, spatialObjects.size(), 0, dims, maxEntries, new Compare<T>(), ret);
+ List<List<T>> ret = new ArrayList<>(p);
+ strPartition(spatialObjects, 0, spatialObjects.size(), 0, dims, maxEntries, new SpatialSingleMeanComparator(0), ret);
return ret;
}
@@ -67,24 +75,23 @@ public class SortTileRecursiveBulkSplit extends AbstractBulkSplit {
* @param ret Output list
* @param <T> data type
*/
- protected <T extends SpatialComparable> void strPartition(List<T> objs, int start, int end, int depth, int dims, int maxEntries, Compare<T> c, List<List<T>> ret) {
+ protected <T extends SpatialComparable> void strPartition(List<T> objs, int start, int end, int depth, int dims, int maxEntries, SpatialSingleMeanComparator c, List<List<T>> ret) {
final int p = (int) Math.ceil((end - start) / (double) maxEntries);
final int s = (int) Math.ceil(Math.pow(p, 1.0 / (dims - depth)));
final double len = end - start; // double intentional!
- for(int i = 0; i < s; i++) {
+ for (int i = 0; i < s; i++) {
// We don't completely sort, but only ensure the quantile is invariant.
int s2 = start + (int) ((i * len) / s);
int e2 = start + (int) (((i + 1) * len) / s);
// LoggingUtil.warning("STR " + dim + " s2:" + s2 + " e2:" + e2);
- if(e2 < end) {
- c.dim = depth;
+ if (e2 < end) {
+ c.setDimension(depth);
QuickSelect.quickSelect(objs, c, s2, end, e2);
}
- if(depth + 1 == dims) {
+ if (depth + 1 == dims) {
ret.add(objs.subList(s2, e2));
- }
- else {
+ } else {
// Descend
strPartition(objs, s2, e2, depth + 1, dims, maxEntries, c, ret);
}
@@ -92,25 +99,16 @@ public class SortTileRecursiveBulkSplit extends AbstractBulkSplit {
}
/**
- * Comparison helper.
- *
- * @apiviz.exclude
+ * Parameterization class.
*
* @author Erich Schubert
*
- * @param <T> Type
+ * @apiviz.exclude
*/
- private static class Compare<T extends SpatialComparable> implements Comparator<T> {
- /**
- * Current dimension.
- */
- int dim;
-
+ public static class Parameterizer extends AbstractParameterizer {
@Override
- public int compare(T o1, T o2) {
- final double v1 = o1.getMin(dim) + o1.getMax(dim);
- final double v2 = o2.getMin(dim) + o2.getMax(dim);
- return Double.compare(v1, v2);
+ protected SortTileRecursiveBulkSplit makeInstance() {
+ return STATIC;
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/SpatialSortBulkSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/SpatialSortBulkSplit.java
index beb6e657..6e2b6369 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/SpatialSortBulkSplit.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/SpatialSortBulkSplit.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -40,7 +40,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
* <p>
* On packing R-trees<br/>
* Kamel, I. and Faloutsos, C.<br/>
- * Proc. 2of the second international conference on Information and knowledge
+ * Proc. of the second international conference on Information and knowledge
* management
* </p>
*
@@ -48,7 +48,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
*
* @author Erich Schubert
*/
-@Reference(title = "On packing R-trees", authors = "Kamel, I. and Faloutsos, C.", booktitle = "Proc. 2of the second international conference on Information and knowledge management", url = "http://dx.doi.org/10.1145/170088.170403")
+@Reference(title = "On packing R-trees", authors = "Kamel, I. and Faloutsos, C.", booktitle = "Proc. of the second international conference on Information and knowledge management", url = "http://dx.doi.org/10.1145/170088.170403")
public class SpatialSortBulkSplit extends AbstractBulkSplit {
/**
* Sorting class
@@ -93,7 +93,7 @@ public class SpatialSortBulkSplit extends AbstractBulkSplit {
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- ObjectParameter<SpatialSorter> sorterP = new ObjectParameter<SpatialSorter>(SORTER_ID, SpatialSorter.class);
+ ObjectParameter<SpatialSorter> sorterP = new ObjectParameter<>(SORTER_ID, SpatialSorter.class);
if(config.grab(sorterP)) {
sorter = sorterP.instantiateClass(config);
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/package-info.java
index 0d01ba83..5c52de3e 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/ApproximativeLeastOverlapInsertionStrategy.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/ApproximativeLeastOverlapInsertionStrategy.java
index c39bd914..5b4e7a56 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/ApproximativeLeastOverlapInsertionStrategy.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/ApproximativeLeastOverlapInsertionStrategy.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -77,7 +77,7 @@ public class ApproximativeLeastOverlapInsertionStrategy extends LeastOverlapInse
}
// Heap of candidates
- TopBoundedHeap<DoubleIntPair> candidates = new TopBoundedHeap<DoubleIntPair>(numCandidates, Collections.reverseOrder());
+ TopBoundedHeap<DoubleIntPair> candidates = new TopBoundedHeap<>(numCandidates, Collections.reverseOrder());
for(int i = 0; i < size; i++) {
// Existing object and extended rectangle:
SpatialComparable entry = getter.get(options, i);
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/CombinedInsertionStrategy.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/CombinedInsertionStrategy.java
index 63bbe9dc..837f0312 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/CombinedInsertionStrategy.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/CombinedInsertionStrategy.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -108,12 +108,12 @@ public class CombinedInsertionStrategy implements InsertionStrategy {
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- ClassParameter<InsertionStrategy> dirP = new ClassParameter<InsertionStrategy>(DIR_STRATEGY_ID, InsertionStrategy.class, LeastEnlargementWithAreaInsertionStrategy.class);
+ ClassParameter<InsertionStrategy> dirP = new ClassParameter<>(DIR_STRATEGY_ID, InsertionStrategy.class, LeastEnlargementWithAreaInsertionStrategy.class);
if(config.grab(dirP)) {
dirStrategy = dirP.instantiateClass(config);
}
- ClassParameter<InsertionStrategy> leafP = new ClassParameter<InsertionStrategy>(LEAF_STRATEGY_ID, InsertionStrategy.class, LeastOverlapInsertionStrategy.class);
+ ClassParameter<InsertionStrategy> leafP = new ClassParameter<>(LEAF_STRATEGY_ID, InsertionStrategy.class, LeastOverlapInsertionStrategy.class);
if(config.grab(leafP)) {
leafStrategy = leafP.instantiateClass(config);
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/InsertionStrategy.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/InsertionStrategy.java
index 96294514..477f0f48 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/InsertionStrategy.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/InsertionStrategy.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastEnlargementInsertionStrategy.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastEnlargementInsertionStrategy.java
index eb211cb6..39348bf5 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastEnlargementInsertionStrategy.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastEnlargementInsertionStrategy.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastEnlargementWithAreaInsertionStrategy.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastEnlargementWithAreaInsertionStrategy.java
index 977a132b..627428e9 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastEnlargementWithAreaInsertionStrategy.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastEnlargementWithAreaInsertionStrategy.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastOverlapInsertionStrategy.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastOverlapInsertionStrategy.java
index 2eba8912..18855d90 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastOverlapInsertionStrategy.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastOverlapInsertionStrategy.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/package-info.java
index ad54e1e1..d425c7bd 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/LimitedReinsertOverflowTreatment.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/LimitedReinsertOverflowTreatment.java
index 3c25cbbc..0af90d78 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/LimitedReinsertOverflowTreatment.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/LimitedReinsertOverflowTreatment.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.overflow
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,7 +25,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.overflow
import java.util.BitSet;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.SquaredEuclideanDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SquaredEuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.index.tree.IndexTreePath;
import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry;
import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRStarTree;
@@ -73,7 +73,7 @@ public class LimitedReinsertOverflowTreatment implements OverflowTreatment {
}
@Override
- public <N extends AbstractRStarTreeNode<N, E>, E extends SpatialEntry> boolean handleOverflow(AbstractRStarTree<N, E> tree, N node, IndexTreePath<E> path) {
+ public <N extends AbstractRStarTreeNode<N, E>, E extends SpatialEntry> boolean handleOverflow(AbstractRStarTree<N, E, ?> tree, N node, IndexTreePath<E> path) {
final int level = /* tree.getHeight() - */(path.getPathCount() - 1);
// No reinsertions at root level
if(path.getPathCount() == 1) {
@@ -121,7 +121,7 @@ public class LimitedReinsertOverflowTreatment implements OverflowTreatment {
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- ObjectParameter<ReinsertStrategy> strategyP = new ObjectParameter<ReinsertStrategy>(REINSERT_STRATEGY_ID, ReinsertStrategy.class, CloseReinsert.class);
+ ObjectParameter<ReinsertStrategy> strategyP = new ObjectParameter<>(REINSERT_STRATEGY_ID, ReinsertStrategy.class, CloseReinsert.class);
if(config.grab(strategyP)) {
reinsertStrategy = strategyP.instantiateClass(config);
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/OverflowTreatment.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/OverflowTreatment.java
index 87d09038..4b2f94b1 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/OverflowTreatment.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/OverflowTreatment.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.overflow
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -49,5 +49,5 @@ public interface OverflowTreatment {
* @param path Path
* @return true when already handled (e.g. by reinserting)
*/
- <N extends AbstractRStarTreeNode<N, E>, E extends SpatialEntry> boolean handleOverflow(AbstractRStarTree<N, E> tree, N node, IndexTreePath<E> path);
+ <N extends AbstractRStarTreeNode<N, E>, E extends SpatialEntry> boolean handleOverflow(AbstractRStarTree<N, E, ?> tree, N node, IndexTreePath<E> path);
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/SplitOnlyOverflowTreatment.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/SplitOnlyOverflowTreatment.java
index cfbcf6a9..82ceb4ef 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/SplitOnlyOverflowTreatment.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/SplitOnlyOverflowTreatment.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.overflow
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -48,7 +48,7 @@ public class SplitOnlyOverflowTreatment implements OverflowTreatment {
}
@Override
- public <N extends AbstractRStarTreeNode<N, E>, E extends SpatialEntry> boolean handleOverflow(AbstractRStarTree<N, E> tree, N node, IndexTreePath<E> path) {
+ public <N extends AbstractRStarTreeNode<N, E>, E extends SpatialEntry> boolean handleOverflow(AbstractRStarTree<N, E, ?> tree, N node, IndexTreePath<E> path) {
return false;
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/package-info.java
index 30899736..fc7f16f0 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/package-info.java
index 41e2eb0b..7d2dfc0a 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/AbstractPartialReinsert.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/AbstractPartialReinsert.java
index bb222dfe..cf447985 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/AbstractPartialReinsert.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/AbstractPartialReinsert.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.reinsert
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,7 +24,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.reinsert
*/
import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDoubleDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.SquaredEuclideanDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SquaredEuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
@@ -99,7 +99,7 @@ public abstract class AbstractPartialReinsert implements ReinsertStrategy {
if (config.grab(reinsertAmountP)) {
reinsertAmount = reinsertAmountP.getValue();
}
- ObjectParameter<SpatialPrimitiveDoubleDistanceFunction<?>> distanceP = new ObjectParameter<SpatialPrimitiveDoubleDistanceFunction<?>>(REINSERT_DISTANCE_ID, SpatialPrimitiveDoubleDistanceFunction.class, SquaredEuclideanDistanceFunction.class);
+ ObjectParameter<SpatialPrimitiveDoubleDistanceFunction<?>> distanceP = new ObjectParameter<>(REINSERT_DISTANCE_ID, SpatialPrimitiveDoubleDistanceFunction.class, SquaredEuclideanDistanceFunction.class);
if (config.grab(distanceP)) {
distanceFunction = distanceP.instantiateClass(config);
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/CloseReinsert.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/CloseReinsert.java
index 12a4ed0f..3002f18b 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/CloseReinsert.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/CloseReinsert.java
@@ -15,7 +15,7 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleIntPair;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/FarReinsert.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/FarReinsert.java
index 771f56fb..02c1d4d7 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/FarReinsert.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/FarReinsert.java
@@ -15,7 +15,7 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleIntPair;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/ReinsertStrategy.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/ReinsertStrategy.java
index cba96367..2a4f130f 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/ReinsertStrategy.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/ReinsertStrategy.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.reinsert
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/package-info.java
index f6a6f6e9..2d2c6871 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/AngTanLinearSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/AngTanLinearSplit.java
index 3e3d599c..c31abc2d 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/AngTanLinearSplit.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/AngTanLinearSplit.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/GreeneSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/GreeneSplit.java
index 99c15fd6..d00479cf 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/GreeneSplit.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/GreeneSplit.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/RTreeLinearSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/RTreeLinearSplit.java
index b4ff2364..4dc9b15d 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/RTreeLinearSplit.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/RTreeLinearSplit.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/RTreeQuadraticSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/RTreeQuadraticSplit.java
index 8f61771d..91ef8f16 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/RTreeQuadraticSplit.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/RTreeQuadraticSplit.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/SplitStrategy.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/SplitStrategy.java
index 658a63da..0bc1ffcf 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/SplitStrategy.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/SplitStrategy.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/TopologicalSplitter.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/TopologicalSplitter.java
index ab32ba19..dc9092ad 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/TopologicalSplitter.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/TopologicalSplitter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -50,7 +50,7 @@ public class TopologicalSplitter implements SplitStrategy {
public static final TopologicalSplitter STATIC = new TopologicalSplitter();
/**
- * constructor.
+ * Constructor.
*/
public TopologicalSplitter() {
// Nothing to do.
@@ -58,7 +58,7 @@ public class TopologicalSplitter implements SplitStrategy {
@Override
public <E extends SpatialComparable, A> BitSet split(A entries, ArrayAdapter<E, A> getter, int minEntries) {
- Split<A, E> split = new Split<A, E>(entries, getter);
+ Split<A, E> split = new Split<>(entries, getter);
split.chooseSplitAxis(minEntries);
split.chooseSplitPoint(minEntries);
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/package-info.java
index 9e8291be..bb8cb1e2 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/NodeArrayAdapter.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/NodeArrayAdapter.java
index 3bf35d9d..def824ba 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/NodeArrayAdapter.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/NodeArrayAdapter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -43,7 +43,6 @@ public class NodeArrayAdapter implements ArrayAdapter<SpatialEntry, AbstractNode
*/
protected NodeArrayAdapter() {
super();
- // TODO Auto-generated constructor stub
}
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/SpatialComparator.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/SpatialComparator.java
deleted file mode 100644
index 2f1ea9b1..00000000
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/SpatialComparator.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util;
-
-/*
- This file is part of ELKI:
- Environment for Developing KDD-Applications Supported by Index-Structures
-
- Copyright (C) 2012
- Ludwig-Maximilians-Universität München
- Lehr- und Forschungseinheit für Datenbanksysteme
- ELKI Development Team
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-import java.util.Comparator;
-
-import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
-
-/**
- * Compares objects of type SpatialComparable.
- *
- * @author Elke Achtert
- *
- * @apiviz.uses SpatialComparable
- */
-public final class SpatialComparator implements Comparator<SpatialComparable> {
- /**
- * Indicates the comparison of the min values of the entries' MBRs.
- */
- public static final int MIN = 1;
-
- /**
- * Indicates the comparison of the max values of the entries' MBRs.
- */
- public static final int MAX = 2;
-
- /**
- * The dimension for comparison.
- */
- private final int compareDimension;
-
- /**
- * Indicates the comparison value (min or max).
- */
- private final int comparisonValue;
-
- /**
- * Creates a new spatial comparator with the specified parameters.
- *
- * @param compareDimension the dimension to be set for comparison
- * @param comparisonValue the comparison value to be set
- */
- public SpatialComparator(int compareDimension, int comparisonValue) {
- this.compareDimension = compareDimension;
- this.comparisonValue = comparisonValue;
- }
-
- /**
- * Compares the two specified spatial comparables according to the sorting
- * dimension and the comparison value of this Comparator.
- *
- * @param o1 the first spatial comparable
- * @param o2 the second spatial comparable
- * @return a negative integer, zero, or a positive integer as the first
- * argument is less than, equal to, or greater than the second.
- */
- @Override
- public int compare(SpatialComparable o1, SpatialComparable o2) {
- if(comparisonValue == MIN) {
- if(o1.getMin(compareDimension) < o2.getMin(compareDimension)) {
- return -1;
- }
-
- if(o1.getMin(compareDimension) > o2.getMin(compareDimension)) {
- return +1;
- }
- }
- else if(comparisonValue == MAX) {
- if(o1.getMax(compareDimension) < o2.getMax(compareDimension)) {
- return -1;
- }
-
- if(o1.getMax(compareDimension) > o2.getMax(compareDimension)) {
- return +1;
- }
- }
- else {
- throw new IllegalArgumentException("No comparison value specified!");
- }
- return 0;
- }
-}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/package-info.java
index 10991028..22088417 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/package-info.java
@@ -6,7 +6,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/vafile/PartialVAFile.java b/src/de/lmu/ifi/dbs/elki/index/vafile/PartialVAFile.java
index 37fbe994..0cbb7c56 100644
--- a/src/de/lmu/ifi/dbs/elki/index/vafile/PartialVAFile.java
+++ b/src/de/lmu/ifi/dbs/elki/index/vafile/PartialVAFile.java
@@ -38,7 +38,9 @@ import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPairList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNHeap;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNList;
import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
@@ -46,21 +48,19 @@ import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.database.relation.RelationUtil;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.LPNormDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.LPNormDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.SubspaceLPNormDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceDBIDList;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceKNNHeap;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceKNNList;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.index.AbstractRefiningIndex;
import de.lmu.ifi.dbs.elki.index.IndexFactory;
import de.lmu.ifi.dbs.elki.index.KNNIndex;
import de.lmu.ifi.dbs.elki.index.RangeIndex;
-import de.lmu.ifi.dbs.elki.index.tree.TreeIndexFactory;
import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.statistics.Counter;
import de.lmu.ifi.dbs.elki.math.MathUtil;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
+import de.lmu.ifi.dbs.elki.persistent.AbstractPageFileFactory;
import de.lmu.ifi.dbs.elki.persistent.ByteArrayUtil;
import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.DoubleMaxHeap;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
@@ -89,7 +89,7 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleObjPair;
* @apiviz.landmark
*
* @apiviz.composedOf DAFile
- * @apiviz.uses PartialVACandidate
+ * @apiviz.has PartialVACandidate
* @apiviz.has PartialVAFileRangeQuery
* @apiviz.has PartialVAFileKNNQuery
*
@@ -143,11 +143,11 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn
super(relation);
this.pageSize = pageSize;
this.partitions = partitions;
- this.stats = new Statistics();
+ this.stats = new Statistics(this.getClass().getName());
}
@Override
- public void initialize(Relation<V> relation, DBIDs ids) throws IllegalStateException {
+ public void initialize() throws IllegalStateException {
if(splitPartitions != null) {
throw new IllegalStateException("Data already inserted.");
}
@@ -159,15 +159,15 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn
final int dimensions = RelationUtil.dimensionality(relation);
splitPartitions = new double[dimensions][];
- daFiles = new ArrayList<DAFile>(dimensions);
+ daFiles = new ArrayList<>(dimensions);
for(int d = 0; d < dimensions; d++) {
final DAFile f = new DAFile(relation, d, partitions);
splitPartitions[d] = f.getSplitPositions();
daFiles.add(f);
}
- vectorApprox = new ArrayList<VectorApproximation>();
- for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
+ vectorApprox = new ArrayList<>();
+ for(DBIDIter iter = relation.iterDBIDs(); iter.valid(); iter.advance()) {
DBID id = DBIDUtil.deref(iter);
V dv = relation.get(id);
VectorApproximation va = calculateFullApproximation(id, dv);
@@ -185,6 +185,16 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn
return "partial va-file";
}
+ @Override
+ public Logging getLogger() {
+ return LOG;
+ }
+
+ @Override
+ public void logStatistics() {
+ stats.logStatistics();
+ }
+
/**
* Fake subspace (full-dimensional).
*
@@ -298,21 +308,21 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn
final int dimensions = query.getDimensionality();
double[] lowerVals = new double[dimensions];
double[] upperVals = new double[dimensions];
-
+
VectorApproximation queryApprox = calculatePartialApproximation(null, query, daFiles);
-
+
for(int i = 0; i < dimensions; i++) {
final double val = query.doubleValue(i);
lowerVals[i] = val - epsilon;
upperVals[i] = val + epsilon;
}
-
+
Vector lowerEpsilon = new Vector(lowerVals);
VectorApproximation lowerEpsilonPartitions = calculatePartialApproximation(null, lowerEpsilon, daFiles);
-
+
Vector upperEpsilon = new Vector(upperVals);
VectorApproximation upperEpsilonPartitions = calculatePartialApproximation(null, upperEpsilon, daFiles);
-
+
for(int i = 0; i < daFiles.size(); i++) {
int coeff = (queryApprox.getApproximation(i) - lowerEpsilonPartitions.getApproximation(i)) + (upperEpsilonPartitions.getApproximation(i) - queryApprox.getApproximation(i)) + 1;
daFiles.get(i).first = coeff;
@@ -334,7 +344,7 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn
double[] borders = daFiles.get(i).second.getSplitPositions();
assert borders != null : "borders are null";
int lastBorderIndex = borders.length - 1;
-
+
// value is lower outlier
if(val < borders[0]) {
approximation[i] = 0;
@@ -361,13 +371,59 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn
* @apiviz.exclude
*/
public static class Statistics {
- public long scannedBytes = 0;
+ private Counter scannedBytes;
+
+ private Counter queryTime;
+
+ private Counter issuedQueries;
+
+ private Counter refinements;
+
+ protected Statistics(String parent) {
+ scannedBytes = LOG.isStatistics() ? LOG.newCounter(parent + ".scannedBytes") : null;
+ queryTime = LOG.isStatistics() ? LOG.newCounter(parent + ".queryTime") : null;
+ issuedQueries = LOG.isStatistics() ? LOG.newCounter(parent + ".issuedQueries") : null;
+ refinements = LOG.isStatistics() ? LOG.newCounter(parent + ".refinements") : null;
+ }
+
+ public void logStatistics() {
+ if(scannedBytes != null) {
+ LOG.statistics(scannedBytes);
+ }
+ if(queryTime != null) {
+ LOG.statistics(queryTime);
+ }
+ if(issuedQueries != null) {
+ LOG.statistics(issuedQueries);
+ }
+ if(refinements != null) {
+ LOG.statistics(refinements);
+ }
+ }
+
+ protected void incrementScannedBytes(long bytes) {
+ if(scannedBytes != null) {
+ scannedBytes.increment(bytes);
+ }
+ }
- public long queryTime = 0;
+ protected void incrementQueryTime(long time) {
+ if(queryTime != null) {
+ queryTime.increment(time);
+ }
+ }
- public int issuedQueries = 0;
+ protected void incrementIssuedQueries() {
+ if(issuedQueries != null) {
+ issuedQueries.increment();
+ }
+ }
- public int refinements = 0;
+ protected void incrementRefinements() {
+ if(refinements != null) {
+ refinements.increment();
+ }
+ }
}
/**
@@ -453,8 +509,8 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn
}
@Override
- public DoubleDistanceDBIDList getRangeForObject(V query, DoubleDistance range) {
- stats.issuedQueries++;
+ public DoubleDistanceDBIDPairList getRangeForObject(V query, DoubleDistance range) {
+ stats.incrementIssuedQueries();
long t = System.nanoTime();
final double epsilonP = Math.pow(range.doubleValue(), p);
@@ -468,10 +524,10 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn
// filter step
// calculate selectivity coefficients
- List<DoubleObjPair<DAFile>> subspaceDAFiles = new ArrayList<DoubleObjPair<DAFile>>(subspace.cardinality());
+ List<DoubleObjPair<DAFile>> subspaceDAFiles = new ArrayList<>(subspace.cardinality());
for(int d = subspace.nextSetBit(0); d >= 0; d = subspace.nextSetBit(d + 1)) {
DAFile daFile = daFiles.get(d);
- subspaceDAFiles.add(new DoubleObjPair<DAFile>(-1, daFile));
+ subspaceDAFiles.add(new DoubleObjPair<>(-1, daFile));
}
calculateSelectivityCoeffs(subspaceDAFiles, query, range.doubleValue());
// sort DA files by selectivity
@@ -481,7 +537,7 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn
// create candidate list (all objects) and prune candidates w.r.t.
// mindist (i.e. remove them from the list)
// important: this structure contains the maxDist values for refinement!
- DoubleDistanceDBIDList result = new DoubleDistanceDBIDList();
+ DoubleDistanceDBIDPairList result = new DoubleDistanceDBIDPairList();
int candidates = 0;
for(VectorApproximation va : vectorApprox) {
DBID id = va.getId();
@@ -508,7 +564,7 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn
}
else { // refine candidate - true refinement
DoubleDistance dis = refine(id, query);
- stats.refinements += 1;
+ stats.incrementRefinements();
if(dis.doubleValue() <= range.doubleValue()) {
result.add(dis.doubleValue(), id);
}
@@ -517,9 +573,9 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn
}
result.sort();
- stats.scannedBytes += relation.size() * VectorApproximation.byteOnDisk(subspace.cardinality(), partitions);
+ stats.incrementScannedBytes(relation.size() * VectorApproximation.byteOnDisk(subspace.cardinality(), partitions));
- stats.queryTime += System.nanoTime() - t;
+ stats.incrementQueryTime(System.nanoTime() - t);
if(LOG.isDebuggingFine()) {
LOG.fine("query = " + query);
@@ -562,7 +618,7 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn
@Override
public DoubleDistanceKNNList getKNNForObject(V query, int k) {
- stats.issuedQueries++;
+ stats.incrementIssuedQueries();
long t = System.nanoTime();
// generate query approximation and lookup table
@@ -603,9 +659,9 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn
if(candidates2 != null) {
candidates1 = candidates2;
}
- candidates2 = new LinkedList<PartialVACandidate>();
+ candidates2 = new LinkedList<>();
- DoubleMaxHeap kMinMaxDists = new DoubleMaxHeap(k+1);
+ DoubleMaxHeap kMinMaxDists = new DoubleMaxHeap(k + 1);
for(PartialVACandidate va : candidates1) {
int dimension = daFiles.get(addition).getDimension();
int objectCell = va.getApproximation(dimension);
@@ -628,21 +684,21 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn
}
}
- stats.scannedBytes += relation.size() * VectorApproximation.byteOnDisk(addition, partitions);
+ stats.incrementScannedBytes(relation.size() * VectorApproximation.byteOnDisk(addition, partitions));
// refinement step
- ArrayList<PartialVACandidate> sortedCandidates = new ArrayList<PartialVACandidate>(candidates2);
+ ArrayList<PartialVACandidate> sortedCandidates = new ArrayList<>(candidates2);
// sort candidates by lower bound (minDist)
Collections.sort(sortedCandidates);
DoubleDistanceKNNList result = retrieveAccurateDistances(sortedCandidates, k, subspace, query);
- stats.queryTime += System.nanoTime() - t;
+ stats.incrementQueryTime(System.nanoTime() - t);
return result;
}
private LinkedList<PartialVACandidate> filter1(int k, int reducedDims, List<DAFile> daFiles, VectorApproximation queryApprox, int subspaceDims, VALPNormDistance dist) {
- LinkedList<PartialVACandidate> candidates1 = new LinkedList<PartialVACandidate>();
- DoubleMaxHeap minmaxdist = new DoubleMaxHeap(k+1);
+ LinkedList<PartialVACandidate> candidates1 = new LinkedList<>();
+ DoubleMaxHeap minmaxdist = new DoubleMaxHeap(k + 1);
for(VectorApproximation va : vectorApprox) {
PartialVACandidate pva = new PartialVACandidate(va);
@@ -704,7 +760,7 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn
*/
public List<DAFile> getWorstCaseDistOrder(VALPNormDistance dist, BitSet subspace) {
int subspaceLength = subspace.cardinality();
- List<DAFile> result = new ArrayList<DAFile>(subspaceLength);
+ List<DAFile> result = new ArrayList<>(subspaceLength);
for(int i = subspace.nextSetBit(0); i >= 0; i = subspace.nextSetBit(i + 1)) {
result.add(daFiles.get(i));
}
@@ -713,13 +769,13 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn
}
protected DoubleDistanceKNNList retrieveAccurateDistances(List<PartialVACandidate> sortedCandidates, int k, BitSet subspace, V query) {
- DoubleDistanceKNNHeap result = new DoubleDistanceKNNHeap(k);
+ DoubleDistanceKNNHeap result = (DoubleDistanceKNNHeap) DBIDUtil.newHeap(DoubleDistance.FACTORY, k);
for(PartialVACandidate va : sortedCandidates) {
double stopdist = result.doubleKNNDistance();
DBID currentID = va.getId();
if(result.size() < k || va.minDistP < stopdist) {
DoubleDistance dist = refine(currentID, query);
- stats.refinements += 1;
+ stats.incrementRefinements();
if(dist.doubleValue() < stopdist) {
result.add(dist.doubleValue(), currentID);
}
@@ -791,7 +847,7 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn
@Override
public PartialVAFile<V> instantiate(Relation<V> relation) {
- return new PartialVAFile<V>(pagesize, relation, numpart);
+ return new PartialVAFile<>(pagesize, relation, numpart);
}
@Override
@@ -820,7 +876,7 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- IntParameter pagesizeP = new IntParameter(TreeIndexFactory.PAGE_SIZE_ID, 1024);
+ IntParameter pagesizeP = new IntParameter(AbstractPageFileFactory.Parameterizer.PAGE_SIZE_ID, 1024);
pagesizeP.addConstraint(new GreaterConstraint(0));
if(config.grab(pagesizeP)) {
pagesize = pagesizeP.getValue();
@@ -834,8 +890,8 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn
@Override
protected Factory<?> makeInstance() {
- return new Factory<NumberVector<?>>(pagesize, numpart);
+ return new Factory<>(pagesize, numpart);
}
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/vafile/VAFile.java b/src/de/lmu/ifi/dbs/elki/index/vafile/VAFile.java
index 09b91be7..e6da2ec9 100644
--- a/src/de/lmu/ifi/dbs/elki/index/vafile/VAFile.java
+++ b/src/de/lmu/ifi/dbs/elki/index/vafile/VAFile.java
@@ -34,7 +34,9 @@ import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPairList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNHeap;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNList;
import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
@@ -42,18 +44,15 @@ import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.database.relation.RelationUtil;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.LPNormDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceDBIDList;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceKNNHeap;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceKNNList;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.LPNormDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.index.AbstractRefiningIndex;
import de.lmu.ifi.dbs.elki.index.IndexFactory;
import de.lmu.ifi.dbs.elki.index.KNNIndex;
import de.lmu.ifi.dbs.elki.index.RangeIndex;
-import de.lmu.ifi.dbs.elki.index.tree.TreeIndexFactory;
import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.persistent.AbstractPageFileFactory;
import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.DoubleMaxHeap;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
@@ -131,13 +130,13 @@ public class VAFile<V extends NumberVector<?>> extends AbstractRefiningIndex<V>
this.partitions = partitions;
this.pageSize = pageSize;
this.scans = 0;
- this.vectorApprox = new ArrayList<VectorApproximation>();
+ this.vectorApprox = new ArrayList<>();
}
@Override
- protected void initialize(Relation<V> relation, DBIDs ids) {
+ public void initialize() {
setPartitions(relation);
- for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
+ for (DBIDIter iter = relation.iterDBIDs(); iter.valid(); iter.advance()) {
DBID id = DBIDUtil.deref(iter);
vectorApprox.add(calculateApproximation(id, relation.get(id)));
}
@@ -150,7 +149,7 @@ public class VAFile<V extends NumberVector<?>> extends AbstractRefiningIndex<V>
* @throws IllegalArgumentException
*/
public void setPartitions(Relation<V> relation) throws IllegalArgumentException {
- if((Math.log(partitions) / Math.log(2)) != (int) (Math.log(partitions) / Math.log(2))) {
+ if ((Math.log(partitions) / Math.log(2)) != (int) (Math.log(partitions) / Math.log(2))) {
throw new IllegalArgumentException("Number of partitions must be a power of 2!");
}
@@ -158,16 +157,16 @@ public class VAFile<V extends NumberVector<?>> extends AbstractRefiningIndex<V>
final int size = relation.size();
splitPositions = new double[dimensions][partitions + 1];
- for(int d = 0; d < dimensions; d++) {
+ for (int d = 0; d < dimensions; d++) {
double[] tempdata = new double[size];
int j = 0;
- for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
+ for (DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
tempdata[j] = relation.get(iditer).doubleValue(d);
j += 1;
}
Arrays.sort(tempdata);
- for(int b = 0; b < partitions; b++) {
+ for (int b = 0; b < partitions; b++) {
int start = (int) (b * size / (double) partitions);
splitPositions[d][b] = tempdata[start];
}
@@ -185,20 +184,20 @@ public class VAFile<V extends NumberVector<?>> extends AbstractRefiningIndex<V>
*/
public VectorApproximation calculateApproximation(DBID id, V dv) {
int approximation[] = new int[dv.getDimensionality()];
- for(int d = 0; d < splitPositions.length; d++) {
+ for (int d = 0; d < splitPositions.length; d++) {
final double val = dv.doubleValue(d);
final int lastBorderIndex = splitPositions[d].length - 1;
// Value is below data grid
- if(val < splitPositions[d][0]) {
+ if (val < splitPositions[d][0]) {
approximation[d] = 0;
- if(id != null) {
+ if (id != null) {
LOG.warning("Vector outside of VAFile grid!");
}
} // Value is above data grid
- else if(val > splitPositions[d][lastBorderIndex]) {
+ else if (val > splitPositions[d][lastBorderIndex]) {
approximation[d] = lastBorderIndex - 1;
- if(id != null) {
+ if (id != null) {
LOG.warning("Vector outside of VAFile grid!");
}
} // normal case
@@ -212,24 +211,10 @@ public class VAFile<V extends NumberVector<?>> extends AbstractRefiningIndex<V>
return new VectorApproximation(id, approximation);
}
- @Override
- public long getReadOperations() {
- return getRandomReadOnly() + getScannedPages();
- }
-
- /**
- * Get the number of random read operations only.
- *
- * @return Random read operations.
- */
- public long getRandomReadOnly() {
- return super.getReadOperations();
- }
-
/**
* Get the number of scanned bytes.
*
- * @return Numebr of scanned bytes.
+ * @return Number of scanned bytes.
*/
public long getScannedPages() {
int vacapacity = pageSize / VectorApproximation.byteOnDisk(splitPositions.length, partitions);
@@ -238,15 +223,15 @@ public class VAFile<V extends NumberVector<?>> extends AbstractRefiningIndex<V>
}
@Override
- public long getWriteOperations() {
- return -1;
+ public Logging getLogger() {
+ return LOG;
}
@Override
- public void resetPageAccess() {
- super.resetPageAccess();
- scans = 0;
- // FIXME: writes
+ public void logStatistics() {
+ super.logStatistics();
+ // FIXME:
+ LOG.statistics("scanned pages:" + getScannedPages());
}
@Override
@@ -262,14 +247,14 @@ public class VAFile<V extends NumberVector<?>> extends AbstractRefiningIndex<V>
@SuppressWarnings("unchecked")
@Override
public <D extends Distance<D>> KNNQuery<V, D> getKNNQuery(DistanceQuery<V, D> distanceQuery, Object... hints) {
- for(Object hint : hints) {
- if(hint == DatabaseQuery.HINT_BULK) {
+ for (Object hint : hints) {
+ if (hint == DatabaseQuery.HINT_BULK) {
// FIXME: support bulk?
return null;
}
}
DistanceFunction<? super V, ?> df = distanceQuery.getDistanceFunction();
- if(df instanceof LPNormDistanceFunction) {
+ if (df instanceof LPNormDistanceFunction) {
double p = ((LPNormDistanceFunction) df).getP();
DistanceQuery<V, ?> ddq = (DistanceQuery<V, ?>) distanceQuery;
KNNQuery<V, ?> dq = new VAFileKNNQuery((DistanceQuery<V, DoubleDistance>) ddq, p);
@@ -283,7 +268,7 @@ public class VAFile<V extends NumberVector<?>> extends AbstractRefiningIndex<V>
@Override
public <D extends Distance<D>> RangeQuery<V, D> getRangeQuery(DistanceQuery<V, D> distanceQuery, Object... hints) {
DistanceFunction<? super V, ?> df = distanceQuery.getDistanceFunction();
- if(df instanceof LPNormDistanceFunction) {
+ if (df instanceof LPNormDistanceFunction) {
double p = ((LPNormDistanceFunction) df).getP();
DistanceQuery<V, ?> ddq = (DistanceQuery<V, ?>) distanceQuery;
RangeQuery<V, ?> dq = new VAFileRangeQuery((DistanceQuery<V, DoubleDistance>) ddq, p);
@@ -317,7 +302,7 @@ public class VAFile<V extends NumberVector<?>> extends AbstractRefiningIndex<V>
}
@Override
- public DoubleDistanceDBIDList getRangeForObject(V query, DoubleDistance range) {
+ public DoubleDistanceDBIDPairList getRangeForObject(V query, DoubleDistance range) {
final double eps = range.doubleValue();
// generate query approximation and lookup table
VectorApproximation queryApprox = calculateApproximation(null, query);
@@ -328,13 +313,13 @@ public class VAFile<V extends NumberVector<?>> extends AbstractRefiningIndex<V>
// Count a VA file scan
scans += 1;
- DoubleDistanceDBIDList result = new DoubleDistanceDBIDList();
+ DoubleDistanceDBIDPairList result = new DoubleDistanceDBIDPairList();
// Approximation step
- for(int i = 0; i < vectorApprox.size(); i++) {
+ for (int i = 0; i < vectorApprox.size(); i++) {
VectorApproximation va = vectorApprox.get(i);
double minDist = vadist.getMinDist(va);
- if(minDist > eps) {
+ if (minDist > eps) {
continue;
}
@@ -343,7 +328,7 @@ public class VAFile<V extends NumberVector<?>> extends AbstractRefiningIndex<V>
// refine the next element
final double dist = refine(va.id, query).doubleValue();
- if(dist <= eps) {
+ if (dist <= eps) {
result.add(dist, va.id);
}
}
@@ -383,29 +368,29 @@ public class VAFile<V extends NumberVector<?>> extends AbstractRefiningIndex<V>
VALPNormDistance vadist = new VALPNormDistance(p, splitPositions, query, queryApprox);
// Heap for the kth smallest maximum distance (yes, we need a max heap!)
- DoubleMaxHeap minMaxHeap = new DoubleMaxHeap(k+1);
+ DoubleMaxHeap minMaxHeap = new DoubleMaxHeap(k + 1);
double minMaxDist = Double.POSITIVE_INFINITY;
// Candidates with minDist <= kth maxDist
- ArrayList<DoubleObjPair<DBID>> candidates = new ArrayList<DoubleObjPair<DBID>>(vectorApprox.size());
+ ArrayList<DoubleObjPair<DBID>> candidates = new ArrayList<>(vectorApprox.size());
// Count a VA file scan
scans += 1;
// Approximation step
- for(int i = 0; i < vectorApprox.size(); i++) {
+ for (int i = 0; i < vectorApprox.size(); i++) {
VectorApproximation va = vectorApprox.get(i);
double minDist = vadist.getMinDist(va);
double maxDist = vadist.getMaxDist(va);
// Skip excess candidate generation:
- if(minDist > minMaxDist) {
+ if (minDist > minMaxDist) {
continue;
}
- candidates.add(new DoubleObjPair<DBID>(minDist, va.id));
+ candidates.add(new DoubleObjPair<>(minDist, va.id));
// Update candidate pruning heap
minMaxHeap.add(maxDist, k);
- if(minMaxHeap.size() >= k) {
+ if (minMaxHeap.size() >= k) {
minMaxDist = minMaxHeap.peek();
}
}
@@ -413,15 +398,15 @@ public class VAFile<V extends NumberVector<?>> extends AbstractRefiningIndex<V>
Collections.sort(candidates);
// refinement step
- DoubleDistanceKNNHeap result = new DoubleDistanceKNNHeap(k);
+ DoubleDistanceKNNHeap result = (DoubleDistanceKNNHeap) DBIDUtil.newHeap(DoubleDistance.FACTORY, k);
// log.fine("candidates size " + candidates.size());
// retrieve accurate distances
- for(DoubleObjPair<DBID> va : candidates) {
+ for (DoubleObjPair<DBID> va : candidates) {
// Stop when we are sure to have all elements
- if(result.size() >= k) {
+ if (result.size() >= k) {
double kDist = result.doubleKNNDistance();
- if(va.first > kDist) {
+ if (va.first > kDist) {
break;
}
}
@@ -430,7 +415,7 @@ public class VAFile<V extends NumberVector<?>> extends AbstractRefiningIndex<V>
final double dist = refine(va.second, query).doubleValue();
result.add(dist, va.second);
}
- if(LOG.isDebuggingFinest()) {
+ if (LOG.isDebuggingFinest()) {
LOG.finest("query = (" + query + ")");
LOG.finest("database: " + vectorApprox.size() + ", candidates: " + candidates.size() + ", results: " + result.size());
}
@@ -483,7 +468,7 @@ public class VAFile<V extends NumberVector<?>> extends AbstractRefiningIndex<V>
@Override
public VAFile<V> instantiate(Relation<V> relation) {
- return new VAFile<V>(pagesize, relation, numpart);
+ return new VAFile<>(pagesize, relation, numpart);
}
@Override
@@ -512,22 +497,22 @@ public class VAFile<V extends NumberVector<?>> extends AbstractRefiningIndex<V>
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- IntParameter pagesizeP = new IntParameter(TreeIndexFactory.PAGE_SIZE_ID, 1024);
+ IntParameter pagesizeP = new IntParameter(AbstractPageFileFactory.Parameterizer.PAGE_SIZE_ID, 1024);
pagesizeP.addConstraint(new GreaterConstraint(0));
- if(config.grab(pagesizeP)) {
+ if (config.grab(pagesizeP)) {
pagesize = pagesizeP.getValue();
}
IntParameter partitionsP = new IntParameter(Factory.PARTITIONS_ID);
partitionsP.addConstraint(new GreaterConstraint(2));
- if(config.grab(partitionsP)) {
+ if (config.grab(partitionsP)) {
numpart = partitionsP.getValue();
}
}
@Override
protected Factory<?> makeInstance() {
- return new Factory<NumberVector<?>>(pagesize, numpart);
+ return new Factory<>(pagesize, numpart);
}
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/vafile/VALPNormDistance.java b/src/de/lmu/ifi/dbs/elki/index/vafile/VALPNormDistance.java
index 2d9469e7..d0b4a8e5 100644
--- a/src/de/lmu/ifi/dbs/elki/index/vafile/VALPNormDistance.java
+++ b/src/de/lmu/ifi/dbs/elki/index/vafile/VALPNormDistance.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.vafile;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/index/vafile/package-info.java b/src/de/lmu/ifi/dbs/elki/index/vafile/package-info.java
index f38b1dca..10aae35c 100644
--- a/src/de/lmu/ifi/dbs/elki/index/vafile/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/index/vafile/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/logging/CLISmartHandler.java b/src/de/lmu/ifi/dbs/elki/logging/CLISmartHandler.java
index b4e6cc09..36ed3d64 100644
--- a/src/de/lmu/ifi/dbs/elki/logging/CLISmartHandler.java
+++ b/src/de/lmu/ifi/dbs/elki/logging/CLISmartHandler.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.logging;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/logging/ELKILogRecord.java b/src/de/lmu/ifi/dbs/elki/logging/ELKILogRecord.java
index 560e1b0f..53540ec2 100644
--- a/src/de/lmu/ifi/dbs/elki/logging/ELKILogRecord.java
+++ b/src/de/lmu/ifi/dbs/elki/logging/ELKILogRecord.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.logging;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/logging/ErrorFormatter.java b/src/de/lmu/ifi/dbs/elki/logging/ErrorFormatter.java
index 827108aa..b4530c25 100644
--- a/src/de/lmu/ifi/dbs/elki/logging/ErrorFormatter.java
+++ b/src/de/lmu/ifi/dbs/elki/logging/ErrorFormatter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.logging;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/logging/Logging.java b/src/de/lmu/ifi/dbs/elki/logging/Logging.java
index 807d4b6e..b9cbc16d 100644
--- a/src/de/lmu/ifi/dbs/elki/logging/Logging.java
+++ b/src/de/lmu/ifi/dbs/elki/logging/Logging.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.logging;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,28 +24,35 @@ package de.lmu.ifi.dbs.elki.logging;
*/
import java.util.HashMap;
-import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import de.lmu.ifi.dbs.elki.logging.progress.Progress;
import de.lmu.ifi.dbs.elki.logging.progress.ProgressLogRecord;
+import de.lmu.ifi.dbs.elki.logging.statistics.Counter;
+import de.lmu.ifi.dbs.elki.logging.statistics.Duration;
+import de.lmu.ifi.dbs.elki.logging.statistics.MillisTimeDuration;
+import de.lmu.ifi.dbs.elki.logging.statistics.Statistic;
+import de.lmu.ifi.dbs.elki.logging.statistics.UnsynchronizedLongCounter;
/**
* This class is a wrapper around {@link java.util.logging.Logger} and
- * {@link java.util.logging.LogManager} offering additional convenience functions.
+ * {@link java.util.logging.LogManager} offering additional convenience
+ * functions.
*
- * If a class keeps a static reference to the appropriate {@link Logging} object,
- * performance penalty compared to standard logging should be minimal.
+ * If a class keeps a static reference to the appropriate {@link Logging}
+ * object, performance penalty compared to standard logging should be minimal.
*
- * However when using {@link java.util.logging.LogRecord} directly instead of
- * {@link ELKILogRecord}, the use of the {@link #log(LogRecord)} method will result in
- * incorrectly logged cause location. Therefore, use {@link ELKILogRecord}!
+ * However when using {@link java.util.logging.LogRecord} directly instead of
+ * {@link ELKILogRecord}, the use of the {@link #log(LogRecord)} method will
+ * result in incorrectly logged cause location. Therefore, use
+ * {@link ELKILogRecord}!
*
* @author Erich Schubert
- *
+ *
* @apiviz.uses LoggingConfiguration
* @apiviz.uses ELKILogRecord oneway - - «create»
+ * @apiviz.uses Level
*/
public class Logging {
/**
@@ -58,7 +65,7 @@ public class Logging {
/**
* HashMap to keep track of loggers.
*/
- private static HashMap<String, Logging> loggers = new HashMap<String, Logging>();
+ private static HashMap<String, Logging> loggers = new HashMap<>();
/**
* Wrapped logger of this instance - not static!
@@ -66,6 +73,47 @@ public class Logging {
private final Logger logger;
/**
+ * Logging Level class.
+ *
+ * @author Erich Schubert
+ */
+ public static class Level extends java.util.logging.Level {
+ /**
+ * Additional level for logging: statistics and timing information.
+ *
+ * Inbetween of "verbose" and "warning".
+ */
+ public static final Level STATISTICS = new Level("STATISTICS", (INFO.intValue() + WARNING.intValue()) >> 1);
+
+ /**
+ * Alias for the "INFO" logging level: "verbose".
+ */
+ public static final java.util.logging.Level VERBOSE = INFO;
+
+ /**
+ * Additional level for logging: additional verbose messages.
+ *
+ * Inbetween of "verbose" and "config", usually 750.
+ */
+ public static final Level VERYVERBOSE = new Level("VERYVERBOSE", (INFO.intValue() + CONFIG.intValue()) >> 1);
+
+ /**
+ * Serial version.
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructor.
+ *
+ * @param name Name
+ * @param value Value
+ */
+ public Level(String name, int value) {
+ super(name, value);
+ }
+ }
+
+ /**
* Constructor, wrapping a logger.
*
* @param logger Logger to wrap.
@@ -87,12 +135,12 @@ public class Logging {
/**
* Retrieve logging utility for a particular class.
*
- * @param name Class name
+ * @param name Class name
* @return Logger
*/
public synchronized static Logging getLogger(final String name) {
Logging logger = loggers.get(name);
- if(logger == null) {
+ if (logger == null) {
logger = new Logging(Logger.getLogger(name));
loggers.put(name, logger);
}
@@ -110,12 +158,21 @@ public class Logging {
}
/**
+ * Test whether to log 'statistics'.
+ *
+ * @return true if logging statistics
+ */
+ public boolean isStatistics() {
+ return logger.isLoggable(Level.STATISTICS);
+ }
+
+ /**
* Test whether to log 'verbose' aka 'info'.
*
* @return true if verbose
*/
public boolean isVerbose() {
- return logger.isLoggable(Level.INFO);
+ return logger.isLoggable(Level.VERBOSE);
}
/**
@@ -128,6 +185,15 @@ public class Logging {
}
/**
+ * Test whether to log 'veryverbose'.
+ *
+ * @return true if extra verbose
+ */
+ public boolean isVeryVerbose() {
+ return logger.isLoggable(Level.VERYVERBOSE);
+ }
+
+ /**
* Test whether to log 'debug' at 'FINE' level.
*
* This is the same as {@link #isDebuggingFine}
@@ -142,7 +208,7 @@ public class Logging {
* Test whether to log 'debug' at 'FINE' level
*
* This is the same as {@link #isDebugging}
- *
+ *
* @return true if debug logging enabled
*/
public boolean isDebuggingFine() {
@@ -173,7 +239,7 @@ public class Logging {
* @param level Level to log at.
* @param message Message to log.
*/
- public void log(Level level, CharSequence message) {
+ public void log(java.util.logging.Level level, CharSequence message) {
LogRecord rec = new ELKILogRecord(level, message);
logger.log(rec);
}
@@ -185,7 +251,7 @@ public class Logging {
* @param message Message to log.
* @param e Exception
*/
- public void log(Level level, CharSequence message, Throwable e) {
+ public void log(java.util.logging.Level level, CharSequence message, Throwable e) {
LogRecord rec = new ELKILogRecord(level, message);
rec.setThrown(e);
logger.log(rec);
@@ -239,6 +305,29 @@ public class Logging {
}
/**
+ * Log a message at the 'STATISTICS' level.
+ *
+ * You should check isTime() before building the message.
+ *
+ * @param message Informational log message.
+ * @param e Exception
+ */
+ public void statistics(CharSequence message, Throwable e) {
+ log(Level.STATISTICS, message, e);
+ }
+
+ /**
+ * Log a message at the 'STATISTICS' level.
+ *
+ * You should check isTime() before building the message.
+ *
+ * @param message Informational log message.
+ */
+ public void statistics(CharSequence message) {
+ log(Level.STATISTICS, message);
+ }
+
+ /**
* Log a message at the 'info' ('verbose') level.
*
* You should check isVerbose() before building the message.
@@ -285,6 +374,29 @@ public class Logging {
}
/**
+ * Log a message at the 'veryverbose' level.
+ *
+ * You should check isVeryVerbose() before building the message.
+ *
+ * @param message Informational log message.
+ * @param e Exception
+ */
+ public void veryverbose(CharSequence message, Throwable e) {
+ log(Level.VERYVERBOSE, message, e);
+ }
+
+ /**
+ * Log a message at the 'veryverbose' level.
+ *
+ * You should check isVeryVerbose() before building the message.
+ *
+ * @param message Informational log message.
+ */
+ public void veryverbose(CharSequence message) {
+ log(Level.VERYVERBOSE, message);
+ }
+
+ /**
* Log a message at the 'fine' debugging level.
*
* You should check isDebugging() before building the message.
@@ -466,7 +578,7 @@ public class Logging {
}
/**
- * Log a Progress object.
+ * Log a Progress object.
*
* @param pgr Progress to log.
*/
@@ -475,9 +587,36 @@ public class Logging {
}
/**
- * @return the wrapped {@link java.util.logging.Logger}
+ * Generate a new counter.
+ *
+ * @param key Key to use
+ * @return Counter.
*/
- public Logger getWrappedLogger() {
- return logger;
+ public Counter newCounter(String key) {
+ return new UnsynchronizedLongCounter(key);
+ }
+
+ /**
+ * Generate a new duration statistic.
+ *
+ * @param key Key to use
+ * @return Duration statistic.
+ */
+ public Duration newDuration(String key) {
+ return new MillisTimeDuration(key);
+ }
+
+ /**
+ * Log a statistics object.
+ *
+ * @param stats Statistics object to report.
+ */
+ public void statistics(Statistic stats) {
+ log(Level.STATISTICS, stats.getKey() + ": " + stats.formatValue());
+ }
+
+ @Override
+ public String toString() {
+ return "Logging(" + logger.getName() + ", " + logger.getLevel() + ")";
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/logging/LoggingConfiguration.java b/src/de/lmu/ifi/dbs/elki/logging/LoggingConfiguration.java
index b0e7936b..1c609b80 100644
--- a/src/de/lmu/ifi/dbs/elki/logging/LoggingConfiguration.java
+++ b/src/de/lmu/ifi/dbs/elki/logging/LoggingConfiguration.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.logging;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,10 +28,10 @@ import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Properties;
import java.util.logging.Handler;
-import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;
+import de.lmu.ifi.dbs.elki.logging.Logging.Level;
import de.lmu.ifi.dbs.elki.utilities.FileUtil;
/**
@@ -56,6 +56,21 @@ public final class LoggingConfiguration {
private static final String TOPLEVEL_PACKAGE = "de.lmu.ifi.dbs.elki";
/**
+ * Top level logger.
+ */
+ private static final Logger LOGGER_GLOBAL_TOP = Logger.getLogger("");
+
+ /**
+ * Logger for ELKI top level package.
+ */
+ private static final Logger LOGGER_ELKI_TOP = Logger.getLogger(TOPLEVEL_PACKAGE);
+
+ /**
+ * Logger for ELKI timing.
+ */
+ private static final Logger LOGGER_TIME_TOP = Logger.getLogger(TOPLEVEL_PACKAGE + ".workflow.AlgorithmStep");
+
+ /**
* Configuration base
*/
private static final String confbase = LoggingConfiguration.class.getPackage().getName();
@@ -92,15 +107,14 @@ public final class LoggingConfiguration {
LogManager logManager = LogManager.getLogManager();
Logger logger = Logger.getLogger(LoggingConfiguration.class.getName());
// allow null as package name.
- if(pkg == null) {
+ if (pkg == null) {
pkg = "";
}
// Load logging configuration from current directory
String cfgfile = name;
- if(new File(name).exists()) {
+ if (new File(name).exists()) {
cfgfile = name;
- }
- else {
+ } else {
// Fall back to full path / resources.
cfgfile = pkg.replace('.', File.separatorChar) + File.separatorChar + name;
}
@@ -115,11 +129,9 @@ public final class LoggingConfiguration {
DEBUG = Boolean.parseBoolean(cfgprop.getProperty("debug"));
logger.info("Logging configuration read.");
- }
- catch(FileNotFoundException e) {
+ } catch (FileNotFoundException e) {
logger.log(Level.SEVERE, "Could not find logging configuration file: " + cfgfile, e);
- }
- catch(Exception e) {
+ } catch (Exception e) {
logger.log(Level.SEVERE, "Failed to configure logging from file: " + cfgfile, e);
}
}
@@ -134,49 +146,47 @@ public final class LoggingConfiguration {
/**
* Reconfigure logging to enable 'verbose' logging at the top level.
*
- * @param verbose verbose flag
- */
- public static void setVerbose(boolean verbose) {
- Logger logger1 = Logger.getLogger("");
- Logger logger2 = Logger.getLogger(TOPLEVEL_PACKAGE);
- if(verbose) {
- // decrease to INFO if it was higher
- if(logger1.getLevel() == null || logger1.getLevel().intValue() > Level.INFO.intValue()) {
- logger1.setLevel(Level.INFO);
+ * @param verbose verbosity level.
+ */
+ public static void setVerbose(java.util.logging.Level verbose) {
+ if (verbose.intValue() <= Level.VERBOSE.intValue()) {
+ // decrease to VERBOSE if it was higher, otherwise further to VERYVERBOSE
+ if (LOGGER_GLOBAL_TOP.getLevel() == null || LOGGER_GLOBAL_TOP.getLevel().intValue() > verbose.intValue()) {
+ LOGGER_GLOBAL_TOP.setLevel(verbose);
}
- if(logger2.getLevel() == null || logger2.getLevel().intValue() > Level.INFO.intValue()) {
- logger2.setLevel(Level.INFO);
+ if (LOGGER_ELKI_TOP.getLevel() == null || LOGGER_ELKI_TOP.getLevel().intValue() > verbose.intValue()) {
+ LOGGER_ELKI_TOP.setLevel(verbose);
}
- }
- else {
- // increase to warning level if it was INFO.
- if(logger1.getLevel() == null || Level.INFO.equals(logger1.getLevel())) {
- logger1.setLevel(Level.WARNING);
+ } else {
+ // re-increase to given level if it was verbose or "very verbose".
+ if (LOGGER_GLOBAL_TOP.getLevel() != null && (//
+ Level.VERBOSE.equals(LOGGER_GLOBAL_TOP.getLevel()) || //
+ Level.VERYVERBOSE.equals(LOGGER_GLOBAL_TOP.getLevel()) //
+ )) {
+ LOGGER_GLOBAL_TOP.setLevel(verbose);
}
- if(logger2.getLevel() == null || Level.INFO.equals(logger2.getLevel())) {
- logger2.setLevel(Level.WARNING);
+ if (LOGGER_ELKI_TOP.getLevel() != null && (//
+ Level.VERBOSE.equals(LOGGER_ELKI_TOP.getLevel()) || //
+ Level.VERYVERBOSE.equals(LOGGER_ELKI_TOP.getLevel()) //
+ )) {
+ LOGGER_ELKI_TOP.setLevel(verbose);
}
}
}
/**
* Enable runtime performance logging.
- *
- * @param time Flag
- */
- public static void setTime(boolean time) {
- Logger logger1 = Logger.getLogger("de.lmu.ifi.dbs.elki.workflow.AlgorithmStep");
- if(time) {
- // decrease to INFO if it was higher
- if(logger1.getLevel() == null || logger1.getLevel().intValue() > Level.INFO.intValue()) {
- logger1.setLevel(Level.INFO);
- }
+ */
+ public static void setStatistics() {
+ // decrease to INFO if it was higher
+ if (LOGGER_GLOBAL_TOP.getLevel() == null || LOGGER_GLOBAL_TOP.getLevel().intValue() > Level.STATISTICS.intValue()) {
+ LOGGER_GLOBAL_TOP.setLevel(Level.STATISTICS);
}
- else {
- // increase to warning level if it was INFO.
- if(logger1.getLevel() != null || logger1.getLevel() == Level.INFO) {
- logger1.setLevel(Level.WARNING);
- }
+ if (LOGGER_ELKI_TOP.getLevel() == null || LOGGER_ELKI_TOP.getLevel().intValue() > Level.STATISTICS.intValue()) {
+ LOGGER_ELKI_TOP.setLevel(Level.STATISTICS);
+ }
+ if (LOGGER_TIME_TOP.getLevel() == null || LOGGER_TIME_TOP.getLevel().intValue() > Level.STATISTICS.intValue()) {
+ LOGGER_TIME_TOP.setLevel(Level.STATISTICS);
}
}
@@ -199,8 +209,8 @@ public final class LoggingConfiguration {
*/
public static void replaceDefaultHandler(Handler handler) {
Logger rootlogger = LogManager.getLogManager().getLogger("");
- for(Handler h : rootlogger.getHandlers()) {
- if(h instanceof CLISmartHandler) {
+ for (Handler h : rootlogger.getHandlers()) {
+ if (h instanceof CLISmartHandler) {
rootlogger.removeHandler(h);
}
}
@@ -216,11 +226,11 @@ public final class LoggingConfiguration {
*/
public static void setLevelFor(String pkg, String level) throws IllegalArgumentException {
Logger logr = Logger.getLogger(pkg);
- if(logr == null) {
+ if (logr == null) {
throw new IllegalArgumentException("Logger not found.");
}
// Can also throw an IllegalArgumentException
- Level lev = Level.parse(level);
+ java.util.logging.Level lev = Level.parse(level);
logr.setLevel(lev);
}
@@ -229,7 +239,7 @@ public final class LoggingConfiguration {
*
* @param level level
*/
- public static void setDefaultLevel(Level level) {
+ public static void setDefaultLevel(java.util.logging.Level level) {
Logger.getLogger(TOPLEVEL_PACKAGE).setLevel(level);
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/logging/LoggingUtil.java b/src/de/lmu/ifi/dbs/elki/logging/LoggingUtil.java
index 1a48fc7a..ce62f419 100644
--- a/src/de/lmu/ifi/dbs/elki/logging/LoggingUtil.java
+++ b/src/de/lmu/ifi/dbs/elki/logging/LoggingUtil.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.logging;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/logging/MessageFormatter.java b/src/de/lmu/ifi/dbs/elki/logging/MessageFormatter.java
index 9c1f6046..6df68224 100644
--- a/src/de/lmu/ifi/dbs/elki/logging/MessageFormatter.java
+++ b/src/de/lmu/ifi/dbs/elki/logging/MessageFormatter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.logging;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/logging/OutputStreamLogger.java b/src/de/lmu/ifi/dbs/elki/logging/OutputStreamLogger.java
index 7bd09da0..7c618ec1 100644
--- a/src/de/lmu/ifi/dbs/elki/logging/OutputStreamLogger.java
+++ b/src/de/lmu/ifi/dbs/elki/logging/OutputStreamLogger.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.logging;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/logging/package-info.java b/src/de/lmu/ifi/dbs/elki/logging/package-info.java
index cb6f3377..8e20cb09 100644
--- a/src/de/lmu/ifi/dbs/elki/logging/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/logging/package-info.java
@@ -56,7 +56,7 @@ if (verbose) {
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/logging/progress/AbstractProgress.java b/src/de/lmu/ifi/dbs/elki/logging/progress/AbstractProgress.java
index 1d196533..ce97b84c 100644
--- a/src/de/lmu/ifi/dbs/elki/logging/progress/AbstractProgress.java
+++ b/src/de/lmu/ifi/dbs/elki/logging/progress/AbstractProgress.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.logging.progress;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/logging/progress/FiniteProgress.java b/src/de/lmu/ifi/dbs/elki/logging/progress/FiniteProgress.java
index 1ddc02f7..83419ef4 100644
--- a/src/de/lmu/ifi/dbs/elki/logging/progress/FiniteProgress.java
+++ b/src/de/lmu/ifi/dbs/elki/logging/progress/FiniteProgress.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.logging.progress;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/logging/progress/IndefiniteProgress.java b/src/de/lmu/ifi/dbs/elki/logging/progress/IndefiniteProgress.java
index 1dd61674..673ceea7 100644
--- a/src/de/lmu/ifi/dbs/elki/logging/progress/IndefiniteProgress.java
+++ b/src/de/lmu/ifi/dbs/elki/logging/progress/IndefiniteProgress.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.logging.progress;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/logging/progress/Progress.java b/src/de/lmu/ifi/dbs/elki/logging/progress/Progress.java
index 74125798..bb2151ba 100644
--- a/src/de/lmu/ifi/dbs/elki/logging/progress/Progress.java
+++ b/src/de/lmu/ifi/dbs/elki/logging/progress/Progress.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.logging.progress;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/logging/progress/ProgressLogRecord.java b/src/de/lmu/ifi/dbs/elki/logging/progress/ProgressLogRecord.java
index 64e8214e..8512ba9f 100644
--- a/src/de/lmu/ifi/dbs/elki/logging/progress/ProgressLogRecord.java
+++ b/src/de/lmu/ifi/dbs/elki/logging/progress/ProgressLogRecord.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.logging.progress;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/logging/progress/ProgressTracker.java b/src/de/lmu/ifi/dbs/elki/logging/progress/ProgressTracker.java
index ad3f7c37..c44fd1fd 100644
--- a/src/de/lmu/ifi/dbs/elki/logging/progress/ProgressTracker.java
+++ b/src/de/lmu/ifi/dbs/elki/logging/progress/ProgressTracker.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.logging.progress;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -40,7 +40,7 @@ public class ProgressTracker {
/**
* Set of potentially active progresses.
*/
- private ArrayList<WeakReference<Progress>> progresses = new ArrayList<WeakReference<Progress>>();
+ private ArrayList<WeakReference<Progress>> progresses = new ArrayList<>();
/**
* Get a list of progresses tracked.
@@ -48,7 +48,7 @@ public class ProgressTracker {
* @return List of progresses.
*/
public synchronized Collection<Progress> getProgresses() {
- List<Progress> list = new ArrayList<Progress>(progresses.size());
+ List<Progress> list = new ArrayList<>(progresses.size());
Iterator<WeakReference<Progress>> iter = progresses.iterator();
while(iter.hasNext()) {
WeakReference<Progress> ref = iter.next();
@@ -82,7 +82,7 @@ public class ProgressTracker {
}
}
}
- progresses.add(new WeakReference<Progress>(p));
+ progresses.add(new WeakReference<>(p));
}
/**
@@ -91,7 +91,7 @@ public class ProgressTracker {
* @return List of progresses removed.
*/
public synchronized Collection<Progress> removeCompleted() {
- List<Progress> list = new ArrayList<Progress>(progresses.size());
+ List<Progress> list = new ArrayList<>(progresses.size());
Iterator<WeakReference<Progress>> iter = progresses.iterator();
while(iter.hasNext()) {
WeakReference<Progress> ref = iter.next();
diff --git a/src/de/lmu/ifi/dbs/elki/logging/progress/StepProgress.java b/src/de/lmu/ifi/dbs/elki/logging/progress/StepProgress.java
index 1a0d3101..ee1225b6 100644
--- a/src/de/lmu/ifi/dbs/elki/logging/progress/StepProgress.java
+++ b/src/de/lmu/ifi/dbs/elki/logging/progress/StepProgress.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.logging.progress;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/logging/progress/package-info.java b/src/de/lmu/ifi/dbs/elki/logging/progress/package-info.java
index 8b25c703..61c53d8d 100644
--- a/src/de/lmu/ifi/dbs/elki/logging/progress/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/logging/progress/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveArrayStaticDBIDs.java b/src/de/lmu/ifi/dbs/elki/logging/statistics/AbstractStatistic.java
index 60dd50eb..8f0b7939 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveArrayStaticDBIDs.java
+++ b/src/de/lmu/ifi/dbs/elki/logging/statistics/AbstractStatistic.java
@@ -1,9 +1,10 @@
-package de.lmu.ifi.dbs.elki.database.ids.integer;
+package de.lmu.ifi.dbs.elki.logging.statistics;
+
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -22,31 +23,34 @@ package de.lmu.ifi.dbs.elki.database.ids.integer;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import gnu.trove.list.TIntList;
-
/**
- * Class accessing a trove int array.
+ * Abstract base class for statistics tracking.
*
* @author Erich Schubert
*/
-class TroveArrayStaticDBIDs extends TroveArrayDBIDs implements IntegerArrayStaticDBIDs {
+public abstract class AbstractStatistic implements Statistic {
/**
- * Actual trove store.
+ * Key to report the statistic with.
*/
- private final TIntList store;
+ String key;
/**
* Constructor.
*
- * @param store Actual trove store.
+ * @param key Tracking key
*/
- protected TroveArrayStaticDBIDs(TIntList store) {
+ public AbstractStatistic(String key) {
super();
- this.store = store;
+ this.key = key;
+ }
+
+ @Override
+ public String getKey() {
+ return key;
}
@Override
- protected TIntList getStore() {
- return store;
+ public String toString() {
+ return key + ": " + formatValue();
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/iterator/EmptyIterator.java b/src/de/lmu/ifi/dbs/elki/logging/statistics/AtomicLongCounter.java
index 6cbdad29..e200d93e 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/EmptyIterator.java
+++ b/src/de/lmu/ifi/dbs/elki/logging/statistics/AtomicLongCounter.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.utilities.iterator;
+package de.lmu.ifi.dbs.elki.logging.statistics;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,49 +23,50 @@ package de.lmu.ifi.dbs.elki.utilities.iterator;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.Iterator;
+import java.util.concurrent.atomic.AtomicLong;
/**
- * Empty iterator/iterable, that never returns any data.
+ * Class to count events in a thread-safe counter.
*
* @author Erich Schubert
- *
- * @param <T> Data type
*/
-public final class EmptyIterator<T> implements Iterator<T>, Iterable<T> {
+public class AtomicLongCounter extends AbstractStatistic implements Counter {
+ /**
+ * The counter to use.
+ */
+ AtomicLong counter = new AtomicLong(0);
+
+ /**
+ * Constructor.
+ *
+ * @param key Key to report.
+ */
+ public AtomicLongCounter(String key) {
+ super(key);
+ }
+
@Override
- public boolean hasNext() {
- return false;
+ public long increment() {
+ return counter.incrementAndGet();
}
@Override
- public T next() {
- return null;
+ public long decrement() {
+ return counter.decrementAndGet();
}
@Override
- public void remove() {
- throw new UnsupportedOperationException();
+ public long increment(long i) {
+ return counter.addAndGet(i);
}
-
+
@Override
- public Iterator<T> iterator() {
- return STATIC();
+ public long getValue() {
+ return counter.get();
}
- /**
- * Static instance
- */
- protected static final EmptyIterator<?> STATIC_INSTANCE = new EmptyIterator<Object>();
-
- /**
- * Access the static instance.
- *
- * @param <T> type to (not) iterate over
- * @return Cast static instance.
- */
- @SuppressWarnings("unchecked")
- public static <T> EmptyIterator<T> STATIC() {
- return (EmptyIterator<T>) STATIC_INSTANCE;
+ @Override
+ public String formatValue() {
+ return Long.toString(getValue());
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/logging/statistics/Counter.java b/src/de/lmu/ifi/dbs/elki/logging/statistics/Counter.java
new file mode 100644
index 00000000..0a39f1bd
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/logging/statistics/Counter.java
@@ -0,0 +1,62 @@
+package de.lmu.ifi.dbs.elki.logging.statistics;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Simple statistic by counting. For example: invocations of a method.
+ *
+ * @author Erich Schubert
+ */
+public interface Counter extends Statistic {
+ /**
+ * Increment the counter.
+ *
+ * @return Current value.
+ */
+ long increment();
+
+ /**
+ * Decrement the counter.
+ *
+ * @return Current value.
+ */
+ long decrement();
+
+ /**
+ * Get the current count.
+ *
+ * @return Current count.
+ */
+ long getValue();
+
+ /**
+ * Increment the counter by i.
+ *
+ * Note: the increment may be negative!
+ *
+ * @param i increment.
+ * @return Current count.
+ */
+ long increment(long i);
+}
diff --git a/src/de/lmu/ifi/dbs/elki/logging/statistics/DoubleStatistic.java b/src/de/lmu/ifi/dbs/elki/logging/statistics/DoubleStatistic.java
new file mode 100644
index 00000000..7754ccf1
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/logging/statistics/DoubleStatistic.java
@@ -0,0 +1,72 @@
+package de.lmu.ifi.dbs.elki.logging.statistics;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.utilities.FormatUtil;
+
+/**
+ * Trivial double-valued statistic.
+ *
+ * @author Erich Schubert
+ */
+public class DoubleStatistic extends AbstractStatistic {
+ /**
+ * Statistic value.
+ */
+ double value;
+
+ /**
+ * Constructor.
+ *
+ * @param key Key
+ */
+ public DoubleStatistic(String key) {
+ super(key);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param key Key
+ * @param value Value
+ */
+ public DoubleStatistic(String key, double value) {
+ super(key);
+ this.value = value;
+ }
+
+ /**
+ * Set the statistics.
+ *
+ * @param value New value
+ */
+ public void setDouble(double value) {
+ this.value = value;
+ }
+
+ @Override
+ public String formatValue() {
+ return FormatUtil.NF.format(value);
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/logging/statistics/Duration.java b/src/de/lmu/ifi/dbs/elki/logging/statistics/Duration.java
new file mode 100644
index 00000000..24799408
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/logging/statistics/Duration.java
@@ -0,0 +1,64 @@
+package de.lmu.ifi.dbs.elki.logging.statistics;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Class that tracks the duration of a task.
+ *
+ * TODO: add support for different time units?
+ *
+ * @author Erich Schubert
+ */
+public interface Duration extends Statistic {
+ /**
+ * Start the timer.
+ */
+ void begin();
+
+ /**
+ * Finish the timer.
+ */
+ void end();
+
+ /**
+ * Get the begin of the interval.
+ *
+ * @return Begin
+ */
+ long getBegin();
+
+ /**
+ * Get the end of the interval.
+ *
+ * @return End
+ */
+ long getEnd();
+
+ /**
+ * Get the duration of the interval.
+ *
+ * @return Duration
+ */
+ long getDuration();
+}
diff --git a/src/de/lmu/ifi/dbs/elki/logging/statistics/LongStatistic.java b/src/de/lmu/ifi/dbs/elki/logging/statistics/LongStatistic.java
new file mode 100644
index 00000000..5ac805e8
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/logging/statistics/LongStatistic.java
@@ -0,0 +1,70 @@
+package de.lmu.ifi.dbs.elki.logging.statistics;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Trivial long-valued statistic.
+ *
+ * @author Erich Schubert
+ */
+public class LongStatistic extends AbstractStatistic {
+ /**
+ * Statistic value.
+ */
+ long value;
+
+ /**
+ * Constructor.
+ *
+ * @param key Key
+ */
+ public LongStatistic(String key) {
+ super(key);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param key Key
+ * @param value Value
+ */
+ public LongStatistic(String key, long value) {
+ super(key);
+ this.value = value;
+ }
+
+ /**
+ * Set the statistics.
+ *
+ * @param value New value
+ */
+ public void setLong(long value) {
+ this.value = value;
+ }
+
+ @Override
+ public String formatValue() {
+ return Long.toString(value);
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/logging/statistics/MillisTimeDuration.java b/src/de/lmu/ifi/dbs/elki/logging/statistics/MillisTimeDuration.java
new file mode 100644
index 00000000..9f2cfd64
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/logging/statistics/MillisTimeDuration.java
@@ -0,0 +1,75 @@
+package de.lmu.ifi.dbs.elki.logging.statistics;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Class that tracks the runtime of a task with {@code System.nanoTime()}
+ *
+ * @author Erich Schubert
+ */
+public class MillisTimeDuration extends AbstractStatistic implements Duration {
+ /**
+ * Tracking variables.
+ */
+ long begin = -1, end = -2;
+
+ /**
+ * Constructor.
+ *
+ * @param key Key
+ */
+ public MillisTimeDuration(String key) {
+ super(key);
+ }
+
+ @Override
+ public void begin() {
+ begin = System.currentTimeMillis();
+ }
+
+ @Override
+ public void end() {
+ end = System.currentTimeMillis();
+ }
+
+ @Override
+ public long getBegin() {
+ return begin;
+ }
+
+ @Override
+ public long getEnd() {
+ return end;
+ }
+
+ @Override
+ public long getDuration() {
+ return (end - begin);
+ }
+
+ @Override
+ public String formatValue() {
+ return getDuration() + " ms";
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/logging/statistics/NanoDuration.java b/src/de/lmu/ifi/dbs/elki/logging/statistics/NanoDuration.java
new file mode 100644
index 00000000..77acbbdb
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/logging/statistics/NanoDuration.java
@@ -0,0 +1,75 @@
+package de.lmu.ifi.dbs.elki.logging.statistics;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Class that tracks the runtime of a task with {@code System.nanoTime()}
+ *
+ * @author Erich Schubert
+ */
+public class NanoDuration extends AbstractStatistic implements Duration {
+ /**
+ * Tracking variables.
+ */
+ long begin = -1, end = -2;
+
+ /**
+ * Constructor.
+ *
+ * @param key Key
+ */
+ public NanoDuration(String key) {
+ super(key);
+ }
+
+ @Override
+ public void begin() {
+ begin = System.nanoTime();
+ }
+
+ @Override
+ public void end() {
+ end = System.nanoTime();
+ }
+
+ @Override
+ public long getBegin() {
+ return begin;
+ }
+
+ @Override
+ public long getEnd() {
+ return end;
+ }
+
+ @Override
+ public long getDuration() {
+ return (end - begin);
+ }
+
+ @Override
+ public String formatValue() {
+ return getDuration() + " ns";
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/KernelDensityFunction.java b/src/de/lmu/ifi/dbs/elki/logging/statistics/Statistic.java
index 29718fcb..0d1a191a 100644
--- a/src/de/lmu/ifi/dbs/elki/math/statistics/KernelDensityFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/logging/statistics/Statistic.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.math.statistics;
+package de.lmu.ifi.dbs.elki.logging.statistics;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,18 +23,23 @@ package de.lmu.ifi.dbs.elki.math.statistics;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
/**
- * Inner function of a kernel density estimator.
+ * Abstract base interface for statistics tracking.
*
* @author Erich Schubert
*/
-public interface KernelDensityFunction {
+public interface Statistic {
+ /**
+ * Get the key of this statistic.
+ *
+ * @return Key
+ */
+ String getKey();
+
/**
- * Density contribution of a point at the given relative distance {@code delta}.
+ * Get a formatted version of the value, for output.
*
- * @param delta Relative distance
- * @return density contribution
+ * @return Value
*/
- public double density(double delta);
-} \ No newline at end of file
+ String formatValue();
+}
diff --git a/src/de/lmu/ifi/dbs/elki/logging/statistics/StringStatistic.java b/src/de/lmu/ifi/dbs/elki/logging/statistics/StringStatistic.java
new file mode 100644
index 00000000..2b7faed3
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/logging/statistics/StringStatistic.java
@@ -0,0 +1,70 @@
+package de.lmu.ifi.dbs.elki.logging.statistics;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Trivial string based statistic.
+ *
+ * @author Erich Schubert
+ */
+public class StringStatistic extends AbstractStatistic {
+ /**
+ * Storage
+ */
+ private String val;
+
+ /**
+ * Constructor.
+ *
+ * @param key Key
+ * @param val Value
+ */
+ public StringStatistic(String key, String val) {
+ super(key);
+ this.val = val;
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param key Key
+ */
+ public StringStatistic(String key) {
+ super(key);
+ }
+
+ /**
+ * Set the value.
+ *
+ * @param val Value
+ */
+ public void setString(String val) {
+ this.val = val;
+ }
+
+ @Override
+ public String formatValue() {
+ return val;
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/iterator/UnmodifiableIterator.java b/src/de/lmu/ifi/dbs/elki/logging/statistics/UnsynchronizedLongCounter.java
index 03c1119c..6068b652 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/UnmodifiableIterator.java
+++ b/src/de/lmu/ifi/dbs/elki/logging/statistics/UnsynchronizedLongCounter.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.utilities.iterator;
+package de.lmu.ifi.dbs.elki.logging.statistics;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,46 +23,49 @@ package de.lmu.ifi.dbs.elki.utilities.iterator;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.Iterator;
-
/**
- * Iterator proxy that does not allow modifications.
+ * Class to count events in a thread-safe counter.
*
* @author Erich Schubert
- *
- * @apiviz.stereotype decorator
- * @apiviz.composedOf Iterator oneway - - decorates
- *
- * @param <T>
*/
-public final class UnmodifiableIterator<T> implements Iterator<T> {
+public class UnsynchronizedLongCounter extends AbstractStatistic implements Counter {
/**
- * Real iterator
+ * The counter to use.
*/
- private Iterator<T> inner;
+ long counter = 0;
/**
* Constructor.
*
- * @param inner Real iterator to proxy.
+ * @param key Key to report.
*/
- public UnmodifiableIterator(Iterator<T> inner) {
- super();
- this.inner = inner;
+ public UnsynchronizedLongCounter(String key) {
+ super(key);
+ }
+
+ @Override
+ public long increment() {
+ return ++counter;
+ }
+
+ @Override
+ public long decrement() {
+ return --counter;
}
@Override
- public boolean hasNext() {
- return inner.hasNext();
+ public long increment(long i) {
+ counter += i;
+ return counter;
}
@Override
- public T next() {
- return inner.next();
+ public long getValue() {
+ return counter;
}
@Override
- public void remove() {
- throw new UnsupportedOperationException();
+ public String formatValue() {
+ return Long.toString(getValue());
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/logging/statistics/package-info.java b/src/de/lmu/ifi/dbs/elki/logging/statistics/package-info.java
new file mode 100644
index 00000000..ef9f5d98
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/logging/statistics/package-info.java
@@ -0,0 +1,24 @@
+/** Classes for logging various statistics. */
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package de.lmu.ifi.dbs.elki.logging.statistics; \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/math/DoubleMinMax.java b/src/de/lmu/ifi/dbs/elki/math/DoubleMinMax.java
index 56814649..1dfdc75d 100644
--- a/src/de/lmu/ifi/dbs/elki/math/DoubleMinMax.java
+++ b/src/de/lmu/ifi/dbs/elki/math/DoubleMinMax.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -68,8 +68,12 @@ public class DoubleMinMax extends DoubleDoublePair {
* @param data New value
*/
public void put(double data) {
- this.first = Math.min(this.first, data);
- this.second = Math.max(this.second, data);
+ if (data < first) {
+ first = data;
+ }
+ if (data > second) {
+ second = data;
+ }
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/math/GeoUtil.java b/src/de/lmu/ifi/dbs/elki/math/GeoUtil.java
deleted file mode 100644
index 226d8112..00000000
--- a/src/de/lmu/ifi/dbs/elki/math/GeoUtil.java
+++ /dev/null
@@ -1,670 +0,0 @@
-package de.lmu.ifi.dbs.elki.math;
-
-/*
- This file is part of ELKI:
- Environment for Developing KDD-Applications Supported by Index-Structures
-
- Copyright (C) 2012
- Ludwig-Maximilians-Universität München
- Lehr- und Forschungseinheit für Datenbanksysteme
- ELKI Development Team
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
-
-/**
- * Class with utility functions for geographic computations.
- *
- * The majority of formulas are adapted from:
- * <p>
- * Ed Williams<br />
- * Aviation Formulary<br />
- * Online: http://williams.best.vwh.net/avform.htm
- * </p>
- *
- * TODO: add ellipsoid version of Vinentry formula.
- *
- * @author Erich Schubert
- * @author Niels Dörre
- */
-@Reference(authors = "Ed Williams", title = "Aviation Formulary", booktitle = "", url = "http://williams.best.vwh.net/avform.htm")
-public final class GeoUtil {
- /**
- * Earth radius approximation in km.
- */
- public static final double EARTH_RADIUS = 6371.009; // km.
-
- /**
- * Radius of the WGS84 Ellipsoid in km.
- */
- public static final double WGS84_RADIUS = 6378.137; // km
-
- /**
- * Flattening of the WGS84 Ellipsoid.
- */
- public static final double WGS84_FLATTENING = 0.00335281066474748;
-
- /**
- * Eccentricity squared of the WGS84 Ellipsoid
- */
- public static final double WGS84_ECCENTRICITY_SQUARED = 2 * WGS84_FLATTENING - (WGS84_FLATTENING * WGS84_FLATTENING);
-
- /**
- * Dummy constructor. Do not instantiate.
- */
- private GeoUtil() {
- // Use static methods. Do not intantiate
- }
-
- /**
- * Compute the approximate on-earth-surface distance of two points using the
- * Haversine formula
- *
- * Complexity: 5 trigonometric functions, 2 sqrt.
- *
- * Reference:
- * <p>
- * R. W. Sinnott,<br/>
- * Virtues of the Haversine<br />
- * Sky and telescope, 68-2, 1984
- * </p>
- *
- * @param lat1 Latitude of first point in degree
- * @param lon1 Longitude of first point in degree
- * @param lat2 Latitude of second point in degree
- * @param lon2 Longitude of second point in degree
- * @return Distance in km (approximately)
- */
- @Reference(authors = "Sinnott, R. W.", title = "Virtues of the Haversine", booktitle = "Sky and telescope, 68-2, 1984")
- public static double haversineFormulaDeg(double lat1, double lon1, double lat2, double lon2) {
- // Convert to radians:
- lat1 = MathUtil.deg2rad(lat1);
- lat2 = MathUtil.deg2rad(lat2);
- lon1 = MathUtil.deg2rad(lon1);
- lon2 = MathUtil.deg2rad(lon2);
- return haversineFormulaRad(lat1, lon1, lat2, lon2);
- }
-
- /**
- * Compute the approximate on-earth-surface distance of two points using the
- * Haversine formula
- *
- * Complexity: 5 trigonometric functions, 2 sqrt.
- *
- * Reference:
- * <p>
- * R. W. Sinnott,<br/>
- * Virtues of the Haversine<br />
- * Sky and telescope, 68-2, 1984
- * </p>
- *
- * @param lat1 Latitude of first point in degree
- * @param lon1 Longitude of first point in degree
- * @param lat2 Latitude of second point in degree
- * @param lon2 Longitude of second point in degree
- * @return Distance in km (approximately)
- */
- @Reference(authors = "Sinnott, R. W.", title = "Virtues of the Haversine", booktitle = "Sky and telescope, 68-2, 1984")
- public static double haversineFormulaRad(double lat1, double lon1, double lat2, double lon2) {
- // Haversine formula, higher precision at < 1 meters but maybe issues at
- // antipodal points.
- final double slat = Math.sin((lat1 - lat2) * .5);
- final double slon = Math.sin((lon1 - lon2) * .5);
- final double a = slat * slat + slon * slon * Math.cos(lat1) * Math.cos(lat2);
- final double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
- return EARTH_RADIUS * c;
- }
-
- /**
- * Compute the approximate on-earth-surface distance of two points.
- *
- * Uses Vincenty's Formula for the spherical case, which does not require
- * iterations.
- *
- * Complexity: 7 trigonometric functions, 1 sqrt.
- *
- * Reference:
- * <p>
- * T. Vincenty<br />
- * Direct and inverse solutions of geodesics on the ellipsoid with application
- * of nested equations<br />
- * Survey review 23 176, 1975
- * </p>
- *
- * @param lat1 Latitude of first point in degree
- * @param lon1 Longitude of first point in degree
- * @param lat2 Latitude of second point in degree
- * @param lon2 Longitude of second point in degree
- * @return Distance in km (approximately)
- */
- @Reference(authors = "T. Vincenty", title = "Direct and inverse solutions of geodesics on the ellipsoid with application of nested equations", booktitle = "Survey review 23 176, 1975", url = "http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf")
- public static double sphericalVincentyFormulaDeg(double lat1, double lon1, double lat2, double lon2) {
- // Work in radians
- lat1 = MathUtil.deg2rad(lat1);
- lat2 = MathUtil.deg2rad(lat2);
- lon1 = MathUtil.deg2rad(lon1);
- lon2 = MathUtil.deg2rad(lon2);
- return sphericalVincentyFormulaRad(lat1, lon1, lat2, lon2);
- }
-
- /**
- * Compute the approximate on-earth-surface distance of two points.
- *
- * Uses Vincenty's Formula for the spherical case, which does not require
- * iterations.
- *
- * Complexity: 7 trigonometric functions, 1 sqrt.
- *
- * Reference:
- * <p>
- * T. Vincenty<br />
- * Direct and inverse solutions of geodesics on the ellipsoid with application
- * of nested equations<br />
- * Survey review 23 176, 1975
- * </p>
- *
- * @param lat1 Latitude of first point in degree
- * @param lon1 Longitude of first point in degree
- * @param lat2 Latitude of second point in degree
- * @param lon2 Longitude of second point in degree
- * @return Distance in km (approximately)
- */
- @Reference(authors = "T. Vincenty", title = "Direct and inverse solutions of geodesics on the ellipsoid with application of nested equations", booktitle = "Survey review 23 176, 1975", url = "http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf")
- public static double sphericalVincentyFormulaRad(double lat1, double lon1, double lat2, double lon2) {
- // Delta
- final double dlon = lon1 - lon2;
-
- // Spherical special case of Vincenty's formula - no iterations needed
- final double slat1 = Math.sin(lat1);
- final double slat2 = Math.sin(lat2);
- final double slond = Math.sin(dlon * .5);
- final double clat1 = Math.cos(lat1);
- final double clat2 = Math.cos(lat2);
- final double clond = Math.cos(dlon * .5);
- final double a = clat2 * slond;
- final double b = (clat1 * slat2) - (slat1 * clat2 * clond);
- final double d = Math.atan2(Math.sqrt(a * a + b * b), slat1 * slat2 + clat1 * clat2 * clond);
- return EARTH_RADIUS * d;
- }
-
- /**
- * Compute the cross-track distance.
- *
- * @param lat1 Latitude of starting point.
- * @param lon1 Longitude of starting point.
- * @param lat2 Latitude of destination point.
- * @param lon2 Longitude of destination point.
- * @param latQ Latitude of query point.
- * @param lonQ Longitude of query point.
- * @param dist1Q Distance from starting point to query point in km.
- * @return Cross-track distance in km. May be negative - this gives the side.
- */
- public static double crossTrackDistanceDeg(double lat1, double lon1, double lat2, double lon2, double latQ, double lonQ, double dist1Q) {
- // Convert to radians.
- lat1 = MathUtil.deg2rad(lat1);
- latQ = MathUtil.deg2rad(latQ);
- lat2 = MathUtil.deg2rad(lat2);
- lon1 = MathUtil.deg2rad(lon1);
- lonQ = MathUtil.deg2rad(lonQ);
- lon2 = MathUtil.deg2rad(lon2);
- return crossTrackDistanceRad(lat1, lon1, lat2, lon2, latQ, lonQ, dist1Q);
- }
-
- /**
- * Compute the cross-track distance.
- *
- * @param lat1 Latitude of starting point.
- * @param lon1 Longitude of starting point.
- * @param lat2 Latitude of destination point.
- * @param lon2 Longitude of destination point.
- * @param latQ Latitude of query point.
- * @param lonQ Longitude of query point.
- * @param dist1Q Distance from starting point to query point in km.
- * @return Cross-track distance in km. May be negative - this gives the side.
- */
- public static double crossTrackDistanceRad(double lat1, double lon1, double lat2, double lon2, double latQ, double lonQ, double dist1Q) {
- final double dlon12 = lon2 - lon1;
- final double dlon1Q = lonQ - lon1;
-
- // Compute trigonometric functions only once.
- final double slat1 = Math.sin(lat1);
- final double slatQ = Math.sin(latQ);
- final double slat2 = Math.sin(lat2);
- final double clat1 = Math.cos(lat1);
- final double clatQ = Math.cos(latQ);
- final double clat2 = Math.cos(lat2);
-
- // Compute the course
- final double crs12, crs1Q;
- {
- // y = sin(dlon) * cos(lat2)
- double yE = Math.sin(dlon12) * clat2;
- double yQ = Math.sin(dlon1Q) * clatQ;
-
- // x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dlon)
- double xE = clat1 * slat2 - slat1 * clat2 * Math.cos(dlon12);
- double xQ = clat1 * slatQ - slat1 * clatQ * Math.cos(dlon1Q);
-
- crs12 = Math.atan2(yE, xE);
- crs1Q = Math.atan2(yQ, xQ);
- }
-
- // Calculate cross-track distance
- return EARTH_RADIUS * Math.asin(Math.sin(dist1Q / EARTH_RADIUS) * Math.sin(crs1Q - crs12));
- }
-
- /**
- * Compute the cross-track distance.
- *
- * XTD = asin(sin(dist_1Q)*sin(crs_1Q-crs_12))
- *
- * @param lat1 Latitude of starting point.
- * @param lon1 Longitude of starting point.
- * @param lat2 Latitude of destination point.
- * @param lon2 Longitude of destination point.
- * @param latQ Latitude of query point.
- * @param lonQ Longitude of query point.
- * @return Cross-track distance in km. May be negative - this gives the side.
- */
- public static double crossTrackDistance(double lat1, double lon1, double lat2, double lon2, double latQ, double lonQ) {
- // Convert to radians.
- lat1 = MathUtil.deg2rad(lat1);
- latQ = MathUtil.deg2rad(latQ);
- lat2 = MathUtil.deg2rad(lat2);
- lon1 = MathUtil.deg2rad(lon1);
- lonQ = MathUtil.deg2rad(lonQ);
- lon2 = MathUtil.deg2rad(lon2);
- return crossTrackDistanceRad(lat1, lon1, lat2, lon2, latQ, lonQ);
- }
-
- /**
- * Compute the cross-track distance.
- *
- * XTD = asin(sin(dist_SQ)*sin(crs_SQ-crs_SE))
- *
- * @param lat1 Latitude of starting point.
- * @param lon1 Longitude of starting point.
- * @param lat2 Latitude of destination point.
- * @param lon2 Longitude of destination point.
- * @param latQ Latitude of query point.
- * @param lonQ Longitude of query point.
- * @return Cross-track distance in km. May be negative - this gives the side.
- */
- public static double crossTrackDistanceRad(double lat1, double lon1, double lat2, double lon2, double latQ, double lonQ) {
- final double dlon12 = lon2 - lon1;
- final double dlon1Q = lonQ - lon1;
-
- // Compute trigonometric functions only once.
- final double clat1 = Math.cos(lat1);
- final double clatQ = Math.cos(latQ);
- final double clat2 = Math.cos(lat2);
- final double slat1 = Math.sin(lat1);
- final double slatQ = Math.sin(latQ);
- final double slat2 = Math.sin(lat2);
-
- // Haversine formula, higher precision at < 1 meters but maybe issues at
- // antipodal points - we do not yet multiply with the radius!
- double angDist1Q;
- {
- final double slat = Math.sin((latQ - lat1) * .5);
- final double slon = Math.sin(dlon1Q * .5);
- final double a = slat * slat + slon * slon * clat1 * clatQ;
- angDist1Q = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
- }
-
- // Compute the course
- final double crs12, crs1Q;
- {
- // y = sin(dlon) * cos(lat2)
- double yE = Math.sin(dlon12) * clat2;
- double yQ = Math.sin(dlon1Q) * clatQ;
-
- // x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dlon)
- double xE = clat1 * slat2 - slat1 * clat2 * Math.cos(dlon12);
- double xQ = clat1 * slatQ - slat1 * clatQ * Math.cos(dlon1Q);
-
- crs12 = Math.atan2(yE, xE);
- crs1Q = Math.atan2(yQ, xQ);
- }
-
- // Calculate cross-track distance
- return EARTH_RADIUS * Math.asin(Math.sin(angDist1Q) * Math.sin(crs1Q - crs12));
- }
-
- /**
- * The along track distance, is the distance from S to Q along the track S to
- * E.
- *
- * ATD=acos(cos(dist_1Q)/cos(XTD))
- *
- * FIXME: can we get a proper sign into this?
- *
- * @param lat1 Latitude of starting point.
- * @param lon1 Longitude of starting point.
- * @param lat2 Latitude of destination point.
- * @param lon2 Longitude of destination point.
- * @param latQ Latitude of query point.
- * @param lonQ Longitude of query point.
- * @return Along-track distance in km. May be negative - this gives the side.
- */
- public static double alongTrackDistance(double lat1, double lon1, double lat2, double lon2, double latQ, double lonQ) {
- double dist1Q = haversineFormulaDeg(lat1, lon1, latQ, lonQ);
- double ctd = crossTrackDistanceDeg(lat1, lon1, lat2, lon2, latQ, lonQ, dist1Q);
- return alongTrackDistance(lat1, lon1, lat2, lon2, latQ, lonQ, dist1Q, ctd);
- }
-
- /**
- * The along track distance, is the distance from S to Q along the track S to
- * E.
- *
- * ATD=acos(cos(dist_SQ)/cos(XTD))
- *
- * FIXME: can we get a proper sign into this?
- *
- * @param lat1 Latitude of starting point.
- * @param lon1 Longitude of starting point.
- * @param lat2 Latitude of destination point.
- * @param lon2 Longitude of destination point.
- * @param latQ Latitude of query point.
- * @param lonQ Longitude of query point.
- * @param dist1Q Distance S to Q
- * @param ctd Cross-track-distance
- * @return Along-track distance in km. May be negative - this gives the side.
- */
- public static double alongTrackDistance(double lat1, double lon1, double lat2, double lon2, double latQ, double lonQ, double dist1Q, double ctd) {
- // TODO: optimize the sign computation!
- int sign = Math.abs(bearing(lat1, lon1, lat2, lon2) - bearing(lat1, lon1, latQ, lonQ)) < MathUtil.HALFPI ? +1 : -1;
- return sign * EARTH_RADIUS * Math.acos(Math.cos(dist1Q / EARTH_RADIUS) / Math.cos(ctd / EARTH_RADIUS));
- // TODO: for short distances, use this instead?
- // asin(sqrt( (sin(dist_1Q))^2 - (sin(XTD))^2 )/cos(XTD))
- }
-
- /**
- * Point to rectangle minimum distance.
- *
- * Complexity:
- * <ul>
- * <li>Trivial cases (on longitude slice): no trigonometric functions.</li>
- * <li>Cross-track case: 10+2 trig</li>
- * <li>Corner case: 10+3 trig, 2 sqrt</li>
- * </ul>
- *
- * @param plat Latitude of query point.
- * @param plng Longitude of query point.
- * @param rminlat Min latitude of rectangle.
- * @param rminlng Min longitude of rectangle.
- * @param rmaxlat Max latitude of rectangle.
- * @param rmaxlng Max longitude of rectangle.
- * @return Distance
- */
- public static double latlngMinDistDeg(double plat, double plng, double rminlat, double rminlng, double rmaxlat, double rmaxlng) {
- // Convert to radians.
- plat = MathUtil.deg2rad(plat);
- plng = MathUtil.deg2rad(plng);
- rminlat = MathUtil.deg2rad(rminlat);
- rminlng = MathUtil.deg2rad(rminlng);
- rmaxlat = MathUtil.deg2rad(rmaxlat);
- rmaxlng = MathUtil.deg2rad(rmaxlng);
-
- return latlngMinDistRad(plat, plng, rminlat, rminlng, rmaxlat, rmaxlng);
- }
-
- /**
- * Point to rectangle minimum distance.
- *
- * Complexity:
- * <ul>
- * <li>Trivial cases (on longitude slice): no trigonometric functions.</li>
- * <li>Cross-track case: 10+2 trig</li>
- * <li>Corner case: 10+3 trig, 2 sqrt</li>
- * </ul>
- *
- * @param plat Latitude of query point.
- * @param plng Longitude of query point.
- * @param rminlat Min latitude of rectangle.
- * @param rminlng Min longitude of rectangle.
- * @param rmaxlat Max latitude of rectangle.
- * @param rmaxlng Max longitude of rectangle.
- * @return Distance
- */
- public static double latlngMinDistRad(double plat, double plng, double rminlat, double rminlng, double rmaxlat, double rmaxlng) {
- // FIXME: handle rectangles crossing the +-180 deg boundary correctly!
-
- // Degenerate rectangles:
- if ((rminlat >= rmaxlat) && (rminlng >= rmaxlng)) {
- return haversineFormulaRad(rminlat, rminlng, plat, plng);
- }
-
- // The simplest case is when the query point is in the same "slice":
- if (rminlng <= plng && plng <= rmaxlng) {
- // Inside rectangle:
- if (rminlat <= plat && plat <= rmaxlat) {
- return 0;
- }
- // South:
- if (plat < rminlat) {
- return EARTH_RADIUS * (rminlat - plat);
- } else {
- // plat > rmaxlat
- return EARTH_RADIUS * (plat - rmaxlat);
- }
- }
-
- // Determine whether going east or west is shorter.
- double lngE = rminlng - plng;
- lngE += (lngE < 0) ? MathUtil.TWOPI : 0;
- double lngW = rmaxlng - plng;
- lngW -= (lngW > 0) ? MathUtil.TWOPI : 0;
-
- // Compute sine and cosine values we will certainly need below:
- final double slatQ = Math.sin(plat);
- final double clatQ = Math.cos(plat);
- final double slatN = Math.sin(rmaxlat);
- final double clatN = Math.cos(rmaxlat);
- final double slatS = Math.sin(rminlat);
- final double clatS = Math.cos(rminlat);
-
- // East, to min edge:
- if (lngE <= -lngW) {
- final double slngD = Math.sin(lngE);
- final double clngD = Math.cos(lngE);
-
- // Bearing to south
- // Math.atan2(slngD * clatS, clatQ * slatS - slatQ * clatS * clngD);
- // Bearing from south
- final double bs = Math.atan2(slngD * clatQ, clatS * slatQ - slatS * clatQ * clngD);
- // Bearing to north
- // Math.atan2(slngD * clatN, clatQ * slatN - slatQ * clatN * clngD);
- // Bearing from north
- final double bn = Math.atan2(slngD * clatQ, clatN * slatQ - slatN * clatQ * clngD);
- if (bs < MathUtil.HALFPI) {
- if (bn > MathUtil.HALFPI) {
- // Radians from south pole = abs(ATD)
- final double radFromS = -MathUtil.HALFPI - plat;
-
- // Cross-track-distance to longitude line.
- return EARTH_RADIUS * Math.asin(Math.sin(radFromS) * -slngD);
- }
- }
- if (bs - MathUtil.HALFPI < MathUtil.HALFPI - bn) {
- // Haversine to north corner.
- final double slatN2 = Math.sin((plat - rmaxlat) * .5);
- final double slon = Math.sin(lngE * .5);
- final double aN = slatN2 * slatN2 + slon * slon * clatQ * clatN;
- final double distN = 2 * Math.atan2(Math.sqrt(aN), Math.sqrt(1 - aN));
- return EARTH_RADIUS * distN;
- } else {
- // Haversine to south corner.
- final double slatS2 = Math.sin((plat - rminlat) * .5);
- final double slon = Math.sin(lngE * .5);
- final double aS = slatS2 * slatS2 + slon * slon * clatQ * clatS;
- final double distS = 2 * Math.atan2(Math.sqrt(aS), Math.sqrt(1 - aS));
- return EARTH_RADIUS * distS;
- }
- } else { // West, to max edge
- final double slngD = Math.sin(lngW);
- final double clngD = Math.cos(lngW);
-
- // Bearing to south
- // Math.atan2(slngD * clatS, clatQ * slatS - slatQ * clatS * clngD);
- // Bearing from south
- final double bs = Math.atan2(slngD * clatQ, clatS * slatQ - slatS * clatQ * clngD);
- // Bearing to north
- // Math.atan2(slngD * clatN, clatQ * slatN - slatQ * clatN * clngD);
- // Bearing from north
- final double bn = Math.atan2(slngD * clatQ, clatN * slatQ - slatN * clatQ * clngD);
- if (bs > -MathUtil.HALFPI) {
- if (bn < -MathUtil.HALFPI) {
- // Radians from south = abs(ATD) = distance from pole
- final double radFromS = -MathUtil.HALFPI - plat;
- // Cross-track-distance to longitude line.
- return EARTH_RADIUS * Math.asin(Math.sin(radFromS) * slngD);
- }
- }
- if (-MathUtil.HALFPI - bs < bn + MathUtil.HALFPI) {
- // Haversine to north corner.
- final double slatN2 = Math.sin((plat - rmaxlat) * .5);
- final double slon = Math.sin(lngW * .5);
- final double aN = slatN2 * slatN2 + slon * slon * clatQ * clatN;
- final double distN = 2 * Math.atan2(Math.sqrt(aN), Math.sqrt(1 - aN));
- return EARTH_RADIUS * distN;
- } else {
- // Haversine to south corner.
- final double slatS2 = Math.sin((plat - rminlat) * .5);
- final double slon = Math.sin(lngW * .5);
- final double aS = slatS2 * slatS2 + slon * slon * clatQ * clatS;
- final double distS = 2 * Math.atan2(Math.sqrt(aS), Math.sqrt(1 - aS));
- return EARTH_RADIUS * distS;
- }
- }
- }
-
- /**
- * Compute the bearing from start to end.
- *
- * @param latS Start latitude, in degree
- * @param lngS Start longitude, in degree
- * @param latE End latitude, in degree
- * @param lngE End longitude, in degree
- * @return Bearing in radians
- */
- public static double bearing(double latS, double lngS, double latE, double lngE) {
- latS = MathUtil.deg2rad(latS);
- latE = MathUtil.deg2rad(latE);
- lngS = MathUtil.deg2rad(lngS);
- lngE = MathUtil.deg2rad(lngE);
- final double slatS = Math.sin(latS);
- final double clatS = Math.cos(latS);
- final double slatE = Math.sin(latE);
- final double clatE = Math.cos(latE);
- return Math.atan2(-Math.sin(lngS - lngE) * clatE, clatS * slatE - slatS * clatE * Math.cos(lngS - lngE));
- }
-
- /**
- * Map a latitude,longitude pair to 3D X-Y-Z coordinates, using athe WGS84
- * ellipsoid.
- *
- * The coordinate system is chosen such that the earth rotates around the Z
- * axis.
- *
- * @param lat Latitude in degree
- * @param lng Longitude in degree
- * @return Coordinate triple
- */
- public static double[] latLngDegToXZYWGS84(double lat, double lng) {
- // Switch to radians:
- lat = Math.toRadians(lat);
- lng = Math.toRadians(lng);
- // Sine and cosines:
- final double clat = Math.cos(lat), slat = Math.sin(lat);
- final double clng = Math.cos(lng), slng = Math.sin(lng);
-
- // Eccentricity squared
- final double v = WGS84_RADIUS / (Math.sqrt(1 - WGS84_ECCENTRICITY_SQUARED * slat * slat));
-
- return new double[] { v * clat * clng, v * clat * slng, (1 - WGS84_ECCENTRICITY_SQUARED) * v * slat };
- }
-
- /**
- * Convert Latitude-Longitude pair to X-Y-Z coordinates using a spherical
- * approximation of the earth.
- *
- * The coordinate system is chosen such that the earth rotates around the Z
- * axis.
- *
- * @param lat Latitude in degree
- * @param lng Longitude in degree
- * @return Coordinate triple
- */
- public static double[] latLngDegToXZY(double lat, double lng) {
- // Map to radians.
- lat = MathUtil.rad2deg(lat);
- lng = MathUtil.rad2deg(lng);
- // Sine and cosines:
- final double clat = Math.cos(lat), slat = Math.sin(lat);
- final double clng = Math.cos(lng), slng = Math.sin(lng);
- return new double[] { EARTH_RADIUS * clat * clng, EARTH_RADIUS * clat * slng, EARTH_RADIUS * slat };
- }
-
- /**
- * Convert a 3D coordinate pair to the corresponding longitude.
- *
- * Only x and y are required - z gives the latitude.
- *
- * @param x X value
- * @param y Y value
- * @return Latitude
- */
- public static double xyzToLatDegWGS84(double x, double y, double z) {
- final double p = Math.sqrt(x * x + y * y);
- double lat = Math.atan2(z, p * (1 - WGS84_ECCENTRICITY_SQUARED));
-
- // Iteratively improving the lat value
- // TODO: instead of a fixed number of iterations, check for convergence.
- for (int i = 0; i < 10; i++) {
- final double slat = Math.sin(lat);
- final double v = WGS84_RADIUS / (Math.sqrt(1 - WGS84_ECCENTRICITY_SQUARED * slat * slat));
- lat = Math.atan2(z + WGS84_ECCENTRICITY_SQUARED * v * slat, p);
- }
-
- return MathUtil.rad2deg(lat);
- }
-
- /**
- * Convert a 3D coordinate pair to the corresponding latitude.
- *
- * Only the z coordinate is required.
- *
- * @param z Z value
- * @return Latitude
- */
- public static double xyzToLatDeg(double z) {
- return MathUtil.rad2deg(Math.asin(z / EARTH_RADIUS));
- }
-
- /**
- * Convert a 3D coordinate pair to the corresponding longitude.
- *
- * Only x and y are required - z gives the latitude.
- *
- * @param x X value
- * @param y Y value
- * @return Latitude
- */
- public static double xyzToLngDeg(double x, double y) {
- return MathUtil.rad2deg(Math.atan2(y, x));
- }
-}
diff --git a/src/de/lmu/ifi/dbs/elki/math/IntegerMinMax.java b/src/de/lmu/ifi/dbs/elki/math/IntegerMinMax.java
index 4c89240b..5804f057 100644
--- a/src/de/lmu/ifi/dbs/elki/math/IntegerMinMax.java
+++ b/src/de/lmu/ifi/dbs/elki/math/IntegerMinMax.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/MathUtil.java b/src/de/lmu/ifi/dbs/elki/math/MathUtil.java
index aaa19f0d..27de942e 100644
--- a/src/de/lmu/ifi/dbs/elki/math/MathUtil.java
+++ b/src/de/lmu/ifi/dbs/elki/math/MathUtil.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -43,12 +43,32 @@ public final class MathUtil {
/**
* Two times Pi.
*/
- public static final double TWOPI = 2 * Math.PI;
+ public static final double TWOPI = 2. * Math.PI;
/**
* Half the value of Pi.
*/
- public static final double HALFPI = 0.5 * Math.PI;
+ public static final double HALFPI = .5 * Math.PI;
+
+ /**
+ * One quarter of Pi.
+ */
+ public static final double QUARTERPI = .25 * Math.PI;
+
+ /**
+ * 1.5 times Pi.
+ */
+ public static final double ONEHALFPI = 1.5 * Math.PI;
+
+ /**
+ * Pi squared
+ */
+ public static final double PISQUARE = Math.PI * Math.PI;
+
+ /**
+ * Square root of Pi.
+ */
+ public static final double SQRTPI = Math.sqrt(Math.PI);
/**
* Square root of two times Pi.
@@ -56,14 +76,19 @@ public final class MathUtil {
public static final double SQRTTWOPI = Math.sqrt(TWOPI);
/**
+ * Constant for sqrt(pi/2)
+ */
+ public static final double SQRTHALFPI = Math.sqrt(HALFPI);
+
+ /**
* Square root of 2.
*/
- public static final double SQRT2 = Math.sqrt(2);
+ public static final double SQRT2 = Math.sqrt(2.);
/**
* Square root of 5.
*/
- public static final double SQRT5 = Math.sqrt(5);
+ public static final double SQRT5 = Math.sqrt(5.);
/**
* Square root of 0.5 == 1 / sqrt(2).
@@ -73,17 +98,27 @@ public final class MathUtil {
/**
* Precomputed value of 1 / sqrt(pi).
*/
- public static final double ONE_BY_SQRTPI = 1 / Math.sqrt(Math.PI);
+ public static final double ONE_BY_SQRTPI = 1. / SQRTPI;
+
+ /**
+ * Precomputed value of 1 / sqrt(2 * pi).
+ */
+ public static final double ONE_BY_SQRTTWOPI = 1. / SQRTTWOPI;
/**
* Logarithm of 2 to the basis e, for logarithm conversion.
*/
- public static final double LOG2 = Math.log(2);
+ public static final double LOG2 = Math.log(2.);
+
+ /**
+ * Logarithm of 3 to the basis e, for logarithm conversion.
+ */
+ public static final double LOG3 = Math.log(3.);
/**
* Natural logarithm of 10.
*/
- public static final double LOG10 = Math.log(10);
+ public static final double LOG10 = Math.log(10.);
/**
* Math.log(Math.PI).
@@ -101,6 +136,11 @@ public final class MathUtil {
public static final double LOGSQRTTWOPI = Math.log(SQRTTWOPI);
/**
+ * Log(log(2))
+ */
+ public static final double LOGLOG2 = Math.log(LOG2);
+
+ /**
* Constant for degrees to radians.
*/
public static final double DEG2RAD = Math.PI / 180.0;
@@ -557,6 +597,61 @@ public final class MathUtil {
}
/**
+ * Normalize an angle to [0:2pi[
+ *
+ * @param x Input angle
+ * @return Normalized angle
+ */
+ public static double normAngle(double x) {
+ x %= TWOPI;
+ if (x > 0) {
+ return x;
+ } else {
+ return x + TWOPI;
+ }
+ }
+
+ /**
+ * <b>Fast</b> way of computing cos(x) from x and sin(x).
+ *
+ * @param angle Input angle x
+ * @param sin Sine of x.
+ * @return Cosine of x
+ */
+ public static double sinToCos(double angle, double sin) {
+ // Numerics of the formula below aren't too good.
+ if ((-1e-5 < sin && sin < 1e-5) || sin > 0.99999 || sin < -0.99999) {
+ return Math.cos(angle);
+ }
+ angle = normAngle(angle);
+ if (angle < HALFPI || angle > ONEHALFPI) {
+ return Math.sqrt(1 - sin * sin);
+ } else {
+ return -Math.sqrt(1 - sin * sin);
+ }
+ }
+
+ /**
+ * <b>Fast</b> way of computing sin(x) from x and cos(x).
+ *
+ * @param angle Input angle x
+ * @param cos Cosine of x.
+ * @return Sine of x
+ */
+ public static double cosToSin(double angle, double cos) {
+ // Numerics of the formula below aren't too good.
+ if ((-1e-5 < cos && cos < 1e-5) || cos > 0.99999 || cos < -0.99999) {
+ return Math.sin(angle);
+ }
+ angle = normAngle(angle);
+ if (angle < Math.PI) {
+ return Math.sqrt(1 - cos * cos);
+ } else {
+ return -Math.sqrt(1 - cos * cos);
+ }
+ }
+
+ /**
* Find the next power of 2.
*
* Classic bit operation, for signed 32-bit. Valid for positive integers only
@@ -745,4 +840,14 @@ public final class MathUtil {
return Double.longBitsToDouble(bits);
}
}
+
+ /**
+ * More stable than {@code Math.log(1 - Math.exp(x))}
+ *
+ * @param x Value
+ * @return log(1-exp(x))
+ */
+ public static double log1mexp(double x) {
+ return (x > -LOG2) ? Math.log(-Math.expm1(x)) : Math.log1p(-Math.exp(x));
+ }
}
diff --git a/src/de/lmu/ifi/dbs/elki/math/Mean.java b/src/de/lmu/ifi/dbs/elki/math/Mean.java
index 56f73f8e..5b943a2f 100644
--- a/src/de/lmu/ifi/dbs/elki/math/Mean.java
+++ b/src/de/lmu/ifi/dbs/elki/math/Mean.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -53,14 +53,14 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
@Reference(authors = "B. P. Welford", title = "Note on a method for calculating corrected sums of squares and products", booktitle = "Technometrics 4(3)")
public class Mean {
/**
- * Mean of values
+ * Mean of values - first moment.
*/
- protected double mean = 0.0;
+ protected double m1 = 0.0;
/**
- * Weight sum (number of samples)
+ * Weight sum (number of samples).
*/
- protected double wsum = 0;
+ protected double n = 0;
/**
* Empty constructor
@@ -75,8 +75,8 @@ public class Mean {
* @param other other instance to copy data from.
*/
public Mean(Mean other) {
- this.mean = other.mean;
- this.wsum = other.wsum;
+ this.m1 = other.m1;
+ this.n = other.n;
}
/**
@@ -85,9 +85,9 @@ public class Mean {
* @param val Value
*/
public void put(double val) {
- wsum += 1.0;
- final double delta = val - mean;
- mean += delta / wsum;
+ n += 1.0;
+ final double delta = val - m1;
+ m1 += delta / n;
}
/**
@@ -100,11 +100,11 @@ public class Mean {
* @param weight weight
*/
public void put(double val, double weight) {
- final double nwsum = weight + wsum;
- final double delta = val - mean;
+ final double nwsum = weight + n;
+ final double delta = val - m1;
final double rval = delta * weight / nwsum;
- mean += rval;
- wsum = nwsum;
+ m1 += rval;
+ n = nwsum;
}
/**
@@ -113,12 +113,12 @@ public class Mean {
* @param other Data to join with
*/
public void put(Mean other) {
- final double nwsum = other.wsum + this.wsum;
+ final double nwsum = other.n + this.n;
// this.mean += rval;
// This supposedly is more numerically stable:
- this.mean = (this.wsum * this.mean + other.wsum * other.mean) / nwsum;
- this.wsum = nwsum;
+ this.m1 = (this.n * this.m1 + other.n * other.m1) / nwsum;
+ this.n = nwsum;
}
/**
@@ -127,7 +127,7 @@ public class Mean {
* @return number of data points
*/
public double getCount() {
- return wsum;
+ return n;
}
/**
@@ -136,7 +136,7 @@ public class Mean {
* @return mean
*/
public double getMean() {
- return mean;
+ return m1;
}
/**
@@ -162,7 +162,7 @@ public class Mean {
* Reset the value.
*/
public void reset() {
- mean = 0;
- wsum = 0;
+ m1 = 0;
+ n = 0;
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/math/MeanVariance.java b/src/de/lmu/ifi/dbs/elki/math/MeanVariance.java
index 0210b0fb..7723daa4 100644
--- a/src/de/lmu/ifi/dbs/elki/math/MeanVariance.java
+++ b/src/de/lmu/ifi/dbs/elki/math/MeanVariance.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -62,7 +62,7 @@ public class MeanVariance extends Mean {
/**
* nVariance
*/
- protected double nvar = 0.0;
+ protected double m2 = 0.0;
/**
* Empty constructor
@@ -77,9 +77,9 @@ public class MeanVariance extends Mean {
* @param other other instance to copy data from.
*/
public MeanVariance(MeanVariance other) {
- this.mean = other.mean;
- this.nvar = other.nvar;
- this.wsum = other.wsum;
+ this.m1 = other.m1;
+ this.m2 = other.m2;
+ this.n = other.n;
}
/**
@@ -89,11 +89,11 @@ public class MeanVariance extends Mean {
*/
@Override
public void put(double val) {
- wsum += 1.0;
- final double delta = val - mean;
- mean += delta / wsum;
+ n += 1.0;
+ final double delta = val - m1;
+ m1 += delta / n;
// The next line needs the *new* mean!
- nvar += delta * (val - mean);
+ m2 += delta * (val - m1);
}
/**
@@ -106,14 +106,15 @@ public class MeanVariance extends Mean {
* @param weight weight
*/
@Override
+ @Reference(authors = "D.H.D. West", title = "Updating Mean and Variance Estimates: An Improved Method", booktitle = "Communications of the ACM, Volume 22 Issue 9")
public void put(double val, double weight) {
- final double nwsum = weight + wsum;
- final double delta = val - mean;
+ final double nwsum = weight + n;
+ final double delta = val - m1;
final double rval = delta * weight / nwsum;
- mean += rval;
+ m1 += rval;
// Use old and new weight sum here:
- nvar += wsum * delta * rval;
- wsum = nwsum;
+ m2 += n * delta * rval;
+ n = nwsum;
}
/**
@@ -123,18 +124,17 @@ public class MeanVariance extends Mean {
*/
@Override
public void put(Mean other) {
- if(other instanceof MeanVariance) {
- final double nwsum = other.wsum + this.wsum;
- final double delta = other.mean - this.mean;
- final double rval = delta * other.wsum / nwsum;
+ if (other instanceof MeanVariance) {
+ final double nwsum = other.n + this.n;
+ final double delta = other.m1 - this.m1;
+ final double rval = delta * other.n / nwsum;
// this.mean += rval;
// This supposedly is more numerically stable:
- this.mean = (this.wsum * this.mean + other.wsum * other.mean) / nwsum;
- this.nvar += ((MeanVariance) other).nvar + delta * this.wsum * rval;
- this.wsum = nwsum;
- }
- else {
+ this.m1 = (this.n * this.m1 + other.n * other.m1) / nwsum;
+ this.m2 += ((MeanVariance) other).m2 + delta * this.n * rval;
+ this.n = nwsum;
+ } else {
throw new AbortException("I cannot combine Mean and MeanVariance to a MeanVariance.");
}
}
@@ -146,7 +146,7 @@ public class MeanVariance extends Mean {
*/
@Override
public double getCount() {
- return wsum;
+ return n;
}
/**
@@ -156,7 +156,7 @@ public class MeanVariance extends Mean {
*/
@Override
public double getMean() {
- return mean;
+ return m1;
}
/**
@@ -167,7 +167,7 @@ public class MeanVariance extends Mean {
* @return variance
*/
public double getNaiveVariance() {
- return nvar / wsum;
+ return m2 / n;
}
/**
@@ -176,8 +176,10 @@ public class MeanVariance extends Mean {
* @return sample variance
*/
public double getSampleVariance() {
- assert (wsum > 1) : "Cannot compute a reasonable sample variance with weight <= 1.0!";
- return nvar / (wsum - 1);
+ if (!(n > 1.)) {
+ throw new ArithmeticException("Cannot compute a reasonable sample variance with weight <= 1.0!");
+ }
+ return m2 / (n - 1);
}
/**
@@ -230,7 +232,7 @@ public class MeanVariance extends Mean {
*/
public static MeanVariance[] newArray(int dimensionality) {
MeanVariance[] arr = new MeanVariance[dimensionality];
- for(int i = 0; i < dimensionality; i++) {
+ for (int i = 0; i < dimensionality; i++) {
arr[i] = new MeanVariance();
}
return arr;
@@ -244,6 +246,6 @@ public class MeanVariance extends Mean {
@Override
public void reset() {
super.reset();
- nvar = 0;
+ m2 = 0;
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/MeanVarianceMinMax.java b/src/de/lmu/ifi/dbs/elki/math/MeanVarianceMinMax.java
index 4ea76002..027a302d 100644
--- a/src/de/lmu/ifi/dbs/elki/math/MeanVarianceMinMax.java
+++ b/src/de/lmu/ifi/dbs/elki/math/MeanVarianceMinMax.java
@@ -1,12 +1,10 @@
package de.lmu.ifi.dbs.elki.math;
-import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
-
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,6 +22,9 @@ import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
+import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
+
/**
* Class collecting mean, variance, minimum and maximum statistics.
*
@@ -61,25 +62,32 @@ public class MeanVarianceMinMax extends MeanVariance {
@Override
public void put(double val) {
super.put(val);
- min = Math.min(min, val);
- max = Math.max(max, val);
+ if (val < min) {
+ min = val;
+ }
+ if (val > max) {
+ max = val;
+ }
}
@Override
public void put(double val, double weight) {
super.put(val, weight);
- min = Math.min(min, val);
- max = Math.max(max, val);
+ if (val < min) {
+ min = val;
+ }
+ if (val > max) {
+ max = val;
+ }
}
@Override
public void put(Mean other) {
- if(other instanceof MeanVarianceMinMax) {
+ if (other instanceof MeanVarianceMinMax) {
super.put(other);
min = Math.min(min, ((MeanVarianceMinMax) other).min);
max = Math.max(max, ((MeanVarianceMinMax) other).max);
- }
- else {
+ } else {
throw new AbortException("Cannot aggregate into a minmax statistic: " + other.getClass());
}
}
@@ -101,14 +109,14 @@ public class MeanVarianceMinMax extends MeanVariance {
public double getMax() {
return this.max;
}
-
+
/**
* Get the current minimum and maximum.
*
* @return current minimum and maximum
*/
- public DoubleMinMax getDoubleMinMax(){
- return new DoubleMinMax(this.min,this.max);
+ public DoubleMinMax getDoubleMinMax() {
+ return new DoubleMinMax(this.min, this.max);
}
/**
@@ -119,7 +127,7 @@ public class MeanVarianceMinMax extends MeanVariance {
public double getDiff() {
return this.getMax() - this.getMin();
}
-
+
/**
* Create and initialize a new array of MeanVarianceMinMax
*
@@ -128,7 +136,7 @@ public class MeanVarianceMinMax extends MeanVariance {
*/
public static MeanVarianceMinMax[] newArray(int dimensionality) {
MeanVarianceMinMax[] arr = new MeanVarianceMinMax[dimensionality];
- for(int i = 0; i < dimensionality; i++) {
+ for (int i = 0; i < dimensionality; i++) {
arr[i] = new MeanVarianceMinMax();
}
return arr;
@@ -145,4 +153,4 @@ public class MeanVarianceMinMax extends MeanVariance {
min = Double.POSITIVE_INFINITY;
max = Double.NEGATIVE_INFINITY;
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/MinMax.java b/src/de/lmu/ifi/dbs/elki/math/MinMax.java
index 98b66173..d3ee45bd 100644
--- a/src/de/lmu/ifi/dbs/elki/math/MinMax.java
+++ b/src/de/lmu/ifi/dbs/elki/math/MinMax.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -178,7 +178,7 @@ public class MinMax<T extends Comparable<? super T>> extends Pair<T, T> {
Class<MinMax<N>> mmcls = ClassGenericsUtil.uglyCastIntoSubclass(MinMax.class);
MinMax<N>[] mms = ClassGenericsUtil.newArrayOfNull(size, mmcls);
for(int i = 0; i < size; i++) {
- mms[i] = new MinMax<N>();
+ mms[i] = new MinMax<>();
}
return mms;
}
diff --git a/src/de/lmu/ifi/dbs/elki/math/PearsonCorrelation.java b/src/de/lmu/ifi/dbs/elki/math/PearsonCorrelation.java
index 175f128d..4cd9c732 100644
--- a/src/de/lmu/ifi/dbs/elki/math/PearsonCorrelation.java
+++ b/src/de/lmu/ifi/dbs/elki/math/PearsonCorrelation.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/Primes.java b/src/de/lmu/ifi/dbs/elki/math/Primes.java
index e9ac0463..5755df1a 100644
--- a/src/de/lmu/ifi/dbs/elki/math/Primes.java
+++ b/src/de/lmu/ifi/dbs/elki/math/Primes.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/SinCosTable.java b/src/de/lmu/ifi/dbs/elki/math/SinCosTable.java
index 16b89772..6cabb172 100644
--- a/src/de/lmu/ifi/dbs/elki/math/SinCosTable.java
+++ b/src/de/lmu/ifi/dbs/elki/math/SinCosTable.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -97,7 +97,7 @@ public abstract class SinCosTable {
double ang = 0.;
for (int i = 0; i < steps; i++, ang += radstep) {
this.costable[i] = Math.cos(ang);
- this.sintable[i] = Math.sin(ang);
+ this.sintable[i] = MathUtil.cosToSin(ang, this.costable[i]);
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/math/StatisticalMoments.java b/src/de/lmu/ifi/dbs/elki/math/StatisticalMoments.java
new file mode 100644
index 00000000..af42c2e5
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/StatisticalMoments.java
@@ -0,0 +1,282 @@
+package de.lmu.ifi.dbs.elki.math;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
+
+/**
+ * Track various statistical moments, including mean, variance, skewness and
+ * kurtosis.
+ *
+ * References:
+ * <p>
+ * T. B. Terriberry<br />
+ * Computing Higher-Order Moments Online<br/>
+ * http://people.xiph.org/~tterribe/notes/homs.html
+ * </p>
+ *
+ * General recurrence, for higher order moments, can be found in:
+ * <p>
+ * Philippe Pébay<br />
+ * Formulas for Robust, One-Pass Parallel Computation of Covariances and
+ * Arbitrary-Order Statistical Moments<br />
+ * Sandia Report SAND2008-6212, Sandia National Laboratories
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@Reference(authors = "T. B. Terriberry", title = "Computing Higher-Order Moments Online", booktitle = "Online - Technical Note", url = "http://people.xiph.org/~tterribe/notes/homs.html")
+public class StatisticalMoments extends MeanVarianceMinMax {
+ /**
+ * Third moment.
+ */
+ double m3;
+
+ /**
+ * Fourth moment.
+ */
+ double m4;
+
+ /**
+ * Empty constructor
+ */
+ public StatisticalMoments() {
+ // nothing to do here, initialization done above.
+ }
+
+ /**
+ * Constructor from other instance
+ *
+ * @param other other instance to copy data from.
+ */
+ public StatisticalMoments(StatisticalMoments other) {
+ this.m1 = other.m1;
+ this.m2 = other.m2;
+ this.n = other.n;
+ this.m3 = other.m3;
+ this.m4 = other.m4;
+ }
+
+ /**
+ * Add a single value with weight 1.0
+ *
+ * @param val Value
+ */
+ @Override
+ public void put(double val) {
+ final double nn = this.n + 1.0;
+ final double delta = val - m1;
+ final double delta_nn = delta / nn;
+ final double delta_nn2 = delta_nn * delta_nn;
+ final double inc = delta * delta_nn * this.n;
+
+ // Update values:
+ m4 += inc * delta_nn2 * (nn * nn - 3. * nn + 3.) + 6. * delta_nn2 * m2 - 4. * delta_nn * m3;
+ m3 += inc * delta_nn * (nn - 2) - 3. * delta_nn * m2;
+ m2 += inc;
+ m1 += delta_nn;
+ n = nn;
+
+ min = Math.min(min, val);
+ max = Math.max(max, val);
+ }
+
+ /**
+ * Add data with a given weight.
+ *
+ * @param val data
+ * @param weight weight
+ */
+ @Override
+ public void put(double val, double weight) {
+ // TODO: any way of further simplifying this?
+ // Right now it is copy & paste from the merge formula.
+ final double nn = weight + this.n;
+ final double delta = val - this.m1;
+
+ // Some factors used below:
+ final double otherm2 = val * val;
+ final double otherm3 = otherm2 * val;
+ final double otherm4 = otherm3 * val;
+
+ final double delta_nn = delta / nn;
+ final double delta_nn2 = delta_nn * delta_nn;
+ final double delta_nn3 = delta_nn2 * delta_nn;
+ final double na2 = this.n * this.n;
+ final double nb2 = weight * weight;
+ final double ntn = this.n * weight;
+
+ this.m4 += otherm4 + delta * delta_nn3 * ntn * (na2 - ntn + nb2) + 6. * (na2 * otherm2 + nb2 * this.m2) * delta_nn2 + 4. * (this.n * otherm3 - weight * this.m3) * delta_nn;
+ this.m3 += otherm3 + delta * delta_nn2 * ntn * (this.n - weight) + 3. * (this.n * otherm2 - weight * this.m2) * delta_nn;
+ this.m2 += otherm2 + delta * delta_nn * this.n * weight;
+ this.m1 += weight * delta_nn;
+ this.n = nn;
+
+ min = Math.min(min, val);
+ max = Math.max(max, val);
+ }
+
+ /**
+ * Join the data of another MeanVariance instance.
+ *
+ * @param other Data to join with
+ */
+ @Override
+ public void put(Mean other) {
+ if (other instanceof StatisticalMoments) {
+ StatisticalMoments othe = (StatisticalMoments) other;
+ final double nn = othe.n + this.n;
+ final double delta = othe.m1 - this.m1;
+
+ // Some factors used below:
+ final double delta_nn = delta / nn;
+ final double delta_nn2 = delta_nn * delta_nn;
+ final double delta_nn3 = delta_nn2 * delta_nn;
+ final double na2 = this.n * this.n;
+ final double nb2 = othe.n * othe.n;
+ final double ntn = this.n * othe.n;
+
+ this.m4 += othe.m4 + delta * delta_nn3 * ntn * (na2 - ntn + nb2) + 6. * (na2 * othe.m2 + nb2 * this.m2) * delta_nn2 + 4. * (this.n * othe.m3 - othe.n * this.m3) * delta_nn;
+ this.m3 += othe.m3 + delta * delta_nn2 * ntn * (this.n - othe.n) + 3. * (this.n * othe.m2 - othe.n * this.m2) * delta_nn;
+ this.m2 += othe.m2 + delta * delta_nn * this.n * othe.n;
+ this.m1 += othe.n * delta_nn;
+ this.n = nn;
+
+ min = Math.min(min, othe.min);
+ max = Math.max(max, othe.max);
+ } else {
+ throw new AbortException("I cannot combine Mean or MeanVariance into to a StatisticalMoments class.");
+ }
+ }
+
+ /**
+ * Get the skewness using sample variance.
+ *
+ * @return Skewness
+ */
+ public double getSampleSkewness() {
+ assert (n > 2.) : "Cannot compute a reasonable sample skewness with weight <= 2.0!";
+ double sigma2 = getSampleVariance();
+ return (m3 * n / (n - 1) / (n - 2)) / Math.pow(sigma2, 1.5);
+ }
+
+ /**
+ * Get the skewness using naive variance.
+ *
+ * @return Skewness
+ */
+ public double getNaiveSkewness() {
+ double sigma2 = getNaiveVariance();
+ return (m3 / n) / Math.pow(sigma2, 1.5);
+ }
+
+ /**
+ * Get the kurtosis using sample variance.
+ *
+ * Note: this formula does <em>not</em> include the correction factor, such
+ * that a normal distribution should be 0.
+ *
+ * @return Kurtosis
+ */
+ public double getSampleKurtosis() {
+ assert (n > 3.) : "Cannot compute a reasonable sample kurtosis with weight <= 3.0!";
+ if (!(m2 > 0)) {
+ throw new ArithmeticException("Kurtosis not defined when variance is 0!");
+ }
+ final double nm1 = n - 1.;
+ return (nm1 / ((n - 2.) * (n - 3.))) * (n * (n + 1) * m4 / (m2 * m2) - 3 * nm1) + 3;
+ }
+
+ /**
+ * Get the kurtosis using naive variance.
+ *
+ * Note: this formula does <em>not</em> include the -3 term.
+ *
+ * @return Kurtosis
+ */
+ public double getNaiveKurtosis() {
+ if (!(m2 > 0)) {
+ throw new ArithmeticException("Kurtosis not defined when variance is 0!");
+ }
+ return (n * m4) / (m2 * m2);
+ }
+
+ /**
+ * Get the kurtosis using sample variance.
+ *
+ * Note: this formula <em>does</em> include the correction factor, such that a
+ * normal distribution should be 0.
+ *
+ * @return Kurtosis
+ */
+ public double getSampleExcessKurtosis() {
+ assert (n > 3.) : "Cannot compute a reasonable sample kurtosis with weight <= 3.0!";
+ if (!(m2 > 0)) {
+ throw new ArithmeticException("Kurtosis not defined when variance is 0!");
+ }
+ final double nm1 = n - 1.;
+ return (nm1 / ((n - 2.) * (n - 3.))) * (n * (n + 1) * m4 / (m2 * m2) - 3 * nm1);
+ }
+
+ /**
+ * Get the kurtosis using naive variance.
+ *
+ * Note: this formula <em>does</em> include the -3 term.
+ *
+ * @return Kurtosis
+ */
+ public double getNaiveExcessKurtosis() {
+ if (!(m2 > 0)) {
+ throw new ArithmeticException("Kurtosis not defined when variance is 0!");
+ }
+ return (n * m4) / (m2 * m2) - 3;
+ }
+
+ /**
+ * Create and initialize a new array of MeanVariance
+ *
+ * @param dimensionality Dimensionality
+ * @return New and initialized Array
+ */
+ public static StatisticalMoments[] newArray(int dimensionality) {
+ StatisticalMoments[] arr = new StatisticalMoments[dimensionality];
+ for (int i = 0; i < dimensionality; i++) {
+ arr[i] = new StatisticalMoments();
+ }
+ return arr;
+ }
+
+ @Override
+ public String toString() {
+ return "StatisticalMoments(mean=" + getMean() + ",m2=" + m2 + ",m3=" + m3 + ",m4=" + m4 + ",n=" + n + ")";
+ }
+
+ @Override
+ public void reset() {
+ super.reset();
+ m3 = 0;
+ m4 = 0;
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/CovarianceDimensionSimilarity.java b/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/CovarianceDimensionSimilarity.java
index ad59ebfd..59380a74 100644
--- a/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/CovarianceDimensionSimilarity.java
+++ b/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/CovarianceDimensionSimilarity.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.dimensionsimilarity;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,6 +23,7 @@ package de.lmu.ifi.dbs.elki.math.dimensionsimilarity;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.math.linearalgebra.CovarianceMatrix;
@@ -47,7 +48,7 @@ public class CovarianceDimensionSimilarity implements DimensionSimilarity<Number
}
@Override
- public void computeDimensionSimilarites(Relation<? extends NumberVector<?>> relation, DBIDs subset, DimensionSimilarityMatrix matrix) {
+ public void computeDimensionSimilarites(Database database, Relation<? extends NumberVector<?>> relation, DBIDs subset, DimensionSimilarityMatrix matrix) {
final int dim = matrix.size();
// FIXME: Use only necessary dimensions!
CovarianceMatrix covmat = CovarianceMatrix.make(relation, subset);
diff --git a/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/DimensionSimilarity.java b/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/DimensionSimilarity.java
index 6b01b3f3..d0c1a0bc 100644
--- a/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/DimensionSimilarity.java
+++ b/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/DimensionSimilarity.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.dimensionsimilarity;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -22,6 +22,7 @@ package de.lmu.ifi.dbs.elki.math.dimensionsimilarity;
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable;
@@ -32,15 +33,18 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable;
*
* @author Erich Schubert
*
+ * @apiviz.uses DimensionSimilarityMatrix - - «writes»
+ *
* @param <V> Object type
*/
public interface DimensionSimilarity<V> extends Parameterizable {
/**
* Compute the dimension similarity matrix
*
+ * @param database Database context
* @param relation Relation
* @param subset DBID subset (for sampling / selection)
* @param matrix Matrix to fill
*/
- public void computeDimensionSimilarites(Relation<? extends V> relation, DBIDs subset, DimensionSimilarityMatrix matrix);
+ public void computeDimensionSimilarites(Database database, Relation<? extends V> relation, DBIDs subset, DimensionSimilarityMatrix matrix);
}
diff --git a/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/DimensionSimilarityMatrix.java b/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/DimensionSimilarityMatrix.java
index 9f7a9707..70429de4 100644
--- a/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/DimensionSimilarityMatrix.java
+++ b/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/DimensionSimilarityMatrix.java
@@ -1,12 +1,13 @@
package de.lmu.ifi.dbs.elki.math.dimensionsimilarity;
import de.lmu.ifi.dbs.elki.math.geometry.PrimsMinimumSpanningTree;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.Matrix;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,6 +30,8 @@ import de.lmu.ifi.dbs.elki.math.geometry.PrimsMinimumSpanningTree;
* Class representing a similarity matrix between dimensions.
*
* @author Erich Schubert
+ *
+ * @apiviz.uses PrimsMinimumSpanningTree
*/
public abstract class DimensionSimilarityMatrix {
/**
@@ -120,6 +123,26 @@ public abstract class DimensionSimilarityMatrix {
return ((y * (y - 1)) >> 1) + x;
}
+ /**
+ * Transform linear triangle matrix into a full matrix.
+ *
+ * @return New matrix
+ */
+ public Matrix copyToFullMatrix() {
+ final int dim = size();
+ Matrix m = new Matrix(dim, dim);
+ double[][] ref = m.getArrayRef();
+ int i = 0;
+ for (int y = 1; y < dim; y++) {
+ for (int x = 0; x < y; x++) {
+ ref[x][y] = sim[i];
+ ref[y][x] = sim[i];
+ ++i;
+ }
+ }
+ return m;
+ }
+
@Override
public String toString() {
StringBuffer buf = new StringBuffer();
@@ -204,6 +227,8 @@ public abstract class DimensionSimilarityMatrix {
* Adapter class for running prim's algorithm.
*
* @author Erich Schubert
+ *
+ * @apiviz.exclude
*/
public static class PrimAdapter implements PrimsMinimumSpanningTree.Adapter<DimensionSimilarityMatrix> {
/**
diff --git a/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/HSMDimensionSimilarity.java b/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/HSMDimensionSimilarity.java
index b221866c..e73d02af 100644
--- a/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/HSMDimensionSimilarity.java
+++ b/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/HSMDimensionSimilarity.java
@@ -24,6 +24,7 @@ package de.lmu.ifi.dbs.elki.math.dimensionsimilarity;
*/
import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
@@ -34,9 +35,6 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
/**
- * FIXME: This needs serious TESTING before release. Large parts have been
- * rewritten, but could not be tested at the time of rewriting.
- *
* Compute the similarity of dimensions by using a hough transformation.
*
* Reference: <br>
@@ -48,6 +46,9 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
* IEEEVisualization and Computer Graphics, 2011.
* </p>
*
+ * FIXME: This needs serious TESTING before release. Large parts have been
+ * rewritten, but could not be tested at the time of rewriting.
+ *
* @author Erich Schubert
* @author Robert Rödler
*/
@@ -63,7 +64,7 @@ public class HSMDimensionSimilarity implements DimensionSimilarity<NumberVector<
*
* The original publication used 50.
*/
- private final static int STEPS = 64;
+ private final static int STEPS = 48; // 64;
/**
* Precompute sinus and cosinus
@@ -78,15 +79,15 @@ public class HSMDimensionSimilarity implements DimensionSimilarity<NumberVector<
}
@Override
- public void computeDimensionSimilarites(Relation<? extends NumberVector<?>> relation, DBIDs subset, DimensionSimilarityMatrix matrix) {
+ public void computeDimensionSimilarites(Database database, Relation<? extends NumberVector<?>> relation, DBIDs subset, DimensionSimilarityMatrix matrix) {
final int dim = matrix.size();
- final int resolution = 500;
- byte[][][][] pics = new byte[dim][dim][][]; // [resolution][resolution];
+ final int resolution = 512;
+ boolean[][][][] pics = new boolean[dim][dim][][]; // [resolution][resolution];
// Initialize / allocate "pictures":
for (int i = 0; i < dim - 1; i++) {
for (int j = i + 1; j < dim; j++) {
- pics[i][j] = new byte[resolution][resolution];
+ pics[i][j] = new boolean[resolution][resolution];
}
}
// FIXME: Get/keep these statistics in the relation, or compute for the
@@ -106,8 +107,8 @@ public class HSMDimensionSimilarity implements DimensionSimilarity<NumberVector<
for (DBIDIter id = subset.iter(); id.valid(); id.advance()) {
NumberVector<?> pvec = relation.get(id);
for (int i = 0; i < dim - 1; i++) {
+ double xi = (pvec.doubleValue(matrix.dim(i)) - off[i]) * scale[i];
for (int j = i + 1; j < dim; j++) {
- double xi = (pvec.doubleValue(matrix.dim(i)) - off[i]) * scale[i];
double xj = (pvec.doubleValue(matrix.dim(j)) - off[j]) * scale[j];
drawLine(0, (int) (resolution * xi), resolution - 1, (int) (resolution * xj), pics[i][j]);
}
@@ -116,11 +117,9 @@ public class HSMDimensionSimilarity implements DimensionSimilarity<NumberVector<
final double stepsq = (double) STEPS * (double) STEPS;
for (int x = 0; x < dim; x++) {
- final int i = matrix.dim(x);
for (int y = x + 1; y < dim; y++) {
- final int j = matrix.dim(y);
- int[][] hough = houghTransformation(pics[i][j]);
- pics[i][j] = null; // Release picture
+ int[][] hough = houghTransformation(pics[x][y]);
+ pics[x][y] = null; // Release picture
// The original publication said "median", but judging from the text,
// meant "mean". Otherwise, always half of the cells are above the
// threshold, which doesn't match the explanation there.
@@ -133,16 +132,17 @@ public class HSMDimensionSimilarity implements DimensionSimilarity<NumberVector<
}
/**
- * Compute the sum of a matix.
+ * Compute the sum of a matrix.
*
* @param mat Matrix
* @return Sum of all elements
*/
private long sumMatrix(int[][] mat) {
long ret = 0;
- for (int i = 0; i < mat[0].length; i++) {
- for (int j = 0; j < mat.length; j++) {
- ret += mat[i][j];
+ for (int i = 0; i < mat.length; i++) {
+ final int[] row = mat[i];
+ for (int j = 0; j < row.length; j++) {
+ ret += row[j];
}
}
return ret;
@@ -174,18 +174,18 @@ public class HSMDimensionSimilarity implements DimensionSimilarity<NumberVector<
* @param mat Binary image
* @return Hough transformation of image.
*/
- private int[][] houghTransformation(byte[][] mat) {
+ private int[][] houghTransformation(boolean[][] mat) {
final int xres = mat.length, yres = mat[0].length;
- final double tscale = STEPS / Math.sqrt(xres * xres + yres * yres);
+ final double tscale = STEPS * .5 / (xres + yres);
final int[][] ret = new int[STEPS][STEPS];
for (int x = 0; x < mat.length; x++) {
for (int y = 0; y < mat[0].length; y++) {
- if (mat[x][y] > 0) {
+ if (mat[x][y]) {
for (int i = 0; i < STEPS; i++) {
- final int d = (int) (tscale * (x * table.cos(i) + y * table.sin(i)));
+ final int d = (STEPS >> 1) + (int) (tscale * (x * table.cos(i) + y * table.sin(i)));
if (d > 0 && d < STEPS) {
- ret[d][i] += mat[x][y];
+ ret[d][i]++;
}
}
}
@@ -204,7 +204,7 @@ public class HSMDimensionSimilarity implements DimensionSimilarity<NumberVector<
* @param y1 End Y
* @param pic Picture array
*/
- private static void drawLine(int x0, int y0, int x1, int y1, byte[][] pic) {
+ private static void drawLine(int x0, int y0, int x1, int y1, boolean[][] pic) {
final int xres = pic.length, yres = pic[0].length;
// Ensure bounds
y0 = (y0 < 0) ? 0 : (y0 >= yres) ? (yres - 1) : y0;
@@ -218,7 +218,7 @@ public class HSMDimensionSimilarity implements DimensionSimilarity<NumberVector<
int err = dx + dy;
for (;;) {
- pic[x0][y0] = 1;
+ pic[x0][y0] = true;
if (x0 == x1 && y0 == y1) {
break;
}
diff --git a/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/HiCSDimensionSimilarity.java b/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/HiCSDimensionSimilarity.java
index 468db679..efc12b5c 100644
--- a/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/HiCSDimensionSimilarity.java
+++ b/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/HiCSDimensionSimilarity.java
@@ -30,6 +30,7 @@ import de.lmu.ifi.dbs.elki.algorithm.outlier.meta.HiCS;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.data.VectorUtil;
import de.lmu.ifi.dbs.elki.data.VectorUtil.SortDBIDsBySingleDimension;
+import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.DBIDArrayIter;
@@ -41,6 +42,7 @@ import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.math.statistics.tests.GoodnessOfFitTest;
import de.lmu.ifi.dbs.elki.math.statistics.tests.KolmogorovSmirnovTest;
import de.lmu.ifi.dbs.elki.utilities.RandomFactory;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
@@ -52,9 +54,17 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.RandomParameter;
/**
* Use the statistical tests as used by HiCS to arrange dimensions.
*
+ * Reference:
* <p>
- * Based on:<br />
- * Fabian Keller, Emmanuel Müller, and Klemens Böhm.<br />
+ * Elke Achtert, Hans-Peter Kriegel, Erich Schubert, Arthur Zimek:<br />
+ * Interactive Data Mining with 3D-Parallel-Coordinate-Trees.<br />
+ * Proceedings of the 2013 ACM International Conference on Management of Data
+ * (SIGMOD), New York City, NY, 2013.
+ * </p>
+ *
+ * Based on:
+ * <p>
+ * F. Keller, E. Müller, and K. Böhm.<br />
* HiCS: High Contrast Subspaces for Density-Based Outlier Ranking. <br />
* In ICDE, pages 1037–1048, 2012.
* </p>
@@ -62,6 +72,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.RandomParameter;
* @author Erich Schubert
* @author Robert Rödler
*/
+@Reference(authors = "Elke Achtert, Hans-Peter Kriegel, Erich Schubert, Arthur Zimek", title = "Interactive Data Mining with 3D-Parallel-Coordinate-Trees", booktitle = "Proc. of the 2013 ACM International Conference on Management of Data (SIGMOD)", url = "http://dx.doi.org/10.1145/2463676.2463696")
public class HiCSDimensionSimilarity implements DimensionSimilarity<NumberVector<?>> {
/**
* Monte-Carlo iterations
@@ -100,7 +111,7 @@ public class HiCSDimensionSimilarity implements DimensionSimilarity<NumberVector
}
@Override
- public void computeDimensionSimilarites(Relation<? extends NumberVector<?>> relation, DBIDs subset, DimensionSimilarityMatrix matrix) {
+ public void computeDimensionSimilarites(Database database, Relation<? extends NumberVector<?>> relation, DBIDs subset, DimensionSimilarityMatrix matrix) {
final Random random = rnd.getRandom();
final int dim = matrix.size();
@@ -129,7 +140,7 @@ public class HiCSDimensionSimilarity implements DimensionSimilarity<NumberVector
*/
private ArrayList<ArrayDBIDs> buildOneDimIndexes(Relation<? extends NumberVector<?>> relation, DBIDs ids, DimensionSimilarityMatrix matrix) {
final int dim = matrix.size();
- ArrayList<ArrayDBIDs> subspaceIndex = new ArrayList<ArrayDBIDs>(dim);
+ ArrayList<ArrayDBIDs> subspaceIndex = new ArrayList<>(dim);
SortDBIDsBySingleDimension comp = new VectorUtil.SortDBIDsBySingleDimension(relation);
for (int i = 0; i < dim; i++) {
@@ -221,12 +232,16 @@ public class HiCSDimensionSimilarity implements DimensionSimilarity<NumberVector
private GoodnessOfFitTest statTest;
/**
- * Holds the value of {@link de.lmu.ifi.dbs.elki.algorithm.outlier.meta.HiCS.Parameterizer#M_ID}.
+ * Holds the value of
+ * {@link de.lmu.ifi.dbs.elki.algorithm.outlier.meta.HiCS.Parameterizer#M_ID}
+ * .
*/
private int m = 50;
/**
- * Holds the value of {@link de.lmu.ifi.dbs.elki.algorithm.outlier.meta.HiCS.Parameterizer#ALPHA_ID}.
+ * Holds the value of
+ * {@link de.lmu.ifi.dbs.elki.algorithm.outlier.meta.HiCS.Parameterizer#ALPHA_ID}
+ * .
*/
private double alpha = 0.1;
@@ -250,7 +265,7 @@ public class HiCSDimensionSimilarity implements DimensionSimilarity<NumberVector
alpha = alphaP.doubleValue();
}
- final ObjectParameter<GoodnessOfFitTest> testP = new ObjectParameter<GoodnessOfFitTest>(HiCS.Parameterizer.TEST_ID, GoodnessOfFitTest.class, KolmogorovSmirnovTest.class);
+ final ObjectParameter<GoodnessOfFitTest> testP = new ObjectParameter<>(HiCS.Parameterizer.TEST_ID, GoodnessOfFitTest.class, KolmogorovSmirnovTest.class);
if (config.grab(testP)) {
statTest = testP.instantiateClass(config);
}
diff --git a/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/MCEDimensionSimilarity.java b/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/MCEDimensionSimilarity.java
index aecdf857..b3e6bb76 100644
--- a/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/MCEDimensionSimilarity.java
+++ b/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/MCEDimensionSimilarity.java
@@ -29,6 +29,7 @@ import java.util.Arrays;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.data.VectorUtil;
import de.lmu.ifi.dbs.elki.data.VectorUtil.SortDBIDsBySingleDimension;
+import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.DBIDArrayIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
@@ -45,7 +46,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
*
* Reference:
* <p>
- * Diansheng Guo<br />
+ * D. Guo<br />
* Coordinating computational and visual approaches for interactive feature
* selection and multivariate clustering<br />
* Information Visualization, 2(4), 2003.
@@ -53,7 +54,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
*
* @author Erich Schubert
*/
-@Reference(authors = "Diansheng Guo", title = "Coordinating computational and visual approaches for interactive feature selection and multivariate clustering", booktitle = "Information Visualization, 2(4)", url = "http://dx.doi.org/10.1057/palgrave.ivs.9500053")
+@Reference(authors = "D. Guo", title = "Coordinating computational and visual approaches for interactive feature selection and multivariate clustering", booktitle = "Information Visualization, 2(4)", url = "http://dx.doi.org/10.1057/palgrave.ivs.9500053")
public class MCEDimensionSimilarity implements DimensionSimilarity<NumberVector<?>> {
/**
* Static instance.
@@ -76,7 +77,7 @@ public class MCEDimensionSimilarity implements DimensionSimilarity<NumberVector<
}
@Override
- public void computeDimensionSimilarites(Relation<? extends NumberVector<?>> relation, DBIDs subset, DimensionSimilarityMatrix matrix) {
+ public void computeDimensionSimilarites(Database database, Relation<? extends NumberVector<?>> relation, DBIDs subset, DimensionSimilarityMatrix matrix) {
final int dim = matrix.size();
// Find a number of bins as recommended by Cheng et al.
@@ -186,7 +187,7 @@ public class MCEDimensionSimilarity implements DimensionSimilarity<NumberVector<
*/
private ArrayList<ArrayList<DBIDs>> buildPartitions(Relation<? extends NumberVector<?>> relation, DBIDs ids, int depth, DimensionSimilarityMatrix matrix) {
final int dim = matrix.size();
- ArrayList<ArrayList<DBIDs>> subspaceIndex = new ArrayList<ArrayList<DBIDs>>(dim);
+ ArrayList<ArrayList<DBIDs>> subspaceIndex = new ArrayList<>(dim);
SortDBIDsBySingleDimension comp = new VectorUtil.SortDBIDsBySingleDimension(relation);
double[] tmp = new double[ids.size()];
Mean mean = new Mean();
@@ -194,7 +195,7 @@ public class MCEDimensionSimilarity implements DimensionSimilarity<NumberVector<
for (int i = 0; i < dim; i++) {
final int d = matrix.dim(i);
// Index for a single dimension:
- ArrayList<DBIDs> idx = new ArrayList<DBIDs>(1 << depth);
+ ArrayList<DBIDs> idx = new ArrayList<>(1 << depth);
// First, we need a copy of the DBIDs and sort it.
ArrayModifiableDBIDs sids = DBIDUtil.newArray(ids);
comp.setDimension(d);
diff --git a/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/SURFINGDimensionSimilarity.java b/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/SURFINGDimensionSimilarity.java
index 551b4759..fd83d44b 100644
--- a/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/SURFINGDimensionSimilarity.java
+++ b/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/SURFINGDimensionSimilarity.java
@@ -48,6 +48,14 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
*
* Reference:
* <p>
+ * Elke Achtert, Hans-Peter Kriegel, Erich Schubert, Arthur Zimek:<br />
+ * Interactive Data Mining with 3D-Parallel-Coordinate-Trees.<br />
+ * Proceedings of the 2013 ACM International Conference on Management of Data
+ * (SIGMOD), New York City, NY, 2013.
+ * </p>
+ *
+ * Based on:
+ * <p>
* Christian Baumgartner, Claudia Plant, Karin Kailing, Hans-Peter Kriegel, and
* Peer Kröger<br />
* Subspace Selection for Clustering High-Dimensional Data<br />
@@ -61,7 +69,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
*
* @apiviz.uses SubspaceEuclideanDistanceFunction
*/
-@Reference(authors = "Christian Baumgartner, Claudia Plant, Karin Kailing, Hans-Peter Kriegel, and Peer Kröger", title = "Subspace Selection for Clustering High-Dimensional Data", booktitle = "IEEE International Conference on Data Mining, 2004", url = "http://dx.doi.org/10.1109/ICDM.2004.10112")
+@Reference(authors = "Elke Achtert, Hans-Peter Kriegel, Erich Schubert, Arthur Zimek", title = "Interactive Data Mining with 3D-Parallel-Coordinate-Trees", booktitle = "Proc. of the 2013 ACM International Conference on Management of Data (SIGMOD)", url = "http://dx.doi.org/10.1145/2463676.2463696")
public class SURFINGDimensionSimilarity implements DimensionSimilarity<NumberVector<?>> {
/**
* Static instance.
@@ -75,10 +83,10 @@ public class SURFINGDimensionSimilarity implements DimensionSimilarity<NumberVec
super();
}
+ @Reference(authors = "Christian Baumgartner, Claudia Plant, Karin Kailing, Hans-Peter Kriegel, and Peer Kröger", title = "Subspace Selection for Clustering High-Dimensional Data", booktitle = "IEEE International Conference on Data Mining, 2004", url = "http://dx.doi.org/10.1109/ICDM.2004.10112")
@Override
- public void computeDimensionSimilarites(Relation<? extends NumberVector<?>> relation, DBIDs subset, DimensionSimilarityMatrix matrix) {
+ public void computeDimensionSimilarites(Database database, Relation<? extends NumberVector<?>> relation, DBIDs subset, DimensionSimilarityMatrix matrix) {
final int dim = matrix.size();
- final Database db = relation.getDatabase();
Mean kdistmean = new Mean();
final int k = Math.max(1, subset.size() / 10);
@@ -92,8 +100,8 @@ public class SURFINGDimensionSimilarity implements DimensionSimilarity<NumberVec
BitSet dims = new BitSet(dim);
dims.set(i);
dims.set(j);
- DistanceQuery<? extends NumberVector<?>, DoubleDistance> dq = db.getDistanceQuery(relation, new SubspaceEuclideanDistanceFunction(dims));
- KNNQuery<? extends NumberVector<?>, DoubleDistance> knnq = db.getKNNQuery(dq, k);
+ DistanceQuery<? extends NumberVector<?>, DoubleDistance> dq = database.getDistanceQuery(relation, new SubspaceEuclideanDistanceFunction(dims));
+ KNNQuery<? extends NumberVector<?>, DoubleDistance> knnq = database.getKNNQuery(dq, k);
kdistmean.reset();
int knn = 0;
diff --git a/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/SlopeDimensionSimilarity.java b/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/SlopeDimensionSimilarity.java
index 3c81da63..1eb62189 100644
--- a/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/SlopeDimensionSimilarity.java
+++ b/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/SlopeDimensionSimilarity.java
@@ -24,19 +24,30 @@ package de.lmu.ifi.dbs.elki.math.dimensionsimilarity;
*/
import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.utilities.DatabaseUtil;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
/**
* Arrange dimensions based on the entropy of the slope spectrum.
*
+ * Reference:
+ * <p>
+ * Elke Achtert, Hans-Peter Kriegel, Erich Schubert, Arthur Zimek:<br />
+ * Interactive Data Mining with 3D-Parallel-Coordinate-Trees.<br />
+ * Proceedings of the 2013 ACM International Conference on Management of Data
+ * (SIGMOD), New York City, NY, 2013.
+ * </p>
+ *
* @author Erich Schubert
* @author Robert Rödler
*/
+@Reference(authors = "Elke Achtert, Hans-Peter Kriegel, Erich Schubert, Arthur Zimek", title = "Interactive Data Mining with 3D-Parallel-Coordinate-Trees", booktitle = "Proc. of the 2013 ACM International Conference on Management of Data (SIGMOD)", url = "http://dx.doi.org/10.1145/2463676.2463696")
public class SlopeDimensionSimilarity implements DimensionSimilarity<NumberVector<?>> {
/**
* Static instance.
@@ -66,7 +77,7 @@ public class SlopeDimensionSimilarity implements DimensionSimilarity<NumberVecto
}
@Override
- public void computeDimensionSimilarites(Relation<? extends NumberVector<?>> relation, DBIDs subset, DimensionSimilarityMatrix matrix) {
+ public void computeDimensionSimilarites(Database database, Relation<? extends NumberVector<?>> relation, DBIDs subset, DimensionSimilarityMatrix matrix) {
final int dim = matrix.size();
final int size = subset.size();
diff --git a/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/SlopeInversionDimensionSimilarity.java b/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/SlopeInversionDimensionSimilarity.java
index aad58448..77408914 100644
--- a/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/SlopeInversionDimensionSimilarity.java
+++ b/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/SlopeInversionDimensionSimilarity.java
@@ -24,10 +24,12 @@ package de.lmu.ifi.dbs.elki.math.dimensionsimilarity;
*/
import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.utilities.DatabaseUtil;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
@@ -36,11 +38,20 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
* {@link SlopeDimensionSimilarity}, we also take the option of inverting an
* axis into account.
*
+ * Reference:
+ * <p>
+ * Elke Achtert, Hans-Peter Kriegel, Erich Schubert, Arthur Zimek:<br />
+ * Interactive Data Mining with 3D-Parallel-Coordinate-Trees.<br />
+ * Proceedings of the 2013 ACM International Conference on Management of Data
+ * (SIGMOD), New York City, NY, 2013.
+ * </p>
+ *
* TODO: shouldn't this be normalized by the single-dimension entropies or so?
*
* @author Erich Schubert
* @author Robert Rödler
*/
+@Reference(authors = "Elke Achtert, Hans-Peter Kriegel, Erich Schubert, Arthur Zimek", title = "Interactive Data Mining with 3D-Parallel-Coordinate-Trees", booktitle = "Proc. of the 2013 ACM International Conference on Management of Data (SIGMOD)", url = "http://dx.doi.org/10.1145/2463676.2463696")
public class SlopeInversionDimensionSimilarity extends SlopeDimensionSimilarity {
/**
* Static instance.
@@ -55,7 +66,7 @@ public class SlopeInversionDimensionSimilarity extends SlopeDimensionSimilarity
}
@Override
- public void computeDimensionSimilarites(Relation<? extends NumberVector<?>> relation, DBIDs subset, DimensionSimilarityMatrix matrix) {
+ public void computeDimensionSimilarites(Database database, Relation<? extends NumberVector<?>> relation, DBIDs subset, DimensionSimilarityMatrix matrix) {
final int dim = matrix.size();
final int size = subset.size();
diff --git a/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/package-info.java b/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/package-info.java
index b6c27c57..bcbd47d5 100644
--- a/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/math/dimensionsimilarity/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/geodesy/AbstractEarthModel.java b/src/de/lmu/ifi/dbs/elki/math/geodesy/AbstractEarthModel.java
new file mode 100644
index 00000000..d8eaa43f
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/geodesy/AbstractEarthModel.java
@@ -0,0 +1,207 @@
+package de.lmu.ifi.dbs.elki.math.geodesy;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+
+/**
+ * Abstract base class for earth models with shared glue code.
+ *
+ * @author Erich Schubert
+ */
+public abstract class AbstractEarthModel implements EarthModel {
+ /**
+ * Maximum number of iterations.
+ */
+ private static final int MAX_ITER = 20;
+
+ /**
+ * Maximum desired precision.
+ */
+ private static final double PRECISION = 1e-10;
+
+ /**
+ * Model parameters: major and minor radius.
+ */
+ final double a, b;
+
+ /**
+ * Model parameters: flattening, inverse flattening.
+ */
+ final double f, invf;
+
+ /**
+ * Derived model parameters: e and e squared.
+ */
+ final double e, esq;
+
+ /**
+ * Constructor.
+ *
+ * @param a Major axis radius
+ * @param b Minor axis radius
+ * @param f Flattening
+ * @param invf Inverse flattening
+ */
+ public AbstractEarthModel(double a, double b, double f, double invf) {
+ super();
+ this.a = a;
+ this.b = b;
+ this.f = f;
+ this.invf = invf;
+ this.esq = f * (2 - f);
+ this.e = Math.sqrt(esq);
+ }
+
+ @Override
+ public double getEquatorialRadius() {
+ return a;
+ }
+
+ @Override
+ public double getPolarDistance() {
+ return b;
+ }
+
+ @Override
+ public double[] latLngDegToECEF(double lat, double lng) {
+ return latLngRadToECEF(MathUtil.deg2rad(lat), MathUtil.deg2rad(lng));
+ }
+
+ @Override
+ public double[] latLngDegToECEF(double lat, double lng, double h) {
+ return latLngRadToECEF(MathUtil.deg2rad(lat), MathUtil.deg2rad(lng), h);
+ }
+
+ @Override
+ public double[] latLngRadToECEF(double lat, double lng) {
+ // Sine and cosines:
+ final double clat = Math.cos(lat), slat = MathUtil.cosToSin(lat, clat);
+ final double clng = Math.cos(lng), slng = MathUtil.cosToSin(lng, clng);
+
+ final double v = a / Math.sqrt(1 - esq * slat * slat);
+ return new double[] { v * clat * clng, v * clat * slng, (1 - esq) * v * slat };
+ }
+
+ @Override
+ public double[] latLngRadToECEF(double lat, double lng, double h) {
+ // Sine and cosines:
+ final double clat = Math.cos(lat), slat = MathUtil.cosToSin(lat, clat);
+ final double clng = Math.cos(lng), slng = MathUtil.cosToSin(lng, clng);
+
+ final double v = a / Math.sqrt(1 - esq * slat * slat);
+ return new double[] { (v + h) * clat * clng, (v + h) * clat * slng, ((1 - esq) * v + h) * slat };
+ }
+
+ @Override
+ public double ecefToLatDeg(double x, double y, double z) {
+ return MathUtil.rad2deg(ecefToLatRad(x, y, z));
+ }
+
+ @Override
+ public double ecefToLatRad(double x, double y, double z) {
+ final double p = Math.sqrt(x * x + y * y);
+ double plat = Math.atan2(z, p * (1 - esq));
+
+ // Iteratively improving the lat value
+ // TODO: instead of a fixed number of iterations, check for convergence?
+ for (int i = 0;; i++) {
+ final double slat = Math.sin(plat);
+ final double v = a / Math.sqrt(1 - esq * slat * slat);
+ final double lat = Math.atan2(z + esq * v * slat, p);
+ if (Math.abs(lat - plat) < PRECISION || i > MAX_ITER) {
+ return lat;
+ }
+ plat = lat;
+ }
+ }
+
+ @Override
+ public double ecefToLngDeg(double x, double y) {
+ return MathUtil.rad2deg(ecefToLngRad(x, y));
+ }
+
+ @Override
+ public double ecefToLngRad(double x, double y) {
+ return Math.atan2(y, x);
+ }
+
+ @Override
+ public double[] ecefToLatLngDegHeight(double x, double y, double z) {
+ double[] ret = ecefToLatLngRadHeight(x, y, z);
+ ret[0] = MathUtil.rad2deg(ret[0]);
+ ret[1] = MathUtil.rad2deg(ret[1]);
+ return ret;
+ }
+
+ @Override
+ public double[] ecefToLatLngRadHeight(double x, double y, double z) {
+ double lng = Math.atan2(y, x);
+ final double p = Math.sqrt(x * x + y * y);
+ double plat = Math.atan2(z, p * (1 - esq));
+ double h = 0;
+
+ // Iteratively improving the lat value
+ // TODO: instead of a fixed number of iterations, check for convergence?
+ for (int i = 0;; i++) {
+ final double slat = Math.sin(plat);
+ final double v = a / Math.sqrt(1 - esq * slat * slat);
+ double lat = Math.atan2(z + esq * v * slat, p);
+ if (Math.abs(lat - plat) < PRECISION || i > MAX_ITER) {
+ h = p / Math.cos(lat) - v;
+ return new double[] { lat, lng, h };
+ }
+ plat = lat;
+ }
+ }
+
+ @Override
+ public double distanceDeg(double lat1, double lng1, double lat2, double lng2) {
+ return distanceRad(MathUtil.deg2rad(lat1), MathUtil.deg2rad(lng1), //
+ MathUtil.deg2rad(lat2), MathUtil.deg2rad(lng2));
+ }
+
+ @Override
+ public double distanceRad(double lat1, double lng1, double lat2, double lng2) {
+ // Vincenty uses minor axis radius!
+ return b * SphereUtil.ellipsoidVincentyFormulaRad(f, lat1, lng1, lat2, lng2);
+ }
+
+ @Override
+ public double minDistDeg(double plat, double plng, double rminlat, double rminlng, double rmaxlat, double rmaxlng) {
+ return minDistRad(MathUtil.deg2rad(plat), MathUtil.deg2rad(plng), //
+ MathUtil.deg2rad(rminlat), MathUtil.deg2rad(rminlng), //
+ MathUtil.deg2rad(rmaxlat), MathUtil.deg2rad(rmaxlng));
+ }
+
+ @Override
+ public double minDistRad(double plat, double plng, double rminlat, double rminlng, double rmaxlat, double rmaxlng) {
+ return b * SphereUtil.latlngMinDistRad(plat, plng, rminlat, rminlng, rmaxlat, rmaxlng);
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName()+" [a=" + a + ", b=" + b + ", f=" + f + ", invf=" + invf + ", e=" + e + ", esq=" + esq + "]";
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/geodesy/Clarke1858SpheroidEarthModel.java b/src/de/lmu/ifi/dbs/elki/math/geodesy/Clarke1858SpheroidEarthModel.java
new file mode 100644
index 00000000..c1d8a9af
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/geodesy/Clarke1858SpheroidEarthModel.java
@@ -0,0 +1,80 @@
+package de.lmu.ifi.dbs.elki.math.geodesy;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.utilities.Alias;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * The Clarke 1858 spheroid earth model.
+ *
+ * Radius: 6378293.645 m
+ *
+ * Flattening: 1 / 294.26068
+ *
+ * @author Erich Schubert
+ */
+@Alias({ "Clarke 1858" })
+public class Clarke1858SpheroidEarthModel extends AbstractEarthModel {
+ /**
+ * Static instance.
+ */
+ public static final Clarke1858SpheroidEarthModel STATIC = new Clarke1858SpheroidEarthModel();
+
+ /**
+ * Radius of the CLARKE1858 Ellipsoid in m (a).
+ */
+ public static final double CLARKE1858_RADIUS = 6378293.645; // m
+
+ /**
+ * Inverse flattening 1/f of the CLARKE1858 Ellipsoid.
+ */
+ public static final double CLARKE1858_INV_FLATTENING = 294.26068;
+
+ /**
+ * Flattening f of the CLARKE1858 Ellipsoid.
+ */
+ public static final double CLARKE1858_FLATTENING = 1 / CLARKE1858_INV_FLATTENING;
+
+ /**
+ * Constructor.
+ */
+ protected Clarke1858SpheroidEarthModel() {
+ super(CLARKE1858_RADIUS, CLARKE1858_RADIUS * (1 - CLARKE1858_FLATTENING), CLARKE1858_FLATTENING, CLARKE1858_INV_FLATTENING);
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected Clarke1858SpheroidEarthModel makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/geodesy/Clarke1880SpheroidEarthModel.java b/src/de/lmu/ifi/dbs/elki/math/geodesy/Clarke1880SpheroidEarthModel.java
new file mode 100644
index 00000000..731cf9eb
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/geodesy/Clarke1880SpheroidEarthModel.java
@@ -0,0 +1,80 @@
+package de.lmu.ifi.dbs.elki.math.geodesy;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.utilities.Alias;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * The Clarke 1880 spheroid earth model.
+ *
+ * Radius: 6378249.145 m
+ *
+ * Flattening: 1 / 293.465
+ *
+ * @author Erich Schubert
+ */
+@Alias({ "Clarke 1880" })
+public class Clarke1880SpheroidEarthModel extends AbstractEarthModel {
+ /**
+ * Static instance.
+ */
+ public static final Clarke1880SpheroidEarthModel STATIC = new Clarke1880SpheroidEarthModel();
+
+ /**
+ * Radius of the CLARKE1880 Ellipsoid in m (a).
+ */
+ public static final double CLARKE1880_RADIUS = 6378249.145; // m
+
+ /**
+ * Inverse flattening 1/f of the CLARKE1880 Ellipsoid.
+ */
+ public static final double CLARKE1880_INV_FLATTENING = 293.465;
+
+ /**
+ * Flattening f of the CLARKE1880 Ellipsoid.
+ */
+ public static final double CLARKE1880_FLATTENING = 1 / CLARKE1880_INV_FLATTENING;
+
+ /**
+ * Constructor.
+ */
+ protected Clarke1880SpheroidEarthModel() {
+ super(CLARKE1880_RADIUS, CLARKE1880_RADIUS * (1 - CLARKE1880_FLATTENING), CLARKE1880_FLATTENING, CLARKE1880_INV_FLATTENING);
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected Clarke1880SpheroidEarthModel makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/geodesy/EarthModel.java b/src/de/lmu/ifi/dbs/elki/math/geodesy/EarthModel.java
new file mode 100644
index 00000000..b27f2e3b
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/geodesy/EarthModel.java
@@ -0,0 +1,221 @@
+package de.lmu.ifi.dbs.elki.math.geodesy;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+
+/**
+ * API for handling different earth models.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.uses SphereUtil
+ */
+public interface EarthModel {
+ /**
+ * Parameter to choose the earth model to use.
+ */
+ public static final OptionID MODEL_ID = new OptionID("geo.model", "Earth model to use for projection. Default: spherical model.");
+
+ /**
+ * Map a degree latitude, longitude pair to 3D X-Y-Z coordinates, using a
+ * spherical earth model.
+ *
+ * The coordinate system is usually chosen such that the earth rotates around
+ * the Z axis and X points to the prime meridian and Equator.
+ *
+ * @param lat Latitude in degree
+ * @param lng Longitude in degree
+ * @return Coordinate triple, in meters.
+ */
+ double[] latLngDegToECEF(double lat, double lng);
+
+ /**
+ * Map a radians latitude, longitude pair to 3D X-Y-Z coordinates, using a
+ * spherical earth model.
+ *
+ * The coordinate system is usually chosen such that the earth rotates around
+ * the Z axis and X points to the prime meridian and Equator.
+ *
+ * @param lat Latitude in radians
+ * @param lng Longitude in radians
+ * @return Coordinate triple, in meters.
+ */
+ double[] latLngRadToECEF(double lat, double lng);
+
+ /**
+ * Map a degree latitude, longitude pair to 3D X-Y-Z coordinates, using a
+ * spherical earth model.
+ *
+ * The coordinate system is usually chosen such that the earth rotates around
+ * the Z axis and X points to the prime meridian and Equator.
+ *
+ * @param lat Latitude in degree
+ * @param lng Longitude in degree
+ * @param h Height
+ * @return Coordinate triple, in meters.
+ */
+ double[] latLngDegToECEF(double lat, double lng, double h);
+
+ /**
+ * Map a radians latitude, longitude pair to 3D X-Y-Z coordinates, using a
+ * spherical earth model.
+ *
+ * The coordinate system is usually chosen such that the earth rotates around
+ * the Z axis and X points to the prime meridian and Equator.
+ *
+ * @param lat Latitude in radians
+ * @param lng Longitude in radians
+ * @param h Height
+ * @return Coordinate triple, in meters.
+ */
+ double[] latLngRadToECEF(double lat, double lng, double h);
+
+ /**
+ * Convert a 3D coordinate pair to the corresponding latitude.
+ *
+ * @param x X value
+ * @param y Y value
+ * @param z Z value
+ * @return Latitude in degrees
+ */
+ double ecefToLatDeg(double x, double y, double z);
+
+ /**
+ * Convert a 3D coordinate pair to the corresponding latitude.
+ *
+ * @param x X value
+ * @param y Y value
+ * @param z Z value
+ * @return Latitude in radians
+ */
+ double ecefToLatRad(double x, double y, double z);
+
+ /**
+ * Convert a 3D coordinate pair to the corresponding longitude.
+ *
+ * @param x X value
+ * @param y Y value
+ * @return Longitude in degrees
+ */
+ double ecefToLngDeg(double x, double y);
+
+ /**
+ * Convert a 3D coordinate pair to the corresponding longitude.
+ *
+ * @param x X value
+ * @param y Y value
+ * @return Longitude in radians
+ */
+ double ecefToLngRad(double x, double y);
+
+ /**
+ * Convert a 3D coordinate pair to the corresponding latitude, longitude and
+ * height.
+ *
+ * Note: if you are not interested in the height, use {@link #ecefToLatDeg}
+ * and {@link #ecefToLngDeg} instead, which has a smaller memory footprint.
+ *
+ * @param x X value
+ * @param y Y value
+ * @param z Z value
+ * @return Array containing (latitude, longitude, height).
+ */
+ double[] ecefToLatLngDegHeight(double x, double y, double z);
+
+ /**
+ * Convert a 3D coordinate pair to the corresponding latitude, longitude and
+ * height.
+ *
+ * Note: if you are not interested in the height, use {@link #ecefToLatRad}
+ * and {@link #ecefToLngRad} instead, which has a smaller memory footprint.
+ *
+ * @param x X value
+ * @param y Y value
+ * @param z Z value
+ * @return Array containing (latitude, longitude, height).
+ */
+ double[] ecefToLatLngRadHeight(double x, double y, double z);
+
+ /**
+ * Compute the geodetic distance between two surface coordinates.
+ *
+ * @param lat1 Latitude of first in degrees.
+ * @param lng1 Longitude of first in degrees.
+ * @param lat2 Latitude of second in degrees.
+ * @param lng2 Longitude of second in degrees.
+ * @return Distance in meters.
+ */
+ double distanceDeg(double lat1, double lng1, double lat2, double lng2);
+
+ /**
+ * Compute the geodetic distance between two surface coordinates.
+ *
+ * @param lat1 Latitude of first in radians.
+ * @param lng1 Longitude of first in radians.
+ * @param lat2 Latitude of second in radians.
+ * @param lng2 Longitude of second in radians.
+ * @return Distance in meters.
+ */
+ double distanceRad(double lat1, double lng1, double lat2, double lng2);
+
+ /**
+ * Compute a lower bound for the geodetic distance point to rectangle.
+ *
+ * @param plat Latitude of point in degrees.
+ * @param plng Longitude of point in degrees.
+ * @param rminlat Min latitude of rectangle in degrees.
+ * @param rminlng Min Longitude of rectangle in degrees.
+ * @param rmaxlat Max Latitude of rectangle in degrees.
+ * @param rmaxlng Max Longitude of rectangle in degrees.
+ * @return Distance in meters.
+ */
+ double minDistDeg(double plat, double plng, double rminlat, double rminlng, double rmaxlat, double rmaxlng);
+
+ /**
+ * Compute a lower bound for the geodetic distance point to rectangle.
+ *
+ * @param plat Latitude of point in radians.
+ * @param plng Longitude of point in radians.
+ * @param rminlat Min latitude of rectangle in radians.
+ * @param rminlng Min Longitude of rectangle in radians.
+ * @param rmaxlat Max Latitude of rectangle in radians.
+ * @param rmaxlng Max Longitude of rectangle in radians.
+ * @return Distance in meters.
+ */
+ double minDistRad(double plat, double plng, double rminlat, double rminlng, double rmaxlat, double rmaxlng);
+
+ /**
+ * Equatorial radius
+ *
+ * @return Radius
+ */
+ double getEquatorialRadius();
+
+ /**
+ * Polar distance.
+ *
+ * @return Distance to poles (= minor radius)
+ */
+ double getPolarDistance();
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/geodesy/GRS67SpheroidEarthModel.java b/src/de/lmu/ifi/dbs/elki/math/geodesy/GRS67SpheroidEarthModel.java
new file mode 100644
index 00000000..81dc7565
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/geodesy/GRS67SpheroidEarthModel.java
@@ -0,0 +1,80 @@
+package de.lmu.ifi.dbs.elki.math.geodesy;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.utilities.Alias;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * The GRS 67 spheroid earth model.
+ *
+ * Radius: 6378160.0 m
+ *
+ * Flattening: 1 / 298.25
+ *
+ * @author Erich Schubert
+ */
+@Alias({ "GRS67", "GRS-67", "GRS67" })
+public class GRS67SpheroidEarthModel extends AbstractEarthModel {
+ /**
+ * Static instance.
+ */
+ public static final GRS67SpheroidEarthModel STATIC = new GRS67SpheroidEarthModel();
+
+ /**
+ * Radius of the GRS67 Ellipsoid in m (a).
+ */
+ public static final double GRS67_RADIUS = 6378160.0; // m
+
+ /**
+ * Inverse flattening 1/f of the GRS67 Ellipsoid.
+ */
+ public static final double GRS67_INV_FLATTENING = 298.25;
+
+ /**
+ * Flattening f of the GRS67 Ellipsoid.
+ */
+ public static final double GRS67_FLATTENING = 1 / GRS67_INV_FLATTENING;
+
+ /**
+ * Constructor.
+ */
+ protected GRS67SpheroidEarthModel() {
+ super(GRS67_RADIUS, GRS67_RADIUS * (1 - GRS67_FLATTENING), GRS67_FLATTENING, GRS67_INV_FLATTENING);
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected GRS67SpheroidEarthModel makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/geodesy/GRS80SpheroidEarthModel.java b/src/de/lmu/ifi/dbs/elki/math/geodesy/GRS80SpheroidEarthModel.java
new file mode 100644
index 00000000..2499da0c
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/geodesy/GRS80SpheroidEarthModel.java
@@ -0,0 +1,81 @@
+package de.lmu.ifi.dbs.elki.math.geodesy;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.utilities.Alias;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * The GRS 80 spheroid earth model, without height model (so not a geoid, just a
+ * spheroid!)
+ *
+ * Radius: 6378137.0 m
+ *
+ * Flattening: 1 / 298.257222101
+ *
+ * @author Erich Schubert
+ */
+@Alias({ "grs80", "GRS-80", "GRS80" })
+public class GRS80SpheroidEarthModel extends AbstractEarthModel {
+ /**
+ * Static instance.
+ */
+ public static final GRS80SpheroidEarthModel STATIC = new GRS80SpheroidEarthModel();
+
+ /**
+ * Radius of the GRS80 Ellipsoid in m (a).
+ */
+ public static final double GRS80_RADIUS = 6378137.0; // m
+
+ /**
+ * Inverse flattening 1/f of the GRS80 Ellipsoid.
+ */
+ public static final double GRS80_INV_FLATTENING = 298.257222101;
+
+ /**
+ * Flattening f of the GRS80 Ellipsoid.
+ */
+ public static final double GRS80_FLATTENING = 1 / GRS80_INV_FLATTENING;
+
+ /**
+ * Constructor.
+ */
+ protected GRS80SpheroidEarthModel() {
+ super(GRS80_RADIUS, GRS80_RADIUS * (1 - GRS80_FLATTENING), GRS80_FLATTENING, GRS80_INV_FLATTENING);
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected GRS80SpheroidEarthModel makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/geodesy/SphereUtil.java b/src/de/lmu/ifi/dbs/elki/math/geodesy/SphereUtil.java
new file mode 100644
index 00000000..b8e57cc3
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/geodesy/SphereUtil.java
@@ -0,0 +1,881 @@
+package de.lmu.ifi.dbs.elki.math.geodesy;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+
+/**
+ * Class with utility functions for distance computations on the sphere.
+ *
+ * Note: the formulas are usually implemented for the unit sphere.
+ *
+ * The majority of formulas are adapted from:
+ * <p>
+ * Ed Williams<br />
+ * Aviation Formulary<br />
+ * Online: http://williams.best.vwh.net/avform.htm
+ * </p>
+ *
+ * TODO: add ellipsoid version of Vinentry formula.
+ *
+ * @author Erich Schubert
+ * @author Niels Dörre
+ */
+@Reference(authors = "Ed Williams", title = "Aviation Formulary", booktitle = "", url = "http://williams.best.vwh.net/avform.htm")
+public final class SphereUtil {
+ /**
+ * Maximum number of iterations.
+ */
+ private static final int MAX_ITER = 20;
+
+ /**
+ * Maximum desired precision.
+ */
+ private static final double PRECISION = 1e-12;
+
+ /**
+ * Constant to divide by 6 via multiplication.
+ */
+ private static final double ONE_SIXTH = 1. / 6;
+
+ /**
+ * Dummy constructor. Do not instantiate.
+ */
+ private SphereUtil() {
+ // Use static methods. Do not intantiate
+ }
+
+ /**
+ * Compute the approximate great-circle distance of two points using the
+ * Haversine formula
+ *
+ * Complexity: 6 (2 of which emulated) trigonometric functions.
+ *
+ * Reference:
+ * <p>
+ * R. W. Sinnott,<br/>
+ * Virtues of the Haversine<br />
+ * Sky and telescope, 68-2, 1984
+ * </p>
+ *
+ * @param lat1 Latitude of first point in degree
+ * @param lon1 Longitude of first point in degree
+ * @param lat2 Latitude of second point in degree
+ * @param lon2 Longitude of second point in degree
+ * @return Distance on unit sphere
+ */
+ public static double cosineFormulaDeg(double lat1, double lon1, double lat2, double lon2) {
+ return cosineFormulaRad(MathUtil.deg2rad(lat1), MathUtil.deg2rad(lon1),//
+ MathUtil.deg2rad(lat2), MathUtil.deg2rad(lon2));
+ }
+
+ /**
+ * Compute the approximate great-circle distance of two points using the
+ * Spherical law of cosines.
+ *
+ * Complexity: 6 (2 of which emulated) trigonometric functions. Note that acos
+ * is rather expensive apparently - roughly atan + sqrt.
+ *
+ * Reference:
+ * <p>
+ * R. W. Sinnott,<br/>
+ * Virtues of the Haversine<br />
+ * Sky and telescope, 68-2, 1984
+ * </p>
+ *
+ * @param lat1 Latitude of first point in degree
+ * @param lon1 Longitude of first point in degree
+ * @param lat2 Latitude of second point in degree
+ * @param lon2 Longitude of second point in degree
+ * @return Distance on unit sphere
+ */
+ public static double cosineFormulaRad(double lat1, double lon1, double lat2, double lon2) {
+ final double slat1 = Math.sin(lat1), clat1 = MathUtil.sinToCos(lat1, slat1);
+ final double slat2 = Math.sin(lat2), clat2 = MathUtil.sinToCos(lat2, slat2);
+ return Math.acos(Math.min(1.0, slat1 * slat2 + clat1 * clat2 * Math.cos(Math.abs(lon2 - lon1))));
+ }
+
+ /**
+ * Compute the approximate great-circle distance of two points using the
+ * Haversine formula
+ *
+ * Complexity: 5 trigonometric functions, 2 sqrt.
+ *
+ * Reference:
+ * <p>
+ * R. W. Sinnott,<br/>
+ * Virtues of the Haversine<br />
+ * Sky and telescope, 68-2, 1984
+ * </p>
+ *
+ * @param lat1 Latitude of first point in degree
+ * @param lon1 Longitude of first point in degree
+ * @param lat2 Latitude of second point in degree
+ * @param lon2 Longitude of second point in degree
+ * @return Distance on unit sphere
+ */
+ @Reference(authors = "Sinnott, R. W.", title = "Virtues of the Haversine", booktitle = "Sky and telescope, 68-2, 1984")
+ public static double haversineFormulaDeg(double lat1, double lon1, double lat2, double lon2) {
+ return haversineFormulaRad(MathUtil.deg2rad(lat1), MathUtil.deg2rad(lon1),//
+ MathUtil.deg2rad(lat2), MathUtil.deg2rad(lon2));
+ }
+
+ /**
+ * Compute the approximate great-circle distance of two points using the
+ * Haversine formula
+ *
+ * Complexity: 5 trigonometric functions, 2 sqrt.
+ *
+ * Reference:
+ * <p>
+ * R. W. Sinnott,<br/>
+ * Virtues of the Haversine<br />
+ * Sky and telescope, 68-2, 1984
+ * </p>
+ *
+ * @param lat1 Latitude of first point in degree
+ * @param lon1 Longitude of first point in degree
+ * @param lat2 Latitude of second point in degree
+ * @param lon2 Longitude of second point in degree
+ * @return Distance on unit sphere
+ */
+ @Reference(authors = "Sinnott, R. W.", title = "Virtues of the Haversine", booktitle = "Sky and telescope, 68-2, 1984")
+ public static double haversineFormulaRad(double lat1, double lon1, double lat2, double lon2) {
+ // Haversine formula, higher precision at < 1 meters but maybe issues at
+ // antipodal points.
+ final double slat = Math.sin((lat1 - lat2) * .5);
+ final double slon = Math.sin((lon1 - lon2) * .5);
+ final double a = slat * slat + slon * slon * Math.cos(lat1) * Math.cos(lat2);
+ return 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
+ }
+
+ /**
+ * Compute the approximate great-circle distance of two points.
+ *
+ * Uses Vincenty's Formula for the spherical case, which does not require
+ * iterations.
+ *
+ * Complexity: 7 trigonometric functions, 1 sqrt.
+ *
+ * Reference:
+ * <p>
+ * T. Vincenty<br />
+ * Direct and inverse solutions of geodesics on the ellipsoid with application
+ * of nested equations<br />
+ * Survey review 23 176, 1975
+ * </p>
+ *
+ * @param lat1 Latitude of first point in degree
+ * @param lon1 Longitude of first point in degree
+ * @param lat2 Latitude of second point in degree
+ * @param lon2 Longitude of second point in degree
+ * @return Distance in radians / on unit sphere.
+ */
+ @Reference(authors = "T. Vincenty", title = "Direct and inverse solutions of geodesics on the ellipsoid with application of nested equations", booktitle = "Survey review 23 176, 1975", url = "http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf")
+ public static double sphericalVincentyFormulaDeg(double lat1, double lon1, double lat2, double lon2) {
+ return sphericalVincentyFormulaRad(MathUtil.deg2rad(lat1), MathUtil.deg2rad(lon1),//
+ MathUtil.deg2rad(lat2), MathUtil.deg2rad(lon2));
+ }
+
+ /**
+ * Compute the approximate great-circle distance of two points.
+ *
+ * Uses Vincenty's Formula for the spherical case, which does not require
+ * iterations.
+ *
+ * Complexity: 7 trigonometric functions, 1 sqrt.
+ *
+ * Reference:
+ * <p>
+ * T. Vincenty<br />
+ * Direct and inverse solutions of geodesics on the ellipsoid with application
+ * of nested equations<br />
+ * Survey review 23 176, 1975
+ * </p>
+ *
+ * @param lat1 Latitude of first point in degree
+ * @param lon1 Longitude of first point in degree
+ * @param lat2 Latitude of second point in degree
+ * @param lon2 Longitude of second point in degree
+ * @return Distance on unit sphere
+ */
+ @Reference(authors = "T. Vincenty", title = "Direct and inverse solutions of geodesics on the ellipsoid with application of nested equations", booktitle = "Survey review 23 176, 1975", url = "http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf")
+ public static double sphericalVincentyFormulaRad(double lat1, double lon1, double lat2, double lon2) {
+ // Half delta longitude.
+ final double dlnh = Math.abs(lon1 - lon2);
+
+ // Spherical special case of Vincenty's formula - no iterations needed
+ final double slat1 = Math.sin(lat1), clat1 = MathUtil.sinToCos(lat1, slat1);
+ final double slat2 = Math.sin(lat2), clat2 = MathUtil.sinToCos(lat2, slat2);
+ final double slond = Math.sin(dlnh), clond = MathUtil.sinToCos(dlnh, slond);
+ final double a = clat2 * slond;
+ final double b = (clat1 * slat2) - (slat1 * clat2 * clond);
+ return Math.atan2(Math.sqrt(a * a + b * b), slat1 * slat2 + clat1 * clat2 * clond);
+ }
+
+ /**
+ * Compute the approximate great-circle distance of two points.
+ *
+ * Reference:
+ * <p>
+ * T. Vincenty<br />
+ * Direct and inverse solutions of geodesics on the ellipsoid with application
+ * of nested equations<br />
+ * Survey review 23 176, 1975
+ * </p>
+ *
+ * @param f Ellipsoid flattening
+ * @param lat1 Latitude of first point in degree
+ * @param lon1 Longitude of first point in degree
+ * @param lat2 Latitude of second point in degree
+ * @param lon2 Longitude of second point in degree
+ * @return Distance for a minor axis of 1.
+ */
+ @Reference(authors = "T. Vincenty", title = "Direct and inverse solutions of geodesics on the ellipsoid with application of nested equations", booktitle = "Survey review 23 176, 1975", url = "http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf")
+ public static double ellipsoidVincentyFormulaDeg(double f, double lat1, double lon1, double lat2, double lon2) {
+ return ellipsoidVincentyFormulaRad(f, MathUtil.deg2rad(lat1), MathUtil.deg2rad(lon1), //
+ MathUtil.deg2rad(lat2), MathUtil.deg2rad(lon2));
+ }
+
+ /**
+ * Compute the approximate great-circle distance of two points.
+ *
+ * Reference:
+ * <p>
+ * T. Vincenty<br />
+ * Direct and inverse solutions of geodesics on the ellipsoid with application
+ * of nested equations<br />
+ * Survey review 23 176, 1975
+ * </p>
+ *
+ * @param f Ellipsoid flattening
+ * @param lat1 Latitude of first point in degree
+ * @param lon1 Longitude of first point in degree
+ * @param lat2 Latitude of second point in degree
+ * @param lon2 Longitude of second point in degree
+ * @return Distance for a minor axis of 1.
+ */
+ @Reference(authors = "T. Vincenty", title = "Direct and inverse solutions of geodesics on the ellipsoid with application of nested equations", booktitle = "Survey review 23 176, 1975", url = "http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf")
+ public static double ellipsoidVincentyFormulaRad(double f, double lat1, double lon1, double lat2, double lon2) {
+ final double dlon = Math.abs(lon2 - lon1);
+ final double onemf = 1 - f; // = 1 - (a-b)/a = b/a
+
+ // Second eccentricity squared
+ final double a_b = 1. / onemf; // = a/b
+ final double ecc2 = (a_b + 1) * (a_b - 1); // (a^2-b^2)/(b^2)
+
+ // Reduced latitudes:
+ final double u1 = Math.atan(onemf * Math.tan(lat1));
+ final double u2 = Math.atan(onemf * Math.tan(lat2));
+ // Trigonometric values
+ final double su1 = Math.sin(u1), cu1 = MathUtil.sinToCos(u1, su1);
+ final double su2 = Math.sin(u2), cu2 = MathUtil.sinToCos(u2, su2);
+
+ // Eqn (13) - initial value
+ double lambda = dlon;
+
+ for (int i = 0;; i++) {
+ final double slon = Math.sin(lambda), clon = MathUtil.sinToCos(lambda, slon);
+
+ // Eqn (14) - \sin \sigma
+ final double term1 = cu2 * slon, term2 = cu1 * su2 - su1 * cu2 * clon;
+ final double ssig = Math.sqrt(term1 * term1 + term2 * term2);
+ // Eqn (15) - \cos \sigma
+ final double csig = su1 * su2 + cu1 * cu2 * clon;
+ // Eqn (16) - \sigma from \tan \sigma
+ final double sigma = Math.atan2(ssig, csig);
+
+ // Two identical points?
+ if (!(ssig > 0)) {
+ return 0.;
+ }
+ // Eqn (17) - \sin \alpha, and this way \cos^2 \alpha
+ final double salp = cu1 * cu2 * slon / ssig;
+ final double c2alp = (1. + salp) * (1. - salp);
+ // Eqn (18) - \cos 2 \sigma_m
+ final double ctwosigm = (Math.abs(c2alp) > 0) ? csig - 2.0 * su1 * su2 / c2alp : 0.;
+ final double c2twosigm = ctwosigm * ctwosigm;
+
+ // Eqn (10) - C
+ final double cc = f * .0625 * c2alp * (4.0 + f * (4.0 - 3.0 * c2alp));
+ // Eqn (11) - new \lambda
+ final double prevlambda = lambda;
+ lambda = dlon + (1.0 - cc) * f * salp * //
+ (sigma + cc * ssig * (ctwosigm + cc * csig * (-1.0 + 2.0 * c2twosigm)));
+ // Check for convergence:
+ if (Math.abs(prevlambda - lambda) < PRECISION || i >= MAX_ITER) {
+ // TODO: what is the proper result to return on MAX_ITER (antipodal
+ // points)?
+ // Definition of u^2, rewritten to use second eccentricity.
+ final double usq = c2alp * ecc2;
+ // Eqn (3) - A
+ final double aa = 1.0 + usq / 16384.0 * (4096.0 + usq * (-768.0 + usq * (320.0 - 175.0 * usq)));
+ // Eqn (4) - B
+ final double bb = usq / 1024.0 * (256.0 + usq * (-128.0 + usq * (74.0 - 47.0 * usq)));
+ // Eqn (6) - \Delta \sigma
+ final double dsig = bb * ssig * (ctwosigm + .25 * bb * (csig * (-1.0 + 2.0 * c2twosigm) //
+ - ONE_SIXTH * bb * ctwosigm * (-3.0 + 4.0 * ssig * ssig) * (-3.0 + 4.0 * c2twosigm)));
+ // Eqn (19) - s
+ return aa * (sigma - dsig);
+ }
+ }
+ }
+
+ /**
+ * Compute the cross-track distance.
+ *
+ * XTD = asin(sin(dist_1Q)*sin(crs_1Q-crs_12))
+ *
+ * @param lat1 Latitude of starting point.
+ * @param lon1 Longitude of starting point.
+ * @param lat2 Latitude of destination point.
+ * @param lon2 Longitude of destination point.
+ * @param latQ Latitude of query point.
+ * @param lonQ Longitude of query point.
+ * @return Cross-track distance in km. May be negative - this gives the side.
+ */
+ public static double crossTrackDistanceDeg(double lat1, double lon1, double lat2, double lon2, double latQ, double lonQ) {
+ return crossTrackDistanceRad(MathUtil.deg2rad(lat1), MathUtil.deg2rad(lon1),//
+ MathUtil.deg2rad(lat2), MathUtil.deg2rad(lon2),//
+ MathUtil.deg2rad(latQ), MathUtil.deg2rad(lonQ));
+ }
+
+ /**
+ * Compute the cross-track distance.
+ *
+ * @param lat1 Latitude of starting point.
+ * @param lon1 Longitude of starting point.
+ * @param lat2 Latitude of destination point.
+ * @param lon2 Longitude of destination point.
+ * @param latQ Latitude of query point.
+ * @param lonQ Longitude of query point.
+ * @param dist1Q Distance from starting point to query point on unit sphere
+ * @return Cross-track distance on unit sphere. May be negative - this gives
+ * the side.
+ */
+ public static double crossTrackDistanceRad(double lat1, double lon1, double lat2, double lon2, double latQ, double lonQ, double dist1Q) {
+ final double dlon12 = lon2 - lon1;
+ final double dlon1Q = lonQ - lon1;
+
+ // Compute trigonometric functions only once.
+ final double slat1 = Math.sin(lat1), clat1 = MathUtil.sinToCos(lat1, slat1);
+ final double slatQ = Math.sin(latQ), clatQ = MathUtil.sinToCos(latQ, slatQ);
+ final double slat2 = Math.sin(lat2), clat2 = MathUtil.sinToCos(lat2, slat2);
+
+ // / Compute the course
+ // y = sin(dlon) * cos(lat2)
+ final double sdlon12 = Math.sin(dlon12), cdlon12 = MathUtil.sinToCos(dlon12, sdlon12);
+ final double sdlon1Q = Math.sin(dlon1Q), cdlon1Q = MathUtil.sinToCos(dlon1Q, sdlon1Q);
+
+ final double yE = sdlon12 * clat2;
+ final double yQ = sdlon1Q * clatQ;
+
+ // x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dlon)
+ final double xE = clat1 * slat2 - slat1 * clat2 * cdlon12;
+ final double xQ = clat1 * slatQ - slat1 * clatQ * cdlon1Q;
+
+ final double crs12 = Math.atan2(yE, xE);
+ final double crs1Q = Math.atan2(yQ, xQ);
+
+ // / Calculate cross-track distance
+ return Math.asin(Math.sin(dist1Q) * Math.sin(crs1Q - crs12));
+ }
+
+ /**
+ * Compute the cross-track distance.
+ *
+ * @param lat1 Latitude of starting point.
+ * @param lon1 Longitude of starting point.
+ * @param lat2 Latitude of destination point.
+ * @param lon2 Longitude of destination point.
+ * @param latQ Latitude of query point.
+ * @param lonQ Longitude of query point.
+ * @param dist1Q Distance from starting point to query point in radians (i.e.
+ * on unit sphere).
+ * @return Cross-track distance on unit sphere. May be negative - this gives
+ * the side.
+ */
+ public static double crossTrackDistanceDeg(double lat1, double lon1, double lat2, double lon2, double latQ, double lonQ, double dist1Q) {
+ return crossTrackDistanceRad(MathUtil.deg2rad(lat1), MathUtil.deg2rad(lon1),//
+ MathUtil.deg2rad(lat2), MathUtil.deg2rad(lon2),//
+ MathUtil.deg2rad(latQ), MathUtil.deg2rad(lonQ),//
+ dist1Q);
+ }
+
+ /**
+ * Compute the cross-track distance.
+ *
+ * XTD = asin(sin(dist_SQ)*sin(crs_SQ-crs_SE))
+ *
+ * @param lat1 Latitude of starting point.
+ * @param lon1 Longitude of starting point.
+ * @param lat2 Latitude of destination point.
+ * @param lon2 Longitude of destination point.
+ * @param latQ Latitude of query point.
+ * @param lonQ Longitude of query point.
+ * @return Cross-track distance in km. May be negative - this gives the side.
+ */
+ public static double crossTrackDistanceRad(double lat1, double lon1, double lat2, double lon2, double latQ, double lonQ) {
+ final double dlon12 = lon2 - lon1;
+ final double dlon1Q = lonQ - lon1;
+ final double dlat1Q = latQ - lat1;
+
+ // Compute trigonometric functions only once.
+ final double clat1 = Math.cos(lat1), slat1 = MathUtil.cosToSin(lat1, clat1);
+ final double clatQ = Math.cos(latQ), slatQ = MathUtil.cosToSin(latQ, clatQ);
+ final double clat2 = Math.cos(lat2), slat2 = MathUtil.cosToSin(lat2, clat2);
+
+ // Haversine formula, higher precision at < 1 meters but maybe issues at
+ // antipodal points - we do not yet multiply with the radius!
+ final double slat = Math.sin(dlat1Q * .5);
+ final double slon = Math.sin(dlon1Q * .5);
+ final double a = slat * slat + slon * slon * clat1 * clatQ;
+ final double angDist1Q = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
+
+ // Compute the course
+ // y = sin(dlon) * cos(lat2)
+ final double sdlon12 = Math.sin(dlon12), cdlon12 = MathUtil.sinToCos(dlon12, sdlon12);
+ final double sdlon1Q = Math.sin(dlon1Q), cdlon1Q = MathUtil.sinToCos(dlon1Q, sdlon1Q);
+ final double yE = sdlon12 * clat2;
+ final double yQ = sdlon1Q * clatQ;
+
+ // x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dlon)
+ final double xE = clat1 * slat2 - slat1 * clat2 * cdlon12;
+ final double xQ = clat1 * slatQ - slat1 * clatQ * cdlon1Q;
+
+ final double crs12 = Math.atan2(yE, xE);
+ final double crs1Q = Math.atan2(yQ, xQ);
+
+ // Calculate cross-track distance
+ return Math.asin(Math.sin(angDist1Q) * Math.sin(crs1Q - crs12));
+ }
+
+ /**
+ * The along track distance, is the distance from S to Q along the track S to
+ * E.
+ *
+ * ATD=acos(cos(dist_1Q)/cos(XTD))
+ *
+ * TODO: optimize.
+ *
+ * @param lat1 Latitude of starting point.
+ * @param lon1 Longitude of starting point.
+ * @param lat2 Latitude of destination point.
+ * @param lon2 Longitude of destination point.
+ * @param latQ Latitude of query point.
+ * @param lonQ Longitude of query point.
+ * @return Along-track distance in radians. May be negative - this gives the
+ * side.
+ */
+ public static double alongTrackDistanceDeg(double lat1, double lon1, double lat2, double lon2, double latQ, double lonQ) {
+ // TODO: inline and share some of the trigonometric computations!
+ double dist1Q = haversineFormulaDeg(lat1, lon1, latQ, lonQ);
+ double ctd = crossTrackDistanceDeg(lat1, lon1, lat2, lon2, latQ, lonQ, dist1Q);
+ return alongTrackDistanceDeg(lat1, lon1, lat2, lon2, latQ, lonQ, dist1Q, ctd);
+ }
+
+ /**
+ * The along track distance, is the distance from S to Q along the track S to
+ * E.
+ *
+ * ATD=acos(cos(dist_1Q)/cos(XTD))
+ *
+ * TODO: optimize.
+ *
+ * @param lat1 Latitude of starting point in radians.
+ * @param lon1 Longitude of starting point in radians.
+ * @param lat2 Latitude of destination point in radians.
+ * @param lon2 Longitude of destination point in radians.
+ * @param latQ Latitude of query point in radians.
+ * @param lonQ Longitude of query point in radians.
+ * @return Along-track distance in radians. May be negative - this gives the
+ * side.
+ */
+ public static double alongTrackDistanceRad(double lat1, double lon1, double lat2, double lon2, double latQ, double lonQ) {
+ // TODO: inline and share some of the trigonometric computations!
+ double dist1Q = haversineFormulaRad(lat1, lon1, latQ, lonQ);
+ double ctd = crossTrackDistanceRad(lat1, lon1, lat2, lon2, latQ, lonQ, dist1Q);
+ return alongTrackDistanceRad(lat1, lon1, lat2, lon2, latQ, lonQ, dist1Q, ctd);
+ }
+
+ /**
+ * The along track distance, is the distance from S to Q along the track S to
+ * E.
+ *
+ * ATD=acos(cos(dist_SQ)/cos(XTD))
+ *
+ * @param lat1 Latitude of starting point.
+ * @param lon1 Longitude of starting point.
+ * @param lat2 Latitude of destination point.
+ * @param lon2 Longitude of destination point.
+ * @param latQ Latitude of query point.
+ * @param lonQ Longitude of query point.
+ * @param dist1Q Distance S to Q in radians.
+ * @param ctd Cross-track-distance in radians.
+ * @return Along-track distance in radians. May be negative - this gives the
+ * side.
+ */
+ public static double alongTrackDistanceDeg(double lat1, double lon1, double lat2, double lon2, double latQ, double lonQ, double dist1Q, double ctd) {
+ return alongTrackDistanceRad(MathUtil.deg2rad(lat1), MathUtil.deg2rad(lon1), MathUtil.deg2rad(lat2), MathUtil.deg2rad(lon2), MathUtil.deg2rad(latQ), MathUtil.deg2rad(lonQ), dist1Q, ctd);
+ }
+
+ /**
+ * The along track distance, is the distance from S to Q along the track S to
+ * E.
+ *
+ * ATD=acos(cos(dist_SQ)/cos(XTD))
+ *
+ * TODO: optimize: can we do a faster sign computation?
+ *
+ * @param lat1 Latitude of starting point in radians.
+ * @param lon1 Longitude of starting point in radians.
+ * @param lat2 Latitude of destination point in radians.
+ * @param lon2 Longitude of destination point in radians.
+ * @param latQ Latitude of query point in radians.
+ * @param lonQ Longitude of query point in radians.
+ * @param dist1Q Distance S to Q in radians.
+ * @param ctd Cross-track-distance in radians.
+ * @return Along-track distance in radians. May be negative - this gives the
+ * side.
+ */
+ public static double alongTrackDistanceRad(double lat1, double lon1, double lat2, double lon2, double latQ, double lonQ, double dist1Q, double ctd) {
+ // FIXME: optimize the sign computation!
+ int sign = Math.abs(bearingRad(lat1, lon1, lat2, lon2) - bearingRad(lat1, lon1, latQ, lonQ)) < MathUtil.HALFPI ? +1 : -1;
+ return sign * Math.acos(Math.cos(dist1Q) / Math.cos(ctd));
+ // TODO: for short distances, use this instead?
+ // asin(sqrt( (sin(dist_1Q))^2 - (sin(XTD))^2 )/cos(XTD))
+ }
+
+ /**
+ * Point to rectangle minimum distance.
+ *
+ * Complexity:
+ * <ul>
+ * <li>Trivial cases (on longitude slice): no trigonometric functions.</li>
+ * <li>Cross-track case: 10+2 trig</li>
+ * <li>Corner case: 10+3 trig, 2 sqrt</li>
+ * </ul>
+ *
+ * Reference:
+ * <p>
+ * Erich Schubert, Arthur Zimek and Hans-Peter Kriegel<br />
+ * Geodetic Distance Queries on R-Trees for Indexing Geographic Data<br />
+ * Advances in Spatial and Temporal Databases - 13th International Symposium,
+ * SSTD 2013, Munich, Germany
+ * </p>
+ *
+ * @param plat Latitude of query point.
+ * @param plng Longitude of query point.
+ * @param rminlat Min latitude of rectangle.
+ * @param rminlng Min longitude of rectangle.
+ * @param rmaxlat Max latitude of rectangle.
+ * @param rmaxlng Max longitude of rectangle.
+ * @return Distance in radians.
+ */
+ @Reference(authors = "Erich Schubert, Arthur Zimek and Hans-Peter Kriegel", title = "Geodetic Distance Queries on R-Trees for Indexing Geographic Data", booktitle = "Advances in Spatial and Temporal Databases - 13th International Symposium, SSTD 2013, Munich, Germany")
+ public static double latlngMinDistDeg(double plat, double plng, double rminlat, double rminlng, double rmaxlat, double rmaxlng) {
+ return latlngMinDistRad(MathUtil.deg2rad(plat), MathUtil.deg2rad(plng),//
+ MathUtil.deg2rad(rminlat), MathUtil.deg2rad(rminlng), //
+ MathUtil.deg2rad(rmaxlat), MathUtil.deg2rad(rmaxlng));
+ }
+
+ /**
+ * Point to rectangle minimum distance.
+ *
+ * Complexity:
+ * <ul>
+ * <li>Trivial cases (on longitude slice): no trigonometric functions.</li>
+ * <li>Corner case: 3/4 trig + (haversine:) 5 trig, 2 sqrt</li>
+ * <li>Cross-track case: 4+3 trig</li>
+ * </ul>
+ *
+ * Reference:
+ * <p>
+ * Erich Schubert, Arthur Zimek and Hans-Peter Kriegel<br />
+ * Geodetic Distance Queries on R-Trees for Indexing Geographic Data<br />
+ * Advances in Spatial and Temporal Databases - 13th International Symposium,
+ * SSTD 2013, Munich, Germany
+ * </p>
+ *
+ * @param plat Latitude of query point.
+ * @param plng Longitude of query point.
+ * @param rminlat Min latitude of rectangle.
+ * @param rminlng Min longitude of rectangle.
+ * @param rmaxlat Max latitude of rectangle.
+ * @param rmaxlng Max longitude of rectangle.
+ * @return Distance on unit sphere.
+ */
+ @Reference(authors = "Erich Schubert, Arthur Zimek and Hans-Peter Kriegel", title = "Geodetic Distance Queries on R-Trees for Indexing Geographic Data", booktitle = "Advances in Spatial and Temporal Databases - 13th International Symposium, SSTD 2013, Munich, Germany")
+ public static double latlngMinDistRad(double plat, double plng, double rminlat, double rminlng, double rmaxlat, double rmaxlng) {
+ // FIXME: handle rectangles crossing the +-180 deg boundary correctly!
+
+ // Degenerate rectangles:
+ if ((rminlat >= rmaxlat) && (rminlng >= rmaxlng)) {
+ return haversineFormulaRad(rminlat, rminlng, plat, plng);
+ }
+
+ // The simplest case is when the query point is in the same "slice":
+ if (rminlng <= plng && plng <= rmaxlng) {
+ // Inside rectangle:
+ if (rminlat <= plat && plat <= rmaxlat) {
+ return 0;
+ }
+ // South:
+ if (plat < rminlat) {
+ return rminlat - plat;
+ } else {
+ // plat > rmaxlat
+ return plat - rmaxlat;
+ }
+ }
+
+ // Determine whether going east or west is shorter.
+ double lngE = rminlng - plng;
+ if (lngE < 0) {
+ lngE += MathUtil.TWOPI;
+ }
+ double lngW = rmaxlng - plng; // we keep this negative!
+ if (lngW > 0) {
+ lngW -= MathUtil.TWOPI;
+ }
+
+ // East, to min edge:
+ if (lngE <= -lngW) {
+ final double clngD = Math.cos(lngE);
+ final double tlatQ = Math.tan(plat);
+ if (lngE > MathUtil.HALFPI) {
+ final double tlatm = Math.tan((rmaxlat + rminlat) * .5);
+ if (tlatQ >= tlatm * clngD) {
+ return haversineFormulaRad(plat, plng, rmaxlat, rminlng);
+ } else {
+ return haversineFormulaRad(plat, plng, rminlat, rminlng);
+ }
+ }
+ final double tlatN = Math.tan(rmaxlat);
+ if (tlatQ >= tlatN * clngD) { // North corner
+ return haversineFormulaRad(plat, plng, rmaxlat, rminlng);
+ }
+ final double tlatS = Math.tan(rminlat);
+ if (tlatQ <= tlatS * clngD) { // South corner
+ return haversineFormulaRad(plat, plng, rminlat, rminlng);
+ }
+ // Cross-track-distance to longitude line.
+ final double slngD = MathUtil.cosToSin(lngE, clngD);
+ return Math.asin(Math.cos(plat) * slngD);
+ } else { // West, to max edge:
+ final double clngD = Math.cos(lngW);
+ final double tlatQ = Math.tan(plat);
+ if (-lngW > MathUtil.HALFPI) {
+ final double tlatm = Math.tan((rmaxlat + rminlat) * .5);
+ if (tlatQ >= tlatm * clngD) {
+ return haversineFormulaRad(plat, plng, rmaxlat, rmaxlng);
+ } else {
+ return haversineFormulaRad(plat, plng, rminlat, rmaxlng);
+ }
+ }
+ final double tlatN = Math.tan(rmaxlat);
+ if (tlatQ >= tlatN * clngD) { // North corner
+ return haversineFormulaRad(plat, plng, rmaxlat, rmaxlng);
+ }
+ final double tlatS = Math.tan(rminlat);
+ if (tlatQ <= tlatS * clngD) { // South corner
+ return haversineFormulaRad(plat, plng, rminlat, rmaxlng);
+ }
+ // Cross-track-distance to longitude line.
+ final double slngD = MathUtil.cosToSin(lngW, clngD);
+ return Math.asin(-Math.cos(plat) * slngD);
+ }
+ }
+
+ /**
+ * Point to rectangle minimum distance.
+ *
+ * Previous version, only around for reference.
+ *
+ * Complexity:
+ * <ul>
+ * <li>Trivial cases (on longitude slice): no trigonometric functions.</li>
+ * <li>Cross-track case: 10+2 trig</li>
+ * <li>Corner case: 10+3 trig, 2 sqrt</li>
+ * </ul>
+ *
+ * Reference:
+ * <p>
+ * Erich Schubert, Arthur Zimek and Hans-Peter Kriegel<br />
+ * Geodetic Distance Queries on R-Trees for Indexing Geographic Data<br />
+ * Advances in Spatial and Temporal Databases - 13th International Symposium,
+ * SSTD 2013, Munich, Germany
+ * </p>
+ *
+ * @param plat Latitude of query point.
+ * @param plng Longitude of query point.
+ * @param rminlat Min latitude of rectangle.
+ * @param rminlng Min longitude of rectangle.
+ * @param rmaxlat Max latitude of rectangle.
+ * @param rmaxlng Max longitude of rectangle.
+ * @return Distance in radians
+ */
+ @Reference(authors = "Erich Schubert, Arthur Zimek and Hans-Peter Kriegel", title = "Geodetic Distance Queries on R-Trees for Indexing Geographic Data", booktitle = "Advances in Spatial and Temporal Databases - 13th International Symposium, SSTD 2013, Munich, Germany")
+ public static double latlngMinDistRadFull(double plat, double plng, double rminlat, double rminlng, double rmaxlat, double rmaxlng) {
+ // FIXME: handle rectangles crossing the +-180 deg boundary correctly!
+
+ // Degenerate rectangles:
+ if ((rminlat >= rmaxlat) && (rminlng >= rmaxlng)) {
+ return haversineFormulaRad(rminlat, rminlng, plat, plng);
+ }
+
+ // The simplest case is when the query point is in the same "slice":
+ if (rminlng <= plng && plng <= rmaxlng) {
+ // Inside rectangle:
+ if (rminlat <= plat && plat <= rmaxlat) {
+ return 0;
+ }
+ // South:
+ if (plat < rminlat) {
+ return rminlat - plat;
+ } else {
+ // plat > rmaxlat
+ return plat - rmaxlat;
+ }
+ }
+
+ // Determine whether going east or west is shorter.
+ double lngE = rminlng - plng;
+ if (lngE < 0) {
+ lngE += MathUtil.TWOPI;
+ }
+ double lngW = rmaxlng - plng; // we keep this negative!
+ if (lngW > 0) {
+ lngW -= MathUtil.TWOPI;
+ }
+
+ // Compute sine and cosine values we will certainly need below:
+ final double slatQ = Math.sin(plat), clatQ = MathUtil.sinToCos(plat, slatQ);
+ final double slatN = Math.sin(rmaxlat), clatN = MathUtil.sinToCos(rmaxlat, slatN);
+ final double slatS = Math.sin(rminlat), clatS = MathUtil.sinToCos(rminlat, slatS);
+
+ // East, to min edge:
+ if (lngE <= -lngW) {
+ final double slngD = Math.sin(lngE);
+ final double clngD = MathUtil.sinToCos(lngE, slngD);
+
+ // Bearing to south
+ // Math.atan2(slngD * clatS, clatQ * slatS - slatQ * clatS * clngD);
+ // Bearing from south
+ final double bs = Math.atan2(slngD * clatQ, clatS * slatQ - slatS * clatQ * clngD);
+ // Bearing to north
+ // Math.atan2(slngD * clatN, clatQ * slatN - slatQ * clatN * clngD);
+ // Bearing from north
+ final double bn = Math.atan2(slngD * clatQ, clatN * slatQ - slatN * clatQ * clngD);
+ if (bs < MathUtil.HALFPI) {
+ if (bn > MathUtil.HALFPI) {
+ // Radians from south pole = abs(ATD)
+ final double radFromS = -MathUtil.HALFPI - plat;
+
+ // Cross-track-distance to longitude line.
+ return Math.asin(Math.sin(radFromS) * -slngD);
+ }
+ }
+ if (bs - MathUtil.HALFPI < MathUtil.HALFPI - bn) {
+ // Haversine to north corner.
+ final double slatN2 = Math.sin((plat - rmaxlat) * .5);
+ final double slon = Math.sin(lngE * .5);
+ final double aN = slatN2 * slatN2 + slon * slon * clatQ * clatN;
+ final double distN = 2 * Math.atan2(Math.sqrt(aN), Math.sqrt(1 - aN));
+ return distN;
+ } else {
+ // Haversine to south corner.
+ final double slatS2 = Math.sin((plat - rminlat) * .5);
+ final double slon = Math.sin(lngE * .5);
+ final double aS = slatS2 * slatS2 + slon * slon * clatQ * clatS;
+ final double distS = 2 * Math.atan2(Math.sqrt(aS), Math.sqrt(1 - aS));
+ return distS;
+ }
+ } else { // West, to max edge
+ final double slngD = Math.sin(lngW);
+ final double clngD = MathUtil.sinToCos(lngW, slngD);
+
+ // Bearing to south
+ // Math.atan2(slngD * clatS, clatQ * slatS - slatQ * clatS * clngD);
+ // Bearing from south
+ final double bs = Math.atan2(slngD * clatQ, clatS * slatQ - slatS * clatQ * clngD);
+ // Bearing to north
+ // Math.atan2(slngD * clatN, clatQ * slatN - slatQ * clatN * clngD);
+ // Bearing from north
+ final double bn = Math.atan2(slngD * clatQ, clatN * slatQ - slatN * clatQ * clngD);
+ if (bs > -MathUtil.HALFPI) {
+ if (bn < -MathUtil.HALFPI) {
+ // Radians from south = abs(ATD) = distance from pole
+ final double radFromS = -MathUtil.HALFPI - plat;
+ // Cross-track-distance to longitude line.
+ return Math.asin(Math.sin(radFromS) * slngD);
+ }
+ }
+ if (-MathUtil.HALFPI - bs < bn + MathUtil.HALFPI) {
+ // Haversine to north corner.
+ final double slatN2 = Math.sin((plat - rmaxlat) * .5);
+ final double slon = Math.sin(lngW * .5);
+ final double aN = slatN2 * slatN2 + slon * slon * clatQ * clatN;
+ final double distN = 2 * Math.atan2(Math.sqrt(aN), Math.sqrt(1 - aN));
+ return distN;
+ } else {
+ // Haversine to south corner.
+ final double slatS2 = Math.sin((plat - rminlat) * .5);
+ final double slon = Math.sin(lngW * .5);
+ final double aS = slatS2 * slatS2 + slon * slon * clatQ * clatS;
+ final double distS = 2 * Math.atan2(Math.sqrt(aS), Math.sqrt(1 - aS));
+ return distS;
+ }
+ }
+ }
+
+ /**
+ * Compute the bearing from start to end.
+ *
+ * @param latS Start latitude, in degree
+ * @param lngS Start longitude, in degree
+ * @param latE End latitude, in degree
+ * @param lngE End longitude, in degree
+ * @return Bearing in degree
+ */
+ public static double bearingDegDeg(double latS, double lngS, double latE, double lngE) {
+ return MathUtil.rad2deg(bearingRad(MathUtil.deg2rad(latS), MathUtil.deg2rad(lngS), MathUtil.deg2rad(latE), MathUtil.deg2rad(lngE)));
+ }
+
+ /**
+ * Compute the bearing from start to end.
+ *
+ * @param latS Start latitude, in radians
+ * @param lngS Start longitude, in radians
+ * @param latE End latitude, in radians
+ * @param lngE End longitude, in radians
+ * @return Bearing in degree
+ */
+ public static double bearingRad(double latS, double lngS, double latE, double lngE) {
+ final double slatS = Math.sin(latS), clatS = MathUtil.sinToCos(latS, slatS);
+ final double slatE = Math.sin(latE), clatE = MathUtil.sinToCos(latE, slatE);
+ return Math.atan2(-Math.sin(lngS - lngE) * clatE, clatS * slatE - slatS * clatE * Math.cos(lngS - lngE));
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/geodesy/SphericalCosineEarthModel.java b/src/de/lmu/ifi/dbs/elki/math/geodesy/SphericalCosineEarthModel.java
new file mode 100644
index 00000000..f81757ac
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/geodesy/SphericalCosineEarthModel.java
@@ -0,0 +1,97 @@
+package de.lmu.ifi.dbs.elki.math.geodesy;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * A simple spherical earth model using radius 6371009 m.
+ *
+ * For distance computations, this variant uses the Cosine formula, which is
+ * faster but less accurate than the Haversince or Vincenty's formula.
+ *
+ * @author Erich Schubert
+ */
+public class SphericalCosineEarthModel extends AbstractEarthModel {
+ /**
+ * Spherical earth model, static instance.
+ */
+ public static final SphericalCosineEarthModel STATIC = new SphericalCosineEarthModel();
+
+ /**
+ * Earth radius approximation in m.
+ */
+ public static final double EARTH_RADIUS = 6371009; // m
+
+ /**
+ * Constructor.
+ */
+ protected SphericalCosineEarthModel() {
+ super(EARTH_RADIUS, EARTH_RADIUS, 0., Double.POSITIVE_INFINITY);
+ }
+
+ @Override
+ public double[] latLngRadToECEF(double lat, double lng) {
+ // Then to sine and cosines:
+ final double clat = Math.cos(lat), slat = MathUtil.cosToSin(lat, clat);
+ final double clng = Math.cos(lng), slng = MathUtil.cosToSin(lng, clng);
+
+ return new double[] { EARTH_RADIUS * clat * clng, EARTH_RADIUS * clat * slng, EARTH_RADIUS * slat };
+ }
+
+ @Override
+ public double[] latLngRadToECEF(double lat, double lng, double h) {
+ // Then to sine and cosines:
+ final double clat = Math.cos(lat), slat = MathUtil.cosToSin(lat, clat);
+ final double clng = Math.cos(lng), slng = MathUtil.cosToSin(lng, clng);
+
+ return new double[] { (EARTH_RADIUS + h) * clat * clng, (EARTH_RADIUS + h) * clat * slng, (EARTH_RADIUS + h) * slat };
+ }
+
+ @Override
+ public double ecefToLatRad(double x, double y, double z) {
+ final double p = Math.sqrt(x * x + y * y);
+ return Math.atan2(z, p);
+ }
+
+ @Override
+ public double distanceRad(double lat1, double lng1, double lat2, double lng2) {
+ return EARTH_RADIUS * SphereUtil.cosineFormulaRad(lat1, lng1, lat2, lng2);
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected SphericalCosineEarthModel makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/geodesy/SphericalHaversineEarthModel.java b/src/de/lmu/ifi/dbs/elki/math/geodesy/SphericalHaversineEarthModel.java
new file mode 100644
index 00000000..5ed8c4ca
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/geodesy/SphericalHaversineEarthModel.java
@@ -0,0 +1,97 @@
+package de.lmu.ifi.dbs.elki.math.geodesy;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * A simple spherical earth model using radius 6371009 m.
+ *
+ * For distance computations, this variant uses the Haversine formula, which is
+ * faster but less accurate than Vincenty's formula.
+ *
+ * @author Erich Schubert
+ */
+public class SphericalHaversineEarthModel extends AbstractEarthModel {
+ /**
+ * Spherical earth model, static instance.
+ */
+ public static final SphericalHaversineEarthModel STATIC = new SphericalHaversineEarthModel();
+
+ /**
+ * Earth radius approximation in m.
+ */
+ public static final double EARTH_RADIUS = 6371009; // m
+
+ /**
+ * Constructor.
+ */
+ protected SphericalHaversineEarthModel() {
+ super(EARTH_RADIUS, EARTH_RADIUS, 0., Double.POSITIVE_INFINITY);
+ }
+
+ @Override
+ public double[] latLngRadToECEF(double lat, double lng) {
+ // Then to sine and cosines:
+ final double clat = Math.cos(lat), slat = MathUtil.cosToSin(lat, clat);
+ final double clng = Math.cos(lng), slng = MathUtil.cosToSin(lng, clng);
+
+ return new double[] { EARTH_RADIUS * clat * clng, EARTH_RADIUS * clat * slng, EARTH_RADIUS * slat };
+ }
+
+ @Override
+ public double[] latLngRadToECEF(double lat, double lng, double h) {
+ // Then to sine and cosines:
+ final double clat = Math.cos(lat), slat = MathUtil.cosToSin(lat, clat);
+ final double clng = Math.cos(lng), slng = MathUtil.cosToSin(lng, clng);
+
+ return new double[] { (EARTH_RADIUS + h) * clat * clng, (EARTH_RADIUS + h) * clat * slng, (EARTH_RADIUS + h) * slat };
+ }
+
+ @Override
+ public double ecefToLatRad(double x, double y, double z) {
+ final double p = Math.sqrt(x * x + y * y);
+ return Math.atan2(z, p);
+ }
+
+ @Override
+ public double distanceRad(double lat1, double lng1, double lat2, double lng2) {
+ return EARTH_RADIUS * SphereUtil.haversineFormulaRad(lat1, lng1, lat2, lng2);
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected SphericalHaversineEarthModel makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/geodesy/SphericalVincentyEarthModel.java b/src/de/lmu/ifi/dbs/elki/math/geodesy/SphericalVincentyEarthModel.java
new file mode 100644
index 00000000..e9a780cc
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/geodesy/SphericalVincentyEarthModel.java
@@ -0,0 +1,96 @@
+package de.lmu.ifi.dbs.elki.math.geodesy;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * A simple spherical earth model using radius 6371009 m.
+ *
+ * @author Erich Schubert
+ */
+public class SphericalVincentyEarthModel extends AbstractEarthModel {
+ /**
+ * Spherical earth model, static instance.
+ */
+ public static final SphericalVincentyEarthModel STATIC = new SphericalVincentyEarthModel();
+
+ /**
+ * Earth radius approximation in m.
+ *
+ * As per International Union of Geodesy and Geophysics (IUGG):
+ */
+ public static final double EARTH_RADIUS = 6371009; // m
+
+ /**
+ * Constructor.
+ */
+ protected SphericalVincentyEarthModel() {
+ super(EARTH_RADIUS, EARTH_RADIUS, 0., Double.POSITIVE_INFINITY);
+ }
+
+ @Override
+ public double[] latLngRadToECEF(double lat, double lng) {
+ // Then to sine and cosines:
+ final double clat = Math.cos(lat), slat = MathUtil.cosToSin(lat, clat);
+ final double clng = Math.cos(lng), slng = MathUtil.cosToSin(lng, clng);
+
+ return new double[] { EARTH_RADIUS * clat * clng, EARTH_RADIUS * clat * slng, EARTH_RADIUS * slat };
+ }
+
+ @Override
+ public double[] latLngRadToECEF(double lat, double lng, double h) {
+ // Then to sine and cosines:
+ final double clat = Math.cos(lat), slat = MathUtil.cosToSin(lat, clat);
+ final double clng = Math.cos(lng), slng = MathUtil.cosToSin(lng, clng);
+
+ return new double[] { (EARTH_RADIUS + h) * clat * clng, (EARTH_RADIUS + h) * clat * slng, (EARTH_RADIUS + h) * slat };
+ }
+
+ @Override
+ public double ecefToLatRad(double x, double y, double z) {
+ final double p = Math.sqrt(x * x + y * y);
+ return Math.atan2(z, p);
+ }
+
+ @Override
+ public double distanceRad(double lat1, double lng1, double lat2, double lng2) {
+ return EARTH_RADIUS * SphereUtil.sphericalVincentyFormulaRad(lat1, lng1, lat2, lng2);
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected SphericalVincentyEarthModel makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/geodesy/WGS72SpheroidEarthModel.java b/src/de/lmu/ifi/dbs/elki/math/geodesy/WGS72SpheroidEarthModel.java
new file mode 100644
index 00000000..44d4f9d0
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/geodesy/WGS72SpheroidEarthModel.java
@@ -0,0 +1,81 @@
+package de.lmu.ifi.dbs.elki.math.geodesy;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.utilities.Alias;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * The WGS72 spheroid earth model, without height model.
+ *
+ *
+ * Radius: 6378135.0 m
+ *
+ * Flattening: 1 / 298.26
+ *
+ * @author Erich Schubert
+ */
+@Alias({ "WGS72", "WGS-72", "WGS72" })
+public class WGS72SpheroidEarthModel extends AbstractEarthModel {
+ /**
+ * Static instance.
+ */
+ public static final WGS72SpheroidEarthModel STATIC = new WGS72SpheroidEarthModel();
+
+ /**
+ * Radius of the WGS72 Ellipsoid in m (a).
+ */
+ public static final double WGS72_RADIUS = 6378135.0; // m
+
+ /**
+ * Inverse flattening 1/f of the WGS72 Ellipsoid.
+ */
+ public static final double WGS72_INV_FLATTENING = 298.26;
+
+ /**
+ * Flattening f of the WGS72 Ellipsoid.
+ */
+ public static final double WGS72_FLATTENING = 1 / WGS72_INV_FLATTENING;
+
+ /**
+ * Constructor.
+ */
+ protected WGS72SpheroidEarthModel() {
+ super(WGS72_RADIUS, WGS72_RADIUS * (1 - WGS72_FLATTENING), WGS72_FLATTENING, WGS72_INV_FLATTENING);
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected WGS72SpheroidEarthModel makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/roc/ComputeROCCurve.java b/src/de/lmu/ifi/dbs/elki/math/geodesy/WGS84SpheroidEarthModel.java
index fae03d24..30ba02aa 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/roc/ComputeROCCurve.java
+++ b/src/de/lmu/ifi/dbs/elki/math/geodesy/WGS84SpheroidEarthModel.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.evaluation.roc;
+package de.lmu.ifi.dbs.elki.math.geodesy;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,31 +23,51 @@ package de.lmu.ifi.dbs.elki.evaluation.roc;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.regex.Pattern;
-
-import de.lmu.ifi.dbs.elki.evaluation.outlier.OutlierROCCurve;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.PatternParameter;
/**
- * Compatibility stub. This class has been renamed.
+ * The WGS84 spheroid earth model, without height model (so not a geoid, just a
+ * spheroid!)
+ *
+ * Note that EGM96 uses the same spheroid, but what really makes the difference
+ * is it's geoid expansion.
+ *
+ * Radius: 6378137.0 m
*
- * TODO: remove at 0.6.0 release.
+ * Flattening: 1 / 298.257223563
*
* @author Erich Schubert
*
- * @deprecated Renamed to {@link OutlierROCCurve}.
+ * @apiviz.landmark
*/
-@Deprecated
-public class ComputeROCCurve extends OutlierROCCurve {
+@Alias({ "wgs84", "WGS-84", "WGS84" })
+public class WGS84SpheroidEarthModel extends AbstractEarthModel {
+ /**
+ * Static instance.
+ */
+ public static final WGS84SpheroidEarthModel STATIC = new WGS84SpheroidEarthModel();
+
+ /**
+ * Radius of the WGS84 Ellipsoid in m (a).
+ */
+ public static final double WGS84_RADIUS = 6378137.0; // m
+
+ /**
+ * Inverse flattening 1/f of the WGS84 Ellipsoid.
+ */
+ public static final double WGS84_INV_FLATTENING = 298.257223563;
+
+ /**
+ * Flattening f of the WGS84 Ellipsoid.
+ */
+ public static final double WGS84_FLATTENING = 1 / WGS84_INV_FLATTENING;
+
/**
* Constructor.
- *
- * @param positive_class_name Pattern
*/
- public ComputeROCCurve(Pattern positive_class_name) {
- super(positive_class_name);
+ protected WGS84SpheroidEarthModel() {
+ super(WGS84_RADIUS, WGS84_RADIUS * (1 - WGS84_FLATTENING), WGS84_FLATTENING, WGS84_INV_FLATTENING);
}
/**
@@ -58,23 +78,9 @@ public class ComputeROCCurve extends OutlierROCCurve {
* @apiviz.exclude
*/
public static class Parameterizer extends AbstractParameterizer {
- /**
- * Pattern for positive class.
- */
- protected Pattern positiveClassName = null;
-
- @Override
- protected void makeOptions(Parameterization config) {
- super.makeOptions(config);
- PatternParameter positiveClassNameP = new PatternParameter(OutlierROCCurve.POSITIVE_CLASS_NAME_ID);
- if(config.grab(positiveClassNameP)) {
- positiveClassName = positiveClassNameP.getValue();
- }
- }
-
@Override
- protected ComputeROCCurve makeInstance() {
- return new ComputeROCCurve(positiveClassName);
+ protected WGS84SpheroidEarthModel makeInstance() {
+ return STATIC;
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/math/geometry/AlphaShape.java b/src/de/lmu/ifi/dbs/elki/math/geometry/AlphaShape.java
index 1ab324c3..11f24cb2 100644
--- a/src/de/lmu/ifi/dbs/elki/math/geometry/AlphaShape.java
+++ b/src/de/lmu/ifi/dbs/elki/math/geometry/AlphaShape.java
@@ -12,7 +12,7 @@ import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -64,11 +64,11 @@ public class AlphaShape {
// Compute delaunay triangulation:
delaunay = (new SweepHullDelaunay2D(points)).getDelaunay();
- List<Polygon> polys = new ArrayList<Polygon>();
+ List<Polygon> polys = new ArrayList<>();
// Working data
BitSet used = new BitSet(delaunay.size());
- List<Vector> cur = new ArrayList<Vector>();
+ List<Vector> cur = new ArrayList<>();
for(int i = 0 /* = used.nextClearBit(0) */; i < delaunay.size() && i >= 0; i = used.nextClearBit(i + 1)) {
if(!used.get(i)) {
@@ -82,7 +82,7 @@ public class AlphaShape {
}
if(cur.size() > 0) {
polys.add(new Polygon(cur));
- cur = new ArrayList<Vector>();
+ cur = new ArrayList<>();
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/math/geometry/GrahamScanConvexHull2D.java b/src/de/lmu/ifi/dbs/elki/math/geometry/GrahamScanConvexHull2D.java
index def48c52..c2945fde 100644
--- a/src/de/lmu/ifi/dbs/elki/math/geometry/GrahamScanConvexHull2D.java
+++ b/src/de/lmu/ifi/dbs/elki/math/geometry/GrahamScanConvexHull2D.java
@@ -76,7 +76,7 @@ public class GrahamScanConvexHull2D {
* Constructor.
*/
public GrahamScanConvexHull2D() {
- this.points = new LinkedList<Vector>();
+ this.points = new LinkedList<>();
}
/**
@@ -86,7 +86,7 @@ public class GrahamScanConvexHull2D {
*/
public void add(Vector point) {
if(this.ok) {
- this.points = new LinkedList<Vector>(this.points);
+ this.points = new LinkedList<>(this.points);
this.ok = false;
}
this.points.add(point);
@@ -229,7 +229,7 @@ public class GrahamScanConvexHull2D {
return;
}
Iterator<Vector> iter = points.iterator();
- Stack<Vector> stack = new Stack<Vector>();
+ Stack<Vector> stack = new Stack<>();
// Start with the first two points on the stack
stack.add(iter.next());
stack.add(iter.next());
diff --git a/src/de/lmu/ifi/dbs/elki/math/geometry/PrimsMinimumSpanningTree.java b/src/de/lmu/ifi/dbs/elki/math/geometry/PrimsMinimumSpanningTree.java
index d6675256..de31f92e 100644
--- a/src/de/lmu/ifi/dbs/elki/math/geometry/PrimsMinimumSpanningTree.java
+++ b/src/de/lmu/ifi/dbs/elki/math/geometry/PrimsMinimumSpanningTree.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.geometry;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -42,6 +42,8 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
* </p>
*
* @author Erich Schubert
+ *
+ * @apiviz.uses Adapter
*/
@Reference(authors = "R. C. Prim", title = "Shortest connection networks and some generalizations", booktitle = "Bell System Technical Journal, 36 (1957)")
public class PrimsMinimumSpanningTree {
diff --git a/src/de/lmu/ifi/dbs/elki/math/geometry/SweepHullDelaunay2D.java b/src/de/lmu/ifi/dbs/elki/math/geometry/SweepHullDelaunay2D.java
index afb8db26..ca6d0e5e 100644
--- a/src/de/lmu/ifi/dbs/elki/math/geometry/SweepHullDelaunay2D.java
+++ b/src/de/lmu/ifi/dbs/elki/math/geometry/SweepHullDelaunay2D.java
@@ -21,7 +21,7 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.IntIntPair;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -113,7 +113,7 @@ public class SweepHullDelaunay2D {
throw new UnsupportedOperationException("There is no delaunay triangulation for less than three objects!");
}
int len = points.size() - 1;
- hull = new LinkedList<IntIntPair>();
+ hull = new LinkedList<>();
tris = hullonly ? null : new ArrayList<Triangle>(len);
final Vector seed;
@@ -614,7 +614,7 @@ public class SweepHullDelaunay2D {
}
DoubleMinMax minmaxX = new DoubleMinMax();
DoubleMinMax minmaxY = new DoubleMinMax();
- List<Vector> hullp = new ArrayList<Vector>(hull.size());
+ List<Vector> hullp = new ArrayList<>(hull.size());
for(IntIntPair pair : hull) {
Vector v = points.get(pair.first);
hullp.add(v);
diff --git a/src/de/lmu/ifi/dbs/elki/math/geometry/XYCurve.java b/src/de/lmu/ifi/dbs/elki/math/geometry/XYCurve.java
index 3a53f2a2..36ee7f23 100644
--- a/src/de/lmu/ifi/dbs/elki/math/geometry/XYCurve.java
+++ b/src/de/lmu/ifi/dbs/elki/math/geometry/XYCurve.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.geometry;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -151,7 +151,7 @@ public class XYCurve implements Result, TextWriteable {
public void addAndSimplify(double x, double y) {
// simplify curve when possible:
final int len = data.size();
- if(len >= 4) {
+ if (len >= 4) {
// Look at the previous 2 points
final double l1x = data.get(len - 4);
final double l1y = data.get(len - 3);
@@ -163,16 +163,16 @@ public class XYCurve implements Result, TextWriteable {
final double cdx = x - l2x;
final double cdy = y - l2y;
// X simplification
- if((ldx == 0) && (cdx == 0)) {
+ if ((ldx == 0) && (cdx == 0)) {
data.remove(len - 2, 2);
}
// horizontal simplification
- else if((ldy == 0) && (cdy == 0)) {
+ else if ((ldy == 0) && (cdy == 0)) {
data.remove(len - 2, 2);
}
// diagonal simplification
- else if(ldy > 0 && cdy > 0) {
- if(Math.abs((ldx / ldy) - (cdx / cdy)) < THRESHOLD) {
+ else if (ldy > 0 && cdy > 0) {
+ if (Math.abs((ldx / ldy) - (cdx / cdy)) < THRESHOLD) {
data.remove(len - 2, 2);
}
}
@@ -255,6 +255,21 @@ public class XYCurve implements Result, TextWriteable {
}
/**
+ * Rescale the graph.
+ *
+ * @param sx Scaling factor for X axis
+ * @param sy Scaling factor for Y axis
+ */
+ public void rescale(double sx, double sy) {
+ for (int i = 0; i < data.size(); i += 2) {
+ data.set(i, sx * data.get(i));
+ data.set(i + 1, sy * data.get(i + 1));
+ }
+ maxx *= sx;
+ maxy *= sy;
+ }
+
+ /**
* Size of curve.
*
* @return curve length
@@ -294,7 +309,7 @@ public class XYCurve implements Result, TextWriteable {
out.commentPrint(" ");
out.commentPrint(labely);
out.flush();
- for(int pos = 0; pos < data.size(); pos+=2) {
+ for (int pos = 0; pos < data.size(); pos += 2) {
out.inlinePrint(Double.toString(data.get(pos)));
out.inlinePrint(Double.toString(data.get(pos + 1)));
out.flush();
@@ -306,7 +321,7 @@ public class XYCurve implements Result, TextWriteable {
StringBuilder buf = new StringBuilder();
buf.append("XYCurve[");
buf.append(labelx).append(',').append(labely).append(':');
- for(int pos = 0; pos < data.size(); pos += 2) {
+ for (int pos = 0; pos < data.size(); pos += 2) {
buf.append(' ').append(data.get(pos)).append(',').append(data.get(pos + 1));
}
buf.append(']');
@@ -334,21 +349,21 @@ public class XYCurve implements Result, TextWriteable {
public static double areaUnderCurve(XYCurve curve) {
TDoubleArrayList data = curve.data;
double prevx = data.get(0), prevy = data.get(1);
- if(prevx > curve.minx) {
+ if (prevx > curve.minx) {
throw new UnsupportedOperationException("Curves must be monotone on X for areaUnderCurve to be valid.");
}
double area = 0.0;
- for(int pos = 2; pos < data.size(); pos += 2) {
+ for (int pos = 2; pos < data.size(); pos += 2) {
final double curx = data.get(pos), cury = data.get(pos + 1);
- if(prevx > curx) {
+ if (prevx > curx) {
throw new UnsupportedOperationException("Curves must be monotone on X for areaUnderCurve to be valid.");
}
area += (curx - prevx) * (prevy + cury) * .5; // .5 = mean Y
prevx = curx;
prevy = cury;
}
- if(prevx < curve.maxx) {
- throw new UnsupportedOperationException("Curves must be monotone on X for areaUnderCurve to be valid.");
+ if (prevx < curve.maxx) {
+ throw new UnsupportedOperationException("Curves must be complete on X for areaUnderCurve to be valid.");
}
return area;
}
@@ -415,4 +430,4 @@ public class XYCurve implements Result, TextWriteable {
return pos < data.size();
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/geometry/package-info.java b/src/de/lmu/ifi/dbs/elki/math/geometry/package-info.java
index a7bb6e6e..d94ac05a 100644
--- a/src/de/lmu/ifi/dbs/elki/math/geometry/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/math/geometry/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/AffineTransformation.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/AffineTransformation.java
index 5a4f40fb..a4df5e80 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/AffineTransformation.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/AffineTransformation.java
@@ -2,11 +2,13 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra;
import java.util.Arrays;
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -215,10 +217,11 @@ public class AffineTransformation {
ht[i][i] = 1.0;
}
// insert rotation values
- ht[axis1][axis1] = +Math.cos(angle);
- ht[axis1][axis2] = -Math.sin(angle);
- ht[axis2][axis1] = +Math.sin(angle);
- ht[axis2][axis2] = +Math.cos(angle);
+ double c = Math.cos(angle), s = MathUtil.cosToSin(angle, c);
+ ht[axis1][axis1] = +c;
+ ht[axis1][axis2] = -s;
+ ht[axis2][axis1] = +s;
+ ht[axis2][axis2] = +c;
// Multiply from left
trans = new Matrix(ht).times(trans);
}
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/Centroid.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/Centroid.java
index c46ae89a..7650ecd2 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/Centroid.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/Centroid.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/CholeskyDecomposition.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/CholeskyDecomposition.java
index 8805b18c..6fa455ca 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/CholeskyDecomposition.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/CholeskyDecomposition.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/CovarianceMatrix.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/CovarianceMatrix.java
index 87b7bf1d..69023328 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/CovarianceMatrix.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/CovarianceMatrix.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/EigenPair.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/EigenPair.java
index 132393c6..3b65d99a 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/EigenPair.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/EigenPair.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/EigenvalueDecomposition.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/EigenvalueDecomposition.java
index 54434cdd..f58cd86f 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/EigenvalueDecomposition.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/EigenvalueDecomposition.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/LUDecomposition.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/LUDecomposition.java
index 6e68352a..16fcf21c 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/LUDecomposition.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/LUDecomposition.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/LinearEquationSystem.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/LinearEquationSystem.java
index 53954c08..f32ce410 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/LinearEquationSystem.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/LinearEquationSystem.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/Matrix.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/Matrix.java
index 5a0d1e74..f9ac4c4c 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/Matrix.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/Matrix.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -1474,7 +1474,7 @@ public class Matrix {
int n = v.size(); // Now we've got the number of columns!
double row[] = v.toArray();
- ArrayList<double[]> rowV = new ArrayList<double[]>();
+ ArrayList<double[]> rowV = new ArrayList<>();
rowV.add(row); // Start storing rows instead of columns.
while (tokenizer.nextToken() == StreamTokenizer.TT_WORD) {
// While non-empty lines
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/ProjectedCentroid.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/ProjectedCentroid.java
index 2a24a74d..a0a1e011 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/ProjectedCentroid.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/ProjectedCentroid.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/ProjectionResult.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/ProjectionResult.java
index 9aa1fa7c..901450c3 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/ProjectionResult.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/ProjectionResult.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/QRDecomposition.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/QRDecomposition.java
index 5b52d837..4b30bf5d 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/QRDecomposition.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/QRDecomposition.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/SingularValueDecomposition.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/SingularValueDecomposition.java
index 772e92eb..4a496b5c 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/SingularValueDecomposition.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/SingularValueDecomposition.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -35,7 +35,7 @@ import de.lmu.ifi.dbs.elki.math.MathUtil;
* The singular values, sigma[k] = S[k][k], are ordered so that sigma[0] >=
* sigma[1] >= ... >= sigma[n-1].
* <P>
- * The singular value decompostion always exists, so the constructor will never
+ * The singular value decomposition always exists, so the constructor will never
* fail. The matrix condition number and the effective numerical rank can be
* computed from this decomposition.
*
@@ -542,7 +542,7 @@ public class SingularValueDecomposition {
/**
* Effective numerical matrix rank
*
- * @return Number of nonnegligible singular values.
+ * @return Number of non-negligible singular values.
*/
public int rank() {
double eps = Math.pow(2.0, -52.0);
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/SortedEigenPairs.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/SortedEigenPairs.java
index dcc2f2c0..185ae612 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/SortedEigenPairs.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/SortedEigenPairs.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/SubspaceProjectionResult.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/SubspaceProjectionResult.java
index 3cab3b51..4e03bc78 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/SubspaceProjectionResult.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/SubspaceProjectionResult.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/VMath.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/VMath.java
index 6b6d7090..efac8ff0 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/VMath.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/VMath.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/Vector.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/Vector.java
index b0e1c78e..eca1dbea 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/Vector.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/Vector.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/fitting/FittingFunction.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/fitting/FittingFunction.java
index 9e77d810..48e90c00 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/fitting/FittingFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/fitting/FittingFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.fitting;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/fitting/FittingFunctionResult.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/fitting/FittingFunctionResult.java
index 76f90138..96d5381b 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/fitting/FittingFunctionResult.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/fitting/FittingFunctionResult.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.fitting;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/fitting/GaussianFittingFunction.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/fitting/GaussianFittingFunction.java
index 42badb2f..239d51c6 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/fitting/GaussianFittingFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/fitting/GaussianFittingFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.fitting;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -61,6 +61,11 @@ import de.lmu.ifi.dbs.elki.math.MathUtil;
*/
public class GaussianFittingFunction implements FittingFunction {
/**
+ * Static instance
+ */
+ public static final GaussianFittingFunction STATIC = new GaussianFittingFunction();
+
+ /**
* compute the mixture of Gaussians at the given position
*/
@Override
@@ -77,7 +82,7 @@ public class GaussianFittingFunction implements FittingFunction {
// Numerical Recipes in C: The Art of Scientific Computing
// Due to their license, we cannot use their code, but we have to implement
// the mathematics ourselves. We hope the loss in precision is not too big.
- for(int i = 0; i < params.length; i += 3) {
+ for (int i = 0; i < params.length; i += 3) {
// Standardized Gaussian parameter (centered, scaled by stddev)
double stdpar = (x - params[i]) / params[i + 1];
double e = Math.exp(-.5 * stdpar * stdpar);
@@ -94,4 +99,4 @@ public class GaussianFittingFunction implements FittingFunction {
return new FittingFunctionResult(y, gradients);
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/fitting/LevenbergMarquardtMethod.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/fitting/LevenbergMarquardtMethod.java
index 20200f99..1f2aa913 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/fitting/LevenbergMarquardtMethod.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/fitting/LevenbergMarquardtMethod.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.fitting;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -357,15 +357,17 @@ public class LevenbergMarquardtMethod {
* Iterate until convergence, at most 100 times.
*/
public void run() {
+ int maxruns = this.maxruns;
+ int maxsmall = this.maxsmall;
while(maxruns > 0) {
double oldchi = getChiSq();
iterate();
- maxruns--;
+ --maxruns;
double newchi = getChiSq();
// stop condition: only a small improvement in Chi.
double deltachi = newchi - oldchi;
if(deltachi < 0 && deltachi > -small) {
- maxsmall--;
+ --maxsmall;
if(maxsmall < 0) {
break;
}
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/fitting/package-info.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/fitting/package-info.java
index 2c4143a8..100f36e2 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/fitting/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/fitting/package-info.java
@@ -7,7 +7,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/package-info.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/package-info.java
index 5c55dfd1..4806b2d6 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/package-info.java
@@ -43,7 +43,7 @@ can be found at <a href="http://math.nist.gov/javanumerics/jama/">http://math.ni
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/AbstractCovarianceMatrixBuilder.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/AbstractCovarianceMatrixBuilder.java
index 3e12dc0e..7079f5e1 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/AbstractCovarianceMatrixBuilder.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/AbstractCovarianceMatrixBuilder.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,8 +28,8 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Matrix;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable;
@@ -52,7 +52,7 @@ public abstract class AbstractCovarianceMatrixBuilder<V extends NumberVector<?>>
public abstract Matrix processIds(DBIDs ids, Relation<? extends V> database);
@Override
- public <D extends NumberDistance<D, ?>> Matrix processQueryResults(DistanceDBIDResult<D> results, Relation<? extends V> database, int k) {
+ public <D extends NumberDistance<D, ?>> Matrix processQueryResults(DistanceDBIDList<D> results, Relation<? extends V> database, int k) {
ModifiableDBIDs ids = DBIDUtil.newArray(k);
int have = 0;
for(DBIDIter it = results.iter(); it.valid() && have < k; it.advance(), have++) {
@@ -62,7 +62,7 @@ public abstract class AbstractCovarianceMatrixBuilder<V extends NumberVector<?>>
}
@Override
- public final <D extends NumberDistance<D, ?>> Matrix processQueryResults(DistanceDBIDResult<D> results, Relation<? extends V> database) {
+ public final <D extends NumberDistance<D, ?>> Matrix processQueryResults(DistanceDBIDList<D> results, Relation<? extends V> database) {
return processQueryResults(results, database, results.size());
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/CompositeEigenPairFilter.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/CompositeEigenPairFilter.java
index 6a1c3898..eb725400 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/CompositeEigenPairFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/CompositeEigenPairFilter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -93,7 +93,7 @@ public class CompositeEigenPairFilter implements EigenPairFilter {
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- ObjectListParameter<EigenPairFilter> filtersP = new ObjectListParameter<EigenPairFilter>(EIGENPAIR_FILTER_COMPOSITE_LIST, EigenPairFilter.class);
+ ObjectListParameter<EigenPairFilter> filtersP = new ObjectListParameter<>(EIGENPAIR_FILTER_COMPOSITE_LIST, EigenPairFilter.class);
if(config.grab(filtersP)) {
filters = filtersP.instantiateClasses(config);
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/CovarianceMatrixBuilder.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/CovarianceMatrixBuilder.java
index fce6dbb3..d819c839 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/CovarianceMatrixBuilder.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/CovarianceMatrixBuilder.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,8 +25,8 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Matrix;
@@ -66,7 +66,7 @@ public interface CovarianceMatrixBuilder<V extends NumberVector<?>> {
* @param <D> distance type
* @return Covariance Matrix
*/
- <D extends NumberDistance<D, ?>> Matrix processQueryResults(DistanceDBIDResult<D> results, Relation<? extends V> database, int k);
+ <D extends NumberDistance<D, ?>> Matrix processQueryResults(DistanceDBIDList<D> results, Relation<? extends V> database, int k);
/**
* Compute Covariance Matrix for a QueryResult Collection.
@@ -78,5 +78,5 @@ public interface CovarianceMatrixBuilder<V extends NumberVector<?>> {
* @param <D> distance type
* @return Covariance Matrix
*/
- <D extends NumberDistance<D, ?>> Matrix processQueryResults(DistanceDBIDResult<D> results, Relation<? extends V> database);
+ <D extends NumberDistance<D, ?>> Matrix processQueryResults(DistanceDBIDList<D> results, Relation<? extends V> database);
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/DropEigenPairFilter.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/DropEigenPairFilter.java
index 8791b6a2..22cefa87 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/DropEigenPairFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/DropEigenPairFilter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -74,8 +74,8 @@ public class DropEigenPairFilter implements EigenPairFilter {
@Override
public FilteredEigenPairs filter(SortedEigenPairs eigenPairs) {
// init strong and weak eigenpairs
- List<EigenPair> strongEigenPairs = new ArrayList<EigenPair>();
- List<EigenPair> weakEigenPairs = new ArrayList<EigenPair>();
+ List<EigenPair> strongEigenPairs = new ArrayList<>();
+ List<EigenPair> weakEigenPairs = new ArrayList<>();
// default value is "all strong".
int contrastMaximum = eigenPairs.size() - 1;
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/EigenPairFilter.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/EigenPairFilter.java
index be1eae17..a3f506e1 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/EigenPairFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/EigenPairFilter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/FilteredEigenPairs.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/FilteredEigenPairs.java
index 4ab120fb..6cb6f07c 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/FilteredEigenPairs.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/FilteredEigenPairs.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/FirstNEigenPairFilter.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/FirstNEigenPairFilter.java
index bd6b4400..f613e067 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/FirstNEigenPairFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/FirstNEigenPairFilter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -82,8 +82,8 @@ public class FirstNEigenPairFilter implements EigenPairFilter {
}
// init strong and weak eigenpairs
- List<EigenPair> strongEigenPairs = new ArrayList<EigenPair>();
- List<EigenPair> weakEigenPairs = new ArrayList<EigenPair>();
+ List<EigenPair> strongEigenPairs = new ArrayList<>();
+ List<EigenPair> weakEigenPairs = new ArrayList<>();
// determine strong and weak eigenpairs
for(int i = 0; i < eigenPairs.size(); i++) {
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/LimitEigenPairFilter.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/LimitEigenPairFilter.java
index d7d999b4..b3bd04b3 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/LimitEigenPairFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/LimitEigenPairFilter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -122,8 +122,8 @@ public class LimitEigenPairFilter implements EigenPairFilter {
}
// init strong and weak eigenpairs
- List<EigenPair> strongEigenPairs = new ArrayList<EigenPair>();
- List<EigenPair> weakEigenPairs = new ArrayList<EigenPair>();
+ List<EigenPair> strongEigenPairs = new ArrayList<>();
+ List<EigenPair> weakEigenPairs = new ArrayList<>();
// determine strong and weak eigenpairs
for (int i = 0; i < eigenPairs.size(); i++) {
@@ -184,7 +184,7 @@ public class LimitEigenPairFilter implements EigenPairFilter {
// delta must be >= 0 and <= 1 if it's a relative value
// Since relative or absolute is dependent on the absolute flag this is a
// global constraint!
- List<ParameterConstraint<? super Double>> cons = new ArrayList<ParameterConstraint<? super Double>>();
+ List<ParameterConstraint<? super Double>> cons = new ArrayList<>();
// TODO: Keep the constraint here - applies to non-conditional case as
// well, and is set above.
ParameterConstraint<Number> aboveNull = new GreaterEqualConstraint(0.);
@@ -192,7 +192,7 @@ public class LimitEigenPairFilter implements EigenPairFilter {
ParameterConstraint<Number> underOne = new LessEqualConstraint(1.);
cons.add(underOne);
- GlobalParameterConstraint gpc = new ParameterFlagGlobalConstraint<Double>(deltaP, cons, absoluteF, false);
+ GlobalParameterConstraint gpc = new ParameterFlagGlobalConstraint<>(deltaP, cons, absoluteF, false);
config.checkConstraint(gpc);
}
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/NormalizingEigenPairFilter.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/NormalizingEigenPairFilter.java
index 55c9c438..1d74d307 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/NormalizingEigenPairFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/NormalizingEigenPairFilter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -60,8 +60,8 @@ public class NormalizingEigenPairFilter implements EigenPairFilter {
public FilteredEigenPairs filter(final SortedEigenPairs eigenPairs) {
// initialize strong and weak eigenpairs
// all normalized eigenpairs are regarded as strong
- final List<EigenPair> strongEigenPairs = new ArrayList<EigenPair>();
- final List<EigenPair> weakEigenPairs = new ArrayList<EigenPair>();
+ final List<EigenPair> strongEigenPairs = new ArrayList<>();
+ final List<EigenPair> weakEigenPairs = new ArrayList<>();
for(int i = 0; i < eigenPairs.size(); i++) {
final EigenPair eigenPair = eigenPairs.getEigenPair(i);
normalizeEigenPair(eigenPair);
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/PCAFilteredAutotuningRunner.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/PCAFilteredAutotuningRunner.java
index 73462c2f..4a36036a 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/PCAFilteredAutotuningRunner.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/PCAFilteredAutotuningRunner.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -30,13 +30,13 @@ import java.util.List;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPairList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.ModifiableDistanceDBIDList;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.database.relation.RelationUtil;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultIter;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceDBIDList;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.ModifiableDistanceDBIDResult;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Centroid;
@@ -76,7 +76,7 @@ public class PCAFilteredAutotuningRunner<V extends NumberVector<?>> extends PCAF
// Assume Euclidean distance. In the context of PCA, the neighborhood should
// be L2-spherical to be unbiased.
V center = Centroid.make(database, ids).toVector(database);
- DoubleDistanceDBIDList dres = new DoubleDistanceDBIDList(ids.size());
+ DoubleDistanceDBIDPairList dres = new DoubleDistanceDBIDPairList(ids.size());
for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
final double dist = EuclideanDistanceFunction.STATIC.doubleDistance(center, database.get(iter));
dres.add(dist, iter);
@@ -117,11 +117,11 @@ public class PCAFilteredAutotuningRunner<V extends NumberVector<?>> extends PCAF
}
@Override
- public <D extends NumberDistance<D, ?>> PCAFilteredResult processQueryResult(DistanceDBIDResult<D> results, Relation<? extends V> database) {
+ public <D extends NumberDistance<D, ?>> PCAFilteredResult processQueryResult(DistanceDBIDList<D> results, Relation<? extends V> database) {
assertSortedByDistance(results);
final int dim = RelationUtil.dimensionality(database);
- List<Matrix> best = new LinkedList<Matrix>();
+ List<Matrix> best = new LinkedList<>();
for (int i = 0; i < dim; i++) {
best.add(null);
}
@@ -131,7 +131,7 @@ public class PCAFilteredAutotuningRunner<V extends NumberVector<?>> extends PCAF
}
int[] bestk = new int[dim];
// 'history'
- LinkedList<Cand> prev = new LinkedList<Cand>();
+ LinkedList<Cand> prev = new LinkedList<>();
// TODO: starting parameter shouldn't be hardcoded...
int smooth = 3;
int startk = 4;
@@ -227,11 +227,11 @@ public class PCAFilteredAutotuningRunner<V extends NumberVector<?>> extends PCAF
* @param results Results to process
* @param <D> distance type
*/
- private <D extends NumberDistance<D, ?>> void assertSortedByDistance(DistanceDBIDResult<D> results) {
+ private <D extends NumberDistance<D, ?>> void assertSortedByDistance(DistanceDBIDList<D> results) {
// TODO: sort results instead?
double dist = -1.0;
boolean sorted = true;
- for (DistanceDBIDResultIter<D> it = results.iter(); it.valid(); it.advance()) {
+ for (DistanceDBIDListIter<D> it = results.iter(); it.valid(); it.advance()) {
double qr = it.getDistance().doubleValue();
if (qr < dist) {
sorted = false;
@@ -240,7 +240,7 @@ public class PCAFilteredAutotuningRunner<V extends NumberVector<?>> extends PCAF
}
if (!sorted) {
try {
- ModifiableDistanceDBIDResult.class.cast(results).sort();
+ ModifiableDistanceDBIDList.class.cast(results).sort();
} catch (ClassCastException e) {
LoggingUtil.warning("WARNING: results not sorted by distance!", e);
} catch (UnsupportedOperationException e) {
@@ -259,7 +259,7 @@ public class PCAFilteredAutotuningRunner<V extends NumberVector<?>> extends PCAF
public static class Parameterizer<V extends NumberVector<?>> extends PCAFilteredRunner.Parameterizer<V> {
@Override
protected PCAFilteredAutotuningRunner<V> makeInstance() {
- return new PCAFilteredAutotuningRunner<V>(covarianceMatrixBuilder, eigenPairFilter, big, small);
+ return new PCAFilteredAutotuningRunner<>(covarianceMatrixBuilder, eigenPairFilter, big, small);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/PCAFilteredResult.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/PCAFilteredResult.java
index 3e79e7b6..7303f530 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/PCAFilteredResult.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/PCAFilteredResult.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/PCAFilteredRunner.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/PCAFilteredRunner.java
index 59dca276..2318b72d 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/PCAFilteredRunner.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/PCAFilteredRunner.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,8 +25,8 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.math.linearalgebra.EigenvalueDecomposition;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Matrix;
@@ -46,7 +46,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
* @author Erich Schubert
*
* @apiviz.landmark
- * @apiviz.uses PCAFilteredResult oneway - - «create»
+ * @apiviz.has PCAFilteredResult oneway - - «create»
* @apiviz.composedOf EigenPairFilter
*
* @param <V> Vector class to use
@@ -140,7 +140,7 @@ public class PCAFilteredRunner<V extends NumberVector<?>> extends PCARunner<V> {
* @return PCA result
*/
@Override
- public <D extends NumberDistance<D, ?>> PCAFilteredResult processQueryResult(DistanceDBIDResult<D> results, Relation<? extends V> database) {
+ public <D extends NumberDistance<D, ?>> PCAFilteredResult processQueryResult(DistanceDBIDList<D> results, Relation<? extends V> database) {
return processCovarMatrix(covarianceMatrixBuilder.processQueryResults(results, database));
}
@@ -206,7 +206,7 @@ public class PCAFilteredRunner<V extends NumberVector<?>> extends PCARunner<V> {
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- ObjectParameter<EigenPairFilter> filterP = new ObjectParameter<EigenPairFilter>(PCA_EIGENPAIR_FILTER, EigenPairFilter.class, PercentageEigenPairFilter.class);
+ ObjectParameter<EigenPairFilter> filterP = new ObjectParameter<>(PCA_EIGENPAIR_FILTER, EigenPairFilter.class, PercentageEigenPairFilter.class);
if (config.grab(filterP)) {
eigenPairFilter = filterP.instantiateClass(config);
}
@@ -225,12 +225,12 @@ public class PCAFilteredRunner<V extends NumberVector<?>> extends PCARunner<V> {
}
// global constraint small <--> big
- config.checkConstraint(new LessGlobalConstraint<Double>(smallP, bigP));
+ config.checkConstraint(new LessGlobalConstraint<>(smallP, bigP));
}
@Override
protected PCAFilteredRunner<V> makeInstance() {
- return new PCAFilteredRunner<V>(covarianceMatrixBuilder, eigenPairFilter, big, small);
+ return new PCAFilteredRunner<>(covarianceMatrixBuilder, eigenPairFilter, big, small);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/PCAResult.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/PCAResult.java
index 87518b1d..1634cbf0 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/PCAResult.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/PCAResult.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/PCARunner.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/PCARunner.java
index 4fb9dbdf..91447024 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/PCARunner.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/PCARunner.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,8 +26,8 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.math.linearalgebra.EigenvalueDecomposition;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Matrix;
@@ -113,7 +113,7 @@ public class PCARunner<V extends NumberVector<?>> implements Parameterizable {
* @param <D> distance type
* @return PCA result
*/
- public <D extends NumberDistance<D, ?>> PCAResult processQueryResult(DistanceDBIDResult<D> results, Relation<? extends V> database) {
+ public <D extends NumberDistance<D, ?>> PCAResult processQueryResult(DistanceDBIDList<D> results, Relation<? extends V> database) {
return processCovarMatrix(covarianceMatrixBuilder.processQueryResults(results, database));
}
@@ -174,7 +174,7 @@ public class PCARunner<V extends NumberVector<?>> implements Parameterizable {
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- ObjectParameter<CovarianceMatrixBuilder<V>> covarianceP = new ObjectParameter<CovarianceMatrixBuilder<V>>(PCA_COVARIANCE_MATRIX, CovarianceMatrixBuilder.class, StandardCovarianceMatrixBuilder.class);
+ ObjectParameter<CovarianceMatrixBuilder<V>> covarianceP = new ObjectParameter<>(PCA_COVARIANCE_MATRIX, CovarianceMatrixBuilder.class, StandardCovarianceMatrixBuilder.class);
if(config.grab(covarianceP)) {
covarianceMatrixBuilder = covarianceP.instantiateClass(config);
}
@@ -182,7 +182,7 @@ public class PCARunner<V extends NumberVector<?>> implements Parameterizable {
@Override
protected PCARunner<V> makeInstance() {
- return new PCARunner<V>(covarianceMatrixBuilder);
+ return new PCARunner<>(covarianceMatrixBuilder);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/PercentageEigenPairFilter.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/PercentageEigenPairFilter.java
index 0daa3d94..85e29867 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/PercentageEigenPairFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/PercentageEigenPairFilter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -96,8 +96,8 @@ public class PercentageEigenPairFilter implements EigenPairFilter {
}
// init strong and weak eigenpairs
- List<EigenPair> strongEigenPairs = new ArrayList<EigenPair>();
- List<EigenPair> weakEigenPairs = new ArrayList<EigenPair>();
+ List<EigenPair> strongEigenPairs = new ArrayList<>();
+ List<EigenPair> weakEigenPairs = new ArrayList<>();
// determine sum of eigenvalues
double totalSum = 0;
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/ProgressiveEigenPairFilter.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/ProgressiveEigenPairFilter.java
index 4c359dad..b99de2e1 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/ProgressiveEigenPairFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/ProgressiveEigenPairFilter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -128,8 +128,8 @@ public class ProgressiveEigenPairFilter implements EigenPairFilter {
@Override
public FilteredEigenPairs filter(SortedEigenPairs eigenPairs) {
// init strong and weak eigenpairs
- List<EigenPair> strongEigenPairs = new ArrayList<EigenPair>();
- List<EigenPair> weakEigenPairs = new ArrayList<EigenPair>();
+ List<EigenPair> strongEigenPairs = new ArrayList<>();
+ List<EigenPair> weakEigenPairs = new ArrayList<>();
// determine sum of eigenvalues
double totalSum = 0;
@@ -162,7 +162,7 @@ public class ProgressiveEigenPairFilter implements EigenPairFilter {
if (!found) {
assert (weakEigenPairs.size() == 0);
weakEigenPairs = strongEigenPairs;
- strongEigenPairs = new ArrayList<EigenPair>();
+ strongEigenPairs = new ArrayList<>();
}
for (; i < eigenPairs.size(); i++) {
EigenPair eigenPair = eigenPairs.getEigenPair(i);
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/RANSACCovarianceMatrixBuilder.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/RANSACCovarianceMatrixBuilder.java
index e39820c4..3e9bccf7 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/RANSACCovarianceMatrixBuilder.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/RANSACCovarianceMatrixBuilder.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -184,7 +184,7 @@ public class RANSACCovarianceMatrixBuilder<V extends NumberVector<?>> extends Ab
@Override
protected RANSACCovarianceMatrixBuilder<V> makeInstance() {
- return new RANSACCovarianceMatrixBuilder<V>(iterations, rnd);
+ return new RANSACCovarianceMatrixBuilder<>(iterations, rnd);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/RelativeEigenPairFilter.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/RelativeEigenPairFilter.java
index 38b0fcc2..12da3fdf 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/RelativeEigenPairFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/RelativeEigenPairFilter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -85,8 +85,8 @@ public class RelativeEigenPairFilter implements EigenPairFilter {
@Override
public FilteredEigenPairs filter(SortedEigenPairs eigenPairs) {
// init strong and weak eigenpairs
- List<EigenPair> strongEigenPairs = new ArrayList<EigenPair>();
- List<EigenPair> weakEigenPairs = new ArrayList<EigenPair>();
+ List<EigenPair> strongEigenPairs = new ArrayList<>();
+ List<EigenPair> weakEigenPairs = new ArrayList<>();
// default value is "all strong".
int contrastAtMax = eigenPairs.size() - 1;
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/SignificantEigenPairFilter.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/SignificantEigenPairFilter.java
index c22e9592..73044b59 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/SignificantEigenPairFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/SignificantEigenPairFilter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -79,8 +79,8 @@ public class SignificantEigenPairFilter implements EigenPairFilter {
@Override
public FilteredEigenPairs filter(SortedEigenPairs eigenPairs) {
// init strong and weak eigenpairs
- List<EigenPair> strongEigenPairs = new ArrayList<EigenPair>();
- List<EigenPair> weakEigenPairs = new ArrayList<EigenPair>();
+ List<EigenPair> strongEigenPairs = new ArrayList<>();
+ List<EigenPair> weakEigenPairs = new ArrayList<>();
// default value is "all strong".
int contrastMaximum = eigenPairs.size() - 1;
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/StandardCovarianceMatrixBuilder.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/StandardCovarianceMatrixBuilder.java
index c7104e3b..90dd59c1 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/StandardCovarianceMatrixBuilder.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/StandardCovarianceMatrixBuilder.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/WeakEigenPairFilter.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/WeakEigenPairFilter.java
index 3c60cd0d..66bcba30 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/WeakEigenPairFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/WeakEigenPairFilter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -80,8 +80,8 @@ public class WeakEigenPairFilter implements EigenPairFilter {
@Override
public FilteredEigenPairs filter(SortedEigenPairs eigenPairs) {
// init strong and weak eigenpairs
- List<EigenPair> strongEigenPairs = new ArrayList<EigenPair>();
- List<EigenPair> weakEigenPairs = new ArrayList<EigenPair>();
+ List<EigenPair> strongEigenPairs = new ArrayList<>();
+ List<EigenPair> weakEigenPairs = new ArrayList<>();
// determine sum of eigenvalues
double totalSum = 0;
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/WeightedCovarianceMatrixBuilder.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/WeightedCovarianceMatrixBuilder.java
index 3066a831..236a24bc 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/WeightedCovarianceMatrixBuilder.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/WeightedCovarianceMatrixBuilder.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,14 +26,14 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
-import de.lmu.ifi.dbs.elki.database.ids.DistanceDBIDPair;
-import de.lmu.ifi.dbs.elki.database.ids.DoubleDistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPair;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.database.relation.RelationUtil;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultIter;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Centroid;
@@ -162,7 +162,7 @@ public class WeightedCovarianceMatrixBuilder<V extends NumberVector<?>> extends
* @return Covariance Matrix
*/
@Override
- public <D extends NumberDistance<D, ?>> Matrix processQueryResults(DistanceDBIDResult<D> results, Relation<? extends V> database, int k) {
+ public <D extends NumberDistance<D, ?>> Matrix processQueryResults(DistanceDBIDList<D> results, Relation<? extends V> database, int k) {
final int dim = RelationUtil.dimensionality(database);
final CovarianceMatrix cmat = new CovarianceMatrix(dim);
@@ -176,7 +176,7 @@ public class WeightedCovarianceMatrixBuilder<V extends NumberVector<?>> extends
double stddev = 0.0;
{
int i = 0;
- for (DistanceDBIDResultIter<D> it = results.iter(); it.valid() && i < k; it.advance(), k++) {
+ for (DistanceDBIDListIter<D> it = results.iter(); it.valid() && i < k; it.advance(), k++) {
DistanceDBIDPair<D> res = it.getDistancePair();
final double dist;
if(res instanceof DoubleDistanceDBIDPair) {
@@ -198,7 +198,7 @@ public class WeightedCovarianceMatrixBuilder<V extends NumberVector<?>> extends
// calculate weighted PCA
int i = 0;
- for (DistanceDBIDResultIter<D> it = results.iter(); it.valid() && i < k; it.advance(), k++) {
+ for (DistanceDBIDListIter<D> it = results.iter(); it.valid() && i < k; it.advance(), k++) {
DistanceDBIDPair<D> res = it.getDistancePair();
final double dist;
if(res instanceof DoubleDistanceDBIDPair) {
@@ -231,7 +231,7 @@ public class WeightedCovarianceMatrixBuilder<V extends NumberVector<?>> extends
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- ObjectParameter<WeightFunction> weightfunctionP = new ObjectParameter<WeightFunction>(WEIGHT_ID, WeightFunction.class, ConstantWeight.class);
+ ObjectParameter<WeightFunction> weightfunctionP = new ObjectParameter<>(WEIGHT_ID, WeightFunction.class, ConstantWeight.class);
if(config.grab(weightfunctionP)) {
weightfunction = weightfunctionP.instantiateClass(config);
}
@@ -239,7 +239,7 @@ public class WeightedCovarianceMatrixBuilder<V extends NumberVector<?>> extends
@Override
protected WeightedCovarianceMatrixBuilder<V> makeInstance() {
- return new WeightedCovarianceMatrixBuilder<V>(weightfunction);
+ return new WeightedCovarianceMatrixBuilder<>(weightfunction);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/package-info.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/package-info.java
index f08a016c..2606234b 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/ConstantWeight.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/ConstantWeight.java
index ef089980..2252b512 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/ConstantWeight.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/ConstantWeight.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/ErfcStddevWeight.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/ErfcStddevWeight.java
index 656406c3..645eff29 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/ErfcStddevWeight.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/ErfcStddevWeight.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/ErfcWeight.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/ErfcWeight.java
index 6a8783ed..be7626a3 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/ErfcWeight.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/ErfcWeight.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/ExponentialStddevWeight.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/ExponentialStddevWeight.java
index e6cb9951..7495805d 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/ExponentialStddevWeight.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/ExponentialStddevWeight.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/ExponentialWeight.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/ExponentialWeight.java
index 0792e764..13653ac8 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/ExponentialWeight.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/ExponentialWeight.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/GaussStddevWeight.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/GaussStddevWeight.java
index 9ef589d6..698cd50d 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/GaussStddevWeight.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/GaussStddevWeight.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/GaussWeight.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/GaussWeight.java
index 05c3389f..bdb1d9d9 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/GaussWeight.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/GaussWeight.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/InverseLinearWeight.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/InverseLinearWeight.java
index d5843cf1..e82b51c9 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/InverseLinearWeight.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/InverseLinearWeight.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/InverseProportionalStddevWeight.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/InverseProportionalStddevWeight.java
index 740ec8ca..b8577617 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/InverseProportionalStddevWeight.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/InverseProportionalStddevWeight.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/InverseProportionalWeight.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/InverseProportionalWeight.java
index c4ae9a97..b51c85fa 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/InverseProportionalWeight.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/InverseProportionalWeight.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/LinearWeight.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/LinearWeight.java
index 38318133..68448433 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/LinearWeight.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/LinearWeight.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/QuadraticStddevWeight.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/QuadraticStddevWeight.java
index 372dc016..1279b22d 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/QuadraticStddevWeight.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/QuadraticStddevWeight.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/QuadraticWeight.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/QuadraticWeight.java
index 49cb1aca..b23713a6 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/QuadraticWeight.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/QuadraticWeight.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/WeightFunction.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/WeightFunction.java
index 79c9f8a5..0c9f8ae0 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/WeightFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/WeightFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,8 +23,6 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import de.lmu.ifi.dbs.elki.utilities.InspectionUtilFrequentlyScanned;
-
/**
* WeightFunction interface that allows the use of various distance-based weight
* functions. In addition to the distance parameter, the maximum distance and
@@ -33,7 +31,7 @@ import de.lmu.ifi.dbs.elki.utilities.InspectionUtilFrequentlyScanned;
*
* @author Erich Schubert
*/
-public interface WeightFunction extends InspectionUtilFrequentlyScanned {
+public interface WeightFunction {
/**
* Evaluate weight function with given parameters.
*
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/package-info.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/package-info.java
index 649a8fb7..7869427b 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/randomprojections/AbstractRandomProjectionFamily.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/randomprojections/AbstractRandomProjectionFamily.java
new file mode 100644
index 00000000..292fb002
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/randomprojections/AbstractRandomProjectionFamily.java
@@ -0,0 +1,131 @@
+package de.lmu.ifi.dbs.elki.math.linearalgebra.randomprojections;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.Random;
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.VectorUtil;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.Matrix;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
+import de.lmu.ifi.dbs.elki.utilities.RandomFactory;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.RandomParameter;
+
+/**
+ * Abstract base class for random projection families.
+ *
+ * @author Erich Schubert
+ */
+public abstract class AbstractRandomProjectionFamily implements RandomProjectionFamily {
+ /**
+ * Random generator.
+ */
+ protected Random random;
+
+ /**
+ * Constructor.
+ */
+ public AbstractRandomProjectionFamily(RandomFactory random) {
+ super();
+ this.random = random.getRandom();
+ }
+
+ /**
+ * Parameterization interface (with the shared
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public abstract static class Parameterizer extends AbstractParameterizer {
+ /**
+ * Parameter for the random generator.
+ */
+ public static final OptionID RANDOM_ID = new OptionID("randomproj.random", "Random generator seed.");
+
+ /**
+ * Random generator.
+ */
+ protected RandomFactory random;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ RandomParameter rndP = new RandomParameter(RANDOM_ID);
+ if (config.grab(rndP)) {
+ random = rndP.getValue();
+ }
+ }
+ }
+
+ /**
+ * Class to project using a matrix multiplication.
+ *
+ * @author Erich Schubert
+ */
+ public static class MatrixProjection implements Projection {
+ /**
+ * Projection matrix.
+ */
+ Matrix matrix;
+
+ /**
+ * Projection buffer.
+ */
+ Vector buf;
+
+ /**
+ * Projection buffer values.
+ */
+ double[] vals;
+
+ /**
+ * Constructor.
+ *
+ * @param matrix Projection matrix.
+ */
+ public MatrixProjection(Matrix matrix) {
+ super();
+ this.matrix = matrix;
+ this.buf = new Vector(matrix.getColumnDimensionality());
+ this.vals = buf.getArrayRef();
+ }
+
+ @Override
+ public double[] project(NumberVector<?> in) {
+ for (int d = 0; d < vals.length; d++) {
+ vals[d] = in.doubleValue(d);
+ }
+ return VectorUtil.fastTimes(matrix, buf);
+ }
+
+ @Override
+ public int getOutputDimensionality() {
+ return matrix.getRowDimensionality();
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/randomprojections/AchlioptasRandomProjectionFamily.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/randomprojections/AchlioptasRandomProjectionFamily.java
new file mode 100644
index 00000000..50610cf9
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/randomprojections/AchlioptasRandomProjectionFamily.java
@@ -0,0 +1,124 @@
+package de.lmu.ifi.dbs.elki.math.linearalgebra.randomprojections;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.linearalgebra.Matrix;
+import de.lmu.ifi.dbs.elki.utilities.RandomFactory;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterEqualConstraint;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleParameter;
+
+/**
+ * Random projections as suggested by Dimitris Achlioptas.
+ *
+ * Reference:
+ * <p>
+ * Database-friendly random projections: Johnson-Lindenstrauss with binary coins
+ * <br />
+ * Dimitris Achlioptas<br />
+ * In: Proceedings of the twentieth ACM SIGMOD-SIGACT-SIGART symposium on
+ * Principles of database systems
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@Reference(title = "Database-friendly random projections: Johnson-Lindenstrauss with binary coins", authors = "Dimitris Achlioptas", booktitle = "Proceedings of the twentieth ACM SIGMOD-SIGACT-SIGART symposium on Principles of database systems", url = "http://dx.doi.org/10.1145/375551.375608")
+public class AchlioptasRandomProjectionFamily extends AbstractRandomProjectionFamily {
+ /**
+ * Projection sparsity.
+ */
+ private double sparsity;
+
+ /**
+ * Constructor.
+ *
+ * @param sparsity Projection sparsity
+ * @param random Random number generator.
+ */
+ public AchlioptasRandomProjectionFamily(double sparsity, RandomFactory random) {
+ super(random);
+ this.sparsity = sparsity;
+ }
+
+ @Override
+ public Projection generateProjection(int idim, int odim) {
+ final double pPos = .5 / sparsity;
+ final double pNeg = pPos + pPos; // Threshold
+ double baseValuePart = Math.sqrt(this.sparsity);
+
+ Matrix projectionMatrix = new Matrix(odim, idim);
+ for (int i = 0; i < odim; ++i) {
+ for (int j = 0; j < idim; ++j) {
+ final double r = random.nextDouble();
+ final double value;
+ if (r < pPos) {
+ value = baseValuePart;
+ } else if (r < pNeg) {
+ value = -baseValuePart;
+ } else {
+ value = 0.;
+ }
+
+ projectionMatrix.set(i, j, value);
+ }
+ }
+ return new MatrixProjection(projectionMatrix);
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractRandomProjectionFamily.Parameterizer {
+ /**
+ * Parameter for the projection sparsity.
+ */
+ public static final OptionID SPARSITY_ID = new OptionID("achlioptas.sparsity", "Frequency of zeros in the projection matrix.");
+
+ /**
+ * Projection sparsity
+ */
+ private double sparsity = 3.;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ DoubleParameter sparsP = new DoubleParameter(SPARSITY_ID);
+ sparsP.setDefaultValue(3.);
+ sparsP.addConstraint(new GreaterEqualConstraint(1.));
+ if (config.grab(sparsP)) {
+ sparsity = sparsP.doubleValue();
+ }
+ }
+
+ @Override
+ protected AchlioptasRandomProjectionFamily makeInstance() {
+ return new AchlioptasRandomProjectionFamily(sparsity, random);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/randomprojections/CauchyRandomProjectionFamily.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/randomprojections/CauchyRandomProjectionFamily.java
new file mode 100644
index 00000000..0e7aa7e1
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/randomprojections/CauchyRandomProjectionFamily.java
@@ -0,0 +1,78 @@
+package de.lmu.ifi.dbs.elki.math.linearalgebra.randomprojections;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.linearalgebra.Matrix;
+import de.lmu.ifi.dbs.elki.utilities.RandomFactory;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+
+/**
+ * Random projections using Cauchy distributions (1-stable).
+ *
+ * Reference:
+ * <p>
+ * M. Datar and N. Immorlica and P. Indyk and V. S. Mirrokni<br />
+ * Locality-sensitive hashing scheme based on p-stable distributions.<br />
+ * In Proc. 20th annual symposium on Computational geometry
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@Reference(title = "Locality-sensitive hashing scheme based on p-stable distributions", authors = "M. Datar and N. Immorlica and P. Indyk and V. S. Mirrokni", booktitle = "Proceedings of the 20th annual symposium on Computational geometry", url = "http://dx.doi.org/10.1145/997817.997857")
+public class CauchyRandomProjectionFamily extends AbstractRandomProjectionFamily {
+ /**
+ * Constructor.
+ *
+ * @param random Random number generator.
+ */
+ public CauchyRandomProjectionFamily(RandomFactory random) {
+ super(random);
+ }
+
+ @Override
+ public Projection generateProjection(int idim, int odim) {
+ Matrix projectionMatrix = new Matrix(odim, idim);
+ for (int i = 0; i < odim; ++i) {
+ for (int j = 0; j < idim; ++j) {
+ final double r = random.nextDouble() - .5;
+ final double value = Math.tan(Math.PI * r);
+ projectionMatrix.set(i, j, value);
+ }
+ }
+ return new MatrixProjection(projectionMatrix);
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractRandomProjectionFamily.Parameterizer {
+ @Override
+ protected CauchyRandomProjectionFamily makeInstance() {
+ return new CauchyRandomProjectionFamily(random);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/randomprojections/GaussianRandomProjectionFamily.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/randomprojections/GaussianRandomProjectionFamily.java
new file mode 100644
index 00000000..722c8454
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/randomprojections/GaussianRandomProjectionFamily.java
@@ -0,0 +1,77 @@
+package de.lmu.ifi.dbs.elki.math.linearalgebra.randomprojections;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.linearalgebra.Matrix;
+import de.lmu.ifi.dbs.elki.utilities.RandomFactory;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+
+/**
+ * Random projections using Cauchy distributions (1-stable).
+ *
+ * Reference:
+ * <p>
+ * M. Datar and N. Immorlica and P. Indyk and V. S. Mirrokni<br />
+ * Locality-sensitive hashing scheme based on p-stable distributions.<br />
+ * In Proc. 20th annual symposium on Computational geometry
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@Reference(title = "Locality-sensitive hashing scheme based on p-stable distributions", authors = "M. Datar and N. Immorlica and P. Indyk and V. S. Mirrokni", booktitle = "Proceedings of the 20th annual symposium on Computational geometry", url = "http://dx.doi.org/10.1145/997817.997857")
+public class GaussianRandomProjectionFamily extends AbstractRandomProjectionFamily {
+ /**
+ * Constructor.
+ *
+ * @param random Random number generator.
+ */
+ public GaussianRandomProjectionFamily(RandomFactory random) {
+ super(random);
+ }
+
+ @Override
+ public Projection generateProjection(int idim, int odim) {
+ Matrix projectionMatrix = new Matrix(odim, idim);
+ for (int i = 0; i < odim; ++i) {
+ for (int j = 0; j < idim; ++j) {
+ final double value = random.nextGaussian();
+ projectionMatrix.set(i, j, value);
+ }
+ }
+ return new MatrixProjection(projectionMatrix);
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractRandomProjectionFamily.Parameterizer {
+ @Override
+ protected GaussianRandomProjectionFamily makeInstance() {
+ return new GaussianRandomProjectionFamily(random);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/randomprojections/RandomProjectionFamily.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/randomprojections/RandomProjectionFamily.java
new file mode 100644
index 00000000..aa796383
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/randomprojections/RandomProjectionFamily.java
@@ -0,0 +1,66 @@
+package de.lmu.ifi.dbs.elki.math.linearalgebra.randomprojections;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+
+/**
+ * Interface for random projection families.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has Projection
+ */
+public interface RandomProjectionFamily {
+ /**
+ * Generate a projection matrix for the given dimensionalities.
+ *
+ * @param idim Input Dimensionality
+ * @param odim Output Dimensionality
+ * @return Projection matrix
+ */
+ Projection generateProjection(int idim, int odim);
+
+ /**
+ * Interface for projection instances.
+ *
+ * @author Erich Schubert
+ */
+ static interface Projection {
+ /**
+ * Project a single vector.
+ *
+ * @param in Input vector
+ * @return Projected vector
+ */
+ double[] project(NumberVector<?> in);
+
+ /**
+ * Get the output dimensionality.
+ *
+ * @return Output dimensionality
+ */
+ int getOutputDimensionality();
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/randomprojections/RandomSubsetProjectionFamily.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/randomprojections/RandomSubsetProjectionFamily.java
new file mode 100644
index 00000000..d5192086
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/randomprojections/RandomSubsetProjectionFamily.java
@@ -0,0 +1,167 @@
+package de.lmu.ifi.dbs.elki.math.linearalgebra.randomprojections;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import java.util.Arrays;
+import java.util.Random;
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.utilities.RandomFactory;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+
+/**
+ * Random projection family based on selecting random features.
+ *
+ * The basic idea of using this for data mining should probably be attributed to
+ * L. Breiman, who used it to improve the performance of predictors in an
+ * ensemble.
+ *
+ * Reference:
+ * <p>
+ * L. Breiman<br />
+ * Bagging predictors<br />
+ * Machine learning 24.2
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@Reference(authors = "L. Breiman", title = "Bagging predictors", booktitle = "Machine learning 24.2", url = "http://dx.doi.org/10.1007/BF00058655")
+public class RandomSubsetProjectionFamily extends AbstractRandomProjectionFamily {
+ /**
+ * Constructor.
+ *
+ * @param random Random generator.
+ */
+ public RandomSubsetProjectionFamily(RandomFactory random) {
+ super(random);
+ }
+
+ @Override
+ public Projection generateProjection(int idim, int odim) {
+ int[] dims;
+ if (odim < idim) {
+ dims = Arrays.copyOf(randomPermutation(range(0, idim), random), odim);
+ } else if (odim == idim) {
+ dims = randomPermutation(range(0, idim), random);
+ } else {
+ int mdim = idim;
+ while (mdim < odim) {
+ mdim += idim;
+ }
+ dims = new int[mdim];
+ for (int i = 0; i < mdim; i++) {
+ dims[i] = i % idim;
+ }
+ dims = Arrays.copyOf(randomPermutation(dims, random), odim);
+ }
+ return new SubsetProjection(dims);
+ }
+
+ /**
+ * Initialize an integer value range.
+ *
+ * FIXME: move to shared code.
+ *
+ * @param start Starting value
+ * @param end End value (exclusive)
+ * @return Array of integers start..end, excluding end.
+ */
+ public static int[] range(int start, int end) {
+ int[] out = new int[end - start];
+ for (int i = 0, j = start; j < end; i++, j++) {
+ out[i] = j;
+ }
+ return out;
+ }
+
+ /**
+ * Perform a random permutation of the array, in-place.
+ *
+ * Knuth / Fisher-Yates style shuffle
+ *
+ * FIXME: move to shared code.
+ *
+ * @param existing Existing array
+ * @param random Random generator.
+ * @return Same array.
+ */
+ public static int[] randomPermutation(final int[] out, Random random) {
+ for (int i = out.length - 1; i > 0; i--) {
+ // Swap with random preceeding element.
+ int ri = random.nextInt(i + 1);
+ int tmp = out[ri];
+ out[ri] = out[i];
+ out[i] = tmp;
+ }
+ return out;
+ }
+
+ /**
+ * Random subset projection.
+ *
+ * @author Erich Schubert
+ */
+ public static class SubsetProjection implements Projection {
+ /**
+ * Input dimensions.
+ */
+ private int[] dims;
+
+ /**
+ * Constructor.
+ *
+ * @param dims Data permutation.
+ */
+ public SubsetProjection(int[] dims) {
+ this.dims = dims;
+ }
+
+ @Override
+ public double[] project(NumberVector<?> in) {
+ double[] buf = new double[dims.length];
+ for (int i = 0; i < dims.length; i++) {
+ buf[i] = in.doubleValue(dims[i]);
+ }
+ return buf;
+ }
+
+ @Override
+ public int getOutputDimensionality() {
+ return dims.length;
+ }
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractRandomProjectionFamily.Parameterizer {
+ @Override
+ protected RandomSubsetProjectionFamily makeInstance() {
+ return new RandomSubsetProjectionFamily(random);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/randomprojections/package-info.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/randomprojections/package-info.java
new file mode 100644
index 00000000..3ddd4a5c
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/randomprojections/package-info.java
@@ -0,0 +1,26 @@
+/**
+<p>Random projection families.</p>
+ */
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package de.lmu.ifi.dbs.elki.math.linearalgebra.randomprojections; \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/math/package-info.java b/src/de/lmu/ifi/dbs/elki/math/package-info.java
index e01c3e50..5a5f168f 100644
--- a/src/de/lmu/ifi/dbs/elki/math/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/math/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/scales/LinearScale.java b/src/de/lmu/ifi/dbs/elki/math/scales/LinearScale.java
index 32015853..07191d61 100644
--- a/src/de/lmu/ifi/dbs/elki/math/scales/LinearScale.java
+++ b/src/de/lmu/ifi/dbs/elki/math/scales/LinearScale.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.scales;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/scales/Scales.java b/src/de/lmu/ifi/dbs/elki/math/scales/Scales.java
index 097b6fce..67a4e748 100644
--- a/src/de/lmu/ifi/dbs/elki/math/scales/Scales.java
+++ b/src/de/lmu/ifi/dbs/elki/math/scales/Scales.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.scales;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/scales/package-info.java b/src/de/lmu/ifi/dbs/elki/math/scales/package-info.java
index 1047bb0a..17465485 100644
--- a/src/de/lmu/ifi/dbs/elki/math/scales/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/math/scales/package-info.java
@@ -6,7 +6,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/AbstractSpatialSorter.java b/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/AbstractSpatialSorter.java
index 7c1265dd..347af4a7 100644
--- a/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/AbstractSpatialSorter.java
+++ b/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/AbstractSpatialSorter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.spacefillingcurves;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -43,7 +43,7 @@ public abstract class AbstractSpatialSorter implements SpatialSorter {
@Override
public <T extends SpatialComparable> void sort(List<T> objs) {
double[] mms = computeMinMax(objs);
- sort(objs, 0, objs.size(), mms);
+ sort(objs, 0, objs.size(), mms, null);
}
/**
@@ -125,18 +125,18 @@ public abstract class AbstractSpatialSorter implements SpatialSorter {
// Compute min and max for each dimension:
double[] mm = new double[dim << 1];
{
- for (int d = 0; d < dim; d++) {
- mm[d << 1] = Double.POSITIVE_INFINITY;
- mm[(d << 1) + 1] = Double.NEGATIVE_INFINITY;
+ for (int d = 0, d2 = 0; d < dim; d++, d2 += 2) {
+ mm[d2] = Double.POSITIVE_INFINITY;
+ mm[d2 + 1] = Double.NEGATIVE_INFINITY;
}
for (SpatialComparable obj : objs) {
- for (int d = 0; d < dim; d++) {
- mm[d << 1] = Math.min(mm[d << 1], obj.getMin(d));
- mm[(d << 1) + 1] = Math.max(mm[(d << 1) + 1], obj.getMax(d));
+ for (int d = 0, d2 = 0; d < dim; d++, d2 += 2) {
+ mm[d2] = Math.min(mm[d2], obj.getMin(d));
+ mm[d2 + 1] = Math.max(mm[d2 + 1], obj.getMax(d));
}
}
- for (int d = 0; d < dim; d++) {
- assert (mm[d << 1] <= mm[(d << 1) + 1]);
+ for (int d = 0, d2 = 0; d < dim; d++, d2 += 2) {
+ assert (mm[d2] <= mm[d2 + 1]) : ("Min > Max in dim " + d + ": " + mm[d2] + " " + mm[d2 + 1]);
}
}
return mm;
diff --git a/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/BinarySplitSpatialSorter.java b/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/BinarySplitSpatialSorter.java
index 1ba58511..742fae07 100644
--- a/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/BinarySplitSpatialSorter.java
+++ b/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/BinarySplitSpatialSorter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.spacefillingcurves;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -22,10 +22,10 @@ package de.lmu.ifi.dbs.elki.math.spacefillingcurves;
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.Comparator;
import java.util.List;
import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialSingleMeanComparator;
import de.lmu.ifi.dbs.elki.utilities.datastructures.QuickSelect;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
@@ -58,9 +58,9 @@ public class BinarySplitSpatialSorter extends AbstractSpatialSorter {
}
@Override
- public <T extends SpatialComparable> void sort(List<T> objs, int start, int end, double[] minmax) {
- final int dims = objs.get(0).getDimensionality();
- binarySplitSort(objs, start, end, 1, dims, new DimC());
+ public <T extends SpatialComparable> void sort(List<T> objs, int start, int end, double[] minmax, int[] dims) {
+ final int numdim = (dims != null) ? dims.length : (minmax.length >>> 1);
+ binarySplitSort(objs, start, end, 0, numdim, dims, new SpatialSingleMeanComparator(0));
}
/**
@@ -70,47 +70,24 @@ public class BinarySplitSpatialSorter extends AbstractSpatialSorter {
* @param objs List of objects
* @param start Interval start
* @param end Interval end (exclusive)
- * @param curdim Current dimension
- * @param dims Number of dimensions
+ * @param depth Recursion depth
+ * @param numdim Number of dimensions
+ * @param dims Dimension indexes to sort by.
* @param comp Comparator to use
* @param <T> Object type
*/
- private <T extends SpatialComparable> void binarySplitSort(List<T> objs, final int start, final int end, int curdim, final int dims, DimC comp) {
+ private <T extends SpatialComparable> void binarySplitSort(List<T> objs, final int start, final int end, int depth, final int numdim, int[] dims, SpatialSingleMeanComparator comp) {
final int mid = start + ((end - start) >>> 1);
// Make invariant
- comp.dim = curdim;
+ comp.setDimension(dims != null ? dims[depth] : depth);
QuickSelect.quickSelect(objs, comp, start, end, mid);
// Recurse
- final int nextdim = (curdim + 1) % dims;
- if(start < mid - 1) {
- binarySplitSort(objs, start, mid, nextdim, dims, comp);
+ final int nextdim = (depth + 1) % numdim;
+ if (start < mid - 1) {
+ binarySplitSort(objs, start, mid, nextdim, numdim, dims, comp);
}
- if(mid + 2 < end) {
- binarySplitSort(objs, mid + 1, end, nextdim, dims, comp);
+ if (mid + 2 < end) {
+ binarySplitSort(objs, mid + 1, end, nextdim, numdim, dims, comp);
}
}
-
- /**
- * Comparator that uses only a particular dimension.
- *
- * This comparator is meant to be reused, and the dimension to be changed, to
- * reduce the number of objects allocated.
- *
- * @author Erich Schubert
- *
- * @apiviz.exclude
- */
- private static class DimC implements Comparator<SpatialComparable> {
- /**
- * Dimension.
- */
- public int dim = -1;
-
- @Override
- public int compare(SpatialComparable o1, SpatialComparable o2) {
- double m1 = o1.getMax(dim) + o1.getMin(dim);
- double m2 = o2.getMax(dim) + o2.getMin(dim);
- return Double.compare(m1, m2);
- }
- }
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/HilbertSpatialSorter.java b/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/HilbertSpatialSorter.java
index 317e47c1..231e8637 100644
--- a/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/HilbertSpatialSorter.java
+++ b/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/HilbertSpatialSorter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.spacefillingcurves;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -57,19 +57,20 @@ public class HilbertSpatialSorter extends AbstractSpatialSorter {
}
@Override
- public <T extends SpatialComparable> void sort(List<T> objs, int start, int end, double[] minmax) {
- final int dim = minmax.length >> 1;
- List<HilbertRef<T>> tmp = new ArrayList<HilbertRef<T>>(end - start);
+ public <T extends SpatialComparable> void sort(List<T> objs, int start, int end, double[] minmax, int[] dims) {
+ final int dim = (dims != null) ? dims.length : (minmax.length >> 1);
+ List<HilbertRef<T>> tmp = new ArrayList<>(end - start);
int[] buf = new int[dim];
for (int i = start; i < end; i++) {
T v = objs.get(i);
// Convert into integers
- for (int d = 0, d2 = 0; d < dim; d++, d2 += 2) {
- double val = (v.getMin(d) + v.getMax(d)) * .5;
- val = Integer.MAX_VALUE * ((val - minmax[d2]) / (minmax[d2 + 1] - minmax[d2]));
+ for (int d = 0; d < dim; d++) {
+ final int ed = (dims != null) ? dims[d] : d, ed2 = ed << 1;
+ double val = (v.getMin(ed) + v.getMax(ed)) * .5;
+ val = Integer.MAX_VALUE * ((val - minmax[ed2]) / (minmax[ed2 + 1] - minmax[ed2]));
buf[d] = (int) val;
}
- tmp.add(new HilbertRef<T>(v, coordinatesToHilbert(buf, Integer.SIZE - 1, 1)));
+ tmp.add(new HilbertRef<>(v, coordinatesToHilbert(buf, Integer.SIZE - 1, 1)));
}
// Sort and copy back
Collections.sort(tmp);
diff --git a/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/PeanoSpatialSorter.java b/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/PeanoSpatialSorter.java
index 865197ae..3519e75d 100644
--- a/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/PeanoSpatialSorter.java
+++ b/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/PeanoSpatialSorter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.spacefillingcurves;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -79,8 +79,8 @@ public class PeanoSpatialSorter extends AbstractSpatialSorter {
}
@Override
- public <T extends SpatialComparable> void sort(List<T> objs, int start, int end, double[] minmax) {
- peanoSort(objs, start, end, minmax, 0, new BitSet(), false);
+ public <T extends SpatialComparable> void sort(List<T> objs, int start, int end, double[] minmax, int[] dims) {
+ peanoSort(objs, start, end, minmax, dims, 0, new BitSet(), false);
}
/**
@@ -90,21 +90,24 @@ public class PeanoSpatialSorter extends AbstractSpatialSorter {
* @param start Start index
* @param end End
* @param mms Minmax values
- * @param dim Dimension
+ * @param dims Dimensions index
+ * @param depth Dimension
* @param bits Bit set for inversions
* @param desc Current ordering
*/
- protected <T extends SpatialComparable> void peanoSort(List<T> objs, int start, int end, double[] mms, int dim, BitSet bits, boolean desc) {
- final int dims = mms.length >> 1;
+ protected <T extends SpatialComparable> void peanoSort(List<T> objs, int start, int end, double[] mms, int[] dims, int depth, BitSet bits, boolean desc) {
+ final int numdim = (dims != null) ? dims.length : (mms.length >> 1);
+ final int edim = (dims != null) ? dims[depth] : depth;
// Find the splitting points.
- final double min = mms[2 * dim], max = mms[2 * dim + 1];
+ final double min = mms[2 * edim], max = mms[2 * edim + 1];
final double tfirst = (min + min + max) / 3.;
final double tsecond = (min + max + max) / 3.;
// Safeguard against duplicate points:
if(max - tsecond < 1E-10 || tsecond - tfirst < 1E-10 || tfirst - min < 1E-10) {
boolean ok = false;
- for(int d = 0; d < mms.length; d += 2) {
- if(mms[d + 1] - mms[d] >= 1E-10) {
+ for (int d = 0; d < numdim; d++) {
+ int d2 = ((dims != null) ? dims[d] : d) << 1;
+ if (mms[d2 + 1] - mms[d2] >= 1E-10) {
ok = true;
break;
}
@@ -113,38 +116,38 @@ public class PeanoSpatialSorter extends AbstractSpatialSorter {
return;
}
}
- final boolean inv = bits.get(dim) ^ desc;
+ final boolean inv = bits.get(edim) ^ desc;
// Split the data set into three parts
int fsplit, ssplit;
if(!inv) {
- fsplit = pivotizeList1D(objs, start, end, dim, tfirst, false);
- ssplit = (fsplit < end - 1) ? pivotizeList1D(objs, fsplit, end, dim, tsecond, false) : fsplit;
+ fsplit = pivotizeList1D(objs, start, end, edim, tfirst, false);
+ ssplit = (fsplit < end - 1) ? pivotizeList1D(objs, fsplit, end, edim, tsecond, false) : fsplit;
}
else {
- fsplit = pivotizeList1D(objs, start, end, dim, tsecond, true);
- ssplit = (fsplit < end - 1) ? pivotizeList1D(objs, fsplit, end, dim, tfirst, true) : fsplit;
+ fsplit = pivotizeList1D(objs, start, end, edim, tsecond, true);
+ ssplit = (fsplit < end - 1) ? pivotizeList1D(objs, fsplit, end, edim, tfirst, true) : fsplit;
}
- int nextdim = (dim + 1) % dims;
+ int nextdim = (depth + 1) % numdim;
// Do we need to update the min/max values?
if(start < fsplit - 1) {
- mms[2 * dim] = !inv ? min : tsecond;
- mms[2 * dim + 1] = !inv ? tfirst : max;
- peanoSort(objs, start, fsplit, mms, nextdim, bits, desc);
+ mms[2 * edim] = !inv ? min : tsecond;
+ mms[2 * edim + 1] = !inv ? tfirst : max;
+ peanoSort(objs, start, fsplit, mms, dims, nextdim, bits, desc);
}
if(fsplit < ssplit - 1) {
- bits.flip(dim); // set (all but dim: we also flip "desc")
- mms[2 * dim] = tfirst;
- mms[2 * dim + 1] = tsecond;
- peanoSort(objs, fsplit, ssplit, mms, nextdim, bits, !desc);
- bits.flip(dim);
+ bits.flip(edim); // set (all but dim: we also flip "desc")
+ mms[2 * edim] = tfirst;
+ mms[2 * edim + 1] = tsecond;
+ peanoSort(objs, fsplit, ssplit, mms, dims, nextdim, bits, !desc);
+ bits.flip(edim);
}
if(ssplit < end - 1) {
- mms[2 * dim] = !inv ? tsecond : min;
- mms[2 * dim + 1] = !inv ? max : tfirst;
- peanoSort(objs, ssplit, end, mms, nextdim, bits, desc);
+ mms[2 * edim] = !inv ? tsecond : min;
+ mms[2 * edim + 1] = !inv ? max : tfirst;
+ peanoSort(objs, ssplit, end, mms, dims, nextdim, bits, desc);
}
// Restore ranges
- mms[2 * dim] = min;
- mms[2 * dim + 1] = max;
+ mms[2 * edim] = min;
+ mms[2 * edim + 1] = max;
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/SpatialSorter.java b/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/SpatialSorter.java
index fe23a854..30e6e019 100644
--- a/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/SpatialSorter.java
+++ b/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/SpatialSorter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.spacefillingcurves;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -49,6 +49,7 @@ public interface SpatialSorter {
* @param start First index to sort (e.g. 0)
* @param end End of range (e.g. <code>site()</code>)
* @param minmax Array with dim pairs of (min, max) of value ranges
+ * @param dims Dimensions to sort by, for indexing vectors <em>and</em> {@code minmax}.
*/
- <T extends SpatialComparable> void sort(List<T> objs, int start, int end, double[] minmax);
+ <T extends SpatialComparable> void sort(List<T> objs, int start, int end, double[] minmax, int[] dims);
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/ZCurveSpatialSorter.java b/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/ZCurveSpatialSorter.java
index c5a91699..d30f88d6 100644
--- a/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/ZCurveSpatialSorter.java
+++ b/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/ZCurveSpatialSorter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.spacefillingcurves;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -37,8 +37,8 @@ public class ZCurveSpatialSorter extends AbstractSpatialSorter {
private static final double STOPVAL = 1E-10;
@Override
- public <T extends SpatialComparable> void sort(List<T> objs, int start, int end, double[] minmax) {
- zSort(objs, start, end, minmax, 0);
+ public <T extends SpatialComparable> void sort(List<T> objs, int start, int end, double[] minmax, int[] dims) {
+ zSort(objs, start, end, minmax, dims, 0);
}
/**
@@ -48,44 +48,44 @@ public class ZCurveSpatialSorter extends AbstractSpatialSorter {
* @param start Start
* @param end End
* @param mms Min-Max value ranges
- * @param dim Current dimension
+ * @param dims Dimensions to process
+ * @param depth Current dimension
*/
- protected <T extends SpatialComparable> void zSort(List<T> objs, int start, int end, double[] mms, int dim) {
+ protected <T extends SpatialComparable> void zSort(List<T> objs, int start, int end, double[] mms, int[] dims, int depth) {
+ final int numdim = (dims != null) ? dims.length : (mms.length >> 1);
+ final int edim = (dims != null) ? dims[depth] : depth;
// Find the splitting points.
- final double min = mms[2 * dim], max = mms[2 * dim + 1];
+ final double min = mms[2 * edim], max = mms[2 * edim + 1];
double spos = (min + max) / 2.;
// Safeguard against duplicate points:
- if(max - spos < STOPVAL || spos - min < STOPVAL) {
+ if (max - spos < STOPVAL || spos - min < STOPVAL) {
boolean ok = false;
- for(int d = 0; d < mms.length; d += 2) {
- if(mms[d + 1] - mms[d] >= STOPVAL) {
- // LoggingUtil.warning("No: " + (mms[d + 1] - mms[d]));
+ for (int d = 0; d < numdim; d++) {
+ int d2 = ((dims != null) ? dims[d] : d) << 1;
+ if (mms[d2 + 1] - mms[d2] >= STOPVAL) {
ok = true;
break;
}
}
- if(!ok) {
+ if (!ok) {
return;
}
}
- int split = pivotizeList1D(objs, start, end, dim, spos, false);
+ int split = pivotizeList1D(objs, start, end, edim, spos, false);
assert (start <= split && split <= end);
- int nextdim = (dim + 1) % objs.get(0).getDimensionality();
- // LoggingUtil.warning("dim: " + dim + " min: " + min + " split: " + spos +
- // " max:" + max + " " + start + " < " + split + " < " + end);
- if(start < split - 1) {
- mms[2 * dim] = min;
- mms[2 * dim + 1] = spos;
- zSort(objs, start, split, mms, nextdim);
+ int nextdim = (depth + 1) % numdim;
+ if (start < split - 1) {
+ mms[2 * edim] = min;
+ mms[2 * edim + 1] = spos;
+ zSort(objs, start, split, mms, dims, nextdim);
}
- if(split < end - 1) {
- mms[2 * dim] = spos;
- mms[2 * dim + 1] = max;
- zSort(objs, split, end, mms, nextdim);
+ if (split < end - 1) {
+ mms[2 * edim] = spos;
+ mms[2 * edim + 1] = max;
+ zSort(objs, split, end, mms, dims, nextdim);
}
// Restore ranges
- mms[2 * dim] = min;
- mms[2 * dim + 1] = max;
- // FIXME: implement completely and test.
+ mms[2 * edim] = min;
+ mms[2 * edim + 1] = max;
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/ZCurveTransformer.java b/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/ZCurveTransformer.java
index 26137cb3..7474a00d 100644
--- a/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/ZCurveTransformer.java
+++ b/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/ZCurveTransformer.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.spacefillingcurves;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/package-info.java b/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/package-info.java
index 9fb9494a..a658d747 100644
--- a/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/KernelDensityEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/KernelDensityEstimator.java
index d7ffefb8..72c50869 100644
--- a/src/de/lmu/ifi/dbs/elki/math/statistics/KernelDensityEstimator.java
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/KernelDensityEstimator.java
@@ -1,10 +1,14 @@
package de.lmu.ifi.dbs.elki.math.statistics;
+import java.util.Arrays;
+
+import de.lmu.ifi.dbs.elki.math.statistics.kernelfunctions.KernelDensityFunction;
+
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,12 +27,10 @@ package de.lmu.ifi.dbs.elki.math.statistics;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
/**
* Estimate density given an array of points.
*
- * Estimates a density using a kernel density estimator. Multiple common Kernel
- * functions are supported.
+ * Estimates a density using a variable width kernel density estimation.
*
* @author Erich Schubert
*
@@ -48,39 +50,51 @@ public class KernelDensityEstimator {
/**
* Initialize and execute kernel density estimation.
*
- * @param data data to use
+ * @param data data to use (must be sorted!)
* @param min minimum value
* @param max maximum value
* @param kernel Kernel function to use
- * @param windows window size
+ * @param window window size
+ * @param epsilon Precision threshold
*/
- public KernelDensityEstimator(double[] data, double min, double max, KernelDensityFunction kernel, int windows) {
- process(data, min, max, kernel, windows);
+ public KernelDensityEstimator(double[] data, double min, double max, KernelDensityFunction kernel, int window, double epsilon) {
+ process(data, min, max, kernel, window, epsilon);
}
-
+
/**
* Process a new array
*
- * @param data data to use
+ * @param data data to use (must be sorted!)
* @param min minimum value
* @param max maximum value
* @param kernel Kernel function to use
- * @param windows window size
+ * @param window window size
+ * @param epsilon Precision threshold
*/
- private void process(double[] data, double min, double max, KernelDensityFunction kernel, int windows) {
+ private void process(double[] data, double min, double max, KernelDensityFunction kernel, int window, double epsilon) {
dens = new double[data.length];
var = new double[data.length];
- double halfwidth = ((max - min) / windows) * .5;
+ // This is the desired bandwidth of the kernel.
+ double halfwidth = ((max - min) / window) * .5;
- // collect data points
- for(int current = 0; current < data.length; current++) {
+ for (int current = 0; current < data.length; current++) {
double value = 0.0;
- // TODO: is there any way we can skip through some of the data (at least if its sorted?)
- // Since we know that all kKernels return 0 outside of [-1:1]?
- for(int i = 0; i < data.length; i++) {
+ for (int i = current; i >= 0; i--) {
double delta = Math.abs(data[i] - data[current]) / halfwidth;
- value += kernel.density(delta);
+ final double contrib = kernel.density(delta);
+ value += contrib;
+ if (contrib < epsilon) {
+ break;
+ }
+ }
+ for (int i = current + 1; i < data.length; i++) {
+ double delta = Math.abs(data[i] - data[current]) / halfwidth;
+ final double contrib = kernel.density(delta);
+ value += contrib;
+ if (contrib < epsilon) {
+ break;
+ }
}
double realwidth = (Math.min(data[current] + halfwidth, max) - Math.max(min, data[current] - halfwidth));
double weight = realwidth / (2 * halfwidth);
@@ -94,22 +108,27 @@ public class KernelDensityEstimator {
*
* @param data data to process
* @param kernel Kernel function to use.
+ * @param epsilon Precision threshold
*/
- public KernelDensityEstimator(double[] data, KernelDensityFunction kernel) {
- double min = Double.MAX_VALUE;
- double max = Double.MIN_VALUE;
- for(double d : data) {
- if(d < min) {
- min = d;
- }
- if(d > max) {
- max = d;
+ public KernelDensityEstimator(double[] data, KernelDensityFunction kernel, double epsilon) {
+ boolean needsort = false;
+ for (int i = 1; i < data.length; i++) {
+ if (data[i - 1] > data[i]) {
+ needsort = true;
+ break;
}
}
- // Heuristics.
+ // Duplicate and sort when needed:
+ if (needsort) {
+ data = data.clone();
+ Arrays.sort(data);
+ }
+ final double min = data[0];
+ final double max = data[data.length - 1];
+ // Heuristic for choosing the window size.
int windows = 1 + (int) (Math.log(data.length));
- process(data, min, max, kernel, windows);
+ process(data, min, max, kernel, windows, epsilon);
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/LinearRegression.java b/src/de/lmu/ifi/dbs/elki/math/statistics/LinearRegression.java
index 231b2071..00999245 100644
--- a/src/de/lmu/ifi/dbs/elki/math/statistics/LinearRegression.java
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/LinearRegression.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.statistics;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/MultipleLinearRegression.java b/src/de/lmu/ifi/dbs/elki/math/statistics/MultipleLinearRegression.java
index 79c84701..0d37ca67 100644
--- a/src/de/lmu/ifi/dbs/elki/math/statistics/MultipleLinearRegression.java
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/MultipleLinearRegression.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.statistics;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/PolynomialRegression.java b/src/de/lmu/ifi/dbs/elki/math/statistics/PolynomialRegression.java
index b1bfe31b..12dfe28c 100644
--- a/src/de/lmu/ifi/dbs/elki/math/statistics/PolynomialRegression.java
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/PolynomialRegression.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.statistics;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/ProbabilityWeightedMoments.java b/src/de/lmu/ifi/dbs/elki/math/statistics/ProbabilityWeightedMoments.java
new file mode 100644
index 00000000..c783f5f1
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/ProbabilityWeightedMoments.java
@@ -0,0 +1,176 @@
+package de.lmu.ifi.dbs.elki.math.statistics;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+
+/**
+ * Estimate the L-Moments of a sample.
+ *
+ * Reference:
+ * <p>
+ * J. R. M. Hosking, J. R. Wallis, and E. F. Wood<br />
+ * Estimation of the generalized extreme-value distribution by the method of
+ * probability-weighted moments.<br />
+ * Technometrics 27.3
+ * </p>
+ *
+ * Also based on:
+ * <p>
+ * J. R. M. Hosking<br />
+ * Fortran routines for use with the method of L-moments Version 3.03<br />
+ * IBM Research.
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@Reference(authors = "J.R.M. Hosking, J. R. Wallis, and E. F. Wood", title = "Estimation of the generalized extreme-value distribution by the method of probability-weighted moments.", booktitle = "Technometrics 27.3", url = "http://dx.doi.org/10.1080/00401706.1985.10488049")
+public class ProbabilityWeightedMoments {
+ /**
+ * Compute the alpha_r factors using the method of probability-weighted
+ * moments.
+ *
+ * @param sorted <b>Presorted</b> data array.
+ * @param nmom Number of moments to compute
+ * @return Alpha moments (0-indexed)
+ */
+ public static <A> double[] alphaPWM(A data, NumberArrayAdapter<?, A> adapter, final int nmom) {
+ final int n = adapter.size(data);
+ final double[] xmom = new double[nmom];
+ double weight = 1. / n;
+ for (int i = 0; i < n; i++) {
+ final double val = adapter.getDouble(data, i);
+ xmom[0] += weight * val;
+ for (int j = 1; j < nmom; j++) {
+ weight *= (n - i - j + 1) / (n - j + 1);
+ xmom[j] += weight * val;
+ }
+ }
+ return xmom;
+ }
+
+ /**
+ * Compute the beta_r factors using the method of probability-weighted
+ * moments.
+ *
+ * @param sorted <b>Presorted</b> data array.
+ * @param nmom Number of moments to compute
+ * @return Beta moments (0-indexed)
+ */
+ public static <A> double[] betaPWM(A data, NumberArrayAdapter<?, A> adapter, final int nmom) {
+ final int n = adapter.size(data);
+ final double[] xmom = new double[nmom];
+ double weight = 1. / n;
+ for (int i = 0; i < n; i++) {
+ final double val = adapter.getDouble(data, i);
+ xmom[0] += weight * val;
+ for (int j = 1; j < nmom; j++) {
+ weight *= (i - j + 1) / (n - j + 1);
+ xmom[j] += weight * val;
+ }
+ }
+ return xmom;
+ }
+
+ /**
+ * Compute the alpha_r and beta_r factors in parallel using the method of
+ * probability-weighted moments. Usually cheaper than computing them
+ * separately.
+ *
+ * @param sorted <b>Presorted</b> data array.
+ * @param nmom Number of moments to compute
+ * @return Alpha and Beta moments (0-indexed, interleaved)
+ */
+ public static <A> double[] alphaBetaPWM(A data, NumberArrayAdapter<?, A> adapter, final int nmom) {
+ final int n = adapter.size(data);
+ final double[] xmom = new double[nmom << 1];
+ double aweight = 1. / n, bweight = aweight;
+ for (int i = 0; i < n; i++) {
+ final double val = adapter.getDouble(data, i);
+ xmom[0] += aweight * val;
+ xmom[1] += bweight * val;
+ for (int j = 1, k = 2; j < nmom; j++, k += 2) {
+ aweight *= (n - i - j + 1) / (n - j + 1);
+ bweight *= (i - j + 1) / (n - j + 1);
+ xmom[k + 1] += aweight * val;
+ xmom[k + 1] += bweight * val;
+ }
+ }
+ return xmom;
+ }
+
+ /**
+ * Compute the sample L-Moments using probability weighted moments.
+ *
+ * @param sorted <b>Presorted</b> data array.
+ * @param nmom Number of moments to compute
+ * @return Array containing Lambda1, Lambda2, Tau3 ... TauN
+ */
+ public static <A> double[] samLMR(A sorted, NumberArrayAdapter<?, A> adapter, final int nmom) {
+ final int n = adapter.size(sorted);
+ if (nmom >= n) {
+ throw new ArithmeticException("Can't compute higher order moments for just" + n + " observations.");
+ }
+ final double[] sum = new double[nmom];
+ // Estimate probability weighted moments (unbiased)
+ for (int i = 0; i < n; i++) {
+ double term = adapter.getDouble(sorted, i);
+ // Robustness: skip bad values
+ if (Double.isInfinite(term) || Double.isNaN(term)) {
+ continue;
+ }
+ sum[0] += term;
+ for (int j = 1, z = i; j < nmom; j++, z--) {
+ term *= z;
+ sum[j] += term;
+ }
+ }
+ // Normalize by "n choose (j + 1)"
+ sum[0] /= n;
+ double z = n;
+ for (int j = 1; j < nmom; j++) {
+ z *= n - j;
+ sum[j] /= z;
+ }
+ for (int k = nmom - 1; k >= 1; --k) {
+ double p = ((k & 1) == 0) ? +1 : -1;
+ double temp = p * sum[0];
+ for (int i = 0; i < k; i++) {
+ double ai = i + 1.;
+ p *= -(k + ai) * (k - i) / (ai * ai);
+ temp += p * sum[i + 1];
+ }
+ sum[k] = temp;
+ }
+ if (nmom > 2 && !(sum[1] > 0)) {
+ throw new ArithmeticException("Can't compute higher order moments for constant data. Sum: " + sum[1]);
+ }
+ // Map lambda3...lambdaN to tau3...tauN
+ for (int i = 2; i < nmom; i++) {
+ sum[i] /= sum[1];
+ }
+ return sum;
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/BetaDistribution.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/BetaDistribution.java
index 1efe19dd..c48583ea 100644
--- a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/BetaDistribution.java
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/BetaDistribution.java
@@ -34,7 +34,7 @@ import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
* @author Jan Brusis
* @author Erich Schubert
*/
-public class BetaDistribution implements DistributionWithRandom {
+public class BetaDistribution implements Distribution {
/**
* Numerical precision to use
*/
@@ -94,7 +94,7 @@ public class BetaDistribution implements DistributionWithRandom {
*/
public BetaDistribution(double a, double b, Random random) {
super();
- if(a <= 0.0 || b <= 0.0) {
+ if (a <= 0.0 || b <= 0.0) {
throw new IllegalArgumentException("Invalid parameters for Beta distribution.");
}
@@ -106,23 +106,23 @@ public class BetaDistribution implements DistributionWithRandom {
@Override
public double pdf(double val) {
- if(val < 0. || val > 1.) {
+ if (val < 0. || val > 1.) {
return 0.;
}
- if(val == 0.) {
- if(alpha > 1.) {
+ if (val == 0.) {
+ if (alpha > 1.) {
return 0.;
}
- if(alpha < 1.) {
+ if (alpha < 1.) {
return Double.POSITIVE_INFINITY;
}
return beta;
}
- if(val == 1.) {
- if(beta > 1.) {
+ if (val == 1.) {
+ if (beta > 1.) {
return 0.;
}
- if(beta < 1.) {
+ if (beta < 1.) {
return Double.POSITIVE_INFINITY;
}
return alpha;
@@ -132,23 +132,22 @@ public class BetaDistribution implements DistributionWithRandom {
@Override
public double cdf(double x) {
- if(alpha <= 0.0 || beta <= 0.0 || Double.isNaN(alpha) || Double.isNaN(beta) || Double.isNaN(x)) {
+ if (alpha <= 0.0 || beta <= 0.0 || Double.isNaN(alpha) || Double.isNaN(beta) || Double.isNaN(x)) {
return Double.NaN;
}
- if(x <= 0.0) {
+ if (x <= 0.0) {
return 0.0;
}
- if(x >= 1.0) {
+ if (x >= 1.0) {
return 1.0;
}
- if(alpha > SWITCH && beta > SWITCH) {
+ if (alpha > SWITCH && beta > SWITCH) {
return regularizedIncBetaQuadrature(alpha, beta, x);
}
double bt = Math.exp(-logbab + alpha * Math.log(x) + beta * Math.log1p(-x));
- if(x < (alpha + 1.0) / (alpha + beta + 2.0)) {
+ if (x < (alpha + 1.0) / (alpha + beta + 2.0)) {
return bt * regularizedIncBetaCF(alpha, beta, x) / alpha;
- }
- else {
+ } else {
return 1.0 - bt * regularizedIncBetaCF(beta, alpha, 1.0 - x) / beta;
}
}
@@ -156,20 +155,19 @@ public class BetaDistribution implements DistributionWithRandom {
@Override
public double quantile(double x) {
// Valid parameters
- if(x < 0 || x > 1 || Double.isNaN(x)) {
+ if (x < 0 || x > 1 || Double.isNaN(x)) {
return Double.NaN;
}
- if(x == 0) {
+ if (x == 0) {
return 0.0;
}
- if(x == 1) {
+ if (x == 1) {
return 1.0;
}
// Simpler to compute inverse?
- if(x > 0.5) {
+ if (x > 0.5) {
return 1 - rawQuantile(1 - x, beta, alpha, logbab);
- }
- else {
+ } else {
return rawQuantile(x, alpha, beta, logbab);
}
}
@@ -207,26 +205,26 @@ public class BetaDistribution implements DistributionWithRandom {
* @return probability density
*/
public static double pdf(double val, double alpha, double beta) {
- if(alpha <= 0. || beta <= 0. || Double.isNaN(alpha) || Double.isNaN(beta) || Double.isNaN(val)) {
+ if (alpha <= 0. || beta <= 0. || Double.isNaN(alpha) || Double.isNaN(beta) || Double.isNaN(val)) {
return Double.NaN;
}
- if(val < 0. || val > 1.) {
+ if (val < 0. || val > 1.) {
return 0.;
}
- if(val == 0.) {
- if(alpha > 1.) {
+ if (val == 0.) {
+ if (alpha > 1.) {
return 0.;
}
- if(alpha < 1.) {
+ if (alpha < 1.) {
return Double.POSITIVE_INFINITY;
}
return beta;
}
- if(val == 1.) {
- if(beta > 1.) {
+ if (val == 1.) {
+ if (beta > 1.) {
return 0.;
}
- if(beta < 1.) {
+ if (beta < 1.) {
return Double.POSITIVE_INFINITY;
}
return alpha;
@@ -235,6 +233,42 @@ public class BetaDistribution implements DistributionWithRandom {
}
/**
+ * Static version of the PDF of the beta distribution
+ *
+ * @param val Value
+ * @param alpha Shape parameter a
+ * @param beta Shape parameter b
+ * @return probability density
+ */
+ public static double logpdf(double val, double alpha, double beta) {
+ if (alpha <= 0. || beta <= 0. || Double.isNaN(alpha) || Double.isNaN(beta) || Double.isNaN(val)) {
+ return Double.NaN;
+ }
+ if (val < 0. || val > 1.) {
+ return Double.NEGATIVE_INFINITY;
+ }
+ if (val == 0.) {
+ if (alpha > 1.) {
+ return Double.NEGATIVE_INFINITY;
+ }
+ if (alpha < 1.) {
+ return Double.POSITIVE_INFINITY;
+ }
+ return Math.log(beta);
+ }
+ if (val == 1.) {
+ if (beta > 1.) {
+ return Double.NEGATIVE_INFINITY;
+ }
+ if (beta < 1.) {
+ return Double.POSITIVE_INFINITY;
+ }
+ return Math.log(alpha);
+ }
+ return -logBeta(alpha, beta) + Math.log(val) * (alpha - 1) + Math.log1p(-val) * (beta - 1);
+ }
+
+ /**
* Compute log beta(a,b)
*
* @param alpha Shape parameter a
@@ -255,23 +289,22 @@ public class BetaDistribution implements DistributionWithRandom {
* @return Value of the regularized incomplete beta function
*/
public static double regularizedIncBeta(double x, double alpha, double beta) {
- if(alpha <= 0.0 || beta <= 0.0 || Double.isNaN(alpha) || Double.isNaN(beta) || Double.isNaN(x)) {
+ if (alpha <= 0.0 || beta <= 0.0 || Double.isNaN(alpha) || Double.isNaN(beta) || Double.isNaN(x)) {
return Double.NaN;
}
- if(x <= 0.0) {
+ if (x <= 0.0) {
return 0.0;
}
- if(x >= 1.0) {
+ if (x >= 1.0) {
return 1.0;
}
- if(alpha > SWITCH && beta > SWITCH) {
+ if (alpha > SWITCH && beta > SWITCH) {
return regularizedIncBetaQuadrature(alpha, beta, x);
}
double bt = Math.exp(-logBeta(alpha, beta) + alpha * Math.log(x) + beta * Math.log1p(-x));
- if(x < (alpha + 1.0) / (alpha + beta + 2.0)) {
+ if (x < (alpha + 1.0) / (alpha + beta + 2.0)) {
return bt * regularizedIncBetaCF(alpha, beta, x) / alpha;
- }
- else {
+ } else {
return 1.0 - bt * regularizedIncBetaCF(beta, alpha, 1.0 - x) / beta;
}
}
@@ -292,37 +325,37 @@ public class BetaDistribution implements DistributionWithRandom {
double qam = alpha - 1.0;
double c = 1.0;
double d = 1.0 - qab * x / qap;
- if(Math.abs(d) < FPMIN) {
+ if (Math.abs(d) < FPMIN) {
d = FPMIN;
}
d = 1.0 / d;
double h = d;
- for(int m = 1; m < 10000; m++) {
+ for (int m = 1; m < 10000; m++) {
int m2 = 2 * m;
double aa = m * (beta - m) * x / ((qam + m2) * (alpha + m2));
d = 1.0 + aa * d;
- if(Math.abs(d) < FPMIN) {
+ if (Math.abs(d) < FPMIN) {
d = FPMIN;
}
c = 1.0 + aa / c;
- if(Math.abs(c) < FPMIN) {
+ if (Math.abs(c) < FPMIN) {
c = FPMIN;
}
d = 1.0 / d;
h *= d * c;
aa = -(alpha + m) * (qab + m) * x / ((alpha + m2) * (qap + m2));
d = 1.0 + aa * d;
- if(Math.abs(d) < FPMIN) {
+ if (Math.abs(d) < FPMIN) {
d = FPMIN;
}
c = 1.0 + aa / c;
- if(Math.abs(c) < FPMIN) {
+ if (Math.abs(c) < FPMIN) {
c = FPMIN;
}
d = 1.0 / d;
double del = d * c;
h *= del;
- if(Math.abs(del - 1.0) <= NUM_PRECISION) {
+ if (Math.abs(del - 1.0) <= NUM_PRECISION) {
break;
}
}
@@ -339,31 +372,31 @@ public class BetaDistribution implements DistributionWithRandom {
* @return result
*/
protected static double regularizedIncBetaQuadrature(double alpha, double beta, double x) {
- double a1 = alpha - 1.0;
- double b1 = beta - 1.0;
- double mu = alpha / (alpha + beta);
- double lnmu = Math.log(mu);
- double lnmuc = Math.log1p(-mu);
- double t = Math.sqrt(alpha * beta / ((alpha + beta) * (alpha + beta) * (alpha + beta + 1.0)));
- double xu;
- if(x > alpha / (alpha + beta)) {
- if(x >= 1.0) {
+ final double alphapbeta = alpha + beta;
+ final double a1 = alpha - 1.0;
+ final double b1 = beta - 1.0;
+ final double mu = alpha / alphapbeta;
+ final double lnmu = Math.log(mu);
+ final double lnmuc = Math.log1p(-mu);
+ double t = Math.sqrt(alpha * beta / (alphapbeta * alphapbeta * (alphapbeta + 1.0)));
+ final double xu;
+ if (x > alpha / alphapbeta) {
+ if (x >= 1.0) {
return 1.0;
}
xu = Math.min(1.0, Math.max(mu + 10.0 * t, x + 5.0 * t));
- }
- else {
- if(x <= 0.0) {
+ } else {
+ if (x <= 0.0) {
return 0.0;
}
xu = Math.max(0.0, Math.min(mu - 10.0 * t, x - 5.0 * t));
}
double sum = 0.0;
- for(int i = 0; i < GAUSSLEGENDRE_Y.length; i++) {
+ for (int i = 0; i < GAUSSLEGENDRE_Y.length; i++) {
t = x + (xu - x) * GAUSSLEGENDRE_Y[i];
sum += GAUSSLEGENDRE_W[i] * Math.exp(a1 * (Math.log(t) - lnmu) + b1 * (Math.log1p(-t) - lnmuc));
}
- double ans = sum * (xu - x) * Math.exp(a1 * lnmu - GammaDistribution.logGamma(alpha) + b1 * lnmuc - GammaDistribution.logGamma(b1) + GammaDistribution.logGamma(alpha + beta));
+ double ans = sum * (xu - x) * Math.exp(a1 * lnmu - GammaDistribution.logGamma(alpha) + b1 * lnmuc - GammaDistribution.logGamma(beta) + GammaDistribution.logGamma(alphapbeta));
return ans > 0 ? 1.0 - ans : -ans;
}
@@ -377,23 +410,22 @@ public class BetaDistribution implements DistributionWithRandom {
*/
public static double quantile(double p, double alpha, double beta) {
// Valid parameters
- if(Double.isNaN(alpha) || Double.isNaN(beta) || Double.isNaN(p) || alpha < 0. || beta < 0.) {
+ if (Double.isNaN(alpha) || Double.isNaN(beta) || Double.isNaN(p) || alpha < 0. || beta < 0.) {
return Double.NaN;
}
- if(p < 0 || p > 1) {
+ if (p < 0 || p > 1) {
return Double.NaN;
}
- if(p == 0) {
+ if (p == 0) {
return 0.0;
}
- if(p == 1) {
+ if (p == 1) {
return 1.0;
}
// Simpler to compute inverse?
- if(p > 0.5) {
+ if (p > 0.5) {
return 1 - rawQuantile(1 - p, beta, alpha, logBeta(beta, alpha));
- }
- else {
+ } else {
return rawQuantile(p, alpha, beta, logBeta(alpha, beta));
}
}
@@ -415,33 +447,30 @@ public class BetaDistribution implements DistributionWithRandom {
double tmp = Math.sqrt(-2 * Math.log(p));
double y = tmp - (2.30753 + 0.27061 * tmp) / (1. + (0.99229 + 0.04481 * tmp) * tmp);
- if(alpha > 1 && beta > 1) {
+ if (alpha > 1 && beta > 1) {
double r = (y * y - 3.) / 6.;
double s = 1. / (alpha + alpha - 1.);
double t = 1. / (beta + beta - 1.);
double h = 2. / (s + t);
double w = y * Math.sqrt(h + r) / h - (t - s) * (r + 5. / 6. - 2. / (3. * h));
x = alpha / (alpha + beta * Math.exp(w + w));
- }
- else {
+ } else {
double r = beta + beta;
double t = 1. / (9. * beta);
t = r * Math.pow(1. - t + y * Math.sqrt(t), 3.0);
- if(t <= 0.) {
+ if (t <= 0.) {
x = 1. - Math.exp((Math.log1p(-p) + Math.log(beta) + logbeta) / beta);
- }
- else {
+ } else {
t = (4. * alpha + r - 2.) / t;
- if(t <= 1.) {
+ if (t <= 1.) {
x = Math.exp((Math.log(p * alpha) + logbeta) / alpha);
- }
- else {
+ } else {
x = 1. - 2. / (t + 1.);
}
}
}
// Degenerate initial approximations
- if(x < 3e-308 || x > 1 - 2.22e-16) {
+ if (x < 3e-308 || x > 1 - 2.22e-16) {
x = 0.5;
}
}
@@ -455,29 +484,29 @@ public class BetaDistribution implements DistributionWithRandom {
final double acu = Math.max(1e-300, Math.pow(10., -13 - 2.5 / (alpha * alpha) - .5 / (p * p)));
double prevstep = 0., y = 0., stepsize = 1;
- for(int outer = 0; outer < 1000; outer++) {
+ for (int outer = 0; outer < 1000; outer++) {
// Current CDF value
double ynew = cdf(x, alpha, beta);
- if(Double.isInfinite(ynew)) { // Degenerated.
+ if (Double.isInfinite(ynew)) { // Degenerated.
return Double.NaN;
}
// Error gradient
ynew = (ynew - p) * Math.exp(logbeta + ialpha * Math.log(x) + ibeta * Math.log1p(-x));
- if(ynew * y <= 0.) {
+ if (ynew * y <= 0.) {
prevstep = Math.max(Math.abs(stepsize), 3e-308);
}
// Inner loop: try different step sizes: y * 3^-i
double g = 1, xnew = 0.;
- for(int inner = 0; inner < 1000; inner++) {
+ for (int inner = 0; inner < 1000; inner++) {
stepsize = g * ynew;
- if(Math.abs(stepsize) < prevstep) {
+ if (Math.abs(stepsize) < prevstep) {
xnew = x - stepsize; // Candidate x
- if(xnew >= 0. && xnew <= 1.) {
+ if (xnew >= 0. && xnew <= 1.) {
// Close enough
- if(prevstep <= acu || Math.abs(ynew) <= acu) {
+ if (prevstep <= acu || Math.abs(ynew) <= acu) {
return x;
}
- if(xnew != 0. && xnew != 1.) {
+ if (xnew != 0. && xnew != 1.) {
break;
}
}
@@ -485,7 +514,7 @@ public class BetaDistribution implements DistributionWithRandom {
g /= 3.;
}
// Convergence
- if(Math.abs(xnew - x) < 1e-15 * x) {
+ if (Math.abs(xnew - x) < 1e-15 * x) {
return x;
}
// Iterate with new values
@@ -496,4 +525,4 @@ public class BetaDistribution implements DistributionWithRandom {
// Not converged in Newton-Raphson
throw new AbortException("Beta quantile computation did not converge.");
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/CauchyDistribution.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/CauchyDistribution.java
new file mode 100644
index 00000000..c218a37f
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/CauchyDistribution.java
@@ -0,0 +1,135 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.Random;
+
+/**
+ * Cauchy distribution.
+ *
+ * @author Erich Schubert
+ */
+public class CauchyDistribution implements Distribution {
+ /**
+ * The location (x0) parameter.
+ */
+ final double location;
+
+ /**
+ * The shape (gamma) parameter.
+ */
+ final double shape;
+
+ /**
+ * The random generator.
+ */
+ private Random random;
+
+ /**
+ * Constructor with default random.
+ *
+ * @param location Location (x0)
+ * @param shape Shape (gamma)
+ */
+ public CauchyDistribution(double location, double shape) {
+ this(location, shape, new Random());
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param location Location (x0)
+ * @param shape Shape (gamma)
+ * @param random Random generator
+ */
+ public CauchyDistribution(double location, double shape, Random random) {
+ super();
+ this.location = location;
+ this.shape = shape;
+ this.random = random;
+ }
+
+ @Override
+ public double pdf(double x) {
+ return pdf(x, location, shape);
+ }
+
+ @Override
+ public double cdf(double x) {
+ return cdf(x, location, shape);
+ }
+
+ @Override
+ public double quantile(double x) {
+ return quantile(x, location, shape);
+ }
+
+ @Override
+ public double nextRandom() {
+ final double r = random.nextDouble() - .5;
+ return Math.tan(Math.PI * r);
+ }
+
+ /**
+ * PDF function, static version.
+ *
+ * @param x Value
+ * @param location Location (x0)
+ * @param shape Shape (gamma)
+ * @return PDF value
+ */
+ public static double pdf(double x, double location, double shape) {
+ final double v = (x - location) / shape;
+ return 1. / Math.PI * shape * (1 + v * v);
+ }
+
+ /**
+ * PDF function, static version.
+ *
+ * @param x Value
+ * @param location Location (x0)
+ * @param shape Shape (gamma)
+ * @return PDF value
+ */
+ public static double cdf(double x, double location, double shape) {
+ return Math.atan2(x - location, shape) / Math.PI + .5;
+ }
+
+ /**
+ * PDF function, static version.
+ *
+ * @param x Value
+ * @param location Location (x0)
+ * @param shape Shape (gamma)
+ * @return PDF value
+ */
+ public static double quantile(double x, double location, double shape) {
+ return location + shape * Math.tan(Math.PI * (x - .5));
+ }
+
+ @Override
+ public String toString() {
+ return "CauchyDistribution(location=" + location + ", shape=" + shape + ")";
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/ChiDistribution.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/ChiDistribution.java
index 5dc5b399..a552e413 100644
--- a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/ChiDistribution.java
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/ChiDistribution.java
@@ -1,12 +1,13 @@
package de.lmu.ifi.dbs.elki.math.statistics.distribution;
import de.lmu.ifi.dbs.elki.utilities.exceptions.ExceptionMessages;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.NotImplementedException;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -32,7 +33,7 @@ import de.lmu.ifi.dbs.elki.utilities.exceptions.ExceptionMessages;
*
* @apiviz.composedOf ChiSquaredDistribution
*/
-public class ChiDistribution implements DistributionWithRandom {
+public class ChiDistribution implements Distribution {
/**
* Degrees of freedom. Usually integer.
*/
@@ -97,7 +98,7 @@ public class ChiDistribution implements DistributionWithRandom {
// FIXME: implement!
@Override
public double quantile(double val) {
- throw new UnsupportedOperationException(ExceptionMessages.UNSUPPORTED_NOT_YET);
+ throw new NotImplementedException(ExceptionMessages.UNSUPPORTED_NOT_YET);
}
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/ChiSquaredDistribution.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/ChiSquaredDistribution.java
index efa24079..235367cd 100644
--- a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/ChiSquaredDistribution.java
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/ChiSquaredDistribution.java
@@ -6,7 +6,7 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -59,14 +59,14 @@ public class ChiSquaredDistribution extends GammaDistribution {
* @return probability density
*/
public static double pdf(double x, double dof) {
- if(x <= 0) {
+ if (x <= 0) {
return 0.0;
}
- if(x == 0) {
+ if (x == 0) {
return 0.0;
}
final double k = dof * .5;
- if(Math.abs(k - 1.0) < Double.MIN_NORMAL) {
+ if (Math.abs(k - 1.0) < Double.MIN_NORMAL) {
return Math.exp(-x * 2.0) * 2.0;
}
return Math.exp((k - 1.0) * Math.log(x * 2.0) - x * 2.0 - logGamma(k)) * 2.0;
@@ -90,4 +90,9 @@ public class ChiSquaredDistribution extends GammaDistribution {
public static double quantile(double x, double dof) {
return GammaDistribution.quantile(x, .5 * dof, .5);
}
-} \ No newline at end of file
+
+ @Override
+ public String toString() {
+ return "ChiSquaredDistribution(dof=" + (2 * getK()) + ")";
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/ConstantDistribution.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/ConstantDistribution.java
index b046f0ef..35d5294f 100644
--- a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/ConstantDistribution.java
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/ConstantDistribution.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.statistics.distribution;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,7 +28,7 @@ package de.lmu.ifi.dbs.elki.math.statistics.distribution;
*
* @author Erich Schubert
*/
-public class ConstantDistribution implements DistributionWithRandom {
+public class ConstantDistribution implements Distribution {
/**
* The constant
*/
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/Distribution.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/Distribution.java
index ad4ef944..519ba0b3 100644
--- a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/Distribution.java
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/Distribution.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.statistics.distribution;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,9 +24,7 @@ package de.lmu.ifi.dbs.elki.math.statistics.distribution;
*/
/**
- * Statistical distributions, with their common functions. See
- * {@link DistributionWithRandom} for distributions that also have a random
- * generator included.
+ * Statistical distributions, with their common functions.
*
* @author Erich Schubert
*/
@@ -56,10 +54,17 @@ public interface Distribution {
double quantile(double val);
/**
+ * Generate a new random value
+ *
+ * @return new random value
+ */
+ double nextRandom();
+
+ /**
* Describe the distribution
*
* @return description
*/
@Override
String toString();
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/ExponentialDistribution.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/ExponentialDistribution.java
index 866f40d6..e5af3e5b 100644
--- a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/ExponentialDistribution.java
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/ExponentialDistribution.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.statistics.distribution;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -30,7 +30,7 @@ import java.util.Random;
*
* @author Erich Schubert
*/
-public class ExponentialDistribution implements DistributionWithRandom {
+public class ExponentialDistribution implements Distribution {
/**
* Random generator.
*/
@@ -40,6 +40,11 @@ public class ExponentialDistribution implements DistributionWithRandom {
* Rate, inverse of mean
*/
double rate;
+
+ /**
+ * Location parameter.
+ */
+ double location;
/**
* Constructor.
@@ -47,7 +52,17 @@ public class ExponentialDistribution implements DistributionWithRandom {
* @param rate Rate parameter (1/scale)
*/
public ExponentialDistribution(double rate) {
- this(rate, new Random());
+ this(rate, 0.0, null);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param rate Rate parameter (1/scale)
+ * @param location Location parameter
+ */
+ public ExponentialDistribution(double rate, double location) {
+ this(rate, location, null);
}
/**
@@ -57,14 +72,29 @@ public class ExponentialDistribution implements DistributionWithRandom {
* @param random Random generator
*/
public ExponentialDistribution(double rate, Random random) {
+ this(rate, 0.0, random);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param rate Rate parameter (1/scale)
+ * @param location Location parameter
+ * @param random Random generator
+ */
+ public ExponentialDistribution(double rate, double location, Random random) {
super();
this.rate = rate;
+ this.location = location;
this.rnd = random;
}
@Override
public double pdf(double val) {
- return rate * Math.exp(-rate * val);
+ if (val < location) {
+ return 0.;
+ }
+ return rate * Math.exp(-rate * (val - location));
}
/**
@@ -75,12 +105,18 @@ public class ExponentialDistribution implements DistributionWithRandom {
* @return probability density
*/
public static double pdf(double val, double rate) {
+ if (val < 0.) {
+ return 0.;
+ }
return rate * Math.exp(-rate * val);
}
@Override
public double cdf(double val) {
- return 1 - Math.exp(-rate * val);
+ if (val < location) {
+ return 0.;
+ }
+ return 1 - Math.exp(-rate * (val - location));
}
/**
@@ -91,12 +127,15 @@ public class ExponentialDistribution implements DistributionWithRandom {
* @return cumulative density
*/
public static double cdf(double val, double rate) {
+ if (val < 0.) {
+ return 0.;
+ }
return 1 - Math.exp(-rate * val);
}
@Override
public double quantile(double val) {
- return -Math.log(1 - val) / rate;
+ return -Math.log(1 - val) / rate + location;
}
/**
@@ -121,6 +160,11 @@ public class ExponentialDistribution implements DistributionWithRandom {
*/
@Override
public double nextRandom() {
- return -Math.log(rnd.nextDouble()) / rate;
+ return -Math.log(rnd.nextDouble()) / rate + location;
+ }
+
+ @Override
+ public String toString() {
+ return "ExponentialDistribution(rate=" + rate + ", location=" + location + ")";
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/ExponentiallyModifiedGaussianDistribution.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/ExponentiallyModifiedGaussianDistribution.java
new file mode 100644
index 00000000..01e91777
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/ExponentiallyModifiedGaussianDistribution.java
@@ -0,0 +1,188 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.Random;
+
+import de.lmu.ifi.dbs.elki.utilities.Alias;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.ExceptionMessages;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.NotImplementedException;
+
+/**
+ * Exponentially modified Gaussian (EMG) distribution (ExGaussian distribution)
+ * is a combination of a normal distribution and an exponential distribution.
+ *
+ * @author Erich Schubert
+ */
+@Alias({ "exgaussian" })
+public class ExponentiallyModifiedGaussianDistribution implements Distribution {
+ /**
+ * Mean value for the generator
+ */
+ private double mean;
+
+ /**
+ * Standard deviation
+ */
+ private double stddev;
+
+ /**
+ * Exponential rate.
+ */
+ private double lambda;
+
+ /**
+ * Random generator.
+ */
+ private Random rnd;
+
+ /**
+ * Constructor for ExGaussian distribution
+ *
+ * @param mean Mean
+ * @param stddev Standard Deviation
+ * @param lambda Rate
+ * @param rnd Random
+ */
+ public ExponentiallyModifiedGaussianDistribution(double mean, double stddev, double lambda, Random rnd) {
+ super();
+ this.mean = mean;
+ this.stddev = stddev;
+ this.lambda = lambda;
+ this.rnd = rnd;
+ }
+
+ /**
+ * Constructor for ExGaussian distribution
+ *
+ * @param mean Mean
+ * @param stddev Standard Deviation
+ * @param lambda Rate
+ */
+ public ExponentiallyModifiedGaussianDistribution(double mean, double stddev, double lambda) {
+ this(mean, stddev, lambda, null);
+ }
+
+ @Override
+ public double pdf(double val) {
+ return pdf(val, mean, stddev, lambda);
+ }
+
+ @Override
+ public double cdf(double val) {
+ return cdf(val, mean, stddev, lambda);
+ }
+
+ /**
+ * @deprecated Not yet implemented!
+ */
+ @Override
+ @Deprecated
+ public double quantile(double q) {
+ return quantile(q, mean, stddev, lambda);
+ }
+
+ @Override
+ public double nextRandom() {
+ double no = mean + rnd.nextGaussian() * stddev;
+ double ex = -Math.log(rnd.nextDouble()) / lambda;
+ return no + ex;
+ }
+
+ @Override
+ public String toString() {
+ return "ExGaussianDistribution(mean=" + mean + ", stddev=" + stddev + ", lambda=" + lambda + ")";
+ }
+
+ /**
+ * @return the mean
+ */
+ public double getMean() {
+ return mean;
+ }
+
+ /**
+ * @return the standard deviation
+ */
+ public double getStddev() {
+ return stddev;
+ }
+
+ /**
+ * @return the lambda value.
+ */
+ public double getLambda() {
+ return lambda;
+ }
+
+ /**
+ * Probability density function of the ExGaussian distribution.
+ *
+ * @param x The value.
+ * @param mu The mean.
+ * @param sigma The standard deviation.
+ * @param lambda Rate parameter.
+ * @return PDF of the given exgauss distribution at x.
+ */
+ public static double pdf(double x, double mu, double sigma, double lambda) {
+ final double dx = x - mu;
+ final double erfc = NormalDistribution.erfc(lambda * sigma * sigma - dx);
+ return .5 * lambda * Math.exp(lambda * (lambda * sigma * sigma * .5 - dx)) * erfc;
+ }
+
+ /**
+ * Cumulative probability density function (CDF) of an exgauss distribution.
+ *
+ * @param x value to evaluate CDF at.
+ * @param mu Mean value.
+ * @param sigma Standard deviation.
+ * @param lambda Rate parameter.
+ * @return The CDF of the given exgauss distribution at x.
+ */
+ public static double cdf(double x, double mu, double sigma, double lambda) {
+ final double u = lambda * (x - mu);
+ final double v = lambda * sigma;
+ final double v2 = v * v;
+ final double logphi = Math.log(NormalDistribution.cdf(u, v2, v));
+ return NormalDistribution.cdf(u, 0., v) - Math.exp(-u + v2 * .5 + logphi);
+ }
+
+ /**
+ * Inverse cumulative probability density function (probit) of an exgauss
+ * distribution.
+ *
+ * @param x value to evaluate probit function at.
+ * @param mu Mean value.
+ * @param sigma Standard deviation.
+ * @param lambda Rate parameter.
+ * @return The probit of the given exgauss distribution at x.
+ *
+ * @deprecated Not yet implemented!
+ */
+ @Deprecated
+ public static double quantile(double x, double mu, double sigma, double lambda) {
+ // FIXME: implement!
+ throw new NotImplementedException(ExceptionMessages.UNSUPPORTED_NOT_YET);
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/GammaDistribution.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/GammaDistribution.java
index 21eebc51..1b9e2b42 100644
--- a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/GammaDistribution.java
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/GammaDistribution.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.statistics.distribution;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -34,7 +34,7 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
*
* @author Erich Schubert
*/
-public class GammaDistribution implements DistributionWithRandom {
+public class GammaDistribution implements Distribution {
/**
* Euler–Mascheroni constant
*/
@@ -51,11 +51,22 @@ public class GammaDistribution implements DistributionWithRandom {
static final double[] LANCZOS = { 0.99999999999999709182, 57.156235665862923517, -59.597960355475491248, 14.136097974741747174, -0.49191381609762019978, .33994649984811888699e-4, .46523628927048575665e-4, -.98374475304879564677e-4, .15808870322491248884e-3, -.21026444172410488319e-3, .21743961811521264320e-3, -.16431810653676389022e-3, .84418223983852743293e-4, -.26190838401581408670e-4, .36899182659531622704e-5, };
/**
- * Numerical precision to use
+ * Numerical precision to use (data type dependent!)
+ *
+ * If you change this, make sure to test exhaustively!
*/
static final double NUM_PRECISION = 1E-15;
/**
+ * Maximum number of iterations for regularizedGammaP. To prevent degeneration
+ * for extreme values.
+ *
+ * FIXME: is this too high, too low? Can we improve behavior for extreme
+ * cases?
+ */
+ static final int MAX_ITERATIONS = 1000;
+
+ /**
* Alpha == k
*/
private final double k;
@@ -79,8 +90,8 @@ public class GammaDistribution implements DistributionWithRandom {
*/
public GammaDistribution(double k, double theta, Random random) {
super();
- if(k <= 0.0 || theta <= 0.0) {
- throw new IllegalArgumentException("Invalid parameters for Gamma distribution.");
+ if (!(k > 0.0) || !(theta > 0.0)) { // Note: also tests for NaNs!
+ throw new IllegalArgumentException("Invalid parameters for Gamma distribution: " + k + " " + theta);
}
this.k = k;
@@ -151,6 +162,9 @@ public class GammaDistribution implements DistributionWithRandom {
* @return cdf value
*/
public static double cdf(double val, double k, double theta) {
+ if (val < 0) {
+ return 0.;
+ }
return regularizedGammaP(k, val * theta);
}
@@ -163,6 +177,9 @@ public class GammaDistribution implements DistributionWithRandom {
* @return cdf value
*/
public static double logcdf(double val, double k, double theta) {
+ if (val < 0) {
+ return Double.NEGATIVE_INFINITY;
+ }
return logregularizedGammaP(k, val * theta);
}
@@ -175,18 +192,17 @@ public class GammaDistribution implements DistributionWithRandom {
* @return probability density
*/
public static double pdf(double x, double k, double theta) {
- if(x < 0) {
+ if (x < 0) {
return 0.0;
}
- if(x == 0) {
- if(k == 1.0) {
+ if (x == 0) {
+ if (k == 1.0) {
return theta;
- }
- else {
+ } else {
return 0.0;
}
}
- if(k == 1.0) {
+ if (k == 1.0) {
return Math.exp(-x * theta) * theta;
}
@@ -202,18 +218,17 @@ public class GammaDistribution implements DistributionWithRandom {
* @return probability density
*/
public static double logpdf(double x, double k, double theta) {
- if(x < 0) {
+ if (x < 0) {
return Double.NEGATIVE_INFINITY;
}
- if(x == 0) {
- if(k == 1.0) {
+ if (x == 0) {
+ if (k == 1.0) {
return Math.log(theta);
- }
- else {
+ } else {
return Double.NEGATIVE_INFINITY;
}
}
- if(k == 1.0) {
+ if (k == 1.0) {
return Math.log(theta) - x * theta;
}
@@ -232,14 +247,14 @@ public class GammaDistribution implements DistributionWithRandom {
* @return log(&#915;(x))
*/
public static double logGamma(final double x) {
- if(Double.isNaN(x) || (x <= 0.0)) {
+ if (Double.isNaN(x) || (x <= 0.0)) {
return Double.NaN;
}
double g = 607.0 / 128.0;
double tmp = x + g + .5;
tmp = (x + 0.5) * Math.log(tmp) - tmp;
double ser = LANCZOS[0];
- for(int i = LANCZOS.length - 1; i > 0; --i) {
+ for (int i = LANCZOS.length - 1; i > 0; --i) {
ser += LANCZOS[i] / (x + i);
}
return tmp + Math.log(MathUtil.SQRTTWOPI * ser / x);
@@ -275,30 +290,30 @@ public class GammaDistribution implements DistributionWithRandom {
*/
public static double regularizedGammaP(final double a, final double x) {
// Special cases
- if(Double.isNaN(a) || Double.isNaN(x) || (a <= 0.0) || (x < 0.0)) {
+ if (Double.isInfinite(a) || Double.isInfinite(x) || !(a > 0.0) || !(x >= 0.0)) {
return Double.NaN;
}
- if(x == 0.0) {
+ if (x == 0.0) {
return 0.0;
}
- if(x >= a + 1) {
+ if (x >= a + 1) {
// Expected to converge faster
return 1.0 - regularizedGammaQ(a, x);
}
// Loosely following "Numerical Recipes"
- double del = 1.0 / a;
- double sum = del;
- for(int n = 1; n < Integer.MAX_VALUE; n++) {
+ double term = 1.0 / a;
+ double sum = term;
+ for (int n = 1; n < MAX_ITERATIONS; n++) {
// compute next element in the series
- del *= x / (a + n);
- sum = sum + del;
- if(Math.abs(del / sum) < NUM_PRECISION || sum >= Double.POSITIVE_INFINITY) {
+ term = x / (a + n) * term;
+ sum = sum + term;
+ if (sum == Double.POSITIVE_INFINITY) {
+ return 1.0;
+ }
+ if (Math.abs(term / sum) < NUM_PRECISION) {
break;
}
}
- if(Double.isInfinite(sum)) {
- return 1.0;
- }
return Math.exp(-x + (a * Math.log(x)) - logGamma(a)) * sum;
}
@@ -316,13 +331,13 @@ public class GammaDistribution implements DistributionWithRandom {
*/
public static double logregularizedGammaP(final double a, final double x) {
// Special cases
- if(Double.isNaN(a) || Double.isNaN(x) || (a <= 0.0) || (x < 0.0)) {
+ if (Double.isNaN(a) || Double.isNaN(x) || (a <= 0.0) || (x < 0.0)) {
return Double.NaN;
}
- if(x == 0.0) {
+ if (x == 0.0) {
return Double.NEGATIVE_INFINITY;
}
- if(x >= a + 1) {
+ if (x >= a + 1) {
// Expected to converge faster
// FIXME: and in log?
return Math.log(1.0 - regularizedGammaQ(a, x));
@@ -330,15 +345,15 @@ public class GammaDistribution implements DistributionWithRandom {
// Loosely following "Numerical Recipes"
double del = 1.0 / a;
double sum = del;
- for(int n = 1; n < Integer.MAX_VALUE; n++) {
+ for (int n = 1; n < Integer.MAX_VALUE; n++) {
// compute next element in the series
del *= x / (a + n);
sum = sum + del;
- if(Math.abs(del / sum) < NUM_PRECISION || sum >= Double.POSITIVE_INFINITY) {
+ if (Math.abs(del / sum) < NUM_PRECISION || sum >= Double.POSITIVE_INFINITY) {
break;
}
}
- if(Double.isInfinite(sum)) {
+ if (Double.isInfinite(sum)) {
return 0;
}
// TODO: reread numerical recipes, can we replace log(sum)?
@@ -360,13 +375,13 @@ public class GammaDistribution implements DistributionWithRandom {
* @return Result
*/
public static double regularizedGammaQ(final double a, final double x) {
- if(Double.isNaN(a) || Double.isNaN(x) || (a <= 0.0) || (x < 0.0)) {
+ if (Double.isNaN(a) || Double.isNaN(x) || (a <= 0.0) || (x < 0.0)) {
return Double.NaN;
}
- if(x == 0.0) {
+ if (x == 0.0) {
return 1.0;
}
- if(x < a + 1.0) {
+ if (x < a + 1.0) {
// Expected to converge faster
return 1.0 - regularizedGammaP(a, x);
}
@@ -376,21 +391,21 @@ public class GammaDistribution implements DistributionWithRandom {
double c = 1.0 / FPMIN;
double d = 1.0 / b;
double fac = d;
- for(int i = 1; i < Integer.MAX_VALUE; i++) {
+ for (int i = 1; i < MAX_ITERATIONS; i++) {
double an = i * (a - i);
b += 2;
d = an * d + b;
- if(Math.abs(d) < FPMIN) {
+ if (Math.abs(d) < FPMIN) {
d = FPMIN;
}
c = b + an / c;
- if(Math.abs(c) < FPMIN) {
+ if (Math.abs(c) < FPMIN) {
c = FPMIN;
}
d = 1 / d;
double del = d * c;
fac *= del;
- if(Math.abs(del - 1.0) <= NUM_PRECISION) {
+ if (Math.abs(del - 1.0) <= NUM_PRECISION) {
break;
}
}
@@ -424,33 +439,30 @@ public class GammaDistribution implements DistributionWithRandom {
final double e4 = 0.041664508, e5 = 0.008345522, e6 = 0.001353826;
final double e7 = 0.000247453;
- if(k < 1.0) { // Base case, for small k
+ if (k < 1.0) { // Base case, for small k
final double b = 1.0 + 0.36788794412 * k; // Step 1
- while(true) {
+ while (true) {
final double p = b * random.nextDouble();
- if(p <= 1.0) { // when gds <= 1
+ if (p <= 1.0) { // when gds <= 1
final double gds = Math.exp(Math.log(p) / k);
- if(Math.log(random.nextDouble()) <= -gds) {
+ if (Math.log(random.nextDouble()) <= -gds) {
return (gds / theta);
}
- }
- else { // when gds > 1
+ } else { // when gds > 1
final double gds = -Math.log((b - p) / k);
- if(Math.log(random.nextDouble()) <= ((k - 1.0) * Math.log(gds))) {
+ if (Math.log(random.nextDouble()) <= ((k - 1.0) * Math.log(gds))) {
return (gds / theta);
}
}
}
- }
- else {
+ } else {
// Step 1. Preparations
final double ss, s, d;
- if(k != -1.0) {
+ if (k != -1.0) {
ss = k - 0.5;
s = Math.sqrt(ss);
d = 5.656854249 - 12.0 * s;
- }
- else {
+ } else {
// For k == -1.0:
ss = 0.0;
s = 0.0;
@@ -465,7 +477,7 @@ public class GammaDistribution implements DistributionWithRandom {
tv2 = 2.0 * random.nextDouble() - 1.0;
tv12 = tv1 * tv1 + tv2 * tv2;
}
- while(tv12 > 1.0);
+ while (tv12 > 1.0);
v1 = tv1;
/* v2 = tv2; */
v12 = tv12;
@@ -480,39 +492,36 @@ public class GammaDistribution implements DistributionWithRandom {
final double t = v1 * Math.sqrt(-2.0 * Math.log(v12) / v12);
final double x = s + 0.5 * t;
final double gds = x * x;
- if(t >= 0.0) {
+ if (t >= 0.0) {
return (gds / theta); // Immediate acceptance
}
// Random uniform
final double un = random.nextDouble();
// Squeeze acceptance
- if(d * un <= t * t * t) {
+ if (d * un <= t * t * t) {
return (gds / theta);
}
- if(k != -1.0) { // Step 4. Set-up for hat case
+ if (k != -1.0) { // Step 4. Set-up for hat case
final double r = 1.0 / k;
q0 = ((((((((q9 * r + q8) * r + q7) * r + q6) * r + q5) * r + q4) * r + q3) * r + q2) * r + q1) * r;
- if(k > 3.686) {
- if(k > 13.022) {
+ if (k > 3.686) {
+ if (k > 13.022) {
b = 1.77;
si = 0.75;
c = 0.1515 / s;
- }
- else {
+ } else {
b = 1.654 + 0.0076 * ss;
si = 1.68 / s + 0.275;
c = 0.062 / s + 0.024;
}
- }
- else {
+ } else {
b = 0.463 + s - 0.178 * ss;
si = 1.235;
c = 0.195 / s - 0.079 + 0.016 * s;
}
- }
- else {
+ } else {
// For k == -1.0:
b = 0.0;
c = 0.0;
@@ -520,24 +529,23 @@ public class GammaDistribution implements DistributionWithRandom {
q0 = 0.0;
}
// Compute v and q
- if(x > 0.0) {
+ if (x > 0.0) {
final double v = t / (s + s);
final double q;
- if(Math.abs(v) > 0.25) {
+ if (Math.abs(v) > 0.25) {
q = q0 - s * t + 0.25 * t * t + (ss + ss) * Math.log(1.0 + v);
- }
- else {
+ } else {
q = q0 + 0.5 * t * t * ((((((((a9 * v + a8) * v + a7) * v + a6) * v + a5) * v + a4) * v + a3) * v + a2) * v + a1) * v;
}
// Quotient acceptance:
- if(Math.log(1.0 - un) <= q) {
+ if (Math.log(1.0 - un) <= q) {
return (gds / theta);
}
}
}
// Double exponential deviate t
- while(true) {
+ while (true) {
double e, u, sign_u, t;
// Retry until t is sufficiently large
do {
@@ -547,30 +555,28 @@ public class GammaDistribution implements DistributionWithRandom {
sign_u = (u > 0) ? 1.0 : -1.0;
t = b + (e * si) * sign_u;
}
- while(t <= -0.71874483771719);
+ while (t <= -0.71874483771719);
// New v(t) and q(t)
final double v = t / (s + s);
final double q;
- if(Math.abs(v) > 0.25) {
+ if (Math.abs(v) > 0.25) {
q = q0 - s * t + 0.25 * t * t + (ss + ss) * Math.log(1.0 + v);
- }
- else {
+ } else {
q = q0 + 0.5 * t * t * ((((((((a9 * v + a8) * v + a7) * v + a6) * v + a5) * v + a4) * v + a3) * v + a2) * v + a1) * v;
}
- if(q <= 0.0) {
+ if (q <= 0.0) {
continue; // retry
}
// Compute w(t)
final double w;
- if(q > 0.5) {
+ if (q > 0.5) {
w = Math.exp(q) - 1.0;
- }
- else {
+ } else {
w = ((((((e7 * q + e6) * q + e5) * q + e4) * q + e3) * q + e2) * q + e1) * q;
}
// Hat acceptance
- if(c * u * sign_u <= w * Math.exp(e - 0.5 * t * t)) {
+ if (c * u * sign_u <= w * Math.exp(e - 0.5 * t * t)) {
final double x = s + 0.5 * t;
return (x * x / theta);
}
@@ -585,7 +591,7 @@ public class GammaDistribution implements DistributionWithRandom {
*
* Reference:
* <p>
- * Algorithm AS 91: The percentage points of the $\chi$ 2 distribution<br />
+ * Algorithm AS 91: The percentage points of the $\chi^2$ distribution<br />
* D.J. Best, D. E. Roberts<br />
* Journal of the Royal Statistical Society. Series C (Applied Statistics)
* </p>
@@ -599,18 +605,18 @@ public class GammaDistribution implements DistributionWithRandom {
protected static double chisquaredProbitApproximation(final double p, double nu, double g) {
final double EPS1 = 1e-2; // Approximation quality
// Sanity checks
- if(Double.isNaN(p) || Double.isNaN(nu)) {
+ if (Double.isNaN(p) || Double.isNaN(nu)) {
return Double.NaN;
}
// Range check
- if(p <= 0) {
+ if (p <= 0) {
return 0;
}
- if(p >= 1) {
+ if (p >= 1) {
return Double.POSITIVE_INFINITY;
}
// Invalid parameters
- if(nu <= 0) {
+ if (nu <= 0) {
return Double.NaN;
}
// Shape of gamma distribution, "XX" in AS 91
@@ -618,7 +624,7 @@ public class GammaDistribution implements DistributionWithRandom {
// For small chi squared values - AS 91
final double logp = Math.log(p);
- if(nu < -1.24 * logp) {
+ if (nu < -1.24 * logp) {
// FIXME: implement and use logGammap1 instead - more stable?
//
// final double lgam1pa = (alpha < 0.5) ? logGammap1(alpha) :
@@ -626,31 +632,29 @@ public class GammaDistribution implements DistributionWithRandom {
// return Math.exp((lgam1pa + logp) / alpha + MathUtil.LOG2);
// This is literal AS 91, above is the GNU R variant.
return Math.pow(p * k * Math.exp(g + k * MathUtil.LOG2), 1 / k);
- }
- else if(nu > 0.32) {
+ } else if (nu > 0.32) {
// Wilson and Hilferty estimate: - AS 91 at 3
final double x = NormalDistribution.quantile(p, 0, 1);
final double p1 = 2. / (9. * nu);
double ch = nu * Math.pow(x * Math.sqrt(p1) + 1 - p1, 3);
// Better approximation for p tending to 1:
- if(ch > 2.2 * nu + 6) {
+ if (ch > 2.2 * nu + 6) {
ch = -2 * (Math.log1p(-p) - (k - 1) * Math.log(0.5 * ch) + g);
}
return ch;
- }
- else {
+ } else {
// nu <= 0.32, AS 91 at 1
final double C7 = 4.67, C8 = 6.66, C9 = 6.73, C10 = 13.32;
final double ag = Math.log1p(-p) + g + (k - 1) * MathUtil.LOG2;
double ch = 0.4;
- while(true) {
+ while (true) {
final double p1 = 1 + ch * (C7 + ch);
final double p2 = ch * (C9 + ch * (C8 + ch));
final double t = -0.5 + (C7 + 2 * ch) / p1 - (C9 + ch * (C10 + 3 * ch)) / p2;
final double delta = (1 - Math.exp(ag + 0.5 * ch) * p2 / p1) / t;
ch -= delta;
- if(Math.abs(delta) > EPS1 * Math.abs(ch)) {
+ if (Math.abs(delta) > EPS1 * Math.abs(ch)) {
return ch;
}
}
@@ -664,7 +668,7 @@ public class GammaDistribution implements DistributionWithRandom {
*
* Reference:
* <p>
- * Algorithm AS 91: The percentage points of the $\chi$^2 distribution<br />
+ * Algorithm AS 91: The percentage points of the $\chi^2$ distribution<br />
* D.J. Best, D. E. Roberts<br />
* Journal of the Royal Statistical Society. Series C (Applied Statistics)
* </p>
@@ -674,34 +678,34 @@ public class GammaDistribution implements DistributionWithRandom {
* @param theta Theta = 1.0/Beta aka. "scaling" parameter
* @return Probit for Gamma distribution
*/
- @Reference(title = "Algorithm AS 91: The percentage points of the $\\chi$^2 distribution", authors = "D.J. Best, D. E. Roberts", booktitle = "Journal of the Royal Statistical Society. Series C (Applied Statistics)")
+ @Reference(title = "Algorithm AS 91: The percentage points of the $\\chi^2$ distribution", authors = "D.J. Best, D. E. Roberts", booktitle = "Journal of the Royal Statistical Society. Series C (Applied Statistics)")
public static double quantile(double p, double k, double theta) {
final double EPS2 = 5e-7; // final precision of AS 91
final int MAXIT = 1000;
// Avoid degenerates
- if(Double.isNaN(p) || Double.isNaN(k) || Double.isNaN(theta)) {
+ if (Double.isNaN(p) || Double.isNaN(k) || Double.isNaN(theta)) {
return Double.NaN;
}
// Range check
- if(p <= 0) {
+ if (p <= 0) {
return 0;
}
- if(p >= 1) {
+ if (p >= 1) {
return Double.POSITIVE_INFINITY;
}
// Shape parameter check
- if(k < 0 || theta <= 0) {
+ if (k < 0 || theta <= 0) {
return Double.NaN;
}
// Corner case - all at 0
- if(k == 0) {
+ if (k == 0) {
return 0.;
}
int max_newton_iterations = 1;
// For small values, ensure some refinement iterations
- if(k < 1e-10) {
+ if (k < 1e-10) {
max_newton_iterations = 7;
}
@@ -713,17 +717,17 @@ public class GammaDistribution implements DistributionWithRandom {
// Second hald of AS 91 follows:
// Refine ChiSquared approximation
chisq: {
- if(Double.isInfinite(ch)) {
+ if (Double.isInfinite(ch)) {
// Cannot refine infinity
max_newton_iterations = 0;
break chisq;
}
- if(ch < EPS2) {
+ if (ch < EPS2) {
// Do not iterate, but refine with newton method
max_newton_iterations = 20;
break chisq;
}
- if(p > 1 - 1e-14 || p < 1e-100) {
+ if (p > 1 - 1e-14 || p < 1e-100) {
// Not in appropriate value range for AS 91
max_newton_iterations = 20;
break chisq;
@@ -732,11 +736,11 @@ public class GammaDistribution implements DistributionWithRandom {
// Phase II: Iteration
final double c = k - 1;
final double ch0 = ch; // backup initial approximation
- for(int i = 1; i <= MAXIT; i++) {
+ for (int i = 1; i <= MAXIT; i++) {
final double q = ch; // previous approximation
final double p1 = 0.5 * ch;
final double p2 = p - regularizedGammaP(k, p1);
- if(Double.isInfinite(p2) || ch <= 0) {
+ if (Double.isInfinite(p2) || ch <= 0) {
ch = ch0;
max_newton_iterations = 27;
break chisq;
@@ -753,11 +757,11 @@ public class GammaDistribution implements DistributionWithRandom {
final double s6 = (120. + c * (346. + 127. * c)) / 5040.;
ch += t * (1 + 0.5 * t * s1 - b * c * (s1 - b * (s2 - b * (s3 - b * (s4 - b * (s5 - b * s6))))));
}
- if(Math.abs(q - ch) < EPS2 * ch) {
+ if (Math.abs(q - ch) < EPS2 * ch) {
break chisq;
}
// Divergence treatment, from GNU R
- if(Math.abs(q - ch) > 0.1 * Math.abs(ch)) {
+ if (Math.abs(q - ch) > 0.1 * Math.abs(ch)) {
ch = ((ch < q) ? 0.9 : 1.1) * q;
}
}
@@ -765,7 +769,7 @@ public class GammaDistribution implements DistributionWithRandom {
// no convergence in MAXIT iterations -- but we add Newton now...
}
double x = 0.5 * ch / theta;
- if(max_newton_iterations > 0) {
+ if (max_newton_iterations > 0) {
// Refine result using final Newton steps.
// TODO: add unit tests that show an improvement! Maybe in logscale only?
x = gammaQuantileNewtonRefinement(Math.log(p), k, theta, max_newton_iterations, x);
@@ -788,33 +792,33 @@ public class GammaDistribution implements DistributionWithRandom {
protected static double gammaQuantileNewtonRefinement(final double logpt, final double k, final double theta, final int maxit, double x) {
final double EPS_N = 1e-15; // Precision threshold
// 0 is not possible, try MIN_NORMAL instead
- if(x <= 0) {
+ if (x <= 0) {
x = Double.MIN_NORMAL;
}
// Current estimation
double logpc = logcdf(x, k, theta);
- if(x == Double.MIN_NORMAL && logpc > logpt * (1. + 1e-7)) {
+ if (x == Double.MIN_NORMAL && logpc > logpt * (1. + 1e-7)) {
return 0.;
}
- if(logpc == Double.NEGATIVE_INFINITY) {
+ if (logpc == Double.NEGATIVE_INFINITY) {
return 0.;
}
// Refine by newton iterations
- for(int i = 0; i < maxit; i++) {
+ for (int i = 0; i < maxit; i++) {
// Error of current approximation
final double logpe = logpc - logpt;
- if(Math.abs(logpe) < Math.abs(EPS_N * logpt)) {
+ if (Math.abs(logpe) < Math.abs(EPS_N * logpt)) {
break;
}
// Step size is controlled by PDF:
final double g = logpdf(x, k, theta);
- if(g == Double.NEGATIVE_INFINITY) {
+ if (g == Double.NEGATIVE_INFINITY) {
break;
}
final double newx = x - logpe * Math.exp(logpc - g);
// New estimate:
logpc = logcdf(newx, k, theta);
- if(Math.abs(logpc - logpt) > Math.abs(logpe) || (i > 0 && Math.abs(logpc - logpt) == Math.abs(logpe))) {
+ if (Math.abs(logpc - logpt) > Math.abs(logpe) || (i > 0 && Math.abs(logpc - logpt) == Math.abs(logpe))) {
// no further improvement
break;
}
@@ -840,21 +844,20 @@ public class GammaDistribution implements DistributionWithRandom {
*/
@Reference(authors = "J. M. Bernando", title = "Algorithm AS 103: Psi (Digamma) Function", booktitle = "Statistical Algorithms")
public static double digamma(double x) {
- if(!(x > 0)) {
+ if (!(x > 0)) {
return Double.NaN;
}
// Method of equation 5:
- if(x <= 1e-5) {
+ if (x <= 1e-5) {
return -EULERS_CONST - 1. / x;
}
// Method of equation 4:
- else if(x > 49.) {
+ else if (x > 49.) {
final double ix2 = 1. / (x * x);
// Partial series expansion
return Math.log(x) - 0.5 / x - ix2 * ((1.0 / 12.) + ix2 * (1.0 / 120. - ix2 / 252.));
// + O(x^8) error
- }
- else {
+ } else {
// Stirling expansion
return digamma(x + 1.) - 1. / x;
}
@@ -869,78 +872,22 @@ public class GammaDistribution implements DistributionWithRandom {
* @return trigamma value
*/
public static double trigamma(double x) {
- if(!(x > 0)) {
+ if (!(x > 0)) {
return Double.NaN;
}
// Method of equation 5:
- if(x <= 1e-5) {
+ if (x <= 1e-5) {
return 1. / (x * x);
}
// Method of equation 4:
- else if(x > 49.) {
+ else if (x > 49.) {
final double ix2 = 1. / (x * x);
// Partial series expansion
return 1 / x - ix2 / 2. + ix2 / x * (1.0 / 6. - ix2 * (1.0 / 30. + ix2 / 42.));
// + O(x^8) error
- }
- else {
+ } else {
// Stirling expansion
return trigamma(x + 1.) - 1. / (x * x);
}
}
-
- /**
- * Mean least squares estimation of Gamma distribution to a set of
- * observations.
- *
- * @param data Data
- * @return Assumed distribution
- */
- public static GammaDistribution estimate(double[] data) {
- return estimate(data, data.length);
- }
-
- /**
- * Mean least squares estimation of Gamma distribution to a set of
- * observations.
- *
- * Reference:
- * <p>
- * Maximum likelihood estimation of the parameters of the gamma distribution
- * and their bias<br />
- * S. C. Choi, R. Wette<br />
- * in: Technometrics
- * </p>
- *
- * @param data Data
- * @param len Length of array
- * @return Assumed distribution
- */
- @Reference(title = "Maximum likelihood estimation of the parameters of the gamma distribution and their bias", authors = "S. C. Choi, R. Wette", booktitle = "Technometrics", url = "http://www.jstor.org/stable/10.2307/1266892")
- public static GammaDistribution estimate(double[] data, int len) {
- double meanx = 0, meanlogx = 0;
- for(int i = 0; i < len; i++) {
- final double logx = Math.log(data[i]);
- final double deltax = data[i] - meanx;
- final double deltalogx = logx - meanlogx;
- meanx += deltax / (i + 1.);
- meanlogx += deltalogx / (i + 1.);
- }
- // Initial approximation
- final double logmeanx = Math.log(meanx);
- final double diff = logmeanx - meanlogx;
- double k = (3 - diff + Math.sqrt((diff - 3) * (diff - 3) + 24 * diff)) / (12 * diff);
-
- // Refine via newton iteration, based on Choi and Wette equation
- while(true) {
- double kdelta = (Math.log(k) - digamma(k) - diff) / (1 / k - trigamma(k));
- if(Math.abs(kdelta) < 1E-8 || Double.isNaN(kdelta)) {
- break;
- }
- k += kdelta;
- }
- // Estimate theta:
- final double theta = k / meanx;
- return new GammaDistribution(k, theta);
- }
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/GeneralizedExtremeValueDistribution.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/GeneralizedExtremeValueDistribution.java
new file mode 100644
index 00000000..9cd6cb4e
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/GeneralizedExtremeValueDistribution.java
@@ -0,0 +1,167 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution;
+
+import java.util.Random;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Generalized Extreme Value (GEV) distribution, also known as Fisher–Tippett
+ * distribution.
+ *
+ * This is a generalization of the Frechnet, Gumbel and (reversed) Weibull
+ * distributions.
+ *
+ * Implementation notice: apparently (see unit tests), our definition differs
+ * from the scipy definition by having the negative shape.
+ *
+ * @author Erich Schubert
+ */
+public class GeneralizedExtremeValueDistribution implements Distribution {
+ /**
+ * Parameters (location, scale, shape)
+ */
+ final double mu, sigma, k;
+
+ /**
+ * Random number generator.
+ */
+ Random random;
+
+ /**
+ * Constructor.
+ *
+ * @param mu Location parameter mu
+ * @param sigma Scale parameter sigma
+ * @param k Shape parameter k
+ */
+ public GeneralizedExtremeValueDistribution(double mu, double sigma, double k) {
+ this(mu, sigma, k, null);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param mu Location parameter mu
+ * @param sigma Scale parameter sigma
+ * @param k Shape parameter k
+ * @param random Random number generator
+ */
+ public GeneralizedExtremeValueDistribution(double mu, double sigma, double k, Random random) {
+ super();
+ this.mu = mu;
+ this.sigma = sigma;
+ this.k = k;
+ this.random = random;
+ }
+
+ /**
+ * PDF of GEV distribution
+ *
+ * @param x Value
+ * @param mu Location parameter mu
+ * @param sigma Scale parameter sigma
+ * @param k Shape parameter k
+ * @return PDF at position x.
+ */
+ public static double pdf(double x, double mu, double sigma, double k) {
+ x = (x - mu) / sigma;
+ if (k > 0 || k < 0) {
+ if (k * x < -1) {
+ return 0.;
+ }
+ final double tx = Math.pow(1 + k * x, -1. / k);
+ return Math.pow(tx, k + 1) * Math.exp(-tx) / sigma;
+ } else { // Gumbel case:
+ return Math.exp(-x - Math.exp(-x)) / sigma;
+ }
+ }
+
+ @Override
+ public double pdf(double x) {
+ return pdf(x, mu, sigma, k);
+ }
+
+ /**
+ * CDF of GEV distribution
+ *
+ * @param val Value
+ * @param mu Location parameter mu
+ * @param sigma Scale parameter sigma
+ * @param k Shape parameter k
+ * @return CDF at position x.
+ */
+ public static double cdf(double val, double mu, double sigma, double k) {
+ final double x = (val - mu) / sigma;
+ if (k > 0 || k < 0) {
+ if (k * x <= -1) {
+ return (k > 0) ? 0 : 1;
+ }
+ return Math.exp(-Math.pow(1 + k * x, -1. / k));
+ } else { // Gumbel case:
+ return Math.exp(-Math.exp(-x));
+ }
+ }
+
+ @Override
+ public double cdf(double val) {
+ return cdf(val, mu, sigma, k);
+ }
+
+ /**
+ * Quantile function of GEV distribution
+ *
+ * @param val Value
+ * @param mu Location parameter mu
+ * @param sigma Scale parameter sigma
+ * @param k Shape parameter k
+ * @return Quantile function at position x.
+ */
+ public static double quantile(double val, double mu, double sigma, double k) {
+ if (val < 0.0 || val > 1.0) {
+ return Double.NaN;
+ }
+ if (k > 0) {
+ return mu + sigma * Math.max((Math.pow(-Math.log(val), -k) - 1.) / k, -1. / k);
+ } else if (k < 0) {
+ return mu + sigma * Math.min((Math.pow(-Math.log(val), -k) - 1.) / k, -1. / k);
+ } else { // Gumbel
+ return mu + sigma * Math.log(1. / Math.log(1. / val));
+ }
+ }
+
+ @Override
+ public double quantile(double val) {
+ return quantile(val, mu, sigma, k);
+ }
+
+ @Override
+ public double nextRandom() {
+ return quantile(random.nextDouble());
+ }
+
+ @Override
+ public String toString() {
+ return "GeneralizedExtremeValueDistribution(sigma=" + sigma + ", mu=" + mu + ", k=" + k + ")";
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/GeneralizedLogisticAlternateDistribution.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/GeneralizedLogisticAlternateDistribution.java
new file mode 100644
index 00000000..467d6aae
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/GeneralizedLogisticAlternateDistribution.java
@@ -0,0 +1,162 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import java.util.Random;
+
+/**
+ * Generalized logistic distribution.
+ *
+ * One of multiple ways of generalizing the logistic distribution.
+ *
+ * Where {@code shape=0} yields the regular logistic distribution.
+ *
+ * @author Erich Schubert
+ */
+public class GeneralizedLogisticAlternateDistribution implements Distribution {
+ /**
+ * Parameters: location and scale
+ */
+ double location, scale;
+
+ /**
+ * Shape parameter, for generalized logistic distribution.
+ */
+ double shape;
+
+ /**
+ * Random number generator
+ */
+ Random random;
+
+ /**
+ * Constructor.
+ *
+ * @param location Location
+ * @param scale Scale
+ * @param shape Shape parameter
+ */
+ public GeneralizedLogisticAlternateDistribution(double location, double scale, double shape) {
+ this(location, scale, shape, null);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param location Location
+ * @param scale Scale
+ * @param shape Shape parameter
+ * @param random Random number generator
+ */
+ public GeneralizedLogisticAlternateDistribution(double location, double scale, double shape, Random random) {
+ super();
+ this.location = location;
+ this.scale = scale;
+ this.shape = shape;
+ this.random = random;
+ if (!(shape > -1.) || !(shape < 1.)) {
+ throw new ArithmeticException("Invalid shape parameter - must be -1 to +1, is: " + shape);
+ }
+ }
+
+ /**
+ * Probability density function.
+ *
+ * @param val Value
+ * @param loc Location
+ * @param scale Scale
+ * @param shape Shape
+ * @return PDF
+ */
+ public static double pdf(double val, double loc, double scale, double shape) {
+ val = (val - loc) / scale;
+ if (shape != 0.) {
+ val = -Math.log(1 - shape * val) / shape;
+ }
+ double f = 1. + Math.exp(-val);
+ return Math.exp(-val * (1 - shape)) / (scale * f * f);
+ }
+
+ @Override
+ public double pdf(double val) {
+ return pdf(val, location, scale, shape);
+ }
+
+ /**
+ * Cumulative density function.
+ *
+ * @param val Value
+ * @param loc Location
+ * @param scale Scale
+ * @param shape Shape
+ * @return CDF
+ */
+ public static double cdf(double val, double loc, double scale, double shape) {
+ val = (val - loc) / scale;
+ if (shape != 0.) {
+ final double tmp = 1 - shape * val;
+ if (tmp < 1e-15) {
+ return (shape < 0) ? 0 : 1;
+ }
+ val = -Math.log(tmp) / shape;
+ }
+ return 1. / (1. + Math.exp(-val));
+ }
+
+ @Override
+ public double cdf(double val) {
+ return cdf(val, location, scale, shape);
+ }
+
+ /**
+ * Quantile function.
+ *
+ * @param val Value
+ * @param loc Location
+ * @param scale Scale
+ * @param shape Shape
+ * @return Quantile
+ */
+ public static double quantile(double val, double loc, double scale, double shape) {
+ if (shape == 0.) {
+ return loc - scale * Math.log((1 - val) / val);
+ }
+ return loc + scale * (1 - Math.pow((1 - val) / val, shape)) / shape;
+ }
+
+ @Override
+ public double quantile(double val) {
+ return quantile(val, location, scale, shape);
+ }
+
+ @Override
+ public double nextRandom() {
+ double u = random.nextDouble();
+ return quantile(u, location, scale, shape);
+ }
+
+ @Override
+ public String toString() {
+ return "GeneralizedLogisticAlternateDistribution(location=" + location + ", scale=" + scale + ", shape=" + shape + ")";
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/GeneralizedLogisticDistribution.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/GeneralizedLogisticDistribution.java
new file mode 100644
index 00000000..76f71107
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/GeneralizedLogisticDistribution.java
@@ -0,0 +1,184 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import java.util.Random;
+
+/**
+ * Generalized logistic distribution. (Type I, Skew-logistic distribution)
+ *
+ * One of multiple ways of generalizing the logistic distribution.
+ *
+ * {@code pdf(x) = shape * Math.exp(-x) / (1 + Math.exp(-x))**(shape+1)}
+ *
+ * {@code cdf(x) = Math.pow(1+Math.exp(-x), -shape)}
+ *
+ * Where {@code shape=1} yields the regular logistic distribution.
+ *
+ * @author Erich Schubert
+ */
+public class GeneralizedLogisticDistribution implements Distribution {
+ /**
+ * Parameters: location and scale
+ */
+ double location, scale;
+
+ /**
+ * Shape parameter, for generalized logistic distribution.
+ */
+ double shape;
+
+ /**
+ * Random number generator
+ */
+ Random random;
+
+ /**
+ * Constructor.
+ *
+ * @param location Location
+ * @param scale Scale
+ * @param shape Shape parameter
+ */
+ public GeneralizedLogisticDistribution(double location, double scale, double shape) {
+ this(location, scale, shape, null);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param location Location
+ * @param scale Scale
+ * @param shape Shape parameter
+ * @param random Random number generator
+ */
+ public GeneralizedLogisticDistribution(double location, double scale, double shape, Random random) {
+ super();
+ this.location = location;
+ this.scale = scale;
+ this.shape = shape;
+ this.random = random;
+ }
+
+ /**
+ * Probability density function.
+ *
+ * @param val Value
+ * @param loc Location
+ * @param scale Scale
+ * @param shape Shape
+ * @return PDF
+ */
+ public static double pdf(double val, double loc, double scale, double shape) {
+ val = (val - loc) / scale;
+ double e = Math.exp(-val);
+ double f = 1. + e;
+ return shape * e / (scale * Math.pow(f, shape + 1.));
+ }
+
+ /**
+ * log Probability density function.
+ *
+ * TODO: untested.
+ *
+ * @param val Value
+ * @param loc Location
+ * @param scale Scale
+ * @param shape Shape
+ * @return log PDF
+ */
+ public static double logpdf(double val, double loc, double scale, double shape) {
+ val = (val - loc) / scale;
+ double e = Math.exp(-val);
+ return -(val + (shape + 1.0) * Math.log1p(e)) + Math.log(shape);
+ }
+
+ @Override
+ public double pdf(double val) {
+ return pdf(val, location, scale, shape);
+ }
+
+ /**
+ * Cumulative density function.
+ *
+ * @param val Value
+ * @param loc Location
+ * @param scale Scale
+ * @param shape Shape
+ * @return CDF
+ */
+ public static double cdf(double val, double loc, double scale, double shape) {
+ val = (val - loc) / scale;
+ return Math.pow(1. + Math.exp(-val), -shape);
+ }
+
+ /**
+ * log Cumulative density function.
+ *
+ * TODO: untested.
+ *
+ * @param val Value
+ * @param loc Location
+ * @param scale Scale
+ * @param shape Shape
+ * @return log PDF
+ */
+ public static double logcdf(double val, double loc, double scale, double shape) {
+ val = (val - loc) / scale;
+ return Math.log1p(Math.exp(-val)) * -shape;
+ }
+
+ @Override
+ public double cdf(double val) {
+ return cdf(val, location, scale, shape);
+ }
+
+ /**
+ * Quantile function.
+ *
+ * @param val Value
+ * @param loc Location
+ * @param scale Scale
+ * @param shape Shape
+ * @return Quantile
+ */
+ public static double quantile(double val, double loc, double scale, double shape) {
+ return loc + scale * -Math.log(Math.pow(val, -1.0 / shape) - 1);
+ }
+
+ @Override
+ public double quantile(double val) {
+ return quantile(val, location, scale, shape);
+ }
+
+ @Override
+ public double nextRandom() {
+ double u = random.nextDouble();
+ return location + scale * -Math.log(Math.pow(u, -1.0 / shape) - 1);
+ }
+
+ @Override
+ public String toString() {
+ return "GeneralizedLogisticDistribution(location=" + location + ", scale=" + scale + ", shape=" + shape + ")";
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/GumbelDistribution.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/GumbelDistribution.java
new file mode 100644
index 00000000..15b4ca24
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/GumbelDistribution.java
@@ -0,0 +1,134 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.Random;
+
+/**
+ * Gumbel distribution, also known as Log-Weibull distribution.
+ *
+ * @author Erich Schubert
+ */
+public class GumbelDistribution implements Distribution {
+ /**
+ * Mode parameter mu.
+ */
+ double mu;
+
+ /**
+ * Shape parameter beta.
+ */
+ double beta;
+
+ /**
+ * Random number generator.
+ */
+ Random random;
+
+ /**
+ * Constructor.
+ *
+ * @param mu Mode
+ * @param beta Shape
+ */
+ public GumbelDistribution(double mu, double beta) {
+ this(mu, beta, null);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param mu Mode
+ * @param beta Shape
+ * @param random Random number generator
+ */
+ public GumbelDistribution(double mu, double beta, Random random) {
+ super();
+ this.mu = mu;
+ this.beta = beta;
+ this.random = random;
+ }
+
+ /**
+ * PDF of Weibull distribution
+ *
+ * @param x Value
+ * @param mu Mode
+ * @param beta Shape
+ * @return PDF at position x.
+ */
+ public static double pdf(double x, double mu, double beta) {
+ final double z = (x - mu) / beta;
+ return Math.exp(-z - Math.exp(-z)) / beta;
+ }
+
+ @Override
+ public double pdf(double x) {
+ return pdf(x, mu, beta);
+ }
+
+ /**
+ * CDF of Weibull distribution
+ *
+ * @param val Value
+ * @param mu Mode
+ * @param beta Shape
+ * @return CDF at position x.
+ */
+ public static double cdf(double val, double mu, double beta) {
+ return Math.exp(-Math.exp(-(val - mu) / beta));
+ }
+
+ @Override
+ public double cdf(double val) {
+ return cdf(val, mu, beta);
+ }
+
+ /**
+ * Quantile function of Weibull distribution
+ *
+ * @param val Value
+ * @param mu Mode
+ * @param beta Shape
+ * @return Quantile function at position x.
+ */
+ public static double quantile(double val, double mu, double beta) {
+ return mu + beta * Math.log(1 / Math.log(1 / val));
+ }
+
+ @Override
+ public double quantile(double val) {
+ return quantile(val, mu, beta);
+ }
+
+ @Override
+ public double nextRandom() {
+ return mu + beta * Math.log(1 / Math.log(1 / random.nextDouble()));
+ }
+
+ @Override
+ public String toString() {
+ return "GumbelDistribution(mu=" + mu + ", beta=" + beta + ")";
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/HaltonUniformDistribution.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/HaltonUniformDistribution.java
index df8fecda..145744db 100644
--- a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/HaltonUniformDistribution.java
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/HaltonUniformDistribution.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.statistics.distribution;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -63,7 +63,7 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
* @author Erich Schubert
*/
@Reference(title = "Randomized halton sequences", authors = "Wang, X. and Hickernell, F.J.", booktitle = "Mathematical and Computer Modelling Vol. 32 (7)", url = "http://dx.doi.org/10.1016/S0895-7177(00)00178-3")
-public class HaltonUniformDistribution implements DistributionWithRandom {
+public class HaltonUniformDistribution implements Distribution {
/**
* Minimum
*/
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/KappaDistribution.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/KappaDistribution.java
new file mode 100644
index 00000000..9414767c
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/KappaDistribution.java
@@ -0,0 +1,223 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import java.util.Random;
+
+/**
+ * Kappa distribution, by Hosking.
+ *
+ * TODO: add references.
+ *
+ * @author Erich Schubert
+ */
+public class KappaDistribution implements Distribution {
+ /**
+ * Parameters: location and scale
+ */
+ double location, scale;
+
+ /**
+ * Shape parameters.
+ */
+ double shape1, shape2;
+
+ /**
+ * Random number generator
+ */
+ Random random;
+
+ /**
+ * Constructor.
+ *
+ * @param location Location
+ * @param scale Scale
+ * @param shape1 Shape parameter
+ * @param shape2 Shape parameter
+ */
+ public KappaDistribution(double location, double scale, double shape1, double shape2) {
+ this(location, scale, shape1, shape2, null);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param location Location
+ * @param scale Scale
+ * @param shape1 Shape parameter
+ * @param shape2 Shape parameter
+ * @param random Random number generator
+ */
+ public KappaDistribution(double location, double scale, double shape1, double shape2, Random random) {
+ super();
+ this.location = location;
+ this.scale = scale;
+ this.shape1 = shape1;
+ this.shape2 = shape2;
+ this.random = random;
+ if(shape2 >= 0.) {
+ if(shape1 < -1.) {
+ throw new ArithmeticException("Invalid shape1 parameter - must be greater than -1 if shape2 >= 0.!");
+ }
+ }
+ else {
+ if(shape1 < 1. || shape1 > 1. / shape2) {
+ throw new ArithmeticException("Invalid shape1 parameter - must be -1 to +1/shape2 if shape2 < 0.!");
+ }
+ }
+ }
+
+ /**
+ * Probability density function.
+ *
+ * @param val Value
+ * @param loc Location
+ * @param scale Scale
+ * @param shape1 Shape parameter
+ * @param shape2 Shape parameter
+ * @return PDF
+ */
+ public static double pdf(double val, double loc, double scale, double shape1, double shape2) {
+ final double c = cdf(val, loc, scale, shape1, shape2);
+ val = (val - loc) / scale;
+ if(shape1 != 0.) {
+ val = 1 - shape1 * val;
+ if(val < 1e-15) {
+ return 0.;
+ }
+ val = (1. - 1. / shape1) * Math.log(val);
+ }
+ val = Math.exp(-val);
+ return val / scale * Math.pow(c, 1. - shape2);
+ }
+
+ @Override
+ public double pdf(double val) {
+ return pdf(val, location, scale, shape1, shape2);
+ }
+
+ /**
+ * Cumulative density function.
+ *
+ * @param val Value
+ * @param loc Location
+ * @param scale Scale
+ * @param shape1 Shape parameter
+ * @param shape2 Shape parameter
+ * @return CDF
+ */
+ public static double cdf(double val, double loc, double scale, double shape1, double shape2) {
+ val = (val - loc) / scale;
+ if(shape1 != 0.) {
+ double tmp = 1. - shape1 * val;
+ if(tmp < 1e-15) {
+ return (shape1 < 0.) ? 0. : 1.;
+ }
+ val = Math.exp(Math.log(tmp) / shape1);
+ }
+ else {
+ val = Math.exp(-val);
+ }
+ if(shape2 != 0.) {
+ double tmp = 1. - shape2 * val;
+ if(tmp < 1e-15) {
+ return 0.;
+ }
+ val = Math.exp(Math.log(tmp) / shape2);
+ }
+ else {
+ val = Math.exp(-val);
+ }
+ return val;
+ }
+
+ @Override
+ public double cdf(double val) {
+ return cdf(val, location, scale, shape1, shape2);
+ }
+
+ /**
+ * Quantile function.
+ *
+ * @param val Value
+ * @param loc Location
+ * @param scale Scale
+ * @param shape1 Shape parameter
+ * @param shape2 Shape parameter
+ * @return Quantile
+ */
+ public static double quantile(double val, double loc, double scale, double shape1, double shape2) {
+ if(!(val >= 0.) || !(val <= 1.)) {
+ return Double.NaN;
+ }
+ if(val == 0.) {
+ if(shape2 <= 0.) {
+ if(shape1 < 0.) {
+ return loc + scale / shape1;
+ }
+ else {
+ return Double.NEGATIVE_INFINITY;
+ }
+ }
+ else {
+ if(shape1 != 0.) {
+ return loc + scale / shape1 * (1. - Math.pow(shape2, -shape1));
+ }
+ else {
+ return loc + scale * Math.log(shape2);
+ }
+ }
+ }
+ if(val == 1.) {
+ if(shape1 <= 0.) {
+ return Double.NEGATIVE_INFINITY;
+ }
+ return loc + scale / shape1;
+ }
+ val = -Math.log(val);
+ if(shape2 != 0.) {
+ val = (1 - Math.exp(-shape2 * val)) / shape2;
+ }
+ val = -Math.log(val);
+ if(shape1 != 0.) {
+ val = (1 - Math.exp(-shape1 * val)) / shape1;
+ }
+ return loc + scale * val;
+ }
+
+ @Override
+ public double quantile(double val) {
+ return quantile(val, location, scale, shape1, shape2);
+ }
+
+ @Override
+ public double nextRandom() {
+ double u = random.nextDouble();
+ return quantile(u, location, scale, shape1, shape2);
+ }
+
+ @Override
+ public String toString() {
+ return "KappaDistribution(location=" + location + ", scale=" + scale + ", shape1=" + shape1 + ", shape2=" + shape2 + ")";
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/LaplaceDistribution.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/LaplaceDistribution.java
new file mode 100644
index 00000000..eb238a20
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/LaplaceDistribution.java
@@ -0,0 +1,172 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.Random;
+
+import de.lmu.ifi.dbs.elki.utilities.Alias;
+
+/**
+ * Laplace distribution also known as double exponential distribution
+ *
+ * @author Erich Schubert
+ */
+@Alias("DoubleExponentialDistribution")
+public class LaplaceDistribution implements Distribution {
+ /**
+ * Random generator.
+ */
+ Random rnd;
+
+ /**
+ * Rate, inverse of mean
+ */
+ double rate;
+
+ /**
+ * Location parameter.
+ */
+ double location;
+
+ /**
+ * Constructor.
+ *
+ * @param rate Rate parameter (1/scale)
+ */
+ public LaplaceDistribution(double rate) {
+ this(rate, 0.0, null);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param rate Rate parameter (1/scale)
+ * @param location Location parameter
+ */
+ public LaplaceDistribution(double rate, double location) {
+ this(rate, location, null);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param rate Rate parameter (1/scale)
+ * @param random Random generator
+ */
+ public LaplaceDistribution(double rate, Random random) {
+ this(rate, 0.0, random);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param rate Rate parameter (1/scale)
+ * @param location Location parameter
+ * @param random Random generator
+ */
+ public LaplaceDistribution(double rate, double location, Random random) {
+ super();
+ this.rate = rate;
+ this.location = location;
+ this.rnd = random;
+ }
+
+ @Override
+ public double pdf(double val) {
+ return .5 * rate * Math.exp(-rate * Math.abs(val - location));
+ }
+
+ /**
+ * PDF, static version
+ *
+ * @param val Value to compute PDF at
+ * @param rate Rate parameter (1/scale)
+ * @return probability density
+ */
+ public static double pdf(double val, double rate) {
+ return .5 * rate * Math.exp(-rate * Math.abs(val));
+ }
+
+ @Override
+ public double cdf(double val) {
+ final double v = .5 * Math.exp(-rate * (val - location));
+ return (val < location) ? v : 1 - v;
+ }
+
+ /**
+ * Cumulative density, static version
+ *
+ * @param val Value to compute CDF at
+ * @param rate Rate parameter (1/scale)
+ * @return cumulative density
+ */
+ public static double cdf(double val, double rate) {
+ final double v = .5 * Math.exp(-rate * val);
+ return (val < 0.) ? v : 1 - v;
+ }
+
+ @Override
+ public double quantile(double val) {
+ if (val < .5) {
+ return Math.log(2 * val) / rate + location;
+ } else {
+ return -Math.log(2. - 2. * val) / rate + location;
+ }
+ }
+
+ /**
+ * Quantile function, static version
+ *
+ * @param val Value to compute quantile for
+ * @param rate Rate parameter
+ * @param location Location parameter
+ * @return Quantile
+ */
+ public static double quantile(double val, double rate, double location) {
+ if (val < .5) {
+ return Math.log(2 * val) / rate + location;
+ } else {
+ return -Math.log(2. - 2. * val) / rate + location;
+ }
+ }
+
+ /**
+ * This method currently uses the naive approach of returning
+ * <code>-log(uniform)</code>.
+ */
+ @Override
+ public double nextRandom() {
+ double val = rnd.nextDouble();
+ if (val < .5) {
+ return Math.log(2 * val) / rate + location;
+ } else {
+ return -Math.log(2. - 2. * val) / rate + location;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "LaplaceDistribution(rate=" + rate + ", location=" + location + ")";
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/LogGammaAlternateDistribution.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/LogGammaAlternateDistribution.java
new file mode 100644
index 00000000..496e6867
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/LogGammaAlternateDistribution.java
@@ -0,0 +1,209 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.Random;
+
+/**
+ * Alternate Log-Gamma Distribution, with random generation and density
+ * functions.
+ *
+ * This distribution can be outlined as Y=log X with X Gamma distributed.
+ *
+ * Note: this matches the loggamma of SciPy.
+ *
+ * @author Erich Schubert
+ */
+public class LogGammaAlternateDistribution implements Distribution {
+ /**
+ * Alpha == k.
+ */
+ private final double k;
+
+ /**
+ * Theta == 1 / Beta.
+ */
+ private final double theta;
+
+ /**
+ * Translation offset.
+ */
+ private final double shift;
+
+ /**
+ * The random generator.
+ */
+ private Random random;
+
+ /**
+ * Constructor for Gamma distribution.
+ *
+ * @param k k, alpha aka. "shape" parameter
+ * @param shift Location offset
+ * @param theta Theta = 1.0/Beta aka. "scaling" parameter
+ * @param random Random generator
+ */
+ public LogGammaAlternateDistribution(double k, double theta, double shift, Random random) {
+ super();
+ if (!(k > 0.0) || !(theta > 0.0)) { // Note: also tests for NaNs!
+ throw new IllegalArgumentException("Invalid parameters for Gamma distribution: " + k + " " + theta);
+ }
+
+ this.k = k;
+ this.theta = theta;
+ this.shift = shift;
+ this.random = random;
+ }
+
+ /**
+ * Constructor for Gamma distribution.
+ *
+ * @param k k, alpha aka. "shape" parameter
+ * @param theta Theta = 1.0/Beta aka. "scaling" parameter
+ * @param shift Location offset
+ */
+ public LogGammaAlternateDistribution(double k, double theta, double shift) {
+ this(k, theta, shift, null);
+ }
+
+ @Override
+ public double pdf(double val) {
+ return pdf(val, k, theta, shift);
+ }
+
+ @Override
+ public double cdf(double val) {
+ return cdf(val, k, theta, shift);
+ }
+
+ @Override
+ public double quantile(double val) {
+ return quantile(val, k, theta, shift);
+ }
+
+ @Override
+ public double nextRandom() {
+ return Math.log(GammaDistribution.nextRandom(k, 1., random)) / theta + shift;
+ }
+
+ /**
+ * Simple toString explaining the distribution parameters.
+ *
+ * Used in producing a model description.
+ */
+ @Override
+ public String toString() {
+ return "LogGammaAlternateDistribution(k=" + k + ", theta=" + theta + ", shift=" + shift + ")";
+ }
+
+ /**
+ * @return the value of k
+ */
+ public double getK() {
+ return k;
+ }
+
+ /**
+ * @return the standard deviation
+ */
+ public double getTheta() {
+ return theta;
+ }
+
+ /**
+ * The CDF, static version.
+ *
+ * @param x Value
+ * @param k Shape k
+ * @param theta Theta = 1.0/Beta aka. "scaling" parameter
+ * @return cdf value
+ */
+ public static double cdf(double x, double k, double theta, double shift) {
+ if (x <= shift) {
+ return 0.;
+ }
+ x = (x - shift) * theta;
+ return GammaDistribution.regularizedGammaP(k, Math.exp(x));
+ }
+
+ /**
+ * The log CDF, static version.
+ *
+ * @param x Value
+ * @param k Shape k
+ * @param theta Theta = 1.0/Beta aka. "scaling" parameter
+ * @return cdf value
+ */
+ public static double logcdf(double x, double k, double theta, double shift) {
+ if (x <= shift) {
+ return 0.;
+ }
+ x = (x - shift) * theta;
+ return GammaDistribution.logregularizedGammaP(k, Math.exp(x));
+ }
+
+ /**
+ * LogGamma distribution PDF (with 0.0 for x &lt; 0)
+ *
+ * @param x query value
+ * @param k Alpha
+ * @param theta Theta = 1 / Beta
+ * @return probability density
+ */
+ public static double pdf(double x, double k, double theta, double shift) {
+ if (x <= shift) {
+ return 0.;
+ }
+ x = (x - shift) * theta;
+ return theta * Math.exp(k * x - Math.exp(x) - GammaDistribution.logGamma(k));
+ }
+
+ /**
+ * LogGamma distribution PDF (with 0.0 for x &lt; 0)
+ *
+ * @param x query value
+ * @param k Alpha
+ * @param theta Theta = 1 / Beta
+ * @return probability density
+ */
+ public static double logpdf(double x, double k, double theta, double shift) {
+ if (x <= shift) {
+ return 0.0;
+ }
+ x = (x - shift) * theta;
+ return Math.log(theta) + k * x - Math.exp(x) - GammaDistribution.logGamma(k);
+ }
+
+ /**
+ * Compute probit (inverse cdf) for LogGamma distributions.
+ *
+ * @param p Probability
+ * @param k k, alpha aka. "shape" parameter
+ * @param theta Theta = 1.0/Beta aka. "scaling" parameter
+ * @return Probit for Gamma distribution
+ */
+ public static double quantile(double p, double k, double theta, double shift) {
+ return Math.log(GammaDistribution.quantile(p, k, 1.)) / theta + shift;
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/LogGammaDistribution.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/LogGammaDistribution.java
new file mode 100644
index 00000000..db3a2b3f
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/LogGammaDistribution.java
@@ -0,0 +1,194 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.Random;
+
+/**
+ * Log-Gamma Distribution, with random generation and density functions.
+ *
+ * This distribution can be outlined as Y=e^X with X Gamma distributed.
+ *
+ * Note: this is a different loggamma than scipy uses.
+ *
+ * @author Erich Schubert
+ */
+public class LogGammaDistribution implements Distribution {
+ /**
+ * Alpha == k.
+ */
+ private final double k;
+
+ /**
+ * Theta == 1 / Beta.
+ */
+ private final double theta;
+
+ /**
+ * Translation offset.
+ */
+ private final double shift;
+
+ /**
+ * The random generator.
+ */
+ private Random random;
+
+ /**
+ * Constructor for Gamma distribution.
+ *
+ * @param k k, alpha aka. "shape" parameter
+ * @param shift Location offset
+ * @param theta Theta = 1.0/Beta aka. "scaling" parameter
+ * @param random Random generator
+ */
+ public LogGammaDistribution(double k, double theta, double shift, Random random) {
+ super();
+ if (!(k > 0.0) || !(theta > 0.0)) { // Note: also tests for NaNs!
+ throw new IllegalArgumentException("Invalid parameters for Gamma distribution: " + k + " " + theta);
+ }
+
+ this.k = k;
+ this.theta = theta;
+ this.shift = shift;
+ this.random = random;
+ }
+
+ /**
+ * Constructor for Gamma distribution.
+ *
+ * @param k k, alpha aka. "shape" parameter
+ * @param theta Theta = 1.0/Beta aka. "scaling" parameter
+ * @param shift Location offset
+ */
+ public LogGammaDistribution(double k, double theta, double shift) {
+ this(k, theta, shift, null);
+ }
+
+ @Override
+ public double pdf(double val) {
+ return pdf(val, k, theta, shift);
+ }
+
+ @Override
+ public double cdf(double val) {
+ return cdf(val, k, theta, shift);
+ }
+
+ @Override
+ public double quantile(double val) {
+ return quantile(val, k, theta, shift);
+ }
+
+ @Override
+ public double nextRandom() {
+ return Math.exp(GammaDistribution.nextRandom(k, theta, random)) + shift;
+ }
+
+ /**
+ * Simple toString explaining the distribution parameters.
+ *
+ * Used in producing a model description.
+ */
+ @Override
+ public String toString() {
+ return "LogGammaDistribution(k=" + k + ", theta=" + theta + ", shift=" + shift + ")";
+ }
+
+ /**
+ * @return the value of k
+ */
+ public double getK() {
+ return k;
+ }
+
+ /**
+ * @return the standard deviation
+ */
+ public double getTheta() {
+ return theta;
+ }
+
+ /**
+ * The CDF, static version.
+ *
+ * @param x Value
+ * @param k Shape k
+ * @param theta Theta = 1.0/Beta aka. "scaling" parameter
+ * @return cdf value
+ */
+ public static double cdf(double x, double k, double theta, double shift) {
+ x = (x - shift);
+ if (x <= 1.) {
+ return 0.;
+ }
+ return GammaDistribution.regularizedGammaP(k, Math.log(x));
+ }
+
+ /**
+ * The log CDF, static version.
+ *
+ * @param x Value
+ * @param k Shape k
+ * @param theta Theta = 1.0/Beta aka. "scaling" parameter
+ * @return cdf value
+ */
+ public static double logcdf(double x, double k, double theta, double shift) {
+ x = (x - shift);
+ if (x <= 1.) {
+ return 0.;
+ }
+ return GammaDistribution.logregularizedGammaP(k, Math.log(x));
+ }
+
+ /**
+ * LogGamma distribution PDF (with 0.0 for x &lt; 0)
+ *
+ * @param x query value
+ * @param k Alpha
+ * @param theta Theta = 1 / Beta
+ * @return probability density
+ */
+ public static double pdf(double x, double k, double theta, double shift) {
+ x = (x - shift);
+ if (x <= 1.) {
+ return 0.;
+ }
+ return Math.pow(theta, -k) / GammaDistribution.gamma(k) * Math.pow(x, -(1. / theta + 1.)) * Math.pow(Math.log(x), k - 1.);
+ }
+
+ // TODO: logpdf
+
+ /**
+ * Compute probit (inverse cdf) for LogGamma distributions.
+ *
+ * @param p Probability
+ * @param k k, alpha aka. "shape" parameter
+ * @param theta Theta = 1.0/Beta aka. "scaling" parameter
+ * @return Probit for Gamma distribution
+ */
+ public static double quantile(double p, double k, double theta, double shift) {
+ return Math.exp(GammaDistribution.quantile(p, k, theta)) + shift;
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/LogLogisticDistribution.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/LogLogisticDistribution.java
new file mode 100644
index 00000000..cb75561d
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/LogLogisticDistribution.java
@@ -0,0 +1,137 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import java.util.Random;
+
+/**
+ * Log-Logistic distribution also known as Fisk distribution.
+ *
+ * @author Erich Schubert
+ */
+public class LogLogisticDistribution implements Distribution {
+ /**
+ * Parameters: scale and shape
+ */
+ double scale, shape;
+
+ /**
+ * Random number generator
+ */
+ Random random;
+
+ /**
+ * Constructor.
+ *
+ * @param scale Scale
+ * @param shape Shape
+ */
+ public LogLogisticDistribution(double scale, double shape) {
+ this(scale, shape, null);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param scale Scale
+ * @param shape Shape
+ * @param random Random number generator
+ */
+ public LogLogisticDistribution(double scale, double shape, Random random) {
+ super();
+ this.scale = scale;
+ this.shape = shape;
+ this.random = random;
+ }
+
+ /**
+ * Probability density function.
+ *
+ * @param val Value
+ * @param scale Scale
+ * @param shape Shape
+ * @return PDF
+ */
+ public static double pdf(double val, double scale, double shape) {
+ if(val < 0) {
+ return 0;
+ }
+ val = Math.abs(val / scale);
+ double f = shape / scale * Math.pow(val, shape - 1.);
+ double d = 1. + Math.pow(val, shape);
+ return f / (d * d);
+ }
+
+ @Override
+ public double pdf(double val) {
+ return pdf(val, scale, shape);
+ }
+
+ /**
+ * Cumulative density function.
+ *
+ * @param val Value
+ * @param scale Scale
+ * @param shape Shape
+ * @return CDF
+ */
+ public static double cdf(double val, double scale, double shape) {
+ if(val < 0) {
+ return 0;
+ }
+ return 1. / (1. + Math.pow(val / scale, -shape));
+ }
+
+ @Override
+ public double cdf(double val) {
+ return cdf(val, scale, shape);
+ }
+
+ /**
+ * Quantile function.
+ *
+ * @param val Value
+ * @param scale Scale
+ * @param shape Shape
+ * @return Quantile
+ */
+ public static double quantile(double val, double scale, double shape) {
+ return scale * Math.pow(val / (1. - val), 1. / shape);
+ }
+
+ @Override
+ public double quantile(double val) {
+ return quantile(val, scale, shape);
+ }
+
+ @Override
+ public double nextRandom() {
+ double u = random.nextDouble();
+ return scale * Math.pow(u / (1. - u), 1. / shape);
+ }
+
+ @Override
+ public String toString() {
+ return "LogLogisticDistribution(scale=" + scale + ", shape=" + shape + ")";
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/LogNormalDistribution.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/LogNormalDistribution.java
new file mode 100644
index 00000000..4c3d9aa0
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/LogNormalDistribution.java
@@ -0,0 +1,165 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import java.util.Random;
+
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
+
+/**
+ * Log-Normal distribution.
+ *
+ * The parameterization of this class is somewhere inbetween of GNU R and SciPy.
+ * Similar to GNU R we use the logmean and logstddev. Similar to Scipy, we also
+ * have a location parameter that shifts the distribution.
+ *
+ * Our implementation maps to SciPy's as follows:
+ * <tt>scipy.stats.lognorm(logstddev, shift, math.exp(logmean))</tt>
+ *
+ * @author Erich Schubert
+ */
+@Alias({ "lognormal" })
+public class LogNormalDistribution implements Distribution {
+ /**
+ * Mean value for the generator
+ */
+ private double logmean;
+
+ /**
+ * Standard deviation
+ */
+ private double logstddev;
+
+ /**
+ * Additional shift factor
+ */
+ private double shift = 0.;
+
+ /**
+ * The random generator.
+ */
+ private Random random;
+
+ /**
+ * Constructor for Log-Normal distribution
+ *
+ * @param logmean Mean
+ * @param logstddev Standard Deviation
+ * @param shift Shifting offset
+ * @param random Random generator
+ */
+ public LogNormalDistribution(double logmean, double logstddev, double shift, Random random) {
+ super();
+ this.logmean = logmean;
+ this.logstddev = logstddev;
+ this.shift = shift;
+ this.random = random;
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param logmean Mean
+ * @param logstddev Standard deviation
+ * @param shift Shifting offset
+ */
+ public LogNormalDistribution(double logmean, double logstddev, double shift) {
+ this(logmean, logstddev, shift, null);
+ }
+
+ @Override
+ public double pdf(double val) {
+ return pdf(val - shift, logmean, logstddev);
+ }
+
+ @Override
+ public double cdf(double val) {
+ return cdf(val - shift, logmean, logstddev);
+ }
+
+ @Override
+ public double quantile(double val) {
+ return quantile(val, logmean, logstddev) + shift;
+ }
+
+ /**
+ * Probability density function of the normal distribution.
+ *
+ * <pre>
+ * 1/(SQRT(2*pi)*sigma*x) * e^(-log(x-mu)^2/2sigma^2)
+ * </pre>
+ *
+ *
+ * @param x The value.
+ * @param mu The mean.
+ * @param sigma The standard deviation.
+ * @return PDF of the given normal distribution at x.
+ */
+ public static double pdf(double x, double mu, double sigma) {
+ if (x <= 0.) {
+ return 0.;
+ }
+ final double x_mu = Math.log(x) - mu;
+ final double sigmasq = sigma * sigma;
+ return 1 / (MathUtil.SQRTTWOPI * sigma * x) * Math.exp(-.5 * x_mu * x_mu / sigmasq);
+ }
+
+ /**
+ * Cumulative probability density function (CDF) of a normal distribution.
+ *
+ * @param x value to evaluate CDF at
+ * @param mu Mean value
+ * @param sigma Standard deviation.
+ * @return The CDF of the given normal distribution at x.
+ */
+ public static double cdf(double x, double mu, double sigma) {
+ if (x <= 0.) {
+ return 0.;
+ }
+ return .5 * (1 + NormalDistribution.erf((Math.log(x) - mu) / (MathUtil.SQRT2 * sigma)));
+ }
+
+ /**
+ * Inverse cumulative probability density function (probit) of a normal
+ * distribution.
+ *
+ * @param x value to evaluate probit function at
+ * @param mu Mean value
+ * @param sigma Standard deviation.
+ * @return The probit of the given normal distribution at x.
+ */
+ public static double quantile(double x, double mu, double sigma) {
+ return Math.exp(mu + sigma * NormalDistribution.standardNormalQuantile(x));
+ }
+
+ @Override
+ public double nextRandom() {
+ return Math.exp(logmean + random.nextGaussian() * logstddev) + shift;
+ }
+
+ @Override
+ public String toString() {
+ return "LogNormalDistribution(logmean=" + logmean + ", logstddev=" + logstddev + ", shift=" + shift + ")";
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/LogisticDistribution.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/LogisticDistribution.java
new file mode 100644
index 00000000..052847d6
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/LogisticDistribution.java
@@ -0,0 +1,186 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import java.util.Random;
+
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+
+/**
+ * Logistic distribution.
+ *
+ * @author Erich Schubert
+ */
+public class LogisticDistribution implements Distribution {
+ /**
+ * Parameters: location and scale
+ */
+ double location, scale;
+
+ /**
+ * Random number generator
+ */
+ Random random;
+
+ /**
+ * Constructor.
+ *
+ * @param location Location
+ * @param scale Scale
+ */
+ public LogisticDistribution(double location, double scale) {
+ this(location, scale, null);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param location Location
+ * @param scale Scale
+ * @param random Random number generator
+ */
+ public LogisticDistribution(double location, double scale, Random random) {
+ super();
+ this.location = location;
+ this.scale = scale;
+ this.random = random;
+ }
+
+ /**
+ * Probability density function.
+ *
+ * @param val Value
+ * @param loc Location
+ * @param scale Scale
+ * @return PDF
+ */
+ public static double pdf(double val, double loc, double scale) {
+ val = Math.abs((val - loc) / scale);
+ double e = Math.exp(-val);
+ double f = 1.0 + e;
+ return e / (scale * f * f);
+ }
+
+ /**
+ * log Probability density function.
+ *
+ * TODO: untested.
+ *
+ * @param val Value
+ * @param loc Location
+ * @param scale Scale
+ * @return log PDF
+ */
+ public static double logpdf(double val, double loc, double scale) {
+ val = Math.abs((val - loc) / scale);
+ double e = Math.exp(-val);
+ double f = 1.0 + e;
+ return -(val + Math.log(scale * f * f));
+ }
+
+ @Override
+ public double pdf(double val) {
+ return pdf(val, location, scale);
+ }
+
+ /**
+ * Cumulative density function.
+ *
+ * @param val Value
+ * @param loc Location
+ * @param scale Scale
+ * @return CDF
+ */
+ public static double cdf(double val, double loc, double scale) {
+ val = (val - loc) / scale;
+ return 1. / (1. + Math.exp(-val));
+ }
+
+ /**
+ * log Cumulative density function.
+ *
+ * TODO: untested.
+ *
+ * @param val Value
+ * @param loc Location
+ * @param scale Scale
+ * @return log PDF
+ */
+ public static double logcdf(double val, double loc, double scale) {
+ val = (val - loc) / scale;
+ if (val <= 18.) {
+ return -Math.log1p(Math.exp(-val));
+ } else if (val > 33.3) {
+ return val;
+ } else {
+ return val - Math.exp(val);
+ }
+ }
+
+ @Override
+ public double cdf(double val) {
+ return cdf(val, location, scale);
+ }
+
+ /**
+ * Quantile function.
+ *
+ * @param val Value
+ * @param loc Location
+ * @param scale Scale
+ * @return Quantile
+ */
+ public static double quantile(double val, double loc, double scale) {
+ return loc + scale * Math.log(val / (1. - val));
+ }
+
+ /**
+ * log Quantile function.
+ *
+ * TODO: untested.
+ *
+ * @param val Value
+ * @param loc Location
+ * @param scale Scale
+ * @return Quantile
+ */
+ public static double logquantile(double val, double loc, double scale) {
+ return loc + scale * (val - MathUtil.log1mexp(-val));
+ }
+
+ @Override
+ public double quantile(double val) {
+ return quantile(val, location, scale);
+ }
+
+ @Override
+ public double nextRandom() {
+ double u = random.nextDouble();
+ return location + scale * Math.log(u / (1. - u));
+ }
+
+ @Override
+ public String toString() {
+ return "LogisticDistribution(location=" + location + ", scale=" + scale + ")";
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/NormalDistribution.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/NormalDistribution.java
index 1845dec1..c4ae7b6c 100644
--- a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/NormalDistribution.java
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/NormalDistribution.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.statistics.distribution;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,13 +26,15 @@ package de.lmu.ifi.dbs.elki.math.statistics.distribution;
import java.util.Random;
import de.lmu.ifi.dbs.elki.math.MathUtil;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
/**
* Gaussian distribution aka normal distribution
*
* @author Erich Schubert
*/
-public class NormalDistribution implements DistributionWithRandom {
+@Alias({ "GaussianDistribution", "normal", "gauss" })
+public class NormalDistribution implements Distribution {
/**
* Coefficients for erf approximation.
*
@@ -106,6 +108,11 @@ public class NormalDistribution implements DistributionWithRandom {
static final double ERFINV_D[] = { 7.784695709041462e-03, 3.224671290700398e-01, 2.445134137142996e+00, 3.754408661907416e+00 };
/**
+ * 1 / CDFINV(0.75)
+ */
+ public static final double ONEBYPHIINV075 = 1.48260221850560186054;
+
+ /**
* Mean value for the generator
*/
private double mean;
@@ -194,28 +201,28 @@ public class NormalDistribution implements DistributionWithRandom {
* @return erfc(x)
*/
public static double erfc(double x) {
- if(Double.isNaN(x)) {
+ if (Double.isNaN(x)) {
return Double.NaN;
}
- if(Double.isInfinite(x)) {
+ if (Double.isInfinite(x)) {
return (x < 0.0) ? 2 : 0;
}
double result = Double.NaN;
double absx = Math.abs(x);
// First approximation interval
- if(absx < 0.46875) {
+ if (absx < 0.46875) {
double z = x * x;
result = 1 - x * ((((ERFAPP_A[0] * z + ERFAPP_A[1]) * z + ERFAPP_A[2]) * z + ERFAPP_A[3]) * z + ERFAPP_A[4]) / ((((ERFAPP_B[0] * z + ERFAPP_B[1]) * z + ERFAPP_B[2]) * z + ERFAPP_B[3]) * z + ERFAPP_B[4]);
}
// Second approximation interval
- else if(absx < 4.0) {
+ else if (absx < 4.0) {
double z = absx;
result = ((((((((ERFAPP_C[0] * z + ERFAPP_C[1]) * z + ERFAPP_C[2]) * z + ERFAPP_C[3]) * z + ERFAPP_C[4]) * z + ERFAPP_C[5]) * z + ERFAPP_C[6]) * z + ERFAPP_C[7]) * z + ERFAPP_C[8]) / ((((((((ERFAPP_D[0] * z + ERFAPP_D[1]) * z + ERFAPP_D[2]) * z + ERFAPP_D[3]) * z + ERFAPP_D[4]) * z + ERFAPP_D[5]) * z + ERFAPP_D[6]) * z + ERFAPP_D[7]) * z + ERFAPP_D[8]);
double rounded = Math.round(result * 16.0) / 16.0;
double del = (absx - rounded) * (absx + rounded);
result = Math.exp(-rounded * rounded) * Math.exp(-del) * result;
- if(x < 0.0) {
+ if (x < 0.0) {
result = 2.0 - result;
}
}
@@ -227,7 +234,7 @@ public class NormalDistribution implements DistributionWithRandom {
double rounded = Math.round(result * 16.0) / 16.0;
double del = (absx - rounded) * (absx + rounded);
result = Math.exp(-rounded * rounded) * Math.exp(-del) * result;
- if(x < 0.0) {
+ if (x < 0.0) {
result = 2.0 - result;
}
}
@@ -254,50 +261,24 @@ public class NormalDistribution implements DistributionWithRandom {
* @return erfinv(x)
*/
public static double erfinv(double x) {
- return standardNormalQuantile(0.5 * (x + 1)) / MathUtil.SQRT2;
+ return standardNormalQuantile(0.5 * (x + 1)) * MathUtil.SQRTHALF;
}
/**
- * Approximate the inverse error function for normal distributions.
- *
- * Largely based on:
- * <p>
- * http://www.math.uio.no/~jacklam/notes/invnorm/index.html <br>
- * by Peter John Acklam
- * </p>
+ * Probability density function of the normal distribution.
*
- * FIXME: precision of this seems to be rather low, compared to our other
- * functions. Only about 8-9 digits agree with SciPy/GNU R.
+ * <pre>
+ * 1/(SQRT(2*pi*sigma^2)) * e^(-(x-mu)^2/2sigma^2)
+ * </pre>
*
- * @param d Quantile. Must be in [0:1], obviously.
- * @return Inverse erf.
+ * @param x The value.
+ * @param mu The mean.
+ * @param sigma The standard deviation.
+ * @return PDF of the given normal distribution at x.
*/
- public static double standardNormalQuantile(double d) {
- if(d == 0) {
- return Double.NEGATIVE_INFINITY;
- }
- else if(d == 1) {
- return Double.POSITIVE_INFINITY;
- }
- else if(Double.isNaN(d) || d < 0 || d > 1) {
- return Double.NaN;
- }
- else if(d < P_LOW) {
- // Rational approximation for lower region:
- double q = Math.sqrt(-2 * Math.log(d));
- return (((((ERFINV_C[0] * q + ERFINV_C[1]) * q + ERFINV_C[2]) * q + ERFINV_C[3]) * q + ERFINV_C[4]) * q + ERFINV_C[5]) / ((((ERFINV_D[0] * q + ERFINV_D[1]) * q + ERFINV_D[2]) * q + ERFINV_D[3]) * q + 1);
- }
- else if(P_HIGH < d) {
- // Rational approximation for upper region:
- double q = Math.sqrt(-2 * Math.log(1 - d));
- return -(((((ERFINV_C[0] * q + ERFINV_C[1]) * q + ERFINV_C[2]) * q + ERFINV_C[3]) * q + ERFINV_C[4]) * q + ERFINV_C[5]) / ((((ERFINV_D[0] * q + ERFINV_D[1]) * q + ERFINV_D[2]) * q + ERFINV_D[3]) * q + 1);
- }
- else {
- // Rational approximation for central region:
- double q = d - 0.5D;
- double r = q * q;
- return (((((ERFINV_A[0] * r + ERFINV_A[1]) * r + ERFINV_A[2]) * r + ERFINV_A[3]) * r + ERFINV_A[4]) * r + ERFINV_A[5]) * q / (((((ERFINV_B[0] * r + ERFINV_B[1]) * r + ERFINV_B[2]) * r + ERFINV_B[3]) * r + ERFINV_B[4]) * r + 1);
- }
+ public static double pdf(double x, double mu, double sigma) {
+ x = (x - mu) / sigma;
+ return MathUtil.ONE_BY_SQRTTWOPI / sigma * Math.exp(-.5 * x * x);
}
/**
@@ -308,14 +289,10 @@ public class NormalDistribution implements DistributionWithRandom {
* </pre>
*
* @param x The value.
- * @param mu The mean.
- * @param sigma The standard deviation.
* @return PDF of the given normal distribution at x.
*/
- public static double pdf(double x, double mu, double sigma) {
- final double x_mu = x - mu;
- final double sigmasq = sigma * sigma;
- return 1 / (Math.sqrt(MathUtil.TWOPI * sigmasq)) * Math.exp(-.5 * x_mu * x_mu / sigmasq);
+ public static double standardNormalPDF(double x) {
+ return Math.exp(-.5 * x * x) * MathUtil.SQRTHALF;
}
/**
@@ -324,10 +301,21 @@ public class NormalDistribution implements DistributionWithRandom {
* @param x value to evaluate CDF at
* @param mu Mean value
* @param sigma Standard deviation.
- * @return The CDF of the normal given distribution at x.
+ * @return The CDF of the given normal distribution at x.
*/
public static double cdf(double x, double mu, double sigma) {
- return .5 * (1 + erf((x - mu) / (MathUtil.SQRT2 * sigma)));
+ x = (x - mu) / sigma;
+ return .5 + .5 * erf(x * MathUtil.SQRTHALF);
+ }
+
+ /**
+ * Cumulative probability density function (CDF) of a normal distribution.
+ *
+ * @param x value to evaluate CDF at
+ * @return The CDF of the given normal distribution at x.
+ */
+ public static double standardNormalCDF(double x) {
+ return .5 + .5 * erf(x * MathUtil.SQRTHALF);
}
/**
@@ -337,9 +325,47 @@ public class NormalDistribution implements DistributionWithRandom {
* @param x value to evaluate probit function at
* @param mu Mean value
* @param sigma Standard deviation.
- * @return The probit of the normal given distribution at x.
+ * @return The probit of the given normal distribution at x.
*/
public static double quantile(double x, double mu, double sigma) {
return mu + sigma * standardNormalQuantile(x);
}
+
+ /**
+ * Approximate the inverse error function for normal distributions.
+ *
+ * Largely based on:
+ * <p>
+ * http://www.math.uio.no/~jacklam/notes/invnorm/index.html <br>
+ * by Peter John Acklam
+ * </p>
+ *
+ * FIXME: precision of this seems to be rather low, compared to our other
+ * functions. Only about 8-9 digits agree with SciPy/GNU R.
+ *
+ * @param d Quantile. Must be in [0:1], obviously.
+ * @return Inverse erf.
+ */
+ public static double standardNormalQuantile(double d) {
+ if (d == 0) {
+ return Double.NEGATIVE_INFINITY;
+ } else if (d == 1) {
+ return Double.POSITIVE_INFINITY;
+ } else if (Double.isNaN(d) || d < 0 || d > 1) {
+ return Double.NaN;
+ } else if (d < P_LOW) {
+ // Rational approximation for lower region:
+ double q = Math.sqrt(-2 * Math.log(d));
+ return (((((ERFINV_C[0] * q + ERFINV_C[1]) * q + ERFINV_C[2]) * q + ERFINV_C[3]) * q + ERFINV_C[4]) * q + ERFINV_C[5]) / ((((ERFINV_D[0] * q + ERFINV_D[1]) * q + ERFINV_D[2]) * q + ERFINV_D[3]) * q + 1);
+ } else if (P_HIGH < d) {
+ // Rational approximation for upper region:
+ double q = Math.sqrt(-2 * Math.log(1 - d));
+ return -(((((ERFINV_C[0] * q + ERFINV_C[1]) * q + ERFINV_C[2]) * q + ERFINV_C[3]) * q + ERFINV_C[4]) * q + ERFINV_C[5]) / ((((ERFINV_D[0] * q + ERFINV_D[1]) * q + ERFINV_D[2]) * q + ERFINV_D[3]) * q + 1);
+ } else {
+ // Rational approximation for central region:
+ double q = d - 0.5D;
+ double r = q * q;
+ return (((((ERFINV_A[0] * r + ERFINV_A[1]) * r + ERFINV_A[2]) * r + ERFINV_A[3]) * r + ERFINV_A[4]) * r + ERFINV_A[5]) * q / (((((ERFINV_B[0] * r + ERFINV_B[1]) * r + ERFINV_B[2]) * r + ERFINV_B[3]) * r + ERFINV_B[4]) * r + 1);
+ }
+ }
}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/PoissonDistribution.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/PoissonDistribution.java
index a4ea9402..f6b2e0ca 100644
--- a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/PoissonDistribution.java
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/PoissonDistribution.java
@@ -1,15 +1,10 @@
package de.lmu.ifi.dbs.elki.math.statistics.distribution;
-import de.lmu.ifi.dbs.elki.math.MathUtil;
-import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
-import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
-import de.lmu.ifi.dbs.elki.utilities.exceptions.ExceptionMessages;
-
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,6 +22,10 @@ import de.lmu.ifi.dbs.elki.utilities.exceptions.ExceptionMessages;
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.ExceptionMessages;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.NotImplementedException;
/**
* INCOMPLETE implementation of the poisson distribution.
@@ -129,30 +128,28 @@ public class PoissonDistribution implements Distribution {
@Reference(title = "Fast and accurate computation of binomial probabilities", authors = "C. Loader", booktitle = "", url = "http://projects.scipy.org/scipy/raw-attachment/ticket/620/loader2000Fast.pdf")
public double pmf(int x) {
// Invalid values
- if(x < 0 || x > n) {
+ if (x < 0 || x > n) {
return 0.0;
}
// Extreme probabilities
- if(p <= 0d) {
+ if (p <= 0d) {
return x == 0 ? 1.0 : 0.0;
}
- if(p >= 1d) {
+ if (p >= 1d) {
return x == n ? 1.0 : 0.0;
}
// Extreme values of x
- if(x == 0) {
- if(p < 0.1) {
+ if (x == 0) {
+ if (p < 0.1) {
return Math.exp(-devianceTerm(n, n * (1.0 - p)) - n * p);
- }
- else {
+ } else {
return Math.exp(n * Math.log(1.0 - p));
}
}
- if(x == n) {
- if(p > 0.9) {
+ if (x == n) {
+ if (p > 0.9) {
return Math.exp(-devianceTerm(n, n * p) - n * (1 - p));
- }
- else {
+ } else {
return Math.exp(n * Math.log(p));
}
}
@@ -166,33 +163,31 @@ public class PoissonDistribution implements Distribution {
@Reference(title = "Fast and accurate computation of binomial probabilities", authors = "C. Loader", booktitle = "", url = "http://projects.scipy.org/scipy/raw-attachment/ticket/620/loader2000Fast.pdf")
public double pdf(double x) {
// Invalid values
- if(x < 0 || x > n) {
+ if (x < 0 || x > n) {
return 0.0;
}
// Extreme probabilities
- if(p <= 0d) {
+ if (p <= 0d) {
return x == 0 ? 1.0 : 0.0;
}
- if(p >= 1d) {
+ if (p >= 1d) {
return x == n ? 1.0 : 0.0;
}
final double q = 1 - p;
// FIXME: check for x to be integer, return 0 otherwise?
// Extreme values of x
- if(x == 0) {
- if(p < 0.1) {
+ if (x == 0) {
+ if (p < 0.1) {
return Math.exp(-devianceTerm(n, n * q) - n * p);
- }
- else {
+ } else {
return Math.exp(n * Math.log(q));
}
}
- if(x == n) {
- if(p > 0.9) {
+ if (x == n) {
+ if (p > 0.9) {
return Math.exp(-devianceTerm(n, n * p) - n * q);
- }
- else {
+ } else {
return Math.exp(n * Math.log(p));
}
}
@@ -204,13 +199,19 @@ public class PoissonDistribution implements Distribution {
// FIXME: implement!
@Override
public double cdf(double val) {
- throw new AbortException(ExceptionMessages.UNSUPPORTED_NOT_YET);
+ throw new NotImplementedException(ExceptionMessages.UNSUPPORTED_NOT_YET);
}
// FIXME: implement!
@Override
public double quantile(double val) {
- throw new AbortException(ExceptionMessages.UNSUPPORTED_NOT_YET);
+ throw new NotImplementedException(ExceptionMessages.UNSUPPORTED_NOT_YET);
+ }
+
+ // FIXME: implement!
+ @Override
+ public double nextRandom() {
+ throw new NotImplementedException(ExceptionMessages.UNSUPPORTED_NOT_YET);
}
/**
@@ -223,16 +224,15 @@ public class PoissonDistribution implements Distribution {
* @return pdf
*/
public static double poissonPDFm1(double x_plus_1, double lambda) {
- if(Double.isInfinite(lambda)) {
+ if (Double.isInfinite(lambda)) {
return 0.;
}
- if(x_plus_1 > 1) {
+ if (x_plus_1 > 1) {
return rawProbability(x_plus_1 - 1, lambda);
}
- if(lambda > Math.abs(x_plus_1 - 1) * MathUtil.LOG2 * Double.MAX_EXPONENT / 1e-14) {
+ if (lambda > Math.abs(x_plus_1 - 1) * MathUtil.LOG2 * Double.MAX_EXPONENT / 1e-14) {
return Math.exp(-lambda - GammaDistribution.logGamma(x_plus_1));
- }
- else {
+ } else {
return rawProbability(x_plus_1, lambda) * (x_plus_1 / lambda);
}
}
@@ -247,16 +247,15 @@ public class PoissonDistribution implements Distribution {
* @return pdf
*/
public static double logpoissonPDFm1(double x_plus_1, double lambda) {
- if(Double.isInfinite(lambda)) {
+ if (Double.isInfinite(lambda)) {
return Double.NEGATIVE_INFINITY;
}
- if(x_plus_1 > 1) {
+ if (x_plus_1 > 1) {
return rawLogProbability(x_plus_1 - 1, lambda);
}
- if(lambda > Math.abs(x_plus_1 - 1) * MathUtil.LOG2 * Double.MAX_EXPONENT / 1e-14) {
+ if (lambda > Math.abs(x_plus_1 - 1) * MathUtil.LOG2 * Double.MAX_EXPONENT / 1e-14) {
return -lambda - GammaDistribution.logGamma(x_plus_1);
- }
- else {
+ } else {
return rawLogProbability(x_plus_1, lambda) + Math.log(x_plus_1 / lambda);
}
}
@@ -272,18 +271,18 @@ public class PoissonDistribution implements Distribution {
@Reference(title = "Fast and accurate computation of binomial probabilities", authors = "C. Loader", booktitle = "", url = "http://projects.scipy.org/scipy/raw-attachment/ticket/620/loader2000Fast.pdf")
private static double stirlingError(int n) {
// Try to use a table value:
- if(n < 16) {
+ if (n < 16) {
return STIRLING_EXACT_ERROR[n << 1];
}
final double nn = n * n;
// Use the appropriate number of terms
- if(n > 500) {
+ if (n > 500) {
return (S0 - S1 / nn) / n;
}
- if(n > 80) {
+ if (n > 80) {
return ((S0 - (S1 - S2 / nn)) / nn) / n;
}
- if(n > 35) {
+ if (n > 35) {
return ((S0 - (S1 - (S2 - S3 / nn) / nn) / nn) / n);
}
return ((S0 - (S1 - (S2 - (S3 - S4 / nn) / nn) / nn) / nn) / n);
@@ -299,24 +298,23 @@ public class PoissonDistribution implements Distribution {
*/
@Reference(title = "Fast and accurate computation of binomial probabilities", authors = "C. Loader", booktitle = "", url = "http://projects.scipy.org/scipy/raw-attachment/ticket/620/loader2000Fast.pdf")
private static double stirlingError(double n) {
- if(n < 16.0) {
+ if (n < 16.0) {
// Our table has a step size of 0.5
final double n2 = 2.0 * n;
- if(Math.floor(n2) == n2) { // Exact match
+ if (Math.floor(n2) == n2) { // Exact match
return STIRLING_EXACT_ERROR[(int) n2];
- }
- else {
+ } else {
return GammaDistribution.logGamma(n + 1.0) - (n + 0.5) * Math.log(n) + n - MathUtil.LOGSQRTTWOPI;
}
}
final double nn = n * n;
- if(n > 500.0) {
+ if (n > 500.0) {
return (S0 - S1 / nn) / n;
}
- if(n > 80.0) {
+ if (n > 80.0) {
return ((S0 - (S1 - S2 / nn)) / nn) / n;
}
- if(n > 35.0) {
+ if (n > 35.0) {
return ((S0 - (S1 - (S2 - S3 / nn) / nn) / nn) / n);
}
return ((S0 - (S1 - (S2 - (S3 - S4 / nn) / nn) / nn) / nn) / n);
@@ -333,15 +331,15 @@ public class PoissonDistribution implements Distribution {
*/
@Reference(title = "Fast and accurate computation of binomial probabilities", authors = "C. Loader", booktitle = "", url = "http://projects.scipy.org/scipy/raw-attachment/ticket/620/loader2000Fast.pdf")
private static double devianceTerm(double x, double np) {
- if(Math.abs(x - np) < 0.1 * (x + np)) {
+ if (Math.abs(x - np) < 0.1 * (x + np)) {
final double v = (x - np) / (x + np);
double s = (x - np) * v;
double ej = 2.0d * x * v;
- for(int j = 1;; j++) {
+ for (int j = 1;; j++) {
ej *= v * v;
final double s1 = s + ej / (2 * j + 1);
- if(s1 == s) {
+ if (s1 == s) {
return s1;
}
s = s1;
@@ -361,17 +359,17 @@ public class PoissonDistribution implements Distribution {
*/
public static double rawProbability(double x, double lambda) {
// Extreme lambda
- if(lambda == 0) {
+ if (lambda == 0) {
return ((x == 0) ? 1. : 0.);
}
// Extreme values
- if(Double.isInfinite(lambda) || x < 0) {
+ if (Double.isInfinite(lambda) || x < 0) {
return 0.;
}
- if(x <= lambda * Double.MIN_NORMAL) {
+ if (x <= lambda * Double.MIN_NORMAL) {
return Math.exp(-lambda);
}
- if(lambda < x * Double.MIN_NORMAL) {
+ if (lambda < x * Double.MIN_NORMAL) {
double r = -lambda + x * Math.log(lambda) - GammaDistribution.logGamma(x + 1);
return Math.exp(r);
}
@@ -391,21 +389,26 @@ public class PoissonDistribution implements Distribution {
*/
public static double rawLogProbability(double x, double lambda) {
// Extreme lambda
- if(lambda == 0) {
+ if (lambda == 0) {
return ((x == 0) ? 1. : Double.NEGATIVE_INFINITY);
}
// Extreme values
- if(Double.isInfinite(lambda) || x < 0) {
+ if (Double.isInfinite(lambda) || x < 0) {
return Double.NEGATIVE_INFINITY;
}
- if(x <= lambda * Double.MIN_NORMAL) {
+ if (x <= lambda * Double.MIN_NORMAL) {
return -lambda;
}
- if(lambda < x * Double.MIN_NORMAL) {
+ if (lambda < x * Double.MIN_NORMAL) {
return -lambda + x * Math.log(lambda) - GammaDistribution.logGamma(x + 1);
}
final double f = MathUtil.TWOPI * x;
final double y = -stirlingError(x) - devianceTerm(x, lambda);
return -0.5 * Math.log(f) + y;
}
-} \ No newline at end of file
+
+ @Override
+ public String toString() {
+ return "PoissonDistribution(n=" + n + ", p=" + p + ")";
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/RayleighDistribution.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/RayleighDistribution.java
new file mode 100644
index 00000000..31faf8ed
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/RayleighDistribution.java
@@ -0,0 +1,165 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.Random;
+
+/**
+ * Rayleigh distribution.
+ *
+ * @author Erich Schubert
+ */
+public class RayleighDistribution implements Distribution {
+ /**
+ * Position parameter.
+ */
+ double mu = 0.0;
+
+ /**
+ * Scale parameter.
+ */
+ double sigma;
+
+ /**
+ * Random number generator.
+ */
+ Random random;
+
+ /**
+ * Constructor.
+ *
+ * @param sigma Scale parameter
+ */
+ public RayleighDistribution(double sigma) {
+ this(0., sigma, null);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param mu Position parameter
+ * @param sigma Scale parameter
+ */
+ public RayleighDistribution(double mu, double sigma) {
+ this(mu, sigma, null);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param sigma Scale parameter
+ * @param random Random number generator
+ */
+ public RayleighDistribution(double sigma, Random random) {
+ this(0., sigma, random);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param mu Position parameter
+ * @param sigma Scale parameter
+ * @param random Random number generator
+ */
+ public RayleighDistribution(double mu, double sigma, Random random) {
+ super();
+ this.mu = mu;
+ this.sigma = sigma;
+ this.random = random;
+ }
+
+ @Override
+ public double pdf(double x) {
+ return pdf(x - mu, sigma);
+ }
+
+ /**
+ * PDF of Rayleigh distribution
+ *
+ * @param x Value
+ * @param sigma Scale
+ * @return PDF at position x.
+ */
+ public static double pdf(double x, double sigma) {
+ if (x <= 0.) {
+ return 0.;
+ }
+ final double xs = x / sigma;
+ return xs / sigma * Math.exp(-.5 * xs * xs);
+ }
+
+ @Override
+ public double cdf(double val) {
+ return cdf(val - mu, sigma);
+ }
+
+ /**
+ * CDF of Rayleigh distribution
+ *
+ * @param x Value
+ * @param sigma Scale parameter
+ * @return CDF at position x.
+ */
+ public static double cdf(double x, double sigma) {
+ if (x <= 0.) {
+ return 0.;
+ }
+ final double xs = x / sigma;
+ return 1. - Math.exp(-.5 * xs * xs);
+ }
+
+ @Override
+ public double quantile(double val) {
+ return mu + quantile(val, sigma);
+ }
+
+ /**
+ * Quantile function of Rayleigh distribution
+ *
+ * @param val Value
+ * @param sigma Scale parameter
+ * @return Quantile function at position x.
+ */
+ public static double quantile(double val, double sigma) {
+ if (!(val >= 0.) || !(val <= 1.)) {
+ return Double.NaN;
+ } else if (val == 0.) {
+ return 0.;
+ } else if (val == 1.) {
+ return Double.POSITIVE_INFINITY;
+ } else {
+ return sigma * Math.sqrt(-2. * Math.log(val));
+ }
+ }
+
+ @Override
+ public double nextRandom() {
+ return mu + sigma * Math.sqrt(-2. * Math.log(random.nextDouble()));
+ }
+
+ @Override
+ public String toString() {
+ return "RayleighDistribution(mu=" + mu + ", sigma=" + sigma + ")";
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/SkewGeneralizedNormalDistribution.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/SkewGeneralizedNormalDistribution.java
new file mode 100644
index 00000000..f04e776b
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/SkewGeneralizedNormalDistribution.java
@@ -0,0 +1,169 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.Random;
+
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+
+/**
+ * Generalized Gaussian distribution by adding a skew term, similar to lognormal
+ * distributions.
+ *
+ * This is one kind of generalized normal distributions. Note that there are
+ * multiple that go by the name of a "Generalized Normal Distribution".
+ *
+ * @author Erich Schubert
+ */
+public class SkewGeneralizedNormalDistribution implements Distribution {
+ /**
+ * Mean value for the generator
+ */
+ private double mean;
+
+ /**
+ * Standard deviation
+ */
+ private double stddev;
+
+ /**
+ * Skew.
+ */
+ private double skew;
+
+ /**
+ * The random generator.
+ */
+ private Random random;
+
+ /**
+ * Constructor for Gaussian distribution
+ *
+ * @param mean Mean
+ * @param stddev Standard Deviation
+ * @param skew Skew
+ * @param random Random generator
+ */
+ public SkewGeneralizedNormalDistribution(double mean, double stddev, double skew, Random random) {
+ super();
+ this.mean = mean;
+ this.stddev = stddev;
+ this.skew = skew;
+ this.random = random;
+ }
+
+ /**
+ * Constructor for Gaussian distribution
+ *
+ * @param mean Mean
+ * @param stddev Standard Deviation
+ * @param skew Skew
+ */
+ public SkewGeneralizedNormalDistribution(double mean, double stddev, double skew) {
+ this(mean, stddev, skew, null);
+ }
+
+ @Override
+ public double pdf(double val) {
+ return pdf(val, mean, stddev, skew);
+ }
+
+ @Override
+ public double cdf(double val) {
+ return cdf(val, mean, stddev, skew);
+ }
+
+ @Override
+ public double quantile(double q) {
+ return quantile(q, mean, stddev, skew);
+ }
+
+ @Override
+ public double nextRandom() {
+ double y = random.nextGaussian();
+ if (Math.abs(skew) > 0.) {
+ y = (1. - Math.exp(-skew * y)) / skew;
+ }
+ return mean + stddev * y;
+
+ }
+
+ @Override
+ public String toString() {
+ return "SkewNormalDistribution(mean=" + mean + ", stddev=" + stddev + ", skew=" + skew + ")";
+ }
+
+ /**
+ * Probability density function of the skewed normal distribution.
+ *
+ * @param x The value.
+ * @param mu The mean.
+ * @param sigma The standard deviation.
+ * @return PDF of the given normal distribution at x.
+ */
+ public static double pdf(double x, double mu, double sigma, double skew) {
+ x = (x - mu) / sigma;
+ if (Math.abs(skew) > 0.) {
+ x = -Math.log(1. - skew * x) / skew;
+ }
+ return MathUtil.SQRTHALF * Math.exp(-.5 * x * x) / sigma / (1 - skew * x);
+ }
+
+ /**
+ * Cumulative probability density function (CDF) of a normal distribution.
+ *
+ * @param x value to evaluate CDF at
+ * @param mu Mean value
+ * @param sigma Standard deviation.
+ * @return The CDF of the given normal distribution at x.
+ */
+ public static double cdf(double x, double mu, double sigma, double skew) {
+ x = (x - mu) / sigma;
+ if (Math.abs(skew) > 0.) {
+ double tmp = 1 - skew * x;
+ if (tmp < 1e-15) {
+ return (skew < 0.) ? 0. : 1.;
+ }
+ x = -Math.log(tmp) / skew;
+ }
+ return .5 + .5 * NormalDistribution.erf(x * MathUtil.SQRTHALF);
+ }
+
+ /**
+ * Inverse cumulative probability density function (probit) of a normal
+ * distribution.
+ *
+ * @param x value to evaluate probit function at
+ * @param mu Mean value
+ * @param sigma Standard deviation.
+ * @return The probit of the given normal distribution at x.
+ */
+ public static double quantile(double x, double mu, double sigma, double skew) {
+ x = NormalDistribution.standardNormalQuantile(x);
+ if (Math.abs(skew) > 0.) {
+ x = (1. - Math.exp(-skew * x)) / skew;
+ }
+ return mu + sigma * x;
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/StudentsTDistribution.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/StudentsTDistribution.java
index fcb96c12..442df2e2 100644
--- a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/StudentsTDistribution.java
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/StudentsTDistribution.java
@@ -23,8 +23,8 @@ package de.lmu.ifi.dbs.elki.math.statistics.distribution;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
import de.lmu.ifi.dbs.elki.utilities.exceptions.ExceptionMessages;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.NotImplementedException;
/**
* Student's t distribution.
@@ -61,7 +61,13 @@ public class StudentsTDistribution implements Distribution {
// FIXME: implement!
@Override
public double quantile(double val) {
- throw new AbortException(ExceptionMessages.UNSUPPORTED_NOT_YET);
+ throw new NotImplementedException(ExceptionMessages.UNSUPPORTED_NOT_YET);
+ }
+
+ // FIXME: implement!
+ @Override
+ public double nextRandom() {
+ throw new NotImplementedException(ExceptionMessages.UNSUPPORTED_NOT_YET);
}
/**
@@ -87,4 +93,9 @@ public class StudentsTDistribution implements Distribution {
double x = v / (val * val + v);
return 1 - (0.5 * BetaDistribution.regularizedIncBeta(x, v * .5, 0.5));
}
-} \ No newline at end of file
+
+ @Override
+ public String toString() {
+ return "StudentsTDistribution(v=" + v + ")";
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/UniformDistribution.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/UniformDistribution.java
index 4f54fbf9..efae5080 100644
--- a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/UniformDistribution.java
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/UniformDistribution.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.math.statistics.distribution;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -30,7 +30,7 @@ import java.util.Random;
*
* @author Erich Schubert
*/
-public class UniformDistribution implements DistributionWithRandom {
+public class UniformDistribution implements Distribution {
/**
* Minimum
*/
@@ -60,8 +60,14 @@ public class UniformDistribution implements DistributionWithRandom {
*/
public UniformDistribution(double min, double max, Random random) {
super();
+ if (Double.isInfinite(min) || Double.isInfinite(max)) {
+ throw new ArithmeticException("Infinite values given for uniform distribution.");
+ }
+ if (Double.isNaN(min) || Double.isNaN(max)) {
+ throw new ArithmeticException("NaN values given for uniform distribution.");
+ }
// Swap parameters if they were given incorrectly.
- if(min > max) {
+ if (min > max) {
double tmp = min;
min = max;
max = tmp;
@@ -79,31 +85,31 @@ public class UniformDistribution implements DistributionWithRandom {
* @param max Maximum value
*/
public UniformDistribution(double min, double max) {
- this(min, max, new Random());
+ this(min, max, null);
}
@Override
public double pdf(double val) {
- if(val < min || val >= max) {
+ if (!(val >= min) || val >= max) {
return 0.0;
}
- return 1.0 / len;
+ return (len > 0.) ? 1.0 / len : Double.POSITIVE_INFINITY;
}
@Override
public double cdf(double val) {
- if(val < min) {
- return 0.0;
+ if (!(val > min)) {
+ return 0.;
}
- if(val > max) {
- return 1.0;
+ if (val >= max) {
+ return 1.;
}
- return (val - min) / len;
+ return (len > 0.) ? (val - min) / len : .5;
}
-
+
@Override
public double quantile(double val) {
- return min + len * val;
+ return min + len * val;
}
@Override
@@ -129,4 +135,4 @@ public class UniformDistribution implements DistributionWithRandom {
public double getMax() {
return max;
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/WaldDistribution.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/WaldDistribution.java
new file mode 100644
index 00000000..ec0ea712
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/WaldDistribution.java
@@ -0,0 +1,173 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.Random;
+
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.ExceptionMessages;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.NotImplementedException;
+
+/**
+ * Inverse Gaussian distribution aka Wald distribution
+ *
+ * @author Erich Schubert
+ */
+@Alias({ "InverseGaussianDistribution", "invgauss" })
+public class WaldDistribution implements Distribution {
+ /**
+ * Mean value
+ */
+ private double mean;
+
+ /**
+ * Shape parameter
+ */
+ private double shape;
+
+ /**
+ * The random generator.
+ */
+ private Random random;
+
+ /**
+ * Constructor for wald distribution
+ *
+ * @param mean Mean
+ * @param shape Shape parameter
+ * @param random Random generator
+ */
+ public WaldDistribution(double mean, double shape, Random random) {
+ super();
+ this.mean = mean;
+ this.shape = shape;
+ this.random = random;
+ }
+
+ /**
+ * Constructor for Gaussian distribution
+ *
+ * @param mean Mean
+ * @param shape Shape parameter
+ */
+ public WaldDistribution(double mean, double shape) {
+ this(mean, shape, null);
+ }
+
+ @Override
+ public double pdf(double val) {
+ return pdf(val, mean, shape);
+ }
+
+ @Override
+ public double cdf(double val) {
+ return cdf(val, mean, shape);
+ }
+
+ /**
+ * @deprecated NOT YET IMPLEMENTED.
+ */
+ @Override
+ @Deprecated
+ public double quantile(double q) {
+ return quantile(q, mean, shape);
+ }
+
+ @Override
+ public double nextRandom() {
+ double v = random.nextGaussian();
+ v *= v;
+ double x = mean + mean * .5 / shape * (mean * v - Math.sqrt(4. * mean * shape * v + mean * mean * v * v));
+ double u = random.nextDouble();
+ if (u * (mean + x) <= mean) {
+ return x;
+ } else {
+ return mean * mean / x;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "WaldDistribution(mean=" + mean + ", shape=" + shape + ")";
+ }
+
+ /**
+ * Probability density function of the Wald distribution.
+ *
+ *
+ * @param x The value.
+ * @param mu The mean.
+ * @param shape Shape parameter
+ * @return PDF of the given Wald distribution at x.
+ */
+ public static double pdf(double x, double mu, double shape) {
+ if (!(x > 0)) {
+ return 0;
+ }
+ final double v = (x - mu);
+ return Math.sqrt(shape / (MathUtil.TWOPI * x * x * x)) * Math.exp(-shape * v * v / (2. * mu * mu * x));
+ }
+
+ /**
+ * Cumulative probability density function (CDF) of a Wald distribution.
+ *
+ * @param x value to evaluate CDF at
+ * @param mu Mean value
+ * @param shape Shape parameter
+ * @return The CDF of the given Wald distribution at x.
+ */
+ public static double cdf(double x, double mu, double shape) {
+ if (!(x > 0.)) {
+ return 0.;
+ }
+ // TODO: accelerate by caching exp(2 * shape / mu).
+ final double v0 = x / mu;
+ final double v1 = Math.sqrt(shape / x);
+ double c1 = NormalDistribution.standardNormalCDF(v1 * (v0 - 1.));
+ double c2 = NormalDistribution.standardNormalCDF(-v1 * (v0 + 1.));
+ if (c2 > 0.) {
+ return c1 + Math.exp(2 * shape / mu) * c2;
+ } else {
+ return c1;
+ }
+ }
+
+ /**
+ * Inverse cumulative probability density function (probit) of a Wald
+ * distribution.
+ *
+ * @param x value to evaluate probit function at
+ * @param mu Mean value
+ * @param shape Shape parameter
+ * @return The probit of the given Wald distribution at x.
+ *
+ * @deprecated NOT YET IMPLEMENTED.
+ */
+ @Deprecated
+ public static double quantile(double x, double mu, double shape) {
+ // FIXME: implement!
+ throw new NotImplementedException(ExceptionMessages.UNSUPPORTED_NOT_YET);
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/WeibullDistribution.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/WeibullDistribution.java
new file mode 100644
index 00000000..165f536a
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/WeibullDistribution.java
@@ -0,0 +1,182 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.Random;
+
+/**
+ * Weibull distribution.
+ *
+ * @author Erich Schubert
+ */
+public class WeibullDistribution implements Distribution {
+ /**
+ * Shift offset.
+ */
+ double theta = 0.0;
+
+ /**
+ * Shape parameter k.
+ */
+ double k;
+
+ /**
+ * Lambda parameter.
+ */
+ double lambda;
+
+ /**
+ * Random number generator.
+ */
+ Random random;
+
+ /**
+ * Constructor.
+ *
+ * @param k Shape parameter
+ * @param lambda Scale parameter
+ */
+ public WeibullDistribution(double k, double lambda) {
+ this(k, lambda, 0.0, null);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param k Shape parameter
+ * @param lambda Scale parameter
+ * @param theta Shift offset parameter
+ */
+ public WeibullDistribution(double k, double lambda, double theta) {
+ this(k, lambda, theta, null);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param k Shape parameter
+ * @param lambda Scale parameter
+ * @param random Random number generator
+ */
+ public WeibullDistribution(double k, double lambda, Random random) {
+ this(k, lambda, 0.0, random);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param k Shape parameter
+ * @param lambda Scale parameter
+ * @param theta Shift offset parameter
+ * @param random Random number generator
+ */
+ public WeibullDistribution(double k, double lambda, double theta, Random random) {
+ super();
+ this.k = k;
+ this.lambda = lambda;
+ this.theta = theta;
+ this.random = random;
+ }
+
+ @Override
+ public double pdf(double x) {
+ return pdf(x, k, lambda, theta);
+ }
+
+ /**
+ * PDF of Weibull distribution
+ *
+ * @param x Value
+ * @param k Shape parameter
+ * @param lambda Scale parameter
+ * @param theta Shift offset parameter
+ * @return PDF at position x.
+ */
+ public static double pdf(double x, double k, double lambda, double theta) {
+ if (x > theta) {
+ double xl = (x - theta) / lambda;
+ return k / lambda * Math.pow(xl, k - 1) * Math.exp(-Math.pow(xl, k));
+ } else {
+ return 0.;
+ }
+ }
+
+ /**
+ * CDF of Weibull distribution
+ *
+ * @param val Value
+ * @param k Shape parameter
+ * @param lambda Scale parameter
+ * @param theta Shift offset parameter
+ * @return CDF at position x.
+ */
+ public static double cdf(double val, double k, double lambda, double theta) {
+ if (val > theta) {
+ return 1.0 - Math.exp(-Math.pow((val - theta) / lambda, k));
+ } else {
+ return 0.0;
+ }
+ }
+
+ @Override
+ public double cdf(double val) {
+ return cdf(val, k, lambda, theta);
+ }
+
+ /**
+ * Quantile function of Weibull distribution
+ *
+ * @param val Value
+ * @param k Shape parameter
+ * @param lambda Scale parameter
+ * @param theta Shift offset parameter
+ * @return Quantile function at position x.
+ */
+ public static double quantile(double val, double k, double lambda, double theta) {
+ if (val < 0.0 || val > 1.0) {
+ return Double.NaN;
+ } else if (val == 0) {
+ return 0.0;
+ } else if (val == 1) {
+ return Double.POSITIVE_INFINITY;
+ } else {
+ return theta + lambda * Math.pow(-Math.log(1.0 - val), 1.0 / k);
+ }
+ }
+
+ @Override
+ public double quantile(double val) {
+ return quantile(val, k, lambda, theta);
+ }
+
+ @Override
+ public double nextRandom() {
+ return theta + lambda * Math.pow(-Math.log(1 - random.nextDouble()), 1. / k);
+ }
+
+ @Override
+ public String toString() {
+ return "WeibullDistribution(k=" + k + ", lambda=" + lambda + ", theta=" + theta + ")";
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/AbstractExpMADEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/AbstractExpMADEstimator.java
new file mode 100644
index 00000000..6f9dc541
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/AbstractExpMADEstimator.java
@@ -0,0 +1,96 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.Distribution;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.QuickSelect;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
+
+/**
+ * Abstract base class for estimators based on the median and MAD.
+ *
+ * @author Erich Schubert
+ *
+ * @param <D> Distribution to generate.
+ */
+public abstract class AbstractExpMADEstimator<D extends Distribution> implements ExpMADDistributionEstimator<D> {
+ /**
+ * Constructor.
+ */
+ public AbstractExpMADEstimator() {
+ super();
+ }
+
+ @Override
+ public abstract D estimateFromExpMedianMAD(double median, double mad);
+
+ @Override
+ public <A> D estimate(A data, NumberArrayAdapter<?, A> adapter) {
+ // TODO: detect pre-sorted data?
+ final int len = adapter.size(data);
+ // Modifiable copy:
+ double[] x = new double[len];
+ for (int i = 0; i < len; i++) {
+ x[i] = Math.exp(adapter.getDouble(data, i));
+ }
+ double median = QuickSelect.median(x);
+ double mad = computeMAD(x, median);
+ return estimateFromExpMedianMAD(median, mad);
+ }
+
+ /**
+ * Compute the median absolute deviation from median.
+ *
+ * @param x Input data <b>will be modified</b>
+ * @param median Median value.
+ * @return Median absolute deviation from median.
+ */
+ public static double computeMAD(double[] x, double median) {
+ // Compute deviations:
+ for (int i = 0; i < x.length; i++) {
+ x[i] = Math.abs(x[i] - median);
+ }
+ double mad = QuickSelect.median(x);
+ // Fallback if we have more than 50% ties to next largest.
+ if (!(mad > 0.)) {
+ double min = Double.POSITIVE_INFINITY;
+ for (double xi : x) {
+ if (xi > 0. && xi < min) {
+ min = xi;
+ }
+ }
+ if (min < Double.POSITIVE_INFINITY) {
+ mad = min;
+ } else {
+ mad = 1.0; // Maybe all constant. No real value.
+ }
+ }
+ return mad;
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/AbstractLMMEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/AbstractLMMEstimator.java
new file mode 100644
index 00000000..3d77a1e6
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/AbstractLMMEstimator.java
@@ -0,0 +1,71 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.Arrays;
+
+import de.lmu.ifi.dbs.elki.math.statistics.ProbabilityWeightedMoments;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.Distribution;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayLikeUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
+
+/**
+ * Abstract base class for L-Moments based estimators (LMM).
+ *
+ * @author Erich Schubert
+ *
+ * @param <D> Distribution class.
+ */
+public abstract class AbstractLMMEstimator<D extends Distribution> implements LMMDistributionEstimator<D> {
+ /**
+ * Constructor.
+ */
+ public AbstractLMMEstimator() {
+ super();
+ }
+
+ @Override
+ public <A> D estimate(A data, NumberArrayAdapter<?, A> adapter) {
+ // Sort:
+ final int size = adapter.size(data);
+ double[] sorted = new double[size];
+ for (int i = 0; i < size; i++) {
+ sorted[i] = adapter.getDouble(data, i);
+ }
+ Arrays.sort(sorted);
+ double[] xmom = ProbabilityWeightedMoments.samLMR(sorted, ArrayLikeUtil.DOUBLEARRAYADAPTER, getNumMoments());
+ return estimateFromLMoments(xmom);
+ }
+
+ @Override
+ abstract public D estimateFromLMoments(double[] xmom);
+
+ @Override
+ abstract public int getNumMoments();
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/AbstractLogMADEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/AbstractLogMADEstimator.java
new file mode 100644
index 00000000..b4e4e095
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/AbstractLogMADEstimator.java
@@ -0,0 +1,101 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.Distribution;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.QuickSelect;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
+
+/**
+ * Abstract base class for estimators based on the median and MAD.
+ *
+ * @author Erich Schubert
+ *
+ * @param <D> Distribution to generate.
+ */
+public abstract class AbstractLogMADEstimator<D extends Distribution> implements LogMADDistributionEstimator<D> {
+ /**
+ * Constructor.
+ */
+ public AbstractLogMADEstimator() {
+ super();
+ }
+
+ @Override
+ public abstract D estimateFromLogMedianMAD(double median, double mad, double shift);
+
+ @Override
+ public <A> D estimate(A data, NumberArrayAdapter<?, A> adapter) {
+ // TODO: detect pre-sorted data?
+ final int len = adapter.size(data);
+ double min = AbstractLogMOMEstimator.min(data, adapter, 0., 1e-10);
+ // Modifiable copy:
+ double[] x = new double[len];
+ for (int i = 0; i < len; i++) {
+ final double val = adapter.getDouble(data, i) - min;
+ x[i] = val > 0. ? Math.log(val) : Double.NEGATIVE_INFINITY;
+ if (Double.isNaN(x[i])) {
+ throw new ArithmeticException("NaN value.");
+ }
+ }
+ double median = QuickSelect.median(x);
+ double mad = computeMAD(x, median);
+ return estimateFromLogMedianMAD(median, mad, min);
+ }
+
+ /**
+ * Compute the median absolute deviation from median.
+ *
+ * @param x Input data <b>will be modified</b>
+ * @param median Median value.
+ * @return Median absolute deviation from median.
+ */
+ public static double computeMAD(double[] x, double median) {
+ // Compute deviations:
+ for (int i = 0; i < x.length; i++) {
+ x[i] = Math.abs(x[i] - median);
+ }
+ double mad = QuickSelect.median(x);
+ // Fallback if we have more than 50% ties to next largest.
+ if (!(mad > 0.)) {
+ double min = Double.POSITIVE_INFINITY;
+ for (double xi : x) {
+ if (xi > 0. && xi < min) {
+ min = xi;
+ }
+ }
+ if (min < Double.POSITIVE_INFINITY) {
+ mad = min;
+ } else {
+ mad = 1.0; // Maybe all constant. No real value.
+ }
+ }
+ return mad;
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/AbstractLogMOMEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/AbstractLogMOMEstimator.java
new file mode 100644
index 00000000..8ae86d4a
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/AbstractLogMOMEstimator.java
@@ -0,0 +1,94 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.math.StatisticalMoments;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.Distribution;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
+
+/**
+ * Abstract base class for estimators based on the statistical moments.
+ *
+ * @author Erich Schubert
+ *
+ * @param <D> Distribution to generate.
+ */
+public abstract class AbstractLogMOMEstimator<D extends Distribution> implements LogMOMDistributionEstimator<D> {
+ /**
+ * Constructor.
+ */
+ public AbstractLogMOMEstimator() {
+ super();
+ }
+
+ @Override
+ public abstract D estimateFromLogStatisticalMoments(StatisticalMoments moments, double shift);
+
+ @Override
+ public <A> D estimate(A data, NumberArrayAdapter<?, A> adapter) {
+ final int len = adapter.size(data);
+ double min = AbstractLogMOMEstimator.min(data, adapter, 0., 1e-10);
+ StatisticalMoments mv = new StatisticalMoments();
+ for (int i = 0; i < len; i++) {
+ final double val = adapter.getDouble(data, i) - min;
+ if (Double.isInfinite(val) || Double.isNaN(val) || val <= 0.) {
+ continue;
+ }
+ mv.put(Math.log(val));
+ }
+ return estimateFromLogStatisticalMoments(mv, min);
+ }
+
+ /**
+ * Utility function to find minimum and maximum values.
+ *
+ * @param <A> array type
+ * @param data Data array
+ * @param adapter Array adapter
+ * @param minmin Minimum value for minimum.
+ * @return Minimum
+ */
+ public static <A> double min(A data, NumberArrayAdapter<?, A> adapter, double minmin, double margin) {
+ final int len = adapter.size(data);
+ double min = adapter.getDouble(data, 0), max = min;
+ for (int i = 1; i < len; i++) {
+ final double val = adapter.getDouble(data, i);
+ if (val < min) {
+ min = val;
+ } else if (val > max) {
+ max = val;
+ }
+ }
+ if (min > minmin) {
+ return minmin;
+ }
+ // Add some extra margin, to not have 0s.
+ return min - (max - min) * margin;
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/AbstractLogMeanVarianceEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/AbstractLogMeanVarianceEstimator.java
new file mode 100644
index 00000000..a21186db
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/AbstractLogMeanVarianceEstimator.java
@@ -0,0 +1,80 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.MeanVariance;
+import de.lmu.ifi.dbs.elki.math.StatisticalMoments;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.Distribution;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
+
+/**
+ * Estimators that work on Mean and Variance only (i.e. the first two moments
+ * only).
+ *
+ * @author Erich Schubert
+ *
+ * @param <D> Distribution to estimate.
+ */
+public abstract class AbstractLogMeanVarianceEstimator<D extends Distribution> extends AbstractLogMOMEstimator<D> {
+ /**
+ * Constructor.
+ */
+ public AbstractLogMeanVarianceEstimator() {
+ super();
+ }
+
+ @Override
+ public D estimateFromLogStatisticalMoments(StatisticalMoments moments, double shift) {
+ if (!(moments.getCount() > 1.)) {
+ throw new ArithmeticException("Too small sample size to estimate variance.");
+ }
+ return estimateFromLogMeanVariance(moments, shift);
+ }
+
+ /**
+ * Estimate the distribution from mean and variance.
+ *
+ * @param mv Mean and variance.
+ * @param shift Shift that was applied to avoid negative values.
+ * @return Distribution
+ */
+ public abstract D estimateFromLogMeanVariance(MeanVariance mv, double shift);
+
+ @Override
+ public <A> D estimate(A data, NumberArrayAdapter<?, A> adapter) {
+ final int len = adapter.size(data);
+ double min = AbstractLogMOMEstimator.min(data, adapter, 0., 1e-10);
+ MeanVariance mv = new MeanVariance();
+ for (int i = 0; i < len; i++) {
+ final double val = adapter.getDouble(data, i) - min;
+ if (Double.isInfinite(val) || Double.isNaN(val) || val <= 0.) {
+ continue;
+ }
+ mv.put(Math.log(val));
+ }
+ if (!(mv.getCount() > 1.)) {
+ throw new ArithmeticException("Too small sample size to estimate variance.");
+ }
+ return estimateFromLogMeanVariance(mv, min);
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/AbstractMADEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/AbstractMADEstimator.java
new file mode 100644
index 00000000..54009592
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/AbstractMADEstimator.java
@@ -0,0 +1,109 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.Distribution;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.QuickSelect;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
+
+/**
+ * Abstract base class for estimators based on the median and MAD.
+ *
+ * @author Erich Schubert
+ *
+ * @param <D> Distribution to generate.
+ */
+public abstract class AbstractMADEstimator<D extends Distribution> implements MADDistributionEstimator<D> {
+ /**
+ * Constructor.
+ */
+ public AbstractMADEstimator() {
+ super();
+ }
+
+ @Override
+ public abstract D estimateFromMedianMAD(double median, double mad);
+
+ @Override
+ public <A> D estimate(A data, NumberArrayAdapter<?, A> adapter) {
+ // TODO: detect pre-sorted data?
+ final int len = adapter.size(data);
+ // Modifiable copy:
+ double[] x = new double[len];
+ for (int i = 0; i < len; i++) {
+ x[i] = adapter.getDouble(data, i);
+ }
+ double median = QuickSelect.median(x);
+ double mad = computeMAD(x, median);
+ return estimateFromMedianMAD(median, mad);
+ }
+
+ /**
+ * Compute the median absolute deviation from median.
+ *
+ * @param x Input data <b>will be modified</b>
+ * @param median Median value.
+ * @return Median absolute deviation from median.
+ */
+ public static double computeMAD(double[] x, double median) {
+ // Compute deviations:
+ for (int i = 0; i < x.length; i++) {
+ x[i] = Math.abs(x[i] - median);
+ }
+ double mad = QuickSelect.median(x);
+ // Fallback if we have more than 50% ties to next largest.
+ if (!(mad > 0.)) {
+ double min = Double.POSITIVE_INFINITY;
+ for (double xi : x) {
+ if (xi > 0. && xi < min) {
+ min = xi;
+ }
+ }
+ if (min < Double.POSITIVE_INFINITY) {
+ mad = min;
+ } else {
+ mad = 1.0; // Maybe all constant. No real value.
+ }
+ }
+ if (mad == Double.POSITIVE_INFINITY) {
+ double max = 0.;
+ for (double xi : x) {
+ if (xi < Double.POSITIVE_INFINITY && xi > max) {
+ max = xi;
+ }
+ }
+ if (max < Double.POSITIVE_INFINITY) {
+ mad = max;
+ } else {
+ mad = 1.0; // No reasonable value. Give up.
+ }
+ }
+ return mad;
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/AbstractMOMEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/AbstractMOMEstimator.java
new file mode 100644
index 00000000..30bd0802
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/AbstractMOMEstimator.java
@@ -0,0 +1,66 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.math.StatisticalMoments;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.Distribution;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
+
+/**
+ * Abstract base class for estimators based on the statistical moments.
+ *
+ * @author Erich Schubert
+ *
+ * @param <D> Distribution to generate.
+ */
+public abstract class AbstractMOMEstimator<D extends Distribution> implements MOMDistributionEstimator<D> {
+ /**
+ * Constructor.
+ */
+ public AbstractMOMEstimator() {
+ super();
+ }
+
+ @Override
+ public abstract D estimateFromStatisticalMoments(StatisticalMoments moments);
+
+ @Override
+ public <A> D estimate(A data, NumberArrayAdapter<?, A> adapter) {
+ StatisticalMoments mv = new StatisticalMoments();
+ int size = adapter.size(data);
+ for (int i = 0; i < size; i++) {
+ final double val = adapter.getDouble(data, i);
+ if (Double.isInfinite(val) || Double.isNaN(val)) {
+ continue;
+ }
+ mv.put(val);
+ }
+ return estimateFromStatisticalMoments(mv);
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/AbstractMeanVarianceEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/AbstractMeanVarianceEstimator.java
new file mode 100644
index 00000000..73a2e6d2
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/AbstractMeanVarianceEstimator.java
@@ -0,0 +1,67 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.MeanVariance;
+import de.lmu.ifi.dbs.elki.math.StatisticalMoments;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.Distribution;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
+
+/**
+ * Estimators that work on Mean and Variance only (i.e. the first two moments
+ * only).
+ *
+ * @author Erich Schubert
+ *
+ * @param <D> Distribution to estimate.
+ */
+public abstract class AbstractMeanVarianceEstimator<D extends Distribution> extends AbstractMOMEstimator<D> implements MeanVarianceDistributionEstimator<D> {
+ /**
+ * Constructor.
+ */
+ public AbstractMeanVarianceEstimator() {
+ super();
+ }
+
+ @Override
+ public D estimateFromStatisticalMoments(StatisticalMoments moments) {
+ return estimateFromMeanVariance(moments);
+ }
+
+ @Override
+ public abstract D estimateFromMeanVariance(MeanVariance mv);
+
+ @Override
+ public <A> D estimate(A data, NumberArrayAdapter<?, A> adapter) {
+ MeanVariance mv = new MeanVariance();
+ int size = adapter.size(data);
+ for (int i = 0; i < size; i++) {
+ final double val = adapter.getDouble(data, i);
+ if (Double.isInfinite(val) || Double.isNaN(val)) {
+ continue;
+ }
+ mv.put(val);
+ }
+ return estimateFromMeanVariance(mv);
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/CauchyMADEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/CauchyMADEstimator.java
new file mode 100644
index 00000000..e1cfb20c
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/CauchyMADEstimator.java
@@ -0,0 +1,80 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.CauchyDistribution;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Estimate Cauchy distribution parameters using Median and MAD.
+ *
+ * Reference:
+ * <p>
+ * D. J. Olive<br />
+ * Applied Robust Statistics<br />
+ * Preprint of an upcoming book, University of Minnesota
+ * </p>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has CauchyDistribution
+ */
+@Reference(title = "Applied Robust Statistics", authors = "D. J. Olive", booktitle = "Applied Robust Statistics", url="http://lagrange.math.siu.edu/Olive/preprints.htm")
+public class CauchyMADEstimator extends AbstractMADEstimator<CauchyDistribution> {
+ /**
+ * Static instance.
+ */
+ public static final CauchyMADEstimator STATIC = new CauchyMADEstimator();
+
+ /**
+ * Private constructor, use static instance!
+ */
+ private CauchyMADEstimator() {
+ // Do not instantiate
+ }
+
+ @Override
+ public CauchyDistribution estimateFromMedianMAD(double median, double mad) {
+ return new CauchyDistribution(median, mad);
+ }
+
+ @Override
+ public Class<? super CauchyDistribution> getDistributionClass() {
+ return CauchyDistribution.class;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected CauchyMADEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/DistributionEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/DistributionEstimator.java
new file mode 100644
index 00000000..953fcff8
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/DistributionEstimator.java
@@ -0,0 +1,52 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.Distribution;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
+
+/**
+ * Estimate distribution parameters from a sample.
+ *
+ * @author Erich Schubert
+ *
+ * @param <D> Distribution type
+ */
+public interface DistributionEstimator<D extends Distribution> {
+ /**
+ * General form of the parameter estimation
+ *
+ * @param data Data set
+ * @param adapter Number array adapter
+ * @return Estimated distribution
+ */
+ <A> D estimate(A data, NumberArrayAdapter<?, A> adapter);
+
+ /**
+ * Get the class that is produced by the estimator.
+ *
+ * @return Distribution class
+ */
+ Class<? super D> getDistributionClass();
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/EMGOlivierNorbergEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/EMGOlivierNorbergEstimator.java
new file mode 100644
index 00000000..65c89c83
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/EMGOlivierNorbergEstimator.java
@@ -0,0 +1,82 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.StatisticalMoments;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.ExponentiallyModifiedGaussianDistribution;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Naive distribution estimation using mean and sample variance.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has ExponentiallyModifiedGaussianDistribution - - estimates
+ */
+@Reference(authors = "J. Olivier, M. M. Norberg", title = "Positively skewed data: Revisiting the Box-Cox power transformation", booktitle = "International Journal of Psychological Research Vol. 3 No. 1")
+public class EMGOlivierNorbergEstimator extends AbstractMOMEstimator<ExponentiallyModifiedGaussianDistribution> {
+ /**
+ * Static estimator class.
+ */
+ public static EMGOlivierNorbergEstimator STATIC = new EMGOlivierNorbergEstimator();
+
+ /**
+ * Private constructor, use static instance!
+ */
+ private EMGOlivierNorbergEstimator() {
+ // Do not instantiate
+ }
+
+ @Override
+ public ExponentiallyModifiedGaussianDistribution estimateFromStatisticalMoments(StatisticalMoments moments) {
+ // Avoid NaN by disallowing negative kurtosis.
+ final double halfsk13 = Math.pow(Math.max(0., moments.getSampleSkewness() * .5), 1. / 3.);
+ final double st = moments.getSampleStddev();
+ final double mu = moments.getMean() - st * halfsk13;
+ // Note: we added "abs" here, to avoid even more NaNs.
+ final double si = st * Math.sqrt(Math.abs((1. + halfsk13) * (1. - halfsk13)));
+ // One more workaround to ensure finite lambda...
+ final double la = (halfsk13 > 0) ? 1 / (st * halfsk13) : 1;
+ return new ExponentiallyModifiedGaussianDistribution(mu, si, la);
+ }
+
+ @Override
+ public Class<? super ExponentiallyModifiedGaussianDistribution> getDistributionClass() {
+ return ExponentiallyModifiedGaussianDistribution.class;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected EMGOlivierNorbergEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/ExpMADDistributionEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/ExpMADDistributionEstimator.java
new file mode 100644
index 00000000..70a16f3e
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/ExpMADDistributionEstimator.java
@@ -0,0 +1,45 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.Distribution;
+
+/**
+ * Distribuition estimators that use the method of moments (MOM) in
+ * exponentiated data.
+ *
+ * @author Erich Schubert
+ *
+ * @param <D> Distribution estimated.
+ */
+public interface ExpMADDistributionEstimator<D extends Distribution> extends DistributionEstimator<D> {
+ /**
+ * General form of the parameter estimation
+ *
+ * @param median Median lof exp values.
+ * @param mad Median absolute deviation from median (in expspace).
+ * @return Estimated distribution
+ */
+ D estimateFromExpMedianMAD(double median, double mad);
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/ExponentialLMMEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/ExponentialLMMEstimator.java
new file mode 100644
index 00000000..66176545
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/ExponentialLMMEstimator.java
@@ -0,0 +1,92 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.ExponentialDistribution;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Estimate the parameters of a Gamma Distribution, using the methods of
+ * L-Moments (LMM).
+ *
+ * Reference:
+ * <p>
+ * J. R. M. Hosking<br />
+ * Fortran routines for use with the method of L-moments Version 3.03<br />
+ * IBM Research.
+ * </p>
+ *
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has ExponentialDistribution
+ */
+@Reference(authors = "J.R.M. Hosking", title = "Fortran routines for use with the method of L-moments Version 3.03", booktitle = "IBM Research Technical Report")
+public class ExponentialLMMEstimator extends AbstractLMMEstimator<ExponentialDistribution> {
+ /**
+ * Static instance.
+ */
+ public static final ExponentialLMMEstimator STATIC = new ExponentialLMMEstimator();
+
+ /**
+ * Constructor. Private: use static instance.
+ */
+ private ExponentialLMMEstimator() {
+ super();
+ }
+
+ @Override
+ public int getNumMoments() {
+ return 2;
+ }
+
+ @Override
+ public ExponentialDistribution estimateFromLMoments(double[] xmom) {
+ double scale = 2. * xmom[1];
+ if (!(scale > 0.)) {
+ throw new ArithmeticException("Data with non-positive scale cannot be exponential distributed.");
+ }
+ return new ExponentialDistribution(1. / scale, xmom[0] - scale);
+ }
+
+ @Override
+ public Class<? super ExponentialDistribution> getDistributionClass() {
+ return ExponentialDistribution.class;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected ExponentialLMMEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/ExponentialMADEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/ExponentialMADEstimator.java
new file mode 100644
index 00000000..208fc72b
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/ExponentialMADEstimator.java
@@ -0,0 +1,85 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.ExponentialDistribution;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Estimate Exponential distribution parameters using Median and MAD.
+ *
+ * Reference:
+ * <p>
+ * D. J. Olive<br />
+ * Applied Robust Statistics<br />
+ * Preprint of an upcoming book, University of Minnesota
+ * </p>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has ExponentialDistribution
+ */
+@Reference(title = "Applied Robust Statistics", authors = "D. J. Olive", booktitle = "Applied Robust Statistics", url="http://lagrange.math.siu.edu/Olive/preprints.htm")
+public class ExponentialMADEstimator extends AbstractMADEstimator<ExponentialDistribution> {
+ /**
+ * Static instance.
+ */
+ public static final ExponentialMADEstimator STATIC = new ExponentialMADEstimator();
+
+ /**
+ * Private constructor, use static instance!
+ */
+ private ExponentialMADEstimator() {
+ // Do not instantiate
+ }
+
+ @Override
+ public ExponentialDistribution estimateFromMedianMAD(double median, double mad) {
+ final double location = median - 1.440 * mad;
+ final double scale = 2.0781 * mad;
+ if (!(scale > 0.)) {
+ throw new ArithmeticException("Data with non-positive MAD cannot be exponential distributed.");
+ }
+ return new ExponentialDistribution(1./scale, location);
+ }
+
+ @Override
+ public Class<? super ExponentialDistribution> getDistributionClass() {
+ return ExponentialDistribution.class;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected ExponentialMADEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/ExponentialMOMEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/ExponentialMOMEstimator.java
new file mode 100644
index 00000000..4c3f93aa
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/ExponentialMOMEstimator.java
@@ -0,0 +1,77 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.MeanVariance;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.ExponentialDistribution;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Estimate Exponential distribution parameters using the mean, which is the
+ * maximum-likelihood estimate (MLE), but not very robust.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has ExponentialDistribution
+ */
+public class ExponentialMOMEstimator extends AbstractMeanVarianceEstimator<ExponentialDistribution> {
+ /**
+ * Static instance.
+ */
+ public static final ExponentialMOMEstimator STATIC = new ExponentialMOMEstimator();
+
+ /**
+ * Private constructor, use static instance!
+ */
+ private ExponentialMOMEstimator() {
+ // Do not instantiate
+ }
+
+ @Override
+ public ExponentialDistribution estimateFromMeanVariance(MeanVariance mv) {
+ final double scale = mv.getMean();
+ if (!(scale > 0.)) {
+ throw new ArithmeticException("Data with non-positive mean cannot be exponential distributed.");
+ }
+ return new ExponentialDistribution(1. / scale);
+ }
+
+ @Override
+ public Class<? super ExponentialDistribution> getDistributionClass() {
+ return ExponentialDistribution.class;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected ExponentialMOMEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/ExponentialMedianEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/ExponentialMedianEstimator.java
new file mode 100644
index 00000000..19ce63c7
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/ExponentialMedianEstimator.java
@@ -0,0 +1,83 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.ExponentialDistribution;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Estimate Exponential distribution parameters using Median and MAD.
+ *
+ * Reference:
+ * <p>
+ * Robust Estimators for Transformed Location Scale Families<br />
+ * D. J. Olive
+ * </p>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has ExponentialDistribution
+ */
+@Reference(title = "Robust Estimators for Transformed Location Scale Families", authors = "D. J. Olive", booktitle = "")
+public class ExponentialMedianEstimator extends AbstractMADEstimator<ExponentialDistribution> {
+ /**
+ * Static instance.
+ */
+ public static final ExponentialMedianEstimator STATIC = new ExponentialMedianEstimator();
+
+ /**
+ * Private constructor, use static instance!
+ */
+ private ExponentialMedianEstimator() {
+ // Do not instantiate
+ }
+
+ @Override
+ public ExponentialDistribution estimateFromMedianMAD(double median, double mad) {
+ final double scale = 1.441 * median;
+ if (!(scale > 0.)) {
+ throw new ArithmeticException("Data with non-positive mean cannot be exponential distributed.");
+ }
+ return new ExponentialDistribution(1. / scale);
+ }
+
+ @Override
+ public Class<? super ExponentialDistribution> getDistributionClass() {
+ return ExponentialDistribution.class;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected ExponentialMedianEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/GammaChoiWetteEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/GammaChoiWetteEstimator.java
new file mode 100644
index 00000000..d41881f0
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/GammaChoiWetteEstimator.java
@@ -0,0 +1,118 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.GammaDistribution;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Estimate distribution parameters using the method by Choi and Wette.
+ *
+ * Reference:
+ * <p>
+ * Maximum likelihood estimation of the parameters of the gamma distribution and
+ * their bias<br />
+ * S. C. Choi, R. Wette<br />
+ * in: Technometrics
+ * </p>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has GammaDistribution - - estimates
+ */
+@Reference(title = "Maximum likelihood estimation of the parameters of the gamma distribution and their bias", authors = "S. C. Choi, R. Wette", booktitle = "Technometrics", url = "http://www.jstor.org/stable/10.2307/1266892")
+public class GammaChoiWetteEstimator implements DistributionEstimator<GammaDistribution> {
+ /**
+ * Static estimation, using iterative refinement.
+ */
+ public static final GammaChoiWetteEstimator STATIC = new GammaChoiWetteEstimator();
+
+ /**
+ * Private constructor.
+ */
+ private GammaChoiWetteEstimator() {
+ // Do not instantiate - use static class
+ }
+
+ @Override
+ public <A> GammaDistribution estimate(A data, NumberArrayAdapter<?, A> adapter) {
+ final int len = adapter.size(data);
+ double meanx = 0, meanlogx = 0;
+ for (int i = 0; i < len; i++) {
+ final double val = adapter.getDouble(data, i);
+ if (val <= 0 || Double.isInfinite(val) || Double.isNaN(val)) {
+ continue;
+ }
+ final double logx = (val > 0) ? Math.log(val) : meanlogx;
+ final double deltax = val - meanx;
+ final double deltalogx = logx - meanlogx;
+ meanx += deltax / (i + 1.);
+ meanlogx += deltalogx / (i + 1.);
+ }
+ // Initial approximation
+ final double logmeanx = Math.log(meanx);
+ final double diff = logmeanx - meanlogx;
+ double k = (3 - diff + Math.sqrt((diff - 3) * (diff - 3) + 24 * diff)) / (12 * diff);
+
+ // Refine via newton iteration, based on Choi and Wette equation
+ while (true) {
+ double kdelta = (Math.log(k) - GammaDistribution.digamma(k) - diff) / (1 / k - GammaDistribution.trigamma(k));
+ if (Math.abs(kdelta) / k < 1E-8 || !(kdelta < Double.POSITIVE_INFINITY)) {
+ break;
+ }
+ k += kdelta;
+ }
+ // Estimate theta:
+ final double theta = k / meanx;
+ if (!(k > 0.0) || !(theta > 0.0)) {
+ throw new ArithmeticException("Gamma estimation produced non-positive parameter values: k=" + k + " theta=" + theta);
+ }
+ return new GammaDistribution(k, theta);
+ }
+
+ @Override
+ public Class<? super GammaDistribution> getDistributionClass() {
+ return GammaDistribution.class;
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected GammaChoiWetteEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/GammaLMMEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/GammaLMMEstimator.java
new file mode 100644
index 00000000..edfc3f51
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/GammaLMMEstimator.java
@@ -0,0 +1,113 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.GammaDistribution;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Estimate the parameters of a Gamma Distribution, using the methods of
+ * L-Moments (LMM).
+ *
+ * Reference:
+ * <p>
+ * J. R. M. Hosking<br />
+ * Fortran routines for use with the method of L-moments Version 3.03<br />
+ * IBM Research.
+ * </p>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has GammaDistribution
+ */
+@Reference(authors = "J.R.M. Hosking", title = "Fortran routines for use with the method of L-moments Version 3.03", booktitle = "IBM Research Technical Report")
+public class GammaLMMEstimator extends AbstractLMMEstimator<GammaDistribution> {
+ /**
+ * Static instance.
+ */
+ public static final GammaLMMEstimator STATIC = new GammaLMMEstimator();
+
+ /** Coefficients for polynomial approximation */
+ private static double //
+ A1 = -0.3080, //
+ A2 = -0.05812, //
+ A3 = 0.01765;
+
+ /** Coefficients for polynomial approximation */
+ private static double //
+ B1 = 0.7213, //
+ B2 = -0.5947, //
+ B3 = -2.1817, //
+ B4 = 1.2113;
+
+ /**
+ * Constructor. Private: use static instance.
+ */
+ private GammaLMMEstimator() {
+ super();
+ }
+
+ @Override
+ public int getNumMoments() {
+ return 2;
+ }
+
+ @Override
+ public GammaDistribution estimateFromLMoments(double[] xmom) {
+ double cv = xmom[1] / xmom[0];
+ double alpha;
+ if (cv < .5) {
+ double t = Math.PI * cv * cv;
+ alpha = (1. + A1 * t) / (t * (1. + t * (A2 + t * A3)));
+ } else {
+ double t = 1. - cv;
+ alpha = t * (B1 + t * B2) / (1. + t * (B3 + t * B4));
+ }
+ final double theta = alpha / xmom[0];
+ if (!(alpha > 0.0) || !(theta > 0.0)) {
+ throw new ArithmeticException("Gamma estimation produced non-positive parameter values: k=" + alpha + " theta=" + theta);
+ }
+ return new GammaDistribution(alpha, theta);
+ }
+
+ @Override
+ public Class<? super GammaDistribution> getDistributionClass() {
+ return GammaDistribution.class;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected GammaLMMEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/GammaMADEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/GammaMADEstimator.java
new file mode 100644
index 00000000..54b0d38b
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/GammaMADEstimator.java
@@ -0,0 +1,96 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.GammaDistribution;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Robust parameter estimation for the Gamma distribution.
+ *
+ * Based on the Median and Median absolute deviation from Median (MAD).
+ *
+ * Reference:
+ * <p>
+ * J. Chen and H. Rubin<br />
+ * Bounds for the difference between median and mean of Gamma and Poisson
+ * distributions<br />
+ * In: Statist. Probab. Lett., 4 , 281–283.
+ * </p>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has GammaDistribution - - estimates
+ */
+@Reference(authors = "J. Chen. H. Rubin", title = "Bounds for the difference between median and mean of Gamma and Poisson distributions", booktitle = "Statist. Probab. Lett., 4")
+public class GammaMADEstimator extends AbstractMADEstimator<GammaDistribution> {
+ /**
+ * Static instance.
+ */
+ public static final GammaMADEstimator STATIC = new GammaMADEstimator();
+
+ /**
+ * Private constructor.
+ */
+ private GammaMADEstimator() {
+ // Do not instantiate - use static class
+ }
+
+ @Override
+ public GammaDistribution estimateFromMedianMAD(double median, double mad) {
+ if (median < Double.MIN_NORMAL) {
+ throw new ArithmeticException("Cannot estimate Gamma parameters on a distribution with zero median.");
+ }
+ if (mad < Double.MIN_NORMAL) {
+ throw new ArithmeticException("Cannot estimate Gamma parameters on a distribution with zero MAD.");
+ }
+
+ final double theta = median / (mad * mad);
+ final double k = median * theta;
+ if (!(k > 0.) || !(theta > 0.)) {
+ throw new ArithmeticException("Gamma estimation produced non-positive parameter values: k=" + k + " theta=" + theta);
+ }
+ return new GammaDistribution(k, theta);
+
+ }
+
+ @Override
+ public Class<? super GammaDistribution> getDistributionClass() {
+ return GammaDistribution.class;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected GammaMADEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/GammaMOMEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/GammaMOMEstimator.java
new file mode 100644
index 00000000..0ff0cf47
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/GammaMOMEstimator.java
@@ -0,0 +1,93 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.MeanVariance;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.GammaDistribution;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Simple parameter estimation for the Gamma distribution.
+ *
+ * This is a very naive estimation, based on the mean and variance only,
+ * sometimes referred to as the "Method of Moments" (MOM).
+ *
+ * Reference:
+ * <p>
+ * G. Casella, R. L. Berger<br />
+ * Statistical inference. Vol. 70
+ * </p>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has GammaDistribution - - estimates
+ */
+@Reference(authors = "G. Casella, R. L. Berger", title = "Statistical inference. Vol. 70", booktitle = "Statistical inference. Vol. 70")
+public class GammaMOMEstimator extends AbstractMeanVarianceEstimator<GammaDistribution> {
+ /**
+ * Static estimation using just the mean and variance.
+ */
+ public static final GammaMOMEstimator STATIC = new GammaMOMEstimator();
+
+ /**
+ * Private constructor.
+ */
+ private GammaMOMEstimator() {
+ // Do not instantiate - use static class
+ }
+
+ @Override
+ public GammaDistribution estimateFromMeanVariance(MeanVariance mv) {
+ final double mu = mv.getMean();
+ final double var = mv.getSampleVariance();
+ if (mu < Double.MIN_NORMAL || var < Double.MIN_NORMAL) {
+ throw new ArithmeticException("Cannot estimate Gamma parameters on a distribution with zero mean or variance: " + mv.toString());
+ }
+ final double theta = mu / var;
+ final double k = mu * theta;
+ if (!(k > 0.) || !(theta > 0.)) {
+ throw new ArithmeticException("Gamma estimation produced non-positive parameter values: k=" + k + " theta=" + theta);
+ }
+ return new GammaDistribution(k, theta);
+ }
+
+ @Override
+ public Class<? super GammaDistribution> getDistributionClass() {
+ return GammaDistribution.class;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected GammaMOMEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/GeneralizedExtremeValueLMMEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/GeneralizedExtremeValueLMMEstimator.java
new file mode 100644
index 00000000..cdadf47d
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/GeneralizedExtremeValueLMMEstimator.java
@@ -0,0 +1,161 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.GammaDistribution;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.GeneralizedExtremeValueDistribution;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Estimate the parameters of a Generalized Extreme Value Distribution, using
+ * the methods of L-Moments (LMM).
+ *
+ * Reference:
+ * <p>
+ * J. R. M. Hosking, J. R. Wallis, and E. F. Wood<br />
+ * Estimation of the generalized extreme-value distribution by the method of
+ * probability-weighted moments.<br />
+ * Technometrics 27.3
+ * </p>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has GeneralizedExtremeValueDistribution
+ */
+@Reference(authors = "J.R.M. Hosking, J. R. Wallis, and E. F. Wood", title = "Estimation of the generalized extreme-value distribution by the method of probability-weighted moments.", booktitle = "Technometrics 27.3", url = "http://dx.doi.org/10.1080/00401706.1985.10488049")
+public class GeneralizedExtremeValueLMMEstimator extends AbstractLMMEstimator<GeneralizedExtremeValueDistribution> {
+ /**
+ * Static instance.
+ */
+ public static final GeneralizedExtremeValueLMMEstimator STATIC = new GeneralizedExtremeValueLMMEstimator();
+
+ /**
+ * Constants for fast rational approximations.
+ */
+ private static final double //
+ A0 = 0.28377530, //
+ A1 = -1.21096399, //
+ A2 = -2.50728214, //
+ A3 = -1.13455566, //
+ A4 = -0.07138022;
+
+ private static final double //
+ B1 = 2.06189696, //
+ B2 = 1.31912239, //
+ B3 = 0.25077104;
+
+ private static final double //
+ C1 = 1.59921491, //
+ C2 = -0.48832213, //
+ C3 = 0.01573152, //
+ D1 = -0.64363929, //
+ D2 = 0.08985247;
+
+ /** Maximum number of iterations. */
+ static int MAXIT = 20;
+
+ /**
+ * Constructor. Private: use static instance.
+ */
+ private GeneralizedExtremeValueLMMEstimator() {
+ super();
+ }
+
+ @Override
+ public int getNumMoments() {
+ return 3;
+ }
+
+ @Override
+ public GeneralizedExtremeValueDistribution estimateFromLMoments(double[] xmom) {
+ double t3 = xmom[2];
+ if (Math.abs(t3) < 1e-50 || (t3 >= 1.)) {
+ throw new ArithmeticException("Invalid moment estimation.");
+ }
+ // Approximation for t3 between 0 and 1:
+ double g;
+ if (t3 > 0.) {
+ double z = 1. - t3;
+ g = (-1. + z * (C1 + z * (C2 + z * C3))) / (1. + z * (D1 + z * D2));
+ // g: Almost zero?
+ if (Math.abs(g) < 1e-50) {
+ double k = 0;
+ double sigma = xmom[1] / MathUtil.LOG2;
+ double mu = xmom[0] - Math.E * sigma;
+ return new GeneralizedExtremeValueDistribution(mu, sigma, k);
+ }
+ } else {
+ // Approximation for t3 between -.8 and 0L:
+ g = (A0 + t3 * (A1 + t3 * (A2 + t3 * (A3 + t3 * A4)))) / (1. + t3 * (B1 + t3 * (B2 + t3 * B3)));
+ if (t3 < -.8) {
+ // Newton-Raphson iteration for t3 < -.8
+ if (t3 <= -.97) {
+ g = 1. - Math.log(1. + t3) / MathUtil.LOG2;
+ }
+ double t0 = .5 * (t3 + 3.);
+ for (int it = 1;; it++) {
+ double x2 = Math.pow(2., -g), xx2 = 1. - x2;
+ double x3 = Math.pow(3., -g), xx3 = 1. - x3;
+ double t = xx3 / xx2;
+ double deriv = (xx2 * x3 * MathUtil.LOG3 - xx3 * x2 * MathUtil.LOG2) / (xx2 * x2);
+ double oldg = g;
+ g -= (t - t0) / deriv;
+ if (Math.abs(g - oldg) < 1e-20 * g) {
+ break;
+ }
+ if (it >= MAXIT) {
+ throw new ArithmeticException("Newton-Raphson did not converge.");
+ }
+ }
+ }
+ }
+ double gam = Math.exp(GammaDistribution.logGamma(1. + g));
+ final double mu, sigma, k;
+ k = g;
+ sigma = xmom[1] * g / (gam * (1. - Math.pow(2., -g)));
+ mu = xmom[0] - sigma * (1. - gam) / g;
+ return new GeneralizedExtremeValueDistribution(mu, sigma, k);
+ }
+
+ @Override
+ public Class<? super GeneralizedExtremeValueDistribution> getDistributionClass() {
+ return GeneralizedExtremeValueDistribution.class;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected GeneralizedExtremeValueLMMEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/GeneralizedLogisticAlternateLMMEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/GeneralizedLogisticAlternateLMMEstimator.java
new file mode 100644
index 00000000..dfcbcd52
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/GeneralizedLogisticAlternateLMMEstimator.java
@@ -0,0 +1,98 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.GeneralizedLogisticAlternateDistribution;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Estimate the parameters of a Generalized Logistic Distribution, using the
+ * methods of L-Moments (LMM).
+ *
+ * Reference:
+ * <p>
+ * J. R. M. Hosking<br />
+ * Fortran routines for use with the method of L-moments Version 3.03<br />
+ * IBM Research.
+ * </p>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has GeneralizedLogisticAlternateDistribution
+ */
+@Reference(authors = "J.R.M. Hosking", title = "Fortran routines for use with the method of L-moments Version 3.03", booktitle = "IBM Research Technical Report")
+public class GeneralizedLogisticAlternateLMMEstimator extends AbstractLMMEstimator<GeneralizedLogisticAlternateDistribution> {
+ /**
+ * Static instance.
+ */
+ public static final GeneralizedLogisticAlternateLMMEstimator STATIC = new GeneralizedLogisticAlternateLMMEstimator();
+
+ /**
+ * Constructor. Private: use static instance.
+ */
+ private GeneralizedLogisticAlternateLMMEstimator() {
+ super();
+ }
+
+ @Override
+ public int getNumMoments() {
+ return 3;
+ }
+
+ @Override
+ public GeneralizedLogisticAlternateDistribution estimateFromLMoments(double[] xmom) {
+ double shape = -xmom[2];
+ if (!(shape >= -1 && shape <= 1)) {
+ throw new ArithmeticException("Invalid moment estimation.");
+ }
+ if (Math.abs(shape) < 1e-6) {
+ // Effectively zero, so non-generalized.
+ return new GeneralizedLogisticAlternateDistribution(xmom[0], xmom[1], 0.);
+ }
+ double tmp = shape * Math.PI / Math.sin(shape * Math.PI);
+ double scale = xmom[1] / tmp;
+ double location = xmom[0] - scale * (1. - tmp) / shape;
+ return new GeneralizedLogisticAlternateDistribution(location, scale, shape);
+ }
+
+ @Override
+ public Class<? super GeneralizedLogisticAlternateDistribution> getDistributionClass() {
+ return GeneralizedLogisticAlternateDistribution.class;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected GeneralizedLogisticAlternateLMMEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/GumbelLMMEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/GumbelLMMEstimator.java
new file mode 100644
index 00000000..c0f64006
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/GumbelLMMEstimator.java
@@ -0,0 +1,90 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.GumbelDistribution;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Estimate the parameters of a Gumbel Distribution, using the methods of
+ * L-Moments (LMM).
+ *
+ * Reference:
+ * <p>
+ * J. R. M. Hosking<br />
+ * Fortran routines for use with the method of L-moments Version 3.03<br />
+ * IBM Research.
+ * </p>
+ *
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has GumbelDistribution
+ */
+@Reference(authors = "J.R.M. Hosking", title = "Fortran routines for use with the method of L-moments Version 3.03", booktitle = "IBM Research Technical Report")
+public class GumbelLMMEstimator extends AbstractLMMEstimator<GumbelDistribution> {
+ /**
+ * Static instance.
+ */
+ public static final GumbelLMMEstimator STATIC = new GumbelLMMEstimator();
+
+ /**
+ * Constructor. Private: use static instance.
+ */
+ private GumbelLMMEstimator() {
+ super();
+ }
+
+ @Override
+ public int getNumMoments() {
+ return 2;
+ }
+
+ @Override
+ public GumbelDistribution estimateFromLMoments(double[] xmom) {
+ double scale = xmom[1] / MathUtil.LOG2;
+ return new GumbelDistribution(xmom[0] - Math.E * scale, scale);
+ }
+
+ @Override
+ public Class<? super GumbelDistribution> getDistributionClass() {
+ return GumbelDistribution.class;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected GumbelLMMEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/GumbelMADEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/GumbelMADEstimator.java
new file mode 100644
index 00000000..ebf6354a
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/GumbelMADEstimator.java
@@ -0,0 +1,82 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.GumbelDistribution;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Parameter estimation via median and median absolute deviation from median
+ * (MAD).
+ *
+ * Reference:
+ * <p>
+ * D. J. Olive<br />
+ * Applied Robust Statistics<br />
+ * Preprint of an upcoming book, University of Minnesota
+ * </p>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has GumbelDistribution - - estimates
+ */
+@Reference(title = "Applied Robust Statistics", authors = "D. J. Olive", booktitle = "Applied Robust Statistics", url="http://lagrange.math.siu.edu/Olive/preprints.htm")
+public class GumbelMADEstimator extends AbstractMADEstimator<GumbelDistribution> {
+ /**
+ * Static instance.
+ */
+ public static final GumbelMADEstimator STATIC = new GumbelMADEstimator();
+
+ /**
+ * Private constructor, use static instance!
+ */
+ private GumbelMADEstimator() {
+ // Do not instantiate
+ }
+
+ @Override
+ public GumbelDistribution estimateFromMedianMAD(double median, double mad) {
+ // TODO: Work around degenerate cases?
+ return new GumbelDistribution(median + 0.4778 * mad, 1.3037 * mad);
+ }
+
+ @Override
+ public Class<? super GumbelDistribution> getDistributionClass() {
+ return GumbelDistribution.class;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected GumbelMADEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LMMDistributionEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LMMDistributionEstimator.java
new file mode 100644
index 00000000..f3d8d1b2
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LMMDistributionEstimator.java
@@ -0,0 +1,51 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.Distribution;
+
+/**
+ * Interface for distribution estimators based on the methods of L-Moments
+ * (LMM).
+ *
+ * @author Erich Schubert
+ *
+ * @param <D> Distribution class.
+ */
+public interface LMMDistributionEstimator<D extends Distribution> extends DistributionEstimator<D> {
+ /**
+ * Estimate from the L-Moments.
+ *
+ * @param moments L-Moments
+ * @return Distribution
+ */
+ D estimateFromLMoments(double[] moments);
+
+ /**
+ * The number of moments needed.
+ *
+ * @return Moments needed.
+ */
+ int getNumMoments();
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LaplaceLMMEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LaplaceLMMEstimator.java
new file mode 100644
index 00000000..1e31af28
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LaplaceLMMEstimator.java
@@ -0,0 +1,78 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.LaplaceDistribution;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Estimate Laplace distribution parameters using the method of L-Moments (LMM).
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has ExponentialDistribution
+ */
+public class LaplaceLMMEstimator extends AbstractLMMEstimator<LaplaceDistribution> {
+ /**
+ * Static instance.
+ */
+ public static final LaplaceLMMEstimator STATIC = new LaplaceLMMEstimator();
+
+ /**
+ * Private constructor, use static instance!
+ */
+ private LaplaceLMMEstimator() {
+ // Do not instantiate
+ }
+
+ @Override
+ public LaplaceDistribution estimateFromLMoments(double[] xmom) {
+ final double location = xmom[0];
+ final double scale = 4. / 3. * xmom[1];
+ return new LaplaceDistribution(1. / scale, location);
+ }
+
+ @Override
+ public int getNumMoments() {
+ return 2;
+ }
+
+ @Override
+ public Class<? super LaplaceDistribution> getDistributionClass() {
+ return LaplaceDistribution.class;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected LaplaceLMMEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LaplaceMADEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LaplaceMADEstimator.java
new file mode 100644
index 00000000..d4671362
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LaplaceMADEstimator.java
@@ -0,0 +1,82 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.LaplaceDistribution;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Estimate Laplace distribution parameters using Median and MAD.
+ *
+ * Reference:
+ * <p>
+ * D. J. Olive<br />
+ * Applied Robust Statistics<br />
+ * Preprint of an upcoming book, University of Minnesota
+ * </p>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has ExponentialDistribution
+ */
+@Reference(title = "Applied Robust Statistics", authors = "D. J. Olive", booktitle = "Applied Robust Statistics", url="http://lagrange.math.siu.edu/Olive/preprints.htm")
+public class LaplaceMADEstimator extends AbstractMADEstimator<LaplaceDistribution> {
+ /**
+ * Static instance.
+ */
+ public static final LaplaceMADEstimator STATIC = new LaplaceMADEstimator();
+
+ /**
+ * Private constructor, use static instance!
+ */
+ private LaplaceMADEstimator() {
+ // Do not instantiate
+ }
+
+ @Override
+ public LaplaceDistribution estimateFromMedianMAD(double median, double mad) {
+ final double location = median;
+ final double scale = 1.443 * mad;
+ return new LaplaceDistribution(1. / scale, location);
+ }
+
+ @Override
+ public Class<? super LaplaceDistribution> getDistributionClass() {
+ return LaplaceDistribution.class;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected LaplaceMADEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LaplaceMLEEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LaplaceMLEEstimator.java
new file mode 100644
index 00000000..f44e2b3a
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LaplaceMLEEstimator.java
@@ -0,0 +1,94 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.LaplaceDistribution;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.QuickSelect;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Estimate Laplace distribution parameters using Median and mean deviation from
+ * median.
+ *
+ * Reference:
+ * <p>
+ * R. M. Norton<br />
+ * The Double Exponential Distribution: Using Calculus to Find a Maximum
+ * Likelihood Estimator<br />
+ * The American Statistician 38 (2)
+ * </p>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has ExponentialDistribution
+ */
+@Reference(title = "The Double Exponential Distribution: Using Calculus to Find a Maximum Likelihood Estimator", authors = "R. M. Norton", booktitle = "The American Statistician 38 (2)", url = "http://dx.doi.org/10.2307%2F2683252")
+public class LaplaceMLEEstimator implements DistributionEstimator<LaplaceDistribution> {
+ /**
+ * Static instance.
+ */
+ public static final LaplaceMLEEstimator STATIC = new LaplaceMLEEstimator();
+
+ /**
+ * Private constructor, use static instance!
+ */
+ private LaplaceMLEEstimator() {
+ // Do not instantiate
+ }
+
+ @Override
+ public <A> LaplaceDistribution estimate(A data, NumberArrayAdapter<?, A> adapter) {
+ int len = adapter.size(data);
+ double[] temp = new double[len];
+ for (int i = 0; i < len; i++) {
+ temp[i] = adapter.getDouble(data, i);
+ }
+ double location = QuickSelect.median(temp);
+ double meandev = 0.;
+ for (int i = 0; i < len; i++) {
+ meandev += Math.abs(temp[i] - location);
+ }
+ return new LaplaceDistribution(len / meandev, location);
+ }
+
+ @Override
+ public Class<? super LaplaceDistribution> getDistributionClass() {
+ return LaplaceDistribution.class;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected LaplaceMLEEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogGammaAlternateExpMADEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogGammaAlternateExpMADEstimator.java
new file mode 100644
index 00000000..7ea0a6be
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogGammaAlternateExpMADEstimator.java
@@ -0,0 +1,85 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.LogGammaAlternateDistribution;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Robust parameter estimation for the LogGamma distribution.
+ *
+ * A modified algorithm for LogGamma distributions.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has LogGammaAlternateDistribution - - estimates
+ */
+public class LogGammaAlternateExpMADEstimator extends AbstractExpMADEstimator<LogGammaAlternateDistribution> {
+ /**
+ * Static estimator, more robust to outliers by using the median.
+ */
+ public static final LogGammaAlternateExpMADEstimator STATIC = new LogGammaAlternateExpMADEstimator();
+
+ /**
+ * Private constructor.
+ */
+ private LogGammaAlternateExpMADEstimator() {
+ // Do not instantiate - use static class
+ }
+
+ @Override
+ public LogGammaAlternateDistribution estimateFromExpMedianMAD(double median, double mad) {
+ if (median < Double.MIN_NORMAL) {
+ throw new ArithmeticException("Cannot estimate Gamma parameters on a distribution with zero median.");
+ }
+ if (mad < Double.MIN_NORMAL) {
+ throw new ArithmeticException("Cannot estimate Gamma parameters on a distribution with zero MAD.");
+ }
+
+ final double b = median / (mad * mad);
+ final double k = median * b;
+ if (!(k > 0.) || !(b > 0.)) {
+ throw new ArithmeticException("LogGammaAlternate estimation produced non-positive parameter values: k=" + k + " b=" + b + " median=" + median + " mad=" + mad);
+ }
+ return new LogGammaAlternateDistribution(k, Math.log(b), 0.);
+ }
+
+ @Override
+ public Class<? super LogGammaAlternateDistribution> getDistributionClass() {
+ return LogGammaAlternateDistribution.class;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected LogGammaAlternateExpMADEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogGammaChoiWetteEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogGammaChoiWetteEstimator.java
new file mode 100644
index 00000000..ba3a899d
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogGammaChoiWetteEstimator.java
@@ -0,0 +1,126 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.GammaDistribution;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.LogGammaDistribution;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Estimate distribution parameters using the method by Choi and Wette.
+ *
+ * A modified algorithm for LogGamma distributions.
+ *
+ * Reference:
+ * <p>
+ * Maximum likelihood estimation of the parameters of the gamma distribution and
+ * their bias<br />
+ * S. C. Choi, R. Wette<br />
+ * in: Technometrics
+ * </p>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has LogGammaDistribution - - estimates
+ */
+@Reference(title = "Maximum likelihood estimation of the parameters of the gamma distribution and their bias", authors = "S. C. Choi, R. Wette", booktitle = "Technometrics", url = "http://www.jstor.org/stable/10.2307/1266892")
+public class LogGammaChoiWetteEstimator implements DistributionEstimator<LogGammaDistribution> {
+ /**
+ * Static estimation, using iterative refinement.
+ */
+ public static final LogGammaChoiWetteEstimator STATIC = new LogGammaChoiWetteEstimator();
+
+ /**
+ * Private constructor.
+ */
+ private LogGammaChoiWetteEstimator() {
+ // Do not instantiate - use static class
+ }
+
+ @Override
+ public <A> LogGammaDistribution estimate(A data, NumberArrayAdapter<?, A> adapter) {
+ final int len = adapter.size(data);
+ double shift = AbstractLogMOMEstimator.min(data, adapter, 0., 1e-10);
+ double meanx = 0, meanlogx = 0;
+ for (int i = 0; i < len; i++) {
+ double val = adapter.getDouble(data, i) - shift;
+ if (val <= 0 || Double.isInfinite(val) || Double.isNaN(val)) {
+ continue;
+ }
+ val = Math.log(val);
+ final double logx = (val > 0) ? Math.log(val) : meanlogx;
+ final double deltax = val - meanx;
+ final double deltalogx = logx - meanlogx;
+ meanx += deltax / (i + 1.);
+ meanlogx += deltalogx / (i + 1.);
+ }
+ if (!(meanx > 0)) {
+ throw new ArithmeticException("Cannot estimate LogGamma distribution with mean " + meanx);
+ }
+ // Initial approximation
+ final double logmeanx = Math.log(meanx);
+ final double diff = logmeanx - meanlogx;
+ double k = (3 - diff + Math.sqrt((diff - 3) * (diff - 3) + 24 * diff)) / (12 * diff);
+
+ // Refine via newton iteration, based on Choi and Wette equation
+ while (true) {
+ double kdelta = (Math.log(k) - GammaDistribution.digamma(k) - diff) / (1 / k - GammaDistribution.trigamma(k));
+ if (Math.abs(kdelta) / k < 1E-8 || !(kdelta < Double.POSITIVE_INFINITY) || !(kdelta > Double.NEGATIVE_INFINITY)) {
+ break;
+ }
+ k += kdelta;
+ }
+ // Estimate theta:
+ final double theta = k / meanx;
+ if (!(k > 0.0) || !(theta > 0.0)) {
+ throw new ArithmeticException("LogGamma estimation produced non-positive parameter values: k=" + k + " theta=" + theta);
+ }
+ return new LogGammaDistribution(k, theta, shift - 1);
+ }
+
+ @Override
+ public Class<? super LogGammaDistribution> getDistributionClass() {
+ return LogGammaDistribution.class;
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected LogGammaChoiWetteEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogGammaLogMADEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogGammaLogMADEstimator.java
new file mode 100644
index 00000000..ed34870c
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogGammaLogMADEstimator.java
@@ -0,0 +1,85 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.LogGammaDistribution;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Robust parameter estimation for the LogGamma distribution.
+ *
+ * A modified algorithm for LogGamma distributions.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has LogGammaDistribution - - estimates
+ */
+public class LogGammaLogMADEstimator extends AbstractLogMADEstimator<LogGammaDistribution> {
+ /**
+ * Static estimator, more robust to outliers by using the median.
+ */
+ public static final LogGammaLogMADEstimator STATIC = new LogGammaLogMADEstimator();
+
+ /**
+ * Private constructor.
+ */
+ private LogGammaLogMADEstimator() {
+ // Do not instantiate - use static class
+ }
+
+ @Override
+ public LogGammaDistribution estimateFromLogMedianMAD(double median, double mad, double shift) {
+ if (median < Double.MIN_NORMAL) {
+ throw new ArithmeticException("Cannot estimate Gamma parameters on a distribution with zero median.");
+ }
+ if (mad < Double.MIN_NORMAL) {
+ throw new ArithmeticException("Cannot estimate Gamma parameters on a distribution with zero MAD.");
+ }
+
+ final double theta = median / (mad * mad);
+ final double k = median * theta;
+ if (!(k > 0.) || !(theta > 0.)) {
+ throw new ArithmeticException("LogGamma estimation produced non-positive parameter values: k=" + k + " theta=" + theta);
+ }
+ return new LogGammaDistribution(k, theta, shift - 1);
+ }
+
+ @Override
+ public Class<? super LogGammaDistribution> getDistributionClass() {
+ return LogGammaDistribution.class;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected LogGammaLogMADEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogGammaLogMOMEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogGammaLogMOMEstimator.java
new file mode 100644
index 00000000..ddc6cbb9
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogGammaLogMOMEstimator.java
@@ -0,0 +1,85 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.MeanVariance;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.LogGammaDistribution;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Simple parameter estimation for the Gamma distribution.
+ *
+ * This is a very naive estimation, based on the mean and variance of the log
+ * transformed values.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has LogGammaDistribution - - estimates
+ */
+public class LogGammaLogMOMEstimator extends AbstractLogMeanVarianceEstimator<LogGammaDistribution> {
+ /**
+ * Static estimation using just the mean and variance.
+ */
+ public static final LogGammaLogMOMEstimator STATIC = new LogGammaLogMOMEstimator();
+
+ /**
+ * Private constructor: use static instance.
+ */
+ private LogGammaLogMOMEstimator() {
+ // Do not instantiate - use static class
+ }
+
+ @Override
+ public LogGammaDistribution estimateFromLogMeanVariance(MeanVariance mv, double shift) {
+ final double mu = mv.getMean();
+ final double var = mv.getSampleVariance();
+ if (mu < Double.MIN_NORMAL || var < Double.MIN_NORMAL) {
+ throw new ArithmeticException("Cannot estimate Gamma parameters on a distribution with zero mean or variance: " + mv.toString());
+ }
+ final double theta = mu / var;
+ final double k = mu * theta;
+ if (!(k > 0.) || !(theta > 0.)) {
+ throw new ArithmeticException("LogGamma estimation produced non-positive parameter values: k=" + k + " theta=" + theta);
+ }
+ return new LogGammaDistribution(k, theta, shift - 1);
+ }
+
+ @Override
+ public Class<? super LogGammaDistribution> getDistributionClass() {
+ return LogGammaDistribution.class;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected LogGammaLogMOMEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogLogisticMADEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogLogisticMADEstimator.java
new file mode 100644
index 00000000..61b111c9
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogLogisticMADEstimator.java
@@ -0,0 +1,81 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.LogLogisticDistribution;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Estimate Logistic distribution parameters using Median and MAD.
+ *
+ * Reference:
+ * <p>
+ * D. J. Olive<br />
+ * Applied Robust Statistics<br />
+ * Preprint of an upcoming book, University of Minnesota
+ * </p>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has LogLogisticDistribution
+ */
+@Reference(title = "Applied Robust Statistics", authors = "D. J. Olive", booktitle = "Applied Robust Statistics", url="http://lagrange.math.siu.edu/Olive/preprints.htm")
+public class LogLogisticMADEstimator extends AbstractMADEstimator<LogLogisticDistribution> {
+ /**
+ * Static instance.
+ */
+ public static final LogLogisticMADEstimator STATIC = new LogLogisticMADEstimator();
+
+ /**
+ * Private constructor, use static instance!
+ */
+ private LogLogisticMADEstimator() {
+ // Do not instantiate
+ }
+
+ @Override
+ public LogLogisticDistribution estimateFromMedianMAD(double median, double mad) {
+ return new LogLogisticDistribution(1. / median, MathUtil.LOG3 / mad);
+ }
+
+ @Override
+ public Class<? super LogLogisticDistribution> getDistributionClass() {
+ return LogLogisticDistribution.class;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected LogLogisticMADEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogMADDistributionEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogMADDistributionEstimator.java
new file mode 100644
index 00000000..9c281952
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogMADDistributionEstimator.java
@@ -0,0 +1,45 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.Distribution;
+
+/**
+ * Distribuition estimators that use the method of moments (MOM) in logspace.
+ *
+ * @author Erich Schubert
+ *
+ * @param <D> Distribution estimated.
+ */
+public interface LogMADDistributionEstimator<D extends Distribution> extends DistributionEstimator<D> {
+ /**
+ * General form of the parameter estimation
+ *
+ * @param median Median lof log values.
+ * @param mad Median absolute deviation from median (in logspace).
+ * @param shift Shift offset that was used to avoid negative values.
+ * @return Estimated distribution
+ */
+ D estimateFromLogMedianMAD(double median, double mad, double shift);
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogMOMDistributionEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogMOMDistributionEstimator.java
new file mode 100644
index 00000000..5a589faa
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogMOMDistributionEstimator.java
@@ -0,0 +1,46 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.math.StatisticalMoments;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.Distribution;
+
+/**
+ * Distribuition estimators that use the method of moments (MOM) in logspace,
+ * i.e. that only need the statistical moments of a data set after logarithms.
+ *
+ * @author Erich Schubert
+ *
+ * @param <D> Distribution estimated.
+ */
+public interface LogMOMDistributionEstimator<D extends Distribution> extends DistributionEstimator<D> {
+ /**
+ * General form of the parameter estimation
+ *
+ * @param moments Statistical moments
+ * @param shift Shifting offset that was used
+ * @return Estimated distribution
+ */
+ D estimateFromLogStatisticalMoments(StatisticalMoments moments, double shift);
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogNormalBilkovaLMMEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogNormalBilkovaLMMEstimator.java
new file mode 100644
index 00000000..e8fab89f
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogNormalBilkovaLMMEstimator.java
@@ -0,0 +1,104 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.LogNormalDistribution;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.NormalDistribution;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Alternate estimate the parameters of a log Gamma Distribution, using the
+ * methods of L-Moments (LMM) for the Generalized Normal Distribution.
+ *
+ * Reference:
+ * <p>
+ * D. Bílková<br />
+ * Lognormal distribution and using L-moment method for estimating its
+ * parameters<br />
+ * Int. Journal of Mathematical Models and Methods in Applied Sciences (NAUN)
+ * </p>
+ *
+ * See also {@link LogNormalLMMEstimator} for a similar estimator, based on the
+ * generalized normal distribution, as used by Hosking.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has LogNormalDistribution
+ */
+@Reference(authors = "D. Bílková", title = "Lognormal distribution and using L-moment method for estimating its parameters", booktitle = "Int. Journal of Mathematical Models and Methods in Applied Sciences (NAUN)", url = "http://www.naun.org/multimedia/NAUN/m3as/17-079.pdf")
+public class LogNormalBilkovaLMMEstimator extends AbstractLMMEstimator<LogNormalDistribution> {
+ /**
+ * Static instance.
+ */
+ public static final LogNormalBilkovaLMMEstimator STATIC = new LogNormalBilkovaLMMEstimator();
+
+ /**
+ * Scaling constant.
+ */
+ private static final double SQRT8_3 = Math.sqrt(8. / 3.);
+
+ /**
+ * Constructor. Private: use static instance.
+ */
+ private LogNormalBilkovaLMMEstimator() {
+ super();
+ }
+
+ @Override
+ public int getNumMoments() {
+ return 3;
+ }
+
+ @Override
+ public LogNormalDistribution estimateFromLMoments(double[] xmom) {
+ if (!(xmom[1] > 0.) || !(Math.abs(xmom[2]) < 1.0) || !(xmom[2] > 0.)) {
+ throw new ArithmeticException("L-Moments invalid");
+ }
+ final double z = SQRT8_3 * NormalDistribution.standardNormalQuantile(.5 * (1. + xmom[2])), z2 = z * z;
+ final double sigma = 0.999281 * z - 0.006118 * z * z2 + 0.000127 * z * z2 * z2;
+ final double sigmasqhalf = sigma * sigma * .5;
+ final double logmu = Math.log(xmom[1] / NormalDistribution.erf(.5 * sigma)) - sigmasqhalf;
+ return new LogNormalDistribution(logmu, Math.max(sigma, Double.MIN_NORMAL), xmom[0] - Math.exp(logmu + sigmasqhalf));
+ }
+
+ @Override
+ public Class<? super LogNormalDistribution> getDistributionClass() {
+ return LogNormalDistribution.class;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected LogNormalBilkovaLMMEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogNormalLMMEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogNormalLMMEstimator.java
new file mode 100644
index 00000000..48865d3f
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogNormalLMMEstimator.java
@@ -0,0 +1,130 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.LogNormalDistribution;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.NormalDistribution;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Estimate the parameters of a log Normal Distribution, using the methods of
+ * L-Moments (LMM) for the Generalized Normal Distribution.
+ *
+ * Reference:
+ * <p>
+ * J. R. M. Hosking<br />
+ * Fortran routines for use with the method of L-moments Version 3.03<br />
+ * IBM Research.
+ * </p>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has LogNormalDistribution
+ */
+@Reference(authors = "J.R.M. Hosking", title = "Fortran routines for use with the method of L-moments Version 3.03", booktitle = "IBM Research Technical Report")
+public class LogNormalLMMEstimator extends AbstractLMMEstimator<LogNormalDistribution> {
+ /**
+ * Static instance.
+ */
+ public static final LogNormalLMMEstimator STATIC = new LogNormalLMMEstimator();
+
+ /** Polynomial approximation */
+ private static final double //
+ A0 = 0.20466534e+01, //
+ A1 = -0.36544371e+01, //
+ A2 = 0.18396733e+01, //
+ A3 = -0.20360244;
+
+ /** Polynomial approximation */
+ private static final double //
+ B1 = -0.20182173e+01, //
+ B2 = 0.12420401e+01, //
+ B3 = -0.21741801;
+
+ /**
+ * Constructor. Private: use static instance.
+ */
+ private LogNormalLMMEstimator() {
+ super();
+ }
+
+ @Override
+ public int getNumMoments() {
+ return 3;
+ }
+
+ @Override
+ public LogNormalDistribution estimateFromLMoments(double[] xmom) {
+ // Note: the third condition probably is okay for Generalized Normal, but
+ // not for lognormal estimation.
+ if (!(xmom[1] > 0.) || !(Math.abs(xmom[2]) < 1.0) || !(xmom[2] > 0.0)) {
+ throw new ArithmeticException("L-Moments invalid");
+ }
+ // Generalized Normal Distribution estimation:
+ double t3 = xmom[2];
+ final double location, scale, shape;
+ if (Math.abs(t3) >= .95) {
+ // Extreme skewness
+ location = 0.;
+ scale = -1;
+ shape = 0.;
+ } else if (Math.abs(t3) < 1e-8) {
+ // t3 effectively zero.
+ location = xmom[0];
+ scale = xmom[1] * MathUtil.SQRTPI;
+ shape = 0.;
+ } else {
+ final double tt = t3 * t3;
+ shape = -t3 * (A0 + tt * (A1 + tt * (A2 + tt * A3))) / (1. + tt * (B1 + tt * (B2 + tt * B3)));
+ final double e = Math.exp(.5 * shape * shape);
+ scale = xmom[1] * shape / (e * NormalDistribution.erf(.5 * shape));
+ location = xmom[0] + scale * (e - 1.) / shape;
+ }
+ // Estimate logNormal from generalized normal:
+ final double sigma = -shape;
+ final double expmu = scale / sigma;
+ return new LogNormalDistribution(Math.log(expmu), Math.max(sigma, Double.MIN_NORMAL), location - expmu);
+ }
+
+ @Override
+ public Class<? super LogNormalDistribution> getDistributionClass() {
+ return LogNormalDistribution.class;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected LogNormalLMMEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogNormalLevenbergMarquardtKDEEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogNormalLevenbergMarquardtKDEEstimator.java
new file mode 100644
index 00000000..b4b8ff0d
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogNormalLevenbergMarquardtKDEEstimator.java
@@ -0,0 +1,122 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import java.util.Arrays;
+
+import de.lmu.ifi.dbs.elki.math.MeanVariance;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.fitting.GaussianFittingFunction;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.fitting.LevenbergMarquardtMethod;
+import de.lmu.ifi.dbs.elki.math.statistics.KernelDensityEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.LogNormalDistribution;
+import de.lmu.ifi.dbs.elki.math.statistics.kernelfunctions.GaussianKernelDensityFunction;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Distribution parameter estimation using Levenberg-Marquardt iterative
+ * optimization and a kernel density estimation.
+ *
+ * Note: this estimator is rather expensive, and needs optimization in the KDE
+ * phase, which currently is O(n^2)!
+ *
+ * This estimator is primarily attractive when only part of the distribution was
+ * observed.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has LogNormalDistribution - - estimates
+ */
+public class LogNormalLevenbergMarquardtKDEEstimator implements DistributionEstimator<LogNormalDistribution> {
+ /**
+ * Static estimator for small sample sizes and <em>partial</em> data.
+ */
+ public static final LogNormalLevenbergMarquardtKDEEstimator STATIC = new LogNormalLevenbergMarquardtKDEEstimator();
+
+ /**
+ * Constructor. Private: use static instance!
+ */
+ private LogNormalLevenbergMarquardtKDEEstimator() {
+ super();
+ }
+
+ @Override
+ public <A> LogNormalDistribution estimate(A data, NumberArrayAdapter<?, A> adapter) {
+ // We first need the basic parameters:
+ final int len = adapter.size(data);
+ MeanVariance mv = new MeanVariance();
+ // X positions of samples
+ double[] x = new double[len];
+ for (int i = 0; i < len; i++) {
+ final double val = adapter.getDouble(data, i);
+ if (!(val > 0)) {
+ throw new ArithmeticException("Cannot fit logNormal to a data set which includes non-positive values: " + val);
+ }
+ x[i] = Math.log(val);
+ mv.put(x[i]);
+ }
+ // Sort our copy.
+ Arrays.sort(x);
+ double median = (x[len >> 1] + x[(len + 1) >> 1]) * .5;
+
+ // Height = density, via KDE.
+ KernelDensityEstimator de = new KernelDensityEstimator(x, GaussianKernelDensityFunction.KERNEL, 1e-6);
+ double[] y = de.getDensity();
+
+ // Weights:
+ double[] s = new double[len];
+ Arrays.fill(s, 1.0);
+
+ // Initial parameter estimate:
+ double[] params = { median, mv.getSampleStddev(), 1 };
+ boolean[] dofit = { true, true, false };
+ LevenbergMarquardtMethod fit = new LevenbergMarquardtMethod(GaussianFittingFunction.STATIC, params, dofit, x, y, s);
+ fit.run();
+ double[] ps = fit.getParams();
+ return new LogNormalDistribution(ps[0], ps[1], 0.);
+ }
+
+ @Override
+ public Class<? super LogNormalDistribution> getDistributionClass() {
+ return LogNormalDistribution.class;
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected LogNormalLevenbergMarquardtKDEEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogNormalLogMADEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogNormalLogMADEstimator.java
new file mode 100644
index 00000000..6ad1dc33
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogNormalLogMADEstimator.java
@@ -0,0 +1,89 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.LogNormalDistribution;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.NormalDistribution;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Estimator using Medians. More robust to outliers, and just slightly more
+ * expensive (needs to copy the data for partial sorting to find the median).
+ *
+ * References:
+ * <p>
+ * F. R. Hampel<br />
+ * The Influence Curve and Its Role in Robust Estimation<br />
+ * in: Journal of the American Statistical Association, June 1974, Vol. 69, No.
+ * 346
+ * </p>
+ * <p>
+ * P. J. Rousseeuw, C. Croux<br />
+ * Alternatives to the Median Absolute Deviation<br />
+ * in: Journal of the American Statistical Association, December 1993, Vol. 88,
+ * No. 424, Theory and Methods
+ * </p>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has LogNormalDistribution - - estimates
+ */
+@Reference(authors = "F. R. Hampel", title = "The Influence Curve and Its Role in Robust Estimation", booktitle = "Journal of the American Statistical Association, June 1974, Vol. 69, No. 346", url = "http://www.jstor.org/stable/10.2307/2285666")
+public class LogNormalLogMADEstimator extends AbstractLogMADEstimator<LogNormalDistribution> {
+ /**
+ * Static estimator, more robust to outliers by using the median.
+ */
+ public static LogNormalLogMADEstimator STATIC = new LogNormalLogMADEstimator();
+
+ /**
+ * Constructor. Private: use static instance!
+ */
+ private LogNormalLogMADEstimator() {
+ super();
+ }
+
+ @Override
+ public LogNormalDistribution estimateFromLogMedianMAD(double median, double mad, double shift) {
+ return new LogNormalDistribution(median, Math.max(NormalDistribution.ONEBYPHIINV075 * mad, Double.MIN_NORMAL), shift);
+ }
+
+ @Override
+ public Class<? super LogNormalDistribution> getDistributionClass() {
+ return LogNormalDistribution.class;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected LogNormalLogMADEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogNormalLogMOMEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogNormalLogMOMEstimator.java
new file mode 100644
index 00000000..5b753c54
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogNormalLogMOMEstimator.java
@@ -0,0 +1,74 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.MeanVariance;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.LogNormalDistribution;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Naive distribution estimation using mean and sample variance.
+ *
+ * This is a maximum-likelihood-estimator (MLE).
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has LogNormalDistribution - - estimates
+ */
+public class LogNormalLogMOMEstimator extends AbstractLogMeanVarianceEstimator<LogNormalDistribution> {
+ /**
+ * Static estimator, using mean and variance.
+ */
+ public static LogNormalLogMOMEstimator STATIC = new LogNormalLogMOMEstimator();
+
+ /**
+ * Private constructor, use static instance!
+ */
+ private LogNormalLogMOMEstimator() {
+ super();
+ }
+
+ @Override
+ public LogNormalDistribution estimateFromLogMeanVariance(MeanVariance mv, double shift) {
+ return new LogNormalDistribution(mv.getMean(), Math.max(mv.getSampleStddev(), Double.MIN_NORMAL), shift);
+ }
+
+ @Override
+ public Class<? super LogNormalDistribution> getDistributionClass() {
+ return LogNormalDistribution.class;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected LogNormalLogMOMEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogisticLMMEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogisticLMMEstimator.java
new file mode 100644
index 00000000..973a91de
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogisticLMMEstimator.java
@@ -0,0 +1,90 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.LogisticDistribution;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Estimate the parameters of a Logistic Distribution, using the methods of
+ * L-Moments (LMM).
+ *
+ * Reference:
+ * <p>
+ * J. R. M. Hosking<br />
+ * Fortran routines for use with the method of L-moments Version 3.03<br />
+ * IBM Research.
+ * </p>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has LogisticDistribution
+ */
+@Reference(authors = "J.R.M. Hosking", title = "Fortran routines for use with the method of L-moments Version 3.03", booktitle = "IBM Research Technical Report")
+public class LogisticLMMEstimator extends AbstractLMMEstimator<LogisticDistribution> {
+ /**
+ * Static instance.
+ */
+ public static final LogisticLMMEstimator STATIC = new LogisticLMMEstimator();
+
+ /**
+ * Constructor. Private: use static instance.
+ */
+ private LogisticLMMEstimator() {
+ super();
+ }
+
+ @Override
+ public int getNumMoments() {
+ return 2;
+ }
+
+ @Override
+ public LogisticDistribution estimateFromLMoments(double[] xmom) {
+ // The original publication would also estimate a shape, but we don't have
+ // the generalized logistic distribution yet.
+ // So we continue as if the Type II shape is 0, fairly trivial:
+ return new LogisticDistribution(xmom[0], xmom[1]);
+ }
+
+ @Override
+ public Class<? super LogisticDistribution> getDistributionClass() {
+ return LogisticDistribution.class;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected LogisticLMMEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogisticMADEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogisticMADEstimator.java
new file mode 100644
index 00000000..45181486
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/LogisticMADEstimator.java
@@ -0,0 +1,80 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.LogisticDistribution;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Estimate Logistic distribution parameters using Median and MAD.
+ *
+ * Reference:
+ * <p>
+ * Robust Estimators for Transformed Location Scale Families<br />
+ * D. J. Olive
+ * </p>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has LogisticDistribution
+ */
+@Reference(title = "Robust Estimators for Transformed Location Scale Families", authors = "D. J. Olive", booktitle = "")
+public class LogisticMADEstimator extends AbstractMADEstimator<LogisticDistribution> {
+ /**
+ * Static instance.
+ */
+ public static final LogisticMADEstimator STATIC = new LogisticMADEstimator();
+
+ /**
+ * Private constructor, use static instance!
+ */
+ private LogisticMADEstimator() {
+ // Do not instantiate
+ }
+
+ @Override
+ public LogisticDistribution estimateFromMedianMAD(double median, double mad) {
+ return new LogisticDistribution(median, mad / MathUtil.LOG3);
+ }
+
+ @Override
+ public Class<? super LogisticDistribution> getDistributionClass() {
+ return LogisticDistribution.class;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected LogisticMADEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/MADDistributionEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/MADDistributionEstimator.java
new file mode 100644
index 00000000..6bf2b3ae
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/MADDistributionEstimator.java
@@ -0,0 +1,45 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.Distribution;
+
+/**
+ * Distribuition estimators that use the method of moments (MOM), i.e. that only
+ * need the statistical moments of a data set.
+ *
+ * @author Erich Schubert
+ *
+ * @param <D> Distribution estimated.
+ */
+public interface MADDistributionEstimator<D extends Distribution> extends DistributionEstimator<D> {
+ /**
+ * General form of the parameter estimation
+ *
+ * @param median Median value
+ * @param mad Median absolute deviation from median
+ * @return Estimated distribution
+ */
+ D estimateFromMedianMAD(double median, double mad);
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/MOMDistributionEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/MOMDistributionEstimator.java
new file mode 100644
index 00000000..383f68cc
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/MOMDistributionEstimator.java
@@ -0,0 +1,45 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.math.StatisticalMoments;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.Distribution;
+
+/**
+ * Distribuition estimators that use the method of moments (MOM), i.e. that only
+ * need the statistical moments of a data set.
+ *
+ * @author Erich Schubert
+ *
+ * @param <D> Distribution estimated.
+ */
+public interface MOMDistributionEstimator<D extends Distribution> extends DistributionEstimator<D> {
+ /**
+ * General form of the parameter estimation
+ *
+ * @param moments Statistical moments
+ * @return Estimated distribution
+ */
+ D estimateFromStatisticalMoments(StatisticalMoments moments);
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/MeanVarianceDistributionEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/MeanVarianceDistributionEstimator.java
new file mode 100644
index 00000000..4d84465f
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/MeanVarianceDistributionEstimator.java
@@ -0,0 +1,45 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.Distribution;
+import de.lmu.ifi.dbs.elki.math.MeanVariance;
+
+/**
+ * Interface for estimators that only need mean and variance.
+ *
+ * These can implicitely (obviously) also handle full statistical moments.
+ *
+ * @author Erich Schubert
+ *
+ * @param <D> Distribution type
+ */
+public interface MeanVarianceDistributionEstimator<D extends Distribution> extends MOMDistributionEstimator<D> {
+ /**
+ * Estimate the distribution from mean and variance.
+ *
+ * @param mv Mean and variance.
+ * @return Distribution
+ */
+ D estimateFromMeanVariance(MeanVariance mv);
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/NormalLMMEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/NormalLMMEstimator.java
new file mode 100644
index 00000000..67880950
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/NormalLMMEstimator.java
@@ -0,0 +1,87 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.NormalDistribution;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Estimate the parameters of a normal distribution using the method of
+ * L-Moments (LMM).
+ *
+ * Reference:
+ * <p>
+ * J. R. M. Hosking<br />
+ * Fortran routines for use with the method of L-moments Version 3.03<br />
+ * IBM Research.
+ * </p>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has NormalDistribution
+ */
+@Reference(authors = "J.R.M. Hosking", title = "Fortran routines for use with the method of L-moments Version 3.03", booktitle = "IBM Research Technical Report")
+public class NormalLMMEstimator extends AbstractLMMEstimator<NormalDistribution> {
+ /**
+ * Static instance
+ */
+ public static final NormalLMMEstimator STATIC = new NormalLMMEstimator();
+
+ /**
+ * Constructor. Private: use static instance.
+ */
+ private NormalLMMEstimator() {
+ super();
+ }
+
+ @Override
+ public int getNumMoments() {
+ return 2;
+ }
+
+ @Override
+ public NormalDistribution estimateFromLMoments(double[] xmom) {
+ return new NormalDistribution(xmom[0], Math.max(xmom[1] * MathUtil.SQRTPI, Double.MIN_NORMAL));
+ }
+
+ @Override
+ public Class<? super NormalDistribution> getDistributionClass() {
+ return NormalDistribution.class;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected NormalLMMEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/NormalLevenbergMarquardtKDEEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/NormalLevenbergMarquardtKDEEstimator.java
new file mode 100644
index 00000000..bbbcda76
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/NormalLevenbergMarquardtKDEEstimator.java
@@ -0,0 +1,118 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import java.util.Arrays;
+
+import de.lmu.ifi.dbs.elki.math.MeanVariance;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.fitting.GaussianFittingFunction;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.fitting.LevenbergMarquardtMethod;
+import de.lmu.ifi.dbs.elki.math.statistics.KernelDensityEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.NormalDistribution;
+import de.lmu.ifi.dbs.elki.math.statistics.kernelfunctions.GaussianKernelDensityFunction;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Distribution parameter estimation using Levenberg-Marquardt iterative
+ * optimization and a kernel density estimation.
+ *
+ * Note: this estimator is rather expensive, and needs optimization in the KDE
+ * phase, which currently is O(n^2)!
+ *
+ * This estimator is primarily attractive when only part of the distribution was
+ * observed.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has NormalDistribution - - estimates
+ */
+public class NormalLevenbergMarquardtKDEEstimator implements DistributionEstimator<NormalDistribution> {
+ /**
+ * Static estimator for small sample sizes and <em>partial</em> data.
+ */
+ public static final NormalLevenbergMarquardtKDEEstimator STATIC = new NormalLevenbergMarquardtKDEEstimator();
+
+ /**
+ * Constructor. Private: use static instance.
+ */
+ private NormalLevenbergMarquardtKDEEstimator() {
+ super();
+ }
+
+ @Override
+ public <A> NormalDistribution estimate(A data, NumberArrayAdapter<?, A> adapter) {
+ // We first need the basic parameters:
+ final int len = adapter.size(data);
+ MeanVariance mv = new MeanVariance();
+ // X positions of samples
+ double[] x = new double[len];
+ for (int i = 0; i < len; i++) {
+ x[i] = adapter.getDouble(data, i);
+ mv.put(x[i]);
+ }
+ // Sort our copy.
+ Arrays.sort(x);
+ double median = (x[len >> 1] + x[(len + 1) >> 1]) * .5;
+
+ // Height = density, via KDE.
+ KernelDensityEstimator de = new KernelDensityEstimator(x, GaussianKernelDensityFunction.KERNEL, 1e-6);
+ double[] y = de.getDensity();
+
+ // Weights:
+ double[] s = new double[len];
+ Arrays.fill(s, 1.0);
+
+ // Initial parameter estimate:
+ double[] params = { median, mv.getSampleStddev(), 1 };
+ boolean[] dofit = { true, true, false };
+ LevenbergMarquardtMethod fit = new LevenbergMarquardtMethod(GaussianFittingFunction.STATIC, params, dofit, x, y, s);
+ fit.run();
+ double[] ps = fit.getParams();
+ return new NormalDistribution(ps[0], ps[1]);
+ }
+
+ @Override
+ public Class<? super NormalDistribution> getDistributionClass() {
+ return NormalDistribution.class;
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected NormalLevenbergMarquardtKDEEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/NormalMADEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/NormalMADEstimator.java
new file mode 100644
index 00000000..2221ad4b
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/NormalMADEstimator.java
@@ -0,0 +1,88 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.NormalDistribution;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Estimator using Medians. More robust to outliers, and just slightly more
+ * expensive (needs to copy the data for partial sorting to find the median).
+ *
+ * References:
+ * <p>
+ * F. R. Hampel<br />
+ * The Influence Curve and Its Role in Robust Estimation<br />
+ * in: Journal of the American Statistical Association, June 1974, Vol. 69, No.
+ * 346
+ * </p>
+ * <p>
+ * P. J. Rousseeuw, C. Croux<br />
+ * Alternatives to the Median Absolute Deviation<br />
+ * in: Journal of the American Statistical Association, December 1993, Vol. 88,
+ * No. 424, Theory and Methods
+ * </p>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has NormalDistribution - - estimates
+ */
+@Reference(authors = "F. R. Hampel", title = "The Influence Curve and Its Role in Robust Estimation", booktitle = "Journal of the American Statistical Association, June 1974, Vol. 69, No. 346", url = "http://www.jstor.org/stable/10.2307/2285666")
+public class NormalMADEstimator extends AbstractMADEstimator<NormalDistribution> {
+ /**
+ * Static estimator, more robust to outliers by using the median.
+ */
+ public static NormalMADEstimator STATIC = new NormalMADEstimator();
+
+ /**
+ * Constructor. Private: use static instance!
+ */
+ private NormalMADEstimator() {
+ super();
+ }
+
+ @Override
+ public NormalDistribution estimateFromMedianMAD(double median, double mad) {
+ return new NormalDistribution(median, Math.max(NormalDistribution.ONEBYPHIINV075 * mad, Double.MIN_NORMAL));
+ }
+
+ @Override
+ public Class<? super NormalDistribution> getDistributionClass() {
+ return NormalDistribution.class;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected NormalMADEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/NormalMOMEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/NormalMOMEstimator.java
new file mode 100644
index 00000000..dae05eb0
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/NormalMOMEstimator.java
@@ -0,0 +1,76 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.MeanVariance;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.NormalDistribution;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Naive maximum-likelihood estimations for the normal distribution using mean
+ * and sample variance.
+ *
+ * While this is the most commonly used estimator, it is not very robust against
+ * extreme values.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has NormalDistribution - - estimates
+ */
+public class NormalMOMEstimator extends AbstractMeanVarianceEstimator<NormalDistribution> {
+ /**
+ * Static estimator, using mean and variance.
+ */
+ public static NormalMOMEstimator STATIC = new NormalMOMEstimator();
+
+ /**
+ * Private constructor, use static instance!
+ */
+ private NormalMOMEstimator() {
+ // Do not instantiate
+ }
+
+ @Override
+ public NormalDistribution estimateFromMeanVariance(MeanVariance mv) {
+ return new NormalDistribution(mv.getMean(), Math.max(mv.getSampleStddev(), Double.MIN_NORMAL));
+ }
+
+ @Override
+ public Class<? super NormalDistribution> getDistributionClass() {
+ return NormalDistribution.class;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected NormalMOMEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/RayleighLMMEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/RayleighLMMEstimator.java
new file mode 100644
index 00000000..a827e1e8
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/RayleighLMMEstimator.java
@@ -0,0 +1,85 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.RayleighDistribution;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Estimate the scale parameter of a (non-shifted) RayleighDistribution using
+ * the method of L-Moments (LMM).
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has RayleighDistribution - - estimates
+ */
+public class RayleighLMMEstimator extends AbstractLMMEstimator<RayleighDistribution> {
+ /**
+ * Static instance.
+ */
+ public static final RayleighLMMEstimator STATIC = new RayleighLMMEstimator();
+
+ /**
+ * Constructor. Private: use static instance!
+ */
+ private RayleighLMMEstimator() {
+ super();
+ }
+
+ @Override
+ public int getNumMoments() {
+ return 2;
+ }
+
+ @Override
+ public RayleighDistribution estimateFromLMoments(double[] xmom) {
+ double sigma = 2. * xmom[1] / (MathUtil.SQRTPI * (MathUtil.SQRT2 - 1.));
+ double mu = xmom[0] - sigma * MathUtil.SQRTHALFPI;
+ return new RayleighDistribution(mu, sigma);
+ }
+
+ @Override
+ public Class<? super RayleighDistribution> getDistributionClass() {
+ return RayleighDistribution.class;
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected RayleighLMMEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/RayleighMADEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/RayleighMADEstimator.java
new file mode 100644
index 00000000..7382ada2
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/RayleighMADEstimator.java
@@ -0,0 +1,90 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.RayleighDistribution;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Estimate the parameters of a RayleighDistribution using the MAD.
+ *
+ * Reference:
+ * <p>
+ * D. J. Olive<br />
+ * Applied Robust Statistics<br />
+ * Preprint of an upcoming book, University of Minnesota
+ * </p>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has RayleighDistribution - - estimates
+ */
+@Reference(title = "Applied Robust Statistics", authors = "D. J. Olive", booktitle = "Applied Robust Statistics", url = "http://lagrange.math.siu.edu/Olive/preprints.htm")
+public class RayleighMADEstimator extends AbstractMADEstimator<RayleighDistribution> {
+ /**
+ * Static instance.
+ */
+ public static final RayleighMADEstimator STATIC = new RayleighMADEstimator();
+
+ /**
+ * Constructor. Private: use static instance!
+ */
+ private RayleighMADEstimator() {
+ super();
+ }
+
+ /**
+ * See reference for the derivation of this constants.
+ */
+ private static final double F1 = 1. / 0.448453, F2 = 1.17741 * F1;
+
+ @Override
+ public RayleighDistribution estimateFromMedianMAD(double median, double mad) {
+ return new RayleighDistribution(median - F2 * mad, F1 * mad);
+ }
+
+ @Override
+ public Class<? super RayleighDistribution> getDistributionClass() {
+ return RayleighDistribution.class;
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected RayleighMADEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/RayleighMLEEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/RayleighMLEEstimator.java
new file mode 100644
index 00000000..aa5dc300
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/RayleighMLEEstimator.java
@@ -0,0 +1,84 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.RayleighDistribution;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Estimate the scale parameter of a (non-shifted) RayleighDistribution using a
+ * maximum likelihood estimate.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has RayleighDistribution - - estimates
+ */
+public class RayleighMLEEstimator implements DistributionEstimator<RayleighDistribution> {
+ /**
+ * Static instance.
+ */
+ public static final RayleighMLEEstimator STATIC = new RayleighMLEEstimator();
+
+ /**
+ * Constructor. Private: use static instance!
+ */
+ private RayleighMLEEstimator() {
+ super();
+ }
+
+ @Override
+ public <A> RayleighDistribution estimate(A data, NumberArrayAdapter<?, A> adapter) {
+ final int len = adapter.size(data);
+ double sumsq = 0.;
+ for(int i = 0; i < len; i++) {
+ double v = adapter.getDouble(data, i);
+ sumsq += v * v;
+ }
+ return new RayleighDistribution(Math.sqrt(.5 * sumsq / len));
+ }
+
+ @Override
+ public Class<? super RayleighDistribution> getDistributionClass() {
+ return RayleighDistribution.class;
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected RayleighMLEEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/SkewGNormalLMMEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/SkewGNormalLMMEstimator.java
new file mode 100644
index 00000000..df05eef9
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/SkewGNormalLMMEstimator.java
@@ -0,0 +1,125 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.NormalDistribution;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.SkewGeneralizedNormalDistribution;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Estimate the parameters of a skew Normal Distribution (Hoskin's Generalized
+ * Normal Distribution), using the methods of L-Moments (LMM).
+ *
+ * Reference:
+ * <p>
+ * J. R. M. Hosking<br />
+ * Fortran routines for use with the method of L-moments Version 3.03<br />
+ * IBM Research.
+ * </p>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has SkewGeneralizedNormalDistribution
+ */
+@Reference(authors = "J.R.M. Hosking", title = "Fortran routines for use with the method of L-moments Version 3.03", booktitle = "IBM Research Technical Report")
+public class SkewGNormalLMMEstimator extends AbstractLMMEstimator<SkewGeneralizedNormalDistribution> {
+ /**
+ * Static instance.
+ */
+ public static final SkewGNormalLMMEstimator STATIC = new SkewGNormalLMMEstimator();
+
+ /** Polynomial approximation */
+ private static final double //
+ A0 = 0.20466534e+01, //
+ A1 = -0.36544371e+01, //
+ A2 = 0.18396733e+01, //
+ A3 = -0.20360244;
+
+ /** Polynomial approximation */
+ private static final double //
+ B1 = -0.20182173e+01, //
+ B2 = 0.12420401e+01, //
+ B3 = -0.21741801;
+
+ /**
+ * Constructor. Private: use static instance.
+ */
+ private SkewGNormalLMMEstimator() {
+ super();
+ }
+
+ @Override
+ public int getNumMoments() {
+ return 3;
+ }
+
+ @Override
+ public SkewGeneralizedNormalDistribution estimateFromLMoments(double[] xmom) {
+ if (!(xmom[1] > 0.) || !(Math.abs(xmom[2]) < 1.0)) {
+ throw new ArithmeticException("L-Moments invalid");
+ }
+ // Generalized Normal Distribution estimation:
+ double t3 = xmom[2];
+ final double location, scale, shape;
+ if (Math.abs(t3) >= .95) {
+ // Extreme skewness
+ location = 0.;
+ scale = -1.;
+ shape = 0.;
+ } else if (Math.abs(t3) <= 1e-8) {
+ // t3 effectively zero.
+ location = xmom[0];
+ scale = xmom[1] * MathUtil.SQRTPI;
+ shape = 0.;
+ } else {
+ final double tt = t3 * t3;
+ shape = -t3 * (A0 + tt * (A1 + tt * (A2 + tt * A3))) / (1. + tt * (B1 + tt * (B2 + tt * B3)));
+ final double e = Math.exp(.5 * shape * shape);
+ scale = xmom[1] * shape / (e * NormalDistribution.erf(.5 * shape));
+ location = xmom[0] + scale * (e - 1.) / shape;
+ }
+ return new SkewGeneralizedNormalDistribution(location, scale, shape);
+ }
+
+ @Override
+ public Class<? super SkewGeneralizedNormalDistribution> getDistributionClass() {
+ return SkewGeneralizedNormalDistribution.class;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected SkewGNormalLMMEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/UniformEnhancedMinMaxEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/UniformEnhancedMinMaxEstimator.java
new file mode 100644
index 00000000..834b0d94
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/UniformEnhancedMinMaxEstimator.java
@@ -0,0 +1,100 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.UniformDistribution;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Slightly improved estimation, that takes sample size into account and
+ * enhances the interval appropriately.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has UniformDistribution - - estimates
+ */
+public class UniformEnhancedMinMaxEstimator implements DistributionEstimator<UniformDistribution> {
+ /**
+ * Slightly more refined estimator: takes sample size into account.
+ */
+ public static final UniformEnhancedMinMaxEstimator STATIC = new UniformEnhancedMinMaxEstimator();
+
+ /**
+ * Constructor. Private: use static instance!
+ */
+ private UniformEnhancedMinMaxEstimator() {
+ super();
+ }
+
+ @Override
+ public <A> UniformDistribution estimate(A data, NumberArrayAdapter<?, A> adapter) {
+ final int len = adapter.size(data);
+ DoubleMinMax mm = new DoubleMinMax();
+ for (int i = 0; i < len; i++) {
+ final double val = adapter.getDouble(data, i);
+ if (val > Double.NEGATIVE_INFINITY && val < Double.POSITIVE_INFINITY) {
+ mm.put(val);
+ }
+ }
+ return estimate(mm.getMin(), mm.getMax(), len);
+ }
+
+ /**
+ * Estimate from simple characteristics.
+ *
+ * @param min Minimum
+ * @param max Maximum
+ * @param count Number of observations
+ * @return Distribution
+ */
+ public UniformDistribution estimate(double min, double max, final int count) {
+ double grow = (count > 1) ? 0.5 * (max - min) / (count - 1) : 0.;
+ return new UniformDistribution(Math.max(min - grow, -Double.MAX_VALUE), Math.min(max + grow, Double.MAX_VALUE));
+ }
+
+ @Override
+ public Class<? super UniformDistribution> getDistributionClass() {
+ return UniformDistribution.class;
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected UniformEnhancedMinMaxEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/UniformLMMEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/UniformLMMEstimator.java
new file mode 100644
index 00000000..5b3e868f
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/UniformLMMEstimator.java
@@ -0,0 +1,77 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.UniformDistribution;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Estimate the parameters of a normal distribution using the method of
+ * L-Moments (LMM).
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has UniformDistribution
+ */
+public class UniformLMMEstimator extends AbstractLMMEstimator<UniformDistribution> {
+ /**
+ * Static instance
+ */
+ public static final UniformLMMEstimator STATIC = new UniformLMMEstimator();
+
+ /**
+ * Constructor. Private: use static instance.
+ */
+ private UniformLMMEstimator() {
+ super();
+ }
+
+ @Override
+ public int getNumMoments() {
+ return 2;
+ }
+
+ @Override
+ public UniformDistribution estimateFromLMoments(double[] xmom) {
+ return new UniformDistribution(Math.max(xmom[0] - 3 * xmom[1], -Double.MAX_VALUE), Math.min(xmom[0] + 3 * xmom[1], Double.MAX_VALUE));
+ }
+
+ @Override
+ public Class<? super UniformDistribution> getDistributionClass() {
+ return UniformDistribution.class;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected UniformLMMEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/UniformMADEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/UniformMADEstimator.java
new file mode 100644
index 00000000..47dad134
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/UniformMADEstimator.java
@@ -0,0 +1,80 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.UniformDistribution;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Estimate Uniform distribution parameters using Median and MAD.
+ *
+ * Reference:
+ * <p>
+ * D. J. Olive<br />
+ * Applied Robust Statistics<br />
+ * Preprint of an upcoming book, University of Minnesota
+ * </p>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has UniformDistribution
+ */
+@Reference(title = "Applied Robust Statistics", authors = "D. J. Olive", booktitle = "Applied Robust Statistics", url="http://lagrange.math.siu.edu/Olive/preprints.htm")
+public class UniformMADEstimator extends AbstractMADEstimator<UniformDistribution> {
+ /**
+ * Static instance.
+ */
+ public static final UniformMADEstimator STATIC = new UniformMADEstimator();
+
+ /**
+ * Private constructor, use static instance!
+ */
+ private UniformMADEstimator() {
+ // Do not instantiate
+ }
+
+ @Override
+ public UniformDistribution estimateFromMedianMAD(double median, double mad) {
+ return new UniformDistribution(Math.max(median - 2 * mad, -Double.MAX_VALUE), Math.min(median + 2 * mad, Double.MAX_VALUE));
+ }
+
+ @Override
+ public Class<? super UniformDistribution> getDistributionClass() {
+ return UniformDistribution.class;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected UniformMADEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/UniformMinMaxEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/UniformMinMaxEstimator.java
new file mode 100644
index 00000000..e9870884
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/UniformMinMaxEstimator.java
@@ -0,0 +1,107 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.Distribution;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.UniformDistribution;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Estimate the uniform distribution by computing min and max.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has UniformDistribution - - estimates
+ */
+public class UniformMinMaxEstimator implements DistributionEstimator<UniformDistribution> {
+ /**
+ * The most naive estimator possible: uses minimum and maximum.
+ */
+ public static final UniformMinMaxEstimator STATIC = new UniformMinMaxEstimator();
+
+ /**
+ * Constructor. Private: use static instance!
+ */
+ private UniformMinMaxEstimator() {
+ super();
+ }
+
+ @Override
+ public <A> UniformDistribution estimate(A data, NumberArrayAdapter<?, A> adapter) {
+ final int len = adapter.size(data);
+ DoubleMinMax mm = new DoubleMinMax();
+ for (int i = 0; i < len; i++) {
+ final double val = adapter.getDouble(data, i);
+ if (val > Double.NEGATIVE_INFINITY && val < Double.POSITIVE_INFINITY) {
+ mm.put(val);
+ }
+ }
+ return estimate(mm);
+ }
+
+ /**
+ * Estimate parameters from minimum and maximum observed.
+ *
+ * @param mm Minimum and Maximum
+ * @return Estimation
+ */
+ public UniformDistribution estimate(DoubleMinMax mm) {
+ return new UniformDistribution(Math.max(mm.getMin(), -Double.MAX_VALUE), Math.min(mm.getMax(), Double.MAX_VALUE));
+ }
+
+ /**
+ * Estimate parameters from minimum and maximum observed.
+ *
+ * @param mm Minimum and Maximum
+ * @return Estimation
+ */
+ public Distribution estimate(double min, double max) {
+ return new UniformDistribution(min, max);
+ }
+
+ @Override
+ public Class<? super UniformDistribution> getDistributionClass() {
+ return UniformDistribution.class;
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected UniformMinMaxEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/WaldMLEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/WaldMLEstimator.java
new file mode 100644
index 00000000..16a33f89
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/WaldMLEstimator.java
@@ -0,0 +1,85 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.WaldDistribution;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Estimate parameter of the Wald distribution.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has WaldDistribution
+ */
+public class WaldMLEstimator implements DistributionEstimator<WaldDistribution> {
+ /**
+ * Static instance.
+ */
+ public static final WaldMLEstimator STATIC = new WaldMLEstimator();
+
+ @Override
+ public <A> WaldDistribution estimate(A data, NumberArrayAdapter<?, A> adapter) {
+ final int len = adapter.size(data);
+ double mean = 0.;
+ for(int i = 0; i < len; i++) {
+ double v = adapter.getDouble(data, i);
+ mean += v;
+ }
+ mean /= len;
+ double invmean = 1. / mean;
+ double invdev = 0.;
+ for(int i = 0; i < len; i++) {
+ double v = adapter.getDouble(data, i);
+ if(v > 0.) {
+ invdev += 1. / v - invmean;
+ }
+ }
+ return new WaldDistribution(mean, len / invdev);
+ }
+
+ @Override
+ public Class<? super WaldDistribution> getDistributionClass() {
+ return WaldDistribution.class;
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected WaldMLEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/WaldMOMEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/WaldMOMEstimator.java
new file mode 100644
index 00000000..82b70936
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/WaldMOMEstimator.java
@@ -0,0 +1,71 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.MeanVariance;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.WaldDistribution;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Estimate parameter of the Wald distribution.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has WaldDistribution
+ */
+public class WaldMOMEstimator extends AbstractMeanVarianceEstimator<WaldDistribution> {
+ /**
+ * Static instance.
+ */
+ public static final WaldMOMEstimator STATIC = new WaldMOMEstimator();
+
+ @Override
+ public WaldDistribution estimateFromMeanVariance(MeanVariance mv) {
+ double mean = mv.getMean();
+ return new WaldDistribution(mean, mean * mean * mean / mv.getSampleVariance());
+ }
+
+ @Override
+ public Class<? super WaldDistribution> getDistributionClass() {
+ return WaldDistribution.class;
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected WaldMOMEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/WeibullLMMEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/WeibullLMMEstimator.java
new file mode 100644
index 00000000..9d7d8e8e
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/WeibullLMMEstimator.java
@@ -0,0 +1,85 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.GammaDistribution;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.WeibullDistribution;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Estimate parameters of the Weibull distribution using the method of L-Moments
+ * (LMM).
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has WeibullDistribution
+ */
+public class WeibullLMMEstimator extends AbstractLMMEstimator<WeibullDistribution> {
+ /**
+ * Static instance.
+ */
+ public static final WeibullLMMEstimator STATIC = new WeibullLMMEstimator();
+
+ /**
+ * Constructor. Private: use static instance!
+ */
+ private WeibullLMMEstimator() {
+ super();
+ }
+
+ @Override
+ public int getNumMoments() {
+ return 3;
+ }
+
+ @Override
+ public WeibullDistribution estimateFromLMoments(double[] xmom) {
+ double l = xmom[2], l2 = l * l, l3 = l2 * l, l4 = l3 * l, l5 = l4 * l, l6 = l5 * l;
+ double k = 285.3 * l6 - 658.6 * l5 + 622.8 * l4 - 317.2 * l3 + 98.52 * l2 - 21.256 * l + 3.516;
+
+ double gam = GammaDistribution.gamma(1. + 1. / k);
+ double lambda = xmom[1] / (1. - Math.pow(2., -1. / k) * gam);
+ double mu = xmom[0] - lambda * gam;
+
+ return new WeibullDistribution(k, lambda, mu);
+ }
+
+ @Override
+ public Class<? super WeibullDistribution> getDistributionClass() {
+ return WeibullDistribution.class;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected WeibullLMMEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/WeibullLogMADEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/WeibullLogMADEstimator.java
new file mode 100644
index 00000000..aacceae7
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/WeibullLogMADEstimator.java
@@ -0,0 +1,85 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.WeibullDistribution;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Parameter estimation via median and median absolute deviation from median
+ * (MAD).
+ *
+ * Reference:
+ * <p>
+ * D. J. Olive<br />
+ * Applied Robust Statistics<br />
+ * Preprint of an upcoming book, University of Minnesota
+ * </p>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has WeibullDistribution - - estimates
+ */
+@Reference(title = "Applied Robust Statistics", authors = "D. J. Olive", booktitle = "Applied Robust Statistics", url="http://lagrange.math.siu.edu/Olive/preprints.htm")
+public class WeibullLogMADEstimator extends AbstractLogMADEstimator<WeibullDistribution> {
+ /**
+ * The more robust median based estimator.
+ */
+ public static final WeibullLogMADEstimator STATIC = new WeibullLogMADEstimator();
+
+ /**
+ * Constructor. Private: use static instance!
+ */
+ private WeibullLogMADEstimator() {
+ super();
+ }
+
+ @Override
+ public WeibullDistribution estimateFromLogMedianMAD(double median, double mad, double shift) {
+ double isigma = 1.30370 / mad;
+ double lambda = Math.exp(isigma * median - MathUtil.LOGLOG2);
+
+ return new WeibullDistribution(isigma, lambda);
+ }
+
+ @Override
+ public Class<? super WeibullDistribution> getDistributionClass() {
+ return WeibullDistribution.class;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected WeibullLogMADEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/WeibullLogMOMEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/WeibullLogMOMEstimator.java
new file mode 100644
index 00000000..9182a7ce
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/WeibullLogMOMEstimator.java
@@ -0,0 +1,101 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.math.MeanVariance;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.WeibullDistribution;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Naive parameter estimation via least squares.
+ *
+ * TODO: this doesn't seem to work very well yet. Buggy?
+ *
+ * TODO: the naming is misleading: while it uses some method of moments, it
+ * doesn't use "the" statistical moments.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has WeibullDistribution - - estimates
+ */
+public class WeibullLogMOMEstimator implements DistributionEstimator<WeibullDistribution> {
+ /**
+ * The naive least-squares estimator.
+ */
+ public static final WeibullLogMOMEstimator STATIC = new WeibullLogMOMEstimator();
+
+ /**
+ * Constructor. Private: use static instance!
+ */
+ private WeibullLogMOMEstimator() {
+ super();
+ }
+
+ @Override
+ public <A> WeibullDistribution estimate(A data, NumberArrayAdapter<?, A> adapter) {
+ double beta1 = 0.0, beta3 = 0.0;
+ MeanVariance mvlogx = new MeanVariance();
+ int size = adapter.size(data);
+ double size1 = size + 1.;
+ for (int i = 0; i < size; i++) {
+ final double val = adapter.getDouble(data, i);
+ if (!(val > 0)) {
+ throw new ArithmeticException("Cannot least squares fit weibull to a data set which includes non-positive values: " + val);
+ }
+ final double yi = Math.log(-Math.log((size - i) / size1));
+ final double logxi = Math.log(val);
+ beta1 += yi * logxi;
+ beta3 += yi;
+ mvlogx.put(logxi);
+ }
+ double k = (beta1 / size - beta3 / size * mvlogx.getMean()) / mvlogx.getSampleVariance();
+ double lambda = 1. / Math.exp(beta3 / size - k * mvlogx.getMean());
+
+ return new WeibullDistribution(k, lambda);
+ }
+
+ @Override
+ public Class<? super WeibullDistribution> getDistributionClass() {
+ return WeibullDistribution.class;
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected WeibullLogMOMEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/meta/BestFitEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/meta/BestFitEstimator.java
new file mode 100644
index 00000000..dee3cbb3
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/meta/BestFitEstimator.java
@@ -0,0 +1,472 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.meta;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
+import de.lmu.ifi.dbs.elki.math.StatisticalMoments;
+import de.lmu.ifi.dbs.elki.math.statistics.ProbabilityWeightedMoments;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.Distribution;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.UniformDistribution;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.CauchyMADEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.DistributionEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.EMGOlivierNorbergEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.ExponentialLMMEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.ExponentialMADEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.ExponentialMOMEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.ExponentialMedianEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.GammaLMMEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.GammaMADEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.GammaMOMEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.GeneralizedExtremeValueLMMEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.GeneralizedLogisticAlternateLMMEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.GumbelLMMEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.GumbelMADEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.LMMDistributionEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.LaplaceLMMEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.LaplaceMADEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.LogGammaLogMADEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.LogGammaLogMOMEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.LogLogisticMADEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.LogMADDistributionEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.LogMOMDistributionEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.LogNormalBilkovaLMMEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.LogNormalLMMEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.LogNormalLogMADEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.LogNormalLogMOMEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.LogisticLMMEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.LogisticMADEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.MADDistributionEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.MOMDistributionEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.NormalLMMEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.NormalMADEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.NormalMOMEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.RayleighLMMEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.RayleighMADEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.SkewGNormalLMMEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.UniformEnhancedMinMaxEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.UniformLMMEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.UniformMADEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.UniformMinMaxEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.WaldMOMEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.WeibullLMMEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.WeibullLogMADEstimator;
+import de.lmu.ifi.dbs.elki.math.statistics.tests.KolmogorovSmirnovTest;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.QuickSelect;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayLikeUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * A meta estimator that will try a number of (inexpensive) estimations, then
+ * choose whichever works best.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.composedOf MOMDistributionEstimator
+ * @apiviz.composedOf MADDistributionEstimator
+ * @apiviz.composedOf LMMDistributionEstimator
+ * @apiviz.composedOf LogMOMDistributionEstimator
+ * @apiviz.composedOf LogMADDistributionEstimator
+ */
+public class BestFitEstimator implements DistributionEstimator<Distribution> {
+ /**
+ * Class logger.
+ */
+ private static final Logging LOG = Logging.getLogger(BestFitEstimator.class);
+
+ /**
+ * Static instance.
+ */
+ public static final BestFitEstimator STATIC = new BestFitEstimator();
+
+ /**
+ * Mean and variance based estimators.
+ */
+ private Collection<MOMDistributionEstimator<?>> momests;
+
+ /**
+ * Median average deviation from median estimators.
+ */
+ private Collection<MADDistributionEstimator<?>> madests;
+
+ /**
+ * L-Moment estimators.
+ */
+ private Collection<LMMDistributionEstimator<?>> lmmests;
+
+ /**
+ * Logspace Method of Moments estimators.
+ */
+ private Collection<LogMOMDistributionEstimator<?>> logmomests;
+
+ /**
+ * Logspace Median average deviation from median estimators.
+ */
+ private Collection<LogMADDistributionEstimator<?>> logmadests;
+
+ /**
+ * Constructor. Use static instance instead!
+ */
+ protected BestFitEstimator() {
+ super();
+ momests = new ArrayList<>(5);
+ momests.add(NormalMOMEstimator.STATIC);
+ momests.add(GammaMOMEstimator.STATIC);
+ momests.add(WaldMOMEstimator.STATIC);
+ momests.add(ExponentialMOMEstimator.STATIC);
+ momests.add(EMGOlivierNorbergEstimator.STATIC);
+ madests = new ArrayList<>(11);
+ madests.add(NormalMADEstimator.STATIC);
+ madests.add(GammaMADEstimator.STATIC);
+ madests.add(ExponentialMADEstimator.STATIC);
+ madests.add(ExponentialMedianEstimator.STATIC);
+ madests.add(LaplaceMADEstimator.STATIC);
+ madests.add(GumbelMADEstimator.STATIC);
+ madests.add(CauchyMADEstimator.STATIC);
+ madests.add(LogisticMADEstimator.STATIC);
+ madests.add(LogLogisticMADEstimator.STATIC);
+ madests.add(RayleighMADEstimator.STATIC);
+ madests.add(UniformMADEstimator.STATIC);
+ lmmests = new ArrayList<>(14);
+ lmmests.add(NormalLMMEstimator.STATIC);
+ lmmests.add(GammaLMMEstimator.STATIC);
+ lmmests.add(ExponentialLMMEstimator.STATIC);
+ lmmests.add(LaplaceLMMEstimator.STATIC);
+ lmmests.add(GumbelLMMEstimator.STATIC);
+ lmmests.add(LogisticLMMEstimator.STATIC);
+ lmmests.add(GeneralizedLogisticAlternateLMMEstimator.STATIC);
+ lmmests.add(LogNormalLMMEstimator.STATIC);
+ lmmests.add(LogNormalBilkovaLMMEstimator.STATIC);
+ lmmests.add(SkewGNormalLMMEstimator.STATIC);
+ lmmests.add(GeneralizedExtremeValueLMMEstimator.STATIC);
+ lmmests.add(RayleighLMMEstimator.STATIC);
+ lmmests.add(WeibullLMMEstimator.STATIC);
+ lmmests.add(UniformLMMEstimator.STATIC);
+ logmomests = new ArrayList<>(2);
+ logmomests.add(LogNormalLogMOMEstimator.STATIC);
+ logmomests.add(LogGammaLogMOMEstimator.STATIC);
+ logmadests = new ArrayList<>(3);
+ logmadests.add(LogNormalLogMADEstimator.STATIC);
+ logmadests.add(LogGammaLogMADEstimator.STATIC);
+ logmadests.add(WeibullLogMADEstimator.STATIC);
+ }
+
+ @Override
+ public <A> Distribution estimate(A data, NumberArrayAdapter<?, A> adapter) {
+ int numlmm = 0;
+ for (LMMDistributionEstimator<?> est : lmmests) {
+ numlmm = Math.max(numlmm, est.getNumMoments());
+ }
+
+ final int len = adapter.size(data);
+
+ // Build various statistics:
+ StatisticalMoments mom = new StatisticalMoments(), logmom = new StatisticalMoments();
+ double[] x = new double[len], scratch = new double[len], logx = new double[len];
+
+ if (LOG.isDebuggingFine()) {
+ LOG.debugFine("Computing statistical moments and L-Moments.");
+ }
+ for (int i = 0; i < len; i++) {
+ final double val = adapter.getDouble(data, i);
+ x[i] = val;
+ mom.put(val);
+ }
+ if (mom.getMax() <= mom.getMin()) {
+ LOG.warning("Constant distribution detected. Cannot fit.");
+ return new UniformDistribution(mom.getMin() - .1, mom.getMax() + .1);
+ }
+ // Sort: for L-Moments, but getting the median is now also cheap.
+ Arrays.sort(x);
+ double[] lmm;
+ try {
+ lmm = (numlmm > 0) ? ProbabilityWeightedMoments.samLMR(x, ArrayLikeUtil.DOUBLEARRAYADAPTER, numlmm) : null;
+ } catch (ArithmeticException e) {
+ lmm = null;
+ }
+ final double min = x[0], median = .5 * (x[len >> 1] + x[(len + 1) >> 1]), max = x[len - 1];
+ if (LOG.isDebuggingFine()) {
+ LOG.debugFine("Computing statistical moments in logspace.");
+ }
+ // Build logspace copy:
+ double shift = Math.min(0., min - (max - min) * 1e-10);
+ for (int i = 0; i < len; i++) {
+ double val = x[i] - shift;
+ val = val > 0. ? Math.log(val) : Double.NEGATIVE_INFINITY;
+ logx[i] = val;
+ if (!Double.isInfinite(val) && !Double.isNaN(val)) {
+ logmom.put(val);
+ }
+ }
+ double logmedian = .5 * (logx[len >> 1] + logx[(len + 1) >> 1]);
+ if (LOG.isDebuggingFine()) {
+ LOG.debugFine("Computing MADs.");
+ }
+ double mad = computeMAD(x, median, scratch, len);
+ double logmad = computeMAD(logx, logmedian, scratch, len);
+
+ Distribution best = null;
+ double bestscore = Double.POSITIVE_INFINITY;
+ DistributionEstimator<?> bestest = null;
+
+ final int numest = momests.size() + madests.size() + lmmests.size() + logmomests.size() + logmadests.size() + 2;
+ FiniteProgress prog = LOG.isDebuggingFine() ? new FiniteProgress("Finding best matching distribution", numest, LOG) : null;
+ for (MOMDistributionEstimator<?> est : momests) {
+ try {
+ Distribution d = est.estimateFromStatisticalMoments(mom);
+ double score = testFit(x, scratch, d);
+ if (LOG.isDebuggingFine()) {
+ LOG.debugFine(est.getClass().getSimpleName() + ": " + score + " " + d.toString());
+ }
+ if (score < bestscore) {
+ best = d;
+ bestscore = score;
+ bestest = est;
+ }
+ } catch (ArithmeticException e) {
+ if (LOG.isDebuggingFine()) {
+ LOG.debugFine("Fitting distribution " + est.getClass().getSimpleName() + " failed: " + e.getMessage());
+ }
+ }
+ if (prog != null) {
+ prog.incrementProcessed(LOG);
+ }
+ }
+ for (MADDistributionEstimator<?> est : madests) {
+ try {
+ Distribution d = est.estimateFromMedianMAD(median, mad);
+ double score = testFit(x, scratch, d);
+ if (LOG.isDebuggingFine()) {
+ LOG.debugFine(est.getClass().getSimpleName() + ": " + score + " " + d.toString());
+ }
+ if (score < bestscore) {
+ best = d;
+ bestscore = score;
+ bestest = est;
+ }
+ } catch (ArithmeticException e) {
+ if (LOG.isDebuggingFine()) {
+ LOG.debugFine("Fitting distribution " + est.getClass().getSimpleName() + " failed: " + e.getMessage());
+ }
+ }
+ if (prog != null) {
+ prog.incrementProcessed(LOG);
+ }
+ }
+ for (LMMDistributionEstimator<?> est : lmmests) {
+ if (lmm != null) {
+ try {
+ Distribution d = est.estimateFromLMoments(lmm);
+ double score = testFit(x, scratch, d);
+ if (LOG.isDebuggingFine()) {
+ LOG.debugFine(est.getClass().getSimpleName() + ": " + score + " " + d.toString());
+ }
+ if (score < bestscore) {
+ best = d;
+ bestscore = score;
+ bestest = est;
+ }
+ } catch (ArithmeticException e) {
+ if (LOG.isDebuggingFine()) {
+ LOG.debugFine("Fitting distribution " + est.getClass().getSimpleName() + " failed: " + e.getMessage());
+ }
+ }
+ }
+ if (prog != null) {
+ prog.incrementProcessed(LOG);
+ }
+ }
+ for (LogMOMDistributionEstimator<?> est : logmomests) {
+ try {
+ Distribution d = est.estimateFromLogStatisticalMoments(logmom, shift);
+ double score = testFit(x, scratch, d);
+ if (LOG.isDebuggingFine()) {
+ LOG.debugFine(est.getClass().getSimpleName() + ": " + score + " " + d.toString());
+ }
+ if (score < bestscore) {
+ best = d;
+ bestscore = score;
+ bestest = est;
+ }
+ } catch (ArithmeticException e) {
+ if (LOG.isDebuggingFine()) {
+ LOG.debugFine("Fitting distribution " + est.getClass().getSimpleName() + " failed: " + e.getMessage());
+ }
+ }
+ if (prog != null) {
+ prog.incrementProcessed(LOG);
+ }
+ }
+ for (LogMADDistributionEstimator<?> est : logmadests) {
+ try {
+ Distribution d = est.estimateFromLogMedianMAD(logmedian, logmad, shift);
+ double score = testFit(x, scratch, d);
+ if (LOG.isDebuggingFine()) {
+ LOG.debugFine(est.getClass().getSimpleName() + ": " + score + " " + d.toString());
+ }
+ if (score < bestscore) {
+ best = d;
+ bestscore = score;
+ bestest = est;
+ }
+ } catch (ArithmeticException e) {
+ if (LOG.isDebuggingFine()) {
+ LOG.debugFine("Fitting distribution " + est.getClass().getSimpleName() + " failed: " + e.getMessage());
+ }
+ }
+ if (prog != null) {
+ prog.incrementProcessed(LOG);
+ }
+ }
+ { // Uniform estimators.
+ final UniformMinMaxEstimator est = UniformMinMaxEstimator.STATIC;
+ try {
+ Distribution d = est.estimate(min, max);
+ double score = testFit(x, scratch, d);
+ if (LOG.isDebuggingFine()) {
+ LOG.debugFine(est.getClass().getSimpleName() + ": " + score + " " + d.toString());
+ }
+ if (score < bestscore) {
+ best = d;
+ bestscore = score;
+ bestest = est;
+ }
+ } catch (ArithmeticException e) {
+ if (LOG.isDebuggingFine()) {
+ LOG.debugFine("Fitting distribution " + est.getClass().getSimpleName() + " failed: " + e.getMessage());
+ }
+ }
+ if (prog != null) {
+ prog.incrementProcessed(LOG);
+ }
+ }
+ { // Uniform estimators.
+ final UniformEnhancedMinMaxEstimator est = UniformEnhancedMinMaxEstimator.STATIC;
+ try {
+ Distribution d = est.estimate(min, max, len);
+ double score = testFit(x, scratch, d);
+ if (LOG.isDebuggingFine()) {
+ LOG.debugFine(est.getClass().getSimpleName() + ": " + score + " " + d.toString());
+ }
+ if (score < bestscore) {
+ best = d;
+ bestscore = score;
+ bestest = est;
+ }
+ } catch (ArithmeticException e) {
+ if (LOG.isDebuggingFine()) {
+ LOG.debugFine("Fitting distribution " + est.getClass().getSimpleName() + " failed: " + e.getMessage());
+ }
+ }
+ if (prog != null) {
+ prog.incrementProcessed(LOG);
+ }
+ }
+ if (prog != null) {
+ prog.ensureCompleted(LOG);
+ }
+
+ if (LOG.isVeryVerbose()) {
+ LOG.veryverbose("Best distribution fit: " + bestscore + " " + best.toString() + " via " + bestest);
+ }
+
+ return best;
+ }
+
+ public double computeMAD(double[] data, double median, double[] scratch, final int len) {
+ // Compute LogMAD:
+ for (int i = 0; i < len; i++) {
+ scratch[i] = Math.abs(data[i] - median);
+ }
+ double logmad = QuickSelect.median(scratch);
+ // Adjust LogMAD if 0:
+ if (!(logmad > 0.)) {
+ double xmin = Double.POSITIVE_INFINITY;
+ for (int i = (len >> 1); i < len; i++) {
+ if (scratch[i] > 0. && scratch[i] < xmin) {
+ xmin = scratch[i];
+ }
+ }
+ if (!Double.isInfinite(xmin)) {
+ logmad = xmin;
+ }
+ }
+ return logmad;
+ }
+
+ /**
+ * Test the quality of a fit.
+ *
+ * @param x Input data
+ * @param test Scratch space for testing (will be overwritten!)
+ * @param dist Distribution
+ * @return K-S-Test score
+ * @throws ArithmeticException
+ */
+ private double testFit(double[] x, double[] test, Distribution dist) throws ArithmeticException {
+ for (int i = 0; i < test.length; i++) {
+ test[i] = dist.cdf(x[i]);
+ if (test[i] > 1.) {
+ test[i] = 1.;
+ }
+ if (test[i] < 0.) {
+ test[i] = 0.;
+ }
+ if (Double.isNaN(test[i])) {
+ throw new ArithmeticException("Got NaN after fitting " + dist.toString());
+ }
+ }
+ // Should actually be sorted already...
+ Arrays.sort(test);
+ return KolmogorovSmirnovTest.simpleTest(test);
+ }
+
+ @Override
+ public Class<? super Distribution> getDistributionClass() {
+ return Distribution.class; // No guarantees, sorry.
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName();
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected BestFitEstimator makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/meta/TrimmedEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/meta/TrimmedEstimator.java
new file mode 100644
index 00000000..5c1cf448
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/meta/TrimmedEstimator.java
@@ -0,0 +1,156 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.meta;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.Arrays;
+
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.Distribution;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.DistributionEstimator;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayLikeUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.LessConstraint;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleParameter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
+
+/**
+ * Trimmed wrapper around other estimators. Sorts the data, trims it, then
+ * analyzes it using another estimator.
+ *
+ * @author Erich Schubert
+ *
+ * @param <D> Distribution type
+ */
+public class TrimmedEstimator<D extends Distribution> implements DistributionEstimator<D> {
+ /**
+ * Distribution estimator to use.
+ */
+ private DistributionEstimator<D> inner;
+
+ /**
+ * Amount of data to trim.
+ */
+ private double trim;
+
+ /**
+ * Constructor.
+ *
+ * @param inner Inner estimator.
+ * @param trim Trimming parameter.
+ */
+ public TrimmedEstimator(DistributionEstimator<D> inner, double trim) {
+ super();
+ this.inner = inner;
+ this.trim = trim;
+ }
+
+ @Override
+ public <A> D estimate(A data, NumberArrayAdapter<?, A> adapter) {
+ // We first need the basic parameters:
+ int len = adapter.size(data);
+ final int cut = ((int) (len * trim)) >> 1;
+ // X positions of samples
+ double[] x = new double[len];
+ for (int i = 0; i < len; i++) {
+ final double val = adapter.getDouble(data, i);
+ x[i] = val;
+ }
+ // Sort our copy.
+ Arrays.sort(x);
+ { // Trim:
+ // TODO: is it more efficient to just copy, or instead use a trimmed array
+ // adapter?
+ double[] trimmed = new double[len - 2 * cut];
+ System.arraycopy(x, cut, trimmed, 0, trimmed.length);
+ x = trimmed;
+ len = trimmed.length;
+ }
+ return inner.estimate(x, ArrayLikeUtil.DOUBLEARRAYADAPTER);
+ }
+
+ @Override
+ public Class<? super D> getDistributionClass() {
+ return inner.getDistributionClass();
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName() + "(" + inner.toString() + ", trim=" + trim + ")";
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ *
+ * @param <D> Distribution type
+ */
+ public static class Parameterizer<D extends Distribution> extends AbstractParameterizer {
+ /**
+ * Option for the class to use on the trimmed sample.
+ */
+ public static final OptionID INNER_ID = new OptionID("trimmedestimate.inner", "Estimator to use on the trimmed data.");
+
+ /**
+ * Option for specifying the amount of data to trim.
+ */
+ public static final OptionID TRIM_ID = new OptionID("trimmedestimate.trim", "Relative amount of data to trim on each end, must be 0 < trim < 0.5");
+
+ /**
+ * Distribution estimator to use.
+ */
+ private DistributionEstimator<D> inner;
+
+ /**
+ * Amount of data to trim.
+ */
+ private double trim;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ ObjectParameter<DistributionEstimator<D>> innerP = new ObjectParameter<>(INNER_ID, DistributionEstimator.class);
+ if (config.grab(innerP)) {
+ inner = innerP.instantiateClass(config);
+ }
+
+ DoubleParameter trimP = new DoubleParameter(TRIM_ID);
+ trimP.addConstraint(new GreaterConstraint(0.));
+ trimP.addConstraint(new LessConstraint(0.5));
+ if (config.grab(trimP)) {
+ trim = trimP.doubleValue();
+ }
+ }
+
+ @Override
+ protected TrimmedEstimator<D> makeInstance() {
+ return new TrimmedEstimator<>(inner, trim);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/meta/WinsorisingEstimator.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/meta/WinsorisingEstimator.java
new file mode 100644
index 00000000..0ef6318d
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/meta/WinsorisingEstimator.java
@@ -0,0 +1,166 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.meta;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.Distribution;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.DistributionEstimator;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.QuickSelect;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayLikeUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.LessConstraint;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleParameter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
+
+/**
+ * Winsorising or Georgization estimator. Similar to trimming, this is expected
+ * to be more robust to outliers. However, instead of removing the extreme
+ * values, they are instead replaced with the cutoff value. This keeps the
+ * quantity of the data the same, and will have a lower impact on variance and
+ * similar measures.
+ *
+ * Reference:
+ * <p>
+ * C. Hastings, F. Mosteller, J. W. Tukey, C. P. Winsor<br />
+ * Low moments for small samples: a comparative study of order statistics.<br />
+ * The Annals of Mathematical Statistics, 18(3) *
+ * </p>
+ *
+ * @author Erich Schubert
+ *
+ * @param <D> Distribution type
+ */
+@Reference(authors = "C. Hastings, F. Mosteller, J. W. Tukey, C. P. Winsor", title = "Low moments for small samples: a comparative study of order statistics", booktitle = "The Annals of Mathematical Statistics, 18(3)", url = "http://dx.doi.org/10.1214/aoms/1177730388")
+public class WinsorisingEstimator<D extends Distribution> implements DistributionEstimator<D> {
+ /**
+ * Distribution estimator to use.
+ */
+ private DistributionEstimator<D> inner;
+
+ /**
+ * Amount of data to winsorize.
+ */
+ private double winsorize;
+
+ /**
+ * Constructor.
+ *
+ * @param inner Inner estimator.
+ * @param winsorize Winsorize parameter.
+ */
+ public WinsorisingEstimator(DistributionEstimator<D> inner, double winsorize) {
+ super();
+ this.inner = inner;
+ this.winsorize = winsorize;
+ }
+
+ @Override
+ public <A> D estimate(A data, NumberArrayAdapter<?, A> adapter) {
+ // We first need the basic parameters:
+ int len = adapter.size(data);
+ final int cut = ((int) (len * winsorize)) >> 1;
+ // X positions of samples
+ double[] x = new double[len];
+ for (int i = 0; i < len; i++) {
+ final double val = adapter.getDouble(data, i);
+ x[i] = val;
+ }
+ // Partially sort our copy.
+ double min = QuickSelect.quickSelect(x, 0, len, cut);
+ double max = QuickSelect.quickSelect(x, cut, len, len - 1 - cut);
+ // Winsorize by replacing the smallest and largest values.
+ // QuickSelect ensured that these are correctly in place.
+ for (int i = 0, j = len - 1; i < cut; i++, j--) {
+ x[i] = min;
+ x[j] = max;
+ }
+ return inner.estimate(x, ArrayLikeUtil.DOUBLEARRAYADAPTER);
+ }
+
+ @Override
+ public Class<? super D> getDistributionClass() {
+ return inner.getDistributionClass();
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName() + "(" + inner.toString() + ", trim=" + winsorize + ")";
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ *
+ * @param <D> Distribution type
+ */
+ public static class Parameterizer<D extends Distribution> extends AbstractParameterizer {
+ /**
+ * Option for the class to use on the winsorized sample.
+ */
+ public static final OptionID INNER_ID = new OptionID("winsorize.inner", "Estimator to use on the winsorized data.");
+
+ /**
+ * Option for specifying the amount of data to winsorize.
+ */
+ public static final OptionID WINSORIZE_ID = new OptionID("winsorize.winsorize", "Relative amount of data to winsorize on each end, must be 0 < winsorize < 0.5");
+
+ /**
+ * Distribution estimator to use.
+ */
+ private DistributionEstimator<D> inner;
+
+ /**
+ * Amount of data to winsorize.
+ */
+ private double winsorize;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ ObjectParameter<DistributionEstimator<D>> innerP = new ObjectParameter<>(INNER_ID, DistributionEstimator.class);
+ if (config.grab(innerP)) {
+ inner = innerP.instantiateClass(config);
+ }
+
+ DoubleParameter trimP = new DoubleParameter(WINSORIZE_ID);
+ trimP.addConstraint(new GreaterConstraint(0.));
+ trimP.addConstraint(new LessConstraint(0.5));
+ if (config.grab(trimP)) {
+ winsorize = trimP.doubleValue();
+ }
+ }
+
+ @Override
+ protected WinsorisingEstimator<D> makeInstance() {
+ return new WinsorisingEstimator<>(inner, winsorize);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/meta/package-info.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/meta/package-info.java
new file mode 100644
index 00000000..c4b75f2d
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/meta/package-info.java
@@ -0,0 +1,6 @@
+/**
+ * Meta estimators: estimators that do not actually estimate themselves, but instead use other estimators, e.g. on a trimmed data set, or as an ensemble.
+ *
+ * @author Erich Schubert
+ */
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.meta; \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/iterator/MIter.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/package-info.java
index d9017d6c..62c98262 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/MIter.java
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/estimator/package-info.java
@@ -1,11 +1,15 @@
-package de.lmu.ifi.dbs.elki.utilities.iterator;
-
+/**
+ * Estimators for statistical distributions.
+ *
+ * @author Erich Schubert
+ */
+package de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,15 +27,3 @@ package de.lmu.ifi.dbs.elki.utilities.iterator;
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
-/**
- * Modifiable iterator, that also supports removal.
- *
- * @author Erich Schubert
- */
-public interface MIter extends Iter {
- /**
- * Remove the object the iterator currently points to.
- */
- void remove();
-}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/package-info.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/package-info.java
index ed9c0e88..49357049 100644
--- a/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/BiweightKernelDensityFunction.java b/src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/BiweightKernelDensityFunction.java
new file mode 100644
index 00000000..4b6ec7b7
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/BiweightKernelDensityFunction.java
@@ -0,0 +1,102 @@
+package de.lmu.ifi.dbs.elki.math.statistics.kernelfunctions;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.utilities.Alias;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Biweight (Quartic) kernel density estimator.
+ *
+ * @author Erich Schubert
+ */
+@Alias({ "biweight", "quartic" })
+public final class BiweightKernelDensityFunction implements KernelDensityFunction {
+ /**
+ * Static instance.
+ */
+ public static final BiweightKernelDensityFunction KERNEL = new BiweightKernelDensityFunction();
+
+ /**
+ * Canonical bandwidth: 35^(1/5)
+ */
+ @Reference(authors = "J.S. Marron, D. Nolan", title = "Canonical kernels for density estimation", booktitle = "Statistics & Probability Letters, Volume 7, Issue 3", url = "http://dx.doi.org/10.1016/0167-7152(88)90050-8")
+ public static final double CANONICAL_BANDWIDTH = Math.pow(35., .2);
+
+ /**
+ * Standard deviation.
+ */
+ public static final double STDDEV = 1. / Math.sqrt(7.);
+
+ /**
+ * R constant.
+ */
+ public static final double R = 5. / 7.;
+
+ /**
+ * Private, empty constructor. Use the static instance!
+ */
+ private BiweightKernelDensityFunction() {
+ // Nothing to do.
+ }
+
+ @Override
+ public double density(double delta) {
+ if (delta >= 1.) {
+ return 0;
+ }
+ final double u = 1 - delta * delta;
+ return 0.9375 * u * u;
+ }
+
+ @Override
+ public double canonicalBandwidth() {
+ return CANONICAL_BANDWIDTH;
+ }
+
+ @Override
+ public double standardDeviation() {
+ return STDDEV;
+ }
+
+ @Override
+ public double getR() {
+ return R;
+ }
+
+ /**
+ * Parameterization stub.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected BiweightKernelDensityFunction makeInstance() {
+ return KERNEL;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/CosineKernelDensityFunction.java b/src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/CosineKernelDensityFunction.java
new file mode 100644
index 00000000..230cb404
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/CosineKernelDensityFunction.java
@@ -0,0 +1,99 @@
+package de.lmu.ifi.dbs.elki.math.statistics.kernelfunctions;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Cosine kernel density estimator.
+ *
+ * @author Erich Schubert
+ */
+public final class CosineKernelDensityFunction implements KernelDensityFunction {
+ /**
+ * Static instance.
+ */
+ public static final CosineKernelDensityFunction KERNEL = new CosineKernelDensityFunction();
+
+ /**
+ * Canonical bandwidth.
+ *
+ * Computed as (R / STDDEV^4)^(1/5)
+ *
+ * This is approximately: 1.7662654022050532
+ */
+ public static final double CANONICAL_BANDWIDTH = Math.pow(MathUtil.PISQUARE / (16. * (1. - 8. / MathUtil.PISQUARE) * (1. - 8. / MathUtil.PISQUARE)), .2);
+
+ /**
+ * Standard deviation.
+ */
+ private static final double STDDEV = Math.sqrt(1. - 8. / MathUtil.PISQUARE);
+
+ /**
+ * R constant.
+ */
+ private static final double R = Math.PI * Math.PI / 16.;
+
+ /**
+ * Private, empty constructor. Use the static instance!
+ */
+ private CosineKernelDensityFunction() {
+ // Nothing to do.
+ }
+
+ @Override
+ public double density(double delta) {
+ return (delta < 1.) ? MathUtil.QUARTERPI * Math.cos(MathUtil.HALFPI * delta) : 0.;
+ }
+
+ @Override
+ public double canonicalBandwidth() {
+ return CANONICAL_BANDWIDTH;
+ }
+
+ @Override
+ public double standardDeviation() {
+ return STDDEV;
+ }
+
+ @Override
+ public double getR() {
+ return R;
+ }
+
+ /**
+ * Parameterization stub.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected CosineKernelDensityFunction makeInstance() {
+ return KERNEL;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/EpanechnikovKernelDensityFunction.java b/src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/EpanechnikovKernelDensityFunction.java
index 25aa2ea7..bf91e227 100644
--- a/src/de/lmu/ifi/dbs/elki/math/statistics/EpanechnikovKernelDensityFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/EpanechnikovKernelDensityFunction.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.math.statistics;
+package de.lmu.ifi.dbs.elki.math.statistics.kernelfunctions;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,6 +23,8 @@ package de.lmu.ifi.dbs.elki.math.statistics;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import de.lmu.ifi.dbs.elki.utilities.Alias;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
/**
@@ -30,14 +32,28 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
*
* @author Erich Schubert
*/
+@Alias({ "epanechnikov" })
public final class EpanechnikovKernelDensityFunction implements KernelDensityFunction {
- @Override
- public double density(double delta) {
- if(delta < 1) {
- return 0.75 * (1 - delta * delta);
- }
- return 0;
- }
+ /**
+ * Static instance.
+ */
+ public static final EpanechnikovKernelDensityFunction KERNEL = new EpanechnikovKernelDensityFunction();
+
+ /**
+ * Canonical bandwidth: 15^(1/5)
+ */
+ @Reference(authors = "J.S. Marron, D. Nolan", title = "Canonical kernels for density estimation", booktitle = "Statistics & Probability Letters, Volume 7, Issue 3", url = "http://dx.doi.org/10.1016/0167-7152(88)90050-8")
+ public static final double CANONICAL_BANDWIDTH = Math.pow(15., .2);
+
+ /**
+ * Standard deviation.
+ */
+ public static final double STDDEV = 1. / Math.sqrt(5.);
+
+ /**
+ * R constant.
+ */
+ public static final double R = 3. / 5.;
/**
* Private, empty constructor. Use the static instance!
@@ -46,16 +62,31 @@ public final class EpanechnikovKernelDensityFunction implements KernelDensityFun
// Nothing to do.
}
- /**
- * Static instance.
- */
- public static final EpanechnikovKernelDensityFunction KERNEL = new EpanechnikovKernelDensityFunction();
+ @Override
+ public double density(double delta) {
+ return (delta < 1.) ? .75 * (1 - delta * delta) : 0.;
+ }
+
+ @Override
+ public double canonicalBandwidth() {
+ return CANONICAL_BANDWIDTH;
+ }
+
+ @Override
+ public double standardDeviation() {
+ return STDDEV;
+ }
+
+ @Override
+ public double getR() {
+ return R;
+ }
/**
* Parameterization stub.
*
* @author Erich Schubert
- *
+ *
* @apiviz.exclude
*/
public static class Parameterizer extends AbstractParameterizer {
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/GaussianKernelDensityFunction.java b/src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/GaussianKernelDensityFunction.java
index 2cd15408..2e666871 100644
--- a/src/de/lmu/ifi/dbs/elki/math/statistics/GaussianKernelDensityFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/GaussianKernelDensityFunction.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.math.statistics;
+package de.lmu.ifi.dbs.elki.math.statistics.kernelfunctions;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,6 +23,8 @@ package de.lmu.ifi.dbs.elki.math.statistics;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
/**
@@ -32,14 +34,20 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
*/
public final class GaussianKernelDensityFunction implements KernelDensityFunction {
/**
- * Scaling constant for Gaussian kernel, to make it sum up to 1.
+ * Static instance.
*/
- private static final double GSCALE = 1.0 / Math.sqrt(2.0 * Math.PI);
+ public static final GaussianKernelDensityFunction KERNEL = new GaussianKernelDensityFunction();
- @Override
- public double density(double delta) {
- return GSCALE * Math.exp(-.5 * delta * delta);
- }
+ /**
+ * Canonical bandwidth: (1./(4*pi))^(1/10)
+ */
+ @Reference(authors = "J.S. Marron, D. Nolan", title = "Canonical kernels for density estimation", booktitle = "Statistics & Probability Letters, Volume 7, Issue 3", url = "http://dx.doi.org/10.1016/0167-7152(88)90050-8")
+ public static final double CANONICAL_BANDWIDTH = Math.pow(.25 / Math.PI, .1);
+
+ /**
+ * R constant.
+ */
+ public static final double R = .5 * MathUtil.ONE_BY_SQRTPI;
/**
* Private, empty constructor. Use the static instance!
@@ -48,16 +56,31 @@ public final class GaussianKernelDensityFunction implements KernelDensityFunctio
// Nothing to do.
}
- /**
- * Static instance.
- */
- public static final GaussianKernelDensityFunction KERNEL = new GaussianKernelDensityFunction();
+ @Override
+ public double density(double delta) {
+ return MathUtil.ONE_BY_SQRTTWOPI * Math.exp(-.5 * delta * delta);
+ }
+
+ @Override
+ public double canonicalBandwidth() {
+ return CANONICAL_BANDWIDTH;
+ }
+
+ @Override
+ public double standardDeviation() {
+ return 1.;
+ }
+
+ @Override
+ public double getR() {
+ return R;
+ }
/**
* Parameterization stub.
*
* @author Erich Schubert
- *
+ *
* @apiviz.exclude
*/
public static class Parameterizer extends AbstractParameterizer {
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/KernelDensityFunction.java b/src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/KernelDensityFunction.java
new file mode 100644
index 00000000..ce6d5a0d
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/KernelDensityFunction.java
@@ -0,0 +1,76 @@
+package de.lmu.ifi.dbs.elki.math.statistics.kernelfunctions;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+
+/**
+ * Inner function of a kernel density estimator.
+ *
+ * Note: as of now, this API does not support asymmetric kernels.
+ *
+ * @author Erich Schubert
+ */
+public interface KernelDensityFunction {
+ /**
+ * Density contribution of a point at the given relative distance
+ * {@code delta >= 0}.
+ *
+ * Note that for {@code delta < 0}, in particular for {@code delta < 1}, the
+ * results may become invalid. So usually, you will want to invoke this as:
+ *
+ * {@code kernel.density(Math.abs(delta))}
+ *
+ * @param delta Relative distance
+ * @return density contribution
+ */
+ public double density(double delta);
+
+ /**
+ * Get the canonical bandwidth for this kernel.
+ *
+ * Note: R uses a different definition of "canonical bandwidth", and also uses
+ * differently scaled kernels.
+ *
+ * @return Canonical bandwidth
+ */
+ @Reference(authors = "J.S. Marron, D. Nolan", title = "Canonical kernels for density estimation", booktitle = "Statistics & Probability Letters, Volume 7, Issue 3", url = "http://dx.doi.org/10.1016/0167-7152(88)90050-8")
+ public double canonicalBandwidth();
+
+ /**
+ * Get the standard deviation of the kernel function.
+ *
+ * @return Standard deviation
+ */
+ public double standardDeviation();
+
+ /**
+ * Get the R integral of the kernel, \int K^2(x) dx
+ *
+ * TODO: any better name for this?
+ *
+ * @return R value
+ */
+ public double getR();
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/TriangularKernelDensityFunction.java b/src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/TriangularKernelDensityFunction.java
index aee544de..c6acf031 100644
--- a/src/de/lmu/ifi/dbs/elki/math/statistics/TriangularKernelDensityFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/TriangularKernelDensityFunction.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.math.statistics;
+package de.lmu.ifi.dbs.elki.math.statistics.kernelfunctions;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -31,13 +31,27 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
* @author Erich Schubert
*/
public final class TriangularKernelDensityFunction implements KernelDensityFunction {
- @Override
- public double density(double delta) {
- if(delta < 1) {
- return 1 - delta;
- }
- return 0;
- }
+ /**
+ * Static instance.
+ */
+ public static final TriangularKernelDensityFunction KERNEL = new TriangularKernelDensityFunction();
+
+ /**
+ * Canonical bandwidth.
+ *
+ * Computed as (R / STDDEV^4)^(1/5)
+ */
+ public static final double CANONICAL_BANDWIDTH = Math.pow(24., .2);
+
+ /**
+ * Standard deviation.
+ */
+ private static final double STDDEV = 1. / Math.sqrt(6.);
+
+ /**
+ * R constant.
+ */
+ private static final double R = 2. / 3.;
/**
* Private, empty constructor. Use the static instance!
@@ -46,16 +60,31 @@ public final class TriangularKernelDensityFunction implements KernelDensityFunct
// Nothing to do.
}
- /**
- * Static instance.
- */
- public static final TriangularKernelDensityFunction KERNEL = new TriangularKernelDensityFunction();
+ @Override
+ public double density(double delta) {
+ return (delta < 1.) ? 1. - delta : 0.;
+ }
+
+ @Override
+ public double canonicalBandwidth() {
+ return CANONICAL_BANDWIDTH;
+ }
+
+ @Override
+ public double standardDeviation() {
+ return STDDEV;
+ }
+
+ @Override
+ public double getR() {
+ return R;
+ }
/**
* Parameterization stub.
*
* @author Erich Schubert
- *
+ *
* @apiviz.exclude
*/
public static class Parameterizer extends AbstractParameterizer {
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/TricubeKernelDensityFunction.java b/src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/TricubeKernelDensityFunction.java
new file mode 100644
index 00000000..933207ed
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/TricubeKernelDensityFunction.java
@@ -0,0 +1,105 @@
+package de.lmu.ifi.dbs.elki.math.statistics.kernelfunctions;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Tricube kernel density estimator.
+ *
+ * @author Erich Schubert
+ */
+public final class TricubeKernelDensityFunction implements KernelDensityFunction {
+ /**
+ * Static instance.
+ */
+ public static final TricubeKernelDensityFunction KERNEL = new TricubeKernelDensityFunction();
+
+ /**
+ * Canonical bandwidth.
+ *
+ * Computed as (R / STDDEV^4)^(1/5)
+ */
+ public static final double CANONICAL_BANDWIDTH = Math.pow(59049 / 1729, .2);
+
+ /**
+ * Standard deviation.
+ */
+ private static final double STDDEV = Math.sqrt(35. / 243.);
+
+ /**
+ * R constant.
+ */
+ private static final double R = 175. / 247.;
+
+ /**
+ * Scaling factor.
+ */
+ private final double SCALE = 70. / 81.;
+
+ /**
+ * Private, empty constructor. Use the static instance!
+ */
+ private TricubeKernelDensityFunction() {
+ // Nothing to do.
+ }
+
+ @Override
+ public double density(double delta) {
+ if (delta >= 1.) {
+ return 0;
+ }
+ final double u = 1 - delta * delta * delta;
+ return SCALE * u * u * u;
+ }
+
+ @Override
+ public double canonicalBandwidth() {
+ return CANONICAL_BANDWIDTH;
+ }
+
+ @Override
+ public double standardDeviation() {
+ return STDDEV;
+ }
+
+ @Override
+ public double getR() {
+ return R;
+ }
+
+ /**
+ * Parameterization stub.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected TricubeKernelDensityFunction makeInstance() {
+ return KERNEL;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/TriweightKernelDensityFunction.java b/src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/TriweightKernelDensityFunction.java
new file mode 100644
index 00000000..993ab8bf
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/TriweightKernelDensityFunction.java
@@ -0,0 +1,102 @@
+package de.lmu.ifi.dbs.elki.math.statistics.kernelfunctions;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.utilities.Alias;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Triweight kernel density estimator.
+ *
+ * @author Erich Schubert
+ */
+@Alias({ "triweight" })
+public final class TriweightKernelDensityFunction implements KernelDensityFunction {
+ /**
+ * Static instance.
+ */
+ public static final TriweightKernelDensityFunction KERNEL = new TriweightKernelDensityFunction();
+
+ /**
+ * Canonical bandwidth: (9450/143)^(1/5)
+ */
+ @Reference(authors = "J.S. Marron, D. Nolan", title = "Canonical kernels for density estimation", booktitle = "Statistics & Probability Letters, Volume 7, Issue 3", url = "http://dx.doi.org/10.1016/0167-7152(88)90050-8")
+ public static final double CANONICAL_BANDWIDTH = Math.pow(9450. / 143., .2);
+
+ /**
+ * Standard deviation.
+ */
+ private static final double STDDEV = 1. / 3.;
+
+ /**
+ * R constant.
+ */
+ private static final double R = 350. / 429.;
+
+ /**
+ * Private, empty constructor. Use the static instance!
+ */
+ private TriweightKernelDensityFunction() {
+ // Nothing to do.
+ }
+
+ @Override
+ public double density(double delta) {
+ if (delta >= 1.) {
+ return 0;
+ }
+ final double u = 1 - delta * delta;
+ return 1.09375 * u * u * u;
+ }
+
+ @Override
+ public double canonicalBandwidth() {
+ return CANONICAL_BANDWIDTH;
+ }
+
+ @Override
+ public double standardDeviation() {
+ return STDDEV;
+ }
+
+ @Override
+ public double getR() {
+ return R;
+ }
+
+ /**
+ * Parameterization stub.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected TriweightKernelDensityFunction makeInstance() {
+ return KERNEL;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/UniformKernelDensityFunction.java b/src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/UniformKernelDensityFunction.java
index 66fe7888..2a820355 100644
--- a/src/de/lmu/ifi/dbs/elki/math/statistics/UniformKernelDensityFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/UniformKernelDensityFunction.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.math.statistics;
+package de.lmu.ifi.dbs.elki.math.statistics.kernelfunctions;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,6 +23,7 @@ package de.lmu.ifi.dbs.elki.math.statistics;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
/**
@@ -31,13 +32,26 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
* @author Erich Schubert
*/
public final class UniformKernelDensityFunction implements KernelDensityFunction {
- @Override
- public double density(double delta) {
- if(delta < 1) {
- return 0.5;
- }
- return 0;
- }
+ /**
+ * Static instance.
+ */
+ public static final UniformKernelDensityFunction KERNEL = new UniformKernelDensityFunction();
+
+ /**
+ * Canonical bandwidth: (9/2)^(1/5)
+ */
+ @Reference(authors = "J.S. Marron, D. Nolan", title = "Canonical kernels for density estimation", booktitle = "Statistics & Probability Letters, Volume 7, Issue 3", url = "http://dx.doi.org/10.1016/0167-7152(88)90050-8")
+ public static final double CANONICAL_BANDWIDTH = Math.pow(4.5, .2);
+
+ /**
+ * Standard deviation.
+ */
+ private static final double STDDEV = 1. / Math.sqrt(3.);
+
+ /**
+ * R constant.
+ */
+ private static final double R = .5;
/**
* Private, empty constructor. Use the static instance!
@@ -46,16 +60,31 @@ public final class UniformKernelDensityFunction implements KernelDensityFunction
// Nothing to do.
}
- /**
- * Static instance.
- */
- public static final UniformKernelDensityFunction KERNEL = new UniformKernelDensityFunction();
+ @Override
+ public double density(double delta) {
+ return (delta < 1.) ? .5 : 0.;
+ }
+
+ @Override
+ public double canonicalBandwidth() {
+ return CANONICAL_BANDWIDTH;
+ }
+
+ @Override
+ public double standardDeviation() {
+ return STDDEV;
+ }
+
+ @Override
+ public double getR() {
+ return R;
+ }
/**
* Parameterization stub.
*
* @author Erich Schubert
- *
+ *
* @apiviz.exclude
*/
public static class Parameterizer extends AbstractParameterizer {
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/package-info.java b/src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/package-info.java
new file mode 100644
index 00000000..adcadcaf
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/kernelfunctions/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Kernel functions from statistics.
+ */
+package de.lmu.ifi.dbs.elki.math.statistics.kernelfunctions; \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/package-info.java b/src/de/lmu/ifi/dbs/elki/math/statistics/package-info.java
index 142524e6..cc39a615 100644
--- a/src/de/lmu/ifi/dbs/elki/math/statistics/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/tests/KolmogorovSmirnovTest.java b/src/de/lmu/ifi/dbs/elki/math/statistics/tests/KolmogorovSmirnovTest.java
index 236f26b8..a134ab09 100644
--- a/src/de/lmu/ifi/dbs/elki/math/statistics/tests/KolmogorovSmirnovTest.java
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/tests/KolmogorovSmirnovTest.java
@@ -64,7 +64,7 @@ public class KolmogorovSmirnovTest implements GoodnessOfFitTest {
*
* @param sample1 first data sample positions
* @param sample2 second data sample positions
- * @return the largest distance between both functions
+ * @return the largest difference between both functions
*/
public static double calculateTestStatistic(double[] sample1, double[] sample2) {
double maximum = 0.0;
@@ -74,26 +74,26 @@ public class KolmogorovSmirnovTest implements GoodnessOfFitTest {
// Parallel iteration over both curves. We can stop if we reach either end,
// As the difference can then only decrease!
- while(index1 < sample1.length && index2 < sample2.length) {
+ while (index1 < sample1.length && index2 < sample2.length) {
// Next (!) positions
final double x1 = sample1[index1], x2 = sample2[index2];
// Advance on first curve
- if(x1 <= x2) {
+ if (x1 <= x2) {
index1++;
// Handle multiple points with same x:
- while(index1 < sample1.length && sample1[index1] == x1) {
+ while (index1 < sample1.length && sample1[index1] == x1) {
index1++;
}
- cdf1 = ((double) index1) / sample1.length;
+ cdf1 = ((double) index1 + 1.) / (sample1.length + 1.);
}
// Advance on second curve
- if(x1 >= x2) {
+ if (x1 >= x2) {
index2++;
// Handle multiple points with same x:
- while(index2 < sample2.length && sample2[index2] == x2) {
+ while (index2 < sample2.length && sample2[index2] == x2) {
index2++;
}
- cdf2 = ((double) index2) / sample2.length;
+ cdf2 = ((double) index2 + 1.) / (sample2.length + 1.);
}
maximum = Math.max(maximum, Math.abs(cdf1 - cdf2));
}
@@ -114,4 +114,49 @@ public class KolmogorovSmirnovTest implements GoodnessOfFitTest {
return STATIC;
}
}
-} \ No newline at end of file
+
+ /**
+ * Simplest version of the test: test if a sorted array is approximately
+ * uniform distributed on [0:1].
+ *
+ * @param test Presorted (!) array
+ * @return Maximum deviation from uniform.
+ */
+ public static double simpleTest(double[] test) {
+ // Weibull style empirical quantiles: (i+1) / (n+1)
+ double scale = 1. / (test.length + 1.);
+ double maxdev = Double.NEGATIVE_INFINITY;
+ for (int i = 0; i < test.length; i++) {
+ // Expected value at position i (Weibull style):
+ double expected = (i + 1.) * scale;
+ double dev = Math.abs(test[i] - expected);
+ if (dev > maxdev) {
+ maxdev = dev;
+ }
+ }
+ return Math.abs(maxdev);
+ }
+
+ /**
+ * Simplest version of the test: test if a sorted array is approximately
+ * uniform distributed on the given interval.
+ *
+ * @param test Presorted (!) array
+ * @param min Minimum of uniform distribution
+ * @param max Maximum of uniform distribution
+ * @return Maximum deviation from uniform.
+ */
+ public static double simpleTest(double[] test, final double min, final double max) {
+ double scale = (max - min) / (test.length + 1.);
+ double maxdev = Double.NEGATIVE_INFINITY;
+ for (int i = 0; i < test.length; i++) {
+ // Expected value at position i (Weibull style):
+ double expected = (i + 1.) * scale + min;
+ double dev = Math.abs(test[i] - expected);
+ if (dev > maxdev) {
+ maxdev = dev;
+ }
+ }
+ return Math.abs(maxdev);
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/tests/package-info.java b/src/de/lmu/ifi/dbs/elki/math/statistics/tests/package-info.java
index 3e39a519..6698f462 100644
--- a/src/de/lmu/ifi/dbs/elki/math/statistics/tests/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/tests/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/package-info.java b/src/de/lmu/ifi/dbs/elki/package-info.java
index e7252314..8daf4487 100644
--- a/src/de/lmu/ifi/dbs/elki/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/package-info.java
@@ -13,7 +13,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/AbstractExternalizablePage.java b/src/de/lmu/ifi/dbs/elki/persistent/AbstractExternalizablePage.java
index 194b594f..7e060012 100644
--- a/src/de/lmu/ifi/dbs/elki/persistent/AbstractExternalizablePage.java
+++ b/src/de/lmu/ifi/dbs/elki/persistent/AbstractExternalizablePage.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.persistent;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/AbstractPageFile.java b/src/de/lmu/ifi/dbs/elki/persistent/AbstractPageFile.java
index e05c20c3..d6e750b8 100644
--- a/src/de/lmu/ifi/dbs/elki/persistent/AbstractPageFile.java
+++ b/src/de/lmu/ifi/dbs/elki/persistent/AbstractPageFile.java
@@ -1,10 +1,13 @@
package de.lmu.ifi.dbs.elki.persistent;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.statistics.Counter;
+
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,7 +26,6 @@ package de.lmu.ifi.dbs.elki.persistent;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
/**
* Abstract base class for the page file API for both caches and true page files
* (in-memory and on-disk).
@@ -36,23 +38,31 @@ public abstract class AbstractPageFile<P extends Page> implements PageFile<P> {
/**
* The read I/O-Access of this file.
*/
- protected long readAccess;
+ private Counter readAccess;
/**
* The write I/O-Access of this file.
*/
- protected long writeAccess;
+ private Counter writeAccess;
/**
* Constructor.
*/
public AbstractPageFile() {
super();
- this.readAccess = 0;
- this.writeAccess = 0;
+ Logging log = getLogger();
+ this.readAccess = log.isStatistics() ? log.newCounter(this.getClass().getName() + ".reads") : null;
+ this.writeAccess = log.isStatistics() ? log.newCounter(this.getClass().getName() + ".writes") : null;
}
/**
+ * Get the class logger.
+ *
+ * @return Logger
+ */
+ abstract protected Logging getLogger();
+
+ /**
* Writes a page into this file. The method tests if the page has already an
* id, otherwise a new id is assigned and returned.
*
@@ -78,20 +88,32 @@ public abstract class AbstractPageFile<P extends Page> implements PageFile<P> {
public void close() {
clear();
}
-
+
@Override
- public final long getReadOperations() {
- return readAccess;
+ public void logStatistics() {
+ if (readAccess != null) {
+ getLogger().statistics(readAccess);
+ }
+ if (writeAccess != null) {
+ getLogger().statistics(writeAccess);
+ }
}
-
- @Override
- public final long getWriteOperations() {
- return writeAccess;
+
+ /**
+ * Count a page read access.
+ */
+ protected void countRead() {
+ if (readAccess != null) {
+ readAccess.increment();
+ }
}
- @Override
- public final void resetPageAccess() {
- this.readAccess = 0;
- this.writeAccess = 0;
+ /**
+ * Count a page write access.
+ */
+ protected void countWrite() {
+ if (writeAccess != null) {
+ writeAccess.increment();
+ }
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/AbstractPageFileFactory.java b/src/de/lmu/ifi/dbs/elki/persistent/AbstractPageFileFactory.java
new file mode 100644
index 00000000..16094f90
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/persistent/AbstractPageFileFactory.java
@@ -0,0 +1,100 @@
+package de.lmu.ifi.dbs.elki.persistent;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
+
+/**
+ * Abstract page file factory.
+ *
+ * @author Erich Schubert
+ *
+ * @param <P> Page type
+ */
+public abstract class AbstractPageFileFactory<P extends Page> implements PageFileFactory<P> {
+ /**
+ * Holds the value of {@link Parameterizer#PAGE_SIZE_ID}.
+ */
+ protected int pageSize;
+
+ /**
+ * Constructor.
+ *
+ * @param pageSize Page size
+ */
+ public AbstractPageFileFactory(int pageSize) {
+ super();
+ this.pageSize = pageSize;
+ }
+
+ @Override
+ public int getPageSize() {
+ return pageSize;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @apiviz.exclude
+ *
+ * @author Erich Schubert
+ *
+ * @param <P> Page type
+ */
+ public static abstract class Parameterizer<P extends Page> extends AbstractParameterizer {
+ /**
+ * Parameter to specify the size of a page in bytes, must be an integer
+ * greater than 0.
+ * <p>
+ * Default value: {@code 4000}
+ * </p>
+ * <p>
+ * Key: {@code -pagefile.pagesize}
+ * </p>
+ */
+ public static final OptionID PAGE_SIZE_ID = new OptionID("pagefile.pagesize", "The size of a page in bytes.");
+
+ /**
+ * Page size
+ */
+ protected int pageSize;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ final IntParameter pageSizeP = new IntParameter(PAGE_SIZE_ID, 4000);
+ pageSizeP.addConstraint(new GreaterConstraint(0));
+ if (config.grab(pageSizeP)) {
+ pageSize = pageSizeP.getValue();
+ }
+ }
+
+ @Override
+ abstract protected PageFileFactory<P> makeInstance();
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/AbstractStoringPageFile.java b/src/de/lmu/ifi/dbs/elki/persistent/AbstractStoringPageFile.java
index 7151e6dd..6ac6eda9 100644
--- a/src/de/lmu/ifi/dbs/elki/persistent/AbstractStoringPageFile.java
+++ b/src/de/lmu/ifi/dbs/elki/persistent/AbstractStoringPageFile.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.persistent;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,15 +25,14 @@ package de.lmu.ifi.dbs.elki.persistent;
import java.util.Stack;
+import de.lmu.ifi.dbs.elki.logging.statistics.LongStatistic;
+
/**
* Abstract class implementing general methods of a PageFile. A PageFile stores
* objects that implement the <code>Page</code> interface.
*
* @author Elke Achtert
*
- * @apiviz.has Page
- * @apiviz.has PageFileStatistics
- *
* @param <P> Page type
*/
public abstract class AbstractStoringPageFile<P extends Page> extends AbstractPageFile<P> {
@@ -56,7 +55,7 @@ public abstract class AbstractStoringPageFile<P extends Page> extends AbstractPa
* Creates a new PageFile.
*/
protected AbstractStoringPageFile(int pageSize) {
- this.emptyPages = new Stack<Integer>();
+ this.emptyPages = new Stack<>();
this.nextPageID = 0;
this.pageSize = pageSize;
}
@@ -148,8 +147,10 @@ public abstract class AbstractStoringPageFile<P extends Page> extends AbstractPa
}
@Override
- public PageFileStatistics getInnerStatistics() {
- // Default: no nested page file.
- return null;
+ public void logStatistics() {
+ super.logStatistics();
+ if (getLogger().isStatistics()) {
+ getLogger().statistics(new LongStatistic(this.getClass().getName() + ".numpages", nextPageID - emptyPages.size()));
+ }
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/ByteArrayUtil.java b/src/de/lmu/ifi/dbs/elki/persistent/ByteArrayUtil.java
index ba9d108e..ba25435f 100644
--- a/src/de/lmu/ifi/dbs/elki/persistent/ByteArrayUtil.java
+++ b/src/de/lmu/ifi/dbs/elki/persistent/ByteArrayUtil.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.persistent;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/ByteBufferInputStream.java b/src/de/lmu/ifi/dbs/elki/persistent/ByteBufferInputStream.java
index 586d5535..dbc5ed2d 100644
--- a/src/de/lmu/ifi/dbs/elki/persistent/ByteBufferInputStream.java
+++ b/src/de/lmu/ifi/dbs/elki/persistent/ByteBufferInputStream.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.persistent;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/ByteBufferOutputStream.java b/src/de/lmu/ifi/dbs/elki/persistent/ByteBufferOutputStream.java
index 2a2971d9..28137393 100644
--- a/src/de/lmu/ifi/dbs/elki/persistent/ByteBufferOutputStream.java
+++ b/src/de/lmu/ifi/dbs/elki/persistent/ByteBufferOutputStream.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.persistent;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/ByteBufferSerializer.java b/src/de/lmu/ifi/dbs/elki/persistent/ByteBufferSerializer.java
index 93f99ba9..8605dd07 100644
--- a/src/de/lmu/ifi/dbs/elki/persistent/ByteBufferSerializer.java
+++ b/src/de/lmu/ifi/dbs/elki/persistent/ByteBufferSerializer.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.persistent;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -31,7 +31,8 @@ import java.nio.ByteBuffer;
*
* @author Erich Schubert
*
- * @apiviz.uses ByteBuffer
+ * @apiviz.has ByteBuffer - - oneway «serializes to/from»
+ * @apiviz.excludeSubtypes
*
* @param <T> Object type processed
*/
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/DefaultPageHeader.java b/src/de/lmu/ifi/dbs/elki/persistent/DefaultPageHeader.java
index e1ca2a41..5ae3312a 100644
--- a/src/de/lmu/ifi/dbs/elki/persistent/DefaultPageHeader.java
+++ b/src/de/lmu/ifi/dbs/elki/persistent/DefaultPageHeader.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.persistent;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/ExternalizablePage.java b/src/de/lmu/ifi/dbs/elki/persistent/ExternalizablePage.java
index 703187ac..0ec0f7fb 100644
--- a/src/de/lmu/ifi/dbs/elki/persistent/ExternalizablePage.java
+++ b/src/de/lmu/ifi/dbs/elki/persistent/ExternalizablePage.java
@@ -6,7 +6,7 @@ import java.io.Externalizable;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/FixedSizeByteBufferSerializer.java b/src/de/lmu/ifi/dbs/elki/persistent/FixedSizeByteBufferSerializer.java
index 56f1f9b3..a1d8600c 100644
--- a/src/de/lmu/ifi/dbs/elki/persistent/FixedSizeByteBufferSerializer.java
+++ b/src/de/lmu/ifi/dbs/elki/persistent/FixedSizeByteBufferSerializer.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.persistent;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,6 +28,7 @@ package de.lmu.ifi.dbs.elki.persistent;
* Serializers with a fixed length serialization.
*
* @author Erich Schubert
+ * @apiviz.excludeSubtypes
*
* @param <T> Type
*/
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/LRUCache.java b/src/de/lmu/ifi/dbs/elki/persistent/LRUCache.java
index 7e06e5ea..18726ec7 100644
--- a/src/de/lmu/ifi/dbs/elki/persistent/LRUCache.java
+++ b/src/de/lmu/ifi/dbs/elki/persistent/LRUCache.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.persistent;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -40,25 +40,25 @@ import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
*
* @author Elke Achtert
*
- * @apiviz.composedOf PageFile
+ * @apiviz.uses PageFile
*
* @param <P> Page type
*/
public class LRUCache<P extends Page> extends AbstractPageFile<P> {
/**
- * Our logger
+ * Our class logger.
*/
private static final Logging LOG = Logging.getLogger(LRUCache.class);
/**
* Cache size in bytes.
*/
- protected long cacheSizeBytes;
+ protected int cacheSizeBytes;
/**
* The maximum number of objects in this cache.
*/
- protected long cacheSize;
+ protected int cacheSize;
/**
* The map holding the objects of this cache.
@@ -74,11 +74,11 @@ public class LRUCache<P extends Page> extends AbstractPageFile<P> {
/**
* Initializes this cache with the specified parameters.
*
- * @param cacheSizeBytes the maximum number of pages in this cache
+ * @param cacheSizeBytes the maximum number of bytes for this cache
* @param file the underlying file of this cache, if a page is dropped it is
* written to the file
*/
- public LRUCache(long cacheSizeBytes, PageFile<P> file) {
+ public LRUCache(int cacheSizeBytes, PageFile<P> file) {
this.file = file;
this.cacheSizeBytes = cacheSizeBytes;
}
@@ -93,7 +93,7 @@ public class LRUCache<P extends Page> extends AbstractPageFile<P> {
*/
@Override
public synchronized P readPage(int pageID) {
- readAccess++;
+ countRead();
P page = map.get(pageID);
if(page != null) {
if(LOG.isDebuggingFine()) {
@@ -112,7 +112,7 @@ public class LRUCache<P extends Page> extends AbstractPageFile<P> {
@Override
public synchronized void writePage(int pageID, P page) {
- writeAccess++;
+ countWrite();
page.setDirty(true);
map.put(pageID, page);
if(LOG.isDebuggingFine()) {
@@ -122,7 +122,7 @@ public class LRUCache<P extends Page> extends AbstractPageFile<P> {
@Override
public void deletePage(int pageID) {
- writeAccess++;
+ countWrite();
map.remove(pageID);
file.deletePage(pageID);
}
@@ -241,7 +241,7 @@ public class LRUCache<P extends Page> extends AbstractPageFile<P> {
return;
}
- List<Integer> keys = new ArrayList<Integer>(map.keySet());
+ List<Integer> keys = new ArrayList<>(map.keySet());
Collections.reverse(keys);
for(Integer id : keys) {
@@ -251,7 +251,13 @@ public class LRUCache<P extends Page> extends AbstractPageFile<P> {
}
@Override
- public PageFileStatistics getInnerStatistics() {
- return file;
+ public void logStatistics() {
+ super.logStatistics();
+ file.logStatistics();
+ }
+
+ @Override
+ protected Logging getLogger() {
+ return LOG;
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/LRUCachePageFileFactory.java b/src/de/lmu/ifi/dbs/elki/persistent/LRUCachePageFileFactory.java
new file mode 100644
index 00000000..a87f8e1f
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/persistent/LRUCachePageFileFactory.java
@@ -0,0 +1,135 @@
+package de.lmu.ifi.dbs.elki.persistent;
+
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterEqualConstraint;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Page file factory for memory page files.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has LRUCache
+ * @apiviz.composedOf PageFileFactory
+ *
+ * @param <P> Page type
+ */
+public class LRUCachePageFileFactory<P extends Page> implements PageFileFactory<P> {
+ /**
+ * Inner page file factory.
+ */
+ private PageFileFactory<P> pageFileFactory;
+
+ /**
+ * Cache size, in bytes.
+ */
+ private int cacheSize;
+
+ /**
+ * Constructor.
+ *
+ * @param pageFileFactory Inner page file
+ * @param cacheSize Size of cache, in bytes.
+ */
+ public LRUCachePageFileFactory(PageFileFactory<P> pageFileFactory, int cacheSize) {
+ super();
+ this.cacheSize = cacheSize;
+ this.pageFileFactory = pageFileFactory;
+ }
+
+ @Override
+ public PageFile<P> newPageFile(Class<P> cls) {
+ PageFile<P> inner = pageFileFactory.newPageFile(cls);
+ return new LRUCache<>(cacheSize, inner);
+ }
+
+ @Override
+ public int getPageSize() {
+ return pageFileFactory.getPageSize();
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ /**
+ * Parameter to specify the size of the cache in bytes, must be an integer
+ * equal to or greater than 0.
+ * <p>
+ * Default value: {@link Integer#MAX_VALUE}
+ * </p>
+ * <p>
+ * Key: {@code -pagefile.cachesize}
+ * </p>
+ */
+ public static final OptionID CACHE_SIZE_ID = new OptionID("pagefile.cachesize", "The size of the cache in bytes.");
+
+ /**
+ * Parameter to specify the inner pagefile.
+ * <p>
+ * Key: {@code -pagefile.pagefile}
+ * </p>
+ */
+ public static final OptionID PAGEFILE_ID = new OptionID("pagefile.pagefile", "The backing pagefile for the cache.");
+
+ /**
+ * Inner page file factory.
+ */
+ PageFileFactory<Page> pageFileFactory;
+
+ /**
+ * Cache size, in bytes.
+ */
+ protected int cacheSize;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ ObjectParameter<PageFileFactory<Page>> pffP = new ObjectParameter<>(PAGEFILE_ID, PageFileFactory.class, PersistentPageFileFactory.class);
+ if (config.grab(pffP)) {
+ pageFileFactory = pffP.instantiateClass(config);
+ }
+
+ IntParameter cacheSizeP = new IntParameter(CACHE_SIZE_ID);
+ cacheSizeP.addConstraint(new GreaterEqualConstraint(0));
+ if (config.grab(cacheSizeP)) {
+ cacheSize = cacheSizeP.getValue();
+ }
+ }
+
+ @Override
+ protected LRUCachePageFileFactory<Page> makeInstance() {
+ return new LRUCachePageFileFactory<>(pageFileFactory, cacheSize);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/MemoryPageFile.java b/src/de/lmu/ifi/dbs/elki/persistent/MemoryPageFile.java
index 7aba9a21..46d10fb4 100644
--- a/src/de/lmu/ifi/dbs/elki/persistent/MemoryPageFile.java
+++ b/src/de/lmu/ifi/dbs/elki/persistent/MemoryPageFile.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.persistent;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,6 +25,7 @@ package de.lmu.ifi.dbs.elki.persistent;
import gnu.trove.map.TIntObjectMap;
import gnu.trove.map.hash.TIntObjectHashMap;
+import de.lmu.ifi.dbs.elki.logging.Logging;
/**
* A memory based implementation of a PageFile that simulates I/O-access.<br>
@@ -36,6 +37,11 @@ import gnu.trove.map.hash.TIntObjectHashMap;
*/
public class MemoryPageFile<P extends Page> extends AbstractStoringPageFile<P> {
/**
+ * Class logger.
+ */
+ private static final Logging LOG = Logging.getLogger(MemoryPageFile.class);
+
+ /**
* Holds the pages.
*/
private final TIntObjectMap<P> file;
@@ -48,18 +54,18 @@ public class MemoryPageFile<P extends Page> extends AbstractStoringPageFile<P> {
*/
public MemoryPageFile(int pageSize) {
super(pageSize);
- this.file = new TIntObjectHashMap<P>();
+ this.file = new TIntObjectHashMap<>();
}
@Override
public synchronized P readPage(int pageID) {
- readAccess++;
+ countRead();
return file.get(pageID);
}
-
+
@Override
protected void writePage(int pageID, P page) {
- writeAccess++;
+ countWrite();
file.put(pageID, page);
page.setDirty(false);
}
@@ -71,7 +77,7 @@ public class MemoryPageFile<P extends Page> extends AbstractStoringPageFile<P> {
super.deletePage(pageID);
// delete from file
- writeAccess++;
+ countWrite();
file.remove(pageID);
}
@@ -79,4 +85,9 @@ public class MemoryPageFile<P extends Page> extends AbstractStoringPageFile<P> {
public void clear() {
file.clear();
}
-} \ No newline at end of file
+
+ @Override
+ protected Logging getLogger() {
+ return LOG;
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/PageFileStatistics.java b/src/de/lmu/ifi/dbs/elki/persistent/MemoryPageFileFactory.java
index df3de612..812e65c9 100644
--- a/src/de/lmu/ifi/dbs/elki/persistent/PageFileStatistics.java
+++ b/src/de/lmu/ifi/dbs/elki/persistent/MemoryPageFileFactory.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.persistent;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,39 +23,41 @@ package de.lmu.ifi.dbs.elki.persistent;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
/**
- * Statistics API for a Page File.
- *
- * See {@link PageFileUtil} for related utility functions for analysing this
- * data!
+ * Page file factory for memory page files.
*
* @author Erich Schubert
+ *
+ * @apiviz.has MemoryPageFile
+ *
+ * @param <P> Page type
*/
-public interface PageFileStatistics {
+public class MemoryPageFileFactory<P extends Page> extends AbstractPageFileFactory<P> {
/**
- * Returns the read I/O-Accesses of this file.
+ * Constructor.
*
- * @return Number of physical read I/O accesses
+ * @param pageSize Size of a page
*/
- public long getReadOperations();
-
+ public MemoryPageFileFactory(int pageSize) {
+ super(pageSize);
+ }
+
+ @Override
+ public PageFile<P> newPageFile(Class<P> cls) {
+ return new MemoryPageFile<>(pageSize);
+ }
+
/**
- * Returns the write I/O-Accesses of this file.
+ * Parameterization class.
*
- * @return Number of physical write I/O accesses
- */
- public long getWriteOperations();
-
- /**
- * Resets the counters for page accesses of this file and flushes the cache.
- */
- public void resetPageAccess();
-
- /**
- * Get statistics for the inner page file, if present.
+ * @author Erich Schubert
*
- * @return Inner page file statistics, or null.
+ * @apiviz.exclude
*/
- public PageFileStatistics getInnerStatistics();
+ public static class Parameterizer extends AbstractPageFileFactory.Parameterizer<Page> {
+ @Override
+ protected MemoryPageFileFactory<Page> makeInstance() {
+ return new MemoryPageFileFactory<>(pageSize);
+ }
+ }
}
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/OnDiskArray.java b/src/de/lmu/ifi/dbs/elki/persistent/OnDiskArray.java
index a37dcbdb..3f0965e2 100644
--- a/src/de/lmu/ifi/dbs/elki/persistent/OnDiskArray.java
+++ b/src/de/lmu/ifi/dbs/elki/persistent/OnDiskArray.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.persistent;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,7 +26,6 @@ package de.lmu.ifi.dbs.elki.persistent;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
-import java.io.Serializable;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel.MapMode;
@@ -45,11 +44,9 @@ import de.lmu.ifi.dbs.elki.utilities.exceptions.ExceptionMessages;
*
* @apiviz.composedOf RandomAccessFile
*/
-// TODO: make serializable - by just keeping the required information, restoring
-// the other.
// TODO: ensure file doesn't become to big - check for overflows in recordsize *
// numrecs + headersize
-public class OnDiskArray implements Serializable {
+public class OnDiskArray {
/**
* Serial version.
*
@@ -60,7 +57,7 @@ public class OnDiskArray implements Serializable {
private static final long serialVersionUID = 7586497243452875056L;
/**
- * Magic number used to identify files
+ * Magic number used to identify files.
*/
protected int magic;
@@ -96,10 +93,13 @@ public class OnDiskArray implements Serializable {
private FileLock lock = null;
/**
- * Writable or read-only object
+ * Writable or read-only object.
*/
private boolean writable;
+ /**
+ * The memory mapped buffer.
+ */
private MappedByteBuffer map;
/**
@@ -108,7 +108,7 @@ public class OnDiskArray implements Serializable {
private static final int INTERNAL_HEADER_SIZE = 4 * ByteArrayUtil.SIZE_INT;
/**
- * Position of file size (in records)
+ * Position of file size (in records).
*/
private static final int HEADER_POS_SIZE = 3 * ByteArrayUtil.SIZE_INT;
@@ -130,7 +130,7 @@ public class OnDiskArray implements Serializable {
this.writable = true;
// do not allow overwriting, unless empty
- if(filename.exists() && filename.length() > 0) {
+ if (filename.exists() && filename.length() > 0) {
throw new IOException(ExceptionMessages.FILE_EXISTS);
}
@@ -150,14 +150,14 @@ public class OnDiskArray implements Serializable {
// write number of records
// verify position.
- if(file.getFilePointer() != HEADER_POS_SIZE) {
+ if (file.getFilePointer() != HEADER_POS_SIZE) {
// TODO: more appropriate exception class?
throw new IOException("File position doesn't match when writing file size.");
}
file.writeInt(initialsize);
// we should have written the complete internal header now.
- if(file.getFilePointer() != INTERNAL_HEADER_SIZE) {
+ if (file.getFilePointer() != INTERNAL_HEADER_SIZE) {
// TODO: more appropriate exception class?
throw new IOException("File position doesn't match header size after writing header.");
}
@@ -191,7 +191,7 @@ public class OnDiskArray implements Serializable {
String mode = writable ? "rw" : "r";
file = new RandomAccessFile(filename, mode);
- if(writable) {
+ if (writable) {
// acquire a file write lock
lock = file.getChannel().lock();
}
@@ -219,7 +219,7 @@ public class OnDiskArray implements Serializable {
String mode = writable ? "rw" : "r";
file = new RandomAccessFile(filename, mode);
- if(writable) {
+ if (writable) {
// acquire a file write lock
lock = file.getChannel().lock();
}
@@ -254,39 +254,38 @@ public class OnDiskArray implements Serializable {
private void validateHeader(boolean validateRecordSize) throws IOException {
int readmagic = file.readInt();
// Validate magic number
- if(readmagic != this.magic) {
+ if (readmagic != this.magic) {
file.close();
throw new IOException("Magic in LinearDiskCache does not match: " + readmagic + " instead of " + this.magic);
}
// Validate header size
- if(file.readInt() != this.headersize) {
+ if (file.readInt() != this.headersize) {
file.close();
throw new IOException("Header size in LinearDiskCache does not match.");
}
- if(validateRecordSize) {
+ if (validateRecordSize) {
// Validate record size
- if(file.readInt() != this.recordsize) {
+ if (file.readInt() != this.recordsize) {
file.close();
throw new IOException("Recordsize in LinearDiskCache does not match.");
}
- }
- else {
+ } else {
// or just read it from file
this.recordsize = file.readInt();
}
// read the number of records and validate with file size.
- if(file.getFilePointer() != HEADER_POS_SIZE) {
+ if (file.getFilePointer() != HEADER_POS_SIZE) {
throw new IOException("Incorrect file position when reading header.");
}
this.numrecs = file.readInt();
- if(numrecs < 0 || file.length() != indexToFileposition(numrecs)) {
+ if (numrecs < 0 || file.length() != indexToFileposition(numrecs)) {
throw new IOException("File size and number of records do not agree.");
}
// yet another sanity check. We should have read all of our internal header
// now.
- if(file.getFilePointer() != INTERNAL_HEADER_SIZE) {
+ if (file.getFilePointer() != INTERNAL_HEADER_SIZE) {
throw new IOException("Incorrect file position after reading header.");
}
}
@@ -325,7 +324,7 @@ public class OnDiskArray implements Serializable {
* @throws IOException on IO errors
*/
public synchronized void resizeFile(int newsize) throws IOException {
- if(!writable) {
+ if (!writable) {
throw new IOException("File is not writeable!");
}
// update the number of records
@@ -346,11 +345,11 @@ public class OnDiskArray implements Serializable {
* @throws IOException on IO errors
*/
public synchronized ByteBuffer getRecordBuffer(int index) throws IOException {
- if(index < 0 || index >= numrecs) {
+ if (index < 0 || index >= numrecs) {
throw new IOException("Access beyond end of file.");
}
// Adjust buffer view
- synchronized(map) {
+ synchronized (map) {
map.limit(recordsize * (index + 1));
map.position(recordsize * index);
return map.slice();
@@ -413,7 +412,7 @@ public class OnDiskArray implements Serializable {
*/
public synchronized void close() throws IOException {
writable = false;
- if(lock != null) {
+ if (lock != null) {
lock.release();
lock = null;
}
@@ -436,8 +435,8 @@ public class OnDiskArray implements Serializable {
* @throws IOException
*/
public void ensureSize(int size) throws IOException {
- if(size > getNumRecords()) {
+ if (size > getNumRecords()) {
resizeFile(size);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/OnDiskArrayPageFile.java b/src/de/lmu/ifi/dbs/elki/persistent/OnDiskArrayPageFile.java
index 1f8c2a1a..061d4ce9 100644
--- a/src/de/lmu/ifi/dbs/elki/persistent/OnDiskArrayPageFile.java
+++ b/src/de/lmu/ifi/dbs/elki/persistent/OnDiskArrayPageFile.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.persistent;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -32,6 +32,7 @@ import java.io.ObjectOutputStream;
import java.nio.ByteBuffer;
import java.util.logging.Level;
+import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
/**
@@ -48,6 +49,11 @@ import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
*/
public class OnDiskArrayPageFile<P extends Page> extends AbstractStoringPageFile<P> {
/**
+ * Class logger.
+ */
+ private static final Logging LOG = Logging.getLogger(OnDiskArrayPageFile.class);
+
+ /**
* Indicates an empty page.
*/
private static final int EMPTY_PAGE = 0;
@@ -102,10 +108,9 @@ public class OnDiskArrayPageFile<P extends Page> extends AbstractStoringPageFile
@Override
public P readPage(int pageID) {
try {
- readAccess++;
+ countRead();
return byteBufferToPage(this.file.getRecordBuffer(pageID));
- }
- catch(IOException e) {
+ } catch (IOException e) {
throw new RuntimeException("IOException occurred during reading of page " + pageID, e);
}
}
@@ -123,11 +128,10 @@ public class OnDiskArrayPageFile<P extends Page> extends AbstractStoringPageFile
super.deletePage(pageID);
// delete from file
- writeAccess++;
+ countWrite();
byte[] array = pageToByteArray(null);
file.getRecordBuffer(pageID).put(array);
- }
- catch(IOException e) {
+ } catch (IOException e) {
throw new RuntimeException(e);
}
}
@@ -140,14 +144,13 @@ public class OnDiskArrayPageFile<P extends Page> extends AbstractStoringPageFile
*/
@Override
public void writePage(int pageID, P page) {
- if(page.isDirty()) {
+ if (page.isDirty()) {
try {
- writeAccess++;
+ countWrite();
byte[] array = pageToByteArray(page);
file.getRecordBuffer(pageID).put(array);
page.setDirty(false);
- }
- catch(IOException e) {
+ } catch (IOException e) {
throw new RuntimeException(e);
}
}
@@ -161,8 +164,7 @@ public class OnDiskArrayPageFile<P extends Page> extends AbstractStoringPageFile
try {
super.close();
file.close();
- }
- catch(IOException e) {
+ } catch (IOException e) {
throw new RuntimeException(e);
}
}
@@ -174,8 +176,7 @@ public class OnDiskArrayPageFile<P extends Page> extends AbstractStoringPageFile
public void clear() {
try {
file.resizeFile(0);
- }
- catch(IOException e) {
+ } catch (IOException e) {
throw new RuntimeException(e);
}
}
@@ -188,25 +189,20 @@ public class OnDiskArrayPageFile<P extends Page> extends AbstractStoringPageFile
*/
@SuppressWarnings("unchecked")
private P byteBufferToPage(ByteBuffer buffer) {
- try {
- InputStream bais = new ByteBufferInputStream(buffer);
- ObjectInputStream ois = new ObjectInputStream(bais);
+ try (InputStream bais = new ByteBufferInputStream(buffer);
+ ObjectInputStream ois = new ObjectInputStream(bais)) {
int type = ois.readInt();
- if(type == EMPTY_PAGE) {
+ if (type == EMPTY_PAGE) {
return null;
- }
- else if(type == FILLED_PAGE) {
+ } else if (type == FILLED_PAGE) {
return (P) ois.readObject();
- }
- else {
+ } else {
throw new IllegalArgumentException("Unknown type: " + type);
}
- }
- catch(IOException e) {
+ } catch (IOException e) {
LoggingUtil.exception(e);
return null;
- }
- catch(ClassNotFoundException e) {
+ } catch (ClassNotFoundException e) {
LoggingUtil.exception(e);
return null;
}
@@ -220,7 +216,7 @@ public class OnDiskArrayPageFile<P extends Page> extends AbstractStoringPageFile
*/
private byte[] pageToByteArray(P page) {
try {
- if(page == null) {
+ if (page == null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeInt(EMPTY_PAGE);
@@ -230,8 +226,7 @@ public class OnDiskArrayPageFile<P extends Page> extends AbstractStoringPageFile
byte[] result = new byte[pageSize];
System.arraycopy(array, 0, result, 0, array.length);
return result;
- }
- else {
+ } else {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeInt(FILLED_PAGE);
@@ -239,10 +234,9 @@ public class OnDiskArrayPageFile<P extends Page> extends AbstractStoringPageFile
oos.close();
baos.close();
byte[] array = baos.toByteArray();
- if(array.length > this.pageSize) {
+ if (array.length > this.pageSize) {
throw new IllegalArgumentException("Size of page " + page + " is greater than specified" + " pagesize: " + array.length + " > " + pageSize);
- }
- else if(array.length == this.pageSize) {
+ } else if (array.length == this.pageSize) {
return array;
}
@@ -252,8 +246,7 @@ public class OnDiskArrayPageFile<P extends Page> extends AbstractStoringPageFile
return result;
}
}
- }
- catch(IOException e) {
+ } catch (IOException e) {
throw new RuntimeException("IOException occurred! ", e);
}
}
@@ -262,7 +255,7 @@ public class OnDiskArrayPageFile<P extends Page> extends AbstractStoringPageFile
public boolean initialize(PageHeader header) {
this.header = header;
try {
- if(existed) {
+ if (existed) {
LoggingUtil.logExpensive(Level.INFO, "Create from existing file.");
this.file = new OnDiskArray(filename, 0, header.size(), pageSize, true);
@@ -275,17 +268,15 @@ public class OnDiskArrayPageFile<P extends Page> extends AbstractStoringPageFile
}
// reading empty nodes in Stack
- for(int i = 0; i < file.getNumRecords(); i++) {
+ for (int i = 0; i < file.getNumRecords(); i++) {
ByteBuffer buffer = file.getRecordBuffer(i);
int type = buffer.getInt();
- if(type == EMPTY_PAGE) {
+ if (type == EMPTY_PAGE) {
emptyPages.push(i);
- }
- else if(type == FILLED_PAGE) {
+ } else if (type == FILLED_PAGE) {
nextPageID = i + 1;
- }
- else {
+ } else {
throw new IllegalArgumentException("Unknown type: " + type);
}
i++;
@@ -304,9 +295,13 @@ public class OnDiskArrayPageFile<P extends Page> extends AbstractStoringPageFile
buffer.put(header.asByteArray());
return false;
}
- }
- catch(IOException e) {
+ } catch (IOException e) {
throw new RuntimeException("IOException occurred.", e);
}
}
+
+ @Override
+ protected Logging getLogger() {
+ return LOG;
+ }
}
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/OnDiskArrayPageFileFactory.java b/src/de/lmu/ifi/dbs/elki/persistent/OnDiskArrayPageFileFactory.java
new file mode 100644
index 00000000..4ddfdf4d
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/persistent/OnDiskArrayPageFileFactory.java
@@ -0,0 +1,101 @@
+package de.lmu.ifi.dbs.elki.persistent;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.FileParameter;
+
+/**
+ * Page file factory for disk-based page files.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has OnDiskArrayPageFile
+ *
+ * @param <P> Page type
+ */
+public class OnDiskArrayPageFileFactory<P extends ExternalizablePage> extends AbstractPageFileFactory<P> {
+ /**
+ * File name.
+ */
+ private String fileName;
+
+ /**
+ * Constructor.
+ *
+ * @param pageSize Page size
+ */
+ public OnDiskArrayPageFileFactory(int pageSize, String fileName) {
+ super(pageSize);
+ this.fileName = fileName;
+ }
+
+ @Override
+ public PageFile<P> newPageFile(Class<P> cls) {
+ if (fileName == null) {
+ throw new AbortException("Disk-backed page file may only be instantiated once!");
+ }
+ OnDiskArrayPageFile<P> pfile = new OnDiskArrayPageFile<>(pageSize, fileName);
+ fileName = null; // To avoid double instantiation.
+ return pfile;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @apiviz.exclude
+ *
+ * @author Erich Schubert
+ */
+ public static class Parameterizer extends AbstractPageFileFactory.Parameterizer<ExternalizablePage> {
+ /**
+ * File name.
+ */
+ private String fileName;
+
+ /**
+ * Optional parameter that specifies the name of the file storing the index.
+ * <p>
+ * Key: {@code -pagefile.file}
+ * </p>
+ */
+ public static final OptionID FILE_ID = new OptionID("pagefile.file", "The name of the file storing the page file.");
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ FileParameter fileNameP = new FileParameter(FILE_ID, FileParameter.FileType.OUTPUT_FILE);
+ if (config.grab(fileNameP)) {
+ fileName = fileNameP.getValue().getPath();
+ }
+ }
+
+ @Override
+ protected OnDiskArrayPageFileFactory<ExternalizablePage> makeInstance() {
+ return new OnDiskArrayPageFileFactory<>(pageSize, fileName);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/OnDiskUpperTriangleMatrix.java b/src/de/lmu/ifi/dbs/elki/persistent/OnDiskUpperTriangleMatrix.java
index 044657c5..6a6cad01 100644
--- a/src/de/lmu/ifi/dbs/elki/persistent/OnDiskUpperTriangleMatrix.java
+++ b/src/de/lmu/ifi/dbs/elki/persistent/OnDiskUpperTriangleMatrix.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.persistent;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/Page.java b/src/de/lmu/ifi/dbs/elki/persistent/Page.java
index 2c3fb252..9be6141c 100644
--- a/src/de/lmu/ifi/dbs/elki/persistent/Page.java
+++ b/src/de/lmu/ifi/dbs/elki/persistent/Page.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.persistent;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,6 +28,8 @@ package de.lmu.ifi.dbs.elki.persistent;
* persistently saved.
*
* @author Elke Achtert
+ *
+ * @apiviz.excludeSubtypes
*/
public interface Page {
/**
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/PageFile.java b/src/de/lmu/ifi/dbs/elki/persistent/PageFile.java
index f50e829e..e3978a51 100644
--- a/src/de/lmu/ifi/dbs/elki/persistent/PageFile.java
+++ b/src/de/lmu/ifi/dbs/elki/persistent/PageFile.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.persistent;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,15 +23,16 @@ package de.lmu.ifi.dbs.elki.persistent;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
/**
* Page file interface.
*
* @author Erich Schubert
*
+ * @apiviz.has Page
+ *
* @param <P> Page file
*/
-public interface PageFile<P extends Page> extends PageFileStatistics {
+public interface PageFile<P extends Page> {
/**
* Sets the id of the given page.
*
@@ -103,4 +104,9 @@ public interface PageFile<P extends Page> extends PageFileStatistics {
* @return true when the file already existed.
*/
public boolean initialize(PageHeader header);
-} \ No newline at end of file
+
+ /**
+ * Log some statistics to the appropriate logger.
+ */
+ public void logStatistics();
+}
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/PageFileFactory.java b/src/de/lmu/ifi/dbs/elki/persistent/PageFileFactory.java
new file mode 100644
index 00000000..3c7fa86d
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/persistent/PageFileFactory.java
@@ -0,0 +1,48 @@
+package de.lmu.ifi.dbs.elki.persistent;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Factory interface for generating page files.
+ *
+ * @author Erich Schubert
+ *
+ * @param <P> Page type
+ */
+public interface PageFileFactory<P extends Page> {
+ /**
+ * Make a new page file.
+ *
+ * @param cls Page class
+ * @return Page file
+ */
+ PageFile<P> newPageFile(Class<P> cls);
+
+ /**
+ * Query the page size.
+ *
+ * @return page size
+ */
+ int getPageSize();
+}
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/PageFileUtil.java b/src/de/lmu/ifi/dbs/elki/persistent/PageFileUtil.java
deleted file mode 100644
index 80a77fca..00000000
--- a/src/de/lmu/ifi/dbs/elki/persistent/PageFileUtil.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package de.lmu.ifi.dbs.elki.persistent;
-
-/*
- This file is part of ELKI:
- Environment for Developing KDD-Applications Supported by Index-Structures
-
- Copyright (C) 2012
- Ludwig-Maximilians-Universität München
- Lehr- und Forschungseinheit für Datenbanksysteme
- ELKI Development Team
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/**
- * Page file statistic utility functions.
- *
- * @author Erich Schubert
- *
- * @apiviz.landmark
- *
- * @apiviz.uses PageFileStatistics oneway - - analyses
- */
-public final class PageFileUtil {
- /**
- * Append the page file statistics to the output buffer.
- *
- * @param buffer Buffer to append to
- */
- public static void appendPageFileStatistics(StringBuilder buffer, PageFileStatistics statistics) {
- if(statistics != null) {
- buffer.append("Page File Layer: ").append(statistics.getClass()).append('\n');
- buffer.append("Read Operations: ").append(statistics.getReadOperations()).append('\n');
- buffer.append("Write Operations: ").append(statistics.getWriteOperations()).append('\n');
- PageFileStatistics inner = statistics.getInnerStatistics();
- if(inner != null) {
- appendPageFileStatistics(buffer, inner);
- }
- }
- }
-
- /**
- * Get the number of (logical) read operations (without caching).
- *
- * @param statistics Statistics.
- * @return logical read operations.
- */
- public static long getLogicalReadOperations(PageFileStatistics statistics) {
- return statistics.getReadOperations();
- }
-
- /**
- * Get the number of (logical) write operations (without caching).
- *
- * @param statistics Statistics.
- * @return logical write operations.
- */
- public static long getLogicalWriteOperations(PageFileStatistics statistics) {
- return statistics.getWriteOperations();
- }
-
- /**
- * Get the number of (physical) read operations (with caching).
- *
- * @param statistics Statistics.
- * @return physical read operations.
- */
- public static long getPhysicalReadOperations(PageFileStatistics statistics) {
- PageFileStatistics inner = statistics.getInnerStatistics();
- if(inner != null) {
- return getPhysicalReadOperations(inner);
- }
- return statistics.getReadOperations();
- }
-
- /**
- * Get the number of (physical) write operations (with caching).
- *
- * @param statistics Statistics.
- * @return physical write operations.
- */
- public static long getPhysicalWriteOperations(PageFileStatistics statistics) {
- PageFileStatistics inner = statistics.getInnerStatistics();
- if(inner != null) {
- return getPhysicalWriteOperations(inner);
- }
- return statistics.getWriteOperations();
- }
-} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/PageHeader.java b/src/de/lmu/ifi/dbs/elki/persistent/PageHeader.java
index 70a31190..9729b1e7 100644
--- a/src/de/lmu/ifi/dbs/elki/persistent/PageHeader.java
+++ b/src/de/lmu/ifi/dbs/elki/persistent/PageHeader.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.persistent;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/PersistentPageFile.java b/src/de/lmu/ifi/dbs/elki/persistent/PersistentPageFile.java
index 750ed646..5e0282c5 100644
--- a/src/de/lmu/ifi/dbs/elki/persistent/PersistentPageFile.java
+++ b/src/de/lmu/ifi/dbs/elki/persistent/PersistentPageFile.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.persistent;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -114,7 +114,7 @@ public class PersistentPageFile<P extends ExternalizablePage> extends AbstractSt
@Override
public P readPage(int pageID) {
try {
- readAccess++;
+ countRead();
long offset = ((long) (header.getReservedPages() + pageID)) * (long) pageSize;
byte[] buffer = new byte[pageSize];
file.seek(offset);
@@ -138,7 +138,7 @@ public class PersistentPageFile<P extends ExternalizablePage> extends AbstractSt
super.deletePage(pageID);
// delete from file
- writeAccess++;
+ countWrite();
byte[] array = pageToByteArray(null);
long offset = ((long) (header.getReservedPages() + pageID)) * (long) pageSize;
file.seek(offset);
@@ -158,7 +158,7 @@ public class PersistentPageFile<P extends ExternalizablePage> extends AbstractSt
@Override
public void writePage(int pageID, P page) {
try {
- writeAccess++;
+ countWrite();
byte[] array = pageToByteArray(page);
long offset = ((long) (header.getReservedPages() + pageID)) * (long) pageSize;
assert offset >= 0 : header.getReservedPages() + " " + pageID + " " + pageSize + " " + offset;
@@ -308,16 +308,18 @@ public class PersistentPageFile<P extends ExternalizablePage> extends AbstractSt
* Increases the {@link AbstractStoringPageFile#readAccess readAccess} counter by
* one.
*/
+ @Deprecated
public void increaseReadAccess() {
- readAccess++;
+ countRead();
}
/**
* Increases the {@link AbstractStoringPageFile#writeAccess writeAccess} counter by
* one.
*/
+ @Deprecated
public void increaseWriteAccess() {
- writeAccess++;
+ countWrite();
}
/**
@@ -398,4 +400,9 @@ public class PersistentPageFile<P extends ExternalizablePage> extends AbstractSt
// Return "new file" status
return existed;
}
+
+ @Override
+ protected Logging getLogger() {
+ return LOG;
+ }
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/PersistentPageFileFactory.java b/src/de/lmu/ifi/dbs/elki/persistent/PersistentPageFileFactory.java
new file mode 100644
index 00000000..5dfe9ecb
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/persistent/PersistentPageFileFactory.java
@@ -0,0 +1,101 @@
+package de.lmu.ifi.dbs.elki.persistent;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.FileParameter;
+
+/**
+ * Page file factory for disk-based page files.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has PersistentPageFile
+ *
+ * @param <P> Page type
+ */
+public class PersistentPageFileFactory<P extends ExternalizablePage> extends AbstractPageFileFactory<P> {
+ /**
+ * File name.
+ */
+ private String fileName;
+
+ /**
+ * Constructor.
+ *
+ * @param pageSize Page size
+ */
+ public PersistentPageFileFactory(int pageSize, String fileName) {
+ super(pageSize);
+ this.fileName = fileName;
+ }
+
+ @Override
+ public PageFile<P> newPageFile(Class<P> cls) {
+ if (fileName == null) {
+ throw new AbortException("Disk-backed page file may only be instantiated once!");
+ }
+ PersistentPageFile<P> pfile = new PersistentPageFile<>(pageSize, fileName, cls);
+ fileName = null; // To avoid double instantiation.
+ return pfile;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @apiviz.exclude
+ *
+ * @author Erich Schubert
+ */
+ public static class Parameterizer extends AbstractPageFileFactory.Parameterizer<ExternalizablePage> {
+ /**
+ * File name.
+ */
+ private String fileName;
+
+ /**
+ * Optional parameter that specifies the name of the file storing the index.
+ * <p>
+ * Key: {@code -pagefile.file}
+ * </p>
+ */
+ public static final OptionID FILE_ID = new OptionID("pagefile.file", "The name of the file storing the page file.");
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ FileParameter fileNameP = new FileParameter(FILE_ID, FileParameter.FileType.OUTPUT_FILE);
+ if (config.grab(fileNameP)) {
+ fileName = fileNameP.getValue().getPath();
+ }
+ }
+
+ @Override
+ protected PersistentPageFileFactory<ExternalizablePage> makeInstance() {
+ return new PersistentPageFileFactory<>(pageSize, fileName);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/package-info.java b/src/de/lmu/ifi/dbs/elki/persistent/package-info.java
index c2d8614c..45f575c1 100644
--- a/src/de/lmu/ifi/dbs/elki/persistent/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/persistent/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/AbstractHierarchicalResult.java b/src/de/lmu/ifi/dbs/elki/result/AbstractHierarchicalResult.java
index 0eba9564..203e8395 100644
--- a/src/de/lmu/ifi/dbs/elki/result/AbstractHierarchicalResult.java
+++ b/src/de/lmu/ifi/dbs/elki/result/AbstractHierarchicalResult.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/AprioriResult.java b/src/de/lmu/ifi/dbs/elki/result/AprioriResult.java
index 6b289f11..45e82b92 100644
--- a/src/de/lmu/ifi/dbs/elki/result/AprioriResult.java
+++ b/src/de/lmu/ifi/dbs/elki/result/AprioriResult.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/BasicResult.java b/src/de/lmu/ifi/dbs/elki/result/BasicResult.java
index 0e3bc571..f2d10149 100644
--- a/src/de/lmu/ifi/dbs/elki/result/BasicResult.java
+++ b/src/de/lmu/ifi/dbs/elki/result/BasicResult.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/CollectionResult.java b/src/de/lmu/ifi/dbs/elki/result/CollectionResult.java
index a43c6fd6..76e35e48 100644
--- a/src/de/lmu/ifi/dbs/elki/result/CollectionResult.java
+++ b/src/de/lmu/ifi/dbs/elki/result/CollectionResult.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/DBIDSelection.java b/src/de/lmu/ifi/dbs/elki/result/DBIDSelection.java
index d504ecbc..97459a6a 100644
--- a/src/de/lmu/ifi/dbs/elki/result/DBIDSelection.java
+++ b/src/de/lmu/ifi/dbs/elki/result/DBIDSelection.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.result;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/DiscardResultHandler.java b/src/de/lmu/ifi/dbs/elki/result/DiscardResultHandler.java
index 2499ff6a..847e22fb 100644
--- a/src/de/lmu/ifi/dbs/elki/result/DiscardResultHandler.java
+++ b/src/de/lmu/ifi/dbs/elki/result/DiscardResultHandler.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/HierarchicalResult.java b/src/de/lmu/ifi/dbs/elki/result/HierarchicalResult.java
index 695ba1aa..28841ddf 100644
--- a/src/de/lmu/ifi/dbs/elki/result/HierarchicalResult.java
+++ b/src/de/lmu/ifi/dbs/elki/result/HierarchicalResult.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/HistogramResult.java b/src/de/lmu/ifi/dbs/elki/result/HistogramResult.java
index 406eeffc..6e3fc745 100644
--- a/src/de/lmu/ifi/dbs/elki/result/HistogramResult.java
+++ b/src/de/lmu/ifi/dbs/elki/result/HistogramResult.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/IterableResult.java b/src/de/lmu/ifi/dbs/elki/result/IterableResult.java
index b53b4bb0..e7a6f35c 100644
--- a/src/de/lmu/ifi/dbs/elki/result/IterableResult.java
+++ b/src/de/lmu/ifi/dbs/elki/result/IterableResult.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/KMLOutputHandler.java b/src/de/lmu/ifi/dbs/elki/result/KMLOutputHandler.java
index 19a50b28..11391036 100644
--- a/src/de/lmu/ifi/dbs/elki/result/KMLOutputHandler.java
+++ b/src/de/lmu/ifi/dbs/elki/result/KMLOutputHandler.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -30,7 +30,6 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.Iterator;
import java.util.LinkedList;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@@ -53,6 +52,7 @@ import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
import de.lmu.ifi.dbs.elki.utilities.DatabaseUtil;
import de.lmu.ifi.dbs.elki.utilities.FormatUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.iterator.ArrayListIter;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
@@ -64,6 +64,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Flag;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
import de.lmu.ifi.dbs.elki.utilities.scaling.outlier.OutlierLinearScaling;
import de.lmu.ifi.dbs.elki.utilities.scaling.outlier.OutlierScalingFunction;
+import de.lmu.ifi.dbs.elki.workflow.OutputStep;
/**
* Class to handle KML output.
@@ -130,10 +131,10 @@ public class KMLOutputHandler implements ResultHandler, Parameterizable {
@Override
public void processNewResult(HierarchicalResult baseResult, Result newResult) {
ArrayList<OutlierResult> ors = ResultUtil.filterResults(newResult, OutlierResult.class);
- if(ors.size() > 1) {
+ if (ors.size() > 1) {
throw new AbortException("More than one outlier result found. The KML writer only supports a single outlier result!");
}
- if(ors.size() == 1) {
+ if (ors.size() == 1) {
Database database = ResultUtil.findDatabase(baseResult);
try {
XMLOutputFactory factory = XMLOutputFactory.newInstance();
@@ -146,27 +147,25 @@ public class KMLOutputHandler implements ResultHandler, Parameterizable {
out.closeEntry();
out.flush();
out.close();
- if(autoopen) {
+ if (autoopen) {
Desktop.getDesktop().open(filename);
}
- }
- catch(XMLStreamException e) {
+ } catch (XMLStreamException e) {
LOG.exception(e);
throw new AbortException("XML error in KML output.", e);
- }
- catch(IOException e) {
+ } catch (IOException e) {
LOG.exception(e);
throw new AbortException("IO error in KML output.", e);
}
}
}
- private void writeKMLData(XMLStreamWriter out, OutlierResult outlierResult, Database database) throws XMLStreamException {
+ private void writeKMLData(XMLStreamWriter xmlw, OutlierResult outlierResult, Database database) throws XMLStreamException {
Relation<Double> scores = outlierResult.getScores();
Relation<PolygonsObject> polys = database.getRelation(TypeUtil.POLYGON_TYPE);
Relation<String> labels = DatabaseUtil.guessObjectLabelRepresentation(database);
- Collection<Relation<?>> otherrel = new LinkedList<Relation<?>>(database.getRelations());
+ Collection<Relation<?>> otherrel = new LinkedList<>(database.getRelations());
otherrel.remove(scores);
otherrel.remove(polys);
otherrel.remove(labels);
@@ -176,130 +175,137 @@ public class KMLOutputHandler implements ResultHandler, Parameterizable {
scaling.prepare(outlierResult);
- out.writeStartDocument();
- out.writeCharacters("\n");
- out.writeStartElement("kml");
- out.writeDefaultNamespace("http://earth.google.com/kml/2.2");
- out.writeStartElement("Document");
+ xmlw.writeStartDocument();
+ xmlw.writeCharacters("\n");
+ xmlw.writeStartElement("kml");
+ xmlw.writeDefaultNamespace("http://earth.google.com/kml/2.2");
+ xmlw.writeStartElement("Document");
{
// TODO: can we automatically generate more helpful data here?
- out.writeStartElement("name");
- out.writeCharacters("ELKI KML output for " + outlierResult.getLongName());
- out.writeEndElement(); // name
- writeNewlineOnDebug(out);
+ xmlw.writeStartElement("name");
+ xmlw.writeCharacters("ELKI KML output for " + outlierResult.getLongName());
+ xmlw.writeEndElement(); // name
+ writeNewlineOnDebug(xmlw);
// TODO: e.g. list the settings in the description?
- out.writeStartElement("description");
- out.writeCharacters("ELKI KML output for " + outlierResult.getLongName());
- out.writeEndElement(); // description
- writeNewlineOnDebug(out);
+ xmlw.writeStartElement("description");
+ xmlw.writeCharacters("ELKI KML output for " + outlierResult.getLongName());
+ xmlw.writeEndElement(); // description
+ writeNewlineOnDebug(xmlw);
}
{
// TODO: generate styles from color scheme
- for(int i = 0; i < NUMSTYLES; i++) {
+ for (int i = 0; i < NUMSTYLES; i++) {
Color col = getColorForValue(i / (NUMSTYLES - 1.0));
- out.writeStartElement("Style");
- out.writeAttribute("id", "s" + i);
- writeNewlineOnDebug(out);
+ xmlw.writeStartElement("Style");
+ xmlw.writeAttribute("id", "s" + i);
+ writeNewlineOnDebug(xmlw);
{
- out.writeStartElement("LineStyle");
- out.writeStartElement("width");
- out.writeCharacters("0");
- out.writeEndElement(); // width
+ xmlw.writeStartElement("LineStyle");
+ xmlw.writeStartElement("width");
+ xmlw.writeCharacters("0");
+ xmlw.writeEndElement(); // width
- out.writeEndElement(); // LineStyle
+ xmlw.writeEndElement(); // LineStyle
}
- writeNewlineOnDebug(out);
+ writeNewlineOnDebug(xmlw);
{
- out.writeStartElement("PolyStyle");
- out.writeStartElement("color");
+ xmlw.writeStartElement("PolyStyle");
+ xmlw.writeStartElement("color");
// KML uses AABBGGRR format!
- out.writeCharacters(String.format("%02x%02x%02x%02x", col.getAlpha(), col.getBlue(), col.getGreen(), col.getRed()));
- out.writeEndElement(); // color
+ xmlw.writeCharacters(String.format("%02x%02x%02x%02x", col.getAlpha(), col.getBlue(), col.getGreen(), col.getRed()));
+ xmlw.writeEndElement(); // color
// out.writeStartElement("fill");
// out.writeCharacters("1"); // Default 1
// out.writeEndElement(); // fill
- out.writeStartElement("outline");
- out.writeCharacters("0");
- out.writeEndElement(); // outline
- out.writeEndElement(); // PolyStyle
+ xmlw.writeStartElement("outline");
+ xmlw.writeCharacters("0");
+ xmlw.writeEndElement(); // outline
+ xmlw.writeEndElement(); // PolyStyle
}
- writeNewlineOnDebug(out);
- out.writeEndElement(); // Style
- writeNewlineOnDebug(out);
+ writeNewlineOnDebug(xmlw);
+ xmlw.writeEndElement(); // Style
+ writeNewlineOnDebug(xmlw);
}
}
for (DBIDIter iter = outlierResult.getOrdering().iter(ids).iter(); iter.valid(); iter.advance()) {
Double score = scores.get(iter);
PolygonsObject poly = polys.get(iter);
String label = labels.get(iter);
- if(score == null) {
+ if (score == null) {
LOG.warning("No score for object " + DBIDUtil.toString(iter));
}
- if(poly == null) {
+ if (poly == null) {
LOG.warning("No polygon for object " + DBIDUtil.toString(iter) + " - skipping.");
continue;
}
- out.writeStartElement("Placemark");
+ xmlw.writeStartElement("Placemark");
{
- out.writeStartElement("name");
- out.writeCharacters(score + " " + label);
- out.writeEndElement(); // name
+ xmlw.writeStartElement("name");
+ xmlw.writeCharacters(score + " " + label);
+ xmlw.writeEndElement(); // name
StringBuilder buf = makeDescription(otherrel, iter);
- out.writeStartElement("description");
- out.writeCData("<div>" + buf.toString() + "</div>");
- out.writeEndElement(); // description
- out.writeStartElement("styleUrl");
+ xmlw.writeStartElement("description");
+ xmlw.writeCData("<div>" + buf.toString() + "</div>");
+ xmlw.writeEndElement(); // description
+ xmlw.writeStartElement("styleUrl");
int style = (int) (scaling.getScaled(score) * NUMSTYLES);
style = Math.max(0, Math.min(style, NUMSTYLES - 1));
- out.writeCharacters("#s" + style);
- out.writeEndElement(); // styleUrl
+ xmlw.writeCharacters("#s" + style);
+ xmlw.writeEndElement(); // styleUrl
}
{
- out.writeStartElement("Polygon");
- writeNewlineOnDebug(out);
- if(compat) {
- out.writeStartElement("altitudeMode");
- out.writeCharacters("relativeToGround");
- out.writeEndElement(); // close altitude mode
- writeNewlineOnDebug(out);
+ xmlw.writeStartElement("Polygon");
+ writeNewlineOnDebug(xmlw);
+ if (compat) {
+ xmlw.writeStartElement("altitudeMode");
+ xmlw.writeCharacters("relativeToGround");
+ xmlw.writeEndElement(); // close altitude mode
+ writeNewlineOnDebug(xmlw);
}
// First polygon clockwise?
boolean first = true;
- for(Polygon p : poly.getPolygons()) {
- if(first) {
- out.writeStartElement("outerBoundaryIs");
- }
- else {
- out.writeStartElement("innerBoundaryIs");
+ for (Polygon p : poly.getPolygons()) {
+ if (first) {
+ xmlw.writeStartElement("outerBoundaryIs");
+ } else {
+ xmlw.writeStartElement("innerBoundaryIs");
}
- out.writeStartElement("LinearRing");
- out.writeStartElement("coordinates");
+ xmlw.writeStartElement("LinearRing");
+ xmlw.writeStartElement("coordinates");
// Reverse anti-clockwise polygons.
boolean reverse = (p.testClockwise() >= 0);
- Iterator<Vector> it = reverse ? p.descendingIterator() : p.iterator();
- while(it.hasNext()) {
- Vector v = it.next();
- out.writeCharacters(FormatUtil.format(v.getArrayRef(), ","));
- if(compat && (v.getDimensionality() == 2)) {
- out.writeCharacters(",500");
+ ArrayListIter<Vector> it = p.iter();
+ if (reverse) {
+ it.seek(p.size() - 1);
+ }
+ while (it.valid()) {
+ Vector v = it.get();
+ xmlw.writeCharacters(FormatUtil.format(v.getArrayRef(), ","));
+ if (compat && (v.getDimensionality() == 2)) {
+ xmlw.writeCharacters(",500");
+ }
+ xmlw.writeCharacters(" ");
+ if (!reverse) {
+ it.advance();
+ } else {
+ it.retract();
}
- out.writeCharacters(" ");
}
- out.writeEndElement(); // close coordinates
- out.writeEndElement(); // close LinearRing
- out.writeEndElement(); // close *BoundaryIs
+ xmlw.writeEndElement(); // close coordinates
+ xmlw.writeEndElement(); // close LinearRing
+ xmlw.writeEndElement(); // close *BoundaryIs
first = false;
}
- writeNewlineOnDebug(out);
- out.writeEndElement(); // Polygon
+ writeNewlineOnDebug(xmlw);
+ xmlw.writeEndElement(); // Polygon
}
- out.writeEndElement(); // Placemark
- writeNewlineOnDebug(out);
+ xmlw.writeEndElement(); // Placemark
+ writeNewlineOnDebug(xmlw);
}
- out.writeEndElement(); // Document
- out.writeEndElement(); // kml
- out.writeEndDocument();
+ xmlw.writeEndElement(); // Document
+ xmlw.writeEndElement(); // kml
+ xmlw.writeEndDocument();
}
/**
@@ -311,15 +317,15 @@ public class KMLOutputHandler implements ResultHandler, Parameterizable {
*/
private StringBuilder makeDescription(Collection<Relation<?>> relations, DBIDRef id) {
StringBuilder buf = new StringBuilder();
- for(Relation<?> rel : relations) {
+ for (Relation<?> rel : relations) {
Object o = rel.get(id);
- if(o == null) {
+ if (o == null) {
continue;
}
String s = o.toString();
// FIXME: strip html characters
- if(s != null) {
- if(buf.length() > 0) {
+ if (s != null) {
+ if (buf.length() > 0) {
buf.append("<br />");
}
buf.append(s);
@@ -335,7 +341,7 @@ public class KMLOutputHandler implements ResultHandler, Parameterizable {
* @throws XMLStreamException
*/
private void writeNewlineOnDebug(XMLStreamWriter out) throws XMLStreamException {
- if(LOG.isDebugging()) {
+ if (LOG.isDebugging()) {
out.writeCharacters("\n");
}
}
@@ -352,12 +358,12 @@ public class KMLOutputHandler implements ResultHandler, Parameterizable {
// Colors at these positions
Color[] cols = new Color[] { new Color(0.0f, 0.0f, 0.0f, 0.6f), new Color(0.0f, 0.0f, 1.0f, 0.8f), new Color(1.0f, 0.0f, 0.0f, 0.9f), new Color(1.0f, 1.0f, 0.0f, 1.0f) };
assert (pos.length == cols.length);
- if(val < pos[0]) {
+ if (val < pos[0]) {
val = pos[0];
}
// Linear interpolation:
- for(int i = 1; i < pos.length; i++) {
- if(val <= pos[i]) {
+ for (int i = 1; i < pos.length; i++) {
+ if (val <= pos[i]) {
Color prev = cols[i - 1];
Color next = cols[i];
final double mix = (val - pos[i - 1]) / (pos[i] - pos[i - 1]);
@@ -430,24 +436,24 @@ public class KMLOutputHandler implements ResultHandler, Parameterizable {
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- FileParameter outputP = new FileParameter(OptionID.OUTPUT, FileParameter.FileType.OUTPUT_FILE);
+ FileParameter outputP = new FileParameter(OutputStep.Parameterizer.OUTPUT_ID, FileParameter.FileType.OUTPUT_FILE);
outputP.setShortDescription("Filename the KMZ file (compressed KML) is written to.");
- if(config.grab(outputP)) {
+ if (config.grab(outputP)) {
filename = outputP.getValue();
}
- ObjectParameter<OutlierScalingFunction> scalingP = new ObjectParameter<OutlierScalingFunction>(SCALING_ID, OutlierScalingFunction.class, OutlierLinearScaling.class);
- if(config.grab(scalingP)) {
+ ObjectParameter<OutlierScalingFunction> scalingP = new ObjectParameter<>(SCALING_ID, OutlierScalingFunction.class, OutlierLinearScaling.class);
+ if (config.grab(scalingP)) {
scaling = scalingP.instantiateClass(config);
}
Flag compatF = new Flag(COMPAT_ID);
- if(config.grab(compatF)) {
+ if (config.grab(compatF)) {
compat = compatF.getValue();
}
Flag autoopenF = new Flag(AUTOOPEN_ID);
- if(config.grab(autoopenF)) {
+ if (config.grab(autoopenF)) {
autoopen = autoopenF.getValue();
}
}
@@ -457,4 +463,4 @@ public class KMLOutputHandler implements ResultHandler, Parameterizable {
return new KMLOutputHandler(filename, scaling, compat, autoopen);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/result/KNNDistanceOrderResult.java b/src/de/lmu/ifi/dbs/elki/result/KNNDistanceOrderResult.java
index 0e5782bc..bbe21b0a 100644
--- a/src/de/lmu/ifi/dbs/elki/result/KNNDistanceOrderResult.java
+++ b/src/de/lmu/ifi/dbs/elki/result/KNNDistanceOrderResult.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/LogResultStructureResultHandler.java b/src/de/lmu/ifi/dbs/elki/result/LogResultStructureResultHandler.java
index 61fae67a..4224ae0a 100644
--- a/src/de/lmu/ifi/dbs/elki/result/LogResultStructureResultHandler.java
+++ b/src/de/lmu/ifi/dbs/elki/result/LogResultStructureResultHandler.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -51,10 +51,10 @@ public class LogResultStructureResultHandler implements ResultHandler {
@Override
public void processNewResult(HierarchicalResult baseResult, Result newResult) {
- if(LOG.isVerbose()) {
- if(newResult instanceof HierarchicalResult) {
+ if (LOG.isVerbose()) {
+ if (newResult instanceof HierarchicalResult) {
Hierarchy<Result> hier = ((HierarchicalResult) newResult).getHierarchy();
- if(hier != null) {
+ if (hier != null) {
StringBuilder buf = new StringBuilder();
recursiveLogResult(buf, hier, newResult, 0);
LOG.verbose(buf.toString());
@@ -71,24 +71,24 @@ public class LogResultStructureResultHandler implements ResultHandler {
* @param depth Depth
*/
private void recursiveLogResult(StringBuilder buf, Hierarchy<Result> hier, Result result, int depth) {
- if(result == null) {
+ if (result == null) {
buf.append("null");
LOG.warning("null result!");
return;
}
- if(depth > 50) {
+ if (depth > 50) {
LOG.warning("Probably infinitely nested results, aborting!");
return;
}
- for(int i = 0; i < depth; i++) {
+ for (int i = 0; i < depth; i++) {
buf.append(" ");
}
buf.append(result.getClass().getSimpleName()).append(": ").append(result.getLongName());
buf.append(" (").append(result.getShortName()).append(")\n");
- if(hier.getChildren(result).size() > 0) {
- for(Result r : hier.getChildren(result)) {
- recursiveLogResult(buf, hier, r, depth + 1);
+ if (hier.numChildren(result) > 0) {
+ for (Hierarchy.Iter<Result> iter = hier.iterChildren(result); iter.valid(); iter.advance()) {
+ recursiveLogResult(buf, hier, iter.get(), depth + 1);
}
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/result/OrderingFromDataStore.java b/src/de/lmu/ifi/dbs/elki/result/OrderingFromDataStore.java
index 65713b11..74eb5323 100644
--- a/src/de/lmu/ifi/dbs/elki/result/OrderingFromDataStore.java
+++ b/src/de/lmu/ifi/dbs/elki/result/OrderingFromDataStore.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/OrderingResult.java b/src/de/lmu/ifi/dbs/elki/result/OrderingResult.java
index 8e4e9e5f..b3261e61 100644
--- a/src/de/lmu/ifi/dbs/elki/result/OrderingResult.java
+++ b/src/de/lmu/ifi/dbs/elki/result/OrderingResult.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/PixmapResult.java b/src/de/lmu/ifi/dbs/elki/result/PixmapResult.java
index 776753e2..f6b4512b 100644
--- a/src/de/lmu/ifi/dbs/elki/result/PixmapResult.java
+++ b/src/de/lmu/ifi/dbs/elki/result/PixmapResult.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/RangeSelection.java b/src/de/lmu/ifi/dbs/elki/result/RangeSelection.java
index f70c1771..b4cc092f 100644
--- a/src/de/lmu/ifi/dbs/elki/result/RangeSelection.java
+++ b/src/de/lmu/ifi/dbs/elki/result/RangeSelection.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.result;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/ReferencePointsResult.java b/src/de/lmu/ifi/dbs/elki/result/ReferencePointsResult.java
index 3964c418..92f59101 100644
--- a/src/de/lmu/ifi/dbs/elki/result/ReferencePointsResult.java
+++ b/src/de/lmu/ifi/dbs/elki/result/ReferencePointsResult.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.result;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/Result.java b/src/de/lmu/ifi/dbs/elki/result/Result.java
index ebd0bed1..99f68402 100644
--- a/src/de/lmu/ifi/dbs/elki/result/Result.java
+++ b/src/de/lmu/ifi/dbs/elki/result/Result.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/ResultAdapter.java b/src/de/lmu/ifi/dbs/elki/result/ResultAdapter.java
index be81a508..fa02b57b 100644
--- a/src/de/lmu/ifi/dbs/elki/result/ResultAdapter.java
+++ b/src/de/lmu/ifi/dbs/elki/result/ResultAdapter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/ResultHandler.java b/src/de/lmu/ifi/dbs/elki/result/ResultHandler.java
index 1fef628f..56e25d27 100644
--- a/src/de/lmu/ifi/dbs/elki/result/ResultHandler.java
+++ b/src/de/lmu/ifi/dbs/elki/result/ResultHandler.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/ResultHierarchy.java b/src/de/lmu/ifi/dbs/elki/result/ResultHierarchy.java
index 2aba395b..52b63d3b 100644
--- a/src/de/lmu/ifi/dbs/elki/result/ResultHierarchy.java
+++ b/src/de/lmu/ifi/dbs/elki/result/ResultHierarchy.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,12 +23,11 @@ package de.lmu.ifi.dbs.elki.result;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.List;
-
import javax.swing.event.EventListenerList;
import de.lmu.ifi.dbs.elki.logging.Logging;
-import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.HierarchyHashmapList;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.HashMapHierarchy;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.Hierarchy;
import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.ModifiableHierarchy;
/**
@@ -37,12 +36,12 @@ import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.ModifiableHierarch
* @author Erich Schubert
*/
// TODO: add listener merging!
-public class ResultHierarchy extends HierarchyHashmapList<Result> {
+public class ResultHierarchy extends HashMapHierarchy<Result> {
/**
* Logger
*/
private static final Logging LOG = Logging.getLogger(ResultHierarchy.class);
-
+
/**
* Holds the listener.
*/
@@ -58,15 +57,16 @@ public class ResultHierarchy extends HierarchyHashmapList<Result> {
@Override
public void add(Result parent, Result child) {
super.add(parent, child);
- if(child instanceof HierarchicalResult) {
+ if (child instanceof HierarchicalResult) {
HierarchicalResult hr = (HierarchicalResult) child;
ModifiableHierarchy<Result> h = hr.getHierarchy();
// Merge hierarchy
hr.setHierarchy(this);
// Add children of child
- for(Result desc : h.getChildren(hr)) {
+ for (Hierarchy.Iter<Result> iter = h.iterChildren(hr); iter.valid(); iter.advance()) {
+ Result desc = iter.get();
this.add(hr, desc);
- if(desc instanceof HierarchicalResult) {
+ if (desc instanceof HierarchicalResult) {
((HierarchicalResult) desc).setHierarchy(this);
}
}
@@ -80,12 +80,6 @@ public class ResultHierarchy extends HierarchyHashmapList<Result> {
fireResultRemoved(child, parent);
}
- @Override
- public void put(Result obj, List<Result> parents, List<Result> children) {
- // TODO: can we support this somehow? Or reduce visibility?
- throw new UnsupportedOperationException();
- }
-
/**
* Register a result listener.
*
@@ -120,10 +114,10 @@ public class ResultHierarchy extends HierarchyHashmapList<Result> {
* @param parent Parent result that was added to
*/
private void fireResultAdded(Result child, Result parent) {
- if(LOG.isDebugging()) {
+ if (LOG.isDebugging()) {
LOG.debug("Result added: " + child + " <- " + parent);
}
- for(ResultListener l : listenerList.getListeners(ResultListener.class)) {
+ for (ResultListener l : listenerList.getListeners(ResultListener.class)) {
l.resultAdded(child, parent);
}
}
@@ -134,10 +128,10 @@ public class ResultHierarchy extends HierarchyHashmapList<Result> {
* @param current Result that has changed
*/
private void fireResultChanged(Result current) {
- if(LOG.isDebugging()) {
+ if (LOG.isDebugging()) {
LOG.debug("Result changed: " + current);
}
- for(ResultListener l : listenerList.getListeners(ResultListener.class)) {
+ for (ResultListener l : listenerList.getListeners(ResultListener.class)) {
l.resultChanged(current);
}
}
@@ -150,11 +144,11 @@ public class ResultHierarchy extends HierarchyHashmapList<Result> {
* @param parent Parent result that has been removed
*/
private void fireResultRemoved(Result child, Result parent) {
- if(LOG.isDebugging()) {
+ if (LOG.isDebugging()) {
LOG.debug("Result removed: " + child + " <- " + parent);
}
- for(ResultListener l : listenerList.getListeners(ResultListener.class)) {
+ for (ResultListener l : listenerList.getListeners(ResultListener.class)) {
l.resultRemoved(child, parent);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/result/ResultListener.java b/src/de/lmu/ifi/dbs/elki/result/ResultListener.java
index d675af28..899aa008 100644
--- a/src/de/lmu/ifi/dbs/elki/result/ResultListener.java
+++ b/src/de/lmu/ifi/dbs/elki/result/ResultListener.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/ResultProcessor.java b/src/de/lmu/ifi/dbs/elki/result/ResultProcessor.java
index 47273b89..88eb3607 100644
--- a/src/de/lmu/ifi/dbs/elki/result/ResultProcessor.java
+++ b/src/de/lmu/ifi/dbs/elki/result/ResultProcessor.java
@@ -1,12 +1,10 @@
package de.lmu.ifi.dbs.elki.result;
-import de.lmu.ifi.dbs.elki.utilities.InspectionUtilFrequentlyScanned;
-
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,8 +23,6 @@ import de.lmu.ifi.dbs.elki.utilities.InspectionUtilFrequentlyScanned;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
-
/**
* Interface for any class that can handle results
*
@@ -34,7 +30,7 @@ import de.lmu.ifi.dbs.elki.utilities.InspectionUtilFrequentlyScanned;
*
* @apiviz.uses Result oneway - - processes
*/
-public interface ResultProcessor extends InspectionUtilFrequentlyScanned {
+public interface ResultProcessor {
/**
* Process a result.
*
diff --git a/src/de/lmu/ifi/dbs/elki/result/ResultUtil.java b/src/de/lmu/ifi/dbs/elki/result/ResultUtil.java
index d081bc2e..e0e59482 100644
--- a/src/de/lmu/ifi/dbs/elki/result/ResultUtil.java
+++ b/src/de/lmu/ifi/dbs/elki/result/ResultUtil.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,7 +26,6 @@ package de.lmu.ifi.dbs.elki.result;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.Iterator;
import java.util.List;
import de.lmu.ifi.dbs.elki.algorithm.clustering.ClusteringAlgorithm;
@@ -38,6 +37,7 @@ import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.Hierarchy;
/**
* Utilities for handling result objects
@@ -54,12 +54,12 @@ public class ResultUtil {
* @return List of all annotation results
*/
public static List<Relation<?>> getRelations(Result r) {
- if(r instanceof Relation<?>) {
- List<Relation<?>> anns = new ArrayList<Relation<?>>(1);
+ if (r instanceof Relation<?>) {
+ List<Relation<?>> anns = new ArrayList<>(1);
anns.add((Relation<?>) r);
return anns;
}
- if(r instanceof HierarchicalResult) {
+ if (r instanceof HierarchicalResult) {
return ClassGenericsUtil.castWithGenericsOrNull(List.class, filterResults((HierarchicalResult) r, Relation.class));
}
return Collections.emptyList();
@@ -72,12 +72,12 @@ public class ResultUtil {
* @return List of ordering results
*/
public static List<OrderingResult> getOrderingResults(Result r) {
- if(r instanceof OrderingResult) {
- List<OrderingResult> ors = new ArrayList<OrderingResult>(1);
+ if (r instanceof OrderingResult) {
+ List<OrderingResult> ors = new ArrayList<>(1);
ors.add((OrderingResult) r);
return ors;
}
- if(r instanceof HierarchicalResult) {
+ if (r instanceof HierarchicalResult) {
return filterResults((HierarchicalResult) r, OrderingResult.class);
}
return Collections.emptyList();
@@ -90,12 +90,12 @@ public class ResultUtil {
* @return List of clustering results
*/
public static List<Clustering<? extends Model>> getClusteringResults(Result r) {
- if(r instanceof Clustering<?>) {
- List<Clustering<?>> crs = new ArrayList<Clustering<?>>(1);
+ if (r instanceof Clustering<?>) {
+ List<Clustering<?>> crs = new ArrayList<>(1);
crs.add((Clustering<?>) r);
return crs;
}
- if(r instanceof HierarchicalResult) {
+ if (r instanceof HierarchicalResult) {
return ClassGenericsUtil.castWithGenericsOrNull(List.class, filterResults((HierarchicalResult) r, Clustering.class));
}
return Collections.emptyList();
@@ -108,12 +108,12 @@ public class ResultUtil {
* @return List of collection results
*/
public static List<CollectionResult<?>> getCollectionResults(Result r) {
- if(r instanceof CollectionResult<?>) {
- List<CollectionResult<?>> crs = new ArrayList<CollectionResult<?>>(1);
+ if (r instanceof CollectionResult<?>) {
+ List<CollectionResult<?>> crs = new ArrayList<>(1);
crs.add((CollectionResult<?>) r);
return crs;
}
- if(r instanceof HierarchicalResult) {
+ if (r instanceof HierarchicalResult) {
return ClassGenericsUtil.castWithGenericsOrNull(List.class, filterResults((HierarchicalResult) r, CollectionResult.class));
}
return Collections.emptyList();
@@ -126,12 +126,12 @@ public class ResultUtil {
* @return List of iterable results
*/
public static List<IterableResult<?>> getIterableResults(Result r) {
- if(r instanceof IterableResult<?>) {
- List<IterableResult<?>> irs = new ArrayList<IterableResult<?>>(1);
+ if (r instanceof IterableResult<?>) {
+ List<IterableResult<?>> irs = new ArrayList<>(1);
irs.add((IterableResult<?>) r);
return irs;
}
- if(r instanceof HierarchicalResult) {
+ if (r instanceof HierarchicalResult) {
return ClassGenericsUtil.castWithGenericsOrNull(List.class, filterResults((HierarchicalResult) r, IterableResult.class));
}
return Collections.emptyList();
@@ -144,12 +144,12 @@ public class ResultUtil {
* @return List of outlier results
*/
public static List<OutlierResult> getOutlierResults(Result r) {
- if(r instanceof OutlierResult) {
- List<OutlierResult> ors = new ArrayList<OutlierResult>(1);
+ if (r instanceof OutlierResult) {
+ List<OutlierResult> ors = new ArrayList<>(1);
ors.add((OutlierResult) r);
return ors;
}
- if(r instanceof HierarchicalResult) {
+ if (r instanceof HierarchicalResult) {
return filterResults((HierarchicalResult) r, OutlierResult.class);
}
return Collections.emptyList();
@@ -162,12 +162,12 @@ public class ResultUtil {
* @return List of settings results
*/
public static List<SettingsResult> getSettingsResults(Result r) {
- if(r instanceof SettingsResult) {
- List<SettingsResult> ors = new ArrayList<SettingsResult>(1);
+ if (r instanceof SettingsResult) {
+ List<SettingsResult> ors = new ArrayList<>(1);
ors.add((SettingsResult) r);
return ors;
}
- if(r instanceof HierarchicalResult) {
+ if (r instanceof HierarchicalResult) {
return filterResults((HierarchicalResult) r, SettingsResult.class);
}
return Collections.emptyList();
@@ -183,14 +183,14 @@ public class ResultUtil {
// We can't ensure that restrictionClass matches C.
@SuppressWarnings("unchecked")
public static <C> ArrayList<C> filterResults(Result r, Class<?> restrictionClass) {
- ArrayList<C> res = new ArrayList<C>();
- if(restrictionClass.isInstance(r)) {
+ ArrayList<C> res = new ArrayList<>();
+ if (restrictionClass.isInstance(r)) {
res.add((C) restrictionClass.cast(r));
}
- if(r instanceof HierarchicalResult) {
- for(Iterator<Result> iter = ((HierarchicalResult) r).getHierarchy().iterDescendants(r); iter.hasNext();) {
- Result result = iter.next();
- if(restrictionClass.isInstance(result)) {
+ if (r instanceof HierarchicalResult) {
+ for (Hierarchy.Iter<Result> iter = ((HierarchicalResult) r).getHierarchy().iterDescendants(r); iter.valid(); iter.advance()) {
+ Result result = iter.get();
+ if (restrictionClass.isInstance(result)) {
res.add((C) restrictionClass.cast(result));
}
}
@@ -207,7 +207,7 @@ public class ResultUtil {
*/
public static <O> void ensureClusteringResult(final Database db, final Result result) {
Collection<Clustering<?>> clusterings = ResultUtil.filterResults(result, Clustering.class);
- if(clusterings.size() == 0) {
+ if (clusterings.size() == 0) {
ClusteringAlgorithm<Clustering<Model>> split = new ByLabelOrAllInOneClustering();
Clustering<Model> c = split.run(db);
addChildResult(db, c);
@@ -222,7 +222,7 @@ public class ResultUtil {
*/
public static SelectionResult ensureSelectionResult(final Database db) {
List<SelectionResult> selections = ResultUtil.filterResults(db, SelectionResult.class);
- if(!selections.isEmpty()) {
+ if (!selections.isEmpty()) {
return selections.get(0);
}
SelectionResult sel = new SelectionResult();
@@ -238,7 +238,7 @@ public class ResultUtil {
*/
public static SamplingResult getSamplingResult(final Relation<?> rel) {
Collection<SamplingResult> selections = ResultUtil.filterResults(rel, SamplingResult.class);
- if(selections.size() == 0) {
+ if (selections.size() == 0) {
final SamplingResult newsam = new SamplingResult(rel);
addChildResult(rel, newsam);
return newsam;
@@ -254,7 +254,7 @@ public class ResultUtil {
*/
public static ScalesResult getScalesResult(final Relation<? extends NumberVector<?>> rel) {
Collection<ScalesResult> scas = ResultUtil.filterResults(rel, ScalesResult.class);
- if(scas.size() == 0) {
+ if (scas.size() == 0) {
final ScalesResult newsca = new ScalesResult(rel);
addChildResult(rel, newsca);
return newsca;
@@ -280,10 +280,9 @@ public class ResultUtil {
*/
public static Database findDatabase(Result baseResult) {
final List<Database> dbs = filterResults(baseResult, Database.class);
- if(!dbs.isEmpty()) {
+ if (!dbs.isEmpty()) {
return dbs.get(0);
- }
- else {
+ } else {
return null;
}
}
@@ -295,11 +294,11 @@ public class ResultUtil {
* @param child Result to remove
*/
public static void removeRecursive(ResultHierarchy hierarchy, Result child) {
- for(Result parent : hierarchy.getParents(child)) {
- hierarchy.remove(parent, child);
+ for (Hierarchy.Iter<Result> iter = hierarchy.iterParents(child); iter.valid(); iter.advance()) {
+ hierarchy.remove(iter.get(), child);
}
- for(Result sub : hierarchy.getChildren(child)) {
- removeRecursive(hierarchy, sub);
+ for (Hierarchy.Iter<Result> iter = hierarchy.iterChildren(child); iter.valid(); iter.advance()) {
+ removeRecursive(hierarchy, iter.get());
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/result/ResultWriter.java b/src/de/lmu/ifi/dbs/elki/result/ResultWriter.java
index 45475dd2..f3b39580 100644
--- a/src/de/lmu/ifi/dbs/elki/result/ResultWriter.java
+++ b/src/de/lmu/ifi/dbs/elki/result/ResultWriter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,6 +25,7 @@ package de.lmu.ifi.dbs.elki.result;
import java.io.File;
import java.io.IOException;
+import java.util.regex.Pattern;
import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.logging.Logging;
@@ -38,9 +39,13 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.FileParameter;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Flag;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.PatternParameter;
+import de.lmu.ifi.dbs.elki.workflow.OutputStep;
/**
- * Result handler that feeds the data into a TextWriter
+ * Result handler that feeds the data into a TextWriter.
+ *
+ * Note: these classes need to be rewritten. Contributions welcome!
*
* @author Erich Schubert
*/
@@ -51,22 +56,6 @@ public class ResultWriter implements ResultHandler {
private static final Logging LOG = Logging.getLogger(ResultWriter.class);
/**
- * Flag to control GZIP compression.
- * <p>
- * Key: {@code -out.gzip}
- * </p>
- */
- public static final OptionID GZIP_OUTPUT_ID = new OptionID("out.gzip", "Enable gzip compression of output files.");
-
- /**
- * Flag to suppress overwrite warning.
- * <p>
- * Key: {@code -out.silentoverwrite}
- * </p>
- */
- public static final OptionID OVERWRITE_OPTION_ID = new OptionID("out.silentoverwrite", "Silently overwrite output files.");
-
- /**
* Holds the file to print results to.
*/
private File out;
@@ -82,17 +71,24 @@ public class ResultWriter implements ResultHandler {
private boolean warnoverwrite = true;
/**
+ * Result filter pattern. Optional!
+ */
+ private Pattern filter = null;
+
+ /**
* Constructor.
*
- * @param out
- * @param gzip
- * @param warnoverwrite
+ * @param out Output file
+ * @param gzip Gzip compression
+ * @param warnoverwrite Warn before overwriting files
+ * @param filter Filter pattern
*/
- public ResultWriter(File out, boolean gzip, boolean warnoverwrite) {
+ public ResultWriter(File out, boolean gzip, boolean warnoverwrite, Pattern filter) {
super();
this.out = out;
this.gzip = gzip;
this.warnoverwrite = warnoverwrite;
+ this.filter = filter;
}
@Override
@@ -101,42 +97,35 @@ public class ResultWriter implements ResultHandler {
StreamFactory output;
try {
- if(out == null) {
+ if (out == null) {
output = new SingleStreamOutput(gzip);
- }
- else if(out.exists()) {
- if(out.isDirectory()) {
- if(warnoverwrite && out.listFiles().length > 0) {
+ } else if (out.exists()) {
+ if (out.isDirectory()) {
+ if (warnoverwrite && out.listFiles().length > 0) {
LOG.warning("Output directory specified is not empty. Files will be overwritten and old files may be left over.");
}
output = new MultipleFilesOutput(out, gzip);
- }
- else {
- if(warnoverwrite) {
+ } else {
+ if (warnoverwrite) {
LOG.warning("Output file exists and will be overwritten!");
}
output = new SingleStreamOutput(out, gzip);
}
- }
- else {
+ } else {
// If it doesn't exist yet, make a MultipleFilesOutput.
output = new MultipleFilesOutput(out, gzip);
}
- }
- catch(IOException e) {
+ } catch (IOException e) {
throw new IllegalStateException("Error opening output.", e);
}
try {
Database db = ResultUtil.findDatabase(baseresult);
- writer.output(db, result, output);
- }
- catch(IOException e) {
+ writer.output(db, result, output, filter);
+ } catch (IOException e) {
throw new IllegalStateException("Input/Output error while writing result.", e);
- }
- catch(UnableToComplyException e) {
+ } catch (UnableToComplyException e) {
throw new IllegalStateException("Unable to comply while writing result.", e);
}
- output.closeAllStreams();
}
/**
@@ -148,6 +137,30 @@ public class ResultWriter implements ResultHandler {
*/
public static class Parameterizer extends AbstractParameterizer {
/**
+ * Flag to control GZIP compression.
+ * <p>
+ * Key: {@code -out.gzip}
+ * </p>
+ */
+ public static final OptionID GZIP_OUTPUT_ID = new OptionID("out.gzip", "Enable gzip compression of output files.");
+
+ /**
+ * Flag to suppress overwrite warning.
+ * <p>
+ * Key: {@code -out.silentoverwrite}
+ * </p>
+ */
+ public static final OptionID OVERWRITE_OPTION_ID = new OptionID("out.silentoverwrite", "Silently overwrite output files.");
+
+ /**
+ * Pattern to filter the output
+ * <p>
+ * Key: {@code -out.filter}
+ * </p>
+ */
+ public static final OptionID FILTER_PATTERN_ID = new OptionID("out.filter", "Filter pattern for output selection. Only output streams that match the given pattern will be written.");
+
+ /**
* Holds the file to print results to.
*/
private File out = null;
@@ -162,29 +175,40 @@ public class ResultWriter implements ResultHandler {
*/
private boolean warnoverwrite = true;
+ /**
+ * Result filter pattern. Optional!
+ */
+ private Pattern filter = null;
+
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- FileParameter outputP = new FileParameter(OptionID.OUTPUT, FileParameter.FileType.OUTPUT_FILE, true);
- if(config.grab(outputP)) {
+ FileParameter outputP = new FileParameter(OutputStep.Parameterizer.OUTPUT_ID, FileParameter.FileType.OUTPUT_FILE, true);
+ if (config.grab(outputP)) {
out = outputP.getValue();
}
Flag gzipF = new Flag(GZIP_OUTPUT_ID);
- if(config.grab(gzipF)) {
+ if (config.grab(gzipF)) {
gzip = gzipF.getValue();
}
Flag overwriteF = new Flag(OVERWRITE_OPTION_ID);
- if(config.grab(overwriteF)) {
+ if (config.grab(overwriteF)) {
// note: inversed meaning
warnoverwrite = !overwriteF.getValue();
}
+
+ PatternParameter filterP = new PatternParameter(FILTER_PATTERN_ID);
+ filterP.setOptional(true);
+ if (config.grab(filterP)) {
+ filter = filterP.getValue();
+ }
}
@Override
protected ResultWriter makeInstance() {
- return new ResultWriter(out, gzip, warnoverwrite);
+ return new ResultWriter(out, gzip, warnoverwrite, filter);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/result/SamplingResult.java b/src/de/lmu/ifi/dbs/elki/result/SamplingResult.java
index 5e6c3df2..17471b9a 100644
--- a/src/de/lmu/ifi/dbs/elki/result/SamplingResult.java
+++ b/src/de/lmu/ifi/dbs/elki/result/SamplingResult.java
@@ -7,7 +7,7 @@ import de.lmu.ifi.dbs.elki.database.relation.Relation;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/ScalesResult.java b/src/de/lmu/ifi/dbs/elki/result/ScalesResult.java
index eca62474..8f9653d8 100644
--- a/src/de/lmu/ifi/dbs/elki/result/ScalesResult.java
+++ b/src/de/lmu/ifi/dbs/elki/result/ScalesResult.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/SelectionResult.java b/src/de/lmu/ifi/dbs/elki/result/SelectionResult.java
index a8fb4ed5..fda68c68 100644
--- a/src/de/lmu/ifi/dbs/elki/result/SelectionResult.java
+++ b/src/de/lmu/ifi/dbs/elki/result/SelectionResult.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/SettingsResult.java b/src/de/lmu/ifi/dbs/elki/result/SettingsResult.java
index d8c24737..ea6664e8 100644
--- a/src/de/lmu/ifi/dbs/elki/result/SettingsResult.java
+++ b/src/de/lmu/ifi/dbs/elki/result/SettingsResult.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/optics/ClusterOrderEntry.java b/src/de/lmu/ifi/dbs/elki/result/optics/ClusterOrderEntry.java
index 06e4766f..fab3a8c3 100644
--- a/src/de/lmu/ifi/dbs/elki/result/optics/ClusterOrderEntry.java
+++ b/src/de/lmu/ifi/dbs/elki/result/optics/ClusterOrderEntry.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.optics;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/optics/ClusterOrderResult.java b/src/de/lmu/ifi/dbs/elki/result/optics/ClusterOrderResult.java
index 66b53dd2..bd500dfa 100644
--- a/src/de/lmu/ifi/dbs/elki/result/optics/ClusterOrderResult.java
+++ b/src/de/lmu/ifi/dbs/elki/result/optics/ClusterOrderResult.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.optics;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -87,7 +87,7 @@ public class ClusterOrderResult<D extends Distance<D>> extends BasicResult imple
*/
public ClusterOrderResult(String name, String shortname) {
super(name, shortname);
- clusterOrder = new ArrayList<ClusterOrderEntry<D>>();
+ clusterOrder = new ArrayList<>();
dbids = DBIDUtil.newHashSet();
map = DataStoreUtil.makeStorage(dbids, DataStoreFactory.HINT_DB, ClusterOrderEntry.class);
@@ -121,7 +121,7 @@ public class ClusterOrderResult<D extends Distance<D>> extends BasicResult imple
* @param reachability Reachability distance
*/
public void add(DBID id, DBID predecessor, D reachability) {
- add(new GenericClusterOrderEntry<D>(id, predecessor, reachability));
+ add(new GenericClusterOrderEntry<>(id, predecessor, reachability));
dbids.add(id);
}
@@ -279,7 +279,7 @@ public class ClusterOrderResult<D extends Distance<D>> extends BasicResult imple
@Override
public SimpleTypeInformation<D> getDataTypeInformation() {
- return new SimpleTypeInformation<D>(Distance.class);
+ return new SimpleTypeInformation<>(Distance.class);
}
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/result/optics/DoubleDistanceClusterOrderEntry.java b/src/de/lmu/ifi/dbs/elki/result/optics/DoubleDistanceClusterOrderEntry.java
index f2ebcce3..74f65e73 100644
--- a/src/de/lmu/ifi/dbs/elki/result/optics/DoubleDistanceClusterOrderEntry.java
+++ b/src/de/lmu/ifi/dbs/elki/result/optics/DoubleDistanceClusterOrderEntry.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.optics;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/optics/GenericClusterOrderEntry.java b/src/de/lmu/ifi/dbs/elki/result/optics/GenericClusterOrderEntry.java
index b04d35ea..7af8a3ec 100644
--- a/src/de/lmu/ifi/dbs/elki/result/optics/GenericClusterOrderEntry.java
+++ b/src/de/lmu/ifi/dbs/elki/result/optics/GenericClusterOrderEntry.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.optics;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/optics/package-info.java b/src/de/lmu/ifi/dbs/elki/result/optics/package-info.java
index a61eb417..e74b3c7b 100644
--- a/src/de/lmu/ifi/dbs/elki/result/optics/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/result/optics/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/outlier/BasicOutlierScoreMeta.java b/src/de/lmu/ifi/dbs/elki/result/outlier/BasicOutlierScoreMeta.java
index 5d56117c..4dc64b2c 100644
--- a/src/de/lmu/ifi/dbs/elki/result/outlier/BasicOutlierScoreMeta.java
+++ b/src/de/lmu/ifi/dbs/elki/result/outlier/BasicOutlierScoreMeta.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/outlier/InvertedOutlierScoreMeta.java b/src/de/lmu/ifi/dbs/elki/result/outlier/InvertedOutlierScoreMeta.java
index 8658c938..d4ea456a 100644
--- a/src/de/lmu/ifi/dbs/elki/result/outlier/InvertedOutlierScoreMeta.java
+++ b/src/de/lmu/ifi/dbs/elki/result/outlier/InvertedOutlierScoreMeta.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/outlier/OrderingFromRelation.java b/src/de/lmu/ifi/dbs/elki/result/outlier/OrderingFromRelation.java
index a60bda3d..2950a2f8 100644
--- a/src/de/lmu/ifi/dbs/elki/result/outlier/OrderingFromRelation.java
+++ b/src/de/lmu/ifi/dbs/elki/result/outlier/OrderingFromRelation.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/outlier/OutlierResult.java b/src/de/lmu/ifi/dbs/elki/result/outlier/OutlierResult.java
index 5c4a58ae..13d5c1a0 100644
--- a/src/de/lmu/ifi/dbs/elki/result/outlier/OutlierResult.java
+++ b/src/de/lmu/ifi/dbs/elki/result/outlier/OutlierResult.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/outlier/OutlierScoreMeta.java b/src/de/lmu/ifi/dbs/elki/result/outlier/OutlierScoreMeta.java
index c71f20ce..a17bade5 100644
--- a/src/de/lmu/ifi/dbs/elki/result/outlier/OutlierScoreMeta.java
+++ b/src/de/lmu/ifi/dbs/elki/result/outlier/OutlierScoreMeta.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/outlier/ProbabilisticOutlierScore.java b/src/de/lmu/ifi/dbs/elki/result/outlier/ProbabilisticOutlierScore.java
index 844bb919..36cd081e 100644
--- a/src/de/lmu/ifi/dbs/elki/result/outlier/ProbabilisticOutlierScore.java
+++ b/src/de/lmu/ifi/dbs/elki/result/outlier/ProbabilisticOutlierScore.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/outlier/QuotientOutlierScoreMeta.java b/src/de/lmu/ifi/dbs/elki/result/outlier/QuotientOutlierScoreMeta.java
index e0dc36ec..3ac643e6 100644
--- a/src/de/lmu/ifi/dbs/elki/result/outlier/QuotientOutlierScoreMeta.java
+++ b/src/de/lmu/ifi/dbs/elki/result/outlier/QuotientOutlierScoreMeta.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/outlier/package-info.java b/src/de/lmu/ifi/dbs/elki/result/outlier/package-info.java
index f72e5366..7007c8b4 100644
--- a/src/de/lmu/ifi/dbs/elki/result/outlier/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/result/outlier/package-info.java
@@ -6,7 +6,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/package-info.java b/src/de/lmu/ifi/dbs/elki/result/package-info.java
index 70894b93..0f3e3aa8 100644
--- a/src/de/lmu/ifi/dbs/elki/result/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/result/package-info.java
@@ -12,7 +12,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/MultipleFilesOutput.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/MultipleFilesOutput.java
index 2e089274..22bde5be 100644
--- a/src/de/lmu/ifi/dbs/elki/result/textwriter/MultipleFilesOutput.java
+++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/MultipleFilesOutput.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.textwriter;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,7 +28,6 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
-import java.util.HashMap;
import java.util.zip.GZIPOutputStream;
import de.lmu.ifi.dbs.elki.logging.Logging;
@@ -50,25 +49,15 @@ public class MultipleFilesOutput implements StreamFactory {
private static final String GZIP_EXTENSION = ".gz";
/**
- * Default stream to write to when no name is supplied.
- */
- private PrintStream defaultStream = null;
-
- /**
* Base file name.
*/
private File basename;
/**
- * HashMap of open print streams.
- */
- private HashMap<String, PrintStream> map = new HashMap<String, PrintStream>();
-
- /**
* Control gzip compression of output.
*/
private boolean usegzip = false;
-
+
/**
* Logger for debugging.
*/
@@ -95,20 +84,6 @@ public class MultipleFilesOutput implements StreamFactory {
}
/**
- * Retrieve/open the default output stream.
- *
- * @return default output stream
- * @throws IOException
- */
- private PrintStream getDefaultStream() throws IOException {
- if(defaultStream != null) {
- return defaultStream;
- }
- defaultStream = newStream("default");
- return defaultStream;
- }
-
- /**
* Open a new stream of the given name
*
* @param name file name (which will be appended to the base name)
@@ -117,14 +92,10 @@ public class MultipleFilesOutput implements StreamFactory {
*/
private PrintStream newStream(String name) throws IOException {
if (LOG.isDebuggingFiner()) {
- LOG.debugFiner("Requested stream: "+name);
- }
- PrintStream res = map.get(name);
- if(res != null) {
- return res;
+ LOG.debugFiner("Requested stream: " + name);
}
// Ensure the directory exists:
- if(!basename.exists()) {
+ if (!basename.exists()) {
basename.mkdirs();
}
String fn = basename.getAbsolutePath() + File.separator + name + EXTENSION;
@@ -137,12 +108,11 @@ public class MultipleFilesOutput implements StreamFactory {
// wrap into gzip stream.
os = new GZIPOutputStream(os);
}
- res = new PrintStream(os);
+ PrintStream res = new PrintStream(os);
if (LOG.isDebuggingFiner()) {
- LOG.debugFiner("Opened new output stream:"+fn);
+ LOG.debugFiner("Opened new output stream:" + fn);
}
// cache.
- map.put(name, res);
return res;
}
@@ -151,12 +121,14 @@ public class MultipleFilesOutput implements StreamFactory {
*/
@Override
public PrintStream openStream(String filename) throws IOException {
- if(filename == null) {
- return getDefaultStream();
- }
return newStream(filename);
}
+ @Override
+ public void closeStream(PrintStream stream) {
+ stream.close();
+ }
+
/**
* Get GZIP compression flag.
*
@@ -174,15 +146,4 @@ public class MultipleFilesOutput implements StreamFactory {
protected void setGzipCompression(boolean usegzip) {
this.usegzip = usegzip;
}
-
- /**
- * Close (and forget) all output streams.
- */
- @Override
- public synchronized void closeAllStreams() {
- for (PrintStream s : map.values()) {
- s.close();
- }
- map.clear();
- }
}
diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/SingleStreamOutput.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/SingleStreamOutput.java
index 46472f52..eb2b6170 100644
--- a/src/de/lmu/ifi/dbs/elki/result/textwriter/SingleStreamOutput.java
+++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/SingleStreamOutput.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.textwriter;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -35,32 +35,32 @@ import java.util.zip.GZIPOutputStream;
* Class to output all result data to a single stream (e.g. Stdout, single file)
*
* @author Erich Schubert
- *
*/
public class SingleStreamOutput implements StreamFactory {
/**
* Output stream
*/
private PrintStream stream;
-
+
/**
* Constructor using stdout.
+ *
* @throws IOException on IO error
*/
- public SingleStreamOutput() throws IOException {
+ public SingleStreamOutput() throws IOException {
this(FileDescriptor.out);
}
-
+
/**
* Constructor using stdout
*
* @param gzip Use gzip compression
* @throws IOException on IO error
*/
- public SingleStreamOutput(boolean gzip) throws IOException {
+ public SingleStreamOutput(boolean gzip) throws IOException {
this(FileDescriptor.out, gzip);
}
-
+
/**
* Constructor with given file name.
*
@@ -91,7 +91,7 @@ public class SingleStreamOutput implements StreamFactory {
public SingleStreamOutput(FileDescriptor out) throws IOException {
this(new FileOutputStream(out));
}
-
+
/**
* Constructor with given FileDescriptor
*
@@ -102,7 +102,7 @@ public class SingleStreamOutput implements StreamFactory {
public SingleStreamOutput(FileDescriptor out, boolean gzip) throws IOException {
this(new FileOutputStream(out), gzip);
}
-
+
/**
* Constructor with given FileOutputStream.
*
@@ -132,18 +132,16 @@ public class SingleStreamOutput implements StreamFactory {
/**
* Return the objects shared print stream.
*
- * @param filename ignored filename for SingleStreamOutput, as the name suggests
+ * @param filename ignored filename for SingleStreamOutput, as the name
+ * suggests
*/
@Override
public PrintStream openStream(String filename) {
return stream;
}
- /**
- * Close output stream.
- */
@Override
- public void closeAllStreams() {
- stream.close();
+ public void closeStream(PrintStream stream) {
+ // Do NOT close. We may still need it.
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/StreamFactory.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/StreamFactory.java
index 0f27b354..431fdc2c 100644
--- a/src/de/lmu/ifi/dbs/elki/result/textwriter/StreamFactory.java
+++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/StreamFactory.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.textwriter;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,22 +29,27 @@ import java.io.PrintStream;
/**
* Interface for output handling (single file, multiple files, ...)
*
+ * Note: these classes need to be rewritten. Contributions welcome!
+ *
* @author Erich Schubert
*/
public interface StreamFactory {
/**
- * Retrieve a print stream for output using the given label.
- * Note that multiple labels MAY result in the same PrintStream, so you
- * should be printing to only one stream at a time to avoid mixing outputs.
+ * Retrieve a print stream for output using the given label. Note that
+ * multiple labels MAY result in the same PrintStream, so you should be
+ * printing to only one stream at a time to avoid mixing outputs.
*
* @param label Output label.
* @return stream object for the given label
* @throws IOException on IO error
*/
public PrintStream openStream(String label) throws IOException;
-
+
/**
- * Close (and forget) all streams the factory has opened.
+ * Close the given output stream (Note: when writing to a single stream
+ * output, it will actually not be closed!)
+ *
+ * @param stream Stream to close
*/
- public void closeAllStreams();
-} \ No newline at end of file
+ public void closeStream(PrintStream stream);
+}
diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriteable.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriteable.java
index a8de4c46..5b56cee6 100644
--- a/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriteable.java
+++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriteable.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.textwriter;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriter.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriter.java
index e5b05883..0cbc81f2 100644
--- a/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriter.java
+++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.textwriter;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -33,6 +33,7 @@ import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.regex.Pattern;
import de.lmu.ifi.dbs.elki.data.Cluster;
import de.lmu.ifi.dbs.elki.data.Clustering;
@@ -62,13 +63,13 @@ import de.lmu.ifi.dbs.elki.result.textwriter.naming.NamingScheme;
import de.lmu.ifi.dbs.elki.result.textwriter.naming.SimpleEnumeratingScheme;
import de.lmu.ifi.dbs.elki.result.textwriter.writers.TextWriterDoubleDoublePair;
import de.lmu.ifi.dbs.elki.result.textwriter.writers.TextWriterObjectArray;
-import de.lmu.ifi.dbs.elki.result.textwriter.writers.TextWriterObjectComment;
import de.lmu.ifi.dbs.elki.result.textwriter.writers.TextWriterObjectInline;
import de.lmu.ifi.dbs.elki.result.textwriter.writers.TextWriterPair;
import de.lmu.ifi.dbs.elki.result.textwriter.writers.TextWriterTextWriteable;
import de.lmu.ifi.dbs.elki.result.textwriter.writers.TextWriterTriple;
import de.lmu.ifi.dbs.elki.result.textwriter.writers.TextWriterVector;
import de.lmu.ifi.dbs.elki.utilities.HandlerList;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.Hierarchy;
import de.lmu.ifi.dbs.elki.utilities.exceptions.UnableToComplyException;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.SerializedParameterization;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ClassParameter;
@@ -78,7 +79,9 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
import de.lmu.ifi.dbs.elki.utilities.pairs.Triple;
/**
- * Class to write a result to human-readable text output
+ * Class to write a result to human-readable text output.
+ *
+ * Note: these classes need to be rewritten. Contributions welcome!
*
* @author Erich Schubert
*
@@ -96,14 +99,13 @@ public class TextWriter {
/**
* Hash map for supported classes in writer.
*/
- public static final HandlerList<TextWriterWriterInterface<?>> writers = new HandlerList<TextWriterWriterInterface<?>>();
+ public static final HandlerList<TextWriterWriterInterface<?>> writers = new HandlerList<>();
/**
* Add some default handlers
*/
static {
TextWriterObjectInline trivialwriter = new TextWriterObjectInline();
- writers.insertHandler(Object.class, new TextWriterObjectComment());
writers.insertHandler(Pair.class, new TextWriterPair());
writers.insertHandler(DoubleDoublePair.class, new TextWriterDoubleDoublePair());
writers.insertHandler(Triple.class, new TextWriterTriple());
@@ -129,7 +131,7 @@ public class TextWriter {
/**
* For producing unique filenames.
*/
- protected Map<String, Object> filenames = new HashMap<String, Object>();
+ protected Map<String, Object> filenames = new HashMap<>();
/**
* Try to find a unique file name.
@@ -139,20 +141,19 @@ public class TextWriter {
* @return unique filename
*/
protected String getFilename(Object result, String filenamepre) {
- if(filenamepre == null || filenamepre.length() == 0) {
+ if (filenamepre == null || filenamepre.length() == 0) {
filenamepre = "result";
}
int i = 0;
- while(true) {
+ while (true) {
String filename;
- if(i > 0) {
+ if (i > 0) {
filename = filenamepre + "-" + i;
- }
- else {
+ } else {
filename = filenamepre;
}
Object existing = filenames.get(filename);
- if(existing == null || existing == result) {
+ if (existing == null || existing == result) {
filenames.put(filename, result);
return filename;
}
@@ -161,102 +162,54 @@ public class TextWriter {
}
/**
- * Writes a header providing information concerning the underlying database
- * and the specified parameter-settings.
- *
- * @param out the print stream where to write
- * @param sr the settings to be written into the header
- */
- protected void printSettings(TextWriterStream out, List<SettingsResult> sr) {
- out.commentPrintSeparator();
- out.commentPrintLn("Settings:");
-
- if(sr != null) {
- for(SettingsResult settings : sr) {
- Object last = null;
- for(Pair<Object, Parameter<?>> setting : settings.getSettings()) {
- if(setting.first != last && setting.first != null) {
- if(last != null) {
- out.commentPrintLn("");
- }
- String name;
- try {
- if(setting.first instanceof Class) {
- name = ((Class<?>) setting.first).getName();
- }
- else {
- name = setting.first.getClass().getName();
- }
- if(ClassParameter.class.isInstance(setting.first)) {
- name = ((ClassParameter<?>) setting.first).getValue().getName();
- }
- }
- catch(NullPointerException e) {
- name = "[null]";
- }
- out.commentPrintLn(name);
- last = setting.first;
- }
- String name = setting.second.getOptionID().getName();
- String value = "[unset]";
- try {
- if(setting.second.isDefined()) {
- value = setting.second.getValueAsString();
- }
- }
- catch(NullPointerException e) {
- value = "[null]";
- }
- out.commentPrintLn(SerializedParameterization.OPTION_PREFIX + name + " " + value);
- }
- }
- }
-
- out.commentPrintSeparator();
- out.flush();
- }
-
- /**
* Stream output.
*
* @param db Database object
* @param r Result class
* @param streamOpener output stream manager
+ * @param filter Filter pattern
* @throws UnableToComplyException when no usable results were found
* @throws IOException on IO error
*/
- public void output(Database db, Result r, StreamFactory streamOpener) throws UnableToComplyException, IOException {
- List<Relation<?>> ra = new LinkedList<Relation<?>>();
- List<OrderingResult> ro = new LinkedList<OrderingResult>();
- List<Clustering<?>> rc = new LinkedList<Clustering<?>>();
- List<IterableResult<?>> ri = new LinkedList<IterableResult<?>>();
- List<SettingsResult> rs = new LinkedList<SettingsResult>();
- List<Result> otherres = new LinkedList<Result>();
+ @SuppressWarnings("unchecked")
+ public void output(Database db, Result r, StreamFactory streamOpener, Pattern filter) throws UnableToComplyException, IOException {
+ List<Relation<?>> ra = new LinkedList<>();
+ List<OrderingResult> ro = new LinkedList<>();
+ List<Clustering<?>> rc = new LinkedList<>();
+ List<IterableResult<?>> ri = new LinkedList<>();
+ List<SettingsResult> rs = new LinkedList<>();
+ List<Result> otherres = new LinkedList<>();
- // collect other results
+ // Split result objects in different known types:
{
List<Result> results = ResultUtil.filterResults(r, Result.class);
- for(Result res : results) {
- if(res instanceof Database) {
+ for (Result res : results) {
+ if (filter != null) {
+ final String nam = res.getShortName();
+ if (nam == null || !filter.matcher(nam).find()) {
+ continue;
+ }
+ }
+ if (res instanceof Database) {
continue;
}
- if(res instanceof Relation) {
+ if (res instanceof Relation) {
ra.add((Relation<?>) res);
continue;
}
- if(res instanceof OrderingResult) {
+ if (res instanceof OrderingResult) {
ro.add((OrderingResult) res);
continue;
}
- if(res instanceof Clustering) {
+ if (res instanceof Clustering) {
rc.add((Clustering<?>) res);
continue;
}
- if(res instanceof IterableResult) {
+ if (res instanceof IterableResult) {
ri.add((IterableResult<?>) res);
continue;
}
- if(res instanceof SettingsResult) {
+ if (res instanceof SettingsResult) {
rs.add((SettingsResult) res);
continue;
}
@@ -264,36 +217,38 @@ public class TextWriter {
}
}
- for(IterableResult<?> rii : ri) {
- writeIterableResult(streamOpener, rii, rs);
+ writeSettingsResult(streamOpener, rs);
+
+ for (IterableResult<?> rii : ri) {
+ writeIterableResult(streamOpener, rii);
}
- for(Clustering<?> c : rc) {
+ for (Clustering<?> c : rc) {
NamingScheme naming = new SimpleEnumeratingScheme(c);
- for(Cluster<?> clus : c.getAllClusters()) {
- writeClusterResult(db, streamOpener, clus, ra, naming, rs);
+ for (Cluster<?> clus : c.getAllClusters()) {
+ writeClusterResult(db, streamOpener, (Clustering<Model>) c, (Cluster<Model>) clus, ra, naming);
}
}
- for(OrderingResult ror : ro) {
- writeOrderingResult(db, streamOpener, ror, ra, rs);
+ for (OrderingResult ror : ro) {
+ writeOrderingResult(db, streamOpener, ror, ra);
}
- for(Result otherr : otherres) {
- writeOtherResult(streamOpener, otherr, rs);
+ for (Result otherr : otherres) {
+ writeOtherResult(streamOpener, otherr);
}
}
private void printObject(TextWriterStream out, Database db, final DBIDRef objID, List<Relation<?>> ra) throws UnableToComplyException, IOException {
SingleObjectBundle bundle = db.getBundle(objID);
// Write database element itself.
- for(int i = 0; i < bundle.metaLength(); i++) {
+ for (int i = 0; i < bundle.metaLength(); i++) {
Object obj = bundle.data(i);
- if(obj != null) {
+ if (obj != null) {
TextWriterWriterInterface<?> owriter = out.getWriterFor(obj);
- if(owriter == null) {
+ if (owriter == null) {
throw new UnableToComplyException("No handler for database object itself: " + obj.getClass().getSimpleName());
}
String lbl = null;
// TODO: ugly compatibility hack...
- if(TypeUtil.DBID.isAssignableFromType(bundle.meta(i))) {
+ if (TypeUtil.DBID.isAssignableFromType(bundle.meta(i))) {
lbl = "ID";
}
owriter.writeObject(out, lbl, obj);
@@ -302,19 +257,19 @@ public class TextWriter {
Collection<Relation<?>> dbrels = db.getRelations();
// print the annotations
- if(ra != null) {
- for(Relation<?> a : ra) {
+ if (ra != null) {
+ for (Relation<?> a : ra) {
// Avoid duplicated output.
- if(dbrels.contains(a)) {
+ if (dbrels.contains(a)) {
continue;
}
String label = a.getShortName();
Object value = a.get(objID);
- if(value == null) {
+ if (value == null) {
continue;
}
TextWriterWriterInterface<?> writer = out.getWriterFor(value);
- if(writer == null) {
+ if (writer == null) {
// Ignore
continue;
}
@@ -322,56 +277,41 @@ public class TextWriter {
}
}
out.flush();
- out.flush();
- }
-
- private void writeOtherResult(StreamFactory streamOpener, Result r, List<SettingsResult> rs) throws UnableToComplyException, IOException {
- PrintStream outStream = streamOpener.openStream(getFilename(r, r.getShortName()));
- TextWriterStream out = new TextWriterStream(outStream, writers);
- TextWriterWriterInterface<?> owriter = out.getWriterFor(r);
- if(owriter == null) {
- throw new UnableToComplyException("No handler for result class: " + r.getClass().getSimpleName());
- }
- // Write settings preamble
- printSettings(out, rs);
- // Write data
- owriter.writeObject(out, null, r);
- out.flush();
}
- private void writeClusterResult(Database db, StreamFactory streamOpener, Cluster<?> clus, List<Relation<?>> ra, NamingScheme naming, List<SettingsResult> sr) throws FileNotFoundException, UnableToComplyException, IOException {
+ private void writeClusterResult(Database db, StreamFactory streamOpener, Clustering<Model> clustering, Cluster<Model> clus, List<Relation<?>> ra, NamingScheme naming) throws FileNotFoundException, UnableToComplyException, IOException {
String filename = null;
- if(naming != null) {
+ if (naming != null) {
filename = filenameFromLabel(naming.getNameFor(clus));
- }
- else {
+ } else {
filename = "cluster";
}
PrintStream outStream = streamOpener.openStream(getFilename(clus, filename));
TextWriterStream out = new TextWriterStream(outStream, writers);
- printSettings(out, sr);
// Write cluster information
out.commentPrintLn("Cluster: " + naming.getNameFor(clus));
Model model = clus.getModel();
- if(model != ClusterModel.CLUSTER && model != null) {
- TextWriterWriterInterface<?> mwri = writers.getHandler(model);
- mwri.writeObject(out, null, model);
+ if (model != ClusterModel.CLUSTER && model != null) {
+ TextWriterWriterInterface<?> mwri = out.getWriterFor(model);
+ if (mwri != null) {
+ mwri.writeObject(out, null, model);
+ }
}
- if(clus.getParents().size() > 0) {
+ if (clustering.getClusterHierarchy().numParents(clus) > 0) {
StringBuilder buf = new StringBuilder();
buf.append("Parents:");
- for(Cluster<?> parent : clus.getParents()) {
- buf.append(" ").append(naming.getNameFor(parent));
+ for (Hierarchy.Iter<Cluster<Model>> iter = clustering.getClusterHierarchy().iterParents(clus); iter.valid(); iter.advance()) {
+ buf.append(' ').append(naming.getNameFor(iter.get()));
}
out.commentPrintLn(buf.toString());
}
- if(clus.getChildren().size() > 0) {
+ if (clustering.getClusterHierarchy().numChildren(clus) > 0) {
StringBuilder buf = new StringBuilder();
buf.append("Children:");
- for(Cluster<?> child : clus.getChildren()) {
- buf.append(" ").append(naming.getNameFor(child));
+ for (Hierarchy.Iter<Cluster<Model>> iter = clustering.getClusterHierarchy().iterChildren(clus); iter.valid(); iter.advance()) {
+ buf.append(' ').append(naming.getNameFor(iter.get()));
}
out.commentPrintLn(buf.toString());
}
@@ -382,48 +322,112 @@ public class TextWriter {
for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
printObject(out, db, iter, ra);
}
- out.commentPrintSeparator();
out.flush();
+ streamOpener.closeStream(outStream);
}
- private void writeIterableResult(StreamFactory streamOpener, IterableResult<?> ri, List<SettingsResult> sr) throws UnableToComplyException, IOException {
+ private void writeIterableResult(StreamFactory streamOpener, IterableResult<?> ri) throws UnableToComplyException, IOException {
PrintStream outStream = streamOpener.openStream(getFilename(ri, ri.getShortName()));
TextWriterStream out = new TextWriterStream(outStream, writers);
- printSettings(out, sr);
// hack to print collectionResult header information
- if(ri instanceof CollectionResult<?>) {
+ if (ri instanceof CollectionResult<?>) {
final Collection<String> hdr = ((CollectionResult<?>) ri).getHeader();
- if(hdr != null) {
- for(String header : hdr) {
+ if (hdr != null) {
+ for (String header : hdr) {
out.commentPrintLn(header);
}
out.flush();
}
}
Iterator<?> i = ri.iterator();
- while(i.hasNext()) {
+ while (i.hasNext()) {
Object o = i.next();
TextWriterWriterInterface<?> writer = out.getWriterFor(o);
- if(writer != null) {
+ if (writer != null) {
writer.writeObject(out, null, o);
}
out.flush();
}
- out.commentPrintSeparator();
out.flush();
+ streamOpener.closeStream(outStream);
}
- private void writeOrderingResult(Database db, StreamFactory streamOpener, OrderingResult or, List<Relation<?>> ra, List<SettingsResult> sr) throws IOException, UnableToComplyException {
+ private void writeOrderingResult(Database db, StreamFactory streamOpener, OrderingResult or, List<Relation<?>> ra) throws IOException, UnableToComplyException {
PrintStream outStream = streamOpener.openStream(getFilename(or, or.getShortName()));
TextWriterStream out = new TextWriterStream(outStream, writers);
- printSettings(out, sr);
for (DBIDIter i = or.iter(or.getDBIDs()).iter(); i.valid(); i.advance()) {
printObject(out, db, i, ra);
}
- out.commentPrintSeparator();
out.flush();
+ streamOpener.closeStream(outStream);
+ }
+
+ private void writeSettingsResult(StreamFactory streamOpener, List<SettingsResult> rs) throws UnableToComplyException, IOException {
+ if (rs.size() < 1) {
+ return;
+ }
+ SettingsResult r = rs.get(0);
+ PrintStream outStream = streamOpener.openStream(getFilename(r, r.getShortName()));
+ TextWriterStream out = new TextWriterStream(outStream, writers);
+ // Write settings preamble
+ out.commentPrintLn("Settings:");
+
+ if (rs != null) {
+ for (SettingsResult settings : rs) {
+ Object last = null;
+ for (Pair<Object, Parameter<?>> setting : settings.getSettings()) {
+ if (setting.first != last && setting.first != null) {
+ if (last != null) {
+ out.commentPrintLn("");
+ }
+ String name;
+ try {
+ if (setting.first instanceof Class) {
+ name = ((Class<?>) setting.first).getName();
+ } else {
+ name = setting.first.getClass().getName();
+ }
+ if (ClassParameter.class.isInstance(setting.first)) {
+ name = ((ClassParameter<?>) setting.first).getValue().getName();
+ }
+ } catch (NullPointerException e) {
+ name = "[null]";
+ }
+ out.commentPrintLn(name);
+ last = setting.first;
+ }
+ String name = setting.second.getOptionID().getName();
+ String value = "[unset]";
+ try {
+ if (setting.second.isDefined()) {
+ value = setting.second.getValueAsString();
+ }
+ } catch (NullPointerException e) {
+ value = "[null]";
+ }
+ out.commentPrintLn(SerializedParameterization.OPTION_PREFIX + name + " " + value);
+ }
+ }
+ }
+ out.flush();
+ streamOpener.closeStream(outStream);
+ }
+
+ private void writeOtherResult(StreamFactory streamOpener, Result r) throws UnableToComplyException, IOException {
+ if (writers.getHandler(r) != null) {
+ PrintStream outStream = streamOpener.openStream(getFilename(r, r.getShortName()));
+ TextWriterStream out = new TextWriterStream(outStream, writers);
+ TextWriterWriterInterface<?> owriter = out.getWriterFor(r);
+ if (owriter == null) {
+ throw new UnableToComplyException("No handler for result class: " + r.getClass().getSimpleName());
+ }
+ // Write data
+ owriter.writeObject(out, null, r);
+ out.flush();
+ streamOpener.closeStream(outStream);
+ }
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriterStream.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriterStream.java
index 7c905fb3..542be099 100644
--- a/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriterStream.java
+++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriterStream.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.textwriter;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,14 +25,16 @@ package de.lmu.ifi.dbs.elki.result.textwriter;
import java.io.PrintStream;
+import de.lmu.ifi.dbs.elki.result.textwriter.writers.TextWriterObjectComment;
import de.lmu.ifi.dbs.elki.utilities.HandlerList;
/**
* Representation of an output stream to a text file.
*
* @author Erich Schubert
- *
- * @apiviz.uses de.lmu.ifi.dbs.elki.result.textwriter.StreamFactory oneway - - wraps
+ *
+ * @apiviz.uses de.lmu.ifi.dbs.elki.result.textwriter.StreamFactory oneway - -
+ * wraps
*/
public class TextWriterStream {
/**
@@ -66,8 +68,8 @@ public class TextWriterStream {
public static final String QUOTE = "# ";
/**
- * Comment separator line.
- * Since this will be printed without {@link #QUOTE} infront, it should be quoted string itself.
+ * Comment separator line. Since this will be printed without {@link #QUOTE}
+ * infront, it should be quoted string itself.
*/
public static final String COMMENTSEP = "###############################################################";
@@ -80,12 +82,17 @@ public class TextWriterStream {
* Marker used in text serialization (and re-parsing)
*/
public static final String SER_MARKER = "Serialization class:";
-
+
/**
* Force incomments flag
*/
// TODO: solve this more gracefully
- private boolean forceincomments = false;
+ private boolean forceincomments = false;
+
+ /**
+ * Fallback writer, using toString.
+ */
+ private TextWriterObjectComment fallbackwriter = new TextWriterObjectComment();
/**
* Constructor.
@@ -99,7 +106,7 @@ public class TextWriterStream {
inline = new StringBuilder();
comment = new StringBuilder();
}
-
+
/**
* Print an object into the comments section
*
@@ -122,22 +129,21 @@ public class TextWriterStream {
/**
* Print a newline into the comments section.
*/
- public void commentPrintLn() {
+ public void commentPrintLn() {
comment.append(NEWLINE);
}
- /**
- * Print a separator line in the comments section.
- */
+ /**
+ * Print a separator line in the comments section.
+ */
public void commentPrintSeparator() {
comment.append(COMMENTSEP + NEWLINE);
}
/**
- * Print data into the inline part of the file.
- * Data is sanitized: newlines are replaced with spaces, and text
- * containing separators is put in quotes. Quotes and escape characters
- * are escaped.
+ * Print data into the inline part of the file. Data is sanitized: newlines
+ * are replaced with spaces, and text containing separators is put in quotes.
+ * Quotes and escape characters are escaped.
*
* @param o object to print
*/
@@ -150,19 +156,19 @@ public class TextWriterStream {
inline.append(SEPARATOR);
}
// remove newlines
- String str = o.toString().replace(NEWLINE," ");
+ String str = o.toString().replace(NEWLINE, " ");
// escaping
- str = str.replace("\\","\\\\").replace("\"","\\\"");
+ str = str.replace("\\", "\\\\").replace("\"", "\\\"");
// when needed, add quotes.
if (str.contains(SEPARATOR)) {
- str = "\""+str+"\"";
+ str = "\"" + str + "\"";
}
inline.append(str);
}
/**
- * Print data into the inline part of the file WITHOUT checking for
- * separators (and thus quoting).
+ * Print data into the inline part of the file WITHOUT checking for separators
+ * (and thus quoting).
*
* @param o object to print.
*/
@@ -175,15 +181,14 @@ public class TextWriterStream {
inline.append(SEPARATOR);
}
// remove newlines
- String str = o.toString().replace(NEWLINE," ");
+ String str = o.toString().replace(NEWLINE, " ");
// escaping
- str = str.replace("\\","\\\\").replace("\"","\\\"");
+ str = str.replace("\\", "\\\\").replace("\"", "\\\"");
inline.append(str);
}
/**
- * Flush output:
- * write inline data, then write comment section. Reset streams.
+ * Flush output: write inline data, then write comment section. Reset streams.
*/
public void flush() {
if (inline.length() > 0) {
@@ -220,13 +225,26 @@ public class TextWriterStream {
* @return appropriate write, if available
*/
public TextWriterWriterInterface<?> getWriterFor(Object o) {
- return writers.getHandler(o);
+ if (o == null) {
+ return null;
+ }
+ TextWriterWriterInterface<?> writer = writers.getHandler(o);
+ if (writer == null) {
+ try {
+ if (o.getClass().getMethod("toString").getDeclaringClass() != Object.class) {
+ return fallbackwriter;
+ }
+ } catch (Exception e) {
+ return null;
+ }
+ }
+ return writer;
}
/**
- * Restore a vector undoing any normalization that was applied.
- * (This class does not support normalization, it is only provided
- * by derived classes, which will then have to use generics.)
+ * Restore a vector undoing any normalization that was applied. (This class
+ * does not support normalization, it is only provided by derived classes,
+ * which will then have to use generics.)
*
* @param <O> Object class
* @param v vector to restore
diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriterWriterInterface.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriterWriterInterface.java
index cfaa3373..35fa487f 100644
--- a/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriterWriterInterface.java
+++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriterWriterInterface.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.textwriter;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/naming/NamingScheme.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/naming/NamingScheme.java
index 4b2c099f..a63d3726 100644
--- a/src/de/lmu/ifi/dbs/elki/result/textwriter/naming/NamingScheme.java
+++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/naming/NamingScheme.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.textwriter.naming;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/naming/SimpleEnumeratingScheme.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/naming/SimpleEnumeratingScheme.java
index c1d0f8e5..dacb342b 100644
--- a/src/de/lmu/ifi/dbs/elki/result/textwriter/naming/SimpleEnumeratingScheme.java
+++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/naming/SimpleEnumeratingScheme.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.textwriter.naming;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -47,12 +47,12 @@ public class SimpleEnumeratingScheme implements NamingScheme {
/**
* count how often each name occurred so far.
*/
- private Map<String, Integer> namecount = new HashMap<String, Integer>();
+ private Map<String, Integer> namecount = new HashMap<>();
/**
* Assigned cluster names.
*/
- private Map<Cluster<?>, String> names = new HashMap<Cluster<?>, String>();
+ private Map<Cluster<?>, String> names = new HashMap<>();
/**
* This is the postfix added to the first cluster, which will be removed when
diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/naming/package-info.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/naming/package-info.java
index 600e731e..ab4b93d0 100644
--- a/src/de/lmu/ifi/dbs/elki/result/textwriter/naming/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/naming/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/package-info.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/package-info.java
index 872df780..60f2f534 100644
--- a/src/de/lmu/ifi/dbs/elki/result/textwriter/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/package-info.java
@@ -6,7 +6,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterDoubleDoublePair.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterDoubleDoublePair.java
index 4af9d8a4..a9975195 100644
--- a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterDoubleDoublePair.java
+++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterDoubleDoublePair.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.textwriter.writers;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterObjectArray.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterObjectArray.java
index be195648..34d5b419 100644
--- a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterObjectArray.java
+++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterObjectArray.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.textwriter.writers;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterObjectComment.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterObjectComment.java
index d4da18f5..d3de4ff3 100644
--- a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterObjectComment.java
+++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterObjectComment.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.textwriter.writers;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterObjectInline.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterObjectInline.java
index a621ab4b..28c549d7 100644
--- a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterObjectInline.java
+++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterObjectInline.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.textwriter.writers;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterPair.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterPair.java
index 3c1440bc..1705f5cc 100644
--- a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterPair.java
+++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterPair.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.textwriter.writers;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterTextWriteable.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterTextWriteable.java
index 87a3661b..04e56ae5 100644
--- a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterTextWriteable.java
+++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterTextWriteable.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.textwriter.writers;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -32,7 +32,7 @@ import de.lmu.ifi.dbs.elki.result.textwriter.TextWriterWriterInterface;
*
* @author Erich Schubert
*
- * @apiviz.uses TextWriteable
+ * @apiviz.has TextWriteable
*/
public class TextWriterTextWriteable extends TextWriterWriterInterface<TextWriteable> {
/**
diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterTriple.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterTriple.java
index 55dd7106..1efde342 100644
--- a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterTriple.java
+++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterTriple.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.textwriter.writers;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterVector.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterVector.java
index 1452c432..46197e21 100644
--- a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterVector.java
+++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterVector.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.result.textwriter.writers;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/package-info.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/package-info.java
index c83dd767..da527a67 100644
--- a/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/package-info.java
@@ -6,7 +6,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/Alias.java b/src/de/lmu/ifi/dbs/elki/utilities/Alias.java
new file mode 100644
index 00000000..839fc406
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/Alias.java
@@ -0,0 +1,47 @@
+package de.lmu.ifi.dbs.elki.utilities;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This interface defines alias names for classes.
+ *
+ * @author Erich Schubert
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.TYPE })
+public @interface Alias {
+ /**
+ * Alias names of the class.
+ *
+ * @return Array of alias names
+ */
+ String[] value();
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/Base64.java b/src/de/lmu/ifi/dbs/elki/utilities/Base64.java
index bcd4c8ff..c6a22f20 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/Base64.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/Base64.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.utilities;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/BitsUtil.java b/src/de/lmu/ifi/dbs/elki/utilities/BitsUtil.java
index ed00dbab..d1e0587c 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/BitsUtil.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/BitsUtil.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -969,19 +969,19 @@ public final class BitsUtil {
* @return Position of first set bit, 64 if no set bit was found.
*/
public static int numberOfLeadingZeros(long v) {
- return Long.SIZE - magnitude(v);
+ return Long.numberOfLeadingZeros(v);
}
/**
- * Find the number of leading zeros; 64 if all zero
+ * Find the number of leading zeros; 32 if all zero
*
- * Note: this the same as {@link Long#numberOfLeadingZeros}.
+ * Note: this the same as {@link Integer#numberOfLeadingZeros}.
*
* @param v Bitset
- * @return Position of first set bit, 64 if no set bit was found.
+ * @return Position of first set bit, 32 if no set bit was found.
*/
public static int numberOfLeadingZeros(int v) {
- return Integer.SIZE - magnitude(v);
+ return Integer.numberOfLeadingZeros(v);
}
/**
@@ -1114,34 +1114,7 @@ public final class BitsUtil {
* @return position of highest bit set, or 0.
*/
public static int magnitude(long v) {
- int log = 0, t;
- if ((v & 0xffffffff00000000L) != 0) {
- t = (int) (v >>>= 32);
- log = 32;
- } else {
- t = (int) v;
- }
- if ((t & 0xffff0000) != 0) {
- t >>>= 16;
- log += 16;
- }
- if (t >= 256) {
- t >>>= 8;
- log += 8;
- }
- if (t >= 16) {
- t >>>= 4;
- log += 4;
- }
- if (t >= 4) {
- t >>>= 2;
- log += 2;
- }
- if (t >= 2) {
- t >>>= 1;
- log += 1;
- }
- return log + t;
+ return Long.SIZE - Long.numberOfLeadingZeros(v);
}
/**
@@ -1151,28 +1124,7 @@ public final class BitsUtil {
* @return position of highest bit set, or 0.
*/
public static int magnitude(int v) {
- int log = 0;
- if ((v & 0xffff0000) != 0) {
- v >>>= 16;
- log = 16;
- }
- if (v >= 256) {
- v >>>= 8;
- log += 8;
- }
- if (v >= 16) {
- v >>>= 4;
- log += 4;
- }
- if (v >= 4) {
- v >>>= 2;
- log += 2;
- }
- if (v >= 2) {
- v >>>= 1;
- log += 1;
- }
- return log + v;
+ return Integer.SIZE - Integer.numberOfLeadingZeros(v);
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/ClassGenericsUtil.java b/src/de/lmu/ifi/dbs/elki/utilities/ClassGenericsUtil.java
index 90b5ac62..a60bf15f 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/ClassGenericsUtil.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/ClassGenericsUtil.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -325,7 +325,7 @@ public final class ClassGenericsUtil {
public static <T> ArrayList<T>[] newArrayOfEmptyArrayList(int len) {
ArrayList[] result = new ArrayList[len];
for (int i = 0; i < len; i++) {
- result[i] = new ArrayList<T>();
+ result[i] = new ArrayList<>();
}
return result;
}
@@ -344,7 +344,7 @@ public final class ClassGenericsUtil {
public static <T> HashSet<T>[] newArrayOfEmptyHashSet(int len) {
HashSet[] result = new HashSet[len];
for (int i = 0; i < len; i++) {
- result[i] = new HashSet<T>();
+ result[i] = new HashSet<>();
}
return result;
}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/DatabaseUtil.java b/src/de/lmu/ifi/dbs/elki/utilities/DatabaseUtil.java
index 31e2431d..baa90829 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/DatabaseUtil.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/DatabaseUtil.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -58,6 +58,9 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
* @author Erich Schubert
*
* @apiviz.landmark
+ *
+ * @apiviz.has RelationObjectIterator
+ * @apiviz.has CollectionFromRelation
*/
public final class DatabaseUtil {
/**
@@ -130,7 +133,7 @@ public final class DatabaseUtil {
NumberVector.Factory<NV, ?> factory = RelationUtil.getNumberVectorFactory(relation);
NV min = factory.newNumberVector(mins);
NV max = factory.newNumberVector(maxs);
- return new Pair<NV, NV>(min, max);
+ return new Pair<>(min, max);
}
/**
@@ -261,7 +264,7 @@ public final class DatabaseUtil {
* database
*/
public static SortedSet<ClassLabel> getClassLabels(Relation<? extends ClassLabel> database) {
- SortedSet<ClassLabel> labels = new TreeSet<ClassLabel>();
+ SortedSet<ClassLabel> labels = new TreeSet<>();
for (DBIDIter it = database.iterDBIDs(); it.valid(); it.advance()) {
labels.add(database.get(it));
}
@@ -305,7 +308,7 @@ public final class DatabaseUtil {
* @return Superclass of all objects in the database
*/
public static <O> Class<?> getBaseObjectClassExpensive(Relation<O> database) {
- List<Class<?>> candidates = new ArrayList<Class<?>>();
+ List<Class<?>> candidates = new ArrayList<>();
DBIDIter iditer = database.iterDBIDs();
// empty database?!
if (!iditer.valid()) {
@@ -471,7 +474,7 @@ public final class DatabaseUtil {
@Override
public Iterator<O> iterator() {
- return new DatabaseUtil.RelationObjectIterator<O>(db);
+ return new DatabaseUtil.RelationObjectIterator<>(db);
}
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/ELKIServiceLoader.java b/src/de/lmu/ifi/dbs/elki/utilities/ELKIServiceLoader.java
index 129c6458..d42b2834 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/ELKIServiceLoader.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/ELKIServiceLoader.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -112,20 +112,19 @@ public class ELKIServiceLoader implements Iterator<Class<?>> {
try {
String fullName = PREFIX + parent.getName();
configfiles = cl.getResources(fullName);
- }
- catch(IOException x) {
+ } catch (IOException x) {
throw new AbortException("Could not load service configuration files.", x);
}
}
@Override
public boolean hasNext() {
- if(nextclass != null) {
+ if (nextclass != null) {
return true;
}
// Find next iterator
- while((curiter == null) || !curiter.hasNext()) {
- if(!configfiles.hasMoreElements()) {
+ while ((curiter == null) || !curiter.hasNext()) {
+ if (!configfiles.hasMoreElements()) {
return false;
}
curiter = parseFile(configfiles.nextElement());
@@ -135,58 +134,55 @@ public class ELKIServiceLoader implements Iterator<Class<?>> {
}
private Iterator<Class<?>> parseFile(URL nextElement) {
- ArrayList<Class<?>> classes = new ArrayList<Class<?>>();
+ ArrayList<Class<?>> classes = new ArrayList<>();
try {
BufferedReader r = new BufferedReader(new InputStreamReader(nextElement.openStream(), "utf-8"));
- while(parseLine(r.readLine(), classes, nextElement)) {
+ while (parseLine(r.readLine(), classes, nextElement)) {
// Continue
}
- }
- catch(IOException x) {
+ } catch (IOException x) {
throw new AbortException("Error reading configuration file", x);
}
return classes.iterator();
}
private boolean parseLine(String line, ArrayList<Class<?>> classes, URL nextElement) {
- if(line == null) {
+ if (line == null) {
return false;
}
// Ignore comments, trim whitespace
{
int begin = 0;
int end = line.indexOf(COMMENT_CHAR);
- if(end < 0) {
+ if (end < 0) {
end = line.length();
}
- while(begin < end && line.charAt(begin) == ' ') {
+ while (begin < end && line.charAt(begin) == ' ') {
begin++;
}
- while(end - 1 > begin && line.charAt(end - 1) == ' ') {
+ while (end - 1 > begin && line.charAt(end - 1) == ' ') {
end--;
}
- if(begin > 0 || end < line.length()) {
+ if (begin > 0 || end < line.length()) {
line = line.substring(begin, end);
}
}
- if(line.length() <= 0) {
+ if (line.length() <= 0) {
return true; // Empty/comment lines are okay, continue
}
// Try to load the class
try {
Class<?> cls = cl.loadClass(line);
// Should not happen. Check anyway.
- if(cls == null) {
+ if (cls == null) {
return true;
}
- if(parent.isAssignableFrom(cls)) {
+ if (parent.isAssignableFrom(cls)) {
classes.add(cls);
- }
- else {
+ } else {
LOG.warning("Class " + line + " does not implement " + parent + " but listed in service file " + nextElement);
}
- }
- catch(ClassNotFoundException e) {
+ } catch (ClassNotFoundException e) {
LOG.warning("Class not found: " + line + "; listed in service file " + nextElement, e);
}
return true;
@@ -203,4 +199,4 @@ public class ELKIServiceLoader implements Iterator<Class<?>> {
public void remove() {
throw new UnsupportedOperationException();
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/FileUtil.java b/src/de/lmu/ifi/dbs/elki/utilities/FileUtil.java
index ef01e084..5c3c78b5 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/FileUtil.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/FileUtil.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -39,7 +39,7 @@ import java.util.zip.GZIPInputStream;
public final class FileUtil {
/**
* Fake Constructor. Use static methods.
- *
+ *
*/
private FileUtil() {
// Do not instantiate.
@@ -68,19 +68,19 @@ public final class FileUtil {
* <code>null</code>
*/
public static String getFilenameExtension(String name) {
- if(name == null) {
+ if (name == null) {
return null;
}
int index = name.lastIndexOf('.');
- if(index >= name.length() - 1) {
+ if (index >= name.length() - 1) {
return null;
}
return name.substring(name.lastIndexOf('.') + 1).toLowerCase();
}
/**
- * Try to open a file, first trying the file system,
- * then falling back to the classpath.
+ * Try to open a file, first trying the file system, then falling back to the
+ * classpath.
*
* @param filename File name in system notation
* @return Input stream
@@ -89,8 +89,7 @@ public final class FileUtil {
public static InputStream openSystemFile(String filename) throws FileNotFoundException {
try {
return new FileInputStream(filename);
- }
- catch(FileNotFoundException e) {
+ } catch (FileNotFoundException e) {
// try with classloader
String resname = filename.replace(File.separatorChar, '/');
InputStream result = ClassLoader.getSystemResourceAsStream(resname);
@@ -116,7 +115,7 @@ public final class FileUtil {
PushbackInputStream pb = new PushbackInputStream(in, 16);
in = pb;
// read a magic from the file header
- byte[] magic = {0, 0};
+ byte[] magic = { 0, 0 };
pb.read(magic);
pb.unread(magic);
if (magic[0] == 31 && magic[1] == -117) {
@@ -145,55 +144,73 @@ public final class FileUtil {
public static File locateFile(String name, String basedir) {
// Try exact match first.
File f = new File(name);
- if(f.exists()) {
+ if (f.exists()) {
return f;
}
// Try with base directory
- if(basedir != null) {
+ if (basedir != null) {
f = new File(basedir, name);
// logger.warning("Trying: "+f.getAbsolutePath());
- if(f.exists()) {
+ if (f.exists()) {
return f;
}
}
// try stripping whitespace
{
String name2 = name.trim();
- if(!name.equals(name2)) {
+ if (!name.equals(name2)) {
// logger.warning("Trying without whitespace.");
f = locateFile(name2, basedir);
- if(f != null) {
+ if (f != null) {
return f;
}
}
}
// try substituting path separators
{
- String name2 = name.replace('/',File.separatorChar);
+ String name2 = name.replace('/', File.separatorChar);
if (!name.equals(name2)) {
// logger.warning("Trying with replaced separators.");
f = locateFile(name2, basedir);
- if(f != null) {
+ if (f != null) {
return f;
}
}
- name2 = name.replace('\\',File.separatorChar);
+ name2 = name.replace('\\', File.separatorChar);
if (!name.equals(name2)) {
// logger.warning("Trying with replaced separators.");
f = locateFile(name2, basedir);
- if(f != null) {
+ if (f != null) {
return f;
}
}
}
// try stripping extra characters, such as quotes.
- if(name.length() > 2 && name.charAt(0) == '"' && name.charAt(name.length() - 1) == '"') {
+ if (name.length() > 2 && name.charAt(0) == '"' && name.charAt(name.length() - 1) == '"') {
// logger.warning("Trying without quotes.");
f = locateFile(name.substring(1, name.length() - 1), basedir);
- if(f != null) {
+ if (f != null) {
return f;
}
}
return null;
}
+
+ /**
+ * Load an input stream (e.g. a Java resource) into a String buffer. The
+ * stream is closed afterwards.
+ *
+ * @param is Input stream
+ * @return String with file/resource contents.
+ * @throws IOException on IO errors
+ */
+ public static String slurp(InputStream is) throws IOException {
+ StringBuilder buf = new StringBuilder();
+ final byte[] b = new byte[4096];
+ for (int n; (n = is.read(b)) != -1;) {
+ buf.append(new String(b, 0, n));
+ }
+ is.close();
+ return buf.toString();
+ }
}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/FormatUtil.java b/src/de/lmu/ifi/dbs/elki/utilities/FormatUtil.java
index e4431fd5..08b7bd0d 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/FormatUtil.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/FormatUtil.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -72,7 +72,7 @@ public final class FormatUtil {
static {
NF.setMinimumFractionDigits(0);
- NF.setMaximumFractionDigits(10);
+ NF.setMaximumFractionDigits(8);
NF.setGroupingUsed(false);
NF0.setMinimumFractionDigits(0);
NF0.setMaximumFractionDigits(0);
@@ -721,7 +721,7 @@ public final class FormatUtil {
* @return String representation of this Matrix
*/
public static String format(Matrix m) {
- return format(m, FormatUtil.NF8);
+ return format(m, FormatUtil.NF);
}
/**
@@ -741,7 +741,7 @@ public final class FormatUtil {
* @return String representation of this Vector
*/
public static String format(Vector m) {
- return format(m, FormatUtil.NF8);
+ return format(m, FormatUtil.NF);
}
/**
@@ -871,7 +871,7 @@ public final class FormatUtil {
* @return string fragments
*/
public static List<String> splitAtLastBlank(String s, int width) {
- List<String> chunks = new ArrayList<String>();
+ List<String> chunks = new ArrayList<>();
String tmp = s;
while (tmp.length() > 0) {
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/HandlerList.java b/src/de/lmu/ifi/dbs/elki/utilities/HandlerList.java
index 8b5fcaca..fa17e04f 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/HandlerList.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/HandlerList.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -42,7 +42,7 @@ public final class HandlerList<H> {
* List with registered Handlers. The list is kept in backwards order, that is
* the later entrys take precedence.
*/
- private ArrayList<Pair<Class<?>, H>> handlers = new ArrayList<Pair<Class<?>, H>>();
+ private ArrayList<Pair<Class<?>, H>> handlers = new ArrayList<>();
/**
* Insert a handler to the beginning of the stack.
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/InspectionUtil.java b/src/de/lmu/ifi/dbs/elki/utilities/InspectionUtil.java
index aedc4e7c..0d147420 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/InspectionUtil.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/InspectionUtil.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,6 +28,7 @@ import gnu.trove.set.hash.THashSet;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Modifier;
+import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
@@ -36,12 +37,8 @@ import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.WeakHashMap;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
import de.lmu.ifi.dbs.elki.logging.Logging;
-import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ClassParameter;
import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
/**
@@ -58,6 +55,11 @@ public class InspectionUtil {
private static final Logging LOG = Logging.getLogger(InspectionUtil.class);
/**
+ * Class loader
+ */
+ private static final ClassLoader CLASSLOADER = ClassLoader.getSystemClassLoader();
+
+ /**
* Default package ignores.
*/
private static final String[] DEFAULT_IGNORES = {
@@ -77,6 +79,8 @@ public class InspectionUtil {
"spin.", "osxadapter.", "antlr.", "ca.odell.", "com.jgoodies.", "com.michaelbaranov.", "com.mysql.", "gnu.dtools.", "net.sf.ext.", "net.sf.jabref.", "org.antlr.", "org.gjt.", "org.java.plugin.", "org.jempbox.", "org.pdfbox.", "wsi.ra.",
// GNU trove
"gnu.trove.",
+ // Java OpenGL
+ "jogamp.", "com.jogamp.", "javax.media.", "jogl.util."
//
};
@@ -86,12 +90,17 @@ public class InspectionUtil {
*/
public static final boolean NONSTATIC_CLASSPATH;
+ /**
+ * Factory class postfix.
+ */
+ public static final String FACTORY_POSTFIX = "$Factory";
+
// Check for non-jar entries in classpath.
static {
String[] classpath = System.getProperty("java.class.path").split(System.getProperty("path.separator"));
boolean hasnonstatic = false;
- for(String path : classpath) {
- if(!path.endsWith(".jar")) {
+ for (String path : classpath) {
+ if (!path.endsWith(".jar")) {
hasnonstatic = true;
}
}
@@ -101,7 +110,7 @@ public class InspectionUtil {
/**
* Weak hash map for class lookups
*/
- private static WeakHashMap<Class<?>, List<Class<?>>> CLASS_CACHE = new WeakHashMap<Class<?>, List<Class<?>>>();
+ private static WeakHashMap<Class<?>, List<Class<?>>> CLASS_CACHE = new WeakHashMap<>();
/**
* (Non-weak) cache for all "frequently scanned" classes.
@@ -116,11 +125,11 @@ public class InspectionUtil {
* @return Found implementations
*/
public static List<Class<?>> cachedFindAllImplementations(Class<?> c) {
- if(c == null) {
+ if (c == null) {
return Collections.emptyList();
}
List<Class<?>> res = CLASS_CACHE.get(c);
- if(res == null) {
+ if (res == null) {
res = findAllImplementations(c, false);
CLASS_CACHE.put(c, res);
}
@@ -137,38 +146,33 @@ public class InspectionUtil {
* @return List of found classes.
*/
public static List<Class<?>> findAllImplementations(Class<?> c, boolean everything) {
- ArrayList<Class<?>> list = new ArrayList<Class<?>>();
+ ArrayList<Class<?>> list = new ArrayList<>();
// Add all from service files (i.e. jars)
{
Iterator<Class<?>> iter = new ELKIServiceLoader(c);
- while(iter.hasNext()) {
+ while (iter.hasNext()) {
list.add(iter.next());
}
}
- if(!InspectionUtil.NONSTATIC_CLASSPATH) {
- if(list.size() == 0) {
+ if (!InspectionUtil.NONSTATIC_CLASSPATH) {
+ if (list.size() == 0) {
LOG.warning("No implementations for " + c.getName() + " were found using index files.");
}
- }
- else {
+ } else {
// Duplicate checking
- THashSet<Class<?>> dupes = new THashSet<Class<?>>(list);
- // Scan for additional ones in class path
- Iterator<Class<?>> iter;
- // If possible, reuse an existing scan result
- if(InspectionUtilFrequentlyScanned.class.isAssignableFrom(c)) {
- iter = getFrequentScan();
- }
- else {
- iter = slowScan(c).iterator();
+ THashSet<Class<?>> dupes = new THashSet<>(list);
+ // Build cache on first use:
+ if (MASTER_CACHE == null) {
+ MASTER_CACHE = slowScan();
}
- while(iter.hasNext()) {
+ Iterator<Class<?>> iter = MASTER_CACHE.iterator();
+ while (iter.hasNext()) {
Class<?> cls = iter.next();
// skip abstract / private classes.
- if(!everything && (Modifier.isInterface(cls.getModifiers()) || Modifier.isAbstract(cls.getModifiers()) || Modifier.isPrivate(cls.getModifiers()))) {
+ if (!everything && (Modifier.isInterface(cls.getModifiers()) || Modifier.isAbstract(cls.getModifiers()) || Modifier.isPrivate(cls.getModifiers()))) {
continue;
}
- if(c.isAssignableFrom(cls) && !dupes.contains(cls)) {
+ if (c.isAssignableFrom(cls) && !dupes.contains(cls)) {
list.add(cls);
dupes.add(cls);
}
@@ -178,64 +182,96 @@ public class InspectionUtil {
}
/**
- * Get (or create) the result of a scan for any "frequent scanned" class.
+ * Find an implementation of the given interface / super class, given a
+ * relative class name or alias name.
*
- * @return Scan result
+ * @param restrictionClass Restriction class
+ * @param value Class name, relative class name, or nickname.
+ * @return Class found or {@code null}
*/
- private static Iterator<Class<?>> getFrequentScan() {
- if(MASTER_CACHE == null) {
- MASTER_CACHE = slowScan(InspectionUtilFrequentlyScanned.class);
+ @SuppressWarnings("unchecked")
+ public static <C> Class<? extends C> findImplementation(Class<? super C> restrictionClass, String value) {
+ // Try exact class factory first.
+ try {
+ return (Class<? extends C>) CLASSLOADER.loadClass(value + FACTORY_POSTFIX);
+ } catch (ClassNotFoundException e) {
+ // Ignore, retry
+ }
+ try {
+ return (Class<? extends C>) CLASSLOADER.loadClass(value);
+ } catch (ClassNotFoundException e) {
+ // Ignore, retry
+ }
+ final String completedName = restrictionClass.getPackage().getName() + "." + value;
+ // Try factory for guessed name next
+ try {
+ return (Class<? extends C>) CLASSLOADER.loadClass(completedName + FACTORY_POSTFIX);
+ } catch (ClassNotFoundException e) {
+ // Ignore, retry
+ }
+ // Last try: guessed name prefix only
+ try {
+ return (Class<? extends C>) CLASSLOADER.loadClass(completedName);
+ } catch (ClassNotFoundException e) {
+ // Ignore, retry
+ }
+ // Try aliases:
+ for (Class<?> c : InspectionUtil.cachedFindAllImplementations(restrictionClass)) {
+ if (c.isAnnotationPresent(Alias.class)) {
+ Alias aliases = c.getAnnotation(Alias.class);
+ for (String alias : aliases.value()) {
+ if (alias.equalsIgnoreCase(value) || alias.equalsIgnoreCase(completedName)) {
+ return (Class<? extends C>) c;
+ }
+ }
+ }
}
- return MASTER_CACHE.iterator();
+ return null;
}
/**
* Perform a full (slow) scan for classes.
*
- * @param cond Class to include
* @return List with the scan result
*/
- private static List<Class<?>> slowScan(Class<?> cond) {
- ArrayList<Class<?>> res = new ArrayList<Class<?>>();
+ private static List<Class<?>> slowScan() {
+ ArrayList<Class<?>> res = new ArrayList<>();
try {
- ClassLoader cl = ClassLoader.getSystemClassLoader();
- Enumeration<URL> cps = cl.getResources("");
- while(cps.hasMoreElements()) {
+ Enumeration<URL> cps = CLASSLOADER.getResources("");
+ while (cps.hasMoreElements()) {
URL u = cps.nextElement();
// Scan file sources only.
- if("file".equals(u.getProtocol())) {
- Iterator<String> it = new DirClassIterator(new File(u.getFile()), DEFAULT_IGNORES);
- while(it.hasNext()) {
+ if ("file".equals(u.getProtocol())) {
+ File path;
+ try {
+ path = new File(u.toURI());
+ } catch (URISyntaxException e) {
+ LOG.exception("Error in classpath: " + u, e);
+ continue;
+ }
+ Iterator<String> it = new DirClassIterator(path, DEFAULT_IGNORES);
+ while (it.hasNext()) {
String classname = it.next();
try {
- Class<?> cls = cl.loadClass(classname);
+ Class<?> cls = CLASSLOADER.loadClass(classname);
// skip classes where we can't get a full name.
- if(cls.getCanonicalName() == null) {
- continue;
- }
- // Implements the right interface?
- if(cond != null && !cond.isAssignableFrom(cls)) {
+ if (cls.getCanonicalName() == null) {
continue;
}
res.add(cls);
- }
- catch(ClassNotFoundException e) {
+ } catch (ClassNotFoundException e) {
continue;
- }
- catch(NoClassDefFoundError e) {
+ } catch (NoClassDefFoundError e) {
continue;
- }
- catch(Exception e) {
+ } catch (Exception e) {
continue;
- }
- catch(Error e) {
+ } catch (Error e) {
continue;
}
}
}
}
- }
- catch(IOException e) {
+ } catch (IOException e) {
LOG.exception(e);
}
Collections.sort(res, new ClassSorter());
@@ -243,86 +279,6 @@ public class InspectionUtil {
}
/**
- * Class to iterate over a Jar file.
- *
- * Note: this is currently unused, as we now require all jar files to include
- * an index in the form of service-style files in META-INF/elki/
- *
- * @author Erich Schubert
- *
- * @apiviz.exclude
- */
- static class JarClassIterator implements Iterator<String> {
- private Enumeration<JarEntry> jarentries;
-
- private String ne;
-
- private String[] ignorepackages;
-
- /**
- * Constructor from Jar file.
- *
- * @param path Jar file entries to iterate over.
- */
- public JarClassIterator(String path, String[] ignorepackages) {
- this.ignorepackages = ignorepackages;
- try {
- JarFile jf = new JarFile(path);
- this.jarentries = jf.entries();
- this.ne = findNext();
- }
- catch(IOException e) {
- LoggingUtil.exception("Error opening jar file: " + path, e);
- this.jarentries = null;
- this.ne = null;
- }
- }
-
- @Override
- public boolean hasNext() {
- // Do we have a next entry?
- return (ne != null);
- }
-
- /**
- * Find the next entry, since we need to skip some jar file entries.
- *
- * @return next entry or null
- */
- private String findNext() {
- nextfile: while(jarentries.hasMoreElements()) {
- JarEntry je = jarentries.nextElement();
- String name = je.getName();
- if(name.endsWith(".class")) {
- String classname = name.substring(0, name.length() - ".class".length()).replace('/', '.');
- for(String pkg : ignorepackages) {
- if(classname.startsWith(pkg)) {
- continue nextfile;
- }
- }
- if(classname.endsWith(ClassParameter.FACTORY_POSTFIX) || !classname.contains("$")) {
- return classname.replace('/', '.');
- }
- }
- }
- return null;
- }
-
- @Override
- public String next() {
- // Return the previously stored entry.
- String ret = ne;
- ne = findNext();
- return ret;
- }
-
- @Override
- public void remove() {
- throw new UnsupportedOperationException();
- }
- }
-
- /**
* Class to iterate over a directory tree.
*
* @author Erich Schubert
@@ -332,15 +288,15 @@ public class InspectionUtil {
static class DirClassIterator implements Iterator<String> {
private static final String CLASS_EXT = ".class";
- private static final String FACTORY_FILE_EXT = ClassParameter.FACTORY_POSTFIX + CLASS_EXT;
+ private static final String FACTORY_FILE_EXT = FACTORY_POSTFIX + CLASS_EXT;
private static final int CLASS_EXT_LENGTH = CLASS_EXT.length();
private String prefix;
- private ArrayList<String> files = new ArrayList<String>(100);
+ private ArrayList<String> files = new ArrayList<>(100);
- private ArrayList<Pair<File, String>> folders = new ArrayList<Pair<File, String>>(100);
+ private ArrayList<Pair<File, String>> folders = new ArrayList<>(100);
private String[] ignorepackages;
@@ -352,16 +308,16 @@ public class InspectionUtil {
public DirClassIterator(File path, String[] ignorepackages) {
this.ignorepackages = ignorepackages;
this.prefix = path.getAbsolutePath();
- if(prefix.charAt(prefix.length() - 1) != File.separatorChar) {
+ if (prefix.charAt(prefix.length() - 1) != File.separatorChar) {
prefix = prefix + File.separatorChar;
}
- this.folders.add(new Pair<File, String>(path, ""));
+ this.folders.add(new Pair<>(path, ""));
}
@Override
public boolean hasNext() {
- if(files.size() == 0) {
+ if (files.size() == 0) {
findNext();
}
return (files.size() > 0);
@@ -371,19 +327,19 @@ public class InspectionUtil {
* Find the next entry, since we need to skip some directories.
*/
private void findNext() {
- while(folders.size() > 0) {
+ while (folders.size() > 0) {
Pair<File, String> pair = folders.remove(folders.size() - 1);
// recurse into directories
- if(pair.first.isDirectory()) {
- nextfile: for(String localname : pair.first.list()) {
+ if (pair.first.isDirectory()) {
+ nextfile: for (String localname : pair.first.list()) {
// Ignore unix-hidden files/dirs
- if(localname.charAt(0) == '.') {
+ if (localname.charAt(0) == '.') {
continue;
}
// Classes
- if(localname.endsWith(CLASS_EXT)) {
- if(localname.indexOf('$') >= 0) {
- if(!localname.endsWith(FACTORY_FILE_EXT)) {
+ if (localname.endsWith(CLASS_EXT)) {
+ if (localname.indexOf('$') >= 0) {
+ if (!localname.endsWith(FACTORY_FILE_EXT)) {
continue;
}
}
@@ -392,14 +348,14 @@ public class InspectionUtil {
}
// Recurse into directories
File newf = new File(pair.first, localname);
- if(newf.isDirectory()) {
+ if (newf.isDirectory()) {
String newpref = pair.second + localname + '.';
- for(String ignore : ignorepackages) {
- if(ignore.equals(newpref)) {
+ for (String ignore : ignorepackages) {
+ if (ignore.equals(newpref)) {
continue nextfile;
}
}
- folders.add(new Pair<File, String>(newf, newpref));
+ folders.add(new Pair<>(newf, newpref));
}
}
}
@@ -408,10 +364,10 @@ public class InspectionUtil {
@Override
public String next() {
- if(files.size() == 0) {
+ if (files.size() == 0) {
findNext();
}
- if(files.size() > 0) {
+ if (files.size() > 0) {
return files.remove(files.size() - 1);
}
return null;
@@ -433,11 +389,19 @@ public class InspectionUtil {
public static class ClassSorter implements Comparator<Class<?>> {
@Override
public int compare(Class<?> o1, Class<?> o2) {
- int pkgcmp = o1.getPackage().getName().compareTo(o2.getPackage().getName());
- if(pkgcmp != 0) {
+ Package p1 = o1.getPackage();
+ Package p2 = o2.getPackage();
+ if (p1 == null) {
+ return -1;
+ }
+ if (p2 == null) {
+ return 1;
+ }
+ int pkgcmp = p1.getName().compareTo(p2.getName());
+ if (pkgcmp != 0) {
return pkgcmp;
}
return o1.getCanonicalName().compareTo(o2.getCanonicalName());
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/QueryStatistic.java b/src/de/lmu/ifi/dbs/elki/utilities/QueryStatistic.java
deleted file mode 100644
index 91acad87..00000000
--- a/src/de/lmu/ifi/dbs/elki/utilities/QueryStatistic.java
+++ /dev/null
@@ -1,98 +0,0 @@
-package de.lmu.ifi.dbs.elki.utilities;
-
-/*
- This file is part of ELKI:
- Environment for Developing KDD-Applications Supported by Index-Structures
-
- Copyright (C) 2012
- Ludwig-Maximilians-Universität München
- Lehr- und Forschungseinheit für Datenbanksysteme
- ELKI Development Team
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-/**
- * Provides some statistics about queries
- * using a filter-refinement architecture.
- *
- * @author Elke Achtert
- */
-public class QueryStatistic {
- /**
- * The number of candidate objects which need a refinement.
- */
- private int candidates;
-
- /**
- * The number of true hits which do not need a refinement.
- */
- private int trueHits;
-
- /**
- * The overall number of the result objects after refinement
- * plus the true hits.
- */
- private int results;
-
- /**
- * Clears the values of this statistic.
- */
- public void clear() {
- this.candidates = 0;
- this.trueHits = 0;
- this.results = 0;
- }
-
- /**
- * Adds the specified number to the number of the result objects.
- *
- * @param results the number of the result objects to be added
- */
- public void addResults(int results) {
- this.results += results;
- }
-
- /**
- * Adds the specified number to the number of the candidate objects.
- *
- * @param candidates the number of the candidate objects to be added
- */
- public void addCandidates(int candidates) {
- this.candidates += candidates;
- }
-
- /**
- * Adds the specified number to the number of the true hits.
- *
- * @param trueHits the number of the true hits to be added
- */
- public void addTrueHits(int trueHits) {
- this.trueHits += trueHits;
- }
-
- /**
- * Returns the number of candidate objects and the number of the result objects after refinement.
- *
- * @return a string representation of this query statistic
- */
- @Override
- public String toString() {
- return
- "# candidates = " + candidates +
- "\n# true hits = " + trueHits +
- "\n# results = " + results;
- }
-}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/RandomFactory.java b/src/de/lmu/ifi/dbs/elki/utilities/RandomFactory.java
index 65a92d33..9b870acb 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/RandomFactory.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/RandomFactory.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/Util.java b/src/de/lmu/ifi/dbs/elki/utilities/Util.java
index 42144958..439ef171 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/Util.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/Util.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,12 +23,10 @@ package de.lmu.ifi.dbs.elki.utilities;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
import java.util.BitSet;
import java.util.Comparator;
import java.util.Random;
-
/**
* This class collects various static helper methods.
*
@@ -39,6 +37,11 @@ import java.util.Random;
*/
public final class Util {
/**
+ * Prime number used in hash code computation.
+ */
+ private static final long HASHPRIME = 2654435761L;
+
+ /**
* Fake constructor: do not instantiate.
*/
private Util() {
@@ -77,21 +80,55 @@ public final class Util {
/**
* Mix multiple hashcodes into one.
*
+ * @param hash Single Hashcodes to "mix"
+ * @return Original hash code
+ */
+ @Deprecated
+ public static int mixHashCodes(int hash) {
+ return hash;
+ }
+
+ /**
+ * Mix multiple hashcodes into one.
+ *
+ * @param hash1 First hashcode to mix
+ * @param hash2 Second hashcode to mix
+ * @return Mixed hash code
+ */
+ public static int mixHashCodes(int hash1, int hash2) {
+ return (int) (hash1 * HASHPRIME + hash2);
+ }
+
+ /**
+ * Mix multiple hashcodes into one.
+ *
+ * @param hash1 First hashcode to mix
+ * @param hash2 Second hashcode to mix
+ * @param hash3 Third hashcode to mix
+ * @return Mixed hash code
+ */
+ public static int mixHashCodes(int hash1, int hash2, int hash3) {
+ long result = hash1 * HASHPRIME + hash2;
+ return (int) (result * HASHPRIME + hash3);
+ }
+
+ /**
+ * Mix multiple hashcodes into one.
+ *
* @param hash Hashcodes to mix
* @return Mixed hash code
*/
public static int mixHashCodes(int... hash) {
- final long prime = 2654435761L;
if (hash.length == 0) {
return 0;
}
long result = hash[0];
for (int i = 1; i < hash.length; i++) {
- result = result * prime + hash[i];
+ result = result * HASHPRIME + hash[i];
}
return (int) result;
}
-
+
/**
* Static instance.
*/
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/AnyMap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/AnyMap.java
deleted file mode 100644
index 763ce105..00000000
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/AnyMap.java
+++ /dev/null
@@ -1,94 +0,0 @@
-package de.lmu.ifi.dbs.elki.utilities.datastructures;
-
-/*
- This file is part of ELKI:
- Environment for Developing KDD-Applications Supported by Index-Structures
-
- Copyright (C) 2012
- Ludwig-Maximilians-Universität München
- Lehr- und Forschungseinheit für Datenbanksysteme
- ELKI Development Team
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-import java.util.HashMap;
-
-/**
- * Associative storage based on a {@link HashMap} for multiple object types that
- * offers a type checked {@link #get(Object, Class)} method.
- *
- * @author Erich Schubert
- *
- * @param <K> Key class type
- */
-public class AnyMap<K> extends HashMap<K, Object> {
- /**
- * Serial version.
- */
- private static final long serialVersionUID = 1L;
-
- /**
- * Constructor
- */
- public AnyMap() {
- super();
- }
-
- /**
- * Type checked get method
- *
- * @param <T> Return type
- * @param key Key
- * @param restriction restriction class
- * @return Object that is guaranteed to be of class restriction or null
- */
- public <T> T get(K key, Class<T> restriction) {
- Object o = super.get(key);
- if(o == null) {
- return null;
- }
- try {
- return restriction.cast(o);
- }
- catch(ClassCastException e) {
- return null;
- }
- }
-
- /**
- * (Largely) type checked get method for use with generic types
- *
- * @param <T> Return type
- * @param key Key
- * @param restriction restriction class
- * @return Object that is guaranteed to be of class restriction or null
- */
- @SuppressWarnings("unchecked")
- public <T> T getGenerics(K key, Class<?> restriction) {
- return (T) get(key, restriction);
- }
-
- /**
- * Depreciate the use of the untyped get method.
- *
- * @deprecated use {@link #get(Object, Class)} or
- * {@link #getGenerics(Object, Class)} instead, for type safety!
- */
- @Override
- @Deprecated
- public Object get(Object key) {
- return super.get(key);
- }
-} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/HashMapList.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/HashMapList.java
deleted file mode 100644
index 26fa4d19..00000000
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/HashMapList.java
+++ /dev/null
@@ -1,124 +0,0 @@
-package de.lmu.ifi.dbs.elki.utilities.datastructures;
-
-/*
- This file is part of ELKI:
- Environment for Developing KDD-Applications Supported by Index-Structures
-
- Copyright (C) 2012
- Ludwig-Maximilians-Universität München
- Lehr- und Forschungseinheit für Datenbanksysteme
- ELKI Development Team
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * Multi-Associative container, that stores a list of values for a particular key.
- *
- * @author Erich Schubert
- *
- * @apiviz.has List oneway - - contains
- *
- * @param <K> Key type
- * @param <V> Value type
- */
-// TODO: use MultiValueMap from apache collections instead?
-public class HashMapList<K, V> extends HashMap<K, List<V>> {
- /**
- * Serial version
- */
- private static final long serialVersionUID = 3883242025598456055L;
-
- /**
- * Constructor.
- */
- public HashMapList() {
- super();
- }
-
- /**
- * Constructor with initial capacity (of the hash)
- *
- * @param initialCapacity initial capacity
- */
- public HashMapList(int initialCapacity) {
- super(initialCapacity);
- }
-
- /**
- * Add a single value to the given key.
- *
- * @param key Key
- * @param value Additional Value
- */
- public synchronized void add(K key, V value) {
- List<V> list = super.get(key);
- if (list == null) {
- list = new ArrayList<V>(1);
- super.put(key, list);
- }
- list.add(value);
- }
-
- /**
- * Check that there is at least one value for the key.
- */
- @Override
- public boolean containsKey(Object key) {
- List<V> list = super.get(key);
- if (list == null) {
- return false;
- }
- return list.size() > 0;
- }
-
- /**
- * Remove a single value from the map.
- *
- * @param key Key to remove
- * @param value Value to remove.
- * @return <tt>true</tt> if this list contained the specified element
- */
- public synchronized boolean remove(K key, V value) {
- List<V> list = super.get(key);
- if (list == null) {
- return false;
- }
- boolean success = list.remove(value);
- // remove empty lists.
- if (list.size() == 0) {
- super.remove(key);
- }
- return success;
- }
-
- /**
- * Test if a given value is already present for the key.
- *
- * @param key Key
- * @param value Value
- * @return <tt>true</tt> if the keys list contains the specified element
- */
- public boolean contains(K key, V value) {
- List<V> list = super.get(key);
- if (list == null) {
- return false;
- }
- return list.contains(value);
- }
-}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/MaskedArrayList.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/MaskedArrayList.java
deleted file mode 100644
index c24519d1..00000000
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/MaskedArrayList.java
+++ /dev/null
@@ -1,174 +0,0 @@
-package de.lmu.ifi.dbs.elki.utilities.datastructures;
-
-/*
- This file is part of ELKI:
- Environment for Developing KDD-Applications Supported by Index-Structures
-
- Copyright (C) 2012
- Ludwig-Maximilians-Universität München
- Lehr- und Forschungseinheit für Datenbanksysteme
- ELKI Development Team
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-import java.util.AbstractCollection;
-import java.util.ArrayList;
-import java.util.BitSet;
-import java.util.Collection;
-import java.util.Iterator;
-
-/**
- * This class is a virtual collection based on masking an array list using a bit
- * mask.
- *
- * @author Erich Schubert
- *
- * @apiviz.stereotype decorator
- * @apiviz.composedOf java.util.ArrayList
- * @apiviz.composedOf java.util.BitSet
- *
- * @param <T> Object type
- */
-public class MaskedArrayList<T> extends AbstractCollection<T> implements Collection<T> {
- /**
- * Data storage
- */
- protected ArrayList<T> data;
-
- /**
- * The bitmask used for masking
- */
- protected BitSet bits;
-
- /**
- * Flag whether to iterator over set or unset values.
- */
- protected boolean inverse = false;
-
- /**
- * Constructor.
- *
- * @param data Data
- * @param bits Bitset to use as mask
- * @param inverse Flag to inverse the masking rule
- */
- public MaskedArrayList(ArrayList<T> data, BitSet bits, boolean inverse) {
- super();
- this.data = data;
- this.bits = bits;
- this.inverse = inverse;
- }
-
- @Override
- public boolean add(T e) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Iterator<T> iterator() {
- if(inverse) {
- return new InvItr();
- }
- else {
- return new Itr();
- }
- }
-
- @Override
- public int size() {
- if(inverse) {
- return data.size() - bits.cardinality();
- }
- else {
- return bits.cardinality();
- }
- }
-
- /**
- * Iterator over set bits
- *
- * @author Erich Schubert
- *
- * @apiviz.exclude
- */
- protected class Itr implements Iterator<T> {
- /**
- * Next position.
- */
- private int pos;
-
- /**
- * Constructor
- */
- protected Itr() {
- this.pos = bits.nextSetBit(0);
- }
-
- @Override
- public boolean hasNext() {
- return (pos >= 0) && (pos < data.size());
- }
-
- @Override
- public T next() {
- T cur = data.get(pos);
- pos = bits.nextSetBit(pos + 1);
- return cur;
- }
-
- @Override
- public void remove() {
- throw new UnsupportedOperationException();
- }
- }
-
- /**
- * Iterator over unset elements.
- *
- * @author Erich Schubert
- *
- * @apiviz.exclude
- */
- protected class InvItr implements Iterator<T> {
- /**
- * Next unset position.
- */
- private int pos;
-
- /**
- * Constructor
- */
- protected InvItr() {
- this.pos = bits.nextClearBit(0);
- }
-
- @Override
- public boolean hasNext() {
- return (pos >= 0) && (pos < data.size());
- }
-
- @Override
- public T next() {
- T cur = data.get(pos);
- pos = bits.nextClearBit(pos + 1);
- return cur;
- }
-
- @Override
- public void remove() {
- throw new UnsupportedOperationException();
- }
- }
-} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/QuickSelect.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/QuickSelect.java
index bfa7950d..3746ff87 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/QuickSelect.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/QuickSelect.java
@@ -1,18 +1,10 @@
package de.lmu.ifi.dbs.elki.utilities.datastructures;
-import java.util.Comparator;
-import java.util.List;
-
-import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs;
-import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDArrayIter;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
-
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -31,6 +23,14 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import java.util.Comparator;
+import java.util.List;
+
+import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.DBID;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDArrayIter;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
+
/**
* QuickSelect computes ("selects") the element at a given rank and can be used
* to compute Medians and arbitrary quantiles by computing the appropriate rank.
@@ -43,13 +43,297 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDRef;
*
* @apiviz.uses ArrayModifiableDBIDs
* @apiviz.uses List
- * @apiviz.uses Comparator
+ * @apiviz.uses Adapter
*/
public class QuickSelect {
/**
* For small arrays, use a simpler method:
*/
- private static final int SMALL = 10;
+ private static final int SMALL = 47;
+
+ /**
+ * Choose the best pivot for the given rank.
+ *
+ * @param rank Rank
+ * @param m1 Pivot candidate
+ * @param m2 Pivot candidate
+ * @param m3 Pivot candidate
+ * @param m4 Pivot candidate
+ * @param m5 Pivot candidate
+ * @return Best pivot candidate
+ */
+ private static final int bestPivot(int rank, int m1, int m2, int m3, int m4, int m5) {
+ if (rank < m1) {
+ return m1;
+ }
+ if (rank > m5) {
+ return m5;
+ }
+ if (rank < m2) {
+ return m2;
+ }
+ if (rank > m4) {
+ return m4;
+ }
+ return m3;
+ }
+
+ /**
+ * QuickSelect is essentially quicksort, except that we only "sort" that half
+ * of the array that we are interested in.
+ *
+ * @param data Data to process
+ * @param start Interval start
+ * @param end Interval end (exclusive)
+ * @param rank rank position we are interested in (starting at 0)
+ */
+ public static <T> void quickSelect(T data, Adapter<T> adapter, int start, int end, int rank) {
+ while (true) {
+ // Optimization for small arrays
+ // This also ensures a minimum size below
+ if (start + SMALL > end) {
+ insertionSort(data, adapter, start, end);
+ return;
+ }
+
+ // Best of 5 pivot picking:
+ // Choose pivots by looking at five candidates.
+ final int len = end - start;
+ final int seventh = (len >> 3) + (len >> 6) + 1;
+ final int m3 = (start + end) >> 1; // middle
+ final int m2 = m3 - seventh;
+ final int m1 = m2 - seventh;
+ final int m4 = m3 + seventh;
+ final int m5 = m4 + seventh;
+
+ // Explicit (and optimal) sorting network for 5 elements
+ // See Knuth for details.
+ if (adapter.compareGreater(data, m1, m2)) {
+ adapter.swap(data, m1, m2);
+ }
+ if (adapter.compareGreater(data, m1, m3)) {
+ adapter.swap(data, m1, m3);
+ }
+ if (adapter.compareGreater(data, m2, m3)) {
+ adapter.swap(data, m2, m3);
+ }
+ if (adapter.compareGreater(data, m4, m5)) {
+ adapter.swap(data, m4, m5);
+ }
+ if (adapter.compareGreater(data, m1, m4)) {
+ adapter.swap(data, m1, m4);
+ }
+ if (adapter.compareGreater(data, m3, m4)) {
+ adapter.swap(data, m3, m4);
+ }
+ if (adapter.compareGreater(data, m2, m5)) {
+ adapter.swap(data, m2, m5);
+ }
+ if (adapter.compareGreater(data, m2, m3)) {
+ adapter.swap(data, m2, m3);
+ }
+ if (adapter.compareGreater(data, m4, m5)) {
+ adapter.swap(data, m4, m5);
+ }
+
+ int best = bestPivot(rank, m1, m2, m3, m4, m5);
+ // final double pivot = data[best];
+ // Move middle element out of the way.
+ adapter.swap(data, best, end - 1);
+
+ // Begin partitioning
+ int i = start, j = end - 2;
+ // This is classic quicksort stuff
+ while (true) {
+ while (i <= j && adapter.compareGreater(data, end - 1, i)) {
+ i++;
+ }
+ while (j >= i && !adapter.compareGreater(data, end - 1, j)) {
+ j--;
+ }
+ if (i >= j) {
+ break;
+ }
+ adapter.swap(data, i, j);
+ }
+
+ // Move pivot (former middle element) back into the appropriate place
+ adapter.swap(data, i, end - 1);
+
+ // In contrast to quicksort, we only need to recurse into the half we are
+ // interested in. Instead of recursion we now use iteration.
+ if (rank < i) {
+ end = i;
+ } else if (rank > i) {
+ start = i + 1;
+ } else {
+ break;
+ }
+ } // Loop until rank==i
+ }
+
+ /**
+ * Sort a small array using repetitive insertion sort.
+ *
+ * @param data Data to sort
+ * @param start Interval start
+ * @param end Interval end
+ */
+ private static <T> void insertionSort(T data, Adapter<T> adapter, int start, int end) {
+ for (int i = start + 1; i < end; i++) {
+ for (int j = i; j > start && adapter.compareGreater(data, j - 1, j); j--) {
+ adapter.swap(data, j, j - 1);
+ }
+ }
+ }
+
+ /**
+ * Adapter class to apply QuickSelect to arbitrary data structures.
+ *
+ * @author Erich Schubert
+ *
+ * @param <T> Data structure type
+ */
+ public static interface Adapter<T> {
+ /**
+ * Swap the two elements at positions i and j.
+ *
+ * @param data Data structure
+ * @param i Position i
+ * @param j Position j
+ */
+ void swap(T data, int i, int j);
+
+ /**
+ * Compare two elements.
+ *
+ * @param data Data structure
+ * @param i Position i
+ * @param j Position j
+ * @return {@code true} when the element at position i is greater than that
+ * at position j.
+ */
+ boolean compareGreater(T data, int i, int j);
+ }
+
+ /**
+ * Adapter for double arrays.
+ */
+ public static Adapter<double[]> DOUBLE_ADAPTER = new Adapter<double[]>() {
+ @Override
+ public void swap(double[] data, int i, int j) {
+ double tmp = data[i];
+ data[i] = data[j];
+ data[j] = tmp;
+ }
+
+ @Override
+ public boolean compareGreater(double[] data, int i, int j) {
+ return data[i] > data[j];
+ }
+ };
+
+ /**
+ * Adapter for integer arrays.
+ */
+ public static Adapter<int[]> INTEGER_ADAPTER = new Adapter<int[]>() {
+ @Override
+ public void swap(int[] data, int i, int j) {
+ int tmp = data[i];
+ data[i] = data[j];
+ data[j] = tmp;
+ }
+
+ @Override
+ public boolean compareGreater(int[] data, int i, int j) {
+ return data[i] > data[j];
+ }
+ };
+
+ /**
+ * Adapter for float arrays.
+ */
+ public static Adapter<float[]> FLOAT_ADAPTER = new Adapter<float[]>() {
+ @Override
+ public void swap(float[] data, int i, int j) {
+ float tmp = data[i];
+ data[i] = data[j];
+ data[j] = tmp;
+ }
+
+ @Override
+ public boolean compareGreater(float[] data, int i, int j) {
+ return data[i] > data[j];
+ }
+ };
+
+ /**
+ * Adapter for short arrays.
+ */
+ public static Adapter<short[]> SHORT_ADAPTER = new Adapter<short[]>() {
+ @Override
+ public void swap(short[] data, int i, int j) {
+ short tmp = data[i];
+ data[i] = data[j];
+ data[j] = tmp;
+ }
+
+ @Override
+ public boolean compareGreater(short[] data, int i, int j) {
+ return data[i] > data[j];
+ }
+ };
+
+ /**
+ * Adapter for long arrays.
+ */
+ public static Adapter<long[]> LONG_ADAPTER = new Adapter<long[]>() {
+ @Override
+ public void swap(long[] data, int i, int j) {
+ long tmp = data[i];
+ data[i] = data[j];
+ data[j] = tmp;
+ }
+
+ @Override
+ public boolean compareGreater(long[] data, int i, int j) {
+ return data[i] > data[j];
+ }
+ };
+
+ /**
+ * Adapter for byte arrays.
+ */
+ public static Adapter<byte[]> BYTE_ADAPTER = new Adapter<byte[]>() {
+ @Override
+ public void swap(byte[] data, int i, int j) {
+ byte tmp = data[i];
+ data[i] = data[j];
+ data[j] = tmp;
+ }
+
+ @Override
+ public boolean compareGreater(byte[] data, int i, int j) {
+ return data[i] > data[j];
+ }
+ };
+
+ /**
+ * Adapter for char arrays.
+ */
+ public static Adapter<char[]> CHAR_ADAPTER = new Adapter<char[]>() {
+ @Override
+ public void swap(char[] data, int i, int j) {
+ char tmp = data[i];
+ data[i] = data[j];
+ data[j] = tmp;
+ }
+
+ @Override
+ public boolean compareGreater(char[] data, int i, int j) {
+ return data[i] > data[j];
+ }
+ };
/**
* QuickSelect is essentially quicksort, except that we only "sort" that half
@@ -94,11 +378,10 @@ public class QuickSelect {
// Integer division is "floor" since we are non-negative.
final int left = begin + ((length - 1) >> 1);
quickSelect(data, begin, end, left);
- if(length % 2 == 1) {
+ if (length % 2 == 1) {
return data[left];
- }
- else {
- quickSelect(data, begin, end, left + 1);
+ } else {
+ quickSelect(data, left + 1, end, left + 1);
return data[left] + .5 * (data[left + 1] - data[left]);
}
}
@@ -136,11 +419,10 @@ public class QuickSelect {
final double err = dleft - ileft;
quickSelect(data, begin, end, ileft);
- if(err <= Double.MIN_NORMAL) {
+ if (err <= Double.MIN_NORMAL) {
return data[ileft];
- }
- else {
- quickSelect(data, begin, end, ileft + 1);
+ } else {
+ quickSelect(data, ileft + 1, end, ileft + 1);
// Mix:
double mix = data[ileft] + (data[ileft + 1] - data[ileft]) * err;
return mix;
@@ -155,66 +437,94 @@ public class QuickSelect {
* @param start Interval start
* @param end Interval end (exclusive)
* @param rank rank position we are interested in (starting at 0)
+ * @return Element at the given rank (starting at 0).
*/
- public static void quickSelect(double[] data, int start, int end, int rank) {
- while(true) {
+ public static double quickSelect(double[] data, int start, int end, int rank) {
+ while (true) {
// Optimization for small arrays
// This also ensures a minimum size below
- if(start + SMALL > end) {
+ if (start + SMALL > end) {
insertionSort(data, start, end);
- return;
+ return data[rank];
}
- // Pick pivot from three candidates: start, middle, end
- // Since we compare them, we can also just "bubble sort" them.
- final int middle = (start + end) >> 1;
- if(data[start] > data[middle]) {
- swap(data, start, middle);
+ // Best of 5 pivot picking:
+ // Choose pivots by looking at five candidates.
+ final int len = end - start;
+ final int seventh = (len >> 3) + (len >> 6) + 1;
+ final int m3 = (start + end) >> 1; // middle
+ final int m2 = m3 - seventh;
+ final int m1 = m2 - seventh;
+ final int m4 = m3 + seventh;
+ final int m5 = m4 + seventh;
+
+ // Explicit (and optimal) sorting network for 5 elements
+ // See Knuth for details.
+ if (data[m1] > data[m2]) {
+ swap(data, m1, m2);
+ }
+ if (data[m1] > data[m3]) {
+ swap(data, m1, m3);
+ }
+ if (data[m2] > data[m3]) {
+ swap(data, m2, m3);
+ }
+ if (data[m4] > data[m5]) {
+ swap(data, m4, m5);
+ }
+ if (data[m1] > data[m4]) {
+ swap(data, m1, m4);
}
- if(data[start] > data[end - 1]) {
- swap(data, start, end - 1);
+ if (data[m3] > data[m4]) {
+ swap(data, m3, m4);
}
- if(data[middle] > data[end - 1]) {
- swap(data, middle, end - 1);
+ if (data[m2] > data[m5]) {
+ swap(data, m2, m5);
+ }
+ if (data[m2] > data[m3]) {
+ swap(data, m2, m3);
+ }
+ if (data[m4] > data[m5]) {
+ swap(data, m4, m5);
}
- // TODO: use more candidates for larger arrays?
- final double pivot = data[middle];
- // Move middle element out of the way, just before end
- // (Since we already know that "end" is bigger)
- swap(data, middle, end - 2);
+ int best = bestPivot(rank, m1, m2, m3, m4, m5);
+ final double pivot = data[best];
+ // Move middle element out of the way.
+ swap(data, best, end - 1);
// Begin partitioning
- int i = start + 1, j = end - 3;
+ int i = start, j = end - 2;
// This is classic quicksort stuff
- while(true) {
- while(data[i] <= pivot && i <= j) {
+ while (true) {
+ while (i <= j && data[i] <= pivot) {
i++;
}
- while(data[j] >= pivot && j >= i) {
+ while (j >= i && data[j] >= pivot) {
j--;
}
- if(i >= j) {
+ if (i >= j) {
break;
}
swap(data, i, j);
+ i++;
+ j--;
}
// Move pivot (former middle element) back into the appropriate place
- swap(data, i, end - 2);
+ swap(data, i, end - 1);
// In contrast to quicksort, we only need to recurse into the half we are
// interested in. Instead of recursion we now use iteration.
- if(rank < i) {
+ if (rank < i) {
end = i;
- }
- else if(rank > i) {
+ } else if (rank > i) {
start = i + 1;
- }
- else {
+ } else {
break;
}
} // Loop until rank==i
+ return data[rank];
}
/**
@@ -225,8 +535,8 @@ public class QuickSelect {
* @param end Interval end
*/
private static void insertionSort(double[] data, int start, int end) {
- for(int i = start + 1; i < end; i++) {
- for(int j = i; j > start && data[j - 1] > data[j]; j--) {
+ for (int i = start + 1; i < end; i++) {
+ for (int j = i; j > start && data[j - 1] > data[j]; j--) {
swap(data, j, j - 1);
}
}
@@ -345,61 +655,85 @@ public class QuickSelect {
* @param rank rank position we are interested in (starting at 0)
*/
public static <T extends Comparable<? super T>> void quickSelect(T[] data, int start, int end, int rank) {
- while(true) {
+ while (true) {
// Optimization for small arrays
// This also ensures a minimum size below
- if(start + SMALL > end) {
+ if (start + SMALL > end) {
insertionSort(data, start, end);
return;
}
- // Pick pivot from three candidates: start, middle, end
- // Since we compare them, we can also just "bubble sort" them.
- final int middle = (start + end) >> 1;
- if(data[start].compareTo(data[middle]) > 0) {
- swap(data, start, middle);
+ // Best of 5 pivot picking:
+ // Choose pivots by looking at five candidates.
+ final int len = end - start;
+ final int seventh = (len >> 3) + (len >> 6) + 1;
+ final int m3 = (start + end) >> 1; // middle
+ final int m2 = m3 - seventh;
+ final int m1 = m2 - seventh;
+ final int m4 = m3 + seventh;
+ final int m5 = m4 + seventh;
+
+ // Explicit (and optimal) sorting network for 5 elements
+ // See Knuth for details.
+ if (data[m1].compareTo(data[m2]) > 0) {
+ swap(data, m1, m2);
+ }
+ if (data[m1].compareTo(data[m3]) > 0) {
+ swap(data, m1, m3);
+ }
+ if (data[m2].compareTo(data[m3]) > 0) {
+ swap(data, m2, m3);
+ }
+ if (data[m4].compareTo(data[m5]) > 0) {
+ swap(data, m4, m5);
+ }
+ if (data[m1].compareTo(data[m4]) > 0) {
+ swap(data, m1, m4);
}
- if(data[start].compareTo(data[end - 1]) > 0) {
- swap(data, start, end - 1);
+ if (data[m3].compareTo(data[m4]) > 0) {
+ swap(data, m3, m4);
}
- if(data[middle].compareTo(data[end - 1]) > 0) {
- swap(data, middle, end - 1);
+ if (data[m2].compareTo(data[m5]) > 0) {
+ swap(data, m2, m5);
+ }
+ if (data[m2].compareTo(data[m3]) > 0) {
+ swap(data, m2, m3);
+ }
+ if (data[m4].compareTo(data[m5]) > 0) {
+ swap(data, m4, m5);
}
- // TODO: use more candidates for larger arrays?
- final T pivot = data[middle];
- // Move middle element out of the way, just before end
- // (Since we already know that "end" is bigger)
- swap(data, middle, end - 2);
+ int best = bestPivot(rank, m1, m2, m3, m4, m5);
+ final T pivot = data[best];
+ // Move middle element out of the way.
+ swap(data, best, end - 1);
// Begin partitioning
- int i = start + 1, j = end - 3;
+ int i = start, j = end - 2;
// This is classic quicksort stuff
- while(true) {
- while(data[i].compareTo(pivot) <= 0 && i <= j) {
+ while (true) {
+ while (i <= j && data[i].compareTo(pivot) <= 0) {
i++;
}
- while(data[j].compareTo(pivot) >= 0 && j >= i) {
+ while (j >= i && data[j].compareTo(pivot) >= 0) {
j--;
}
- if(i >= j) {
+ if (i >= j) {
break;
}
swap(data, i, j);
}
// Move pivot (former middle element) back into the appropriate place
- swap(data, i, end - 2);
+ swap(data, i, end - 1);
// In contrast to quicksort, we only need to recurse into the half we are
// interested in. Instead of recursion we now use iteration.
- if(rank < i) {
+ if (rank < i) {
end = i;
- }
- else if(rank > i) {
+ } else if (rank > i) {
start = i + 1;
- }
- else {
+ } else {
break;
}
} // Loop until rank==i
@@ -414,8 +748,8 @@ public class QuickSelect {
* @param end Interval end
*/
private static <T extends Comparable<? super T>> void insertionSort(T[] data, int start, int end) {
- for(int i = start + 1; i < end; i++) {
- for(int j = i; j > start && data[j - 1].compareTo(data[j]) > 0; j--) {
+ for (int i = start + 1; i < end; i++) {
+ for (int j = i; j > start && data[j - 1].compareTo(data[j]) > 0; j--) {
swap(data, j, j - 1);
}
}
@@ -536,61 +870,86 @@ public class QuickSelect {
* @param rank rank position we are interested in (starting at 0)
*/
public static <T extends Comparable<? super T>> void quickSelect(List<? extends T> data, int start, int end, int rank) {
- while(true) {
+ while (true) {
// Optimization for small arrays
// This also ensures a minimum size below
- if(start + SMALL > end) {
+ if (start + SMALL > end) {
insertionSort(data, start, end);
return;
}
- // Pick pivot from three candidates: start, middle, end
- // Since we compare them, we can also just "bubble sort" them.
- final int middle = (start + end) >> 1;
- if(data.get(start).compareTo(data.get(middle)) > 0) {
- swap(data, start, middle);
+ // Best of 5 pivot picking:
+ // Choose pivots by looking at five candidates.
+ final int len = end - start;
+ final int seventh = (len >> 3) + (len >> 6) + 1;
+ final int m3 = (start + end) >> 1; // middle
+ final int m2 = m3 - seventh;
+ final int m1 = m2 - seventh;
+ final int m4 = m3 + seventh;
+ final int m5 = m4 + seventh;
+
+ // Explicit (and optimal) sorting network for 5 elements
+ // See Knuth for details.
+ if (data.get(m1).compareTo(data.get(m2)) > 0) {
+ swap(data, m1, m2);
}
- if(data.get(start).compareTo(data.get(end - 1)) > 0) {
- swap(data, start, end - 1);
+ if (data.get(m1).compareTo(data.get(m3)) > 0) {
+ swap(data, m1, m3);
}
- if(data.get(middle).compareTo(data.get(end - 1)) > 0) {
- swap(data, middle, end - 1);
+ if (data.get(m2).compareTo(data.get(m3)) > 0) {
+ swap(data, m2, m3);
+ }
+ if (data.get(m4).compareTo(data.get(m5)) > 0) {
+ swap(data, m4, m5);
+ }
+ if (data.get(m1).compareTo(data.get(m4)) > 0) {
+ swap(data, m1, m4);
+ }
+ if (data.get(m3).compareTo(data.get(m4)) > 0) {
+ swap(data, m3, m4);
+ }
+ if (data.get(m2).compareTo(data.get(m5)) > 0) {
+ swap(data, m2, m5);
+ }
+ if (data.get(m2).compareTo(data.get(m3)) > 0) {
+ swap(data, m2, m3);
+ }
+ if (data.get(m4).compareTo(data.get(m5)) > 0) {
+ swap(data, m4, m5);
}
- // TODO: use more candidates for larger arrays?
- final T pivot = data.get(middle);
+ int best = bestPivot(rank, m1, m2, m3, m4, m5);
+ final T pivot = data.get(best);
// Move middle element out of the way, just before end
// (Since we already know that "end" is bigger)
- swap(data, middle, end - 2);
+ swap(data, best, end - 1);
// Begin partitioning
- int i = start + 1, j = end - 3;
+ int i = start, j = end - 2;
// This is classic quicksort stuff
- while(true) {
- while(data.get(i).compareTo(pivot) <= 0 && i <= j) {
+ while (true) {
+ while (i <= j && data.get(i).compareTo(pivot) <= 0) {
i++;
}
- while(data.get(j).compareTo(pivot) >= 0 && j >= i) {
+ while (j >= i && data.get(j).compareTo(pivot) >= 0) {
j--;
}
- if(i >= j) {
+ if (i >= j) {
break;
}
swap(data, i, j);
}
// Move pivot (former middle element) back into the appropriate place
- swap(data, i, end - 2);
+ swap(data, i, end - 1);
// In contrast to quicksort, we only need to recurse into the half we are
// interested in. Instead of recursion we now use iteration.
- if(rank < i) {
+ if (rank < i) {
end = i;
- }
- else if(rank > i) {
+ } else if (rank > i) {
start = i + 1;
- }
- else {
+ } else {
break;
}
} // Loop until rank==i
@@ -605,8 +964,8 @@ public class QuickSelect {
* @param end Interval end
*/
private static <T extends Comparable<? super T>> void insertionSort(List<T> data, int start, int end) {
- for(int i = start + 1; i < end; i++) {
- for(int j = i; j > start && data.get(j - 1).compareTo(data.get(j)) > 0; j--) {
+ for (int i = start + 1; i < end; i++) {
+ for (int j = i; j > start && data.get(j - 1).compareTo(data.get(j)) > 0; j--) {
swap(data, j, j - 1);
}
}
@@ -731,61 +1090,86 @@ public class QuickSelect {
* @param rank rank position we are interested in (starting at 0)
*/
public static <T> void quickSelect(List<? extends T> data, Comparator<? super T> comparator, int start, int end, int rank) {
- while(true) {
+ while (true) {
// Optimization for small arrays
// This also ensures a minimum size below
- if(start + SMALL > end) {
+ if (start + SMALL > end) {
insertionSort(data, comparator, start, end);
return;
}
- // Pick pivot from three candidates: start, middle, end
- // Since we compare them, we can also just "bubble sort" them.
- final int middle = (start + end) >> 1;
- if(comparator.compare(data.get(start), data.get(middle)) > 0) {
- swap(data, start, middle);
+ // Best of 5 pivot picking:
+ // Choose pivots by looking at five candidates.
+ final int len = end - start;
+ final int seventh = (len >> 3) + (len >> 6) + 1;
+ final int m3 = (start + end) >> 1; // middle
+ final int m2 = m3 - seventh;
+ final int m1 = m2 - seventh;
+ final int m4 = m3 + seventh;
+ final int m5 = m4 + seventh;
+
+ // Explicit (and optimal) sorting network for 5 elements
+ // See Knuth for details.
+ if (comparator.compare(data.get(m1), data.get(m2)) > 0) {
+ swap(data, m1, m2);
+ }
+ if (comparator.compare(data.get(m1), data.get(m3)) > 0) {
+ swap(data, m1, m3);
+ }
+ if (comparator.compare(data.get(m2), data.get(m3)) > 0) {
+ swap(data, m2, m3);
+ }
+ if (comparator.compare(data.get(m4), data.get(m5)) > 0) {
+ swap(data, m4, m5);
}
- if(comparator.compare(data.get(start), data.get(end - 1)) > 0) {
- swap(data, start, end - 1);
+ if (comparator.compare(data.get(m1), data.get(m4)) > 0) {
+ swap(data, m1, m4);
}
- if(comparator.compare(data.get(middle), data.get(end - 1)) > 0) {
- swap(data, middle, end - 1);
+ if (comparator.compare(data.get(m3), data.get(m4)) > 0) {
+ swap(data, m3, m4);
+ }
+ if (comparator.compare(data.get(m2), data.get(m5)) > 0) {
+ swap(data, m2, m5);
+ }
+ if (comparator.compare(data.get(m2), data.get(m3)) > 0) {
+ swap(data, m2, m3);
+ }
+ if (comparator.compare(data.get(m4), data.get(m5)) > 0) {
+ swap(data, m4, m5);
}
- // TODO: use more candidates for larger arrays?
- final T pivot = data.get(middle);
+ int best = bestPivot(rank, m1, m2, m3, m4, m5);
+ final T pivot = data.get(best);
// Move middle element out of the way, just before end
// (Since we already know that "end" is bigger)
- swap(data, middle, end - 2);
+ swap(data, best, end - 1);
// Begin partitioning
- int i = start + 1, j = end - 3;
+ int i = start, j = end - 2;
// This is classic quicksort stuff
- while(true) {
- while(comparator.compare(data.get(i), pivot) <= 0 && i <= j) {
+ while (true) {
+ while (i <= j && comparator.compare(data.get(i), pivot) <= 0) {
i++;
}
- while(comparator.compare(data.get(j), pivot) >= 0 && j >= i) {
+ while (j >= i && comparator.compare(data.get(j), pivot) >= 0) {
j--;
}
- if(i >= j) {
+ if (i >= j) {
break;
}
swap(data, i, j);
}
// Move pivot (former middle element) back into the appropriate place
- swap(data, i, end - 2);
+ swap(data, i, end - 1);
// In contrast to quicksort, we only need to recurse into the half we are
// interested in. Instead of recursion we now use iteration.
- if(rank < i) {
+ if (rank < i) {
end = i;
- }
- else if(rank > i) {
+ } else if (rank > i) {
start = i + 1;
- }
- else {
+ } else {
break;
}
} // Loop until rank==i
@@ -800,8 +1184,8 @@ public class QuickSelect {
* @param end Interval end
*/
private static <T> void insertionSort(List<T> data, Comparator<? super T> comparator, int start, int end) {
- for(int i = start + 1; i < end; i++) {
- for(int j = i; j > start && comparator.compare(data.get(j - 1), data.get(j)) > 0; j--) {
+ for (int i = start + 1; i < end; i++) {
+ for (int j = i; j > start && comparator.compare(data.get(j - 1), data.get(j)) > 0; j--) {
swap(data, j, j - 1);
}
}
@@ -882,7 +1266,7 @@ public class QuickSelect {
* @param data Data to process
* @param comparator Comparator to use
* @param begin Begin of valid values
- * @param end End of valid values (inclusive!)
+ * @param end End of valid values (exclusive)
* @param quant Quantile to compute
* @return Value at quantile
*/
@@ -904,93 +1288,132 @@ public class QuickSelect {
* @param data Data to process
* @param comparator Comparator to use
* @param start Interval start
- * @param end Interval end (inclusive)
+ * @param end Interval end (exclusive)
* @param rank rank position we are interested in (starting at 0)
*/
public static void quickSelect(ArrayModifiableDBIDs data, Comparator<? super DBIDRef> comparator, int start, int end, int rank) {
- while(true) {
+ DBIDArrayIter refi = data.iter(), refj = data.iter(), pivot = data.iter();
+ while (true) {
// Optimization for small arrays
// This also ensures a minimum size below
- if(start + SMALL > end) {
- insertionSort(data, comparator, start, end);
+ if (start + SMALL > end) {
+ insertionSort(data, comparator, start, end, refi, refj);
return;
}
- // Pick pivot from three candidates: start, middle, end
- // Since we compare them, we can also just "bubble sort" them.
- final int middle = (start + end) >> 1;
- if(comparator.compare(data.get(start), data.get(middle)) > 0) {
- data.swap(start, middle);
+ // Best of 5 pivot picking:
+ // Choose pivots by looking at five candidates.
+ final int len = end - start;
+ final int seventh = (len >> 3) + (len >> 6) + 1;
+ final int m3 = (start + end) >> 1; // middle
+ final int m2 = m3 - seventh;
+ final int m1 = m2 - seventh;
+ final int m4 = m3 + seventh;
+ final int m5 = m4 + seventh;
+
+ // Explicit (and optimal) sorting network for 5 elements
+ // See Knuth for details.
+ if (compare(refi, m1, refj, m2, comparator) > 0) {
+ data.swap(m1, m2);
+ }
+ if (compare(refi, m1, refj, m3, comparator) > 0) {
+ data.swap(m1, m3);
+ }
+ if (compare(refi, m2, refj, m3, comparator) > 0) {
+ data.swap(m2, m3);
+ }
+ if (compare(refi, m4, refj, m5, comparator) > 0) {
+ data.swap(m4, m5);
}
- if(comparator.compare(data.get(start), data.get(end - 1)) > 0) {
- data.swap(start, end - 1);
+ if (compare(refi, m1, refj, m4, comparator) > 0) {
+ data.swap(m1, m4);
}
- if(comparator.compare(data.get(middle), data.get(end - 1)) > 0) {
- data.swap(middle, end - 1);
+ if (compare(refi, m3, refj, m4, comparator) > 0) {
+ data.swap(m3, m4);
+ }
+ if (compare(refi, m2, refj, m5, comparator) > 0) {
+ data.swap(m2, m5);
+ }
+ if (compare(refi, m2, refj, m3, comparator) > 0) {
+ data.swap(m2, m3);
+ }
+ if (compare(refi, m4, refj, m5, comparator) > 0) {
+ data.swap(m4, m5);
}
- // TODO: use more candidates for larger arrays?
- final DBID pivot = data.get(middle);
- // Move middle element out of the way, just before end
- // (Since we already know that "end" is bigger)
- data.swap(middle, end - 2);
+ int best = bestPivot(rank, m1, m2, m3, m4, m5);
+ // Move middle element out of the way.
+ data.swap(best, end - 1);
+ pivot.seek(end - 1);
// Begin partitioning
- int i = start + 1, j = end - 3;
- DBIDArrayIter refi = data.iter(), refj = data.iter();
+ int i = start, j = end - 3;
refi.seek(i);
refj.seek(j);
// This is classic quicksort stuff
- while(true) {
- while(comparator.compare(refi, pivot) <= 0 && i <= j) {
+ while (true) {
+ while (i <= j && comparator.compare(refi, pivot) <= 0) {
i++;
refi.advance();
}
- while(comparator.compare(refj, pivot) >= 0 && j >= i) {
+ while (j >= i && comparator.compare(refj, pivot) >= 0) {
j--;
refj.retract();
}
- if(i >= j) {
+ if (i >= j) {
break;
}
data.swap(i, j);
}
// Move pivot (former middle element) back into the appropriate place
- data.swap(i, end - 2);
+ data.swap(i, end - 1);
// In contrast to quicksort, we only need to recurse into the half we are
// interested in. Instead of recursion we now use iteration.
- if(rank < i) {
+ if (rank < i) {
end = i;
- }
- else if(rank > i) {
+ } else if (rank > i) {
start = i + 1;
- }
- else {
+ } else {
break;
}
} // Loop until rank==i
}
/**
+ * Compare two elements.
+ *
+ * @param i1 First scratch variable
+ * @param p1 Value for first
+ * @param i2 Second scratch variable
+ * @param p2 Value for second
+ * @param comp Comparator
+ * @return Comparison result
+ */
+ private static int compare(DBIDArrayIter i1, int p1, DBIDArrayIter i2, int p2, Comparator<? super DBIDRef> comp) {
+ i1.seek(p1);
+ i2.seek(p2);
+ return comp.compare(i1, i2);
+ }
+
+ /**
* Sort a small array using repetitive insertion sort.
*
* @param data Data to sort
* @param start Interval start
* @param end Interval end
*/
- private static void insertionSort(ArrayModifiableDBIDs data, Comparator<? super DBIDRef> comparator, int start, int end) {
- DBIDArrayIter iter1 = data.iter(), iter2 = data.iter();
- for(int i = start + 1; i < end; i++) {
- iter1.seek(i - 1);
- iter2.seek(i);
- for(int j = i; j > start; j--, iter1.retract(), iter2.retract()) {
- if(comparator.compare(iter1, iter2) > 0) {
+ private static void insertionSort(ArrayModifiableDBIDs data, Comparator<? super DBIDRef> comparator, int start, int end, DBIDArrayIter iter1, DBIDArrayIter iter2) {
+ for (int i = start + 1; i < end; i++) {
+ for (int j = i; j > start; j--) {
+ iter1.seek(j - 1);
+ iter2.seek(j);
+ if (comparator.compare(iter1, iter2) <= 0) {
break;
}
data.swap(j, j - 1);
}
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ArrayAdapter.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ArrayAdapter.java
index 969d068d..2c5eeed1 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ArrayAdapter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ArrayAdapter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ArrayDBIDsAdapter.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ArrayDBIDsAdapter.java
index 5b1b92b5..da831471 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ArrayDBIDsAdapter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ArrayDBIDsAdapter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ArrayLikeUtil.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ArrayLikeUtil.java
index a08feb1a..8fab6f2b 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ArrayLikeUtil.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ArrayLikeUtil.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,6 +27,7 @@ import java.util.List;
import de.lmu.ifi.dbs.elki.data.FeatureVector;
import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
/**
* Utility class that allows plug-in use of various "array-like" types such as
@@ -42,17 +43,17 @@ public final class ArrayLikeUtil {
/**
* Static instance for lists.
*/
- private static final ListArrayAdapter<Object> LISTADAPTER = new ListArrayAdapter<Object>();
+ private static final ListArrayAdapter<Object> LISTADAPTER = new ListArrayAdapter<>();
/**
* Static instance for lists of numbers.
*/
- private static final NumberListArrayAdapter<Number> NUMBERLISTADAPTER = new NumberListArrayAdapter<Number>();
+ private static final NumberListArrayAdapter<Number> NUMBERLISTADAPTER = new NumberListArrayAdapter<>();
/**
* Static instance.
*/
- private static final IdentityArrayAdapter<?> IDENTITYADAPTER = new IdentityArrayAdapter<Object>();
+ private static final IdentityArrayAdapter<?> IDENTITYADAPTER = new IdentityArrayAdapter<>();
/**
* Static instance.
@@ -83,7 +84,12 @@ public final class ArrayLikeUtil {
* Use ArrayDBIDs as array.
*/
public static final ArrayDBIDsAdapter ARRAYDBIDADAPTER = new ArrayDBIDsAdapter();
-
+
+ /**
+ * Adapter for vectors.
+ */
+ public static final NumberArrayAdapter<Double, Vector> VECTORADAPTER = new VectorAdapter();
+
/**
* Fake constructor. Do not instantiate!
*/
@@ -169,9 +175,9 @@ public final class ArrayLikeUtil {
final int size = adapter.size(array);
int index = 0;
double max = adapter.getDouble(array, 0);
- for(int i = 1; i < size; i++) {
+ for (int i = 1; i < size; i++) {
double val = adapter.getDouble(array, i);
- if(val > max) {
+ if (val > max) {
max = val;
index = i;
}
@@ -199,8 +205,11 @@ public final class ArrayLikeUtil {
* @return primitive double array
*/
public static <A> double[] toPrimitiveDoubleArray(A array, NumberArrayAdapter<?, ? super A> adapter) {
+ if (adapter == DOUBLEARRAYADAPTER) {
+ return ((double[]) array).clone();
+ }
double[] ret = new double[adapter.size(array)];
- for(int i = 0; i < ret.length; i++) {
+ for (int i = 0; i < ret.length; i++) {
ret[i] = adapter.getDouble(array, i);
}
return ret;
@@ -234,8 +243,11 @@ public final class ArrayLikeUtil {
* @return primitive float array
*/
public static <A> float[] toPrimitiveFloatArray(A array, NumberArrayAdapter<?, ? super A> adapter) {
+ if (adapter == FLOATARRAYADAPTER) {
+ return ((float[]) array).clone();
+ }
float[] ret = new float[adapter.size(array)];
- for(int i = 0; i < ret.length; i++) {
+ for (int i = 0; i < ret.length; i++) {
ret[i] = adapter.getFloat(array, i);
}
return ret;
@@ -260,4 +272,39 @@ public final class ArrayLikeUtil {
public static <N extends Number> float[] toPrimitiveFloatArray(NumberVector<N> obj) {
return toPrimitiveFloatArray(obj, numberVectorAdapter(obj));
}
-} \ No newline at end of file
+
+ /**
+ * Convert a numeric array-like to a <code>int[]</code>.
+ *
+ * @param array Array-like
+ * @param adapter Adapter
+ * @return primitive double array
+ */
+ public static <A> int[] toPrimitiveIntegerArray(A array, NumberArrayAdapter<?, ? super A> adapter) {
+ int[] ret = new int[adapter.size(array)];
+ for (int i = 0; i < ret.length; i++) {
+ ret[i] = adapter.getInteger(array, i);
+ }
+ return ret;
+ }
+
+ /**
+ * Convert a list of numbers to <code>int[]</code>.
+ *
+ * @param array List of numbers
+ * @return double array
+ */
+ public static int[] toPrimitiveIntegerArray(List<? extends Number> array) {
+ return toPrimitiveIntegerArray(array, NUMBERLISTADAPTER);
+ }
+
+ /**
+ * Convert a number vector to <code>int[]</code>.
+ *
+ * @param obj Object to convert
+ * @return primitive double array
+ */
+ public static <N extends Number> int[] toPrimitiveIntegerArray(NumberVector<N> obj) {
+ return toPrimitiveIntegerArray(obj, numberVectorAdapter(obj));
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/DoubleArrayAdapter.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/DoubleArrayAdapter.java
index 117f3845..0e31a61a 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/DoubleArrayAdapter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/DoubleArrayAdapter.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ExtendedArray.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ExtendedArray.java
index 491c4f95..3af14982 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ExtendedArray.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ExtendedArray.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -91,6 +91,6 @@ public class ExtendedArray<T> implements ArrayAdapter<T, ExtendedArray<T>> {
*/
@SuppressWarnings("unchecked")
public static <T, A> ExtendedArray<T> extend(A array, ArrayAdapter<T, A> getter, T extra) {
- return new ExtendedArray<T>(array, (ArrayAdapter<T, Object>) getter, extra);
+ return new ExtendedArray<>(array, (ArrayAdapter<T, Object>) getter, extra);
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/FeatureVectorAdapter.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/FeatureVectorAdapter.java
index 38b662e8..deb5aafc 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/FeatureVectorAdapter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/FeatureVectorAdapter.java
@@ -6,7 +6,7 @@ import de.lmu.ifi.dbs.elki.data.FeatureVector;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/FloatArrayAdapter.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/FloatArrayAdapter.java
index ae501039..831dc929 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/FloatArrayAdapter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/FloatArrayAdapter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/IdentityArrayAdapter.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/IdentityArrayAdapter.java
index 0c6e03dd..dfde46b7 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/IdentityArrayAdapter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/IdentityArrayAdapter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ListArrayAdapter.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ListArrayAdapter.java
index cba1e706..729dfab8 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ListArrayAdapter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ListArrayAdapter.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/NumberArrayAdapter.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/NumberArrayAdapter.java
index 1dc823b1..5ebbcb0d 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/NumberArrayAdapter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/NumberArrayAdapter.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/NumberListArrayAdapter.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/NumberListArrayAdapter.java
index 89a4e3d6..a2606347 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/NumberListArrayAdapter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/NumberListArrayAdapter.java
@@ -6,7 +6,7 @@ import java.util.List;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/NumberVectorAdapter.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/NumberVectorAdapter.java
index fd1e6636..5e674026 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/NumberVectorAdapter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/NumberVectorAdapter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/SingleSubsetArrayAdapter.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/SingleSubsetArrayAdapter.java
index d7483e4d..941c6245 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/SingleSubsetArrayAdapter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/SingleSubsetArrayAdapter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/SubsetArrayAdapter.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/SubsetArrayAdapter.java
index c607759f..746647cc 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/SubsetArrayAdapter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/SubsetArrayAdapter.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/SubsetNumberArrayAdapter.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/SubsetNumberArrayAdapter.java
index 6719b60e..c394f9b7 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/SubsetNumberArrayAdapter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/SubsetNumberArrayAdapter.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/TDoubleListAdapter.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/TDoubleListAdapter.java
index cee393ac..a52ff15e 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/TDoubleListAdapter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/TDoubleListAdapter.java
@@ -6,7 +6,7 @@ import gnu.trove.list.TDoubleList;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/VectorAdapter.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/VectorAdapter.java
new file mode 100644
index 00000000..0bb979e9
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/VectorAdapter.java
@@ -0,0 +1,85 @@
+package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
+
+/**
+ * Adapter to use a feature vector as an array of features.
+ *
+ * Use the static instance from {@link ArrayLikeUtil}!
+ *
+ * @author Erich Schubert
+ */
+public class VectorAdapter implements NumberArrayAdapter<Double, Vector> {
+ /**
+ * Constructor.
+ *
+ * Use the static instance from {@link ArrayLikeUtil}!
+ */
+ protected VectorAdapter() {
+ super();
+ }
+
+ @Override
+ public int size(Vector array) {
+ return array.getDimensionality();
+ }
+
+ @Override
+ @Deprecated
+ public Double get(Vector array, int off) throws IndexOutOfBoundsException {
+ return array.getValue(off + 1);
+ }
+
+ @Override
+ public double getDouble(Vector array, int off) throws IndexOutOfBoundsException {
+ return array.doubleValue(off);
+ }
+
+ @Override
+ public float getFloat(Vector array, int off) throws IndexOutOfBoundsException {
+ return array.floatValue(off);
+ }
+
+ @Override
+ public int getInteger(Vector array, int off) throws IndexOutOfBoundsException {
+ return array.intValue(off);
+ }
+
+ @Override
+ public short getShort(Vector array, int off) throws IndexOutOfBoundsException {
+ return array.shortValue(off);
+ }
+
+ @Override
+ public long getLong(Vector array, int off) throws IndexOutOfBoundsException {
+ return array.longValue(off);
+ }
+
+ @Override
+ public byte getByte(Vector array, int off) throws IndexOutOfBoundsException {
+ return array.byteValue(off);
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/package-info.java
index 55627df4..33058cf4 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arrays/IntegerArrayQuickSort.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arrays/IntegerArrayQuickSort.java
index a0c93997..eaf47738 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arrays/IntegerArrayQuickSort.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arrays/IntegerArrayQuickSort.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.arrays;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arrays/IntegerComparator.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arrays/IntegerComparator.java
index 51164425..0ccd47db 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arrays/IntegerComparator.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arrays/IntegerComparator.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.arrays;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arrays/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arrays/package-info.java
index 3db78032..874a6d44 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arrays/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arrays/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/AbstractHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/AbstractHeap.java
deleted file mode 100644
index b6f098e6..00000000
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/AbstractHeap.java
+++ /dev/null
@@ -1,103 +0,0 @@
-package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
-
-/*
- This file is part of ELKI:
- Environment for Developing KDD-Applications Supported by Index-Structures
-
- Copyright (C) 2012
- Ludwig-Maximilians-Universität München
- Lehr- und Forschungseinheit für Datenbanksysteme
- ELKI Development Team
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/**
- * Abstract base class for heaps.
- *
- * @author Erich Schubert
- */
-public class AbstractHeap {
- /**
- * Default initial capacity
- */
- public static final int DEFAULT_INITIAL_CAPACITY = 11;
-
- /**
- * Current number of objects
- */
- public int size = 0;
-
- /**
- * Indicate up to where the heap is valid
- */
- public int validSize = 0;
-
- /**
- * (Structural) modification counter. Used to invalidate iterators.
- */
- public int modCount = 0;
-
- /**
- * Constructor.
- */
- public AbstractHeap() {
- super();
- }
-
- /**
- * Query the size
- *
- * @return Size
- */
- public int size() {
- return this.size;
- }
-
- /**
- * Delete all elements from the heap.
- */
- public void clear() {
- this.size = 0;
- this.validSize = -1;
- heapModified();
- }
-
- /**
- * Test whether we need to resize to have the requested capacity.
- *
- * @param requiredSize required capacity
- * @param capacity Current capacity
- * @return new capacity
- */
- protected final int desiredSize(int requiredSize, int capacity) {
- // Double until 64, then increase by 50% each time.
- int newCapacity = ((capacity < 64) ? ((capacity + 1) * 2) : ((capacity / 2) * 3));
- // overflow?
- if (newCapacity < 0) {
- throw new OutOfMemoryError();
- }
- if (requiredSize > newCapacity) {
- newCapacity = requiredSize;
- }
- return newCapacity;
- }
-
- /**
- * Called at the end of each heap modification.
- */
- protected void heapModified() {
- modCount++;
- }
-}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/ComparableMaxHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/ComparableMaxHeap.java
index ab8ef1bb..222fe83a 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/ComparableMaxHeap.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/ComparableMaxHeap.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,41 +23,409 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import java.util.Arrays;
+import java.util.ConcurrentModificationException;
+
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+
/**
- * Basic in-memory heap structure.
+ * Advanced priority queue class, based on a binary heap (for small sizes),
+ * which will for larger heaps be accompanied by a 4-ary heap (attached below
+ * the root of the two-ary heap, making the root actually 3-ary).
+ *
+ * This code was automatically instantiated for the type: Comparable
+ *
+ * This combination was found to work quite well in benchmarks, but YMMV.
*
- * This heap is built lazily: if you first add many elements, then poll the
- * heap, it will be bulk-loaded in O(n) instead of iteratively built in O(n log
- * n). This is implemented via a simple validTo counter.
+ * Some other observations from benchmarking:
+ * <ul>
+ * <li>Bulk loading did not improve things</li>
+ * <li>Primitive heaps are substantially faster.</li>
+ * <li>Since an array in Java has an overhead of 12 bytes, odd-sized object and
+ * integer arrays are actually well aligned both for 2-ary and 4-ary heaps.</li>
+ * <li>Workload makes a huge difference. A load-once, poll-until-empty priority
+ * queue is something different than e.g. a top-k heap, which will see a lot of
+ * top element replacements.</li>
+ * <li>Random vs. increasing vs. decreasing vs. sawtooth insertion patterns for
+ * top-k make a difference.</li>
+ * <li>Different day, different benchmark results ...</li>
+ * </ul>
*
* @author Erich Schubert
+ *
+ * @apiviz.has UnsortedIter
+ * @param <K> Key type
*/
-public class ComparableMaxHeap<K extends Comparable<K>> extends ObjectHeap<K> {
+public class ComparableMaxHeap<K extends Comparable<? super K>> implements ObjectHeap<K> {
+ /**
+ * Base heap.
+ */
+ protected Comparable<Object>[] twoheap;
+
+ /**
+ * Extension heap.
+ */
+ protected Comparable<Object>[] fourheap;
+
+ /**
+ * Current size of heap.
+ */
+ protected int size;
+
+ /**
+ * (Structural) modification counter. Used to invalidate iterators.
+ */
+ protected int modCount = 0;
+
+ /**
+ * Maximum size of the 2-ary heap. A complete 2-ary heap has (2^k-1) elements.
+ */
+ private final static int TWO_HEAP_MAX_SIZE = (1 << 9) - 1;
+
+ /**
+ * Initial size of the 2-ary heap.
+ */
+ private final static int TWO_HEAP_INITIAL_SIZE = (1 << 5) - 1;
+
+ /**
+ * Initial size of 4-ary heap when initialized.
+ *
+ * 21 = 4-ary heap of height 2: 1 + 4 + 4*4
+ *
+ * 85 = 4-ary heap of height 3: 21 + 4*4*4
+ *
+ * 341 = 4-ary heap of height 4: 85 + 4*4*4*4
+ *
+ * Since we last grew by 255 (to 511), let's use 341.
+ */
+ private final static int FOUR_HEAP_INITIAL_SIZE = 341;
+
/**
- * Constructor with default capacity.
+ * Constructor, with default size.
*/
+ @SuppressWarnings("unchecked")
public ComparableMaxHeap() {
- super(DEFAULT_INITIAL_CAPACITY);
+ super();
+ Comparable<Object>[] twoheap = (Comparable<Object>[]) java.lang.reflect.Array.newInstance(Comparable.class, TWO_HEAP_INITIAL_SIZE);
+
+ this.twoheap = twoheap;
+ this.fourheap = null;
+ this.size = 0;
+ this.modCount = 0;
}
/**
- * Constructor with initial capacity.
+ * Constructor, with given minimum size.
*
- * @param size initial capacity
+ * @param minsize Minimum size
*/
- public ComparableMaxHeap(int size) {
- super(size);
+ @SuppressWarnings("unchecked")
+ public ComparableMaxHeap(int minsize) {
+ super();
+ if (minsize < TWO_HEAP_MAX_SIZE) {
+ final int size = MathUtil.nextPow2Int(minsize + 1) - 1;
+ Comparable<Object>[] twoheap = (Comparable<Object>[]) java.lang.reflect.Array.newInstance(Comparable.class, size);
+
+ this.twoheap = twoheap;
+ this.fourheap = null;
+ } else {
+ Comparable<Object>[] twoheap = (Comparable<Object>[]) java.lang.reflect.Array.newInstance(Comparable.class, TWO_HEAP_INITIAL_SIZE);
+ Comparable<Object>[] fourheap = (Comparable<Object>[]) java.lang.reflect.Array.newInstance(Comparable.class, minsize - TWO_HEAP_MAX_SIZE);
+ this.twoheap = twoheap;
+ this.fourheap = fourheap;
+ }
+ this.size = 0;
+ this.modCount = 0;
+ }
+
+ @Override
+ public void clear() {
+ size = 0;
+ ++modCount;
+ fourheap = null;
+ Arrays.fill(twoheap, null);
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return (size == 0);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public void add(K o) {
+ final Comparable<Object> co = (Comparable<Object>)o;
+ // System.err.println("Add: " + o);
+ if (size < TWO_HEAP_MAX_SIZE) {
+ if (size >= twoheap.length) {
+ // Grow by one layer.
+ twoheap = Arrays.copyOf(twoheap, twoheap.length + twoheap.length + 1);
+ }
+ final int twopos = size;
+ twoheap[twopos] = co;
+ ++size;
+ heapifyUp2(twopos, co);
+ ++modCount;
+ } else {
+ final int fourpos = size - TWO_HEAP_MAX_SIZE;
+ if (fourheap == null) {
+ fourheap = (Comparable<Object>[]) java.lang.reflect.Array.newInstance(Comparable.class, FOUR_HEAP_INITIAL_SIZE);
+ } else if (fourpos >= fourheap.length) {
+ // Grow extension heap by half.
+ fourheap = Arrays.copyOf(fourheap, fourheap.length + (fourheap.length >> 1));
+ }
+ fourheap[fourpos] = co;
+ ++size;
+ heapifyUp4(fourpos, co);
+ ++modCount;
+ }
+ }
+
+ @Override
+ public void add(K key, int max) {
+ if (size < max) {
+ add(key);
+ } else if (twoheap[0].compareTo(key) >= 0) {
+ replaceTopElement(key);
+ }
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public K replaceTopElement(K reinsert) {
+ final Comparable<Object> ret = twoheap[0];
+ heapifyDown((Comparable<Object>) reinsert);
+ ++modCount;
+ return (K)ret;
}
/**
- * Compare two objects
+ * Heapify-Up method for 2-ary heap.
*
- * @param o1 First object
- * @param o2 Second object
+ * @param twopos Position in 2-ary heap.
+ * @param cur Current object
*/
+ private void heapifyUp2(int twopos, Comparable<Object> cur) {
+ while (twopos > 0) {
+ final int parent = (twopos - 1) >>> 1;
+ Comparable<Object> par = twoheap[parent];
+ if (cur.compareTo(par) <= 0) {
+ break;
+ }
+ twoheap[twopos] = par;
+ twopos = parent;
+ }
+ twoheap[twopos] = cur;
+ }
+
+ /**
+ * Heapify-Up method for 4-ary heap.
+ *
+ * @param fourpos Position in 4-ary heap.
+ * @param cur Current object
+ */
+ private void heapifyUp4(int fourpos, Comparable<Object> cur) {
+ while (fourpos > 0) {
+ final int parent = (fourpos - 1) >> 2;
+ Comparable<Object> par = fourheap[parent];
+ if (cur.compareTo(par) <= 0) {
+ break;
+ }
+ fourheap[fourpos] = par;
+ fourpos = parent;
+ }
+ if (fourpos == 0 && twoheap[0].compareTo(cur) < 0) {
+ fourheap[0] = twoheap[0];
+ twoheap[0] = cur;
+ } else {
+ fourheap[fourpos] = cur;
+ }
+ }
+
@Override
@SuppressWarnings("unchecked")
- protected boolean comp(Object o1, Object o2) {
- return ((K) o1).compareTo((K) o2) < 0;
+ public K poll() {
+ final Comparable<Object> ret = twoheap[0];
+ --size;
+ // Replacement object:
+ if (size >= TWO_HEAP_MAX_SIZE) {
+ final int last = size - TWO_HEAP_MAX_SIZE;
+ final Comparable<Object> reinsert = fourheap[last];
+ fourheap[last] = null;
+ heapifyDown(reinsert);
+ } else if (size > 0) {
+ final Comparable<Object> reinsert = twoheap[size];
+ twoheap[size] = null;
+ heapifyDown(reinsert);
+ } else {
+ twoheap[0] = null;
+ }
+ ++modCount;
+ return (K)ret;
+ }
+
+ /**
+ * Invoke heapify-down for the root object.
+ *
+ * @param reinsert Object to insert.
+ */
+ private void heapifyDown(Comparable<Object> reinsert) {
+ if (size > TWO_HEAP_MAX_SIZE) {
+ // Special case: 3-ary situation.
+ final int best = (twoheap[1].compareTo(twoheap[2]) >= 0) ? 1 : 2;
+ if (fourheap[0].compareTo(twoheap[best]) > 0) {
+ twoheap[0] = fourheap[0];
+ heapifyDown4(0, reinsert);
+ } else {
+ twoheap[0] = twoheap[best];
+ heapifyDown2(best, reinsert);
+ }
+ return;
+ }
+ heapifyDown2(0, reinsert);
+ }
+
+ /**
+ * Heapify-Down for 2-ary heap.
+ *
+ * @param twopos Position in 2-ary heap.
+ * @param cur Current object
+ */
+ private void heapifyDown2(int twopos, Comparable<Object> cur) {
+ final int stop = Math.min(size, TWO_HEAP_MAX_SIZE) >>> 1;
+ while (twopos < stop) {
+ int bestchild = (twopos << 1) + 1;
+ Comparable<Object> best = twoheap[bestchild];
+ final int right = bestchild + 1;
+ if (right < size && best.compareTo(twoheap[right]) < 0) {
+ bestchild = right;
+ best = twoheap[right];
+ }
+ if (cur.compareTo(best) >= 0) {
+ break;
+ }
+ twoheap[twopos] = best;
+ twopos = bestchild;
+ }
+ twoheap[twopos] = cur;
+ }
+
+ /**
+ * Heapify-Down for 4-ary heap.
+ *
+ * @param fourpos Position in 4-ary heap.
+ * @param cur Current object
+ */
+ private void heapifyDown4(int fourpos, Comparable<Object> cur) {
+ final int stop = (size - TWO_HEAP_MAX_SIZE + 2) >>> 2;
+ while (fourpos < stop) {
+ final int child = (fourpos << 2) + 1;
+ Comparable<Object> best = fourheap[child];
+ int bestchild = child, candidate = child + 1, minsize = candidate + TWO_HEAP_MAX_SIZE;
+ if (size > minsize) {
+ Comparable<Object> nextchild = fourheap[candidate];
+ if (best.compareTo(nextchild) < 0) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+
+ minsize += 2;
+ if (size >= minsize) {
+ nextchild = fourheap[++candidate];
+ if (best.compareTo(nextchild) < 0) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+
+ if (size > minsize) {
+ nextchild = fourheap[++candidate];
+ if (best.compareTo(nextchild) < 0) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+ }
+ }
+ }
+ if (cur.compareTo(best) >= 0) {
+ break;
+ }
+ fourheap[fourpos] = best;
+ fourpos = bestchild;
+ }
+ fourheap[fourpos] = cur;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public K peek() {
+ return (K)twoheap[0];
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder buf = new StringBuilder();
+ buf.append(ComparableMaxHeap.class.getSimpleName()).append(" [");
+ for (UnsortedIter iter = new UnsortedIter(); iter.valid(); iter.advance()) {
+ buf.append(iter.get()).append(',');
+ }
+ buf.append(']');
+ return buf.toString();
+ }
+
+ @Override
+ public UnsortedIter unsortedIter() {
+ return new UnsortedIter();
+ }
+
+ /**
+ * Unsorted iterator - in heap order. Does not poll the heap.
+ *
+ * Use this class as follows:
+ *
+ * <pre>
+ * {@code
+ * for (ObjectHeap.UnsortedIter<K> iter = heap.unsortedIter(); iter.valid(); iter.next()) {
+ * doSomething(iter.get());
+ * }
+ * }
+ * </pre>
+ *
+ * @author Erich Schubert
+ */
+ private class UnsortedIter implements ObjectHeap.UnsortedIter<K> {
+ /**
+ * Iterator position.
+ */
+ protected int pos = 0;
+
+ /**
+ * Modification counter we were initialized at.
+ */
+ protected final int myModCount = modCount;
+
+ @Override
+ public boolean valid() {
+ if (modCount != myModCount) {
+ throw new ConcurrentModificationException();
+ }
+ return pos < size;
+ }
+
+ @Override
+ public void advance() {
+ pos++;
+ }
+
+ @SuppressWarnings("unchecked")
+
+ @Override
+ public K get() {
+ return (K)((pos < TWO_HEAP_MAX_SIZE) ? twoheap[pos] : fourheap[pos - TWO_HEAP_MAX_SIZE]);
+ }
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/ComparableMinHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/ComparableMinHeap.java
index 06d2cb32..3cc5a02f 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/ComparableMinHeap.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/ComparableMinHeap.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,41 +23,409 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import java.util.Arrays;
+import java.util.ConcurrentModificationException;
+
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+
/**
- * Basic in-memory heap structure.
+ * Advanced priority queue class, based on a binary heap (for small sizes),
+ * which will for larger heaps be accompanied by a 4-ary heap (attached below
+ * the root of the two-ary heap, making the root actually 3-ary).
+ *
+ * This code was automatically instantiated for the type: Comparable
+ *
+ * This combination was found to work quite well in benchmarks, but YMMV.
*
- * This heap is built lazily: if you first add many elements, then poll the
- * heap, it will be bulk-loaded in O(n) instead of iteratively built in O(n log
- * n). This is implemented via a simple validTo counter.
+ * Some other observations from benchmarking:
+ * <ul>
+ * <li>Bulk loading did not improve things</li>
+ * <li>Primitive heaps are substantially faster.</li>
+ * <li>Since an array in Java has an overhead of 12 bytes, odd-sized object and
+ * integer arrays are actually well aligned both for 2-ary and 4-ary heaps.</li>
+ * <li>Workload makes a huge difference. A load-once, poll-until-empty priority
+ * queue is something different than e.g. a top-k heap, which will see a lot of
+ * top element replacements.</li>
+ * <li>Random vs. increasing vs. decreasing vs. sawtooth insertion patterns for
+ * top-k make a difference.</li>
+ * <li>Different day, different benchmark results ...</li>
+ * </ul>
*
* @author Erich Schubert
+ *
+ * @apiviz.has UnsortedIter
+ * @param <K> Key type
*/
-public class ComparableMinHeap<K extends Comparable<K>> extends ObjectHeap<K> {
+public class ComparableMinHeap<K extends Comparable<? super K>> implements ObjectHeap<K> {
+ /**
+ * Base heap.
+ */
+ protected Comparable<Object>[] twoheap;
+
+ /**
+ * Extension heap.
+ */
+ protected Comparable<Object>[] fourheap;
+
+ /**
+ * Current size of heap.
+ */
+ protected int size;
+
+ /**
+ * (Structural) modification counter. Used to invalidate iterators.
+ */
+ protected int modCount = 0;
+
+ /**
+ * Maximum size of the 2-ary heap. A complete 2-ary heap has (2^k-1) elements.
+ */
+ private final static int TWO_HEAP_MAX_SIZE = (1 << 9) - 1;
+
+ /**
+ * Initial size of the 2-ary heap.
+ */
+ private final static int TWO_HEAP_INITIAL_SIZE = (1 << 5) - 1;
+
+ /**
+ * Initial size of 4-ary heap when initialized.
+ *
+ * 21 = 4-ary heap of height 2: 1 + 4 + 4*4
+ *
+ * 85 = 4-ary heap of height 3: 21 + 4*4*4
+ *
+ * 341 = 4-ary heap of height 4: 85 + 4*4*4*4
+ *
+ * Since we last grew by 255 (to 511), let's use 341.
+ */
+ private final static int FOUR_HEAP_INITIAL_SIZE = 341;
+
/**
- * Constructor with default capacity.
+ * Constructor, with default size.
*/
+ @SuppressWarnings("unchecked")
public ComparableMinHeap() {
- super(DEFAULT_INITIAL_CAPACITY);
+ super();
+ Comparable<Object>[] twoheap = (Comparable<Object>[]) java.lang.reflect.Array.newInstance(Comparable.class, TWO_HEAP_INITIAL_SIZE);
+
+ this.twoheap = twoheap;
+ this.fourheap = null;
+ this.size = 0;
+ this.modCount = 0;
}
/**
- * Constructor with initial capacity.
+ * Constructor, with given minimum size.
*
- * @param size initial capacity
+ * @param minsize Minimum size
*/
- public ComparableMinHeap(int size) {
- super(size);
+ @SuppressWarnings("unchecked")
+ public ComparableMinHeap(int minsize) {
+ super();
+ if (minsize < TWO_HEAP_MAX_SIZE) {
+ final int size = MathUtil.nextPow2Int(minsize + 1) - 1;
+ Comparable<Object>[] twoheap = (Comparable<Object>[]) java.lang.reflect.Array.newInstance(Comparable.class, size);
+
+ this.twoheap = twoheap;
+ this.fourheap = null;
+ } else {
+ Comparable<Object>[] twoheap = (Comparable<Object>[]) java.lang.reflect.Array.newInstance(Comparable.class, TWO_HEAP_INITIAL_SIZE);
+ Comparable<Object>[] fourheap = (Comparable<Object>[]) java.lang.reflect.Array.newInstance(Comparable.class, minsize - TWO_HEAP_MAX_SIZE);
+ this.twoheap = twoheap;
+ this.fourheap = fourheap;
+ }
+ this.size = 0;
+ this.modCount = 0;
+ }
+
+ @Override
+ public void clear() {
+ size = 0;
+ ++modCount;
+ fourheap = null;
+ Arrays.fill(twoheap, null);
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return (size == 0);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public void add(K o) {
+ final Comparable<Object> co = (Comparable<Object>)o;
+ // System.err.println("Add: " + o);
+ if (size < TWO_HEAP_MAX_SIZE) {
+ if (size >= twoheap.length) {
+ // Grow by one layer.
+ twoheap = Arrays.copyOf(twoheap, twoheap.length + twoheap.length + 1);
+ }
+ final int twopos = size;
+ twoheap[twopos] = co;
+ ++size;
+ heapifyUp2(twopos, co);
+ ++modCount;
+ } else {
+ final int fourpos = size - TWO_HEAP_MAX_SIZE;
+ if (fourheap == null) {
+ fourheap = (Comparable<Object>[]) java.lang.reflect.Array.newInstance(Comparable.class, FOUR_HEAP_INITIAL_SIZE);
+ } else if (fourpos >= fourheap.length) {
+ // Grow extension heap by half.
+ fourheap = Arrays.copyOf(fourheap, fourheap.length + (fourheap.length >> 1));
+ }
+ fourheap[fourpos] = co;
+ ++size;
+ heapifyUp4(fourpos, co);
+ ++modCount;
+ }
+ }
+
+ @Override
+ public void add(K key, int max) {
+ if (size < max) {
+ add(key);
+ } else if (twoheap[0].compareTo(key) <= 0) {
+ replaceTopElement(key);
+ }
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public K replaceTopElement(K reinsert) {
+ final Comparable<Object> ret = twoheap[0];
+ heapifyDown((Comparable<Object>) reinsert);
+ ++modCount;
+ return (K)ret;
}
/**
- * Compare two objects
+ * Heapify-Up method for 2-ary heap.
*
- * @param o1 First object
- * @param o2 Second object
+ * @param twopos Position in 2-ary heap.
+ * @param cur Current object
*/
+ private void heapifyUp2(int twopos, Comparable<Object> cur) {
+ while (twopos > 0) {
+ final int parent = (twopos - 1) >>> 1;
+ Comparable<Object> par = twoheap[parent];
+ if (cur.compareTo(par) >= 0) {
+ break;
+ }
+ twoheap[twopos] = par;
+ twopos = parent;
+ }
+ twoheap[twopos] = cur;
+ }
+
+ /**
+ * Heapify-Up method for 4-ary heap.
+ *
+ * @param fourpos Position in 4-ary heap.
+ * @param cur Current object
+ */
+ private void heapifyUp4(int fourpos, Comparable<Object> cur) {
+ while (fourpos > 0) {
+ final int parent = (fourpos - 1) >> 2;
+ Comparable<Object> par = fourheap[parent];
+ if (cur.compareTo(par) >= 0) {
+ break;
+ }
+ fourheap[fourpos] = par;
+ fourpos = parent;
+ }
+ if (fourpos == 0 && twoheap[0].compareTo(cur) > 0) {
+ fourheap[0] = twoheap[0];
+ twoheap[0] = cur;
+ } else {
+ fourheap[fourpos] = cur;
+ }
+ }
+
@Override
@SuppressWarnings("unchecked")
- protected boolean comp(Object o1, Object o2) {
- return ((K) o1).compareTo((K) o2) > 0;
+ public K poll() {
+ final Comparable<Object> ret = twoheap[0];
+ --size;
+ // Replacement object:
+ if (size >= TWO_HEAP_MAX_SIZE) {
+ final int last = size - TWO_HEAP_MAX_SIZE;
+ final Comparable<Object> reinsert = fourheap[last];
+ fourheap[last] = null;
+ heapifyDown(reinsert);
+ } else if (size > 0) {
+ final Comparable<Object> reinsert = twoheap[size];
+ twoheap[size] = null;
+ heapifyDown(reinsert);
+ } else {
+ twoheap[0] = null;
+ }
+ ++modCount;
+ return (K)ret;
+ }
+
+ /**
+ * Invoke heapify-down for the root object.
+ *
+ * @param reinsert Object to insert.
+ */
+ private void heapifyDown(Comparable<Object> reinsert) {
+ if (size > TWO_HEAP_MAX_SIZE) {
+ // Special case: 3-ary situation.
+ final int best = (twoheap[1].compareTo(twoheap[2]) <= 0) ? 1 : 2;
+ if (fourheap[0].compareTo(twoheap[best]) < 0) {
+ twoheap[0] = fourheap[0];
+ heapifyDown4(0, reinsert);
+ } else {
+ twoheap[0] = twoheap[best];
+ heapifyDown2(best, reinsert);
+ }
+ return;
+ }
+ heapifyDown2(0, reinsert);
+ }
+
+ /**
+ * Heapify-Down for 2-ary heap.
+ *
+ * @param twopos Position in 2-ary heap.
+ * @param cur Current object
+ */
+ private void heapifyDown2(int twopos, Comparable<Object> cur) {
+ final int stop = Math.min(size, TWO_HEAP_MAX_SIZE) >>> 1;
+ while (twopos < stop) {
+ int bestchild = (twopos << 1) + 1;
+ Comparable<Object> best = twoheap[bestchild];
+ final int right = bestchild + 1;
+ if (right < size && best.compareTo(twoheap[right]) > 0) {
+ bestchild = right;
+ best = twoheap[right];
+ }
+ if (cur.compareTo(best) <= 0) {
+ break;
+ }
+ twoheap[twopos] = best;
+ twopos = bestchild;
+ }
+ twoheap[twopos] = cur;
+ }
+
+ /**
+ * Heapify-Down for 4-ary heap.
+ *
+ * @param fourpos Position in 4-ary heap.
+ * @param cur Current object
+ */
+ private void heapifyDown4(int fourpos, Comparable<Object> cur) {
+ final int stop = (size - TWO_HEAP_MAX_SIZE + 2) >>> 2;
+ while (fourpos < stop) {
+ final int child = (fourpos << 2) + 1;
+ Comparable<Object> best = fourheap[child];
+ int bestchild = child, candidate = child + 1, minsize = candidate + TWO_HEAP_MAX_SIZE;
+ if (size > minsize) {
+ Comparable<Object> nextchild = fourheap[candidate];
+ if (best.compareTo(nextchild) > 0) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+
+ minsize += 2;
+ if (size >= minsize) {
+ nextchild = fourheap[++candidate];
+ if (best.compareTo(nextchild) > 0) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+
+ if (size > minsize) {
+ nextchild = fourheap[++candidate];
+ if (best.compareTo(nextchild) > 0) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+ }
+ }
+ }
+ if (cur.compareTo(best) <= 0) {
+ break;
+ }
+ fourheap[fourpos] = best;
+ fourpos = bestchild;
+ }
+ fourheap[fourpos] = cur;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public K peek() {
+ return (K)twoheap[0];
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder buf = new StringBuilder();
+ buf.append(ComparableMinHeap.class.getSimpleName()).append(" [");
+ for (UnsortedIter iter = new UnsortedIter(); iter.valid(); iter.advance()) {
+ buf.append(iter.get()).append(',');
+ }
+ buf.append(']');
+ return buf.toString();
+ }
+
+ @Override
+ public UnsortedIter unsortedIter() {
+ return new UnsortedIter();
+ }
+
+ /**
+ * Unsorted iterator - in heap order. Does not poll the heap.
+ *
+ * Use this class as follows:
+ *
+ * <pre>
+ * {@code
+ * for (ObjectHeap.UnsortedIter<K> iter = heap.unsortedIter(); iter.valid(); iter.next()) {
+ * doSomething(iter.get());
+ * }
+ * }
+ * </pre>
+ *
+ * @author Erich Schubert
+ */
+ private class UnsortedIter implements ObjectHeap.UnsortedIter<K> {
+ /**
+ * Iterator position.
+ */
+ protected int pos = 0;
+
+ /**
+ * Modification counter we were initialized at.
+ */
+ protected final int myModCount = modCount;
+
+ @Override
+ public boolean valid() {
+ if (modCount != myModCount) {
+ throw new ConcurrentModificationException();
+ }
+ return pos < size;
+ }
+
+ @Override
+ public void advance() {
+ pos++;
+ }
+
+ @SuppressWarnings("unchecked")
+
+ @Override
+ public K get() {
+ return (K)((pos < TWO_HEAP_MAX_SIZE) ? twoheap[pos] : fourheap[pos - TWO_HEAP_MAX_SIZE]);
+ }
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/ComparatorMaxHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/ComparatorMaxHeap.java
new file mode 100644
index 00000000..7b660d31
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/ComparatorMaxHeap.java
@@ -0,0 +1,440 @@
+package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.Arrays;
+import java.util.ConcurrentModificationException;
+
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+
+/**
+ * Advanced priority queue class, based on a binary heap (for small sizes),
+ * which will for larger heaps be accompanied by a 4-ary heap (attached below
+ * the root of the two-ary heap, making the root actually 3-ary).
+ *
+ * This code was automatically instantiated for the type: Comparator
+ *
+ * This combination was found to work quite well in benchmarks, but YMMV.
+ *
+ * Some other observations from benchmarking:
+ * <ul>
+ * <li>Bulk loading did not improve things</li>
+ * <li>Primitive heaps are substantially faster.</li>
+ * <li>Since an array in Java has an overhead of 12 bytes, odd-sized object and
+ * integer arrays are actually well aligned both for 2-ary and 4-ary heaps.</li>
+ * <li>Workload makes a huge difference. A load-once, poll-until-empty priority
+ * queue is something different than e.g. a top-k heap, which will see a lot of
+ * top element replacements.</li>
+ * <li>Random vs. increasing vs. decreasing vs. sawtooth insertion patterns for
+ * top-k make a difference.</li>
+ * <li>Different day, different benchmark results ...</li>
+ * </ul>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has UnsortedIter
+ * @param <K> Key type
+ */
+public class ComparatorMaxHeap<K> implements ObjectHeap<K> {
+ /**
+ * Base heap.
+ */
+ protected Object[] twoheap;
+
+ /**
+ * Extension heap.
+ */
+ protected Object[] fourheap;
+
+ /**
+ * Current size of heap.
+ */
+ protected int size;
+
+ /**
+ * (Structural) modification counter. Used to invalidate iterators.
+ */
+ protected int modCount = 0;
+
+ /**
+ * Maximum size of the 2-ary heap. A complete 2-ary heap has (2^k-1) elements.
+ */
+ private final static int TWO_HEAP_MAX_SIZE = (1 << 9) - 1;
+
+ /**
+ * Initial size of the 2-ary heap.
+ */
+ private final static int TWO_HEAP_INITIAL_SIZE = (1 << 5) - 1;
+
+ /**
+ * Initial size of 4-ary heap when initialized.
+ *
+ * 21 = 4-ary heap of height 2: 1 + 4 + 4*4
+ *
+ * 85 = 4-ary heap of height 3: 21 + 4*4*4
+ *
+ * 341 = 4-ary heap of height 4: 85 + 4*4*4*4
+ *
+ * Since we last grew by 255 (to 511), let's use 341.
+ */
+ private final static int FOUR_HEAP_INITIAL_SIZE = 341;
+
+
+ /**
+ * Comparator
+ */
+ protected java.util.Comparator<Object> comparator;
+
+ /**
+ * Constructor, with default size.
+ * @param comparator Comparator
+ */
+ @SuppressWarnings("unchecked")
+ public ComparatorMaxHeap(java.util.Comparator<? super K> comparator) {
+ super();
+ this.comparator = (java.util.Comparator<Object>) java.util.Comparator.class.cast(comparator);
+ Object[] twoheap = new Object[TWO_HEAP_INITIAL_SIZE];
+
+ this.twoheap = twoheap;
+ this.fourheap = null;
+ this.size = 0;
+ this.modCount = 0;
+ }
+
+ /**
+ * Constructor, with given minimum size.
+ *
+ * @param minsize Minimum size
+ * @param comparator Comparator
+ */
+ @SuppressWarnings("unchecked")
+ public ComparatorMaxHeap(int minsize, java.util.Comparator<? super K> comparator) {
+ super();
+ this.comparator = (java.util.Comparator<Object>) java.util.Comparator.class.cast(comparator);
+ if (minsize < TWO_HEAP_MAX_SIZE) {
+ final int size = MathUtil.nextPow2Int(minsize + 1) - 1;
+ Object[] twoheap = new Object[size];
+
+ this.twoheap = twoheap;
+ this.fourheap = null;
+ } else {
+ Object[] twoheap = new Object[TWO_HEAP_INITIAL_SIZE];
+ Object[] fourheap = new Object[Math.max(21, minsize - TWO_HEAP_MAX_SIZE)];
+ this.twoheap = twoheap;
+ this.fourheap = fourheap;
+ }
+ this.size = 0;
+ this.modCount = 0;
+ }
+
+ @Override
+ public void clear() {
+ size = 0;
+ ++modCount;
+ fourheap = null;
+ Arrays.fill(twoheap, null);
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return (size == 0);
+ }
+
+ @Override
+ public void add(K o) {
+ final Object co = o;
+ // System.err.println("Add: " + o);
+ if (size < TWO_HEAP_MAX_SIZE) {
+ if (size >= twoheap.length) {
+ // Grow by one layer.
+ twoheap = Arrays.copyOf(twoheap, twoheap.length + twoheap.length + 1);
+ }
+ final int twopos = size;
+ twoheap[twopos] = co;
+ ++size;
+ heapifyUp2(twopos, co);
+ ++modCount;
+ } else {
+ final int fourpos = size - TWO_HEAP_MAX_SIZE;
+ if (fourheap == null) {
+ fourheap = new Object[FOUR_HEAP_INITIAL_SIZE];
+ } else if (fourpos >= fourheap.length) {
+ // Grow extension heap by half.
+ fourheap = Arrays.copyOf(fourheap, fourheap.length + (fourheap.length >> 1));
+ }
+ fourheap[fourpos] = co;
+ ++size;
+ heapifyUp4(fourpos, co);
+ ++modCount;
+ }
+ }
+
+ @Override
+ public void add(K key, int max) {
+ if (size < max) {
+ add(key);
+ } else if (comparator.compare(twoheap[0], key) >= 0) {
+ replaceTopElement(key);
+ }
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public K replaceTopElement(K reinsert) {
+ final Object ret = twoheap[0];
+ heapifyDown( reinsert);
+ ++modCount;
+ return (K)ret;
+ }
+
+ /**
+ * Heapify-Up method for 2-ary heap.
+ *
+ * @param twopos Position in 2-ary heap.
+ * @param cur Current object
+ */
+ private void heapifyUp2(int twopos, Object cur) {
+ while (twopos > 0) {
+ final int parent = (twopos - 1) >>> 1;
+ Object par = twoheap[parent];
+ if (comparator.compare(cur, par) <= 0) {
+ break;
+ }
+ twoheap[twopos] = par;
+ twopos = parent;
+ }
+ twoheap[twopos] = cur;
+ }
+
+ /**
+ * Heapify-Up method for 4-ary heap.
+ *
+ * @param fourpos Position in 4-ary heap.
+ * @param cur Current object
+ */
+ private void heapifyUp4(int fourpos, Object cur) {
+ while (fourpos > 0) {
+ final int parent = (fourpos - 1) >> 2;
+ Object par = fourheap[parent];
+ if (comparator.compare(cur, par) <= 0) {
+ break;
+ }
+ fourheap[fourpos] = par;
+ fourpos = parent;
+ }
+ if (fourpos == 0 && comparator.compare(twoheap[0], cur) < 0) {
+ fourheap[0] = twoheap[0];
+ twoheap[0] = cur;
+ } else {
+ fourheap[fourpos] = cur;
+ }
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public K poll() {
+ final Object ret = twoheap[0];
+ --size;
+ // Replacement object:
+ if (size >= TWO_HEAP_MAX_SIZE) {
+ final int last = size - TWO_HEAP_MAX_SIZE;
+ final Object reinsert = fourheap[last];
+ fourheap[last] = null;
+ heapifyDown(reinsert);
+ } else if (size > 0) {
+ final Object reinsert = twoheap[size];
+ twoheap[size] = null;
+ heapifyDown(reinsert);
+ } else {
+ twoheap[0] = null;
+ }
+ ++modCount;
+ return (K)ret;
+ }
+
+ /**
+ * Invoke heapify-down for the root object.
+ *
+ * @param reinsert Object to insert.
+ */
+ private void heapifyDown(Object reinsert) {
+ if (size > TWO_HEAP_MAX_SIZE) {
+ // Special case: 3-ary situation.
+ final int best = (comparator.compare(twoheap[1], twoheap[2]) >= 0) ? 1 : 2;
+ if (comparator.compare(fourheap[0], twoheap[best]) > 0) {
+ twoheap[0] = fourheap[0];
+ heapifyDown4(0, reinsert);
+ } else {
+ twoheap[0] = twoheap[best];
+ heapifyDown2(best, reinsert);
+ }
+ return;
+ }
+ heapifyDown2(0, reinsert);
+ }
+
+ /**
+ * Heapify-Down for 2-ary heap.
+ *
+ * @param twopos Position in 2-ary heap.
+ * @param cur Current object
+ */
+ private void heapifyDown2(int twopos, Object cur) {
+ final int stop = Math.min(size, TWO_HEAP_MAX_SIZE) >>> 1;
+ while (twopos < stop) {
+ int bestchild = (twopos << 1) + 1;
+ Object best = twoheap[bestchild];
+ final int right = bestchild + 1;
+ if (right < size && comparator.compare(best, twoheap[right]) < 0) {
+ bestchild = right;
+ best = twoheap[right];
+ }
+ if (comparator.compare(cur, best) >= 0) {
+ break;
+ }
+ twoheap[twopos] = best;
+ twopos = bestchild;
+ }
+ twoheap[twopos] = cur;
+ }
+
+ /**
+ * Heapify-Down for 4-ary heap.
+ *
+ * @param fourpos Position in 4-ary heap.
+ * @param cur Current object
+ */
+ private void heapifyDown4(int fourpos, Object cur) {
+ final int stop = (size - TWO_HEAP_MAX_SIZE + 2) >>> 2;
+ while (fourpos < stop) {
+ final int child = (fourpos << 2) + 1;
+ Object best = fourheap[child];
+ int bestchild = child, candidate = child + 1, minsize = candidate + TWO_HEAP_MAX_SIZE;
+ if (size > minsize) {
+ Object nextchild = fourheap[candidate];
+ if (comparator.compare(best, nextchild) < 0) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+
+ minsize += 2;
+ if (size >= minsize) {
+ nextchild = fourheap[++candidate];
+ if (comparator.compare(best, nextchild) < 0) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+
+ if (size > minsize) {
+ nextchild = fourheap[++candidate];
+ if (comparator.compare(best, nextchild) < 0) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+ }
+ }
+ }
+ if (comparator.compare(cur, best) >= 0) {
+ break;
+ }
+ fourheap[fourpos] = best;
+ fourpos = bestchild;
+ }
+ fourheap[fourpos] = cur;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public K peek() {
+ return (K)twoheap[0];
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder buf = new StringBuilder();
+ buf.append(ComparatorMaxHeap.class.getSimpleName()).append(" [");
+ for (UnsortedIter iter = new UnsortedIter(); iter.valid(); iter.advance()) {
+ buf.append(iter.get()).append(',');
+ }
+ buf.append(']');
+ return buf.toString();
+ }
+
+ @Override
+ public UnsortedIter unsortedIter() {
+ return new UnsortedIter();
+ }
+
+ /**
+ * Unsorted iterator - in heap order. Does not poll the heap.
+ *
+ * Use this class as follows:
+ *
+ * <pre>
+ * {@code
+ * for (ObjectHeap.UnsortedIter<K> iter = heap.unsortedIter(); iter.valid(); iter.next()) {
+ * doSomething(iter.get());
+ * }
+ * }
+ * </pre>
+ *
+ * @author Erich Schubert
+ */
+ private class UnsortedIter implements ObjectHeap.UnsortedIter<K> {
+ /**
+ * Iterator position.
+ */
+ protected int pos = 0;
+
+ /**
+ * Modification counter we were initialized at.
+ */
+ protected final int myModCount = modCount;
+
+ @Override
+ public boolean valid() {
+ if (modCount != myModCount) {
+ throw new ConcurrentModificationException();
+ }
+ return pos < size;
+ }
+
+ @Override
+ public void advance() {
+ pos++;
+ }
+
+ @SuppressWarnings("unchecked")
+
+ @Override
+ public K get() {
+ return (K)((pos < TWO_HEAP_MAX_SIZE) ? twoheap[pos] : fourheap[pos - TWO_HEAP_MAX_SIZE]);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/ComparatorMinHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/ComparatorMinHeap.java
new file mode 100644
index 00000000..e12c5f64
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/ComparatorMinHeap.java
@@ -0,0 +1,440 @@
+package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.Arrays;
+import java.util.ConcurrentModificationException;
+
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+
+/**
+ * Advanced priority queue class, based on a binary heap (for small sizes),
+ * which will for larger heaps be accompanied by a 4-ary heap (attached below
+ * the root of the two-ary heap, making the root actually 3-ary).
+ *
+ * This code was automatically instantiated for the type: Comparator
+ *
+ * This combination was found to work quite well in benchmarks, but YMMV.
+ *
+ * Some other observations from benchmarking:
+ * <ul>
+ * <li>Bulk loading did not improve things</li>
+ * <li>Primitive heaps are substantially faster.</li>
+ * <li>Since an array in Java has an overhead of 12 bytes, odd-sized object and
+ * integer arrays are actually well aligned both for 2-ary and 4-ary heaps.</li>
+ * <li>Workload makes a huge difference. A load-once, poll-until-empty priority
+ * queue is something different than e.g. a top-k heap, which will see a lot of
+ * top element replacements.</li>
+ * <li>Random vs. increasing vs. decreasing vs. sawtooth insertion patterns for
+ * top-k make a difference.</li>
+ * <li>Different day, different benchmark results ...</li>
+ * </ul>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has UnsortedIter
+ * @param <K> Key type
+ */
+public class ComparatorMinHeap<K> implements ObjectHeap<K> {
+ /**
+ * Base heap.
+ */
+ protected Object[] twoheap;
+
+ /**
+ * Extension heap.
+ */
+ protected Object[] fourheap;
+
+ /**
+ * Current size of heap.
+ */
+ protected int size;
+
+ /**
+ * (Structural) modification counter. Used to invalidate iterators.
+ */
+ protected int modCount = 0;
+
+ /**
+ * Maximum size of the 2-ary heap. A complete 2-ary heap has (2^k-1) elements.
+ */
+ private final static int TWO_HEAP_MAX_SIZE = (1 << 9) - 1;
+
+ /**
+ * Initial size of the 2-ary heap.
+ */
+ private final static int TWO_HEAP_INITIAL_SIZE = (1 << 5) - 1;
+
+ /**
+ * Initial size of 4-ary heap when initialized.
+ *
+ * 21 = 4-ary heap of height 2: 1 + 4 + 4*4
+ *
+ * 85 = 4-ary heap of height 3: 21 + 4*4*4
+ *
+ * 341 = 4-ary heap of height 4: 85 + 4*4*4*4
+ *
+ * Since we last grew by 255 (to 511), let's use 341.
+ */
+ private final static int FOUR_HEAP_INITIAL_SIZE = 341;
+
+
+ /**
+ * Comparator
+ */
+ protected java.util.Comparator<Object> comparator;
+
+ /**
+ * Constructor, with default size.
+ * @param comparator Comparator
+ */
+ @SuppressWarnings("unchecked")
+ public ComparatorMinHeap(java.util.Comparator<? super K> comparator) {
+ super();
+ this.comparator = (java.util.Comparator<Object>) java.util.Comparator.class.cast(comparator);
+ Object[] twoheap = new Object[TWO_HEAP_INITIAL_SIZE];
+
+ this.twoheap = twoheap;
+ this.fourheap = null;
+ this.size = 0;
+ this.modCount = 0;
+ }
+
+ /**
+ * Constructor, with given minimum size.
+ *
+ * @param minsize Minimum size
+ * @param comparator Comparator
+ */
+ @SuppressWarnings("unchecked")
+ public ComparatorMinHeap(int minsize, java.util.Comparator<? super K> comparator) {
+ super();
+ this.comparator = (java.util.Comparator<Object>) java.util.Comparator.class.cast(comparator);
+ if (minsize < TWO_HEAP_MAX_SIZE) {
+ final int size = MathUtil.nextPow2Int(minsize + 1) - 1;
+ Object[] twoheap = new Object[size];
+
+ this.twoheap = twoheap;
+ this.fourheap = null;
+ } else {
+ Object[] twoheap = new Object[TWO_HEAP_INITIAL_SIZE];
+ Object[] fourheap = new Object[Math.max(21, minsize - TWO_HEAP_MAX_SIZE)];
+ this.twoheap = twoheap;
+ this.fourheap = fourheap;
+ }
+ this.size = 0;
+ this.modCount = 0;
+ }
+
+ @Override
+ public void clear() {
+ size = 0;
+ ++modCount;
+ fourheap = null;
+ Arrays.fill(twoheap, null);
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return (size == 0);
+ }
+
+ @Override
+ public void add(K o) {
+ final Object co = o;
+ // System.err.println("Add: " + o);
+ if (size < TWO_HEAP_MAX_SIZE) {
+ if (size >= twoheap.length) {
+ // Grow by one layer.
+ twoheap = Arrays.copyOf(twoheap, twoheap.length + twoheap.length + 1);
+ }
+ final int twopos = size;
+ twoheap[twopos] = co;
+ ++size;
+ heapifyUp2(twopos, co);
+ ++modCount;
+ } else {
+ final int fourpos = size - TWO_HEAP_MAX_SIZE;
+ if (fourheap == null) {
+ fourheap = new Object[FOUR_HEAP_INITIAL_SIZE];
+ } else if (fourpos >= fourheap.length) {
+ // Grow extension heap by half.
+ fourheap = Arrays.copyOf(fourheap, fourheap.length + (fourheap.length >> 1));
+ }
+ fourheap[fourpos] = co;
+ ++size;
+ heapifyUp4(fourpos, co);
+ ++modCount;
+ }
+ }
+
+ @Override
+ public void add(K key, int max) {
+ if (size < max) {
+ add(key);
+ } else if (comparator.compare(twoheap[0], key) <= 0) {
+ replaceTopElement(key);
+ }
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public K replaceTopElement(K reinsert) {
+ final Object ret = twoheap[0];
+ heapifyDown( reinsert);
+ ++modCount;
+ return (K)ret;
+ }
+
+ /**
+ * Heapify-Up method for 2-ary heap.
+ *
+ * @param twopos Position in 2-ary heap.
+ * @param cur Current object
+ */
+ private void heapifyUp2(int twopos, Object cur) {
+ while (twopos > 0) {
+ final int parent = (twopos - 1) >>> 1;
+ Object par = twoheap[parent];
+ if (comparator.compare(cur, par) >= 0) {
+ break;
+ }
+ twoheap[twopos] = par;
+ twopos = parent;
+ }
+ twoheap[twopos] = cur;
+ }
+
+ /**
+ * Heapify-Up method for 4-ary heap.
+ *
+ * @param fourpos Position in 4-ary heap.
+ * @param cur Current object
+ */
+ private void heapifyUp4(int fourpos, Object cur) {
+ while (fourpos > 0) {
+ final int parent = (fourpos - 1) >> 2;
+ Object par = fourheap[parent];
+ if (comparator.compare(cur, par) >= 0) {
+ break;
+ }
+ fourheap[fourpos] = par;
+ fourpos = parent;
+ }
+ if (fourpos == 0 && comparator.compare(twoheap[0], cur) > 0) {
+ fourheap[0] = twoheap[0];
+ twoheap[0] = cur;
+ } else {
+ fourheap[fourpos] = cur;
+ }
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public K poll() {
+ final Object ret = twoheap[0];
+ --size;
+ // Replacement object:
+ if (size >= TWO_HEAP_MAX_SIZE) {
+ final int last = size - TWO_HEAP_MAX_SIZE;
+ final Object reinsert = fourheap[last];
+ fourheap[last] = null;
+ heapifyDown(reinsert);
+ } else if (size > 0) {
+ final Object reinsert = twoheap[size];
+ twoheap[size] = null;
+ heapifyDown(reinsert);
+ } else {
+ twoheap[0] = null;
+ }
+ ++modCount;
+ return (K)ret;
+ }
+
+ /**
+ * Invoke heapify-down for the root object.
+ *
+ * @param reinsert Object to insert.
+ */
+ private void heapifyDown(Object reinsert) {
+ if (size > TWO_HEAP_MAX_SIZE) {
+ // Special case: 3-ary situation.
+ final int best = (comparator.compare(twoheap[1], twoheap[2]) <= 0) ? 1 : 2;
+ if (comparator.compare(fourheap[0], twoheap[best]) < 0) {
+ twoheap[0] = fourheap[0];
+ heapifyDown4(0, reinsert);
+ } else {
+ twoheap[0] = twoheap[best];
+ heapifyDown2(best, reinsert);
+ }
+ return;
+ }
+ heapifyDown2(0, reinsert);
+ }
+
+ /**
+ * Heapify-Down for 2-ary heap.
+ *
+ * @param twopos Position in 2-ary heap.
+ * @param cur Current object
+ */
+ private void heapifyDown2(int twopos, Object cur) {
+ final int stop = Math.min(size, TWO_HEAP_MAX_SIZE) >>> 1;
+ while (twopos < stop) {
+ int bestchild = (twopos << 1) + 1;
+ Object best = twoheap[bestchild];
+ final int right = bestchild + 1;
+ if (right < size && comparator.compare(best, twoheap[right]) > 0) {
+ bestchild = right;
+ best = twoheap[right];
+ }
+ if (comparator.compare(cur, best) <= 0) {
+ break;
+ }
+ twoheap[twopos] = best;
+ twopos = bestchild;
+ }
+ twoheap[twopos] = cur;
+ }
+
+ /**
+ * Heapify-Down for 4-ary heap.
+ *
+ * @param fourpos Position in 4-ary heap.
+ * @param cur Current object
+ */
+ private void heapifyDown4(int fourpos, Object cur) {
+ final int stop = (size - TWO_HEAP_MAX_SIZE + 2) >>> 2;
+ while (fourpos < stop) {
+ final int child = (fourpos << 2) + 1;
+ Object best = fourheap[child];
+ int bestchild = child, candidate = child + 1, minsize = candidate + TWO_HEAP_MAX_SIZE;
+ if (size > minsize) {
+ Object nextchild = fourheap[candidate];
+ if (comparator.compare(best, nextchild) > 0) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+
+ minsize += 2;
+ if (size >= minsize) {
+ nextchild = fourheap[++candidate];
+ if (comparator.compare(best, nextchild) > 0) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+
+ if (size > minsize) {
+ nextchild = fourheap[++candidate];
+ if (comparator.compare(best, nextchild) > 0) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+ }
+ }
+ }
+ if (comparator.compare(cur, best) <= 0) {
+ break;
+ }
+ fourheap[fourpos] = best;
+ fourpos = bestchild;
+ }
+ fourheap[fourpos] = cur;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public K peek() {
+ return (K)twoheap[0];
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder buf = new StringBuilder();
+ buf.append(ComparatorMinHeap.class.getSimpleName()).append(" [");
+ for (UnsortedIter iter = new UnsortedIter(); iter.valid(); iter.advance()) {
+ buf.append(iter.get()).append(',');
+ }
+ buf.append(']');
+ return buf.toString();
+ }
+
+ @Override
+ public UnsortedIter unsortedIter() {
+ return new UnsortedIter();
+ }
+
+ /**
+ * Unsorted iterator - in heap order. Does not poll the heap.
+ *
+ * Use this class as follows:
+ *
+ * <pre>
+ * {@code
+ * for (ObjectHeap.UnsortedIter<K> iter = heap.unsortedIter(); iter.valid(); iter.next()) {
+ * doSomething(iter.get());
+ * }
+ * }
+ * </pre>
+ *
+ * @author Erich Schubert
+ */
+ private class UnsortedIter implements ObjectHeap.UnsortedIter<K> {
+ /**
+ * Iterator position.
+ */
+ protected int pos = 0;
+
+ /**
+ * Modification counter we were initialized at.
+ */
+ protected final int myModCount = modCount;
+
+ @Override
+ public boolean valid() {
+ if (modCount != myModCount) {
+ throw new ConcurrentModificationException();
+ }
+ return pos < size;
+ }
+
+ @Override
+ public void advance() {
+ pos++;
+ }
+
+ @SuppressWarnings("unchecked")
+
+ @Override
+ public K get() {
+ return (K)((pos < TWO_HEAP_MAX_SIZE) ? twoheap[pos] : fourheap[pos - TWO_HEAP_MAX_SIZE]);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleHeap.java
index f9f928bd..acf77d86 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleHeap.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleHeap.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,53 +23,22 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.Arrays;
-
-import de.lmu.ifi.dbs.elki.math.MathUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.iterator.Iter;
/**
- * Basic in-memory heap structure.
- *
- * This heap is built lazily: if you first add many elements, then poll the
- * heap, it will be bulk-loaded in O(n) instead of iteratively built in O(n log
- * n). This is implemented via a simple validTo counter.
+ * Basic in-memory heap for double values.
*
* @author Erich Schubert
+ *
+ * @apiviz.has UnsortedIter
*/
-public abstract class DoubleHeap extends AbstractHeap {
- /**
- * Heap storage: queue
- */
- protected transient double[] queue;
-
- /**
- * Constructor with initial capacity.
- *
- * @param size initial capacity
- */
- public DoubleHeap(int size) {
- super();
- this.size = 0;
- this.queue = new double[size];
- }
-
+public interface DoubleHeap {
/**
* Add a key-value pair to the heap
*
* @param key Key
*/
- public void add(double key) {
- // resize when needed
- if (size + 1 > queue.length) {
- resize(size + 1);
- }
- // final int pos = size;
- this.queue[size] = key;
- this.size += 1;
- heapifyUp(size - 1, key);
- validSize += 1;
- heapModified();
- }
+ void add(double key);
/**
* Add a key-value pair to the heap, except if the new element is larger than
@@ -78,13 +47,7 @@ public abstract class DoubleHeap extends AbstractHeap {
* @param key Key
* @param max Maximum size of heap
*/
- public void add(double key, int max) {
- if (size < max) {
- add(key);
- } else if (comp(key, peek())) {
- replaceTopElement(key);
- }
- }
+ void add(double key, int max);
/**
* Combined operation that removes the top element, and inserts a new element
@@ -93,172 +56,67 @@ public abstract class DoubleHeap extends AbstractHeap {
* @param e New element to insert
* @return Previous top element of the heap
*/
- public double replaceTopElement(double e) {
- ensureValid();
- double oldroot = queue[0];
- heapifyDown(0, e);
- heapModified();
- return oldroot;
- }
+ double replaceTopElement(double e);
/**
* Get the current top key
*
* @return Top key
*/
- public double peek() {
- if (size == 0) {
- throw new ArrayIndexOutOfBoundsException("Peek() on an empty heap!");
- }
- ensureValid();
- return queue[0];
- }
+ double peek();
/**
* Remove the first element
*
* @return Top element
*/
- public double poll() {
- return removeAt(0);
- }
+ double poll();
/**
- * Repair the heap
+ * Delete all elements from the heap.
*/
- protected void ensureValid() {
- if (validSize != size) {
- if (size > 1) {
- // Parent of first invalid
- int nextmin = validSize > 0 ? ((validSize - 1) >>> 1) : 0;
- int curmin = MathUtil.nextAllOnesInt(nextmin); // Next line
- int nextmax = curmin - 1; // End of valid line
- int pos = (size - 2) >>> 1; // Parent of last element
- // System.err.println(validSize+"<="+size+" iter:"+pos+"->"+curmin+", "+nextmin);
- while (pos >= nextmin) {
- // System.err.println(validSize+"<="+size+" iter:"+pos+"->"+curmin);
- while (pos >= curmin) {
- if (!heapifyDown(pos, queue[pos])) {
- final int parent = (pos - 1) >>> 1;
- if (parent < curmin) {
- nextmin = Math.min(nextmin, parent);
- nextmax = Math.max(nextmax, parent);
- }
- }
- pos--;
- }
- curmin = nextmin;
- pos = Math.min(pos, nextmax);
- nextmax = -1;
- }
- }
- validSize = size;
- }
- }
+ void clear();
/**
- * Remove the element at the given position.
+ * Query the size
*
- * @param pos Element position.
- * @return Removed element
+ * @return Size
*/
- protected double removeAt(int pos) {
- if (pos < 0 || pos >= size) {
- return 0.0;
- }
- final double top = queue[0];
- // Replacement object:
- final double reinkey = queue[size - 1];
- // Keep heap in sync
- if (validSize == size) {
- size -= 1;
- validSize -= 1;
- heapifyDown(pos, reinkey);
- } else {
- size -= 1;
- validSize = Math.min(pos >>> 1, validSize);
- queue[pos] = reinkey;
- }
- heapModified();
- return top;
- }
-
+ public int size();
+
/**
- * Execute a "Heapify Upwards" aka "SiftUp". Used in insertions.
+ * Is the heap empty?
*
- * @param pos insertion position
- * @param curkey Current key
+ * @return {@code true} when the size is 0.
*/
- protected void heapifyUp(int pos, double curkey) {
- while (pos > 0) {
- final int parent = (pos - 1) >>> 1;
- double parkey = queue[parent];
-
- if (comp(curkey, parkey)) { // Compare
- break;
- }
- queue[pos] = parkey;
- pos = parent;
- }
- queue[pos] = curkey;
- }
+ public boolean isEmpty();
/**
- * Execute a "Heapify Downwards" aka "SiftDown". Used in deletions.
+ * Get an unsorted iterator to inspect the heap.
*
- * @param ipos re-insertion position
- * @param curkey Current key
- * @return true when the order was changed
+ * @return Iterator
*/
- protected boolean heapifyDown(final int ipos, double curkey) {
- int pos = ipos;
- final int half = size >>> 1;
- while (pos < half) {
- // Get left child (must exist!)
- int cpos = (pos << 1) + 1;
- double chikey = queue[cpos];
- // Test right child, if present
- final int rchild = cpos + 1;
- if (rchild < size) {
- double right = queue[rchild];
- if (comp(chikey, right)) { // Compare
- cpos = rchild;
- chikey = right;
- }
- }
-
- if (comp(chikey, curkey)) { // Compare
- break;
- }
- queue[pos] = chikey;
- pos = cpos;
- }
- queue[pos] = curkey;
- return (pos == ipos);
- }
+ UnsortedIter unsortedIter();
/**
- * Test whether we need to resize to have the requested capacity.
+ * Unsorted iterator - in heap order. Does not poll the heap.
*
- * @param requiredSize required capacity
- */
- protected final void resize(int requiredSize) {
- queue = Arrays.copyOf(queue, desiredSize(requiredSize, queue.length));
- }
-
- /**
- * Delete all elements from the heap.
+ * <pre>
+ * {@code
+ * for (DoubleHeap.UnsortedIter iter = heap.unsortedIter(); iter.valid(); iter.next()) {
+ * doSomething(iter.get());
+ * }
+ * }
+ * </pre>
+ *
+ * @author Erich Schubert
*/
- @Override
- public void clear() {
- super.clear();
- for (int i = 0; i < size; i++) {
- queue[i] = 0.0;
- }
+ public static interface UnsortedIter extends Iter {
+ /**
+ * Get the iterators current object.
+ *
+ * @return Current object
+ */
+ double get();
}
-
- /**
- * Compare two objects
- */
- abstract protected boolean comp(double o1, double o2);
}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleIntegerHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleIntegerHeap.java
new file mode 100644
index 00000000..c3bf85f4
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleIntegerHeap.java
@@ -0,0 +1,127 @@
+package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.utilities.datastructures.iterator.Iter;
+
+/**
+ * Basic in-memory heap interface, for double keys and int values.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has UnsortedIter
+ */
+public interface DoubleIntegerHeap {
+ /**
+ * Add a key-value pair to the heap
+ *
+ * @param key Key
+ * @param val Value
+ */
+ void add(double key, int val);
+
+ /**
+ * Add a key-value pair to the heap if it improves the top.
+ *
+ * @param key Key
+ * @param val Value
+ * @param k Desired maximum size
+ */
+ void add(double key, int val, int k);
+
+ /**
+ * Combined operation that removes the top element, and inserts a new element
+ * instead.
+ *
+ * @param key Key of new element
+ * @param val Value of new element
+ */
+ void replaceTopElement(double key, int val);
+
+ /**
+ * Get the current top key
+ *
+ * @return Top key
+ */
+ double peekKey();
+
+ /**
+ * Get the current top value
+ *
+ * @return Value
+ */
+ int peekValue();
+
+ /**
+ * Remove the first element
+ */
+ void poll();
+
+ /**
+ * Clear the heap contents.
+ */
+ void clear();
+
+ /**
+ * Query the size
+ *
+ * @return Size
+ */
+ public int size();
+
+ /**
+ * Is the heap empty?
+ *
+ * @return {@code true} when the size is 0.
+ */
+ public boolean isEmpty();
+
+ /**
+ * Get an unsorted iterator to inspect the heap.
+ *
+ * @return Iterator
+ */
+ UnsortedIter unsortedIter();
+
+ /**
+ * Unsorted iterator - in heap order. Does not poll the heap.
+ *
+ * @author Erich Schubert
+ */
+ public static interface UnsortedIter extends Iter {
+ /**
+ * Get the current key
+ *
+ * @return Current key
+ */
+ double getKey();
+
+ /**
+ * Get the current value
+ *
+ * @return Current value
+ */
+ int getValue();
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleIntegerMaxHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleIntegerMaxHeap.java
new file mode 100644
index 00000000..34f1e889
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleIntegerMaxHeap.java
@@ -0,0 +1,478 @@
+package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.Arrays;
+import java.util.ConcurrentModificationException;
+
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+
+/**
+ * Advanced priority queue class, based on a binary heap (for small sizes),
+ * which will for larger heaps be accompanied by a 4-ary heap (attached below
+ * the root of the two-ary heap, making the root actually 3-ary).
+ *
+ * This code was automatically instantiated for the types: Double and Integer
+ *
+ * This combination was found to work quite well in benchmarks, but YMMV.
+ *
+ * Some other observations from benchmarking:
+ * <ul>
+ * <li>Bulk loading did not improve things</li>
+ * <li>Primitive heaps are substantially faster.</li>
+ * <li>Since an array in Java has an overhead of 12 bytes, odd-sized object and
+ * integer arrays are actually well aligned both for 2-ary and 4-ary heaps.</li>
+ * <li>Workload makes a huge difference. A load-once, poll-until-empty priority
+ * queue is something different than e.g. a top-k heap, which will see a lot of
+ * top element replacements.</li>
+ * <li>Random vs. increasing vs. decreasing vs. sawtooth insertion patterns for
+ * top-k make a difference.</li>
+ * <li>Different day, different benchmark results ...</li>
+ * </ul>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has UnsortedIter
+ */
+public class DoubleIntegerMaxHeap implements DoubleIntegerHeap {
+ /**
+ * Base heap.
+ */
+ protected double[] twoheap;
+
+ /**
+ * Base heap values.
+ */
+ protected int[] twovals;
+
+ /**
+ * Extension heap.
+ */
+ protected double[] fourheap;
+
+ /**
+ * Extension heapvalues.
+ */
+ protected int[] fourvals;
+
+ /**
+ * Current size of heap.
+ */
+ protected int size;
+
+ /**
+ * (Structural) modification counter. Used to invalidate iterators.
+ */
+ protected int modCount = 0;
+
+ /**
+ * Maximum size of the 2-ary heap. A complete 2-ary heap has (2^k-1) elements.
+ */
+ private final static int TWO_HEAP_MAX_SIZE = (1 << 9) - 1;
+
+ /**
+ * Initial size of the 2-ary heap.
+ */
+ private final static int TWO_HEAP_INITIAL_SIZE = (1 << 5) - 1;
+
+ /**
+ * Initial size of 4-ary heap when initialized.
+ *
+ * 21 = 4-ary heap of height 2: 1 + 4 + 4*4
+ *
+ * 85 = 4-ary heap of height 3: 21 + 4*4*4
+ *
+ * 341 = 4-ary heap of height 4: 85 + 4*4*4*4
+ *
+ * Since we last grew by 255 (to 511), let's use 341.
+ */
+ private final static int FOUR_HEAP_INITIAL_SIZE = 341;
+
+ /**
+ * Constructor, with default size.
+ */
+ public DoubleIntegerMaxHeap() {
+ super();
+ double[] twoheap = new double[TWO_HEAP_INITIAL_SIZE];
+ int[] twovals = new int[TWO_HEAP_INITIAL_SIZE];
+
+ this.twoheap = twoheap;
+ this.twovals = twovals;
+ this.fourheap = null;
+ this.fourvals = null;
+ this.size = 0;
+ this.modCount = 0;
+ }
+
+ /**
+ * Constructor, with given minimum size.
+ *
+ * @param minsize Minimum size
+ */
+ public DoubleIntegerMaxHeap(int minsize) {
+ super();
+ if (minsize < TWO_HEAP_MAX_SIZE) {
+ final int size = MathUtil.nextPow2Int(minsize + 1) - 1;
+ double[] twoheap = new double[size];
+ int[] twovals = new int[size];
+
+ this.twoheap = twoheap;
+ this.twovals = twovals;
+ this.fourheap = null;
+ this.fourvals = null;
+ } else {
+ double[] twoheap = new double[TWO_HEAP_INITIAL_SIZE];
+ int[] twovals = new int[TWO_HEAP_INITIAL_SIZE];
+ double[] fourheap = new double[Math.max(21, minsize - TWO_HEAP_MAX_SIZE)];
+ int[] fourvals = new int[Math.max(21, minsize - TWO_HEAP_MAX_SIZE)];
+ this.twoheap = twoheap;
+ this.twovals = twovals;
+ this.fourheap = fourheap;
+ this.fourvals = fourvals;
+ }
+ this.size = 0;
+ this.modCount = 0;
+ }
+
+ @Override
+ public void clear() {
+ size = 0;
+ ++modCount;
+ fourheap = null;
+ fourvals = null;
+ Arrays.fill(twoheap, 0.0);
+ Arrays.fill(twovals, 0);
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return (size == 0);
+ }
+
+ @Override
+ public void add(double o, int v) {
+ final double co = o;
+ final int cv = v;
+ // System.err.println("Add: " + o);
+ if (size < TWO_HEAP_MAX_SIZE) {
+ if (size >= twoheap.length) {
+ // Grow by one layer.
+ twoheap = Arrays.copyOf(twoheap, twoheap.length + twoheap.length + 1);
+ twovals = Arrays.copyOf(twovals, twovals.length + twovals.length + 1);
+ }
+ final int twopos = size;
+ twoheap[twopos] = co;
+ twovals[twopos] = cv;
+ ++size;
+ heapifyUp2(twopos, co, cv);
+ ++modCount;
+ } else {
+ final int fourpos = size - TWO_HEAP_MAX_SIZE;
+ if (fourheap == null) {
+ fourheap = new double[FOUR_HEAP_INITIAL_SIZE];
+ fourvals = new int[FOUR_HEAP_INITIAL_SIZE];
+ } else if (fourpos >= fourheap.length) {
+ // Grow extension heap by half.
+ fourheap = Arrays.copyOf(fourheap, fourheap.length + (fourheap.length >> 1));
+ fourvals = Arrays.copyOf(fourvals, fourvals.length + (fourvals.length >> 1));
+ }
+ fourheap[fourpos] = co;
+ fourvals[fourpos] = cv;
+ ++size;
+ heapifyUp4(fourpos, co, cv);
+ ++modCount;
+ }
+ }
+
+ @Override
+ public void add(double key, int val, int max) {
+ if (size < max) {
+ add(key, val);
+ } else if (twoheap[0] >= key) {
+ replaceTopElement(key, val);
+ }
+ }
+
+ @Override
+ public void replaceTopElement(double reinsert, int val) {
+ heapifyDown(reinsert, val);
+ ++modCount;
+ }
+
+ /**
+ * Heapify-Up method for 2-ary heap.
+ *
+ * @param twopos Position in 2-ary heap.
+ * @param cur Current object
+ * @param val Current value
+ */
+ private void heapifyUp2(int twopos, double cur, int val) {
+ while (twopos > 0) {
+ final int parent = (twopos - 1) >>> 1;
+ double par = twoheap[parent];
+ if (cur <= par) {
+ break;
+ }
+ twoheap[twopos] = par;
+ twovals[twopos] = twovals[parent];
+ twopos = parent;
+ }
+ twoheap[twopos] = cur;
+ twovals[twopos] = val;
+ }
+
+ /**
+ * Heapify-Up method for 4-ary heap.
+ *
+ * @param fourpos Position in 4-ary heap.
+ * @param cur Current object
+ * @param val Current value
+ */
+ private void heapifyUp4(int fourpos, double cur, int val) {
+ while (fourpos > 0) {
+ final int parent = (fourpos - 1) >> 2;
+ double par = fourheap[parent];
+ if (cur <= par) {
+ break;
+ }
+ fourheap[fourpos] = par;
+ fourvals[fourpos] = fourvals[parent];
+ fourpos = parent;
+ }
+ if (fourpos == 0 && twoheap[0] < cur) {
+ fourheap[0] = twoheap[0];
+ fourvals[0] = twovals[0];
+ twoheap[0] = cur;
+ twovals[0] = val;
+ } else {
+ fourheap[fourpos] = cur;
+ fourvals[fourpos] = val;
+ }
+ }
+
+ @Override
+ public void poll() {
+ --size;
+ // Replacement object:
+ if (size >= TWO_HEAP_MAX_SIZE) {
+ final int last = size - TWO_HEAP_MAX_SIZE;
+ final double reinsert = fourheap[last];
+ final int reinsertv = fourvals[last];
+ fourheap[last] = 0.0;
+ fourvals[last] = 0;
+ heapifyDown(reinsert, reinsertv);
+ } else if (size > 0) {
+ final double reinsert = twoheap[size];
+ final int reinsertv = twovals[size];
+ twoheap[size] = 0.0;
+ twovals[size] = 0;
+ heapifyDown(reinsert, reinsertv);
+ } else {
+ twoheap[0] = 0.0;
+ twovals[0] = 0;
+ }
+ ++modCount;
+ }
+
+ /**
+ * Invoke heapify-down for the root object.
+ *
+ * @param reinsert Object to insert.
+ * @param val Value to reinsert.
+ */
+ private void heapifyDown(double reinsert, int val) {
+ if (size > TWO_HEAP_MAX_SIZE) {
+ // Special case: 3-ary situation.
+ final int best = (twoheap[1] >= twoheap[2]) ? 1 : 2;
+ if (fourheap[0] > twoheap[best]) {
+ twoheap[0] = fourheap[0];
+ twovals[0] = fourvals[0];
+ heapifyDown4(0, reinsert, val);
+ } else {
+ twoheap[0] = twoheap[best];
+ twovals[0] = twovals[best];
+ heapifyDown2(best, reinsert, val);
+ }
+ return;
+ }
+ heapifyDown2(0, reinsert, val);
+ }
+
+ /**
+ * Heapify-Down for 2-ary heap.
+ *
+ * @param twopos Position in 2-ary heap.
+ * @param cur Current object
+ * @param val Value to reinsert.
+ */
+ private void heapifyDown2(int twopos, double cur, int val) {
+ final int stop = Math.min(size, TWO_HEAP_MAX_SIZE) >>> 1;
+ while (twopos < stop) {
+ int bestchild = (twopos << 1) + 1;
+ double best = twoheap[bestchild];
+ final int right = bestchild + 1;
+ if (right < size && best < twoheap[right]) {
+ bestchild = right;
+ best = twoheap[right];
+ }
+ if (cur >= best) {
+ break;
+ }
+ twoheap[twopos] = best;
+ twovals[twopos] = twovals[bestchild];
+ twopos = bestchild;
+ }
+ twoheap[twopos] = cur;
+ twovals[twopos] = val;
+ }
+
+ /**
+ * Heapify-Down for 4-ary heap.
+ *
+ * @param fourpos Position in 4-ary heap.
+ * @param cur Current object
+ * @param val Value to reinsert.
+ */
+ private void heapifyDown4(int fourpos, double cur, int val) {
+ final int stop = (size - TWO_HEAP_MAX_SIZE + 2) >>> 2;
+ while (fourpos < stop) {
+ final int child = (fourpos << 2) + 1;
+ double best = fourheap[child];
+ int bestchild = child, candidate = child + 1, minsize = candidate + TWO_HEAP_MAX_SIZE;
+ if (size > minsize) {
+ double nextchild = fourheap[candidate];
+ if (best < nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+
+ minsize += 2;
+ if (size >= minsize) {
+ nextchild = fourheap[++candidate];
+ if (best < nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+
+ if (size > minsize) {
+ nextchild = fourheap[++candidate];
+ if (best < nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+ }
+ }
+ }
+ if (cur >= best) {
+ break;
+ }
+ fourheap[fourpos] = best;
+ fourvals[fourpos] = fourvals[bestchild];
+ fourpos = bestchild;
+ }
+ fourheap[fourpos] = cur;
+ fourvals[fourpos] = val;
+ }
+
+ @Override
+ public double peekKey() {
+ return twoheap[0];
+ }
+
+ @Override
+ public int peekValue() {
+ return twovals[0];
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder buf = new StringBuilder();
+ buf.append(DoubleIntegerMaxHeap.class.getSimpleName()).append(" [");
+ for (UnsortedIter iter = new UnsortedIter(); iter.valid(); iter.advance()) {
+ buf.append(iter.getKey()).append(':').append(iter.getValue()).append(',');
+ }
+ buf.append(']');
+ return buf.toString();
+ }
+
+ @Override
+ public UnsortedIter unsortedIter() {
+ return new UnsortedIter();
+ }
+
+ /**
+ * Unsorted iterator - in heap order. Does not poll the heap.
+ *
+ * Use this class as follows:
+ *
+ * <pre>
+ * {@code
+ * for (DoubleIntegerHeap.UnsortedIter iter = heap.unsortedIter(); iter.valid(); iter.next()) {
+ * doSomething(iter.get());
+ * }
+ * }
+ * </pre>
+ *
+ * @author Erich Schubert
+ */
+ private class UnsortedIter implements DoubleIntegerHeap.UnsortedIter {
+ /**
+ * Iterator position.
+ */
+ protected int pos = 0;
+
+ /**
+ * Modification counter we were initialized at.
+ */
+ protected final int myModCount = modCount;
+
+ @Override
+ public boolean valid() {
+ if (modCount != myModCount) {
+ throw new ConcurrentModificationException();
+ }
+ return pos < size;
+ }
+
+ @Override
+ public void advance() {
+ pos++;
+ }
+
+ @Override
+ public double getKey() {
+ return ((pos < TWO_HEAP_MAX_SIZE) ? twoheap[pos] : fourheap[pos - TWO_HEAP_MAX_SIZE]);
+ }
+
+ @Override
+ public int getValue() {
+ return ((pos < TWO_HEAP_MAX_SIZE) ? twovals[pos] : fourvals[pos - TWO_HEAP_MAX_SIZE]);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleIntegerMinHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleIntegerMinHeap.java
new file mode 100644
index 00000000..ca6192ad
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleIntegerMinHeap.java
@@ -0,0 +1,478 @@
+package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.Arrays;
+import java.util.ConcurrentModificationException;
+
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+
+/**
+ * Advanced priority queue class, based on a binary heap (for small sizes),
+ * which will for larger heaps be accompanied by a 4-ary heap (attached below
+ * the root of the two-ary heap, making the root actually 3-ary).
+ *
+ * This code was automatically instantiated for the types: Double and Integer
+ *
+ * This combination was found to work quite well in benchmarks, but YMMV.
+ *
+ * Some other observations from benchmarking:
+ * <ul>
+ * <li>Bulk loading did not improve things</li>
+ * <li>Primitive heaps are substantially faster.</li>
+ * <li>Since an array in Java has an overhead of 12 bytes, odd-sized object and
+ * integer arrays are actually well aligned both for 2-ary and 4-ary heaps.</li>
+ * <li>Workload makes a huge difference. A load-once, poll-until-empty priority
+ * queue is something different than e.g. a top-k heap, which will see a lot of
+ * top element replacements.</li>
+ * <li>Random vs. increasing vs. decreasing vs. sawtooth insertion patterns for
+ * top-k make a difference.</li>
+ * <li>Different day, different benchmark results ...</li>
+ * </ul>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has UnsortedIter
+ */
+public class DoubleIntegerMinHeap implements DoubleIntegerHeap {
+ /**
+ * Base heap.
+ */
+ protected double[] twoheap;
+
+ /**
+ * Base heap values.
+ */
+ protected int[] twovals;
+
+ /**
+ * Extension heap.
+ */
+ protected double[] fourheap;
+
+ /**
+ * Extension heapvalues.
+ */
+ protected int[] fourvals;
+
+ /**
+ * Current size of heap.
+ */
+ protected int size;
+
+ /**
+ * (Structural) modification counter. Used to invalidate iterators.
+ */
+ protected int modCount = 0;
+
+ /**
+ * Maximum size of the 2-ary heap. A complete 2-ary heap has (2^k-1) elements.
+ */
+ private final static int TWO_HEAP_MAX_SIZE = (1 << 9) - 1;
+
+ /**
+ * Initial size of the 2-ary heap.
+ */
+ private final static int TWO_HEAP_INITIAL_SIZE = (1 << 5) - 1;
+
+ /**
+ * Initial size of 4-ary heap when initialized.
+ *
+ * 21 = 4-ary heap of height 2: 1 + 4 + 4*4
+ *
+ * 85 = 4-ary heap of height 3: 21 + 4*4*4
+ *
+ * 341 = 4-ary heap of height 4: 85 + 4*4*4*4
+ *
+ * Since we last grew by 255 (to 511), let's use 341.
+ */
+ private final static int FOUR_HEAP_INITIAL_SIZE = 341;
+
+ /**
+ * Constructor, with default size.
+ */
+ public DoubleIntegerMinHeap() {
+ super();
+ double[] twoheap = new double[TWO_HEAP_INITIAL_SIZE];
+ int[] twovals = new int[TWO_HEAP_INITIAL_SIZE];
+
+ this.twoheap = twoheap;
+ this.twovals = twovals;
+ this.fourheap = null;
+ this.fourvals = null;
+ this.size = 0;
+ this.modCount = 0;
+ }
+
+ /**
+ * Constructor, with given minimum size.
+ *
+ * @param minsize Minimum size
+ */
+ public DoubleIntegerMinHeap(int minsize) {
+ super();
+ if (minsize < TWO_HEAP_MAX_SIZE) {
+ final int size = MathUtil.nextPow2Int(minsize + 1) - 1;
+ double[] twoheap = new double[size];
+ int[] twovals = new int[size];
+
+ this.twoheap = twoheap;
+ this.twovals = twovals;
+ this.fourheap = null;
+ this.fourvals = null;
+ } else {
+ double[] twoheap = new double[TWO_HEAP_INITIAL_SIZE];
+ int[] twovals = new int[TWO_HEAP_INITIAL_SIZE];
+ double[] fourheap = new double[Math.max(21, minsize - TWO_HEAP_MAX_SIZE)];
+ int[] fourvals = new int[Math.max(21, minsize - TWO_HEAP_MAX_SIZE)];
+ this.twoheap = twoheap;
+ this.twovals = twovals;
+ this.fourheap = fourheap;
+ this.fourvals = fourvals;
+ }
+ this.size = 0;
+ this.modCount = 0;
+ }
+
+ @Override
+ public void clear() {
+ size = 0;
+ ++modCount;
+ fourheap = null;
+ fourvals = null;
+ Arrays.fill(twoheap, 0.0);
+ Arrays.fill(twovals, 0);
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return (size == 0);
+ }
+
+ @Override
+ public void add(double o, int v) {
+ final double co = o;
+ final int cv = v;
+ // System.err.println("Add: " + o);
+ if (size < TWO_HEAP_MAX_SIZE) {
+ if (size >= twoheap.length) {
+ // Grow by one layer.
+ twoheap = Arrays.copyOf(twoheap, twoheap.length + twoheap.length + 1);
+ twovals = Arrays.copyOf(twovals, twovals.length + twovals.length + 1);
+ }
+ final int twopos = size;
+ twoheap[twopos] = co;
+ twovals[twopos] = cv;
+ ++size;
+ heapifyUp2(twopos, co, cv);
+ ++modCount;
+ } else {
+ final int fourpos = size - TWO_HEAP_MAX_SIZE;
+ if (fourheap == null) {
+ fourheap = new double[FOUR_HEAP_INITIAL_SIZE];
+ fourvals = new int[FOUR_HEAP_INITIAL_SIZE];
+ } else if (fourpos >= fourheap.length) {
+ // Grow extension heap by half.
+ fourheap = Arrays.copyOf(fourheap, fourheap.length + (fourheap.length >> 1));
+ fourvals = Arrays.copyOf(fourvals, fourvals.length + (fourvals.length >> 1));
+ }
+ fourheap[fourpos] = co;
+ fourvals[fourpos] = cv;
+ ++size;
+ heapifyUp4(fourpos, co, cv);
+ ++modCount;
+ }
+ }
+
+ @Override
+ public void add(double key, int val, int max) {
+ if (size < max) {
+ add(key, val);
+ } else if (twoheap[0] <= key) {
+ replaceTopElement(key, val);
+ }
+ }
+
+ @Override
+ public void replaceTopElement(double reinsert, int val) {
+ heapifyDown(reinsert, val);
+ ++modCount;
+ }
+
+ /**
+ * Heapify-Up method for 2-ary heap.
+ *
+ * @param twopos Position in 2-ary heap.
+ * @param cur Current object
+ * @param val Current value
+ */
+ private void heapifyUp2(int twopos, double cur, int val) {
+ while (twopos > 0) {
+ final int parent = (twopos - 1) >>> 1;
+ double par = twoheap[parent];
+ if (cur >= par) {
+ break;
+ }
+ twoheap[twopos] = par;
+ twovals[twopos] = twovals[parent];
+ twopos = parent;
+ }
+ twoheap[twopos] = cur;
+ twovals[twopos] = val;
+ }
+
+ /**
+ * Heapify-Up method for 4-ary heap.
+ *
+ * @param fourpos Position in 4-ary heap.
+ * @param cur Current object
+ * @param val Current value
+ */
+ private void heapifyUp4(int fourpos, double cur, int val) {
+ while (fourpos > 0) {
+ final int parent = (fourpos - 1) >> 2;
+ double par = fourheap[parent];
+ if (cur >= par) {
+ break;
+ }
+ fourheap[fourpos] = par;
+ fourvals[fourpos] = fourvals[parent];
+ fourpos = parent;
+ }
+ if (fourpos == 0 && twoheap[0] > cur) {
+ fourheap[0] = twoheap[0];
+ fourvals[0] = twovals[0];
+ twoheap[0] = cur;
+ twovals[0] = val;
+ } else {
+ fourheap[fourpos] = cur;
+ fourvals[fourpos] = val;
+ }
+ }
+
+ @Override
+ public void poll() {
+ --size;
+ // Replacement object:
+ if (size >= TWO_HEAP_MAX_SIZE) {
+ final int last = size - TWO_HEAP_MAX_SIZE;
+ final double reinsert = fourheap[last];
+ final int reinsertv = fourvals[last];
+ fourheap[last] = 0.0;
+ fourvals[last] = 0;
+ heapifyDown(reinsert, reinsertv);
+ } else if (size > 0) {
+ final double reinsert = twoheap[size];
+ final int reinsertv = twovals[size];
+ twoheap[size] = 0.0;
+ twovals[size] = 0;
+ heapifyDown(reinsert, reinsertv);
+ } else {
+ twoheap[0] = 0.0;
+ twovals[0] = 0;
+ }
+ ++modCount;
+ }
+
+ /**
+ * Invoke heapify-down for the root object.
+ *
+ * @param reinsert Object to insert.
+ * @param val Value to reinsert.
+ */
+ private void heapifyDown(double reinsert, int val) {
+ if (size > TWO_HEAP_MAX_SIZE) {
+ // Special case: 3-ary situation.
+ final int best = (twoheap[1] <= twoheap[2]) ? 1 : 2;
+ if (fourheap[0] < twoheap[best]) {
+ twoheap[0] = fourheap[0];
+ twovals[0] = fourvals[0];
+ heapifyDown4(0, reinsert, val);
+ } else {
+ twoheap[0] = twoheap[best];
+ twovals[0] = twovals[best];
+ heapifyDown2(best, reinsert, val);
+ }
+ return;
+ }
+ heapifyDown2(0, reinsert, val);
+ }
+
+ /**
+ * Heapify-Down for 2-ary heap.
+ *
+ * @param twopos Position in 2-ary heap.
+ * @param cur Current object
+ * @param val Value to reinsert.
+ */
+ private void heapifyDown2(int twopos, double cur, int val) {
+ final int stop = Math.min(size, TWO_HEAP_MAX_SIZE) >>> 1;
+ while (twopos < stop) {
+ int bestchild = (twopos << 1) + 1;
+ double best = twoheap[bestchild];
+ final int right = bestchild + 1;
+ if (right < size && best > twoheap[right]) {
+ bestchild = right;
+ best = twoheap[right];
+ }
+ if (cur <= best) {
+ break;
+ }
+ twoheap[twopos] = best;
+ twovals[twopos] = twovals[bestchild];
+ twopos = bestchild;
+ }
+ twoheap[twopos] = cur;
+ twovals[twopos] = val;
+ }
+
+ /**
+ * Heapify-Down for 4-ary heap.
+ *
+ * @param fourpos Position in 4-ary heap.
+ * @param cur Current object
+ * @param val Value to reinsert.
+ */
+ private void heapifyDown4(int fourpos, double cur, int val) {
+ final int stop = (size - TWO_HEAP_MAX_SIZE + 2) >>> 2;
+ while (fourpos < stop) {
+ final int child = (fourpos << 2) + 1;
+ double best = fourheap[child];
+ int bestchild = child, candidate = child + 1, minsize = candidate + TWO_HEAP_MAX_SIZE;
+ if (size > minsize) {
+ double nextchild = fourheap[candidate];
+ if (best > nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+
+ minsize += 2;
+ if (size >= minsize) {
+ nextchild = fourheap[++candidate];
+ if (best > nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+
+ if (size > minsize) {
+ nextchild = fourheap[++candidate];
+ if (best > nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+ }
+ }
+ }
+ if (cur <= best) {
+ break;
+ }
+ fourheap[fourpos] = best;
+ fourvals[fourpos] = fourvals[bestchild];
+ fourpos = bestchild;
+ }
+ fourheap[fourpos] = cur;
+ fourvals[fourpos] = val;
+ }
+
+ @Override
+ public double peekKey() {
+ return twoheap[0];
+ }
+
+ @Override
+ public int peekValue() {
+ return twovals[0];
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder buf = new StringBuilder();
+ buf.append(DoubleIntegerMinHeap.class.getSimpleName()).append(" [");
+ for (UnsortedIter iter = new UnsortedIter(); iter.valid(); iter.advance()) {
+ buf.append(iter.getKey()).append(':').append(iter.getValue()).append(',');
+ }
+ buf.append(']');
+ return buf.toString();
+ }
+
+ @Override
+ public UnsortedIter unsortedIter() {
+ return new UnsortedIter();
+ }
+
+ /**
+ * Unsorted iterator - in heap order. Does not poll the heap.
+ *
+ * Use this class as follows:
+ *
+ * <pre>
+ * {@code
+ * for (DoubleIntegerHeap.UnsortedIter iter = heap.unsortedIter(); iter.valid(); iter.next()) {
+ * doSomething(iter.get());
+ * }
+ * }
+ * </pre>
+ *
+ * @author Erich Schubert
+ */
+ private class UnsortedIter implements DoubleIntegerHeap.UnsortedIter {
+ /**
+ * Iterator position.
+ */
+ protected int pos = 0;
+
+ /**
+ * Modification counter we were initialized at.
+ */
+ protected final int myModCount = modCount;
+
+ @Override
+ public boolean valid() {
+ if (modCount != myModCount) {
+ throw new ConcurrentModificationException();
+ }
+ return pos < size;
+ }
+
+ @Override
+ public void advance() {
+ pos++;
+ }
+
+ @Override
+ public double getKey() {
+ return ((pos < TWO_HEAP_MAX_SIZE) ? twoheap[pos] : fourheap[pos - TWO_HEAP_MAX_SIZE]);
+ }
+
+ @Override
+ public int getValue() {
+ return ((pos < TWO_HEAP_MAX_SIZE) ? twovals[pos] : fourvals[pos - TWO_HEAP_MAX_SIZE]);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleLongHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleLongHeap.java
new file mode 100644
index 00000000..b93adafa
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleLongHeap.java
@@ -0,0 +1,127 @@
+package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2012
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.utilities.datastructures.iterator.Iter;
+
+/**
+ * Basic in-memory heap interface, for double keys and long values.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has UnsortedIter
+ */
+public interface DoubleLongHeap {
+ /**
+ * Add a key-value pair to the heap
+ *
+ * @param key Key
+ * @param val Value
+ */
+ void add(double key, long val);
+
+ /**
+ * Add a key-value pair to the heap if it improves the top.
+ *
+ * @param key Key
+ * @param val Value
+ * @param k Desired maximum size
+ */
+ void add(double key, long val, int k);
+
+ /**
+ * Combined operation that removes the top element, and inserts a new element
+ * instead.
+ *
+ * @param key Key of new element
+ * @param val Value of new element
+ */
+ void replaceTopElement(double key, long val);
+
+ /**
+ * Get the current top key
+ *
+ * @return Top key
+ */
+ double peekKey();
+
+ /**
+ * Get the current top value
+ *
+ * @return Value
+ */
+ long peekValue();
+
+ /**
+ * Remove the first element
+ */
+ void poll();
+
+ /**
+ * Clear the heap contents.
+ */
+ void clear();
+
+ /**
+ * Query the size
+ *
+ * @return Size
+ */
+ public int size();
+
+ /**
+ * Is the heap empty?
+ *
+ * @return {@code true} when the size is 0.
+ */
+ public boolean isEmpty();
+
+ /**
+ * Get an unsorted iterator to inspect the heap.
+ *
+ * @return Iterator
+ */
+ UnsortedIter unsortedIter();
+
+ /**
+ * Unsorted iterator - in heap order. Does not poll the heap.
+ *
+ * @author Erich Schubert
+ */
+ public static interface UnsortedIter extends Iter {
+ /**
+ * Get the current key
+ *
+ * @return Current key
+ */
+ double getKey();
+
+ /**
+ * Get the current value
+ *
+ * @return Current value
+ */
+ long getValue();
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleLongMaxHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleLongMaxHeap.java
new file mode 100644
index 00000000..6d15656c
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleLongMaxHeap.java
@@ -0,0 +1,478 @@
+package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.Arrays;
+import java.util.ConcurrentModificationException;
+
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+
+/**
+ * Advanced priority queue class, based on a binary heap (for small sizes),
+ * which will for larger heaps be accompanied by a 4-ary heap (attached below
+ * the root of the two-ary heap, making the root actually 3-ary).
+ *
+ * This code was automatically instantiated for the types: Double and Long
+ *
+ * This combination was found to work quite well in benchmarks, but YMMV.
+ *
+ * Some other observations from benchmarking:
+ * <ul>
+ * <li>Bulk loading did not improve things</li>
+ * <li>Primitive heaps are substantially faster.</li>
+ * <li>Since an array in Java has an overhead of 12 bytes, odd-sized object and
+ * integer arrays are actually well aligned both for 2-ary and 4-ary heaps.</li>
+ * <li>Workload makes a huge difference. A load-once, poll-until-empty priority
+ * queue is something different than e.g. a top-k heap, which will see a lot of
+ * top element replacements.</li>
+ * <li>Random vs. increasing vs. decreasing vs. sawtooth insertion patterns for
+ * top-k make a difference.</li>
+ * <li>Different day, different benchmark results ...</li>
+ * </ul>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has UnsortedIter
+ */
+public class DoubleLongMaxHeap implements DoubleLongHeap {
+ /**
+ * Base heap.
+ */
+ protected double[] twoheap;
+
+ /**
+ * Base heap values.
+ */
+ protected long[] twovals;
+
+ /**
+ * Extension heap.
+ */
+ protected double[] fourheap;
+
+ /**
+ * Extension heapvalues.
+ */
+ protected long[] fourvals;
+
+ /**
+ * Current size of heap.
+ */
+ protected int size;
+
+ /**
+ * (Structural) modification counter. Used to invalidate iterators.
+ */
+ protected int modCount = 0;
+
+ /**
+ * Maximum size of the 2-ary heap. A complete 2-ary heap has (2^k-1) elements.
+ */
+ private final static int TWO_HEAP_MAX_SIZE = (1 << 9) - 1;
+
+ /**
+ * Initial size of the 2-ary heap.
+ */
+ private final static int TWO_HEAP_INITIAL_SIZE = (1 << 5) - 1;
+
+ /**
+ * Initial size of 4-ary heap when initialized.
+ *
+ * 21 = 4-ary heap of height 2: 1 + 4 + 4*4
+ *
+ * 85 = 4-ary heap of height 3: 21 + 4*4*4
+ *
+ * 341 = 4-ary heap of height 4: 85 + 4*4*4*4
+ *
+ * Since we last grew by 255 (to 511), let's use 341.
+ */
+ private final static int FOUR_HEAP_INITIAL_SIZE = 341;
+
+ /**
+ * Constructor, with default size.
+ */
+ public DoubleLongMaxHeap() {
+ super();
+ double[] twoheap = new double[TWO_HEAP_INITIAL_SIZE];
+ long[] twovals = new long[TWO_HEAP_INITIAL_SIZE];
+
+ this.twoheap = twoheap;
+ this.twovals = twovals;
+ this.fourheap = null;
+ this.fourvals = null;
+ this.size = 0;
+ this.modCount = 0;
+ }
+
+ /**
+ * Constructor, with given minimum size.
+ *
+ * @param minsize Minimum size
+ */
+ public DoubleLongMaxHeap(int minsize) {
+ super();
+ if (minsize < TWO_HEAP_MAX_SIZE) {
+ final int size = MathUtil.nextPow2Int(minsize + 1) - 1;
+ double[] twoheap = new double[size];
+ long[] twovals = new long[size];
+
+ this.twoheap = twoheap;
+ this.twovals = twovals;
+ this.fourheap = null;
+ this.fourvals = null;
+ } else {
+ double[] twoheap = new double[TWO_HEAP_INITIAL_SIZE];
+ long[] twovals = new long[TWO_HEAP_INITIAL_SIZE];
+ double[] fourheap = new double[Math.max(21, minsize - TWO_HEAP_MAX_SIZE)];
+ long[] fourvals = new long[Math.max(21, minsize - TWO_HEAP_MAX_SIZE)];
+ this.twoheap = twoheap;
+ this.twovals = twovals;
+ this.fourheap = fourheap;
+ this.fourvals = fourvals;
+ }
+ this.size = 0;
+ this.modCount = 0;
+ }
+
+ @Override
+ public void clear() {
+ size = 0;
+ ++modCount;
+ fourheap = null;
+ fourvals = null;
+ Arrays.fill(twoheap, 0.0);
+ Arrays.fill(twovals, 0);
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return (size == 0);
+ }
+
+ @Override
+ public void add(double o, long v) {
+ final double co = o;
+ final long cv = v;
+ // System.err.println("Add: " + o);
+ if (size < TWO_HEAP_MAX_SIZE) {
+ if (size >= twoheap.length) {
+ // Grow by one layer.
+ twoheap = Arrays.copyOf(twoheap, twoheap.length + twoheap.length + 1);
+ twovals = Arrays.copyOf(twovals, twovals.length + twovals.length + 1);
+ }
+ final int twopos = size;
+ twoheap[twopos] = co;
+ twovals[twopos] = cv;
+ ++size;
+ heapifyUp2(twopos, co, cv);
+ ++modCount;
+ } else {
+ final int fourpos = size - TWO_HEAP_MAX_SIZE;
+ if (fourheap == null) {
+ fourheap = new double[FOUR_HEAP_INITIAL_SIZE];
+ fourvals = new long[FOUR_HEAP_INITIAL_SIZE];
+ } else if (fourpos >= fourheap.length) {
+ // Grow extension heap by half.
+ fourheap = Arrays.copyOf(fourheap, fourheap.length + (fourheap.length >> 1));
+ fourvals = Arrays.copyOf(fourvals, fourvals.length + (fourvals.length >> 1));
+ }
+ fourheap[fourpos] = co;
+ fourvals[fourpos] = cv;
+ ++size;
+ heapifyUp4(fourpos, co, cv);
+ ++modCount;
+ }
+ }
+
+ @Override
+ public void add(double key, long val, int max) {
+ if (size < max) {
+ add(key, val);
+ } else if (twoheap[0] >= key) {
+ replaceTopElement(key, val);
+ }
+ }
+
+ @Override
+ public void replaceTopElement(double reinsert, long val) {
+ heapifyDown(reinsert, val);
+ ++modCount;
+ }
+
+ /**
+ * Heapify-Up method for 2-ary heap.
+ *
+ * @param twopos Position in 2-ary heap.
+ * @param cur Current object
+ * @param val Current value
+ */
+ private void heapifyUp2(int twopos, double cur, long val) {
+ while (twopos > 0) {
+ final int parent = (twopos - 1) >>> 1;
+ double par = twoheap[parent];
+ if (cur <= par) {
+ break;
+ }
+ twoheap[twopos] = par;
+ twovals[twopos] = twovals[parent];
+ twopos = parent;
+ }
+ twoheap[twopos] = cur;
+ twovals[twopos] = val;
+ }
+
+ /**
+ * Heapify-Up method for 4-ary heap.
+ *
+ * @param fourpos Position in 4-ary heap.
+ * @param cur Current object
+ * @param val Current value
+ */
+ private void heapifyUp4(int fourpos, double cur, long val) {
+ while (fourpos > 0) {
+ final int parent = (fourpos - 1) >> 2;
+ double par = fourheap[parent];
+ if (cur <= par) {
+ break;
+ }
+ fourheap[fourpos] = par;
+ fourvals[fourpos] = fourvals[parent];
+ fourpos = parent;
+ }
+ if (fourpos == 0 && twoheap[0] < cur) {
+ fourheap[0] = twoheap[0];
+ fourvals[0] = twovals[0];
+ twoheap[0] = cur;
+ twovals[0] = val;
+ } else {
+ fourheap[fourpos] = cur;
+ fourvals[fourpos] = val;
+ }
+ }
+
+ @Override
+ public void poll() {
+ --size;
+ // Replacement object:
+ if (size >= TWO_HEAP_MAX_SIZE) {
+ final int last = size - TWO_HEAP_MAX_SIZE;
+ final double reinsert = fourheap[last];
+ final long reinsertv = fourvals[last];
+ fourheap[last] = 0.0;
+ fourvals[last] = 0;
+ heapifyDown(reinsert, reinsertv);
+ } else if (size > 0) {
+ final double reinsert = twoheap[size];
+ final long reinsertv = twovals[size];
+ twoheap[size] = 0.0;
+ twovals[size] = 0;
+ heapifyDown(reinsert, reinsertv);
+ } else {
+ twoheap[0] = 0.0;
+ twovals[0] = 0;
+ }
+ ++modCount;
+ }
+
+ /**
+ * Invoke heapify-down for the root object.
+ *
+ * @param reinsert Object to insert.
+ * @param val Value to reinsert.
+ */
+ private void heapifyDown(double reinsert, long val) {
+ if (size > TWO_HEAP_MAX_SIZE) {
+ // Special case: 3-ary situation.
+ final int best = (twoheap[1] >= twoheap[2]) ? 1 : 2;
+ if (fourheap[0] > twoheap[best]) {
+ twoheap[0] = fourheap[0];
+ twovals[0] = fourvals[0];
+ heapifyDown4(0, reinsert, val);
+ } else {
+ twoheap[0] = twoheap[best];
+ twovals[0] = twovals[best];
+ heapifyDown2(best, reinsert, val);
+ }
+ return;
+ }
+ heapifyDown2(0, reinsert, val);
+ }
+
+ /**
+ * Heapify-Down for 2-ary heap.
+ *
+ * @param twopos Position in 2-ary heap.
+ * @param cur Current object
+ * @param val Value to reinsert.
+ */
+ private void heapifyDown2(int twopos, double cur, long val) {
+ final int stop = Math.min(size, TWO_HEAP_MAX_SIZE) >>> 1;
+ while (twopos < stop) {
+ int bestchild = (twopos << 1) + 1;
+ double best = twoheap[bestchild];
+ final int right = bestchild + 1;
+ if (right < size && best < twoheap[right]) {
+ bestchild = right;
+ best = twoheap[right];
+ }
+ if (cur >= best) {
+ break;
+ }
+ twoheap[twopos] = best;
+ twovals[twopos] = twovals[bestchild];
+ twopos = bestchild;
+ }
+ twoheap[twopos] = cur;
+ twovals[twopos] = val;
+ }
+
+ /**
+ * Heapify-Down for 4-ary heap.
+ *
+ * @param fourpos Position in 4-ary heap.
+ * @param cur Current object
+ * @param val Value to reinsert.
+ */
+ private void heapifyDown4(int fourpos, double cur, long val) {
+ final int stop = (size - TWO_HEAP_MAX_SIZE + 2) >>> 2;
+ while (fourpos < stop) {
+ final int child = (fourpos << 2) + 1;
+ double best = fourheap[child];
+ int bestchild = child, candidate = child + 1, minsize = candidate + TWO_HEAP_MAX_SIZE;
+ if (size > minsize) {
+ double nextchild = fourheap[candidate];
+ if (best < nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+
+ minsize += 2;
+ if (size >= minsize) {
+ nextchild = fourheap[++candidate];
+ if (best < nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+
+ if (size > minsize) {
+ nextchild = fourheap[++candidate];
+ if (best < nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+ }
+ }
+ }
+ if (cur >= best) {
+ break;
+ }
+ fourheap[fourpos] = best;
+ fourvals[fourpos] = fourvals[bestchild];
+ fourpos = bestchild;
+ }
+ fourheap[fourpos] = cur;
+ fourvals[fourpos] = val;
+ }
+
+ @Override
+ public double peekKey() {
+ return twoheap[0];
+ }
+
+ @Override
+ public long peekValue() {
+ return twovals[0];
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder buf = new StringBuilder();
+ buf.append(DoubleLongMaxHeap.class.getSimpleName()).append(" [");
+ for (UnsortedIter iter = new UnsortedIter(); iter.valid(); iter.advance()) {
+ buf.append(iter.getKey()).append(':').append(iter.getValue()).append(',');
+ }
+ buf.append(']');
+ return buf.toString();
+ }
+
+ @Override
+ public UnsortedIter unsortedIter() {
+ return new UnsortedIter();
+ }
+
+ /**
+ * Unsorted iterator - in heap order. Does not poll the heap.
+ *
+ * Use this class as follows:
+ *
+ * <pre>
+ * {@code
+ * for (DoubleLongHeap.UnsortedIter iter = heap.unsortedIter(); iter.valid(); iter.next()) {
+ * doSomething(iter.get());
+ * }
+ * }
+ * </pre>
+ *
+ * @author Erich Schubert
+ */
+ private class UnsortedIter implements DoubleLongHeap.UnsortedIter {
+ /**
+ * Iterator position.
+ */
+ protected int pos = 0;
+
+ /**
+ * Modification counter we were initialized at.
+ */
+ protected final int myModCount = modCount;
+
+ @Override
+ public boolean valid() {
+ if (modCount != myModCount) {
+ throw new ConcurrentModificationException();
+ }
+ return pos < size;
+ }
+
+ @Override
+ public void advance() {
+ pos++;
+ }
+
+ @Override
+ public double getKey() {
+ return ((pos < TWO_HEAP_MAX_SIZE) ? twoheap[pos] : fourheap[pos - TWO_HEAP_MAX_SIZE]);
+ }
+
+ @Override
+ public long getValue() {
+ return ((pos < TWO_HEAP_MAX_SIZE) ? twovals[pos] : fourvals[pos - TWO_HEAP_MAX_SIZE]);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleLongMinHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleLongMinHeap.java
new file mode 100644
index 00000000..d38eb6e3
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleLongMinHeap.java
@@ -0,0 +1,478 @@
+package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.Arrays;
+import java.util.ConcurrentModificationException;
+
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+
+/**
+ * Advanced priority queue class, based on a binary heap (for small sizes),
+ * which will for larger heaps be accompanied by a 4-ary heap (attached below
+ * the root of the two-ary heap, making the root actually 3-ary).
+ *
+ * This code was automatically instantiated for the types: Double and Long
+ *
+ * This combination was found to work quite well in benchmarks, but YMMV.
+ *
+ * Some other observations from benchmarking:
+ * <ul>
+ * <li>Bulk loading did not improve things</li>
+ * <li>Primitive heaps are substantially faster.</li>
+ * <li>Since an array in Java has an overhead of 12 bytes, odd-sized object and
+ * integer arrays are actually well aligned both for 2-ary and 4-ary heaps.</li>
+ * <li>Workload makes a huge difference. A load-once, poll-until-empty priority
+ * queue is something different than e.g. a top-k heap, which will see a lot of
+ * top element replacements.</li>
+ * <li>Random vs. increasing vs. decreasing vs. sawtooth insertion patterns for
+ * top-k make a difference.</li>
+ * <li>Different day, different benchmark results ...</li>
+ * </ul>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has UnsortedIter
+ */
+public class DoubleLongMinHeap implements DoubleLongHeap {
+ /**
+ * Base heap.
+ */
+ protected double[] twoheap;
+
+ /**
+ * Base heap values.
+ */
+ protected long[] twovals;
+
+ /**
+ * Extension heap.
+ */
+ protected double[] fourheap;
+
+ /**
+ * Extension heapvalues.
+ */
+ protected long[] fourvals;
+
+ /**
+ * Current size of heap.
+ */
+ protected int size;
+
+ /**
+ * (Structural) modification counter. Used to invalidate iterators.
+ */
+ protected int modCount = 0;
+
+ /**
+ * Maximum size of the 2-ary heap. A complete 2-ary heap has (2^k-1) elements.
+ */
+ private final static int TWO_HEAP_MAX_SIZE = (1 << 9) - 1;
+
+ /**
+ * Initial size of the 2-ary heap.
+ */
+ private final static int TWO_HEAP_INITIAL_SIZE = (1 << 5) - 1;
+
+ /**
+ * Initial size of 4-ary heap when initialized.
+ *
+ * 21 = 4-ary heap of height 2: 1 + 4 + 4*4
+ *
+ * 85 = 4-ary heap of height 3: 21 + 4*4*4
+ *
+ * 341 = 4-ary heap of height 4: 85 + 4*4*4*4
+ *
+ * Since we last grew by 255 (to 511), let's use 341.
+ */
+ private final static int FOUR_HEAP_INITIAL_SIZE = 341;
+
+ /**
+ * Constructor, with default size.
+ */
+ public DoubleLongMinHeap() {
+ super();
+ double[] twoheap = new double[TWO_HEAP_INITIAL_SIZE];
+ long[] twovals = new long[TWO_HEAP_INITIAL_SIZE];
+
+ this.twoheap = twoheap;
+ this.twovals = twovals;
+ this.fourheap = null;
+ this.fourvals = null;
+ this.size = 0;
+ this.modCount = 0;
+ }
+
+ /**
+ * Constructor, with given minimum size.
+ *
+ * @param minsize Minimum size
+ */
+ public DoubleLongMinHeap(int minsize) {
+ super();
+ if (minsize < TWO_HEAP_MAX_SIZE) {
+ final int size = MathUtil.nextPow2Int(minsize + 1) - 1;
+ double[] twoheap = new double[size];
+ long[] twovals = new long[size];
+
+ this.twoheap = twoheap;
+ this.twovals = twovals;
+ this.fourheap = null;
+ this.fourvals = null;
+ } else {
+ double[] twoheap = new double[TWO_HEAP_INITIAL_SIZE];
+ long[] twovals = new long[TWO_HEAP_INITIAL_SIZE];
+ double[] fourheap = new double[Math.max(21, minsize - TWO_HEAP_MAX_SIZE)];
+ long[] fourvals = new long[Math.max(21, minsize - TWO_HEAP_MAX_SIZE)];
+ this.twoheap = twoheap;
+ this.twovals = twovals;
+ this.fourheap = fourheap;
+ this.fourvals = fourvals;
+ }
+ this.size = 0;
+ this.modCount = 0;
+ }
+
+ @Override
+ public void clear() {
+ size = 0;
+ ++modCount;
+ fourheap = null;
+ fourvals = null;
+ Arrays.fill(twoheap, 0.0);
+ Arrays.fill(twovals, 0);
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return (size == 0);
+ }
+
+ @Override
+ public void add(double o, long v) {
+ final double co = o;
+ final long cv = v;
+ // System.err.println("Add: " + o);
+ if (size < TWO_HEAP_MAX_SIZE) {
+ if (size >= twoheap.length) {
+ // Grow by one layer.
+ twoheap = Arrays.copyOf(twoheap, twoheap.length + twoheap.length + 1);
+ twovals = Arrays.copyOf(twovals, twovals.length + twovals.length + 1);
+ }
+ final int twopos = size;
+ twoheap[twopos] = co;
+ twovals[twopos] = cv;
+ ++size;
+ heapifyUp2(twopos, co, cv);
+ ++modCount;
+ } else {
+ final int fourpos = size - TWO_HEAP_MAX_SIZE;
+ if (fourheap == null) {
+ fourheap = new double[FOUR_HEAP_INITIAL_SIZE];
+ fourvals = new long[FOUR_HEAP_INITIAL_SIZE];
+ } else if (fourpos >= fourheap.length) {
+ // Grow extension heap by half.
+ fourheap = Arrays.copyOf(fourheap, fourheap.length + (fourheap.length >> 1));
+ fourvals = Arrays.copyOf(fourvals, fourvals.length + (fourvals.length >> 1));
+ }
+ fourheap[fourpos] = co;
+ fourvals[fourpos] = cv;
+ ++size;
+ heapifyUp4(fourpos, co, cv);
+ ++modCount;
+ }
+ }
+
+ @Override
+ public void add(double key, long val, int max) {
+ if (size < max) {
+ add(key, val);
+ } else if (twoheap[0] <= key) {
+ replaceTopElement(key, val);
+ }
+ }
+
+ @Override
+ public void replaceTopElement(double reinsert, long val) {
+ heapifyDown(reinsert, val);
+ ++modCount;
+ }
+
+ /**
+ * Heapify-Up method for 2-ary heap.
+ *
+ * @param twopos Position in 2-ary heap.
+ * @param cur Current object
+ * @param val Current value
+ */
+ private void heapifyUp2(int twopos, double cur, long val) {
+ while (twopos > 0) {
+ final int parent = (twopos - 1) >>> 1;
+ double par = twoheap[parent];
+ if (cur >= par) {
+ break;
+ }
+ twoheap[twopos] = par;
+ twovals[twopos] = twovals[parent];
+ twopos = parent;
+ }
+ twoheap[twopos] = cur;
+ twovals[twopos] = val;
+ }
+
+ /**
+ * Heapify-Up method for 4-ary heap.
+ *
+ * @param fourpos Position in 4-ary heap.
+ * @param cur Current object
+ * @param val Current value
+ */
+ private void heapifyUp4(int fourpos, double cur, long val) {
+ while (fourpos > 0) {
+ final int parent = (fourpos - 1) >> 2;
+ double par = fourheap[parent];
+ if (cur >= par) {
+ break;
+ }
+ fourheap[fourpos] = par;
+ fourvals[fourpos] = fourvals[parent];
+ fourpos = parent;
+ }
+ if (fourpos == 0 && twoheap[0] > cur) {
+ fourheap[0] = twoheap[0];
+ fourvals[0] = twovals[0];
+ twoheap[0] = cur;
+ twovals[0] = val;
+ } else {
+ fourheap[fourpos] = cur;
+ fourvals[fourpos] = val;
+ }
+ }
+
+ @Override
+ public void poll() {
+ --size;
+ // Replacement object:
+ if (size >= TWO_HEAP_MAX_SIZE) {
+ final int last = size - TWO_HEAP_MAX_SIZE;
+ final double reinsert = fourheap[last];
+ final long reinsertv = fourvals[last];
+ fourheap[last] = 0.0;
+ fourvals[last] = 0;
+ heapifyDown(reinsert, reinsertv);
+ } else if (size > 0) {
+ final double reinsert = twoheap[size];
+ final long reinsertv = twovals[size];
+ twoheap[size] = 0.0;
+ twovals[size] = 0;
+ heapifyDown(reinsert, reinsertv);
+ } else {
+ twoheap[0] = 0.0;
+ twovals[0] = 0;
+ }
+ ++modCount;
+ }
+
+ /**
+ * Invoke heapify-down for the root object.
+ *
+ * @param reinsert Object to insert.
+ * @param val Value to reinsert.
+ */
+ private void heapifyDown(double reinsert, long val) {
+ if (size > TWO_HEAP_MAX_SIZE) {
+ // Special case: 3-ary situation.
+ final int best = (twoheap[1] <= twoheap[2]) ? 1 : 2;
+ if (fourheap[0] < twoheap[best]) {
+ twoheap[0] = fourheap[0];
+ twovals[0] = fourvals[0];
+ heapifyDown4(0, reinsert, val);
+ } else {
+ twoheap[0] = twoheap[best];
+ twovals[0] = twovals[best];
+ heapifyDown2(best, reinsert, val);
+ }
+ return;
+ }
+ heapifyDown2(0, reinsert, val);
+ }
+
+ /**
+ * Heapify-Down for 2-ary heap.
+ *
+ * @param twopos Position in 2-ary heap.
+ * @param cur Current object
+ * @param val Value to reinsert.
+ */
+ private void heapifyDown2(int twopos, double cur, long val) {
+ final int stop = Math.min(size, TWO_HEAP_MAX_SIZE) >>> 1;
+ while (twopos < stop) {
+ int bestchild = (twopos << 1) + 1;
+ double best = twoheap[bestchild];
+ final int right = bestchild + 1;
+ if (right < size && best > twoheap[right]) {
+ bestchild = right;
+ best = twoheap[right];
+ }
+ if (cur <= best) {
+ break;
+ }
+ twoheap[twopos] = best;
+ twovals[twopos] = twovals[bestchild];
+ twopos = bestchild;
+ }
+ twoheap[twopos] = cur;
+ twovals[twopos] = val;
+ }
+
+ /**
+ * Heapify-Down for 4-ary heap.
+ *
+ * @param fourpos Position in 4-ary heap.
+ * @param cur Current object
+ * @param val Value to reinsert.
+ */
+ private void heapifyDown4(int fourpos, double cur, long val) {
+ final int stop = (size - TWO_HEAP_MAX_SIZE + 2) >>> 2;
+ while (fourpos < stop) {
+ final int child = (fourpos << 2) + 1;
+ double best = fourheap[child];
+ int bestchild = child, candidate = child + 1, minsize = candidate + TWO_HEAP_MAX_SIZE;
+ if (size > minsize) {
+ double nextchild = fourheap[candidate];
+ if (best > nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+
+ minsize += 2;
+ if (size >= minsize) {
+ nextchild = fourheap[++candidate];
+ if (best > nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+
+ if (size > minsize) {
+ nextchild = fourheap[++candidate];
+ if (best > nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+ }
+ }
+ }
+ if (cur <= best) {
+ break;
+ }
+ fourheap[fourpos] = best;
+ fourvals[fourpos] = fourvals[bestchild];
+ fourpos = bestchild;
+ }
+ fourheap[fourpos] = cur;
+ fourvals[fourpos] = val;
+ }
+
+ @Override
+ public double peekKey() {
+ return twoheap[0];
+ }
+
+ @Override
+ public long peekValue() {
+ return twovals[0];
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder buf = new StringBuilder();
+ buf.append(DoubleLongMinHeap.class.getSimpleName()).append(" [");
+ for (UnsortedIter iter = new UnsortedIter(); iter.valid(); iter.advance()) {
+ buf.append(iter.getKey()).append(':').append(iter.getValue()).append(',');
+ }
+ buf.append(']');
+ return buf.toString();
+ }
+
+ @Override
+ public UnsortedIter unsortedIter() {
+ return new UnsortedIter();
+ }
+
+ /**
+ * Unsorted iterator - in heap order. Does not poll the heap.
+ *
+ * Use this class as follows:
+ *
+ * <pre>
+ * {@code
+ * for (DoubleLongHeap.UnsortedIter iter = heap.unsortedIter(); iter.valid(); iter.next()) {
+ * doSomething(iter.get());
+ * }
+ * }
+ * </pre>
+ *
+ * @author Erich Schubert
+ */
+ private class UnsortedIter implements DoubleLongHeap.UnsortedIter {
+ /**
+ * Iterator position.
+ */
+ protected int pos = 0;
+
+ /**
+ * Modification counter we were initialized at.
+ */
+ protected final int myModCount = modCount;
+
+ @Override
+ public boolean valid() {
+ if (modCount != myModCount) {
+ throw new ConcurrentModificationException();
+ }
+ return pos < size;
+ }
+
+ @Override
+ public void advance() {
+ pos++;
+ }
+
+ @Override
+ public double getKey() {
+ return ((pos < TWO_HEAP_MAX_SIZE) ? twoheap[pos] : fourheap[pos - TWO_HEAP_MAX_SIZE]);
+ }
+
+ @Override
+ public long getValue() {
+ return ((pos < TWO_HEAP_MAX_SIZE) ? twovals[pos] : fourvals[pos - TWO_HEAP_MAX_SIZE]);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleMaxHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleMaxHeap.java
index 1b7d6037..7ea28f14 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleMaxHeap.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleMaxHeap.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,40 +23,400 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import java.util.Arrays;
+import java.util.ConcurrentModificationException;
+
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+
/**
- * Basic in-memory heap structure.
+ * Advanced priority queue class, based on a binary heap (for small sizes),
+ * which will for larger heaps be accompanied by a 4-ary heap (attached below
+ * the root of the two-ary heap, making the root actually 3-ary).
+ *
+ * This code was automatically instantiated for the type: Double
*
- * This heap is built lazily: if you first add many elements, then poll the
- * heap, it will be bulk-loaded in O(n) instead of iteratively built in O(n log
- * n). This is implemented via a simple validTo counter.
+ * This combination was found to work quite well in benchmarks, but YMMV.
+ *
+ * Some other observations from benchmarking:
+ * <ul>
+ * <li>Bulk loading did not improve things</li>
+ * <li>Primitive heaps are substantially faster.</li>
+ * <li>Since an array in Java has an overhead of 12 bytes, odd-sized object and
+ * integer arrays are actually well aligned both for 2-ary and 4-ary heaps.</li>
+ * <li>Workload makes a huge difference. A load-once, poll-until-empty priority
+ * queue is something different than e.g. a top-k heap, which will see a lot of
+ * top element replacements.</li>
+ * <li>Random vs. increasing vs. decreasing vs. sawtooth insertion patterns for
+ * top-k make a difference.</li>
+ * <li>Different day, different benchmark results ...</li>
+ * </ul>
*
* @author Erich Schubert
+ *
+ * @apiviz.has UnsortedIter
*/
-public class DoubleMaxHeap extends DoubleHeap {
+public class DoubleMaxHeap implements DoubleHeap {
+ /**
+ * Base heap.
+ */
+ protected double[] twoheap;
+
+ /**
+ * Extension heap.
+ */
+ protected double[] fourheap;
+
+ /**
+ * Current size of heap.
+ */
+ protected int size;
+
+ /**
+ * (Structural) modification counter. Used to invalidate iterators.
+ */
+ protected int modCount = 0;
+
+ /**
+ * Maximum size of the 2-ary heap. A complete 2-ary heap has (2^k-1) elements.
+ */
+ private final static int TWO_HEAP_MAX_SIZE = (1 << 9) - 1;
+
/**
- * Constructor with default capacity.
+ * Initial size of the 2-ary heap.
+ */
+ private final static int TWO_HEAP_INITIAL_SIZE = (1 << 5) - 1;
+
+ /**
+ * Initial size of 4-ary heap when initialized.
+ *
+ * 21 = 4-ary heap of height 2: 1 + 4 + 4*4
+ *
+ * 85 = 4-ary heap of height 3: 21 + 4*4*4
+ *
+ * 341 = 4-ary heap of height 4: 85 + 4*4*4*4
+ *
+ * Since we last grew by 255 (to 511), let's use 341.
+ */
+ private final static int FOUR_HEAP_INITIAL_SIZE = 341;
+
+ /**
+ * Constructor, with default size.
*/
public DoubleMaxHeap() {
- super(DEFAULT_INITIAL_CAPACITY);
+ super();
+ double[] twoheap = new double[TWO_HEAP_INITIAL_SIZE];
+
+ this.twoheap = twoheap;
+ this.fourheap = null;
+ this.size = 0;
+ this.modCount = 0;
}
/**
- * Constructor with initial capacity.
+ * Constructor, with given minimum size.
*
- * @param size initial capacity
+ * @param minsize Minimum size
*/
- public DoubleMaxHeap(int size) {
- super(size);
+ public DoubleMaxHeap(int minsize) {
+ super();
+ if (minsize < TWO_HEAP_MAX_SIZE) {
+ final int size = MathUtil.nextPow2Int(minsize + 1) - 1;
+ double[] twoheap = new double[size];
+
+ this.twoheap = twoheap;
+ this.fourheap = null;
+ } else {
+ double[] twoheap = new double[TWO_HEAP_INITIAL_SIZE];
+ double[] fourheap = new double[Math.max(21, minsize - TWO_HEAP_MAX_SIZE)];
+ this.twoheap = twoheap;
+ this.fourheap = fourheap;
+ }
+ this.size = 0;
+ this.modCount = 0;
+ }
+
+ @Override
+ public void clear() {
+ size = 0;
+ ++modCount;
+ fourheap = null;
+ Arrays.fill(twoheap, 0.0);
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return (size == 0);
+ }
+
+ @Override
+ public void add(double o) {
+ final double co = o;
+ // System.err.println("Add: " + o);
+ if (size < TWO_HEAP_MAX_SIZE) {
+ if (size >= twoheap.length) {
+ // Grow by one layer.
+ twoheap = Arrays.copyOf(twoheap, twoheap.length + twoheap.length + 1);
+ }
+ final int twopos = size;
+ twoheap[twopos] = co;
+ ++size;
+ heapifyUp2(twopos, co);
+ ++modCount;
+ } else {
+ final int fourpos = size - TWO_HEAP_MAX_SIZE;
+ if (fourheap == null) {
+ fourheap = new double[FOUR_HEAP_INITIAL_SIZE];
+ } else if (fourpos >= fourheap.length) {
+ // Grow extension heap by half.
+ fourheap = Arrays.copyOf(fourheap, fourheap.length + (fourheap.length >> 1));
+ }
+ fourheap[fourpos] = co;
+ ++size;
+ heapifyUp4(fourpos, co);
+ ++modCount;
+ }
+ }
+
+ @Override
+ public void add(double key, int max) {
+ if (size < max) {
+ add(key);
+ } else if (twoheap[0] >= key) {
+ replaceTopElement(key);
+ }
+ }
+
+ @Override
+ public double replaceTopElement(double reinsert) {
+ final double ret = twoheap[0];
+ heapifyDown( reinsert);
+ ++modCount;
+ return ret;
+ }
+
+ /**
+ * Heapify-Up method for 2-ary heap.
+ *
+ * @param twopos Position in 2-ary heap.
+ * @param cur Current object
+ */
+ private void heapifyUp2(int twopos, double cur) {
+ while (twopos > 0) {
+ final int parent = (twopos - 1) >>> 1;
+ double par = twoheap[parent];
+ if (cur <= par) {
+ break;
+ }
+ twoheap[twopos] = par;
+ twopos = parent;
+ }
+ twoheap[twopos] = cur;
+ }
+
+ /**
+ * Heapify-Up method for 4-ary heap.
+ *
+ * @param fourpos Position in 4-ary heap.
+ * @param cur Current object
+ */
+ private void heapifyUp4(int fourpos, double cur) {
+ while (fourpos > 0) {
+ final int parent = (fourpos - 1) >> 2;
+ double par = fourheap[parent];
+ if (cur <= par) {
+ break;
+ }
+ fourheap[fourpos] = par;
+ fourpos = parent;
+ }
+ if (fourpos == 0 && twoheap[0] < cur) {
+ fourheap[0] = twoheap[0];
+ twoheap[0] = cur;
+ } else {
+ fourheap[fourpos] = cur;
+ }
+ }
+
+ @Override
+ public double poll() {
+ final double ret = twoheap[0];
+ --size;
+ // Replacement object:
+ if (size >= TWO_HEAP_MAX_SIZE) {
+ final int last = size - TWO_HEAP_MAX_SIZE;
+ final double reinsert = fourheap[last];
+ fourheap[last] = 0.0;
+ heapifyDown(reinsert);
+ } else if (size > 0) {
+ final double reinsert = twoheap[size];
+ twoheap[size] = 0.0;
+ heapifyDown(reinsert);
+ } else {
+ twoheap[0] = 0.0;
+ }
+ ++modCount;
+ return ret;
+ }
+
+ /**
+ * Invoke heapify-down for the root object.
+ *
+ * @param reinsert Object to insert.
+ */
+ private void heapifyDown(double reinsert) {
+ if (size > TWO_HEAP_MAX_SIZE) {
+ // Special case: 3-ary situation.
+ final int best = (twoheap[1] >= twoheap[2]) ? 1 : 2;
+ if (fourheap[0] > twoheap[best]) {
+ twoheap[0] = fourheap[0];
+ heapifyDown4(0, reinsert);
+ } else {
+ twoheap[0] = twoheap[best];
+ heapifyDown2(best, reinsert);
+ }
+ return;
+ }
+ heapifyDown2(0, reinsert);
+ }
+
+ /**
+ * Heapify-Down for 2-ary heap.
+ *
+ * @param twopos Position in 2-ary heap.
+ * @param cur Current object
+ */
+ private void heapifyDown2(int twopos, double cur) {
+ final int stop = Math.min(size, TWO_HEAP_MAX_SIZE) >>> 1;
+ while (twopos < stop) {
+ int bestchild = (twopos << 1) + 1;
+ double best = twoheap[bestchild];
+ final int right = bestchild + 1;
+ if (right < size && best < twoheap[right]) {
+ bestchild = right;
+ best = twoheap[right];
+ }
+ if (cur >= best) {
+ break;
+ }
+ twoheap[twopos] = best;
+ twopos = bestchild;
+ }
+ twoheap[twopos] = cur;
}
/**
- * Compare two objects
+ * Heapify-Down for 4-ary heap.
*
- * @param o1 First object
- * @param o2 Second object
+ * @param fourpos Position in 4-ary heap.
+ * @param cur Current object
*/
+ private void heapifyDown4(int fourpos, double cur) {
+ final int stop = (size - TWO_HEAP_MAX_SIZE + 2) >>> 2;
+ while (fourpos < stop) {
+ final int child = (fourpos << 2) + 1;
+ double best = fourheap[child];
+ int bestchild = child, candidate = child + 1, minsize = candidate + TWO_HEAP_MAX_SIZE;
+ if (size > minsize) {
+ double nextchild = fourheap[candidate];
+ if (best < nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+
+ minsize += 2;
+ if (size >= minsize) {
+ nextchild = fourheap[++candidate];
+ if (best < nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+
+ if (size > minsize) {
+ nextchild = fourheap[++candidate];
+ if (best < nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+ }
+ }
+ }
+ if (cur >= best) {
+ break;
+ }
+ fourheap[fourpos] = best;
+ fourpos = bestchild;
+ }
+ fourheap[fourpos] = cur;
+ }
+
+ @Override
+ public double peek() {
+ return twoheap[0];
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder buf = new StringBuilder();
+ buf.append(DoubleMaxHeap.class.getSimpleName()).append(" [");
+ for (UnsortedIter iter = new UnsortedIter(); iter.valid(); iter.advance()) {
+ buf.append(iter.get()).append(',');
+ }
+ buf.append(']');
+ return buf.toString();
+ }
+
@Override
- protected boolean comp(double o1, double o2) {
- return o1 < o2;
+ public UnsortedIter unsortedIter() {
+ return new UnsortedIter();
+ }
+
+ /**
+ * Unsorted iterator - in heap order. Does not poll the heap.
+ *
+ * Use this class as follows:
+ *
+ * <pre>
+ * {@code
+ * for (DoubleHeap.UnsortedIter iter = heap.unsortedIter(); iter.valid(); iter.next()) {
+ * doSomething(iter.get());
+ * }
+ * }
+ * </pre>
+ *
+ * @author Erich Schubert
+ */
+ private class UnsortedIter implements DoubleHeap.UnsortedIter {
+ /**
+ * Iterator position.
+ */
+ protected int pos = 0;
+
+ /**
+ * Modification counter we were initialized at.
+ */
+ protected final int myModCount = modCount;
+
+ @Override
+ public boolean valid() {
+ if (modCount != myModCount) {
+ throw new ConcurrentModificationException();
+ }
+ return pos < size;
+ }
+
+ @Override
+ public void advance() {
+ pos++;
+ }
+
+ @Override
+ public double get() {
+ return ((pos < TWO_HEAP_MAX_SIZE) ? twoheap[pos] : fourheap[pos - TWO_HEAP_MAX_SIZE]);
+ }
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleMinHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleMinHeap.java
index 2ce05ff9..e9334153 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleMinHeap.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleMinHeap.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,40 +23,400 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import java.util.Arrays;
+import java.util.ConcurrentModificationException;
+
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+
/**
- * Basic in-memory heap structure.
+ * Advanced priority queue class, based on a binary heap (for small sizes),
+ * which will for larger heaps be accompanied by a 4-ary heap (attached below
+ * the root of the two-ary heap, making the root actually 3-ary).
+ *
+ * This code was automatically instantiated for the type: Double
*
- * This heap is built lazily: if you first add many elements, then poll the
- * heap, it will be bulk-loaded in O(n) instead of iteratively built in O(n log
- * n). This is implemented via a simple validTo counter.
+ * This combination was found to work quite well in benchmarks, but YMMV.
+ *
+ * Some other observations from benchmarking:
+ * <ul>
+ * <li>Bulk loading did not improve things</li>
+ * <li>Primitive heaps are substantially faster.</li>
+ * <li>Since an array in Java has an overhead of 12 bytes, odd-sized object and
+ * integer arrays are actually well aligned both for 2-ary and 4-ary heaps.</li>
+ * <li>Workload makes a huge difference. A load-once, poll-until-empty priority
+ * queue is something different than e.g. a top-k heap, which will see a lot of
+ * top element replacements.</li>
+ * <li>Random vs. increasing vs. decreasing vs. sawtooth insertion patterns for
+ * top-k make a difference.</li>
+ * <li>Different day, different benchmark results ...</li>
+ * </ul>
*
* @author Erich Schubert
+ *
+ * @apiviz.has UnsortedIter
*/
-public class DoubleMinHeap extends DoubleHeap {
+public class DoubleMinHeap implements DoubleHeap {
+ /**
+ * Base heap.
+ */
+ protected double[] twoheap;
+
+ /**
+ * Extension heap.
+ */
+ protected double[] fourheap;
+
+ /**
+ * Current size of heap.
+ */
+ protected int size;
+
+ /**
+ * (Structural) modification counter. Used to invalidate iterators.
+ */
+ protected int modCount = 0;
+
+ /**
+ * Maximum size of the 2-ary heap. A complete 2-ary heap has (2^k-1) elements.
+ */
+ private final static int TWO_HEAP_MAX_SIZE = (1 << 9) - 1;
+
/**
- * Constructor with default capacity.
+ * Initial size of the 2-ary heap.
+ */
+ private final static int TWO_HEAP_INITIAL_SIZE = (1 << 5) - 1;
+
+ /**
+ * Initial size of 4-ary heap when initialized.
+ *
+ * 21 = 4-ary heap of height 2: 1 + 4 + 4*4
+ *
+ * 85 = 4-ary heap of height 3: 21 + 4*4*4
+ *
+ * 341 = 4-ary heap of height 4: 85 + 4*4*4*4
+ *
+ * Since we last grew by 255 (to 511), let's use 341.
+ */
+ private final static int FOUR_HEAP_INITIAL_SIZE = 341;
+
+ /**
+ * Constructor, with default size.
*/
public DoubleMinHeap() {
- super(DEFAULT_INITIAL_CAPACITY);
+ super();
+ double[] twoheap = new double[TWO_HEAP_INITIAL_SIZE];
+
+ this.twoheap = twoheap;
+ this.fourheap = null;
+ this.size = 0;
+ this.modCount = 0;
}
/**
- * Constructor with initial capacity.
+ * Constructor, with given minimum size.
*
- * @param size initial capacity
+ * @param minsize Minimum size
*/
- public DoubleMinHeap(int size) {
- super(size);
+ public DoubleMinHeap(int minsize) {
+ super();
+ if (minsize < TWO_HEAP_MAX_SIZE) {
+ final int size = MathUtil.nextPow2Int(minsize + 1) - 1;
+ double[] twoheap = new double[size];
+
+ this.twoheap = twoheap;
+ this.fourheap = null;
+ } else {
+ double[] twoheap = new double[TWO_HEAP_INITIAL_SIZE];
+ double[] fourheap = new double[Math.max(21, minsize - TWO_HEAP_MAX_SIZE)];
+ this.twoheap = twoheap;
+ this.fourheap = fourheap;
+ }
+ this.size = 0;
+ this.modCount = 0;
+ }
+
+ @Override
+ public void clear() {
+ size = 0;
+ ++modCount;
+ fourheap = null;
+ Arrays.fill(twoheap, 0.0);
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return (size == 0);
+ }
+
+ @Override
+ public void add(double o) {
+ final double co = o;
+ // System.err.println("Add: " + o);
+ if (size < TWO_HEAP_MAX_SIZE) {
+ if (size >= twoheap.length) {
+ // Grow by one layer.
+ twoheap = Arrays.copyOf(twoheap, twoheap.length + twoheap.length + 1);
+ }
+ final int twopos = size;
+ twoheap[twopos] = co;
+ ++size;
+ heapifyUp2(twopos, co);
+ ++modCount;
+ } else {
+ final int fourpos = size - TWO_HEAP_MAX_SIZE;
+ if (fourheap == null) {
+ fourheap = new double[FOUR_HEAP_INITIAL_SIZE];
+ } else if (fourpos >= fourheap.length) {
+ // Grow extension heap by half.
+ fourheap = Arrays.copyOf(fourheap, fourheap.length + (fourheap.length >> 1));
+ }
+ fourheap[fourpos] = co;
+ ++size;
+ heapifyUp4(fourpos, co);
+ ++modCount;
+ }
+ }
+
+ @Override
+ public void add(double key, int max) {
+ if (size < max) {
+ add(key);
+ } else if (twoheap[0] <= key) {
+ replaceTopElement(key);
+ }
+ }
+
+ @Override
+ public double replaceTopElement(double reinsert) {
+ final double ret = twoheap[0];
+ heapifyDown( reinsert);
+ ++modCount;
+ return ret;
+ }
+
+ /**
+ * Heapify-Up method for 2-ary heap.
+ *
+ * @param twopos Position in 2-ary heap.
+ * @param cur Current object
+ */
+ private void heapifyUp2(int twopos, double cur) {
+ while (twopos > 0) {
+ final int parent = (twopos - 1) >>> 1;
+ double par = twoheap[parent];
+ if (cur >= par) {
+ break;
+ }
+ twoheap[twopos] = par;
+ twopos = parent;
+ }
+ twoheap[twopos] = cur;
+ }
+
+ /**
+ * Heapify-Up method for 4-ary heap.
+ *
+ * @param fourpos Position in 4-ary heap.
+ * @param cur Current object
+ */
+ private void heapifyUp4(int fourpos, double cur) {
+ while (fourpos > 0) {
+ final int parent = (fourpos - 1) >> 2;
+ double par = fourheap[parent];
+ if (cur >= par) {
+ break;
+ }
+ fourheap[fourpos] = par;
+ fourpos = parent;
+ }
+ if (fourpos == 0 && twoheap[0] > cur) {
+ fourheap[0] = twoheap[0];
+ twoheap[0] = cur;
+ } else {
+ fourheap[fourpos] = cur;
+ }
+ }
+
+ @Override
+ public double poll() {
+ final double ret = twoheap[0];
+ --size;
+ // Replacement object:
+ if (size >= TWO_HEAP_MAX_SIZE) {
+ final int last = size - TWO_HEAP_MAX_SIZE;
+ final double reinsert = fourheap[last];
+ fourheap[last] = 0.0;
+ heapifyDown(reinsert);
+ } else if (size > 0) {
+ final double reinsert = twoheap[size];
+ twoheap[size] = 0.0;
+ heapifyDown(reinsert);
+ } else {
+ twoheap[0] = 0.0;
+ }
+ ++modCount;
+ return ret;
+ }
+
+ /**
+ * Invoke heapify-down for the root object.
+ *
+ * @param reinsert Object to insert.
+ */
+ private void heapifyDown(double reinsert) {
+ if (size > TWO_HEAP_MAX_SIZE) {
+ // Special case: 3-ary situation.
+ final int best = (twoheap[1] <= twoheap[2]) ? 1 : 2;
+ if (fourheap[0] < twoheap[best]) {
+ twoheap[0] = fourheap[0];
+ heapifyDown4(0, reinsert);
+ } else {
+ twoheap[0] = twoheap[best];
+ heapifyDown2(best, reinsert);
+ }
+ return;
+ }
+ heapifyDown2(0, reinsert);
+ }
+
+ /**
+ * Heapify-Down for 2-ary heap.
+ *
+ * @param twopos Position in 2-ary heap.
+ * @param cur Current object
+ */
+ private void heapifyDown2(int twopos, double cur) {
+ final int stop = Math.min(size, TWO_HEAP_MAX_SIZE) >>> 1;
+ while (twopos < stop) {
+ int bestchild = (twopos << 1) + 1;
+ double best = twoheap[bestchild];
+ final int right = bestchild + 1;
+ if (right < size && best > twoheap[right]) {
+ bestchild = right;
+ best = twoheap[right];
+ }
+ if (cur <= best) {
+ break;
+ }
+ twoheap[twopos] = best;
+ twopos = bestchild;
+ }
+ twoheap[twopos] = cur;
}
/**
- * Compare two objects
+ * Heapify-Down for 4-ary heap.
*
- * @param o1 First object
- * @param o2 Second object
+ * @param fourpos Position in 4-ary heap.
+ * @param cur Current object
*/
+ private void heapifyDown4(int fourpos, double cur) {
+ final int stop = (size - TWO_HEAP_MAX_SIZE + 2) >>> 2;
+ while (fourpos < stop) {
+ final int child = (fourpos << 2) + 1;
+ double best = fourheap[child];
+ int bestchild = child, candidate = child + 1, minsize = candidate + TWO_HEAP_MAX_SIZE;
+ if (size > minsize) {
+ double nextchild = fourheap[candidate];
+ if (best > nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+
+ minsize += 2;
+ if (size >= minsize) {
+ nextchild = fourheap[++candidate];
+ if (best > nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+
+ if (size > minsize) {
+ nextchild = fourheap[++candidate];
+ if (best > nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+ }
+ }
+ }
+ if (cur <= best) {
+ break;
+ }
+ fourheap[fourpos] = best;
+ fourpos = bestchild;
+ }
+ fourheap[fourpos] = cur;
+ }
+
+ @Override
+ public double peek() {
+ return twoheap[0];
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder buf = new StringBuilder();
+ buf.append(DoubleMinHeap.class.getSimpleName()).append(" [");
+ for (UnsortedIter iter = new UnsortedIter(); iter.valid(); iter.advance()) {
+ buf.append(iter.get()).append(',');
+ }
+ buf.append(']');
+ return buf.toString();
+ }
+
@Override
- protected boolean comp(double o1, double o2) {
- return o1 > o2;
+ public UnsortedIter unsortedIter() {
+ return new UnsortedIter();
+ }
+
+ /**
+ * Unsorted iterator - in heap order. Does not poll the heap.
+ *
+ * Use this class as follows:
+ *
+ * <pre>
+ * {@code
+ * for (DoubleHeap.UnsortedIter iter = heap.unsortedIter(); iter.valid(); iter.next()) {
+ * doSomething(iter.get());
+ * }
+ * }
+ * </pre>
+ *
+ * @author Erich Schubert
+ */
+ private class UnsortedIter implements DoubleHeap.UnsortedIter {
+ /**
+ * Iterator position.
+ */
+ protected int pos = 0;
+
+ /**
+ * Modification counter we were initialized at.
+ */
+ protected final int myModCount = modCount;
+
+ @Override
+ public boolean valid() {
+ if (modCount != myModCount) {
+ throw new ConcurrentModificationException();
+ }
+ return pos < size;
+ }
+
+ @Override
+ public void advance() {
+ pos++;
+ }
+
+ @Override
+ public double get() {
+ return ((pos < TWO_HEAP_MAX_SIZE) ? twoheap[pos] : fourheap[pos - TWO_HEAP_MAX_SIZE]);
+ }
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleObjMaxHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleObjMaxHeap.java
deleted file mode 100644
index 8417309a..00000000
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleObjMaxHeap.java
+++ /dev/null
@@ -1,328 +0,0 @@
-package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
-
-/*
- This file is part of ELKI:
- Environment for Developing KDD-Applications Supported by Index-Structures
-
- Copyright (C) 2012
- Ludwig-Maximilians-Universität München
- Lehr- und Forschungseinheit für Datenbanksysteme
- ELKI Development Team
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-import java.util.Arrays;
-import java.util.Comparator;
-
-import de.lmu.ifi.dbs.elki.math.MathUtil;
-
-/**
- * Basic in-memory heap structure.
- *
- * This heap is built lazily: if you first add many elements, then poll the
- * heap, it will be bulk-loaded in O(n) instead of iteratively built in O(n log
- * n). This is implemented via a simple validTo counter.
- *
- * @author Erich Schubert
- *
- * @param <V> value type
- */
-public class DoubleObjMaxHeap<V> {
- /**
- * Heap storage: keys
- */
- protected double[] keys;
-
- /**
- * Heap storage: values
- */
- protected Object[] values;
-
- /**
- * Current number of objects
- */
- protected int size = 0;
-
- /**
- * Indicate up to where the heap is valid
- */
- protected int validSize = 0;
-
- /**
- * (Structural) modification counter. Used to invalidate iterators.
- */
- public transient int modCount = 0;
-
- /**
- * Default initial capacity
- */
- private static final int DEFAULT_INITIAL_CAPACITY = 11;
-
- /**
- * Default constructor: default capacity, natural ordering.
- */
- public DoubleObjMaxHeap() {
- this(DEFAULT_INITIAL_CAPACITY);
- }
-
- /**
- * Constructor with initial capacity and {@link Comparator}.
- *
- * @param size initial capacity
- */
- public DoubleObjMaxHeap(int size) {
- super();
- this.size = 0;
- this.keys = new double[size];
- this.values = new Object[size];
- }
-
- /**
- * Add a key-value pair to the heap
- *
- * @param key Key
- * @param val Value
- * @return Success code
- */
- public boolean add(double key, V val) {
- // resize when needed
- if(size + 1 > keys.length) {
- resize(size + 1);
- }
- // final int pos = size;
- this.keys[size] = key;
- this.values[size] = val;
- this.size += 1;
- heapifyUp(size - 1, key, val);
- validSize += 1;
- // We have changed - return true according to {@link Collection#put}
- modCount++;
- return true;
- }
-
- /**
- * Get the current top key
- *
- * @return Top key
- */
- public double peekKey() {
- if(size == 0) {
- throw new ArrayIndexOutOfBoundsException("Peek() on an empty heap!");
- }
- ensureValid();
- return keys[0];
- }
-
- /**
- * Get the current top value
- *
- * @return Value
- */
- @SuppressWarnings("unchecked")
- public V peekValue() {
- if(size == 0) {
- throw new ArrayIndexOutOfBoundsException("Peek() on an empty heap!");
- }
- ensureValid();
- return (V) values[0];
- }
-
- /**
- * Remove the first element
- */
- public void poll() {
- removeAt(0);
- }
-
- /**
- * Repair the heap
- */
- protected void ensureValid() {
- if(validSize != size) {
- if(size > 1) {
- // Parent of first invalid
- int nextmin = validSize > 0 ? ((validSize - 1) >>> 1) : 0;
- int curmin = MathUtil.nextAllOnesInt(nextmin); // Next line
- int nextmax = curmin - 1; // End of valid line
- int pos = (size - 2) >>> 1; // Parent of last element
- // System.err.println(validSize+"<="+size+" iter:"+pos+"->"+curmin+", "+nextmin);
- while(pos >= nextmin) {
- // System.err.println(validSize+"<="+size+" iter:"+pos+"->"+curmin);
- while(pos >= curmin) {
- if(!heapifyDown(pos, keys[pos], values[pos])) {
- final int parent = (pos - 1) >>> 1;
- if(parent < curmin) {
- nextmin = Math.min(nextmin, parent);
- nextmax = Math.max(nextmax, parent);
- }
- }
- pos--;
- }
- curmin = nextmin;
- pos = Math.min(pos, nextmax);
- nextmax = -1;
- }
- }
- validSize = size;
- }
- }
-
- /**
- * Remove the element at the given position.
- *
- * @param pos Element position.
- */
- protected void removeAt(int pos) {
- if(pos < 0 || pos >= size) {
- return;
- }
- // Replacement object:
- final double reinkey = keys[size - 1];
- final Object reinval = values[size - 1];
- values[size - 1] = null;
- // Keep heap in sync
- if(validSize == size) {
- size -= 1;
- validSize -= 1;
- heapifyDown(pos, reinkey, reinval);
- }
- else {
- size -= 1;
- validSize = Math.min(pos >>> 1, validSize);
- keys[pos] = reinkey;
- values[pos] = reinval;
- }
- modCount++;
- }
-
- /**
- * Execute a "Heapify Upwards" aka "SiftUp". Used in insertions.
- *
- * @param pos insertion position
- * @param curkey Current key
- * @param curval Current value
- */
- protected void heapifyUp(int pos, double curkey, Object curval) {
- while(pos > 0) {
- final int parent = (pos - 1) >>> 1;
- double parkey = keys[parent];
-
- if(curkey <= parkey) { // Compare
- break;
- }
- keys[pos] = parkey;
- values[pos] = values[parent];
- pos = parent;
- }
- keys[pos] = curkey;
- values[pos] = curval;
- }
-
- /**
- * Execute a "Heapify Downwards" aka "SiftDown". Used in deletions.
- *
- * @param ipos re-insertion position
- * @param curkey Current key
- * @param curval Current value
- * @return true when the order was changed
- */
- protected boolean heapifyDown(final int ipos, double curkey, Object curval) {
- int pos = ipos;
- final int half = size >>> 1;
- while(pos < half) {
- // Get left child (must exist!)
- int cpos = (pos << 1) + 1;
- double chikey = keys[cpos];
- Object chival = values[cpos];
- // Test right child, if present
- final int rchild = cpos + 1;
- if(rchild < size) {
- double right = keys[rchild];
- if(chikey < right) { // Compare
- cpos = rchild;
- chikey = right;
- chival = values[rchild];
- }
- }
-
- if(curkey >= chikey) { // Compare
- break;
- }
- keys[pos] = chikey;
- values[pos] = chival;
- pos = cpos;
- }
- keys[pos] = curkey;
- values[pos] = curval;
- return (pos == ipos);
- }
-
- /**
- * Query the size
- *
- * @return Size
- */
- public int size() {
- return this.size;
- }
-
- /**
- * Test whether we need to resize to have the requested capacity.
- *
- * @param requiredSize required capacity
- */
- protected final void resize(int requiredSize) {
- // Double until 64, then increase by 50% each time.
- int newCapacity = ((keys.length < 64) ? ((keys.length + 1) << 1) : ((keys.length >> 1) * 3));
- // overflow?
- if(newCapacity < 0) {
- throw new OutOfMemoryError();
- }
- if(requiredSize > newCapacity) {
- newCapacity = requiredSize;
- }
- keys = Arrays.copyOf(keys, newCapacity);
- values = Arrays.copyOf(values, newCapacity);
- }
-
- /**
- * Delete all elements from the heap.
- */
- public void clear() {
- // clean up references in the array for memory management
- Arrays.fill(values, null);
- this.size = 0;
- this.validSize = -1;
- modCount++;
- }
-
- /**
- * Test whether the heap is still valid.
- *
- * Debug method.
- *
- * @return {@code null} when the heap is correct
- */
- protected String checkHeap() {
- ensureValid();
- for(int i = 1; i < size; i++) {
- final int parent = (i - 1) >>> 1;
- if(keys[parent] < keys[i]) { // Compare
- return "@" + parent + ": " + keys[parent] + " < @" + i + ": " + keys[i];
- }
- }
- return null;
- }
-}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleObjMinHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleObjMinHeap.java
deleted file mode 100644
index 244277e8..00000000
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleObjMinHeap.java
+++ /dev/null
@@ -1,328 +0,0 @@
-package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
-
-/*
- This file is part of ELKI:
- Environment for Developing KDD-Applications Supported by Index-Structures
-
- Copyright (C) 2012
- Ludwig-Maximilians-Universität München
- Lehr- und Forschungseinheit für Datenbanksysteme
- ELKI Development Team
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-import java.util.Arrays;
-import java.util.Comparator;
-
-import de.lmu.ifi.dbs.elki.math.MathUtil;
-
-/**
- * Basic in-memory heap structure.
- *
- * This heap is built lazily: if you first add many elements, then poll the
- * heap, it will be bulk-loaded in O(n) instead of iteratively built in O(n log
- * n). This is implemented via a simple validTo counter.
- *
- * @author Erich Schubert
- *
- * @param <V> value type
- */
-public class DoubleObjMinHeap<V> {
- /**
- * Heap storage: keys
- */
- protected double[] keys;
-
- /**
- * Heap storage: values
- */
- protected Object[] values;
-
- /**
- * Current number of objects
- */
- protected int size = 0;
-
- /**
- * Indicate up to where the heap is valid
- */
- protected int validSize = 0;
-
- /**
- * (Structural) modification counter. Used to invalidate iterators.
- */
- public transient int modCount = 0;
-
- /**
- * Default initial capacity
- */
- private static final int DEFAULT_INITIAL_CAPACITY = 11;
-
- /**
- * Default constructor: default capacity, natural ordering.
- */
- public DoubleObjMinHeap() {
- this(DEFAULT_INITIAL_CAPACITY);
- }
-
- /**
- * Constructor with initial capacity and {@link Comparator}.
- *
- * @param size initial capacity
- */
- public DoubleObjMinHeap(int size) {
- super();
- this.size = 0;
- this.keys = new double[size];
- this.values = new Object[size];
- }
-
- /**
- * Add a key-value pair to the heap
- *
- * @param key Key
- * @param val Value
- * @return Success code
- */
- public boolean add(double key, V val) {
- // resize when needed
- if(size + 1 > keys.length) {
- resize(size + 1);
- }
- // final int pos = size;
- this.keys[size] = key;
- this.values[size] = val;
- this.size += 1;
- heapifyUp(size - 1, key, val);
- validSize += 1;
- // We have changed - return true according to {@link Collection#put}
- modCount++;
- return true;
- }
-
- /**
- * Get the current top key
- *
- * @return Top key
- */
- public double peekKey() {
- if(size == 0) {
- throw new ArrayIndexOutOfBoundsException("Peek() on an empty heap!");
- }
- ensureValid();
- return keys[0];
- }
-
- /**
- * Get the current top value
- *
- * @return Value
- */
- @SuppressWarnings("unchecked")
- public V peekValue() {
- if(size == 0) {
- throw new ArrayIndexOutOfBoundsException("Peek() on an empty heap!");
- }
- ensureValid();
- return (V) values[0];
- }
-
- /**
- * Remove the first element
- */
- public void poll() {
- removeAt(0);
- }
-
- /**
- * Repair the heap
- */
- protected void ensureValid() {
- if(validSize != size) {
- if(size > 1) {
- // Parent of first invalid
- int nextmin = validSize > 0 ? ((validSize - 1) >>> 1) : 0;
- int curmin = MathUtil.nextAllOnesInt(nextmin); // Next line
- int nextmax = curmin - 1; // End of valid line
- int pos = (size - 2) >>> 1; // Parent of last element
- // System.err.println(validSize+"<="+size+" iter:"+pos+"->"+curmin+", "+nextmin);
- while(pos >= nextmin) {
- // System.err.println(validSize+"<="+size+" iter:"+pos+"->"+curmin);
- while(pos >= curmin) {
- if(!heapifyDown(pos, keys[pos], values[pos])) {
- final int parent = (pos - 1) >>> 1;
- if(parent < curmin) {
- nextmin = Math.min(nextmin, parent);
- nextmax = Math.max(nextmax, parent);
- }
- }
- pos--;
- }
- curmin = nextmin;
- pos = Math.min(pos, nextmax);
- nextmax = -1;
- }
- }
- validSize = size;
- }
- }
-
- /**
- * Remove the element at the given position.
- *
- * @param pos Element position.
- */
- protected void removeAt(int pos) {
- if(pos < 0 || pos >= size) {
- return;
- }
- // Replacement object:
- final double reinkey = keys[size - 1];
- final Object reinval = values[size - 1];
- values[size - 1] = null;
- // Keep heap in sync
- if(validSize == size) {
- size -= 1;
- validSize -= 1;
- heapifyDown(pos, reinkey, reinval);
- }
- else {
- size -= 1;
- validSize = Math.min(pos >>> 1, validSize);
- keys[pos] = reinkey;
- values[pos] = reinval;
- }
- modCount++;
- }
-
- /**
- * Execute a "Heapify Upwards" aka "SiftUp". Used in insertions.
- *
- * @param pos insertion position
- * @param curkey Current key
- * @param curval Current value
- */
- protected void heapifyUp(int pos, double curkey, Object curval) {
- while(pos > 0) {
- final int parent = (pos - 1) >>> 1;
- double parkey = keys[parent];
-
- if(curkey >= parkey) { // Compare
- break;
- }
- keys[pos] = parkey;
- values[pos] = values[parent];
- pos = parent;
- }
- keys[pos] = curkey;
- values[pos] = curval;
- }
-
- /**
- * Execute a "Heapify Downwards" aka "SiftDown". Used in deletions.
- *
- * @param ipos re-insertion position
- * @param curkey Current key
- * @param curval Current value
- * @return true when the order was changed
- */
- protected boolean heapifyDown(final int ipos, double curkey, Object curval) {
- int pos = ipos;
- final int half = size >>> 1;
- while(pos < half) {
- // Get left child (must exist!)
- int cpos = (pos << 1) + 1;
- double chikey = keys[cpos];
- Object chival = values[cpos];
- // Test right child, if present
- final int rchild = cpos + 1;
- if(rchild < size) {
- double right = keys[rchild];
- if(chikey > right) { // Compare
- cpos = rchild;
- chikey = right;
- chival = values[rchild];
- }
- }
-
- if(curkey <= chikey) { // Compare
- break;
- }
- keys[pos] = chikey;
- values[pos] = chival;
- pos = cpos;
- }
- keys[pos] = curkey;
- values[pos] = curval;
- return (pos == ipos);
- }
-
- /**
- * Query the size
- *
- * @return Size
- */
- public int size() {
- return this.size;
- }
-
- /**
- * Test whether we need to resize to have the requested capacity.
- *
- * @param requiredSize required capacity
- */
- protected final void resize(int requiredSize) {
- // Double until 64, then increase by 50% each time.
- int newCapacity = ((keys.length < 64) ? ((keys.length + 1) << 1) : ((keys.length >> 1) * 3));
- // overflow?
- if(newCapacity < 0) {
- throw new OutOfMemoryError();
- }
- if(requiredSize > newCapacity) {
- newCapacity = requiredSize;
- }
- keys = Arrays.copyOf(keys, newCapacity);
- values = Arrays.copyOf(values, newCapacity);
- }
-
- /**
- * Delete all elements from the heap.
- */
- public void clear() {
- // clean up references in the array for memory management
- Arrays.fill(values, null);
- this.size = 0;
- this.validSize = -1;
- modCount++;
- }
-
- /**
- * Test whether the heap is still valid.
- *
- * Debug method.
- *
- * @return {@code null} when the heap is correct
- */
- protected String checkHeap() {
- ensureValid();
- for(int i = 1; i < size; i++) {
- final int parent = (i - 1) >>> 1;
- if(keys[parent] > keys[i]) { // Compare
- return "@" + parent + ": " + keys[parent] + " < @" + i + ": " + keys[i];
- }
- }
- return null;
- }
-}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleObjectHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleObjectHeap.java
new file mode 100644
index 00000000..db65ce81
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleObjectHeap.java
@@ -0,0 +1,129 @@
+package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.utilities.datastructures.iterator.Iter;
+
+/**
+ * Basic in-memory heap interface, for double keys and V values.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has UnsortedIter
+ * @param <V> Value type
+ */
+public interface DoubleObjectHeap<V> {
+ /**
+ * Add a key-value pair to the heap
+ *
+ * @param key Key
+ * @param val Value
+ */
+ void add(double key, V val);
+
+ /**
+ * Add a key-value pair to the heap if it improves the top.
+ *
+ * @param key Key
+ * @param val Value
+ * @param k Desired maximum size
+ */
+ void add(double key, V val, int k);
+
+ /**
+ * Combined operation that removes the top element, and inserts a new element
+ * instead.
+ *
+ * @param key Key of new element
+ * @param val Value of new element
+ */
+ void replaceTopElement(double key, V val);
+
+ /**
+ * Get the current top key
+ *
+ * @return Top key
+ */
+ double peekKey();
+
+ /**
+ * Get the current top value
+ *
+ * @return Value
+ */
+ V peekValue();
+
+ /**
+ * Remove the first element
+ */
+ void poll();
+
+ /**
+ * Clear the heap contents.
+ */
+ void clear();
+
+ /**
+ * Query the size
+ *
+ * @return Size
+ */
+ public int size();
+
+ /**
+ * Is the heap empty?
+ *
+ * @return {@code true} when the size is 0.
+ */
+ public boolean isEmpty();
+
+ /**
+ * Get an unsorted iterator to inspect the heap.
+ *
+ * @return Iterator
+ */
+ UnsortedIter<V> unsortedIter();
+
+ /**
+ * Unsorted iterator - in heap order. Does not poll the heap.
+ *
+ * @author Erich Schubert
+ * @param <V> Value type
+ */
+ public static interface UnsortedIter<V> extends Iter {
+ /**
+ * Get the current key
+ *
+ * @return Current key
+ */
+ double getKey();
+
+ /**
+ * Get the current value
+ *
+ * @return Current value
+ */
+ V getValue();
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleObjectMaxHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleObjectMaxHeap.java
new file mode 100644
index 00000000..dd89573c
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleObjectMaxHeap.java
@@ -0,0 +1,482 @@
+package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.Arrays;
+import java.util.ConcurrentModificationException;
+
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+
+/**
+ * Advanced priority queue class, based on a binary heap (for small sizes),
+ * which will for larger heaps be accompanied by a 4-ary heap (attached below
+ * the root of the two-ary heap, making the root actually 3-ary).
+ *
+ * This code was automatically instantiated for the types: Double and Object
+ *
+ * This combination was found to work quite well in benchmarks, but YMMV.
+ *
+ * Some other observations from benchmarking:
+ * <ul>
+ * <li>Bulk loading did not improve things</li>
+ * <li>Primitive heaps are substantially faster.</li>
+ * <li>Since an array in Java has an overhead of 12 bytes, odd-sized object and
+ * integer arrays are actually well aligned both for 2-ary and 4-ary heaps.</li>
+ * <li>Workload makes a huge difference. A load-once, poll-until-empty priority
+ * queue is something different than e.g. a top-k heap, which will see a lot of
+ * top element replacements.</li>
+ * <li>Random vs. increasing vs. decreasing vs. sawtooth insertion patterns for
+ * top-k make a difference.</li>
+ * <li>Different day, different benchmark results ...</li>
+ * </ul>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has UnsortedIter
+ * @param <V> Value type
+ */
+public class DoubleObjectMaxHeap<V> implements DoubleObjectHeap<V> {
+ /**
+ * Base heap.
+ */
+ protected double[] twoheap;
+
+ /**
+ * Base heap values.
+ */
+ protected Object[] twovals;
+
+ /**
+ * Extension heap.
+ */
+ protected double[] fourheap;
+
+ /**
+ * Extension heapvalues.
+ */
+ protected Object[] fourvals;
+
+ /**
+ * Current size of heap.
+ */
+ protected int size;
+
+ /**
+ * (Structural) modification counter. Used to invalidate iterators.
+ */
+ protected int modCount = 0;
+
+ /**
+ * Maximum size of the 2-ary heap. A complete 2-ary heap has (2^k-1) elements.
+ */
+ private final static int TWO_HEAP_MAX_SIZE = (1 << 9) - 1;
+
+ /**
+ * Initial size of the 2-ary heap.
+ */
+ private final static int TWO_HEAP_INITIAL_SIZE = (1 << 5) - 1;
+
+ /**
+ * Initial size of 4-ary heap when initialized.
+ *
+ * 21 = 4-ary heap of height 2: 1 + 4 + 4*4
+ *
+ * 85 = 4-ary heap of height 3: 21 + 4*4*4
+ *
+ * 341 = 4-ary heap of height 4: 85 + 4*4*4*4
+ *
+ * Since we last grew by 255 (to 511), let's use 341.
+ */
+ private final static int FOUR_HEAP_INITIAL_SIZE = 341;
+
+ /**
+ * Constructor, with default size.
+ */
+ public DoubleObjectMaxHeap() {
+ super();
+ double[] twoheap = new double[TWO_HEAP_INITIAL_SIZE];
+ Object[] twovals = new Object[TWO_HEAP_INITIAL_SIZE];
+
+ this.twoheap = twoheap;
+ this.twovals = twovals;
+ this.fourheap = null;
+ this.fourvals = null;
+ this.size = 0;
+ this.modCount = 0;
+ }
+
+ /**
+ * Constructor, with given minimum size.
+ *
+ * @param minsize Minimum size
+ */
+ public DoubleObjectMaxHeap(int minsize) {
+ super();
+ if (minsize < TWO_HEAP_MAX_SIZE) {
+ final int size = MathUtil.nextPow2Int(minsize + 1) - 1;
+ double[] twoheap = new double[size];
+ Object[] twovals = new Object[size];
+
+ this.twoheap = twoheap;
+ this.twovals = twovals;
+ this.fourheap = null;
+ this.fourvals = null;
+ } else {
+ double[] twoheap = new double[TWO_HEAP_INITIAL_SIZE];
+ Object[] twovals = new Object[TWO_HEAP_INITIAL_SIZE];
+ double[] fourheap = new double[Math.max(21, minsize - TWO_HEAP_MAX_SIZE)];
+ Object[] fourvals = new Object[Math.max(21, minsize - TWO_HEAP_MAX_SIZE)];
+ this.twoheap = twoheap;
+ this.twovals = twovals;
+ this.fourheap = fourheap;
+ this.fourvals = fourvals;
+ }
+ this.size = 0;
+ this.modCount = 0;
+ }
+
+ @Override
+ public void clear() {
+ size = 0;
+ ++modCount;
+ fourheap = null;
+ fourvals = null;
+ Arrays.fill(twoheap, 0.0);
+ Arrays.fill(twovals, null);
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return (size == 0);
+ }
+
+ @Override
+ public void add(double o, V v) {
+ final double co = o;
+ final Object cv = (Object)v;
+ // System.err.println("Add: " + o);
+ if (size < TWO_HEAP_MAX_SIZE) {
+ if (size >= twoheap.length) {
+ // Grow by one layer.
+ twoheap = Arrays.copyOf(twoheap, twoheap.length + twoheap.length + 1);
+ twovals = Arrays.copyOf(twovals, twovals.length + twovals.length + 1);
+ }
+ final int twopos = size;
+ twoheap[twopos] = co;
+ twovals[twopos] = cv;
+ ++size;
+ heapifyUp2(twopos, co, cv);
+ ++modCount;
+ } else {
+ final int fourpos = size - TWO_HEAP_MAX_SIZE;
+ if (fourheap == null) {
+ fourheap = new double[FOUR_HEAP_INITIAL_SIZE];
+ fourvals = new Object[FOUR_HEAP_INITIAL_SIZE];
+ } else if (fourpos >= fourheap.length) {
+ // Grow extension heap by half.
+ fourheap = Arrays.copyOf(fourheap, fourheap.length + (fourheap.length >> 1));
+ fourvals = Arrays.copyOf(fourvals, fourvals.length + (fourvals.length >> 1));
+ }
+ fourheap[fourpos] = co;
+ fourvals[fourpos] = cv;
+ ++size;
+ heapifyUp4(fourpos, co, cv);
+ ++modCount;
+ }
+ }
+
+ @Override
+ public void add(double key, V val, int max) {
+ if (size < max) {
+ add(key, val);
+ } else if (twoheap[0] >= key) {
+ replaceTopElement(key, val);
+ }
+ }
+
+ @Override
+ public void replaceTopElement(double reinsert, V val) {
+ heapifyDown(reinsert, (Object)val);
+ ++modCount;
+ }
+
+ /**
+ * Heapify-Up method for 2-ary heap.
+ *
+ * @param twopos Position in 2-ary heap.
+ * @param cur Current object
+ * @param val Current value
+ */
+ private void heapifyUp2(int twopos, double cur, Object val) {
+ while (twopos > 0) {
+ final int parent = (twopos - 1) >>> 1;
+ double par = twoheap[parent];
+ if (cur <= par) {
+ break;
+ }
+ twoheap[twopos] = par;
+ twovals[twopos] = twovals[parent];
+ twopos = parent;
+ }
+ twoheap[twopos] = cur;
+ twovals[twopos] = val;
+ }
+
+ /**
+ * Heapify-Up method for 4-ary heap.
+ *
+ * @param fourpos Position in 4-ary heap.
+ * @param cur Current object
+ * @param val Current value
+ */
+ private void heapifyUp4(int fourpos, double cur, Object val) {
+ while (fourpos > 0) {
+ final int parent = (fourpos - 1) >> 2;
+ double par = fourheap[parent];
+ if (cur <= par) {
+ break;
+ }
+ fourheap[fourpos] = par;
+ fourvals[fourpos] = fourvals[parent];
+ fourpos = parent;
+ }
+ if (fourpos == 0 && twoheap[0] < cur) {
+ fourheap[0] = twoheap[0];
+ fourvals[0] = twovals[0];
+ twoheap[0] = cur;
+ twovals[0] = val;
+ } else {
+ fourheap[fourpos] = cur;
+ fourvals[fourpos] = val;
+ }
+ }
+
+ @Override
+ public void poll() {
+ --size;
+ // Replacement object:
+ if (size >= TWO_HEAP_MAX_SIZE) {
+ final int last = size - TWO_HEAP_MAX_SIZE;
+ final double reinsert = fourheap[last];
+ final Object reinsertv = fourvals[last];
+ fourheap[last] = 0.0;
+ fourvals[last] = null;
+ heapifyDown(reinsert, reinsertv);
+ } else if (size > 0) {
+ final double reinsert = twoheap[size];
+ final Object reinsertv = twovals[size];
+ twoheap[size] = 0.0;
+ twovals[size] = null;
+ heapifyDown(reinsert, reinsertv);
+ } else {
+ twoheap[0] = 0.0;
+ twovals[0] = null;
+ }
+ ++modCount;
+ }
+
+ /**
+ * Invoke heapify-down for the root object.
+ *
+ * @param reinsert Object to insert.
+ * @param val Value to reinsert.
+ */
+ private void heapifyDown(double reinsert, Object val) {
+ if (size > TWO_HEAP_MAX_SIZE) {
+ // Special case: 3-ary situation.
+ final int best = (twoheap[1] >= twoheap[2]) ? 1 : 2;
+ if (fourheap[0] > twoheap[best]) {
+ twoheap[0] = fourheap[0];
+ twovals[0] = fourvals[0];
+ heapifyDown4(0, reinsert, val);
+ } else {
+ twoheap[0] = twoheap[best];
+ twovals[0] = twovals[best];
+ heapifyDown2(best, reinsert, val);
+ }
+ return;
+ }
+ heapifyDown2(0, reinsert, val);
+ }
+
+ /**
+ * Heapify-Down for 2-ary heap.
+ *
+ * @param twopos Position in 2-ary heap.
+ * @param cur Current object
+ * @param val Value to reinsert.
+ */
+ private void heapifyDown2(int twopos, double cur, Object val) {
+ final int stop = Math.min(size, TWO_HEAP_MAX_SIZE) >>> 1;
+ while (twopos < stop) {
+ int bestchild = (twopos << 1) + 1;
+ double best = twoheap[bestchild];
+ final int right = bestchild + 1;
+ if (right < size && best < twoheap[right]) {
+ bestchild = right;
+ best = twoheap[right];
+ }
+ if (cur >= best) {
+ break;
+ }
+ twoheap[twopos] = best;
+ twovals[twopos] = twovals[bestchild];
+ twopos = bestchild;
+ }
+ twoheap[twopos] = cur;
+ twovals[twopos] = val;
+ }
+
+ /**
+ * Heapify-Down for 4-ary heap.
+ *
+ * @param fourpos Position in 4-ary heap.
+ * @param cur Current object
+ * @param val Value to reinsert.
+ */
+ private void heapifyDown4(int fourpos, double cur, Object val) {
+ final int stop = (size - TWO_HEAP_MAX_SIZE + 2) >>> 2;
+ while (fourpos < stop) {
+ final int child = (fourpos << 2) + 1;
+ double best = fourheap[child];
+ int bestchild = child, candidate = child + 1, minsize = candidate + TWO_HEAP_MAX_SIZE;
+ if (size > minsize) {
+ double nextchild = fourheap[candidate];
+ if (best < nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+
+ minsize += 2;
+ if (size >= minsize) {
+ nextchild = fourheap[++candidate];
+ if (best < nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+
+ if (size > minsize) {
+ nextchild = fourheap[++candidate];
+ if (best < nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+ }
+ }
+ }
+ if (cur >= best) {
+ break;
+ }
+ fourheap[fourpos] = best;
+ fourvals[fourpos] = fourvals[bestchild];
+ fourpos = bestchild;
+ }
+ fourheap[fourpos] = cur;
+ fourvals[fourpos] = val;
+ }
+
+ @Override
+ public double peekKey() {
+ return twoheap[0];
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public V peekValue() {
+ return (V)twovals[0];
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder buf = new StringBuilder();
+ buf.append(DoubleObjectMaxHeap.class.getSimpleName()).append(" [");
+ for (UnsortedIter iter = new UnsortedIter(); iter.valid(); iter.advance()) {
+ buf.append(iter.getKey()).append(':').append(iter.getValue()).append(',');
+ }
+ buf.append(']');
+ return buf.toString();
+ }
+
+ @Override
+ public UnsortedIter unsortedIter() {
+ return new UnsortedIter();
+ }
+
+ /**
+ * Unsorted iterator - in heap order. Does not poll the heap.
+ *
+ * Use this class as follows:
+ *
+ * <pre>
+ * {@code
+ * for (DoubleObjectHeap.UnsortedIter<V> iter = heap.unsortedIter(); iter.valid(); iter.next()) {
+ * doSomething(iter.get());
+ * }
+ * }
+ * </pre>
+ *
+ * @author Erich Schubert
+ */
+ private class UnsortedIter implements DoubleObjectHeap.UnsortedIter<V> {
+ /**
+ * Iterator position.
+ */
+ protected int pos = 0;
+
+ /**
+ * Modification counter we were initialized at.
+ */
+ protected final int myModCount = modCount;
+
+ @Override
+ public boolean valid() {
+ if (modCount != myModCount) {
+ throw new ConcurrentModificationException();
+ }
+ return pos < size;
+ }
+
+ @Override
+ public void advance() {
+ pos++;
+ }
+
+ @Override
+ public double getKey() {
+ return ((pos < TWO_HEAP_MAX_SIZE) ? twoheap[pos] : fourheap[pos - TWO_HEAP_MAX_SIZE]);
+ }
+
+ @SuppressWarnings("unchecked")
+
+ @Override
+ public V getValue() {
+ return (V)((pos < TWO_HEAP_MAX_SIZE) ? twovals[pos] : fourvals[pos - TWO_HEAP_MAX_SIZE]);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleObjectMinHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleObjectMinHeap.java
new file mode 100644
index 00000000..905cdedb
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoubleObjectMinHeap.java
@@ -0,0 +1,482 @@
+package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.Arrays;
+import java.util.ConcurrentModificationException;
+
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+
+/**
+ * Advanced priority queue class, based on a binary heap (for small sizes),
+ * which will for larger heaps be accompanied by a 4-ary heap (attached below
+ * the root of the two-ary heap, making the root actually 3-ary).
+ *
+ * This code was automatically instantiated for the types: Double and Object
+ *
+ * This combination was found to work quite well in benchmarks, but YMMV.
+ *
+ * Some other observations from benchmarking:
+ * <ul>
+ * <li>Bulk loading did not improve things</li>
+ * <li>Primitive heaps are substantially faster.</li>
+ * <li>Since an array in Java has an overhead of 12 bytes, odd-sized object and
+ * integer arrays are actually well aligned both for 2-ary and 4-ary heaps.</li>
+ * <li>Workload makes a huge difference. A load-once, poll-until-empty priority
+ * queue is something different than e.g. a top-k heap, which will see a lot of
+ * top element replacements.</li>
+ * <li>Random vs. increasing vs. decreasing vs. sawtooth insertion patterns for
+ * top-k make a difference.</li>
+ * <li>Different day, different benchmark results ...</li>
+ * </ul>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has UnsortedIter
+ * @param <V> Value type
+ */
+public class DoubleObjectMinHeap<V> implements DoubleObjectHeap<V> {
+ /**
+ * Base heap.
+ */
+ protected double[] twoheap;
+
+ /**
+ * Base heap values.
+ */
+ protected Object[] twovals;
+
+ /**
+ * Extension heap.
+ */
+ protected double[] fourheap;
+
+ /**
+ * Extension heapvalues.
+ */
+ protected Object[] fourvals;
+
+ /**
+ * Current size of heap.
+ */
+ protected int size;
+
+ /**
+ * (Structural) modification counter. Used to invalidate iterators.
+ */
+ protected int modCount = 0;
+
+ /**
+ * Maximum size of the 2-ary heap. A complete 2-ary heap has (2^k-1) elements.
+ */
+ private final static int TWO_HEAP_MAX_SIZE = (1 << 9) - 1;
+
+ /**
+ * Initial size of the 2-ary heap.
+ */
+ private final static int TWO_HEAP_INITIAL_SIZE = (1 << 5) - 1;
+
+ /**
+ * Initial size of 4-ary heap when initialized.
+ *
+ * 21 = 4-ary heap of height 2: 1 + 4 + 4*4
+ *
+ * 85 = 4-ary heap of height 3: 21 + 4*4*4
+ *
+ * 341 = 4-ary heap of height 4: 85 + 4*4*4*4
+ *
+ * Since we last grew by 255 (to 511), let's use 341.
+ */
+ private final static int FOUR_HEAP_INITIAL_SIZE = 341;
+
+ /**
+ * Constructor, with default size.
+ */
+ public DoubleObjectMinHeap() {
+ super();
+ double[] twoheap = new double[TWO_HEAP_INITIAL_SIZE];
+ Object[] twovals = new Object[TWO_HEAP_INITIAL_SIZE];
+
+ this.twoheap = twoheap;
+ this.twovals = twovals;
+ this.fourheap = null;
+ this.fourvals = null;
+ this.size = 0;
+ this.modCount = 0;
+ }
+
+ /**
+ * Constructor, with given minimum size.
+ *
+ * @param minsize Minimum size
+ */
+ public DoubleObjectMinHeap(int minsize) {
+ super();
+ if (minsize < TWO_HEAP_MAX_SIZE) {
+ final int size = MathUtil.nextPow2Int(minsize + 1) - 1;
+ double[] twoheap = new double[size];
+ Object[] twovals = new Object[size];
+
+ this.twoheap = twoheap;
+ this.twovals = twovals;
+ this.fourheap = null;
+ this.fourvals = null;
+ } else {
+ double[] twoheap = new double[TWO_HEAP_INITIAL_SIZE];
+ Object[] twovals = new Object[TWO_HEAP_INITIAL_SIZE];
+ double[] fourheap = new double[Math.max(21, minsize - TWO_HEAP_MAX_SIZE)];
+ Object[] fourvals = new Object[Math.max(21, minsize - TWO_HEAP_MAX_SIZE)];
+ this.twoheap = twoheap;
+ this.twovals = twovals;
+ this.fourheap = fourheap;
+ this.fourvals = fourvals;
+ }
+ this.size = 0;
+ this.modCount = 0;
+ }
+
+ @Override
+ public void clear() {
+ size = 0;
+ ++modCount;
+ fourheap = null;
+ fourvals = null;
+ Arrays.fill(twoheap, 0.0);
+ Arrays.fill(twovals, null);
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return (size == 0);
+ }
+
+ @Override
+ public void add(double o, V v) {
+ final double co = o;
+ final Object cv = (Object)v;
+ // System.err.println("Add: " + o);
+ if (size < TWO_HEAP_MAX_SIZE) {
+ if (size >= twoheap.length) {
+ // Grow by one layer.
+ twoheap = Arrays.copyOf(twoheap, twoheap.length + twoheap.length + 1);
+ twovals = Arrays.copyOf(twovals, twovals.length + twovals.length + 1);
+ }
+ final int twopos = size;
+ twoheap[twopos] = co;
+ twovals[twopos] = cv;
+ ++size;
+ heapifyUp2(twopos, co, cv);
+ ++modCount;
+ } else {
+ final int fourpos = size - TWO_HEAP_MAX_SIZE;
+ if (fourheap == null) {
+ fourheap = new double[FOUR_HEAP_INITIAL_SIZE];
+ fourvals = new Object[FOUR_HEAP_INITIAL_SIZE];
+ } else if (fourpos >= fourheap.length) {
+ // Grow extension heap by half.
+ fourheap = Arrays.copyOf(fourheap, fourheap.length + (fourheap.length >> 1));
+ fourvals = Arrays.copyOf(fourvals, fourvals.length + (fourvals.length >> 1));
+ }
+ fourheap[fourpos] = co;
+ fourvals[fourpos] = cv;
+ ++size;
+ heapifyUp4(fourpos, co, cv);
+ ++modCount;
+ }
+ }
+
+ @Override
+ public void add(double key, V val, int max) {
+ if (size < max) {
+ add(key, val);
+ } else if (twoheap[0] <= key) {
+ replaceTopElement(key, val);
+ }
+ }
+
+ @Override
+ public void replaceTopElement(double reinsert, V val) {
+ heapifyDown(reinsert, (Object)val);
+ ++modCount;
+ }
+
+ /**
+ * Heapify-Up method for 2-ary heap.
+ *
+ * @param twopos Position in 2-ary heap.
+ * @param cur Current object
+ * @param val Current value
+ */
+ private void heapifyUp2(int twopos, double cur, Object val) {
+ while (twopos > 0) {
+ final int parent = (twopos - 1) >>> 1;
+ double par = twoheap[parent];
+ if (cur >= par) {
+ break;
+ }
+ twoheap[twopos] = par;
+ twovals[twopos] = twovals[parent];
+ twopos = parent;
+ }
+ twoheap[twopos] = cur;
+ twovals[twopos] = val;
+ }
+
+ /**
+ * Heapify-Up method for 4-ary heap.
+ *
+ * @param fourpos Position in 4-ary heap.
+ * @param cur Current object
+ * @param val Current value
+ */
+ private void heapifyUp4(int fourpos, double cur, Object val) {
+ while (fourpos > 0) {
+ final int parent = (fourpos - 1) >> 2;
+ double par = fourheap[parent];
+ if (cur >= par) {
+ break;
+ }
+ fourheap[fourpos] = par;
+ fourvals[fourpos] = fourvals[parent];
+ fourpos = parent;
+ }
+ if (fourpos == 0 && twoheap[0] > cur) {
+ fourheap[0] = twoheap[0];
+ fourvals[0] = twovals[0];
+ twoheap[0] = cur;
+ twovals[0] = val;
+ } else {
+ fourheap[fourpos] = cur;
+ fourvals[fourpos] = val;
+ }
+ }
+
+ @Override
+ public void poll() {
+ --size;
+ // Replacement object:
+ if (size >= TWO_HEAP_MAX_SIZE) {
+ final int last = size - TWO_HEAP_MAX_SIZE;
+ final double reinsert = fourheap[last];
+ final Object reinsertv = fourvals[last];
+ fourheap[last] = 0.0;
+ fourvals[last] = null;
+ heapifyDown(reinsert, reinsertv);
+ } else if (size > 0) {
+ final double reinsert = twoheap[size];
+ final Object reinsertv = twovals[size];
+ twoheap[size] = 0.0;
+ twovals[size] = null;
+ heapifyDown(reinsert, reinsertv);
+ } else {
+ twoheap[0] = 0.0;
+ twovals[0] = null;
+ }
+ ++modCount;
+ }
+
+ /**
+ * Invoke heapify-down for the root object.
+ *
+ * @param reinsert Object to insert.
+ * @param val Value to reinsert.
+ */
+ private void heapifyDown(double reinsert, Object val) {
+ if (size > TWO_HEAP_MAX_SIZE) {
+ // Special case: 3-ary situation.
+ final int best = (twoheap[1] <= twoheap[2]) ? 1 : 2;
+ if (fourheap[0] < twoheap[best]) {
+ twoheap[0] = fourheap[0];
+ twovals[0] = fourvals[0];
+ heapifyDown4(0, reinsert, val);
+ } else {
+ twoheap[0] = twoheap[best];
+ twovals[0] = twovals[best];
+ heapifyDown2(best, reinsert, val);
+ }
+ return;
+ }
+ heapifyDown2(0, reinsert, val);
+ }
+
+ /**
+ * Heapify-Down for 2-ary heap.
+ *
+ * @param twopos Position in 2-ary heap.
+ * @param cur Current object
+ * @param val Value to reinsert.
+ */
+ private void heapifyDown2(int twopos, double cur, Object val) {
+ final int stop = Math.min(size, TWO_HEAP_MAX_SIZE) >>> 1;
+ while (twopos < stop) {
+ int bestchild = (twopos << 1) + 1;
+ double best = twoheap[bestchild];
+ final int right = bestchild + 1;
+ if (right < size && best > twoheap[right]) {
+ bestchild = right;
+ best = twoheap[right];
+ }
+ if (cur <= best) {
+ break;
+ }
+ twoheap[twopos] = best;
+ twovals[twopos] = twovals[bestchild];
+ twopos = bestchild;
+ }
+ twoheap[twopos] = cur;
+ twovals[twopos] = val;
+ }
+
+ /**
+ * Heapify-Down for 4-ary heap.
+ *
+ * @param fourpos Position in 4-ary heap.
+ * @param cur Current object
+ * @param val Value to reinsert.
+ */
+ private void heapifyDown4(int fourpos, double cur, Object val) {
+ final int stop = (size - TWO_HEAP_MAX_SIZE + 2) >>> 2;
+ while (fourpos < stop) {
+ final int child = (fourpos << 2) + 1;
+ double best = fourheap[child];
+ int bestchild = child, candidate = child + 1, minsize = candidate + TWO_HEAP_MAX_SIZE;
+ if (size > minsize) {
+ double nextchild = fourheap[candidate];
+ if (best > nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+
+ minsize += 2;
+ if (size >= minsize) {
+ nextchild = fourheap[++candidate];
+ if (best > nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+
+ if (size > minsize) {
+ nextchild = fourheap[++candidate];
+ if (best > nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+ }
+ }
+ }
+ if (cur <= best) {
+ break;
+ }
+ fourheap[fourpos] = best;
+ fourvals[fourpos] = fourvals[bestchild];
+ fourpos = bestchild;
+ }
+ fourheap[fourpos] = cur;
+ fourvals[fourpos] = val;
+ }
+
+ @Override
+ public double peekKey() {
+ return twoheap[0];
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public V peekValue() {
+ return (V)twovals[0];
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder buf = new StringBuilder();
+ buf.append(DoubleObjectMinHeap.class.getSimpleName()).append(" [");
+ for (UnsortedIter iter = new UnsortedIter(); iter.valid(); iter.advance()) {
+ buf.append(iter.getKey()).append(':').append(iter.getValue()).append(',');
+ }
+ buf.append(']');
+ return buf.toString();
+ }
+
+ @Override
+ public UnsortedIter unsortedIter() {
+ return new UnsortedIter();
+ }
+
+ /**
+ * Unsorted iterator - in heap order. Does not poll the heap.
+ *
+ * Use this class as follows:
+ *
+ * <pre>
+ * {@code
+ * for (DoubleObjectHeap.UnsortedIter<V> iter = heap.unsortedIter(); iter.valid(); iter.next()) {
+ * doSomething(iter.get());
+ * }
+ * }
+ * </pre>
+ *
+ * @author Erich Schubert
+ */
+ private class UnsortedIter implements DoubleObjectHeap.UnsortedIter<V> {
+ /**
+ * Iterator position.
+ */
+ protected int pos = 0;
+
+ /**
+ * Modification counter we were initialized at.
+ */
+ protected final int myModCount = modCount;
+
+ @Override
+ public boolean valid() {
+ if (modCount != myModCount) {
+ throw new ConcurrentModificationException();
+ }
+ return pos < size;
+ }
+
+ @Override
+ public void advance() {
+ pos++;
+ }
+
+ @Override
+ public double getKey() {
+ return ((pos < TWO_HEAP_MAX_SIZE) ? twoheap[pos] : fourheap[pos - TWO_HEAP_MAX_SIZE]);
+ }
+
+ @SuppressWarnings("unchecked")
+
+ @Override
+ public V getValue() {
+ return (V)((pos < TWO_HEAP_MAX_SIZE) ? twovals[pos] : fourvals[pos - TWO_HEAP_MAX_SIZE]);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoublePriorityObject.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoublePriorityObject.java
index 92d548cb..82453885 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoublePriorityObject.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoublePriorityObject.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/Heap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/Heap.java
index 86d3ae08..2c278110 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/Heap.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/Heap.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,11 +25,6 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
import java.util.Arrays;
import java.util.Comparator;
-import java.util.ConcurrentModificationException;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-
-import de.lmu.ifi.dbs.elki.math.MathUtil;
/**
* Basic in-memory heap structure. Closely related to a
@@ -45,11 +40,11 @@ import de.lmu.ifi.dbs.elki.math.MathUtil;
* @param <E> Element type. Should be {@link java.lang.Comparable} or a
* {@link java.util.Comparator} needs to be given.
*/
-public class Heap<E> implements Iterable<E> {
+public class Heap<E> {
/**
* Heap storage.
*/
- protected transient Object[] queue;
+ protected Object[] queue;
/**
* Current number of objects.
@@ -57,11 +52,6 @@ public class Heap<E> implements Iterable<E> {
protected int size = 0;
/**
- * Indicate up to where the heap is valid.
- */
- protected int validSize = 0;
-
- /**
* The comparator or {@code null}.
*/
protected final Comparator<Object> comparator;
@@ -69,7 +59,7 @@ public class Heap<E> implements Iterable<E> {
/**
* (Structural) modification counter. Used to invalidate iterators.
*/
- private transient int modCount = 0;
+ private int modCount = 0;
/**
* Default initial capacity.
@@ -126,10 +116,8 @@ public class Heap<E> implements Iterable<E> {
resize(size + 1);
}
// final int pos = size;
- this.queue[size] = e;
this.size += 1;
heapifyUp(size - 1, e);
- validSize += 1;
heapModified();
}
@@ -142,7 +130,6 @@ public class Heap<E> implements Iterable<E> {
*/
@SuppressWarnings("unchecked")
public E replaceTopElement(E e) {
- ensureValid();
E oldroot = (E) queue[0];
heapifyDown(0, e);
heapModified();
@@ -159,7 +146,6 @@ public class Heap<E> implements Iterable<E> {
if (size == 0) {
return null;
}
- ensureValid();
return (E) queue[0];
}
@@ -169,70 +155,10 @@ public class Heap<E> implements Iterable<E> {
* @return Top element.
*/
public E poll() {
- ensureValid();
return removeAt(0);
}
/**
- * Perform pending heap repair operations in a single bulk operation.
- */
- protected void ensureValid() {
- if (validSize != size) {
- if (size > 1) {
- // Bottom up heap update.
- if (comparator != null) {
- // Parent of first invalid
- int nextmin = validSize > 0 ? ((validSize - 1) >>> 1) : 0;
- int curmin = MathUtil.nextAllOnesInt(nextmin); // Next line
- int nextmax = curmin - 1; // End of valid line
- int pos = (size - 2) >>> 1; // Parent of last element
- // System.err.println(validSize+"<="+size+" iter:"+pos+"->"+curmin+", "+nextmin);
- while (pos >= nextmin) {
- // System.err.println(validSize+"<="+size+" iter:"+pos+"->"+curmin);
- while (pos >= curmin) {
- if (!heapifyDownComparator(pos, queue[pos])) {
- final int parent = (pos - 1) >>> 1;
- if (parent < curmin) {
- nextmin = Math.min(nextmin, parent);
- nextmax = Math.max(nextmax, parent);
- }
- }
- pos--;
- }
- curmin = nextmin;
- pos = Math.min(pos, nextmax);
- nextmax = -1;
- }
- } else {
- // Parent of first invalid
- int nextmin = validSize > 0 ? ((validSize - 1) >>> 1) : 0;
- int curmin = MathUtil.nextAllOnesInt(nextmin); // Next line
- int nextmax = curmin - 1; // End of valid line
- int pos = (size - 2) >>> 1; // Parent of last element
- // System.err.println(validSize+"<="+size+" iter:"+pos+"->"+curmin+", "+nextmin);
- while (pos >= nextmin) {
- // System.err.println(validSize+"<="+size+" iter:"+pos+"->"+curmin);
- while (pos >= curmin) {
- if (!heapifyDownComparable(pos, queue[pos])) {
- final int parent = (pos - 1) >>> 1;
- if (parent < curmin) {
- nextmin = Math.min(nextmin, parent);
- nextmax = Math.max(nextmax, parent);
- }
- }
- pos--;
- }
- curmin = nextmin;
- pos = Math.min(pos, nextmax);
- nextmax = -1;
- }
- }
- }
- validSize = size;
- }
- }
-
- /**
* Remove the element at the given position.
*
* @param pos Element position.
@@ -247,16 +173,8 @@ public class Heap<E> implements Iterable<E> {
// Replacement object:
final Object reinsert = queue[size - 1];
queue[size - 1] = null;
- // Keep heap in sync
- if (validSize == size) {
- size -= 1;
- validSize -= 1;
- heapifyDown(pos, reinsert);
- } else {
- size -= 1;
- validSize = Math.min(pos >>> 1, validSize);
- queue[pos] = reinsert;
- }
+ size--;
+ heapifyDown(pos, reinsert);
heapModified();
return ret;
}
@@ -367,7 +285,7 @@ public class Heap<E> implements Iterable<E> {
pos = cpos;
}
queue[pos] = cur;
- return (pos == ipos);
+ return (pos != ipos);
}
/**
@@ -405,7 +323,7 @@ public class Heap<E> implements Iterable<E> {
pos = min;
}
queue[pos] = cur;
- return (pos == ipos);
+ return (pos != ipos);
}
/**
@@ -453,15 +371,9 @@ public class Heap<E> implements Iterable<E> {
queue[i] = null;
}
this.size = 0;
- this.validSize = -1;
heapModified();
}
- @Override
- public Iterator<E> iterator() {
- return new Itr();
- }
-
/**
* Called at the end of each heap modification.
*/
@@ -470,52 +382,12 @@ public class Heap<E> implements Iterable<E> {
}
/**
- * Iterator over queue elements. No particular order (i.e. heap order!)
+ * Get an unordered heap iterator.
*
- * @author Erich Schubert
- *
- * @apiviz.exclude
+ * @return Iterator.
*/
- protected final class Itr implements Iterator<E> {
- /**
- * Cursor position.
- */
- private int cursor = 0;
-
- /**
- * Modification counter this iterator is valid for.
- */
- private int expectedModCount = modCount;
-
- @Override
- public boolean hasNext() {
- return cursor < size;
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public E next() {
- if (expectedModCount != modCount) {
- throw new ConcurrentModificationException();
- }
- if (cursor < size) {
- return (E) queue[cursor++];
- }
- throw new NoSuchElementException();
- }
-
- @Override
- public void remove() {
- if (expectedModCount != modCount) {
- throw new ConcurrentModificationException();
- }
- if (cursor > 0) {
- cursor--;
- } else {
- throw new IllegalStateException();
- }
- expectedModCount = modCount;
- }
+ public UnorderedIter unorderedIter() {
+ return new UnorderedIter();
}
/**
@@ -526,7 +398,6 @@ public class Heap<E> implements Iterable<E> {
* @return {@code null} when the heap is correct
*/
protected String checkHeap() {
- ensureValid();
if (comparator == null) {
for (int i = 1; i < size; i++) {
final int parent = (i - 1) >>> 1;
@@ -546,4 +417,43 @@ public class Heap<E> implements Iterable<E> {
}
return null;
}
+
+ /**
+ * Heap iterator.
+ *
+ * @author Erich Schubert
+ */
+ public class UnorderedIter implements de.lmu.ifi.dbs.elki.utilities.datastructures.iterator.Iter {
+ /**
+ * Current iterator position.
+ */
+ int pos = 0;
+
+ /**
+ * Constructor.
+ */
+ protected UnorderedIter() {
+ super();
+ }
+
+ @Override
+ public boolean valid() {
+ return pos < size();
+ }
+
+ @Override
+ public void advance() {
+ pos++;
+ }
+
+ /**
+ * Get the current queue element.
+ *
+ * @return Element
+ */
+ @SuppressWarnings("unchecked")
+ public E get() {
+ return (E) queue[pos];
+ }
+ }
}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerHeap.java
index 6203ad96..3235926b 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerHeap.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerHeap.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,53 +23,22 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.Arrays;
-
-import de.lmu.ifi.dbs.elki.math.MathUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.iterator.Iter;
/**
- * Basic in-memory heap structure.
- *
- * This heap is built lazily: if you first add many elements, then poll the
- * heap, it will be bulk-loaded in O(n) instead of iteratively built in O(n log
- * n). This is implemented via a simple validTo counter.
+ * Basic in-memory heap for int values.
*
* @author Erich Schubert
+ *
+ * @apiviz.has UnsortedIter
*/
-public abstract class IntegerHeap extends AbstractHeap {
- /**
- * Heap storage: queue
- */
- protected transient int[] queue;
-
- /**
- * Constructor with initial capacity.
- *
- * @param size initial capacity
- */
- public IntegerHeap(int size) {
- super();
- this.size = 0;
- this.queue = new int[size];
- }
-
+public interface IntegerHeap {
/**
* Add a key-value pair to the heap
*
* @param key Key
*/
- public void add(int key) {
- // resize when needed
- if (size + 1 > queue.length) {
- resize(size + 1);
- }
- // final int pos = size;
- this.queue[size] = key;
- this.size += 1;
- heapifyUp(size - 1, key);
- validSize += 1;
- heapModified();
- }
+ void add(int key);
/**
* Add a key-value pair to the heap, except if the new element is larger than
@@ -78,13 +47,7 @@ public abstract class IntegerHeap extends AbstractHeap {
* @param key Key
* @param max Maximum size of heap
*/
- public void add(int key, int max) {
- if (size < max) {
- add(key);
- } else if (comp(key, peek())) {
- replaceTopElement(key);
- }
- }
+ void add(int key, int max);
/**
* Combined operation that removes the top element, and inserts a new element
@@ -93,172 +56,67 @@ public abstract class IntegerHeap extends AbstractHeap {
* @param e New element to insert
* @return Previous top element of the heap
*/
- public int replaceTopElement(int e) {
- ensureValid();
- int oldroot = queue[0];
- heapifyDown(0, e);
- heapModified();
- return oldroot;
- }
+ int replaceTopElement(int e);
/**
* Get the current top key
*
* @return Top key
*/
- public int peek() {
- if (size == 0) {
- throw new ArrayIndexOutOfBoundsException("Peek() on an empty heap!");
- }
- ensureValid();
- return queue[0];
- }
+ int peek();
/**
* Remove the first element
*
* @return Top element
*/
- public int poll() {
- return removeAt(0);
- }
+ int poll();
/**
- * Repair the heap
+ * Delete all elements from the heap.
*/
- protected void ensureValid() {
- if (validSize != size) {
- if (size > 1) {
- // Parent of first invalid
- int nextmin = validSize > 0 ? ((validSize - 1) >>> 1) : 0;
- int curmin = MathUtil.nextAllOnesInt(nextmin); // Next line
- int nextmax = curmin - 1; // End of valid line
- int pos = (size - 2) >>> 1; // Parent of last element
- // System.err.println(validSize+"<="+size+" iter:"+pos+"->"+curmin+", "+nextmin);
- while (pos >= nextmin) {
- // System.err.println(validSize+"<="+size+" iter:"+pos+"->"+curmin);
- while (pos >= curmin) {
- if (!heapifyDown(pos, queue[pos])) {
- final int parent = (pos - 1) >>> 1;
- if (parent < curmin) {
- nextmin = Math.min(nextmin, parent);
- nextmax = Math.max(nextmax, parent);
- }
- }
- pos--;
- }
- curmin = nextmin;
- pos = Math.min(pos, nextmax);
- nextmax = -1;
- }
- }
- validSize = size;
- }
- }
+ void clear();
/**
- * Remove the element at the given position.
+ * Query the size
*
- * @param pos Element position.
- * @return Removed element
+ * @return Size
*/
- protected int removeAt(int pos) {
- if (pos < 0 || pos >= size) {
- return 0;
- }
- final int top = queue[0];
- // Replacement object:
- final int reinkey = queue[size - 1];
- // Keep heap in sync
- if (validSize == size) {
- size -= 1;
- validSize -= 1;
- heapifyDown(pos, reinkey);
- } else {
- size -= 1;
- validSize = Math.min(pos >>> 1, validSize);
- queue[pos] = reinkey;
- }
- heapModified();
- return top;
- }
-
+ public int size();
+
/**
- * Execute a "Heapify Upwards" aka "SiftUp". Used in insertions.
+ * Is the heap empty?
*
- * @param pos insertion position
- * @param curkey Current key
+ * @return {@code true} when the size is 0.
*/
- protected void heapifyUp(int pos, int curkey) {
- while (pos > 0) {
- final int parent = (pos - 1) >>> 1;
- int parkey = queue[parent];
-
- if (comp(curkey, parkey)) { // Compare
- break;
- }
- queue[pos] = parkey;
- pos = parent;
- }
- queue[pos] = curkey;
- }
+ public boolean isEmpty();
/**
- * Execute a "Heapify Downwards" aka "SiftDown". Used in deletions.
+ * Get an unsorted iterator to inspect the heap.
*
- * @param ipos re-insertion position
- * @param curkey Current key
- * @return true when the order was changed
+ * @return Iterator
*/
- protected boolean heapifyDown(final int ipos, int curkey) {
- int pos = ipos;
- final int half = size >>> 1;
- while (pos < half) {
- // Get left child (must exist!)
- int cpos = (pos << 1) + 1;
- int chikey = queue[cpos];
- // Test right child, if present
- final int rchild = cpos + 1;
- if (rchild < size) {
- int right = queue[rchild];
- if (comp(chikey, right)) { // Compare
- cpos = rchild;
- chikey = right;
- }
- }
-
- if (comp(chikey, curkey)) { // Compare
- break;
- }
- queue[pos] = chikey;
- pos = cpos;
- }
- queue[pos] = curkey;
- return (pos == ipos);
- }
+ UnsortedIter unsortedIter();
/**
- * Test whether we need to resize to have the requested capacity.
+ * Unsorted iterator - in heap order. Does not poll the heap.
*
- * @param requiredSize required capacity
- */
- protected final void resize(int requiredSize) {
- queue = Arrays.copyOf(queue, desiredSize(requiredSize, queue.length));
- }
-
- /**
- * Delete all elements from the heap.
+ * <pre>
+ * {@code
+ * for (IntegerHeap.UnsortedIter iter = heap.unsortedIter(); iter.valid(); iter.next()) {
+ * doSomething(iter.get());
+ * }
+ * }
+ * </pre>
+ *
+ * @author Erich Schubert
*/
- @Override
- public void clear() {
- super.clear();
- for (int i = 0; i < size; i++) {
- queue[i] = 0;
- }
+ public static interface UnsortedIter extends Iter {
+ /**
+ * Get the iterators current object.
+ *
+ * @return Current object
+ */
+ int get();
}
-
- /**
- * Compare two objects
- */
- abstract protected boolean comp(int o1, int o2);
}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerMaxHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerMaxHeap.java
index 383eb727..60f61d99 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerMaxHeap.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerMaxHeap.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,40 +23,400 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import java.util.Arrays;
+import java.util.ConcurrentModificationException;
+
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+
/**
- * Basic in-memory heap structure.
+ * Advanced priority queue class, based on a binary heap (for small sizes),
+ * which will for larger heaps be accompanied by a 4-ary heap (attached below
+ * the root of the two-ary heap, making the root actually 3-ary).
+ *
+ * This code was automatically instantiated for the type: Integer
*
- * This heap is built lazily: if you first add many elements, then poll the
- * heap, it will be bulk-loaded in O(n) instead of iteratively built in O(n log
- * n). This is implemented via a simple validTo counter.
+ * This combination was found to work quite well in benchmarks, but YMMV.
+ *
+ * Some other observations from benchmarking:
+ * <ul>
+ * <li>Bulk loading did not improve things</li>
+ * <li>Primitive heaps are substantially faster.</li>
+ * <li>Since an array in Java has an overhead of 12 bytes, odd-sized object and
+ * integer arrays are actually well aligned both for 2-ary and 4-ary heaps.</li>
+ * <li>Workload makes a huge difference. A load-once, poll-until-empty priority
+ * queue is something different than e.g. a top-k heap, which will see a lot of
+ * top element replacements.</li>
+ * <li>Random vs. increasing vs. decreasing vs. sawtooth insertion patterns for
+ * top-k make a difference.</li>
+ * <li>Different day, different benchmark results ...</li>
+ * </ul>
*
* @author Erich Schubert
+ *
+ * @apiviz.has UnsortedIter
*/
-public class IntegerMaxHeap extends IntegerHeap {
+public class IntegerMaxHeap implements IntegerHeap {
+ /**
+ * Base heap.
+ */
+ protected int[] twoheap;
+
+ /**
+ * Extension heap.
+ */
+ protected int[] fourheap;
+
+ /**
+ * Current size of heap.
+ */
+ protected int size;
+
+ /**
+ * (Structural) modification counter. Used to invalidate iterators.
+ */
+ protected int modCount = 0;
+
+ /**
+ * Maximum size of the 2-ary heap. A complete 2-ary heap has (2^k-1) elements.
+ */
+ private final static int TWO_HEAP_MAX_SIZE = (1 << 9) - 1;
+
/**
- * Constructor with default capacity.
+ * Initial size of the 2-ary heap.
+ */
+ private final static int TWO_HEAP_INITIAL_SIZE = (1 << 5) - 1;
+
+ /**
+ * Initial size of 4-ary heap when initialized.
+ *
+ * 21 = 4-ary heap of height 2: 1 + 4 + 4*4
+ *
+ * 85 = 4-ary heap of height 3: 21 + 4*4*4
+ *
+ * 341 = 4-ary heap of height 4: 85 + 4*4*4*4
+ *
+ * Since we last grew by 255 (to 511), let's use 341.
+ */
+ private final static int FOUR_HEAP_INITIAL_SIZE = 341;
+
+ /**
+ * Constructor, with default size.
*/
public IntegerMaxHeap() {
- super(DEFAULT_INITIAL_CAPACITY);
+ super();
+ int[] twoheap = new int[TWO_HEAP_INITIAL_SIZE];
+
+ this.twoheap = twoheap;
+ this.fourheap = null;
+ this.size = 0;
+ this.modCount = 0;
}
/**
- * Constructor with initial capacity.
+ * Constructor, with given minimum size.
*
- * @param size initial capacity
+ * @param minsize Minimum size
*/
- public IntegerMaxHeap(int size) {
- super(size);
+ public IntegerMaxHeap(int minsize) {
+ super();
+ if (minsize < TWO_HEAP_MAX_SIZE) {
+ final int size = MathUtil.nextPow2Int(minsize + 1) - 1;
+ int[] twoheap = new int[size];
+
+ this.twoheap = twoheap;
+ this.fourheap = null;
+ } else {
+ int[] twoheap = new int[TWO_HEAP_INITIAL_SIZE];
+ int[] fourheap = new int[Math.max(21, minsize - TWO_HEAP_MAX_SIZE)];
+ this.twoheap = twoheap;
+ this.fourheap = fourheap;
+ }
+ this.size = 0;
+ this.modCount = 0;
+ }
+
+ @Override
+ public void clear() {
+ size = 0;
+ ++modCount;
+ fourheap = null;
+ Arrays.fill(twoheap, 0);
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return (size == 0);
+ }
+
+ @Override
+ public void add(int o) {
+ final int co = o;
+ // System.err.println("Add: " + o);
+ if (size < TWO_HEAP_MAX_SIZE) {
+ if (size >= twoheap.length) {
+ // Grow by one layer.
+ twoheap = Arrays.copyOf(twoheap, twoheap.length + twoheap.length + 1);
+ }
+ final int twopos = size;
+ twoheap[twopos] = co;
+ ++size;
+ heapifyUp2(twopos, co);
+ ++modCount;
+ } else {
+ final int fourpos = size - TWO_HEAP_MAX_SIZE;
+ if (fourheap == null) {
+ fourheap = new int[FOUR_HEAP_INITIAL_SIZE];
+ } else if (fourpos >= fourheap.length) {
+ // Grow extension heap by half.
+ fourheap = Arrays.copyOf(fourheap, fourheap.length + (fourheap.length >> 1));
+ }
+ fourheap[fourpos] = co;
+ ++size;
+ heapifyUp4(fourpos, co);
+ ++modCount;
+ }
+ }
+
+ @Override
+ public void add(int key, int max) {
+ if (size < max) {
+ add(key);
+ } else if (twoheap[0] >= key) {
+ replaceTopElement(key);
+ }
+ }
+
+ @Override
+ public int replaceTopElement(int reinsert) {
+ final int ret = twoheap[0];
+ heapifyDown( reinsert);
+ ++modCount;
+ return ret;
+ }
+
+ /**
+ * Heapify-Up method for 2-ary heap.
+ *
+ * @param twopos Position in 2-ary heap.
+ * @param cur Current object
+ */
+ private void heapifyUp2(int twopos, int cur) {
+ while (twopos > 0) {
+ final int parent = (twopos - 1) >>> 1;
+ int par = twoheap[parent];
+ if (cur <= par) {
+ break;
+ }
+ twoheap[twopos] = par;
+ twopos = parent;
+ }
+ twoheap[twopos] = cur;
+ }
+
+ /**
+ * Heapify-Up method for 4-ary heap.
+ *
+ * @param fourpos Position in 4-ary heap.
+ * @param cur Current object
+ */
+ private void heapifyUp4(int fourpos, int cur) {
+ while (fourpos > 0) {
+ final int parent = (fourpos - 1) >> 2;
+ int par = fourheap[parent];
+ if (cur <= par) {
+ break;
+ }
+ fourheap[fourpos] = par;
+ fourpos = parent;
+ }
+ if (fourpos == 0 && twoheap[0] < cur) {
+ fourheap[0] = twoheap[0];
+ twoheap[0] = cur;
+ } else {
+ fourheap[fourpos] = cur;
+ }
+ }
+
+ @Override
+ public int poll() {
+ final int ret = twoheap[0];
+ --size;
+ // Replacement object:
+ if (size >= TWO_HEAP_MAX_SIZE) {
+ final int last = size - TWO_HEAP_MAX_SIZE;
+ final int reinsert = fourheap[last];
+ fourheap[last] = 0;
+ heapifyDown(reinsert);
+ } else if (size > 0) {
+ final int reinsert = twoheap[size];
+ twoheap[size] = 0;
+ heapifyDown(reinsert);
+ } else {
+ twoheap[0] = 0;
+ }
+ ++modCount;
+ return ret;
+ }
+
+ /**
+ * Invoke heapify-down for the root object.
+ *
+ * @param reinsert Object to insert.
+ */
+ private void heapifyDown(int reinsert) {
+ if (size > TWO_HEAP_MAX_SIZE) {
+ // Special case: 3-ary situation.
+ final int best = (twoheap[1] >= twoheap[2]) ? 1 : 2;
+ if (fourheap[0] > twoheap[best]) {
+ twoheap[0] = fourheap[0];
+ heapifyDown4(0, reinsert);
+ } else {
+ twoheap[0] = twoheap[best];
+ heapifyDown2(best, reinsert);
+ }
+ return;
+ }
+ heapifyDown2(0, reinsert);
+ }
+
+ /**
+ * Heapify-Down for 2-ary heap.
+ *
+ * @param twopos Position in 2-ary heap.
+ * @param cur Current object
+ */
+ private void heapifyDown2(int twopos, int cur) {
+ final int stop = Math.min(size, TWO_HEAP_MAX_SIZE) >>> 1;
+ while (twopos < stop) {
+ int bestchild = (twopos << 1) + 1;
+ int best = twoheap[bestchild];
+ final int right = bestchild + 1;
+ if (right < size && best < twoheap[right]) {
+ bestchild = right;
+ best = twoheap[right];
+ }
+ if (cur >= best) {
+ break;
+ }
+ twoheap[twopos] = best;
+ twopos = bestchild;
+ }
+ twoheap[twopos] = cur;
}
/**
- * Compare two objects
+ * Heapify-Down for 4-ary heap.
*
- * @param o1 First object
- * @param o2 Second object
+ * @param fourpos Position in 4-ary heap.
+ * @param cur Current object
*/
+ private void heapifyDown4(int fourpos, int cur) {
+ final int stop = (size - TWO_HEAP_MAX_SIZE + 2) >>> 2;
+ while (fourpos < stop) {
+ final int child = (fourpos << 2) + 1;
+ int best = fourheap[child];
+ int bestchild = child, candidate = child + 1, minsize = candidate + TWO_HEAP_MAX_SIZE;
+ if (size > minsize) {
+ int nextchild = fourheap[candidate];
+ if (best < nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+
+ minsize += 2;
+ if (size >= minsize) {
+ nextchild = fourheap[++candidate];
+ if (best < nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+
+ if (size > minsize) {
+ nextchild = fourheap[++candidate];
+ if (best < nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+ }
+ }
+ }
+ if (cur >= best) {
+ break;
+ }
+ fourheap[fourpos] = best;
+ fourpos = bestchild;
+ }
+ fourheap[fourpos] = cur;
+ }
+
+ @Override
+ public int peek() {
+ return twoheap[0];
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder buf = new StringBuilder();
+ buf.append(IntegerMaxHeap.class.getSimpleName()).append(" [");
+ for (UnsortedIter iter = new UnsortedIter(); iter.valid(); iter.advance()) {
+ buf.append(iter.get()).append(',');
+ }
+ buf.append(']');
+ return buf.toString();
+ }
+
@Override
- protected boolean comp(int o1, int o2) {
- return o1 < o2;
+ public UnsortedIter unsortedIter() {
+ return new UnsortedIter();
+ }
+
+ /**
+ * Unsorted iterator - in heap order. Does not poll the heap.
+ *
+ * Use this class as follows:
+ *
+ * <pre>
+ * {@code
+ * for (IntegerHeap.UnsortedIter iter = heap.unsortedIter(); iter.valid(); iter.next()) {
+ * doSomething(iter.get());
+ * }
+ * }
+ * </pre>
+ *
+ * @author Erich Schubert
+ */
+ private class UnsortedIter implements IntegerHeap.UnsortedIter {
+ /**
+ * Iterator position.
+ */
+ protected int pos = 0;
+
+ /**
+ * Modification counter we were initialized at.
+ */
+ protected final int myModCount = modCount;
+
+ @Override
+ public boolean valid() {
+ if (modCount != myModCount) {
+ throw new ConcurrentModificationException();
+ }
+ return pos < size;
+ }
+
+ @Override
+ public void advance() {
+ pos++;
+ }
+
+ @Override
+ public int get() {
+ return ((pos < TWO_HEAP_MAX_SIZE) ? twoheap[pos] : fourheap[pos - TWO_HEAP_MAX_SIZE]);
+ }
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerMinHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerMinHeap.java
index f81fe275..c352ece4 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerMinHeap.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerMinHeap.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,40 +23,400 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import java.util.Arrays;
+import java.util.ConcurrentModificationException;
+
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+
/**
- * Basic in-memory heap structure.
+ * Advanced priority queue class, based on a binary heap (for small sizes),
+ * which will for larger heaps be accompanied by a 4-ary heap (attached below
+ * the root of the two-ary heap, making the root actually 3-ary).
+ *
+ * This code was automatically instantiated for the type: Integer
*
- * This heap is built lazily: if you first add many elements, then poll the
- * heap, it will be bulk-loaded in O(n) instead of iteratively built in O(n log
- * n). This is implemented via a simple validTo counter.
+ * This combination was found to work quite well in benchmarks, but YMMV.
+ *
+ * Some other observations from benchmarking:
+ * <ul>
+ * <li>Bulk loading did not improve things</li>
+ * <li>Primitive heaps are substantially faster.</li>
+ * <li>Since an array in Java has an overhead of 12 bytes, odd-sized object and
+ * integer arrays are actually well aligned both for 2-ary and 4-ary heaps.</li>
+ * <li>Workload makes a huge difference. A load-once, poll-until-empty priority
+ * queue is something different than e.g. a top-k heap, which will see a lot of
+ * top element replacements.</li>
+ * <li>Random vs. increasing vs. decreasing vs. sawtooth insertion patterns for
+ * top-k make a difference.</li>
+ * <li>Different day, different benchmark results ...</li>
+ * </ul>
*
* @author Erich Schubert
+ *
+ * @apiviz.has UnsortedIter
*/
-public class IntegerMinHeap extends IntegerHeap {
+public class IntegerMinHeap implements IntegerHeap {
+ /**
+ * Base heap.
+ */
+ protected int[] twoheap;
+
+ /**
+ * Extension heap.
+ */
+ protected int[] fourheap;
+
+ /**
+ * Current size of heap.
+ */
+ protected int size;
+
+ /**
+ * (Structural) modification counter. Used to invalidate iterators.
+ */
+ protected int modCount = 0;
+
+ /**
+ * Maximum size of the 2-ary heap. A complete 2-ary heap has (2^k-1) elements.
+ */
+ private final static int TWO_HEAP_MAX_SIZE = (1 << 9) - 1;
+
/**
- * Constructor with default capacity.
+ * Initial size of the 2-ary heap.
+ */
+ private final static int TWO_HEAP_INITIAL_SIZE = (1 << 5) - 1;
+
+ /**
+ * Initial size of 4-ary heap when initialized.
+ *
+ * 21 = 4-ary heap of height 2: 1 + 4 + 4*4
+ *
+ * 85 = 4-ary heap of height 3: 21 + 4*4*4
+ *
+ * 341 = 4-ary heap of height 4: 85 + 4*4*4*4
+ *
+ * Since we last grew by 255 (to 511), let's use 341.
+ */
+ private final static int FOUR_HEAP_INITIAL_SIZE = 341;
+
+ /**
+ * Constructor, with default size.
*/
public IntegerMinHeap() {
- super(DEFAULT_INITIAL_CAPACITY);
+ super();
+ int[] twoheap = new int[TWO_HEAP_INITIAL_SIZE];
+
+ this.twoheap = twoheap;
+ this.fourheap = null;
+ this.size = 0;
+ this.modCount = 0;
}
/**
- * Constructor with initial capacity.
+ * Constructor, with given minimum size.
*
- * @param size initial capacity
+ * @param minsize Minimum size
*/
- public IntegerMinHeap(int size) {
- super(size);
+ public IntegerMinHeap(int minsize) {
+ super();
+ if (minsize < TWO_HEAP_MAX_SIZE) {
+ final int size = MathUtil.nextPow2Int(minsize + 1) - 1;
+ int[] twoheap = new int[size];
+
+ this.twoheap = twoheap;
+ this.fourheap = null;
+ } else {
+ int[] twoheap = new int[TWO_HEAP_INITIAL_SIZE];
+ int[] fourheap = new int[Math.max(21, minsize - TWO_HEAP_MAX_SIZE)];
+ this.twoheap = twoheap;
+ this.fourheap = fourheap;
+ }
+ this.size = 0;
+ this.modCount = 0;
+ }
+
+ @Override
+ public void clear() {
+ size = 0;
+ ++modCount;
+ fourheap = null;
+ Arrays.fill(twoheap, 0);
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return (size == 0);
+ }
+
+ @Override
+ public void add(int o) {
+ final int co = o;
+ // System.err.println("Add: " + o);
+ if (size < TWO_HEAP_MAX_SIZE) {
+ if (size >= twoheap.length) {
+ // Grow by one layer.
+ twoheap = Arrays.copyOf(twoheap, twoheap.length + twoheap.length + 1);
+ }
+ final int twopos = size;
+ twoheap[twopos] = co;
+ ++size;
+ heapifyUp2(twopos, co);
+ ++modCount;
+ } else {
+ final int fourpos = size - TWO_HEAP_MAX_SIZE;
+ if (fourheap == null) {
+ fourheap = new int[FOUR_HEAP_INITIAL_SIZE];
+ } else if (fourpos >= fourheap.length) {
+ // Grow extension heap by half.
+ fourheap = Arrays.copyOf(fourheap, fourheap.length + (fourheap.length >> 1));
+ }
+ fourheap[fourpos] = co;
+ ++size;
+ heapifyUp4(fourpos, co);
+ ++modCount;
+ }
+ }
+
+ @Override
+ public void add(int key, int max) {
+ if (size < max) {
+ add(key);
+ } else if (twoheap[0] <= key) {
+ replaceTopElement(key);
+ }
+ }
+
+ @Override
+ public int replaceTopElement(int reinsert) {
+ final int ret = twoheap[0];
+ heapifyDown( reinsert);
+ ++modCount;
+ return ret;
+ }
+
+ /**
+ * Heapify-Up method for 2-ary heap.
+ *
+ * @param twopos Position in 2-ary heap.
+ * @param cur Current object
+ */
+ private void heapifyUp2(int twopos, int cur) {
+ while (twopos > 0) {
+ final int parent = (twopos - 1) >>> 1;
+ int par = twoheap[parent];
+ if (cur >= par) {
+ break;
+ }
+ twoheap[twopos] = par;
+ twopos = parent;
+ }
+ twoheap[twopos] = cur;
+ }
+
+ /**
+ * Heapify-Up method for 4-ary heap.
+ *
+ * @param fourpos Position in 4-ary heap.
+ * @param cur Current object
+ */
+ private void heapifyUp4(int fourpos, int cur) {
+ while (fourpos > 0) {
+ final int parent = (fourpos - 1) >> 2;
+ int par = fourheap[parent];
+ if (cur >= par) {
+ break;
+ }
+ fourheap[fourpos] = par;
+ fourpos = parent;
+ }
+ if (fourpos == 0 && twoheap[0] > cur) {
+ fourheap[0] = twoheap[0];
+ twoheap[0] = cur;
+ } else {
+ fourheap[fourpos] = cur;
+ }
+ }
+
+ @Override
+ public int poll() {
+ final int ret = twoheap[0];
+ --size;
+ // Replacement object:
+ if (size >= TWO_HEAP_MAX_SIZE) {
+ final int last = size - TWO_HEAP_MAX_SIZE;
+ final int reinsert = fourheap[last];
+ fourheap[last] = 0;
+ heapifyDown(reinsert);
+ } else if (size > 0) {
+ final int reinsert = twoheap[size];
+ twoheap[size] = 0;
+ heapifyDown(reinsert);
+ } else {
+ twoheap[0] = 0;
+ }
+ ++modCount;
+ return ret;
+ }
+
+ /**
+ * Invoke heapify-down for the root object.
+ *
+ * @param reinsert Object to insert.
+ */
+ private void heapifyDown(int reinsert) {
+ if (size > TWO_HEAP_MAX_SIZE) {
+ // Special case: 3-ary situation.
+ final int best = (twoheap[1] <= twoheap[2]) ? 1 : 2;
+ if (fourheap[0] < twoheap[best]) {
+ twoheap[0] = fourheap[0];
+ heapifyDown4(0, reinsert);
+ } else {
+ twoheap[0] = twoheap[best];
+ heapifyDown2(best, reinsert);
+ }
+ return;
+ }
+ heapifyDown2(0, reinsert);
+ }
+
+ /**
+ * Heapify-Down for 2-ary heap.
+ *
+ * @param twopos Position in 2-ary heap.
+ * @param cur Current object
+ */
+ private void heapifyDown2(int twopos, int cur) {
+ final int stop = Math.min(size, TWO_HEAP_MAX_SIZE) >>> 1;
+ while (twopos < stop) {
+ int bestchild = (twopos << 1) + 1;
+ int best = twoheap[bestchild];
+ final int right = bestchild + 1;
+ if (right < size && best > twoheap[right]) {
+ bestchild = right;
+ best = twoheap[right];
+ }
+ if (cur <= best) {
+ break;
+ }
+ twoheap[twopos] = best;
+ twopos = bestchild;
+ }
+ twoheap[twopos] = cur;
}
/**
- * Compare two objects
+ * Heapify-Down for 4-ary heap.
*
- * @param o1 First object
- * @param o2 Second object
+ * @param fourpos Position in 4-ary heap.
+ * @param cur Current object
*/
+ private void heapifyDown4(int fourpos, int cur) {
+ final int stop = (size - TWO_HEAP_MAX_SIZE + 2) >>> 2;
+ while (fourpos < stop) {
+ final int child = (fourpos << 2) + 1;
+ int best = fourheap[child];
+ int bestchild = child, candidate = child + 1, minsize = candidate + TWO_HEAP_MAX_SIZE;
+ if (size > minsize) {
+ int nextchild = fourheap[candidate];
+ if (best > nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+
+ minsize += 2;
+ if (size >= minsize) {
+ nextchild = fourheap[++candidate];
+ if (best > nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+
+ if (size > minsize) {
+ nextchild = fourheap[++candidate];
+ if (best > nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+ }
+ }
+ }
+ if (cur <= best) {
+ break;
+ }
+ fourheap[fourpos] = best;
+ fourpos = bestchild;
+ }
+ fourheap[fourpos] = cur;
+ }
+
+ @Override
+ public int peek() {
+ return twoheap[0];
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder buf = new StringBuilder();
+ buf.append(IntegerMinHeap.class.getSimpleName()).append(" [");
+ for (UnsortedIter iter = new UnsortedIter(); iter.valid(); iter.advance()) {
+ buf.append(iter.get()).append(',');
+ }
+ buf.append(']');
+ return buf.toString();
+ }
+
@Override
- protected boolean comp(int o1, int o2) {
- return o1 > o2;
+ public UnsortedIter unsortedIter() {
+ return new UnsortedIter();
+ }
+
+ /**
+ * Unsorted iterator - in heap order. Does not poll the heap.
+ *
+ * Use this class as follows:
+ *
+ * <pre>
+ * {@code
+ * for (IntegerHeap.UnsortedIter iter = heap.unsortedIter(); iter.valid(); iter.next()) {
+ * doSomething(iter.get());
+ * }
+ * }
+ * </pre>
+ *
+ * @author Erich Schubert
+ */
+ private class UnsortedIter implements IntegerHeap.UnsortedIter {
+ /**
+ * Iterator position.
+ */
+ protected int pos = 0;
+
+ /**
+ * Modification counter we were initialized at.
+ */
+ protected final int myModCount = modCount;
+
+ @Override
+ public boolean valid() {
+ if (modCount != myModCount) {
+ throw new ConcurrentModificationException();
+ }
+ return pos < size;
+ }
+
+ @Override
+ public void advance() {
+ pos++;
+ }
+
+ @Override
+ public int get() {
+ return ((pos < TWO_HEAP_MAX_SIZE) ? twoheap[pos] : fourheap[pos - TWO_HEAP_MAX_SIZE]);
+ }
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerObjectHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerObjectHeap.java
new file mode 100644
index 00000000..01f7aea0
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerObjectHeap.java
@@ -0,0 +1,129 @@
+package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.utilities.datastructures.iterator.Iter;
+
+/**
+ * Basic in-memory heap interface, for int keys and V values.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has UnsortedIter
+ * @param <V> Value type
+ */
+public interface IntegerObjectHeap<V> {
+ /**
+ * Add a key-value pair to the heap
+ *
+ * @param key Key
+ * @param val Value
+ */
+ void add(int key, V val);
+
+ /**
+ * Add a key-value pair to the heap if it improves the top.
+ *
+ * @param key Key
+ * @param val Value
+ * @param k Desired maximum size
+ */
+ void add(int key, V val, int k);
+
+ /**
+ * Combined operation that removes the top element, and inserts a new element
+ * instead.
+ *
+ * @param key Key of new element
+ * @param val Value of new element
+ */
+ void replaceTopElement(int key, V val);
+
+ /**
+ * Get the current top key
+ *
+ * @return Top key
+ */
+ int peekKey();
+
+ /**
+ * Get the current top value
+ *
+ * @return Value
+ */
+ V peekValue();
+
+ /**
+ * Remove the first element
+ */
+ void poll();
+
+ /**
+ * Clear the heap contents.
+ */
+ void clear();
+
+ /**
+ * Query the size
+ *
+ * @return Size
+ */
+ public int size();
+
+ /**
+ * Is the heap empty?
+ *
+ * @return {@code true} when the size is 0.
+ */
+ public boolean isEmpty();
+
+ /**
+ * Get an unsorted iterator to inspect the heap.
+ *
+ * @return Iterator
+ */
+ UnsortedIter<V> unsortedIter();
+
+ /**
+ * Unsorted iterator - in heap order. Does not poll the heap.
+ *
+ * @author Erich Schubert
+ * @param <V> Value type
+ */
+ public static interface UnsortedIter<V> extends Iter {
+ /**
+ * Get the current key
+ *
+ * @return Current key
+ */
+ int getKey();
+
+ /**
+ * Get the current value
+ *
+ * @return Current value
+ */
+ V getValue();
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerObjectMaxHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerObjectMaxHeap.java
new file mode 100644
index 00000000..93a4e75a
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerObjectMaxHeap.java
@@ -0,0 +1,482 @@
+package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.Arrays;
+import java.util.ConcurrentModificationException;
+
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+
+/**
+ * Advanced priority queue class, based on a binary heap (for small sizes),
+ * which will for larger heaps be accompanied by a 4-ary heap (attached below
+ * the root of the two-ary heap, making the root actually 3-ary).
+ *
+ * This code was automatically instantiated for the types: Integer and Object
+ *
+ * This combination was found to work quite well in benchmarks, but YMMV.
+ *
+ * Some other observations from benchmarking:
+ * <ul>
+ * <li>Bulk loading did not improve things</li>
+ * <li>Primitive heaps are substantially faster.</li>
+ * <li>Since an array in Java has an overhead of 12 bytes, odd-sized object and
+ * integer arrays are actually well aligned both for 2-ary and 4-ary heaps.</li>
+ * <li>Workload makes a huge difference. A load-once, poll-until-empty priority
+ * queue is something different than e.g. a top-k heap, which will see a lot of
+ * top element replacements.</li>
+ * <li>Random vs. increasing vs. decreasing vs. sawtooth insertion patterns for
+ * top-k make a difference.</li>
+ * <li>Different day, different benchmark results ...</li>
+ * </ul>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has UnsortedIter
+ * @param <V> Value type
+ */
+public class IntegerObjectMaxHeap<V> implements IntegerObjectHeap<V> {
+ /**
+ * Base heap.
+ */
+ protected int[] twoheap;
+
+ /**
+ * Base heap values.
+ */
+ protected Object[] twovals;
+
+ /**
+ * Extension heap.
+ */
+ protected int[] fourheap;
+
+ /**
+ * Extension heapvalues.
+ */
+ protected Object[] fourvals;
+
+ /**
+ * Current size of heap.
+ */
+ protected int size;
+
+ /**
+ * (Structural) modification counter. Used to invalidate iterators.
+ */
+ protected int modCount = 0;
+
+ /**
+ * Maximum size of the 2-ary heap. A complete 2-ary heap has (2^k-1) elements.
+ */
+ private final static int TWO_HEAP_MAX_SIZE = (1 << 9) - 1;
+
+ /**
+ * Initial size of the 2-ary heap.
+ */
+ private final static int TWO_HEAP_INITIAL_SIZE = (1 << 5) - 1;
+
+ /**
+ * Initial size of 4-ary heap when initialized.
+ *
+ * 21 = 4-ary heap of height 2: 1 + 4 + 4*4
+ *
+ * 85 = 4-ary heap of height 3: 21 + 4*4*4
+ *
+ * 341 = 4-ary heap of height 4: 85 + 4*4*4*4
+ *
+ * Since we last grew by 255 (to 511), let's use 341.
+ */
+ private final static int FOUR_HEAP_INITIAL_SIZE = 341;
+
+ /**
+ * Constructor, with default size.
+ */
+ public IntegerObjectMaxHeap() {
+ super();
+ int[] twoheap = new int[TWO_HEAP_INITIAL_SIZE];
+ Object[] twovals = new Object[TWO_HEAP_INITIAL_SIZE];
+
+ this.twoheap = twoheap;
+ this.twovals = twovals;
+ this.fourheap = null;
+ this.fourvals = null;
+ this.size = 0;
+ this.modCount = 0;
+ }
+
+ /**
+ * Constructor, with given minimum size.
+ *
+ * @param minsize Minimum size
+ */
+ public IntegerObjectMaxHeap(int minsize) {
+ super();
+ if (minsize < TWO_HEAP_MAX_SIZE) {
+ final int size = MathUtil.nextPow2Int(minsize + 1) - 1;
+ int[] twoheap = new int[size];
+ Object[] twovals = new Object[size];
+
+ this.twoheap = twoheap;
+ this.twovals = twovals;
+ this.fourheap = null;
+ this.fourvals = null;
+ } else {
+ int[] twoheap = new int[TWO_HEAP_INITIAL_SIZE];
+ Object[] twovals = new Object[TWO_HEAP_INITIAL_SIZE];
+ int[] fourheap = new int[Math.max(21, minsize - TWO_HEAP_MAX_SIZE)];
+ Object[] fourvals = new Object[Math.max(21, minsize - TWO_HEAP_MAX_SIZE)];
+ this.twoheap = twoheap;
+ this.twovals = twovals;
+ this.fourheap = fourheap;
+ this.fourvals = fourvals;
+ }
+ this.size = 0;
+ this.modCount = 0;
+ }
+
+ @Override
+ public void clear() {
+ size = 0;
+ ++modCount;
+ fourheap = null;
+ fourvals = null;
+ Arrays.fill(twoheap, 0);
+ Arrays.fill(twovals, null);
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return (size == 0);
+ }
+
+ @Override
+ public void add(int o, V v) {
+ final int co = o;
+ final Object cv = (Object)v;
+ // System.err.println("Add: " + o);
+ if (size < TWO_HEAP_MAX_SIZE) {
+ if (size >= twoheap.length) {
+ // Grow by one layer.
+ twoheap = Arrays.copyOf(twoheap, twoheap.length + twoheap.length + 1);
+ twovals = Arrays.copyOf(twovals, twovals.length + twovals.length + 1);
+ }
+ final int twopos = size;
+ twoheap[twopos] = co;
+ twovals[twopos] = cv;
+ ++size;
+ heapifyUp2(twopos, co, cv);
+ ++modCount;
+ } else {
+ final int fourpos = size - TWO_HEAP_MAX_SIZE;
+ if (fourheap == null) {
+ fourheap = new int[FOUR_HEAP_INITIAL_SIZE];
+ fourvals = new Object[FOUR_HEAP_INITIAL_SIZE];
+ } else if (fourpos >= fourheap.length) {
+ // Grow extension heap by half.
+ fourheap = Arrays.copyOf(fourheap, fourheap.length + (fourheap.length >> 1));
+ fourvals = Arrays.copyOf(fourvals, fourvals.length + (fourvals.length >> 1));
+ }
+ fourheap[fourpos] = co;
+ fourvals[fourpos] = cv;
+ ++size;
+ heapifyUp4(fourpos, co, cv);
+ ++modCount;
+ }
+ }
+
+ @Override
+ public void add(int key, V val, int max) {
+ if (size < max) {
+ add(key, val);
+ } else if (twoheap[0] >= key) {
+ replaceTopElement(key, val);
+ }
+ }
+
+ @Override
+ public void replaceTopElement(int reinsert, V val) {
+ heapifyDown(reinsert, (Object)val);
+ ++modCount;
+ }
+
+ /**
+ * Heapify-Up method for 2-ary heap.
+ *
+ * @param twopos Position in 2-ary heap.
+ * @param cur Current object
+ * @param val Current value
+ */
+ private void heapifyUp2(int twopos, int cur, Object val) {
+ while (twopos > 0) {
+ final int parent = (twopos - 1) >>> 1;
+ int par = twoheap[parent];
+ if (cur <= par) {
+ break;
+ }
+ twoheap[twopos] = par;
+ twovals[twopos] = twovals[parent];
+ twopos = parent;
+ }
+ twoheap[twopos] = cur;
+ twovals[twopos] = val;
+ }
+
+ /**
+ * Heapify-Up method for 4-ary heap.
+ *
+ * @param fourpos Position in 4-ary heap.
+ * @param cur Current object
+ * @param val Current value
+ */
+ private void heapifyUp4(int fourpos, int cur, Object val) {
+ while (fourpos > 0) {
+ final int parent = (fourpos - 1) >> 2;
+ int par = fourheap[parent];
+ if (cur <= par) {
+ break;
+ }
+ fourheap[fourpos] = par;
+ fourvals[fourpos] = fourvals[parent];
+ fourpos = parent;
+ }
+ if (fourpos == 0 && twoheap[0] < cur) {
+ fourheap[0] = twoheap[0];
+ fourvals[0] = twovals[0];
+ twoheap[0] = cur;
+ twovals[0] = val;
+ } else {
+ fourheap[fourpos] = cur;
+ fourvals[fourpos] = val;
+ }
+ }
+
+ @Override
+ public void poll() {
+ --size;
+ // Replacement object:
+ if (size >= TWO_HEAP_MAX_SIZE) {
+ final int last = size - TWO_HEAP_MAX_SIZE;
+ final int reinsert = fourheap[last];
+ final Object reinsertv = fourvals[last];
+ fourheap[last] = 0;
+ fourvals[last] = null;
+ heapifyDown(reinsert, reinsertv);
+ } else if (size > 0) {
+ final int reinsert = twoheap[size];
+ final Object reinsertv = twovals[size];
+ twoheap[size] = 0;
+ twovals[size] = null;
+ heapifyDown(reinsert, reinsertv);
+ } else {
+ twoheap[0] = 0;
+ twovals[0] = null;
+ }
+ ++modCount;
+ }
+
+ /**
+ * Invoke heapify-down for the root object.
+ *
+ * @param reinsert Object to insert.
+ * @param val Value to reinsert.
+ */
+ private void heapifyDown(int reinsert, Object val) {
+ if (size > TWO_HEAP_MAX_SIZE) {
+ // Special case: 3-ary situation.
+ final int best = (twoheap[1] >= twoheap[2]) ? 1 : 2;
+ if (fourheap[0] > twoheap[best]) {
+ twoheap[0] = fourheap[0];
+ twovals[0] = fourvals[0];
+ heapifyDown4(0, reinsert, val);
+ } else {
+ twoheap[0] = twoheap[best];
+ twovals[0] = twovals[best];
+ heapifyDown2(best, reinsert, val);
+ }
+ return;
+ }
+ heapifyDown2(0, reinsert, val);
+ }
+
+ /**
+ * Heapify-Down for 2-ary heap.
+ *
+ * @param twopos Position in 2-ary heap.
+ * @param cur Current object
+ * @param val Value to reinsert.
+ */
+ private void heapifyDown2(int twopos, int cur, Object val) {
+ final int stop = Math.min(size, TWO_HEAP_MAX_SIZE) >>> 1;
+ while (twopos < stop) {
+ int bestchild = (twopos << 1) + 1;
+ int best = twoheap[bestchild];
+ final int right = bestchild + 1;
+ if (right < size && best < twoheap[right]) {
+ bestchild = right;
+ best = twoheap[right];
+ }
+ if (cur >= best) {
+ break;
+ }
+ twoheap[twopos] = best;
+ twovals[twopos] = twovals[bestchild];
+ twopos = bestchild;
+ }
+ twoheap[twopos] = cur;
+ twovals[twopos] = val;
+ }
+
+ /**
+ * Heapify-Down for 4-ary heap.
+ *
+ * @param fourpos Position in 4-ary heap.
+ * @param cur Current object
+ * @param val Value to reinsert.
+ */
+ private void heapifyDown4(int fourpos, int cur, Object val) {
+ final int stop = (size - TWO_HEAP_MAX_SIZE + 2) >>> 2;
+ while (fourpos < stop) {
+ final int child = (fourpos << 2) + 1;
+ int best = fourheap[child];
+ int bestchild = child, candidate = child + 1, minsize = candidate + TWO_HEAP_MAX_SIZE;
+ if (size > minsize) {
+ int nextchild = fourheap[candidate];
+ if (best < nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+
+ minsize += 2;
+ if (size >= minsize) {
+ nextchild = fourheap[++candidate];
+ if (best < nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+
+ if (size > minsize) {
+ nextchild = fourheap[++candidate];
+ if (best < nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+ }
+ }
+ }
+ if (cur >= best) {
+ break;
+ }
+ fourheap[fourpos] = best;
+ fourvals[fourpos] = fourvals[bestchild];
+ fourpos = bestchild;
+ }
+ fourheap[fourpos] = cur;
+ fourvals[fourpos] = val;
+ }
+
+ @Override
+ public int peekKey() {
+ return twoheap[0];
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public V peekValue() {
+ return (V)twovals[0];
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder buf = new StringBuilder();
+ buf.append(IntegerObjectMaxHeap.class.getSimpleName()).append(" [");
+ for (UnsortedIter iter = new UnsortedIter(); iter.valid(); iter.advance()) {
+ buf.append(iter.getKey()).append(':').append(iter.getValue()).append(',');
+ }
+ buf.append(']');
+ return buf.toString();
+ }
+
+ @Override
+ public UnsortedIter unsortedIter() {
+ return new UnsortedIter();
+ }
+
+ /**
+ * Unsorted iterator - in heap order. Does not poll the heap.
+ *
+ * Use this class as follows:
+ *
+ * <pre>
+ * {@code
+ * for (IntegerObjectHeap.UnsortedIter<V> iter = heap.unsortedIter(); iter.valid(); iter.next()) {
+ * doSomething(iter.get());
+ * }
+ * }
+ * </pre>
+ *
+ * @author Erich Schubert
+ */
+ private class UnsortedIter implements IntegerObjectHeap.UnsortedIter<V> {
+ /**
+ * Iterator position.
+ */
+ protected int pos = 0;
+
+ /**
+ * Modification counter we were initialized at.
+ */
+ protected final int myModCount = modCount;
+
+ @Override
+ public boolean valid() {
+ if (modCount != myModCount) {
+ throw new ConcurrentModificationException();
+ }
+ return pos < size;
+ }
+
+ @Override
+ public void advance() {
+ pos++;
+ }
+
+ @Override
+ public int getKey() {
+ return ((pos < TWO_HEAP_MAX_SIZE) ? twoheap[pos] : fourheap[pos - TWO_HEAP_MAX_SIZE]);
+ }
+
+ @SuppressWarnings("unchecked")
+
+ @Override
+ public V getValue() {
+ return (V)((pos < TWO_HEAP_MAX_SIZE) ? twovals[pos] : fourvals[pos - TWO_HEAP_MAX_SIZE]);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerObjectMinHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerObjectMinHeap.java
new file mode 100644
index 00000000..e54c7d28
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerObjectMinHeap.java
@@ -0,0 +1,482 @@
+package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.Arrays;
+import java.util.ConcurrentModificationException;
+
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+
+/**
+ * Advanced priority queue class, based on a binary heap (for small sizes),
+ * which will for larger heaps be accompanied by a 4-ary heap (attached below
+ * the root of the two-ary heap, making the root actually 3-ary).
+ *
+ * This code was automatically instantiated for the types: Integer and Object
+ *
+ * This combination was found to work quite well in benchmarks, but YMMV.
+ *
+ * Some other observations from benchmarking:
+ * <ul>
+ * <li>Bulk loading did not improve things</li>
+ * <li>Primitive heaps are substantially faster.</li>
+ * <li>Since an array in Java has an overhead of 12 bytes, odd-sized object and
+ * integer arrays are actually well aligned both for 2-ary and 4-ary heaps.</li>
+ * <li>Workload makes a huge difference. A load-once, poll-until-empty priority
+ * queue is something different than e.g. a top-k heap, which will see a lot of
+ * top element replacements.</li>
+ * <li>Random vs. increasing vs. decreasing vs. sawtooth insertion patterns for
+ * top-k make a difference.</li>
+ * <li>Different day, different benchmark results ...</li>
+ * </ul>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has UnsortedIter
+ * @param <V> Value type
+ */
+public class IntegerObjectMinHeap<V> implements IntegerObjectHeap<V> {
+ /**
+ * Base heap.
+ */
+ protected int[] twoheap;
+
+ /**
+ * Base heap values.
+ */
+ protected Object[] twovals;
+
+ /**
+ * Extension heap.
+ */
+ protected int[] fourheap;
+
+ /**
+ * Extension heapvalues.
+ */
+ protected Object[] fourvals;
+
+ /**
+ * Current size of heap.
+ */
+ protected int size;
+
+ /**
+ * (Structural) modification counter. Used to invalidate iterators.
+ */
+ protected int modCount = 0;
+
+ /**
+ * Maximum size of the 2-ary heap. A complete 2-ary heap has (2^k-1) elements.
+ */
+ private final static int TWO_HEAP_MAX_SIZE = (1 << 9) - 1;
+
+ /**
+ * Initial size of the 2-ary heap.
+ */
+ private final static int TWO_HEAP_INITIAL_SIZE = (1 << 5) - 1;
+
+ /**
+ * Initial size of 4-ary heap when initialized.
+ *
+ * 21 = 4-ary heap of height 2: 1 + 4 + 4*4
+ *
+ * 85 = 4-ary heap of height 3: 21 + 4*4*4
+ *
+ * 341 = 4-ary heap of height 4: 85 + 4*4*4*4
+ *
+ * Since we last grew by 255 (to 511), let's use 341.
+ */
+ private final static int FOUR_HEAP_INITIAL_SIZE = 341;
+
+ /**
+ * Constructor, with default size.
+ */
+ public IntegerObjectMinHeap() {
+ super();
+ int[] twoheap = new int[TWO_HEAP_INITIAL_SIZE];
+ Object[] twovals = new Object[TWO_HEAP_INITIAL_SIZE];
+
+ this.twoheap = twoheap;
+ this.twovals = twovals;
+ this.fourheap = null;
+ this.fourvals = null;
+ this.size = 0;
+ this.modCount = 0;
+ }
+
+ /**
+ * Constructor, with given minimum size.
+ *
+ * @param minsize Minimum size
+ */
+ public IntegerObjectMinHeap(int minsize) {
+ super();
+ if (minsize < TWO_HEAP_MAX_SIZE) {
+ final int size = MathUtil.nextPow2Int(minsize + 1) - 1;
+ int[] twoheap = new int[size];
+ Object[] twovals = new Object[size];
+
+ this.twoheap = twoheap;
+ this.twovals = twovals;
+ this.fourheap = null;
+ this.fourvals = null;
+ } else {
+ int[] twoheap = new int[TWO_HEAP_INITIAL_SIZE];
+ Object[] twovals = new Object[TWO_HEAP_INITIAL_SIZE];
+ int[] fourheap = new int[Math.max(21, minsize - TWO_HEAP_MAX_SIZE)];
+ Object[] fourvals = new Object[Math.max(21, minsize - TWO_HEAP_MAX_SIZE)];
+ this.twoheap = twoheap;
+ this.twovals = twovals;
+ this.fourheap = fourheap;
+ this.fourvals = fourvals;
+ }
+ this.size = 0;
+ this.modCount = 0;
+ }
+
+ @Override
+ public void clear() {
+ size = 0;
+ ++modCount;
+ fourheap = null;
+ fourvals = null;
+ Arrays.fill(twoheap, 0);
+ Arrays.fill(twovals, null);
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return (size == 0);
+ }
+
+ @Override
+ public void add(int o, V v) {
+ final int co = o;
+ final Object cv = (Object)v;
+ // System.err.println("Add: " + o);
+ if (size < TWO_HEAP_MAX_SIZE) {
+ if (size >= twoheap.length) {
+ // Grow by one layer.
+ twoheap = Arrays.copyOf(twoheap, twoheap.length + twoheap.length + 1);
+ twovals = Arrays.copyOf(twovals, twovals.length + twovals.length + 1);
+ }
+ final int twopos = size;
+ twoheap[twopos] = co;
+ twovals[twopos] = cv;
+ ++size;
+ heapifyUp2(twopos, co, cv);
+ ++modCount;
+ } else {
+ final int fourpos = size - TWO_HEAP_MAX_SIZE;
+ if (fourheap == null) {
+ fourheap = new int[FOUR_HEAP_INITIAL_SIZE];
+ fourvals = new Object[FOUR_HEAP_INITIAL_SIZE];
+ } else if (fourpos >= fourheap.length) {
+ // Grow extension heap by half.
+ fourheap = Arrays.copyOf(fourheap, fourheap.length + (fourheap.length >> 1));
+ fourvals = Arrays.copyOf(fourvals, fourvals.length + (fourvals.length >> 1));
+ }
+ fourheap[fourpos] = co;
+ fourvals[fourpos] = cv;
+ ++size;
+ heapifyUp4(fourpos, co, cv);
+ ++modCount;
+ }
+ }
+
+ @Override
+ public void add(int key, V val, int max) {
+ if (size < max) {
+ add(key, val);
+ } else if (twoheap[0] <= key) {
+ replaceTopElement(key, val);
+ }
+ }
+
+ @Override
+ public void replaceTopElement(int reinsert, V val) {
+ heapifyDown(reinsert, (Object)val);
+ ++modCount;
+ }
+
+ /**
+ * Heapify-Up method for 2-ary heap.
+ *
+ * @param twopos Position in 2-ary heap.
+ * @param cur Current object
+ * @param val Current value
+ */
+ private void heapifyUp2(int twopos, int cur, Object val) {
+ while (twopos > 0) {
+ final int parent = (twopos - 1) >>> 1;
+ int par = twoheap[parent];
+ if (cur >= par) {
+ break;
+ }
+ twoheap[twopos] = par;
+ twovals[twopos] = twovals[parent];
+ twopos = parent;
+ }
+ twoheap[twopos] = cur;
+ twovals[twopos] = val;
+ }
+
+ /**
+ * Heapify-Up method for 4-ary heap.
+ *
+ * @param fourpos Position in 4-ary heap.
+ * @param cur Current object
+ * @param val Current value
+ */
+ private void heapifyUp4(int fourpos, int cur, Object val) {
+ while (fourpos > 0) {
+ final int parent = (fourpos - 1) >> 2;
+ int par = fourheap[parent];
+ if (cur >= par) {
+ break;
+ }
+ fourheap[fourpos] = par;
+ fourvals[fourpos] = fourvals[parent];
+ fourpos = parent;
+ }
+ if (fourpos == 0 && twoheap[0] > cur) {
+ fourheap[0] = twoheap[0];
+ fourvals[0] = twovals[0];
+ twoheap[0] = cur;
+ twovals[0] = val;
+ } else {
+ fourheap[fourpos] = cur;
+ fourvals[fourpos] = val;
+ }
+ }
+
+ @Override
+ public void poll() {
+ --size;
+ // Replacement object:
+ if (size >= TWO_HEAP_MAX_SIZE) {
+ final int last = size - TWO_HEAP_MAX_SIZE;
+ final int reinsert = fourheap[last];
+ final Object reinsertv = fourvals[last];
+ fourheap[last] = 0;
+ fourvals[last] = null;
+ heapifyDown(reinsert, reinsertv);
+ } else if (size > 0) {
+ final int reinsert = twoheap[size];
+ final Object reinsertv = twovals[size];
+ twoheap[size] = 0;
+ twovals[size] = null;
+ heapifyDown(reinsert, reinsertv);
+ } else {
+ twoheap[0] = 0;
+ twovals[0] = null;
+ }
+ ++modCount;
+ }
+
+ /**
+ * Invoke heapify-down for the root object.
+ *
+ * @param reinsert Object to insert.
+ * @param val Value to reinsert.
+ */
+ private void heapifyDown(int reinsert, Object val) {
+ if (size > TWO_HEAP_MAX_SIZE) {
+ // Special case: 3-ary situation.
+ final int best = (twoheap[1] <= twoheap[2]) ? 1 : 2;
+ if (fourheap[0] < twoheap[best]) {
+ twoheap[0] = fourheap[0];
+ twovals[0] = fourvals[0];
+ heapifyDown4(0, reinsert, val);
+ } else {
+ twoheap[0] = twoheap[best];
+ twovals[0] = twovals[best];
+ heapifyDown2(best, reinsert, val);
+ }
+ return;
+ }
+ heapifyDown2(0, reinsert, val);
+ }
+
+ /**
+ * Heapify-Down for 2-ary heap.
+ *
+ * @param twopos Position in 2-ary heap.
+ * @param cur Current object
+ * @param val Value to reinsert.
+ */
+ private void heapifyDown2(int twopos, int cur, Object val) {
+ final int stop = Math.min(size, TWO_HEAP_MAX_SIZE) >>> 1;
+ while (twopos < stop) {
+ int bestchild = (twopos << 1) + 1;
+ int best = twoheap[bestchild];
+ final int right = bestchild + 1;
+ if (right < size && best > twoheap[right]) {
+ bestchild = right;
+ best = twoheap[right];
+ }
+ if (cur <= best) {
+ break;
+ }
+ twoheap[twopos] = best;
+ twovals[twopos] = twovals[bestchild];
+ twopos = bestchild;
+ }
+ twoheap[twopos] = cur;
+ twovals[twopos] = val;
+ }
+
+ /**
+ * Heapify-Down for 4-ary heap.
+ *
+ * @param fourpos Position in 4-ary heap.
+ * @param cur Current object
+ * @param val Value to reinsert.
+ */
+ private void heapifyDown4(int fourpos, int cur, Object val) {
+ final int stop = (size - TWO_HEAP_MAX_SIZE + 2) >>> 2;
+ while (fourpos < stop) {
+ final int child = (fourpos << 2) + 1;
+ int best = fourheap[child];
+ int bestchild = child, candidate = child + 1, minsize = candidate + TWO_HEAP_MAX_SIZE;
+ if (size > minsize) {
+ int nextchild = fourheap[candidate];
+ if (best > nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+
+ minsize += 2;
+ if (size >= minsize) {
+ nextchild = fourheap[++candidate];
+ if (best > nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+
+ if (size > minsize) {
+ nextchild = fourheap[++candidate];
+ if (best > nextchild) {
+ bestchild = candidate;
+ best = nextchild;
+ }
+ }
+ }
+ }
+ if (cur <= best) {
+ break;
+ }
+ fourheap[fourpos] = best;
+ fourvals[fourpos] = fourvals[bestchild];
+ fourpos = bestchild;
+ }
+ fourheap[fourpos] = cur;
+ fourvals[fourpos] = val;
+ }
+
+ @Override
+ public int peekKey() {
+ return twoheap[0];
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public V peekValue() {
+ return (V)twovals[0];
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder buf = new StringBuilder();
+ buf.append(IntegerObjectMinHeap.class.getSimpleName()).append(" [");
+ for (UnsortedIter iter = new UnsortedIter(); iter.valid(); iter.advance()) {
+ buf.append(iter.getKey()).append(':').append(iter.getValue()).append(',');
+ }
+ buf.append(']');
+ return buf.toString();
+ }
+
+ @Override
+ public UnsortedIter unsortedIter() {
+ return new UnsortedIter();
+ }
+
+ /**
+ * Unsorted iterator - in heap order. Does not poll the heap.
+ *
+ * Use this class as follows:
+ *
+ * <pre>
+ * {@code
+ * for (IntegerObjectHeap.UnsortedIter<V> iter = heap.unsortedIter(); iter.valid(); iter.next()) {
+ * doSomething(iter.get());
+ * }
+ * }
+ * </pre>
+ *
+ * @author Erich Schubert
+ */
+ private class UnsortedIter implements IntegerObjectHeap.UnsortedIter<V> {
+ /**
+ * Iterator position.
+ */
+ protected int pos = 0;
+
+ /**
+ * Modification counter we were initialized at.
+ */
+ protected final int myModCount = modCount;
+
+ @Override
+ public boolean valid() {
+ if (modCount != myModCount) {
+ throw new ConcurrentModificationException();
+ }
+ return pos < size;
+ }
+
+ @Override
+ public void advance() {
+ pos++;
+ }
+
+ @Override
+ public int getKey() {
+ return ((pos < TWO_HEAP_MAX_SIZE) ? twoheap[pos] : fourheap[pos - TWO_HEAP_MAX_SIZE]);
+ }
+
+ @SuppressWarnings("unchecked")
+
+ @Override
+ public V getValue() {
+ return (V)((pos < TWO_HEAP_MAX_SIZE) ? twovals[pos] : fourvals[pos - TWO_HEAP_MAX_SIZE]);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerPriorityObject.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerPriorityObject.java
index 2014de65..f007b9fc 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerPriorityObject.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerPriorityObject.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/ObjectHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/ObjectHeap.java
index 2e20ed56..b5dbbb0e 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/ObjectHeap.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/ObjectHeap.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,53 +23,24 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.Arrays;
-
-import de.lmu.ifi.dbs.elki.math.MathUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.iterator.Iter;
/**
- * Basic in-memory heap structure.
- *
- * This heap is built lazily: if you first add many elements, then poll the
- * heap, it will be bulk-loaded in O(n) instead of iteratively built in O(n log
- * n). This is implemented via a simple validTo counter.
+ * Basic in-memory heap for K values.
*
* @author Erich Schubert
+ *
+ * @apiviz.has UnsortedIter
+ *
+ * @param <K> Key type
*/
-public abstract class ObjectHeap<K> extends AbstractHeap {
- /**
- * Heap storage: queue
- */
- protected transient Object[] queue;
-
- /**
- * Constructor with initial capacity.
- *
- * @param size initial capacity
- */
- public ObjectHeap(int size) {
- super();
- this.size = 0;
- this.queue = new Object[size];
- }
-
+public interface ObjectHeap<K> {
/**
* Add a key-value pair to the heap
*
* @param key Key
*/
- public void add(Object key) {
- // resize when needed
- if (size + 1 > queue.length) {
- resize(size + 1);
- }
- // final int pos = size;
- this.queue[size] = key;
- this.size += 1;
- heapifyUp(size - 1, key);
- validSize += 1;
- heapModified();
- }
+ void add(K key);
/**
* Add a key-value pair to the heap, except if the new element is larger than
@@ -78,13 +49,7 @@ public abstract class ObjectHeap<K> extends AbstractHeap {
* @param key Key
* @param max Maximum size of heap
*/
- public void add(Object key, int max) {
- if (size < max) {
- add(key);
- } else if (comp(key, peek())) {
- replaceTopElement(key);
- }
- }
+ void add(K key, int max);
/**
* Combined operation that removes the top element, and inserts a new element
@@ -93,175 +58,69 @@ public abstract class ObjectHeap<K> extends AbstractHeap {
* @param e New element to insert
* @return Previous top element of the heap
*/
- @SuppressWarnings("unchecked")
- public Object replaceTopElement(Object e) {
- ensureValid();
- Object oldroot = (K) queue[0];
- heapifyDown(0, e);
- heapModified();
- return oldroot;
- }
+ K replaceTopElement(K e);
/**
* Get the current top key
*
* @return Top key
*/
- @SuppressWarnings("unchecked")
- public Object peek() {
- if (size == 0) {
- throw new ArrayIndexOutOfBoundsException("Peek() on an empty heap!");
- }
- ensureValid();
- return (K) queue[0];
- }
+ K peek();
/**
* Remove the first element
*
* @return Top element
*/
- public Object poll() {
- return removeAt(0);
- }
+ K poll();
/**
- * Repair the heap
+ * Delete all elements from the heap.
*/
- protected void ensureValid() {
- if (validSize != size) {
- if (size > 1) {
- // Parent of first invalid
- int nextmin = validSize > 0 ? ((validSize - 1) >>> 1) : 0;
- int curmin = MathUtil.nextAllOnesInt(nextmin); // Next line
- int nextmax = curmin - 1; // End of valid line
- int pos = (size - 2) >>> 1; // Parent of last element
- // System.err.println(validSize+"<="+size+" iter:"+pos+"->"+curmin+", "+nextmin);
- while (pos >= nextmin) {
- // System.err.println(validSize+"<="+size+" iter:"+pos+"->"+curmin);
- while (pos >= curmin) {
- if (!heapifyDown(pos, queue[pos])) {
- final int parent = (pos - 1) >>> 1;
- if (parent < curmin) {
- nextmin = Math.min(nextmin, parent);
- nextmax = Math.max(nextmax, parent);
- }
- }
- pos--;
- }
- curmin = nextmin;
- pos = Math.min(pos, nextmax);
- nextmax = -1;
- }
- }
- validSize = size;
- }
- }
+ void clear();
/**
- * Remove the element at the given position.
+ * Query the size
*
- * @param pos Element position.
- * @return Removed element
+ * @return Size
*/
- @SuppressWarnings("unchecked")
- protected Object removeAt(int pos) {
- if (pos < 0 || pos >= size) {
- return null;
- }
- final Object top = (K) queue[0];
- // Replacement object:
- final Object reinkey = queue[size - 1];
- // Keep heap in sync
- if (validSize == size) {
- size -= 1;
- validSize -= 1;
- heapifyDown(pos, reinkey);
- } else {
- size -= 1;
- validSize = Math.min(pos >>> 1, validSize);
- queue[pos] = reinkey;
- }
- heapModified();
- return top;
- }
+ public int size();
/**
- * Execute a "Heapify Upwards" aka "SiftUp". Used in insertions.
+ * Is the heap empty?
*
- * @param pos insertion position
- * @param curkey Current key
+ * @return {@code true} when the size is 0.
*/
- protected void heapifyUp(int pos, Object curkey) {
- while (pos > 0) {
- final int parent = (pos - 1) >>> 1;
- Object parkey = queue[parent];
-
- if (comp(curkey, parkey)) { // Compare
- break;
- }
- queue[pos] = parkey;
- pos = parent;
- }
- queue[pos] = curkey;
- }
+ public boolean isEmpty();
/**
- * Execute a "Heapify Downwards" aka "SiftDown". Used in deletions.
+ * Get an unsorted iterator to inspect the heap.
*
- * @param ipos re-insertion position
- * @param curkey Current key
- * @return true when the order was changed
+ * @return Iterator
*/
- protected boolean heapifyDown(final int ipos, Object curkey) {
- int pos = ipos;
- final int half = size >>> 1;
- while (pos < half) {
- // Get left child (must exist!)
- int cpos = (pos << 1) + 1;
- Object chikey = queue[cpos];
- // Test right child, if present
- final int rchild = cpos + 1;
- if (rchild < size) {
- Object right = queue[rchild];
- if (comp(chikey, right)) { // Compare
- cpos = rchild;
- chikey = right;
- }
- }
-
- if (comp(chikey, curkey)) { // Compare
- break;
- }
- queue[pos] = chikey;
- pos = cpos;
- }
- queue[pos] = curkey;
- return (pos == ipos);
- }
+ UnsortedIter<K> unsortedIter();
/**
- * Test whether we need to resize to have the requested capacity.
+ * Unsorted iterator - in heap order. Does not poll the heap.
*
- * @param requiredSize required capacity
- */
- protected final void resize(int requiredSize) {
- queue = Arrays.copyOf(queue, desiredSize(requiredSize, queue.length));
- }
-
- /**
- * Delete all elements from the heap.
+ * <pre>
+ * {@code
+ * for (ObjectHeap.UnsortedIter<K> iter = heap.unsortedIter(); iter.valid(); iter.next()) {
+ * doSomething(iter.get());
+ * }
+ * }
+ * </pre>
+ *
+ * @author Erich Schubert
+ *
+ * @param <K> Key type
*/
- @Override
- public void clear() {
- super.clear();
- for (int i = 0; i < size; i++) {
- queue[i] = null;
- }
+ public static interface UnsortedIter<K> extends Iter {
+ /**
+ * Get the iterators current object.
+ *
+ * @return Current object
+ */
+ K get();
}
-
- /**
- * Compare two objects
- */
- abstract protected boolean comp(Object o1, Object o2);
}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TiedTopBoundedHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TiedTopBoundedHeap.java
index 2daaafa4..32f57999 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TiedTopBoundedHeap.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TiedTopBoundedHeap.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,11 +25,8 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
import java.util.ArrayList;
import java.util.Comparator;
-import java.util.Iterator;
import java.util.List;
-import de.lmu.ifi.dbs.elki.utilities.iterator.MergedIterator;
-
/**
* A size-limited heap similar to {@link TopBoundedHeap}, discarding elements
* with the highest value. However, this variation keeps a list of tied
@@ -43,7 +40,7 @@ public class TiedTopBoundedHeap<E> extends TopBoundedHeap<E> {
/**
* List to keep ties in.
*/
- private List<E> ties = new ArrayList<E>();
+ private List<E> ties = new ArrayList<>();
/**
* Constructor with comparator.
@@ -75,12 +72,6 @@ public class TiedTopBoundedHeap<E> extends TopBoundedHeap<E> {
ties.clear();
}
- @SuppressWarnings("unchecked")
- @Override
- public Iterator<E> iterator() {
- return new MergedIterator<E>(ties.iterator(), super.iterator());
- }
-
@Override
public E peek() {
if (ties.isEmpty()) {
@@ -131,4 +122,44 @@ public class TiedTopBoundedHeap<E> extends TopBoundedHeap<E> {
ties.clear();
}
}
+
+ /**
+ * Get an unordered heap iterator.
+ *
+ * @return Iterator.
+ */
+ @Override
+ public UnorderedIter unorderedIter() {
+ return new UnorderedIter();
+ }
+
+ /**
+ * Unordered heap iterator class.
+ *
+ * @author Erich Schubert
+ *
+ */
+ public class UnorderedIter extends Heap<E>.UnorderedIter {
+ /**
+ * Constructor.
+ */
+ protected UnorderedIter() {
+ super();
+ }
+
+ @Override
+ public boolean valid() {
+ return pos < size();
+ }
+
+ @Override
+ public E get() {
+ final int ssize = TiedTopBoundedHeap.super.size();
+ if (pos < ssize) {
+ return super.get();
+ } else {
+ return ties.get(pos - ssize);
+ }
+ }
+ }
}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TiedTopBoundedUpdatableHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TiedTopBoundedUpdatableHeap.java
index 8e39af1d..3905030f 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TiedTopBoundedUpdatableHeap.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TiedTopBoundedUpdatableHeap.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,7 +29,6 @@ import java.util.Iterator;
import java.util.List;
import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
-import de.lmu.ifi.dbs.elki.utilities.iterator.MergedIterator;
/**
* A size-limited heap similar to {@link TopBoundedHeap}, discarding elements
@@ -44,7 +43,7 @@ public class TiedTopBoundedUpdatableHeap<E> extends TopBoundedUpdatableHeap<E> {
/**
* List to keep ties in.
*/
- private List<E> ties = new ArrayList<E>();
+ private List<E> ties = new ArrayList<>();
/**
* Constructor with comparator.
@@ -76,12 +75,6 @@ public class TiedTopBoundedUpdatableHeap<E> extends TopBoundedUpdatableHeap<E> {
ties.clear();
}
- @SuppressWarnings("unchecked")
- @Override
- public Iterator<E> iterator() {
- return new MergedIterator<E>(ties.iterator(), super.iterator());
- }
-
@Override
public void offerAt(int pos, E e) {
if(pos == IN_TIES) {
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TopBoundedHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TopBoundedHeap.java
index 07b595f6..9adda9f3 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TopBoundedHeap.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TopBoundedHeap.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -69,7 +69,6 @@ public class TopBoundedHeap<E> extends Heap<E> {
return;
}
// Peek at the top element, return if we are worse.
- ensureValid();
final int comp;
if (comparator == null) {
@SuppressWarnings("unchecked")
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TopBoundedUpdatableHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TopBoundedUpdatableHeap.java
index 75f2abcf..4a591d4c 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TopBoundedUpdatableHeap.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TopBoundedUpdatableHeap.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -68,7 +68,6 @@ public class TopBoundedUpdatableHeap<E> extends UpdatableHeap<E> {
super.offerAt(pos, e);
return;
}
- ensureValid();
if (compare(e, queue[0]) < 0) {
// while we did not change, this still was "successful".
return;
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/UpdatableHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/UpdatableHeap.java
index 1ab5f4df..a585d94d 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/UpdatableHeap.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/UpdatableHeap.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -49,7 +49,7 @@ public class UpdatableHeap<O> extends Heap<O> {
/**
* Holds the indices in the heap of each element.
*/
- protected final TObjectIntMap<Object> index = new TObjectIntHashMap<Object>(100, 0.5f, NO_VALUE);
+ protected final TObjectIntMap<Object> index = new TObjectIntHashMap<>(100, 0.5f, NO_VALUE);
/**
* Simple constructor with default size.
@@ -105,43 +105,32 @@ public class UpdatableHeap<O> extends Heap<O> {
* @param e Element
*/
protected void offerAt(final int pos, O e) {
- if(pos == NO_VALUE) {
+ if (pos == NO_VALUE) {
// resize when needed
- if(size + 1 > queue.length) {
+ if (size + 1 > queue.length) {
resize(size + 1);
}
- // final int pos = size;
- this.queue[size] = e;
index.put(e, size);
- size += 1;
- // We do NOT YET update the heap. This is done lazily.
+ size++;
+ heapifyUp(size - 1, e);
heapModified();
return;
- }
- else {
+ } else {
assert (pos >= 0) : "Unexpected negative position.";
assert (queue[pos].equals(e));
// Did the value improve?
- if(comparator == null) {
+ if (comparator == null) {
@SuppressWarnings("unchecked")
Comparable<Object> c = (Comparable<Object>) e;
- if(c.compareTo(queue[pos]) >= 0) {
+ if (c.compareTo(queue[pos]) >= 0) {
return;
}
- }
- else {
- if(comparator.compare(e, queue[pos]) >= 0) {
+ } else {
+ if (comparator.compare(e, queue[pos]) >= 0) {
return;
}
}
- if(pos >= validSize) {
- queue[pos] = e;
- // validSize = Math.min(pos, validSize);
- }
- else {
- // ensureValid();
- heapifyUp(pos, e);
- }
+ heapifyUp(pos, e);
heapModified();
return;
}
@@ -149,7 +138,7 @@ public class UpdatableHeap<O> extends Heap<O> {
@Override
protected O removeAt(int pos) {
- if(pos < 0 || pos >= size) {
+ if (pos < 0 || pos >= size) {
return null;
}
@SuppressWarnings("unchecked")
@@ -158,34 +147,22 @@ public class UpdatableHeap<O> extends Heap<O> {
final Object reinsert = queue[size - 1];
queue[size - 1] = null;
// Keep heap in sync?
- if(validSize == size) {
- size -= 1;
- validSize -= 1;
- if(comparator != null) {
- if(comparator.compare(ret, reinsert) > 0) {
- heapifyUpComparator(pos, reinsert);
- }
- else {
- heapifyDownComparator(pos, reinsert);
- }
+ size--;
+ if (comparator != null) {
+ if (comparator.compare(ret, reinsert) > 0) {
+ heapifyUpComparator(pos, reinsert);
+ } else {
+ heapifyDownComparator(pos, reinsert);
}
- else {
- @SuppressWarnings("unchecked")
- Comparable<Object> comp = (Comparable<Object>) ret;
- if(comp.compareTo(reinsert) > 0) {
- heapifyUpComparable(pos, reinsert);
- }
- else {
- heapifyDownComparable(pos, reinsert);
- }
+ } else {
+ @SuppressWarnings("unchecked")
+ Comparable<Object> comp = (Comparable<Object>) ret;
+ if (comp.compareTo(reinsert) > 0) {
+ heapifyUpComparable(pos, reinsert);
+ } else {
+ heapifyDownComparable(pos, reinsert);
}
}
- else {
- size -= 1;
- validSize = Math.min(pos >>> 1, validSize);
- queue[pos] = reinsert;
- index.put(reinsert, pos);
- }
heapModified();
// Keep index up to date
index.remove(ret);
@@ -200,10 +177,9 @@ public class UpdatableHeap<O> extends Heap<O> {
*/
public O removeObject(O e) {
int pos = index.get(e);
- if(pos >= 0) {
+ if (pos >= 0) {
return removeAt(pos);
- }
- else {
+ } else {
return null;
}
}
@@ -214,7 +190,7 @@ public class UpdatableHeap<O> extends Heap<O> {
index.remove(node);
return node;
}
-
+
@Override
public O replaceTopElement(O e) {
O node = super.replaceTopElement(e);
@@ -232,11 +208,11 @@ public class UpdatableHeap<O> extends Heap<O> {
@SuppressWarnings("unchecked")
protected void heapifyUpComparable(int pos, Object elem) {
final Comparable<Object> cur = (Comparable<Object>) elem; // queue[pos];
- while(pos > 0) {
+ while (pos > 0) {
final int parent = (pos - 1) >>> 1;
Object par = queue[parent];
- if(cur.compareTo(par) >= 0) {
+ if (cur.compareTo(par) >= 0) {
break;
}
queue[pos] = par;
@@ -255,11 +231,11 @@ public class UpdatableHeap<O> extends Heap<O> {
*/
@Override
protected void heapifyUpComparator(int pos, Object cur) {
- while(pos > 0) {
+ while (pos > 0) {
final int parent = (pos - 1) >>> 1;
Object par = queue[parent];
- if(comparator.compare(cur, par) >= 0) {
+ if (comparator.compare(cur, par) >= 0) {
break;
}
queue[pos] = par;
@@ -276,21 +252,21 @@ public class UpdatableHeap<O> extends Heap<O> {
Comparable<Object> cur = (Comparable<Object>) reinsert;
int pos = ipos;
final int half = size >>> 1;
- while(pos < half) {
+ while (pos < half) {
// Get left child (must exist!)
int cpos = (pos << 1) + 1;
Object child = queue[cpos];
// Test right child, if present
final int rchild = cpos + 1;
- if(rchild < size) {
+ if (rchild < size) {
Object right = queue[rchild];
- if(((Comparable<Object>) child).compareTo(right) > 0) {
+ if (((Comparable<Object>) child).compareTo(right) > 0) {
cpos = rchild;
child = right;
}
}
- if(cur.compareTo(child) <= 0) {
+ if (cur.compareTo(child) <= 0) {
break;
}
queue[pos] = child;
@@ -299,32 +275,32 @@ public class UpdatableHeap<O> extends Heap<O> {
}
queue[pos] = cur;
index.put(cur, pos);
- return (pos == ipos);
+ return (pos != ipos);
}
@Override
protected boolean heapifyDownComparator(final int ipos, Object cur) {
int pos = ipos;
final int half = size >>> 1;
- while(pos < half) {
+ while (pos < half) {
int min = pos;
Object best = cur;
final int lchild = (pos << 1) + 1;
Object left = queue[lchild];
- if(comparator.compare(best, left) > 0) {
+ if (comparator.compare(best, left) > 0) {
min = lchild;
best = left;
}
final int rchild = lchild + 1;
- if(rchild < size) {
+ if (rchild < size) {
Object right = queue[rchild];
- if(comparator.compare(best, right) > 0) {
+ if (comparator.compare(best, right) > 0) {
min = rchild;
best = right;
}
}
- if(min == pos) {
+ if (min == pos) {
break;
}
queue[pos] = best;
@@ -333,6 +309,6 @@ public class UpdatableHeap<O> extends Heap<O> {
}
queue[pos] = cur;
index.put(cur, pos);
- return (pos == ipos);
+ return (pos != ipos);
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/package-info.java
index 3f193171..83be37f4 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/HashMapHierarchy.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/HashMapHierarchy.java
new file mode 100644
index 00000000..c77a9329
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/HashMapHierarchy.java
@@ -0,0 +1,580 @@
+package de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+
+/**
+ * Centralized hierarchy implementation, using a HashMap of Lists.
+ *
+ * @author Erich Schubert
+ *
+ * @param <O> Object type (arbitrary!)
+ */
+public class HashMapHierarchy<O> implements ModifiableHierarchy<O> {
+ /**
+ * Reference storage.
+ */
+ final private HashMap<O, Rec<O>> graph;
+
+ /**
+ * Constructor.
+ */
+ public HashMapHierarchy() {
+ super();
+ this.graph = new HashMap<>();
+ }
+
+ @Override
+ public int size() {
+ return graph.size();
+ }
+
+ @Override
+ public void add(O parent, O child) {
+ // Add child to parent.
+ {
+ Rec<O> rec = graph.get(parent);
+ if (rec == null) {
+ rec = new Rec<>();
+ graph.put(parent, rec);
+ }
+ rec.addChild(child);
+ }
+ // Add child to parent
+ {
+ Rec<O> rec = graph.get(child);
+ if (rec == null) {
+ rec = new Rec<>();
+ graph.put(child, rec);
+ }
+ rec.addParent(parent);
+ }
+ }
+
+ @Override
+ public void add(O entry) {
+ Rec<O> rec = graph.get(entry);
+ if (rec == null) {
+ rec = new Rec<>();
+ graph.put(entry, rec);
+ }
+ }
+
+ @Override
+ public void remove(O parent, O child) {
+ // Remove child from parent.
+ {
+ Rec<O> rec = graph.get(parent);
+ if (rec != null) {
+ rec.removeChild(child);
+ }
+ }
+ // Remove parent from child
+ {
+ Rec<O> rec = graph.get(child);
+ if (rec != null) {
+ rec.removeParent(parent);
+ }
+ }
+ }
+
+ @Override
+ public void remove(O entry) {
+ Rec<O> rec = graph.get(entry);
+ if (rec == null) {
+ return;
+ }
+ for (int i = 0; i < rec.nump; i++) {
+ graph.get(rec.parents[i]).removeChild(entry);
+ rec.parents[i] = null;
+ }
+ for (int i = 0; i < rec.numc; i++) {
+ graph.get(rec.children[i]).removeParent(entry);
+ rec.children[i] = null;
+ }
+ graph.remove(entry);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void removeSubtree(O entry) {
+ Rec<O> rec = graph.get(entry);
+ if (rec == null) {
+ return;
+ }
+ for (int i = 0; i < rec.nump; i++) {
+ graph.get(rec.parents[i]).removeChild(entry);
+ rec.parents[i] = null;
+ }
+ for (int i = 0; i < rec.numc; i++) {
+ final Rec<O> crec = graph.get(rec.children[i]);
+ crec.removeParent(entry);
+ if (crec.nump == 0) {
+ removeSubtree((O) rec.children[i]);
+ }
+ rec.children[i] = null;
+ }
+ }
+
+ @Override
+ public int numChildren(O obj) {
+ Rec<O> rec = graph.get(obj);
+ if (rec == null) {
+ return 0;
+ }
+ return rec.numc;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Iter<O> iterChildren(O obj) {
+ Rec<O> rec = graph.get(obj);
+ if (rec == null) {
+ return (Iter<O>) EMPTY_ITERATOR;
+ }
+ return rec.iterChildren();
+ }
+
+ @Override
+ public Iter<O> iterDescendants(O obj) {
+ return new ItrDesc(obj);
+ }
+
+ @Override
+ public int numParents(O obj) {
+ Rec<O> rec = graph.get(obj);
+ if (rec == null) {
+ return 0;
+ }
+ return rec.nump;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Iter<O> iterParents(O obj) {
+ Rec<O> rec = graph.get(obj);
+ if (rec == null) {
+ return (Iter<O>) EMPTY_ITERATOR;
+ }
+ return rec.iterParents();
+ }
+
+ @Override
+ public Iter<O> iterAncestors(O obj) {
+ return new ItrAnc(obj);
+ }
+
+ @Override
+ public Iter<O> iterAll() {
+ return new ItrAll();
+ }
+
+ /**
+ * Hierarchy pointers for an object.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ *
+ * @param <O> object type
+ */
+ private static class Rec<O> {
+ /**
+ * Number of parents, number of children.
+ */
+ int nump = 0, numc = 0;
+
+ /**
+ * Parents.
+ */
+ Object[] parents = null;
+
+ /**
+ * Children.
+ */
+ Object[] children = null;
+
+ /**
+ * Add a parent.
+ *
+ * @param parent Parent to add.
+ */
+ void addParent(O parent) {
+ if (parents == null) {
+ parents = new Object[1];
+ parents[0] = parent;
+ nump = 1;
+ } else {
+ for (int i = 0; i < nump; i++) {
+ if (parent.equals(parents[i])) {
+ return;
+ }
+ }
+ if (parents.length == nump) {
+ final int newsize = Math.min(5, (parents.length << 1) + 1);
+ parents = Arrays.copyOf(parents, newsize);
+ }
+ parents[nump] = parent;
+ nump++;
+ }
+ }
+
+ /**
+ * Add a child.
+ *
+ * @param child Child to add
+ */
+ void addChild(O child) {
+ if (children == null) {
+ children = new Object[5];
+ children[0] = child;
+ numc = 1;
+ } else {
+ for (int i = 0; i < numc; i++) {
+ if (child.equals(children[i])) {
+ return;
+ }
+ }
+ if (children.length == numc) {
+ children = Arrays.copyOf(children, (children.length << 1) + 1);
+ }
+ children[numc] = child;
+ numc++;
+ }
+ }
+
+ /**
+ * Remove a parent.
+ *
+ * @param parent Parent to remove.
+ */
+ void removeParent(O parent) {
+ if (parents == null) {
+ return;
+ }
+ for (int i = 0; i < nump; i++) {
+ if (parent.equals(parents[i])) {
+ System.arraycopy(parents, i + 1, parents, i, nump - 1 - i);
+ parents[nump] = null;
+ nump--;
+ break;
+ }
+ }
+ if (nump == 0) {
+ parents = null;
+ }
+ }
+
+ /**
+ * Remove a child.
+ *
+ * @param child Child to remove.
+ */
+ void removeChild(O child) {
+ if (children == null) {
+ return;
+ }
+ for (int i = 0; i < numc; i++) {
+ if (child.equals(children[i])) {
+ System.arraycopy(children, i + 1, children, i, numc - 1 - i);
+ children[numc] = null;
+ numc--;
+ break;
+ }
+ }
+ if (numc == 0) {
+ children = null;
+ }
+ }
+
+ /**
+ * Iterate over parents.
+ *
+ * @return Iterator for parents.
+ */
+ @SuppressWarnings("unchecked")
+ public Iter<O> iterParents() {
+ if (nump == 0) {
+ return (Iter<O>) EMPTY_ITERATOR;
+ }
+ return new ItrParents();
+ }
+
+ /**
+ * Iterate over parents.
+ *
+ * @return Iterator for parents.
+ */
+ @SuppressWarnings("unchecked")
+ public Iter<O> iterChildren() {
+ if (numc == 0) {
+ return (Iter<O>) EMPTY_ITERATOR;
+ }
+ return new ItrChildren();
+ }
+
+ /**
+ * Parent iterator.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ class ItrParents implements Iter<O> {
+ int pos = 0;
+
+ @Override
+ public boolean valid() {
+ return pos < nump;
+ }
+
+ @Override
+ public void advance() {
+ pos++;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public O get() {
+ return (O) parents[pos];
+ }
+ }
+
+ /**
+ * Child iterator.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ class ItrChildren implements Iter<O> {
+ int pos = 0;
+
+ @Override
+ public boolean valid() {
+ return pos < numc;
+ }
+
+ @Override
+ public void advance() {
+ pos++;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public O get() {
+ return (O) children[pos];
+ }
+ }
+ }
+
+ /**
+ * Iterator to collect into the descendants.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ private class ItrDesc implements Iter<O> {
+ /**
+ * Iterator over children
+ */
+ final Iter<O> childiter;
+
+ /**
+ * Iterator of current child
+ */
+ Iter<O> subiter = null;
+
+ /**
+ * Starting element.
+ *
+ * @param start
+ */
+ ItrDesc(O start) {
+ childiter = iterChildren(start);
+ }
+
+ @Override
+ public boolean valid() {
+ return childiter.valid() || (subiter != null && subiter.valid());
+ }
+
+ @Override
+ public void advance() {
+ if (subiter == null) { // Not yet descended
+ assert (childiter.valid());
+ subiter = iterDescendants(childiter.get());
+ } else { // Continue with subtree
+ subiter.advance();
+ }
+ if (subiter.valid()) {
+ return;
+ }
+ // Proceed to next child.
+ childiter.advance();
+ subiter = null;
+ }
+
+ @Override
+ public O get() {
+ if (subiter != null) {
+ assert (subiter.valid());
+ return subiter.get();
+ } else {
+ assert (childiter.valid());
+ return childiter.get();
+ }
+ }
+ }
+
+ /**
+ * Iterator over all Ancestors.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ private class ItrAnc implements Iter<O> {
+ /**
+ * Iterator over children
+ */
+ final Iter<O> parentiter;
+
+ /**
+ * Iterator of current child
+ */
+ Iter<O> subiter = null;
+
+ /**
+ * Starting element.
+ *
+ * @param start
+ */
+ ItrAnc(O start) {
+ parentiter = iterParents(start);
+ }
+
+ @Override
+ public boolean valid() {
+ return parentiter.valid() || (subiter != null && subiter.valid());
+ }
+
+ @Override
+ public void advance() {
+ if (subiter == null) { // Not yet descended
+ assert (parentiter.valid());
+ subiter = iterAncestors(parentiter.get());
+ } else { // Continue with subtree
+ subiter.advance();
+ }
+ if (subiter.valid()) {
+ return;
+ }
+ // Proceed to next child.
+ parentiter.advance();
+ subiter = null;
+ }
+
+ @Override
+ public O get() {
+ if (subiter != null) {
+ assert (subiter.valid());
+ return subiter.get();
+ } else {
+ assert (parentiter.valid());
+ return parentiter.get();
+ }
+ }
+ }
+
+ /**
+ * Iterator over all members of the hierarchy.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ private class ItrAll implements Iter<O> {
+ /**
+ * The true iterator.
+ */
+ final Iterator<O> iter;
+
+ /**
+ * Current object.
+ */
+ O cur = null;
+
+ /**
+ * Constructor.
+ */
+ ItrAll() {
+ iter = graph.keySet().iterator();
+ advance();
+ }
+
+ @Override
+ public boolean valid() {
+ return cur != null;
+ }
+
+ @Override
+ public void advance() {
+ if (iter.hasNext()) {
+ cur = iter.next();
+ } else {
+ cur = null;
+ }
+ }
+
+ @Override
+ public O get() {
+ return cur;
+ }
+ }
+
+ /**
+ * Empty iterator.
+ */
+ private static final Iter<?> EMPTY_ITERATOR = new Iter<Object>() {
+ @Override
+ public boolean valid() {
+ return false;
+ }
+
+ @Override
+ public void advance() {
+ throw new UnsupportedOperationException("Empty iterators must not be advanced.");
+ }
+
+ @Override
+ public Object get() {
+ throw new UnsupportedOperationException("Iterator is empty.");
+ }
+ };
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/Hierarchical.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/Hierarchical.java
deleted file mode 100644
index 29909069..00000000
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/Hierarchical.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy;
-
-/*
- This file is part of ELKI:
- Environment for Developing KDD-Applications Supported by Index-Structures
-
- Copyright (C) 2012
- Ludwig-Maximilians-Universität München
- Lehr- und Forschungseinheit für Datenbanksysteme
- ELKI Development Team
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-import java.util.Iterator;
-import java.util.List;
-
-
-/**
- * Interface for objects with an <b>internal</b> hierarchy interface.
- *
- * Note that the object can chose to delegate the hierarchy to an external hierarchy.
- *
- * @author Erich Schubert
- *
- * @param <O> Object type in hierarchy
- */
-public interface Hierarchical<O> {
- /**
- * Test for hierarchical properties
- *
- * @return hierarchical data model.
- */
- public boolean isHierarchical();
-
- /**
- * Get number of children
- *
- * @return number of children
- */
- public int numChildren();
-
- /**
- * Get children list. Resulting list MAY be modified. Result MAY be null, if
- * the model is not hierarchical.
- *
- * @return list of children
- */
- public List<O> getChildren();
-
- /**
- * Iterate descendants (recursive children)
- *
- * @return iterator for descendants
- */
- public Iterator<O> iterDescendants();
-
- /**
- * Get number of parents
- *
- * @return number of parents
- */
- public int numParents();
-
- /**
- * Get parents list. Resulting list MAY be modified. Result MAY be null, if
- * the model is not hierarchical.
- *
- * @return list of parents
- */
- public List<O> getParents();
-
- /**
- * Iterate ancestors (recursive parents)
- *
- * @return iterator for ancestors
- */
- public Iterator<O> iterAncestors();
-} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/Hierarchy.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/Hierarchy.java
index 0a16e9b7..fec9c7b4 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/Hierarchy.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/Hierarchy.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,38 +23,40 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.Iterator;
-import java.util.List;
-
/**
* This interface represents an (external) hierarchy of objects. It can contain
* arbitrary objects, BUT the hierarchy has to be accessed using the hierarchy
- * object, i.e. {@code hierarchy.getChildren(object);}.
- *
- * See {@link Hierarchical} for an interface for objects with an internal
- * hierarchy (where you can use {@code object.getChildren();})
+ * object, i.e. {@code hierarchy.iterChildren(object);}.
*
* @author Erich Schubert
*
+ * @apiviz.has Iter
+ *
* @param <O> Object type
*/
public interface Hierarchy<O> {
/**
+ * Total size - number of objects contained.
+ *
+ * @return Size
+ */
+ int size();
+
+ /**
* Get number of children
*
* @param self object to get number of children for
* @return number of children
*/
- public int numChildren(O self);
+ int numChildren(O self);
/**
- * Get children list. Resulting list MAY be modified. Result MAY be null, if
- * the model is not hierarchical.
+ * Iterate over the (direct) children.
*
* @param self object to get children for
- * @return list of children
+ * @return iterator for children
*/
- public List<O> getChildren(O self);
+ Iter<O> iterChildren(O self);
/**
* Iterate descendants (recursive children)
@@ -62,7 +64,7 @@ public interface Hierarchy<O> {
* @param self object to get descendants for
* @return iterator for descendants
*/
- public Iterator<O> iterDescendants(O self);
+ Iter<O> iterDescendants(O self);
/**
* Get number of (direct) parents
@@ -70,16 +72,15 @@ public interface Hierarchy<O> {
* @param self reference object
* @return number of parents
*/
- public int numParents(O self);
+ int numParents(O self);
/**
- * Get parents list. Resulting list MAY be modified. Result MAY be null, if
- * the model is not hierarchical.
+ * Iterate over the (direct) parents.
*
* @param self object to get parents for
- * @return list of parents
+ * @return iterator of parents
*/
- public List<O> getParents(O self);
+ Iter<O> iterParents(O self);
/**
* Iterate ancestors (recursive parents)
@@ -87,5 +88,30 @@ public interface Hierarchy<O> {
* @param self object to get ancestors for
* @return iterator for ancestors
*/
- public Iterator<O> iterAncestors(O self);
-} \ No newline at end of file
+ Iter<O> iterAncestors(O self);
+
+ /**
+ * Iterate over all members.
+ *
+ * @return Iterator over all members.
+ */
+ Iter<O> iterAll();
+
+ /**
+ * Iterator interface.
+ *
+ * TODO: add a skipSubtree method?
+ *
+ * @author Erich Schubert
+ *
+ * @param <O> Object type.
+ */
+ static interface Iter<O> extends de.lmu.ifi.dbs.elki.utilities.datastructures.iterator.Iter {
+ /**
+ * Access the current object.
+ *
+ * @return Current object
+ */
+ O get();
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/HierarchyHashmapList.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/HierarchyHashmapList.java
deleted file mode 100644
index bd6d67bf..00000000
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/HierarchyHashmapList.java
+++ /dev/null
@@ -1,299 +0,0 @@
-package de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy;
-
-/*
- This file is part of ELKI:
- Environment for Developing KDD-Applications Supported by Index-Structures
-
- Copyright (C) 2012
- Ludwig-Maximilians-Universität München
- Lehr- und Forschungseinheit für Datenbanksysteme
- ELKI Development Team
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-
-import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
-import de.lmu.ifi.dbs.elki.utilities.iterator.EmptyIterator;
-
-/**
- * Centralized hierarchy implementation, using a HashMap of Lists.
- *
- * @author Erich Schubert
- *
- * @param <O> Object type (arbitrary!)
- */
-public class HierarchyHashmapList<O> implements ModifiableHierarchy<O> {
- /**
- * The data storage for parents
- */
- final private HashMap<O, List<O>> pmap;
-
- /**
- * The data storage for children
- */
- final private HashMap<O, List<O>> cmap;
-
- /**
- * Constructor
- */
- public HierarchyHashmapList() {
- super();
- this.pmap = new HashMap<O, List<O>>();
- this.cmap = new HashMap<O, List<O>>();
- }
-
- @Override
- public void add(O parent, O child) {
- // Add child to parent.
- {
- List<O> pchi = this.cmap.get(parent);
- if(pchi == null) {
- pchi = new LinkedList<O>();
- this.cmap.put(parent, pchi);
- }
- if(!pchi.contains(child)) {
- pchi.add(child);
- } else {
- LoggingUtil.warning("Result added twice: "+parent+" -> "+child, new Throwable());
- }
- }
- // Add child to parent
- {
- List<O> cpar = this.pmap.get(child);
- if(cpar == null) {
- cpar = new LinkedList<O>();
- this.pmap.put(child, cpar);
- }
- if(!cpar.contains(parent)) {
- cpar.add(parent);
- } else {
- LoggingUtil.warning("Result added twice: "+parent+" <- "+child, new Throwable());
- }
- }
- }
-
- @Override
- public void remove(O parent, O child) {
- // Remove child from parent.
- {
- List<O> pchi = this.cmap.get(parent);
- if(pchi != null) {
- while(pchi.remove(child)) {
- // repeat - remove all instances
- }
- if(pchi.size() == 0) {
- this.cmap.remove(parent);
- }
- }
- }
- // Remove parent from child
- {
- List<O> cpar = this.pmap.get(child);
- if(cpar != null) {
- while(cpar.remove(parent)) {
- // repeat - remove all instances
- }
- if(cpar.size() == 0) {
- this.pmap.remove(child);
- }
- }
- }
- }
-
- /**
- * Put an object along with parent and child lists.
- *
- * @param obj Object
- * @param parents Parent list
- * @param children Child list
- */
- public void put(O obj, List<O> parents, List<O> children) {
- this.pmap.put(obj, parents);
- this.cmap.put(obj, children);
- }
-
- @Override
- public int numChildren(O obj) {
- List<O> children = this.cmap.get(obj);
- if(children == null) {
- return 0;
- }
- return children.size();
- }
-
- @Override
- public List<O> getChildren(O obj) {
- List<O> children = this.cmap.get(obj);
- if(children == null) {
- return Collections.emptyList();
- }
- return children;
- }
-
- @Override
- public Iterator<O> iterDescendants(O obj) {
- return new ItrDesc(obj);
- }
-
- @Override
- public int numParents(O obj) {
- List<O> parents = this.pmap.get(obj);
- if(parents == null) {
- return 0;
- }
- return parents.size();
- }
-
- @Override
- public List<O> getParents(O obj) {
- List<O> parents = this.pmap.get(obj);
- if(parents == null) {
- return Collections.emptyList();
- }
- return parents;
- }
-
- @Override
- public Iterator<O> iterAncestors(O obj) {
- return new ItrAnc(obj);
- }
-
- /**
- * Iterator to collect into the descendants.
- *
- * @author Erich Schubert
- *
- * @apiviz.exclude
- */
- private class ItrDesc implements Iterator<O> {
- /**
- * Starting object (for cloning);
- */
- final O start;
-
- /**
- * Iterator over children
- */
- final Iterator<O> childiter;
-
- /**
- * Iterator of current child
- */
- Iterator<O> subiter;
-
- public ItrDesc(O start) {
- this.start = start;
- List<O> children = getChildren(start);
- if(children != null) {
- this.childiter = children.iterator();
- }
- else {
- this.childiter = EmptyIterator.STATIC();
- }
- this.subiter = null;
- }
-
- @Override
- public boolean hasNext() {
- if(subiter != null && subiter.hasNext()) {
- return true;
- }
- return childiter.hasNext();
- }
-
- @Override
- public O next() {
- // Try nested iterator first ...
- if(subiter != null && subiter.hasNext()) {
- return subiter.next();
- }
- // Next direct child, update subiter.
- final O child = childiter.next();
- subiter = iterDescendants(child);
- return child;
- }
-
- @Override
- public void remove() {
- throw new UnsupportedOperationException();
- }
- }
-
- /**
- * Iterator over all Ancestors.
- *
- * @author Erich Schubert
- *
- * @apiviz.exclude
- */
- private class ItrAnc implements Iterator<O> {
- /**
- * Starting object (for cloning);
- */
- final O start;
-
- /**
- * Iterator over parents
- */
- final Iterator<O> parentiter;
-
- /**
- * Iterator of current parent
- */
- Iterator<O> subiter;
-
- public ItrAnc(O start) {
- this.start = start;
- List<O> parents = getParents(start);
- if(parents != null) {
- this.parentiter = parents.iterator();
- }
- else {
- this.parentiter = EmptyIterator.STATIC();
- }
- this.subiter = null;
- }
-
- @Override
- public boolean hasNext() {
- if(subiter != null && subiter.hasNext()) {
- return true;
- }
- return parentiter.hasNext();
- }
-
- @Override
- public O next() {
- // Try nested iterator first ...
- if(subiter != null && subiter.hasNext()) {
- return subiter.next();
- }
- // Next direct parent, update subiter.
- final O parent = parentiter.next();
- subiter = iterAncestors(parent);
- return parent;
- }
-
- @Override
- public void remove() {
- throw new UnsupportedOperationException();
- }
- }
-} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/HierarchyReferenceLists.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/HierarchyReferenceLists.java
deleted file mode 100644
index 76091298..00000000
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/HierarchyReferenceLists.java
+++ /dev/null
@@ -1,232 +0,0 @@
-package de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy;
-
-/*
- This file is part of ELKI:
- Environment for Developing KDD-Applications Supported by Index-Structures
-
- Copyright (C) 2012
- Ludwig-Maximilians-Universität München
- Lehr- und Forschungseinheit für Datenbanksysteme
- ELKI Development Team
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-import java.util.Iterator;
-import java.util.List;
-
-import de.lmu.ifi.dbs.elki.utilities.iterator.EmptyIterator;
-
-/**
- * Hierarchy implementation with a per-object representation.
- *
- * @author Erich Schubert
- *
- * @apiviz.uses Hierarchical
- *
- * @param <O> Type of objects in hierarchy
- */
-public class HierarchyReferenceLists<O extends Hierarchical<O>> implements Hierarchy<O> {
- /**
- * Owner
- */
- protected O owner;
-
- /**
- * Storage for children
- */
- protected List<O> children;
-
- /**
- * Storage for parents
- */
- protected List<O> parents;
-
- /**
- * Constructor for hierarchy object.
- *
- * @param owner owning cluster.
- * @param children child clusters. May be null.
- * @param parents parent clusters. May be null.
- */
- public HierarchyReferenceLists(O owner, List<O> children, List<O> parents) {
- super();
- this.owner = owner;
- this.children = children;
- this.parents = parents;
- }
-
- @Override
- public int numChildren(O self) {
- if(owner != self) {
- throw new UnsupportedOperationException("Decentral hierarchy queried for wrong object!");
- }
- if(children == null) {
- return 0;
- }
- return children.size();
- }
-
- @Override
- public List<O> getChildren(O self) {
- if(owner != self) {
- throw new UnsupportedOperationException("Decentral hierarchy queried for wrong object!");
- }
- return children;
- }
-
- @Override
- public Iterator<O> iterDescendants(O self) {
- if(owner != self) {
- return EmptyIterator.STATIC();
- }
- if (children == null) {
- return EmptyIterator.STATIC();
- }
- return new ItrDesc(self);
- }
-
- @Override
- public int numParents(O self) {
- if(owner != self) {
- throw new UnsupportedOperationException("Decentral hierarchy queried for wrong object!");
- }
- if (parents == null) {
- return 0;
- }
- return parents.size();
- }
-
- /**
- * Return parents
- */
- @Override
- public List<O> getParents(O self) {
- if(owner != self) {
- throw new UnsupportedOperationException("Decentral hierarchy queried for wrong object!");
- }
- return parents;
- }
-
- @Override
- public Iterator<O> iterAncestors(O self) {
- if(owner != self) {
- throw new UnsupportedOperationException("Decentral hierarchy queried for wrong object!");
- }
- if (parents == null) {
- return EmptyIterator.STATIC();
- }
- return new ItrAnc(self);
- }
-
- /**
- * Iterator to collect into the descendants.
- *
- * @author Erich Schubert
- *
- * @apiviz.exclude
- */
- private class ItrDesc implements Iterator<O> {
- /**
- * Iterator over children
- */
- final Iterator<O> childiter;
-
- /**
- * Iterator of current child
- */
- Iterator<O> subiter;
-
- public ItrDesc(O start) {
- assert (start == owner);
- this.childiter = children.iterator();
- this.subiter = null;
- }
-
- @Override
- public boolean hasNext() {
- if(subiter != null && subiter.hasNext()) {
- return true;
- }
- return childiter.hasNext();
- }
-
- @Override
- public O next() {
- // Try nested iterator first ...
- if(subiter != null && subiter.hasNext()) {
- return subiter.next();
- }
- // Next direct child, update subiter.
- final O child = childiter.next();
- subiter = child.iterDescendants();
- return child;
- }
-
- @Override
- public void remove() {
- throw new UnsupportedOperationException();
- }
- }
-
- /**
- * Iterator over all Ancestors.
- *
- * @author Erich Schubert
- *
- * @apiviz.exclude
- */
- private class ItrAnc implements Iterator<O> {
- /**
- * Iterator over parents
- */
- final Iterator<O> parentiter;
-
- /**
- * Iterator of current parent
- */
- Iterator<O> subiter;
-
- public ItrAnc(O start) {
- assert (start == owner);
- this.parentiter = parents.iterator();
- this.subiter = null;
- }
-
- @Override
- public boolean hasNext() {
- if(subiter != null && subiter.hasNext()) {
- return true;
- }
- return parentiter.hasNext();
- }
-
- @Override
- public O next() {
- // Try nested iterator first ...
- if(subiter != null && subiter.hasNext()) {
- return subiter.next();
- }
- // Next direct parent, update subiter.
- final O parent = parentiter.next();
- subiter = parent.iterAncestors();
- return parent;
- }
-
- @Override
- public void remove() {
- throw new UnsupportedOperationException();
- }
- }
-} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/ModifiableHierarchy.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/ModifiableHierarchy.java
index dadc6f66..06001d6b 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/ModifiableHierarchy.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/ModifiableHierarchy.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,8 +23,6 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
-
/**
* Modifiable Hierarchy.
*
@@ -39,8 +37,14 @@ public interface ModifiableHierarchy<O> extends Hierarchy<O> {
* @param parent Parent
* @param child Child
*/
- // TODO: return true when new?
- public void add(O parent, O child);
+ void add(O parent, O child);
+
+ /**
+ * Add an entry (initializes data structures).
+ *
+ * @param entry Entry
+ */
+ void add(O entry);
/**
* Remove a parent-child relationship.
@@ -48,6 +52,20 @@ public interface ModifiableHierarchy<O> extends Hierarchy<O> {
* @param parent Parent
* @param child Child
*/
- // TODO: return true when found?
- public void remove(O parent, O child);
+ void remove(O parent, O child);
+
+ /**
+ * Remove an entry and all its parent-child relationships.
+ *
+ * @param entry Entry
+ */
+ void remove(O entry);
+
+ /**
+ * Remove an entry and it's whole subtree (unless the elements are reachable
+ * by a different path!)
+ *
+ * @param entry Entry
+ */
+ void removeSubtree(O entry);
}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/package-info.java
index 0aba31be..965b15fc 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/AbstractObjDynamicHistogram.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/AbstractObjDynamicHistogram.java
index 9d0dba0d..165c2c8b 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/AbstractObjDynamicHistogram.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/AbstractObjDynamicHistogram.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.histogram;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -127,21 +127,36 @@ public abstract class AbstractObjDynamicHistogram<T> extends AbstractObjStaticHi
// Store in cache
if (cachefill >= 0) {
if (cachefill < cacheposs.length) {
-
cacheposs[cachefill] = coord;
cachevals[cachefill] = cloneForCache(value);
- cachefill++;
+ ++cachefill;
return;
- } else {
- materialize();
- // But continue below!
}
}
- // Check if we need to resample to accomodate this bin.
- testResample(coord);
- // super class will handle histogram resizing / shifting
- T exist = get(coord);
- data[getBinNr(coord)] = aggregate(exist, value);
+ if (coord == Double.NEGATIVE_INFINITY) {
+ aggregateSpecial(value, 0);
+ } else if (coord == Double.POSITIVE_INFINITY) {
+ aggregateSpecial(value, 1);
+ } else if (Double.isNaN(coord)) {
+ aggregateSpecial(value, 2);
+ } else {
+ // super class will handle histogram resizing / shifting
+ T exist = get(coord);
+ data[getBinNr(coord)] = aggregate(exist, value);
+ }
+ }
+
+ /**
+ * Aggregate for a special value.
+ *
+ * @param value Parameter value
+ * @param bin Special bin index.
+ */
+ protected void aggregateSpecial(T value, int bin) {
+ final T exist = getSpecial(bin);
+ // Note: do not inline above accessor, as getSpecial will initialize the
+ // special variable used below!
+ special[bin] = aggregate(exist, value);
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/AbstractObjStaticHistogram.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/AbstractObjStaticHistogram.java
index c1882302..4a1649af 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/AbstractObjStaticHistogram.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/AbstractObjStaticHistogram.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.histogram;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -35,6 +35,16 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.histogram;
*/
public abstract class AbstractObjStaticHistogram<T> extends AbstractStaticHistogram implements ObjHistogram<T> {
/**
+ * Data store
+ */
+ Object[] data;
+
+ /**
+ * Special value storage: infinity, NaN
+ */
+ Object[] special = null;
+
+ /**
* Constructor.
*
* @param bins Number of bins
@@ -46,15 +56,13 @@ public abstract class AbstractObjStaticHistogram<T> extends AbstractStaticHistog
if (bins >= 0) {
// -1 will be used by FlexiHistogram to delay initialization.
data = new Object[bins];
+ for (int i = 0; i < bins; i++) {
+ data[i] = makeObject();
+ }
}
}
/**
- * Data store
- */
- Object[] data;
-
- /**
* Access the value of a bin with new data.
*
* @param coord Coordinate
@@ -62,6 +70,15 @@ public abstract class AbstractObjStaticHistogram<T> extends AbstractStaticHistog
*/
@SuppressWarnings("unchecked")
public T get(double coord) {
+ if (coord == Double.NEGATIVE_INFINITY) {
+ return getSpecial(0);
+ }
+ if (coord == Double.POSITIVE_INFINITY) {
+ return getSpecial(1);
+ }
+ if (Double.isNaN(coord)) {
+ return getSpecial(2);
+ }
int bin = getBinNr(coord);
if (bin < 0) {
if (size - bin > data.length) {
@@ -103,6 +120,19 @@ public abstract class AbstractObjStaticHistogram<T> extends AbstractStaticHistog
}
/**
+ * Ensure that we have storage for special values (infinity, NaN)
+ *
+ * @param idx Index to return.
+ */
+ @SuppressWarnings("unchecked")
+ protected T getSpecial(int idx) {
+ if (special == null) {
+ special = new Object[] { makeObject(), makeObject(), makeObject() };
+ }
+ return (T) special[idx];
+ }
+
+ /**
* Class to make a new object for the data store.
*
* @return New instance.
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/AbstractStaticHistogram.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/AbstractStaticHistogram.java
index 799ac009..3363e61e 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/AbstractStaticHistogram.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/AbstractStaticHistogram.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.histogram;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/DoubleArrayStaticHistogram.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/DoubleArrayStaticHistogram.java
index aeba3c4b..86b53d03 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/DoubleArrayStaticHistogram.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/DoubleArrayStaticHistogram.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.histogram;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/DoubleDynamicHistogram.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/DoubleDynamicHistogram.java
index 77a1f9e4..84f97dfe 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/DoubleDynamicHistogram.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/DoubleDynamicHistogram.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.histogram;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/DoubleHistogram.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/DoubleHistogram.java
index d5cee785..e4a24c95 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/DoubleHistogram.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/DoubleHistogram.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.histogram;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/DoubleStaticHistogram.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/DoubleStaticHistogram.java
index db839d10..5a634cf2 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/DoubleStaticHistogram.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/DoubleStaticHistogram.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.histogram;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/FloatDynamicHistogram.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/FloatDynamicHistogram.java
index a14ed00a..9829eaf8 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/FloatDynamicHistogram.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/FloatDynamicHistogram.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.histogram;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/FloatHistogram.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/FloatHistogram.java
index f5a65bfa..7f034152 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/FloatHistogram.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/FloatHistogram.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.histogram;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/FloatStaticHistogram.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/FloatStaticHistogram.java
index b3f41994..063bd80a 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/FloatStaticHistogram.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/FloatStaticHistogram.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.histogram;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/Histogram.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/Histogram.java
index 75be6830..8c8d9a87 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/Histogram.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/Histogram.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.histogram;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,7 +23,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.histogram;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import de.lmu.ifi.dbs.elki.utilities.iterator.ArrayIter;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.iterator.ArrayIter;
/**
* Abstract API for histograms. Without specific type information, to allow this
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/IntArrayStaticHistogram.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/IntArrayStaticHistogram.java
index 8d00604b..ff9a82aa 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/IntArrayStaticHistogram.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/IntArrayStaticHistogram.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.histogram;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/IntDynamicHistogram.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/IntDynamicHistogram.java
index 0967ebd5..b131af7d 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/IntDynamicHistogram.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/IntDynamicHistogram.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.histogram;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/IntHistogram.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/IntHistogram.java
index 9ec4ec56..9bfae100 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/IntHistogram.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/IntHistogram.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.histogram;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/IntStaticHistogram.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/IntStaticHistogram.java
index d4de36d7..7b1eed94 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/IntStaticHistogram.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/IntStaticHistogram.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.histogram;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/LongArrayStaticHistogram.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/LongArrayStaticHistogram.java
index efbf751f..e3580792 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/LongArrayStaticHistogram.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/LongArrayStaticHistogram.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.histogram;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/LongDynamicHistogram.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/LongDynamicHistogram.java
index 676a5e8f..93c4eee5 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/LongDynamicHistogram.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/LongDynamicHistogram.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.histogram;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/LongHistogram.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/LongHistogram.java
index 9be15e65..16577c38 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/LongHistogram.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/LongHistogram.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.histogram;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/LongStaticHistogram.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/LongStaticHistogram.java
index 63e15599..b270908d 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/LongStaticHistogram.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/LongStaticHistogram.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.histogram;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/MeanVarianceStaticHistogram.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/MeanVarianceStaticHistogram.java
index 2a464382..0f1ea0a3 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/MeanVarianceStaticHistogram.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/MeanVarianceStaticHistogram.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.histogram;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/ObjHistogram.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/ObjHistogram.java
index ac4d4e4b..bad4eec1 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/ObjHistogram.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/ObjHistogram.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.histogram;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/ShortDynamicHistogram.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/ShortDynamicHistogram.java
index ff94928b..a49810ee 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/ShortDynamicHistogram.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/ShortDynamicHistogram.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.histogram;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/ShortHistogram.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/ShortHistogram.java
index 699df896..0b83bc4c 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/ShortHistogram.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/ShortHistogram.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.histogram;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/ShortStaticHistogram.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/ShortStaticHistogram.java
index b2809e1e..2819d966 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/ShortStaticHistogram.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/ShortStaticHistogram.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.histogram;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/package-info.java
index 65dd6446..cee1836b 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/histogram/package-info.java
@@ -13,7 +13,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/iterator/ArrayIter.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/iterator/ArrayIter.java
index fb6601d1..7b2a96ad 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/ArrayIter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/iterator/ArrayIter.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.utilities.iterator;
+package de.lmu.ifi.dbs.elki.utilities.datastructures.iterator;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,8 +27,8 @@ package de.lmu.ifi.dbs.elki.utilities.iterator;
* Array iterators can also go backwards and seek.
*
* @author Erich Schubert
- *
- * @apiviz.landmark
+ *
+ * @apiviz.excludeSubtypes
*/
public interface ArrayIter extends Iter {
/**
@@ -37,7 +37,7 @@ public interface ArrayIter extends Iter {
* @return Iterator position
*/
public int getOffset();
-
+
/**
* Moves the iterator forward or backward by the given offset.
*
@@ -56,4 +56,4 @@ public interface ArrayIter extends Iter {
* @param off Seek offset
*/
public void seek(int off);
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/iterator/ReverseListIterator.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/iterator/ArrayListIter.java
index c207e44c..820217ec 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/ReverseListIterator.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/iterator/ArrayListIter.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.utilities.iterator;
+package de.lmu.ifi.dbs.elki.utilities.datastructures.iterator;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,83 +23,77 @@ package de.lmu.ifi.dbs.elki.utilities.iterator;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.Iterator;
import java.util.List;
-import java.util.ListIterator;
/**
- * Reverse iterator for lists.
+ * ELKI style Iterator for array lists.
+ *
+ * Note: this implementation is only efficient for lists with efficient random
+ * access and seeking (i.e. ArrayLists, but not Linked Lists!)
*
* @author Erich Schubert
*
- * @param <E> Element type
+ * @apiviz.excludeSubtypes
+ *
+ * @param <O> contained object type.
*/
-public class ReverseListIterator<E> implements Iterator<E>, ListIterator<E> {
+public class ArrayListIter<O> implements ArrayIter {
/**
- * The actual iterator
+ * The array list to iterate over.
*/
- final ListIterator<E> iter;
+ final List<O> data;
/**
- * Constructor.
- *
- * @param iter List iterator
+ * Current position.
*/
- public ReverseListIterator(ListIterator<E> iter) {
- this.iter = iter;
- }
+ int pos = 0;
/**
* Constructor.
*
- * @param list Existing list
+ * @param data Data array.
*/
- public ReverseListIterator(List<E> list) {
- this.iter = list.listIterator(list.size());
- }
-
- @Override
- public boolean hasNext() {
- return iter.hasPrevious();
+ public ArrayListIter(List<O> data) {
+ super();
+ this.data = data;
}
@Override
- public E next() {
- return iter.previous();
+ public boolean valid() {
+ return pos < data.size();
}
@Override
- public void remove() {
- iter.remove();
+ public void advance() {
+ pos++;
}
@Override
- public boolean hasPrevious() {
- return iter.hasNext();
+ public int getOffset() {
+ return pos;
}
@Override
- public E previous() {
- return iter.next();
+ public void advance(int count) {
+ pos += count;
}
@Override
- public int nextIndex() {
- return iter.previousIndex();
+ public void retract() {
+ pos--;
}
@Override
- public int previousIndex() {
- return iter.nextIndex();
+ public void seek(int off) {
+ pos = off;
}
- @Override
- public void set(E e) {
- iter.set(e);
- }
-
- @Override
- public void add(E e) {
- iter.add(e);
+ /**
+ * Get the current element.
+ *
+ * @return current element
+ */
+ public O get() {
+ return data.get(pos);
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/iterator/Iter.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/iterator/Iter.java
index 8bb1dcc6..3d111f14 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/Iter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/iterator/Iter.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.utilities.iterator;
+package de.lmu.ifi.dbs.elki.utilities.datastructures.iterator;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -54,12 +54,13 @@ package de.lmu.ifi.dbs.elki.utilities.iterator;
* @author Erich Schubert
*
* @apiviz.landmark
+ * @apiviz.excludeSubtypes
*/
public interface Iter {
/**
* Returns true if the iterator currently points to a valid object.
*
- * @return a <code>boolean</code> value
+ * @return a <code>boolean</code> value, whether the position is valid.
*/
public boolean valid();
@@ -67,4 +68,4 @@ public interface Iter {
* Moves the iterator forward to the next entry.
*/
public void advance();
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/iterator/MIter.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/iterator/MIter.java
new file mode 100644
index 00000000..14e5443d
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/iterator/MIter.java
@@ -0,0 +1,54 @@
+package de.lmu.ifi.dbs.elki.utilities.datastructures.iterator;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Modifiable iterator, that also supports removal.
+ *
+ * Usage example:
+ *
+ * <pre>
+ * {@code
+ * for (MIter iter = ids.iter(); iter.valid(); iter.advance()) {
+ * if (testSomething(iter)) {
+ * iter.remove();
+ * continue; // Iterator may point to something else
+ * }
+ * }
+ * }
+ * </pre>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.excludeSubtypes
+ */
+public interface MIter extends Iter {
+ /**
+ * Remove the object the iterator currently points to.
+ *
+ * Note that, usually, the iterator will now point to a different object, very
+ * often to the previous one (but this is not guaranteed!)
+ */
+ void remove();
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/iterator/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/iterator/package-info.java
new file mode 100644
index 00000000..d241fcc4
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/iterator/package-info.java
@@ -0,0 +1,40 @@
+/**
+ * <p>ELKI Iterator API.</p>
+ *
+ * <p>ELKI uses a custom iterator API instead of the usual {@link java.util.Iterator} classes (the "Java Collections API").
+ * The reason for this is largely efficiency. Benchmarking showed that the Java Iterator API can be quite expensive when dealing
+ * with primitive types, as {@link java.util.Iterator#next} is meant to always return an object.</p>
+ *
+ * <p>However, the benefits become more apparent when considering multi-valued iterators.
+ * For example an iterator over a k nearest neighbor set in ELKI both represents an object by its DBID,
+ * and a distance value. For double-valued distances, it can be retrieved using a primitive value getter
+ * (saving an extra object copy), and since the iterator can be used as a DBIDRef, it can also represent
+ * the current object without creating additional objects.</p>
+ *
+ * <p>While it may seem odd to depart from Java conventions such as the collections API,
+ * note that these iterators are very close to the standard C++ conventions, so nothing entirely unusual.
+ * Also the GNU trove libraries - used by ELKI in various places - use the same kind of iterators.</p>
+ */
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package de.lmu.ifi.dbs.elki.utilities.datastructures.iterator; \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/package-info.java
index ae8308af..a0d894a9 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/designpattern/Observers.java b/src/de/lmu/ifi/dbs/elki/utilities/designpattern/Observers.java
deleted file mode 100644
index dacae560..00000000
--- a/src/de/lmu/ifi/dbs/elki/utilities/designpattern/Observers.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package de.lmu.ifi.dbs.elki.utilities.designpattern;
-
-import java.util.ArrayList;
-
-/*
- This file is part of ELKI:
- Environment for Developing KDD-Applications Supported by Index-Structures
-
- Copyright (C) 2012
- Ludwig-Maximilians-Universität München
- Lehr- und Forschungseinheit für Datenbanksysteme
- ELKI Development Team
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/**
- * Class to manage the observers of an instance.
- *
- * Design note: to avoid reference cycles, this object does not keep track of
- * its owner.
- *
- * @author Erich Schubert
- *
- * @apiviz.stereotype delegate
- * @apiviz.has Observer
- */
-public class Observers<T> extends ArrayList<Observer<? super T>> {
- /**
- * Serial version
- */
- private static final long serialVersionUID = 1L;
-
- /**
- * Constructor.
- */
- public Observers() {
- super();
- }
-
- /**
- * Add an observer to the object.
- *
- * @param o Observer to add
- */
- public void addObserver(Observer<? super T> o) {
- super.add(o);
- }
-
- /**
- * Remove an observer from the object.
- *
- * @param o Observer to remove
- */
- public void removeObserver(Observer<? super T> o) {
- super.remove(o);
- }
-
- /**
- * Notify the observers of the changed object.
- *
- * @param owner Owner of the Observers list - changed instance
- */
- public void notifyObservers(T owner) {
- for(Observer<? super T> observer : this) {
- observer.update(owner);
- }
- }
-} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/designpattern/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/designpattern/package-info.java
deleted file mode 100644
index 563470af..00000000
--- a/src/de/lmu/ifi/dbs/elki/utilities/designpattern/package-info.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- * <p>Interfaces and implementations related to common "design patterns".</p>
- */
-/*
-This file is part of ELKI:
-Environment for Developing KDD-Applications Supported by Index-Structures
-
-Copyright (C) 2012
-Ludwig-Maximilians-Universität München
-Lehr- und Forschungseinheit für Datenbanksysteme
-ELKI Development Team
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-package de.lmu.ifi.dbs.elki.utilities.designpattern; \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/documentation/Description.java b/src/de/lmu/ifi/dbs/elki/utilities/documentation/Description.java
index 2769ff13..10fe40f3 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/documentation/Description.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/documentation/Description.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.documentation;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/documentation/DocumentationUtil.java b/src/de/lmu/ifi/dbs/elki/utilities/documentation/DocumentationUtil.java
index 0fa869f4..a1d649d4 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/documentation/DocumentationUtil.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/documentation/DocumentationUtil.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.documentation;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/documentation/Reference.java b/src/de/lmu/ifi/dbs/elki/utilities/documentation/Reference.java
index acb3a0aa..8d2768e2 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/documentation/Reference.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/documentation/Reference.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.documentation;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -36,7 +36,7 @@ import java.lang.annotation.Target;
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
-@Target( { ElementType.TYPE, ElementType.METHOD })
+@Target( { ElementType.TYPE, ElementType.METHOD, ElementType.FIELD })
public @interface Reference {
/**
* Publication title.
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/documentation/Restricted.java b/src/de/lmu/ifi/dbs/elki/utilities/documentation/Restricted.java
index 8daa97ab..0cb205df 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/documentation/Restricted.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/documentation/Restricted.java
@@ -10,7 +10,7 @@ import java.lang.annotation.Target;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/documentation/Title.java b/src/de/lmu/ifi/dbs/elki/utilities/documentation/Title.java
index 2a390f19..9676e8e0 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/documentation/Title.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/documentation/Title.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.documentation;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/documentation/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/documentation/package-info.java
index 70f31ace..d6f9ac3c 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/documentation/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/documentation/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVoting.java b/src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVoting.java
index a83517f0..47c46d46 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVoting.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVoting.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.ensemble;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -39,4 +39,14 @@ public interface EnsembleVoting extends Parameterizable {
* @return combined score.
*/
public double combine(double[] scores);
+
+ /**
+ * Combine scores function. Note: it is assumed that the scores are
+ * comparable.
+ *
+ * @param scores Scores to combine
+ * @param count Number of entries to use.
+ * @return combined score.
+ */
+ public double combine(double[] scores, int count);
}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingBayes.java b/src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingBayes.java
deleted file mode 100644
index 7263513b..00000000
--- a/src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingBayes.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package de.lmu.ifi.dbs.elki.utilities.ensemble;
-
-/*
- This file is part of ELKI:
- Environment for Developing KDD-Applications Supported by Index-Structures
-
- Copyright (C) 2012
- Ludwig-Maximilians-Universität München
- Lehr- und Forschungseinheit für Datenbanksysteme
- ELKI Development Team
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterEqualConstraint;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.LessConstraint;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleParameter;
-
-/**
- * Combination rule based on Bayes theorems.
- *
- * Note: this assumes that the scores are probabilistic!
- *
- * @author Erich Schubert
- */
-public class EnsembleVotingBayes implements EnsembleVoting {
- /**
- * Minimum vote to cast
- */
- private double minvote = 0.05;
-
- /**
- * Constructor.
- *
- * @param minvote Minimum vote to cast (0 to 0.5)
- */
- public EnsembleVotingBayes(double minvote) {
- this.minvote = minvote;
- }
-
- @Override
- public double combine(double[] scores) {
- double pos = 1.0;
- double neg = 1.0;
- for (double score : scores) {
- if (score < minvote) {
- score = minvote;
- } else if (score > 1.0 - minvote) {
- score = 1.0 - minvote;
- }
- pos *= score;
- neg *= (1.0 - score);
- }
- return pos / (pos + neg);
- }
-
- /**
- * Parameterization class.
- *
- * @author Erich Schubert
- *
- * @apiviz.exclude
- */
- public static class Parameterizer extends AbstractParameterizer {
- /**
- * Option ID for the minimum and maximum vote
- */
- public static final OptionID MIN_ID = new OptionID("ensemble.bayes.min", "Minimum (and maximum) vote share, in the range 0 to 0.5");
-
- /**
- * Minimum vote to cast
- */
- private double minvote = 0.05;
-
- @Override
- protected void makeOptions(Parameterization config) {
- super.makeOptions(config);
- DoubleParameter minvoteP = new DoubleParameter(MIN_ID, 0.05);
- minvoteP.addConstraint(new GreaterEqualConstraint(0.0));
- minvoteP.addConstraint(new LessConstraint(0.5));
-
- if (config.grab(minvoteP)) {
- minvote = minvoteP.getValue();
- }
- }
-
- @Override
- protected EnsembleVotingBayes makeInstance() {
- return new EnsembleVotingBayes(minvote);
- }
- }
-}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingInverseMultiplicative.java b/src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingInverseMultiplicative.java
new file mode 100644
index 00000000..2e082761
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingInverseMultiplicative.java
@@ -0,0 +1,75 @@
+package de.lmu.ifi.dbs.elki.utilities.ensemble;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Inverse multiplicative voting:
+ *
+ * {@code 1-product(1-s_i)}
+ *
+ * @author Erich Schubert
+ */
+public class EnsembleVotingInverseMultiplicative implements EnsembleVoting {
+ /**
+ * Static instance.
+ */
+ public static final EnsembleVotingInverseMultiplicative STATIC = new EnsembleVotingInverseMultiplicative();
+
+ /**
+ * Constructor.
+ */
+ public EnsembleVotingInverseMultiplicative() {
+ super();
+ }
+
+ @Override
+ public double combine(double[] scores) {
+ return combine(scores, scores.length);
+ }
+
+ @Override
+ public double combine(double[] scores, int count) {
+ double prod = 1.;
+ for (int i = 0; i < count; i++) {
+ prod *= (1 - scores[i]);
+ }
+ return 1 - prod;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected EnsembleVotingInverseMultiplicative makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingMax.java b/src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingMax.java
index b467e9f6..e179999d 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingMax.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingMax.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.ensemble;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -39,9 +39,16 @@ public class EnsembleVotingMax implements EnsembleVoting {
@Override
public double combine(double[] scores) {
- double max = Double.NEGATIVE_INFINITY;
- for (double val : scores) {
- max = Math.max(max, val);
+ return combine(scores, scores.length);
+ }
+
+ @Override
+ public double combine(double[] scores, int count) {
+ double max = scores[0];
+ for (int i = 1; i < count; i++) {
+ if (scores[i] > max) {
+ max = scores[i];
+ }
}
return max;
}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingMean.java b/src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingMean.java
index 20746927..19643782 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingMean.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingMean.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.ensemble;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -39,10 +39,15 @@ public class EnsembleVotingMean implements EnsembleVoting {
@Override
public double combine(double[] scores) {
- double sum = 0.0;
- for (double score : scores) {
- sum += score;
+ return combine(scores, scores.length);
+ }
+
+ @Override
+ public double combine(double[] scores, int count) {
+ double sum = 0.;
+ for (int i = 0; i < count; i++) {
+ sum += scores[i];
}
- return sum / scores.length;
+ return sum / count;
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingMedian.java b/src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingMedian.java
index fa1b3fa6..de137b40 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingMedian.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingMedian.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.ensemble;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -55,7 +55,12 @@ public class EnsembleVotingMedian implements EnsembleVoting {
@Override
public double combine(double[] scores) {
- return QuickSelect.quantile(scores, quantile);
+ return combine(scores, scores.length);
+ }
+
+ @Override
+ public double combine(double[] scores, int count) {
+ return QuickSelect.quantile(scores, 0, count, quantile);
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingMin.java b/src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingMin.java
index fcf5c138..b4baa4ab 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingMin.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingMin.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.ensemble;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -40,9 +40,16 @@ public class EnsembleVotingMin implements EnsembleVoting {
@Override
public double combine(double[] scores) {
- double min = Double.POSITIVE_INFINITY;
- for (double val : scores) {
- min = Math.min(min, val);
+ return combine(scores, scores.length);
+ }
+
+ @Override
+ public double combine(double[] scores, int count) {
+ double min = scores[0];
+ for (int i = 1; i < count; i++) {
+ if (scores[i] < min) {
+ min = scores[i];
+ }
}
return min;
}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingMultiplicative.java b/src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingMultiplicative.java
new file mode 100644
index 00000000..3d99b8aa
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingMultiplicative.java
@@ -0,0 +1,75 @@
+package de.lmu.ifi.dbs.elki.utilities.ensemble;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Inverse multiplicative voting:
+ *
+ * {@code product(s_i)}
+ *
+ * @author Erich Schubert
+ */
+public class EnsembleVotingMultiplicative implements EnsembleVoting {
+ /**
+ * Static instance.
+ */
+ public static final EnsembleVotingMultiplicative STATIC = new EnsembleVotingMultiplicative();
+
+ /**
+ * Constructor.
+ */
+ public EnsembleVotingMultiplicative() {
+ super();
+ }
+
+ @Override
+ public double combine(double[] scores) {
+ return combine(scores, scores.length);
+ }
+
+ @Override
+ public double combine(double[] scores, int count) {
+ double prod = 1.;
+ for (int i = 0; i < count; i++) {
+ prod *= scores[i];
+ }
+ return prod;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected EnsembleVotingMultiplicative makeInstance() {
+ return STATIC;
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingRestrictedBayes.java b/src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingRestrictedBayes.java
deleted file mode 100644
index c2edcbfd..00000000
--- a/src/de/lmu/ifi/dbs/elki/utilities/ensemble/EnsembleVotingRestrictedBayes.java
+++ /dev/null
@@ -1,127 +0,0 @@
-package de.lmu.ifi.dbs.elki.utilities.ensemble;
-
-/*
- This file is part of ELKI:
- Environment for Developing KDD-Applications Supported by Index-Structures
-
- Copyright (C) 2012
- Ludwig-Maximilians-Universität München
- Lehr- und Forschungseinheit für Datenbanksysteme
- ELKI Development Team
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterEqualConstraint;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.LessConstraint;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.LessEqualConstraint;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.LessGlobalConstraint;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleParameter;
-
-/**
- * Combination rule based on Bayes theorems.
- *
- * @author Erich Schubert
- */
-public class EnsembleVotingRestrictedBayes implements EnsembleVoting {
- /**
- * Minimum vote to cast
- */
- private double minvote = 0.05;
-
- /**
- * Maximum vote to cast
- */
- private double maxvote = 1.0;
-
- /**
- * Constructor.
- *
- * @param minvote minimum vote
- * @param maxvote maximum vote
- */
- public EnsembleVotingRestrictedBayes(double minvote, double maxvote) {
- this.minvote = minvote;
- this.maxvote = maxvote;
- }
-
- @Override
- public double combine(double[] scores) {
- double pos = 1.0;
- double neg = 1.0;
- for (double score : scores) {
- score = Math.min(minvote, Math.max(maxvote, score));
- final double cscore = score;
- pos *= cscore;
- neg *= (1.0 - cscore);
- }
- return pos / (pos + neg);
- }
-
- /**
- * Parameterization class.
- *
- * @author Erich Schubert
- *
- * @apiviz.exclude
- */
- public static class Parameterizer extends AbstractParameterizer {
- /**
- * Option ID for the minimum and maximum vote
- */
- public static final OptionID MIN_ID = new OptionID("ensemble.bayes.min", "Minimum vote share.");
-
- /**
- * Option ID for the minimum and maximum vote
- */
- public static final OptionID MAX_ID = new OptionID("ensemble.bayes.max", "Maximum vote share.");
-
- /**
- * Minimum vote to cast
- */
- private double minvote = 0.05;
-
- /**
- * Maximum vote to cast
- */
- private double maxvote = 1.0;
-
- @Override
- protected void makeOptions(Parameterization config) {
- super.makeOptions(config);
- DoubleParameter minvoteP = new DoubleParameter(MIN_ID, 0.05);
- minvoteP.addConstraint(new GreaterEqualConstraint(0.0));
- minvoteP.addConstraint(new LessConstraint(0.0));
- if (config.grab(minvoteP)) {
- minvote = minvoteP.doubleValue();
- }
- DoubleParameter maxvoteP = new DoubleParameter(MAX_ID, 0.95);
- maxvoteP.addConstraint(new GreaterConstraint(0.0));
- maxvoteP.addConstraint(new LessEqualConstraint(0.0));
- if (config.grab(maxvoteP)) {
- maxvote = maxvoteP.doubleValue();
- }
- config.checkConstraint(new LessGlobalConstraint<Double>(minvoteP, maxvoteP));
- }
-
- @Override
- protected EnsembleVotingRestrictedBayes makeInstance() {
- return new EnsembleVotingRestrictedBayes(minvote, maxvote);
- }
- }
-}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/ensemble/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/ensemble/package-info.java
index 572b40bb..76ee4ab8 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/ensemble/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/ensemble/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/exceptions/APIViolationException.java b/src/de/lmu/ifi/dbs/elki/utilities/exceptions/APIViolationException.java
index d332f2b0..ab6430f4 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/exceptions/APIViolationException.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/exceptions/APIViolationException.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.exceptions;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/exceptions/AbortException.java b/src/de/lmu/ifi/dbs/elki/utilities/exceptions/AbortException.java
index 768cb243..21179a62 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/exceptions/AbortException.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/exceptions/AbortException.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.exceptions;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/exceptions/ExceptionMessages.java b/src/de/lmu/ifi/dbs/elki/utilities/exceptions/ExceptionMessages.java
index 1b1eed80..cdaa6220 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/exceptions/ExceptionMessages.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/exceptions/ExceptionMessages.java
@@ -1,26 +1,27 @@
package de.lmu.ifi.dbs.elki.utilities.exceptions;
-/*
-This file is part of ELKI:
-Environment for Developing KDD-Applications Supported by Index-Structures
-
-Copyright (C) 2012
-Ludwig-Maximilians-Universität München
-Lehr- und Forschungseinheit für Datenbanksysteme
-ELKI Development Team
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU Affero General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
-
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
/**
* Interface to collect exception messages that are used in several cases.
@@ -32,38 +33,48 @@ public interface ExceptionMessages {
* Message when the user requested a help message.
*/
public static final String USER_REQUESTED_HELP = "Aborted: User requested help message.";
+
/**
* Messages in case a database is unexpectedly empty.
*/
public static final String DATABASE_EMPTY = "database empty: must contain elements";
+
/**
- * Message when a new label was discovered in a database, that did not exist before.
+ * Message when a new label was discovered in a database, that did not exist
+ * before.
*/
public static final String INCONSISTENT_STATE_NEW_LABEL = "inconsistent state of database - found new label";
+
/**
* Message when an empty clustering is encountered.
*/
public static final String CLUSTERING_EMPTY = "Clustering doesn't contain any cluster.";
+
/**
* Message when a distance doesn't support undefined values.
*/
public static final String UNSUPPORTED_UNDEFINED_DISTANCE = "Undefinded distance not supported!";
+
/**
* Generic "unsupported" message
*/
public static final String UNSUPPORTED = "Unsupported.";
+
/**
* Generic "not yet supported" message
*/
public static final String UNSUPPORTED_NOT_YET = "Not yet supported.";
+
/**
* "remove unsupported" message for iterators
*/
public static final String UNSUPPORTED_REMOVE = "remove() unsupported";
+
/**
* File not found. 404.
*/
public static final String FILE_NOT_FOUND = "File not found";
+
/**
* File already exists, will not overwrite.
*/
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/exceptions/NotImplementedException.java b/src/de/lmu/ifi/dbs/elki/utilities/exceptions/NotImplementedException.java
new file mode 100644
index 00000000..343a5b38
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/exceptions/NotImplementedException.java
@@ -0,0 +1,57 @@
+package de.lmu.ifi.dbs.elki.utilities.exceptions;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Exception thrown when a particular code path was not yet implemented.
+ *
+ * See {@link ExceptionMessages} for common explanations.
+ *
+ * @author Erich Schubert
+ */
+public class NotImplementedException extends AbortException {
+ /**
+ * Serial version.
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructor.
+ *
+ * @param message Error message
+ * @param cause Cause
+ */
+ public NotImplementedException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param message Error message
+ */
+ public NotImplementedException(String message) {
+ super(message);
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/exceptions/ObjectNotFoundException.java b/src/de/lmu/ifi/dbs/elki/utilities/exceptions/ObjectNotFoundException.java
index c99e5394..266ad0bb 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/exceptions/ObjectNotFoundException.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/exceptions/ObjectNotFoundException.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.exceptions;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/exceptions/UnableToComplyException.java b/src/de/lmu/ifi/dbs/elki/utilities/exceptions/UnableToComplyException.java
index 024615f8..ecb80950 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/exceptions/UnableToComplyException.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/exceptions/UnableToComplyException.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.exceptions;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/exceptions/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/exceptions/package-info.java
index f9733d18..b55fd8ee 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/exceptions/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/exceptions/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/iterator/AbstractFilteredIterator.java b/src/de/lmu/ifi/dbs/elki/utilities/iterator/AbstractFilteredIterator.java
deleted file mode 100644
index 9a729595..00000000
--- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/AbstractFilteredIterator.java
+++ /dev/null
@@ -1,120 +0,0 @@
-package de.lmu.ifi.dbs.elki.utilities.iterator;
-
-/*
- This file is part of ELKI:
- Environment for Developing KDD-Applications Supported by Index-Structures
-
- Copyright (C) 2012
- Ludwig-Maximilians-Universität München
- Lehr- und Forschungseinheit für Datenbanksysteme
- ELKI Development Team
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-import java.util.Iterator;
-
-import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
-
-/**
- * Abstract class to build filtered views on Iterables.
- *
- * @author Erich Schubert
- *
- * @apiviz.stereotype decorator
- * @apiviz.composedOf Iterator
- *
- * @param <IN> Input type
- * @param <OUT> Output type
- */
-public abstract class AbstractFilteredIterator<IN, OUT extends IN> implements Iterator<OUT> {
- /**
- * The iterator to use.
- */
- Iterator<IN> itr = null;
-
- /**
- * The next object to return.
- */
- OUT nextobj = null;
-
- /**
- * Constructor.
- */
- public AbstractFilteredIterator() {
- super();
- }
-
- /**
- * Init the iterators.
- */
- protected void init() {
- this.itr = getParentIterator();
- if (this.itr == null) {
- throw new AbortException("Filtered iterator has 'null' parent.");
- }
- }
-
- /**
- * Get an iterator for the actual data. Used in initialization.
- *
- * @return iterator
- */
- protected abstract Iterator<IN> getParentIterator();
-
- /**
- * Test the filter predicate for a new object.
- *
- * @param nextobj Object to test
- * @return cast object when true, {@code null} otherwise
- */
- protected abstract OUT testFilter(IN nextobj);
-
- /**
- * Find the next visualizer.
- */
- private void updateNext() {
- if(itr == null) {
- init();
- }
- nextobj = null;
- while(itr.hasNext()) {
- IN v = itr.next();
- nextobj = testFilter(v);
- if(nextobj != null) {
- break;
- }
- }
- }
-
- @Override
- public boolean hasNext() {
- if(itr == null) {
- updateNext();
- }
- return (nextobj != null);
- }
-
- @Override
- public OUT next() {
- OUT ret = this.nextobj;
- updateNext();
- return ret;
- }
-
- @Override
- public void remove() {
- throw new UnsupportedOperationException();
- }
-} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/iterator/MergedIterator.java b/src/de/lmu/ifi/dbs/elki/utilities/iterator/MergedIterator.java
deleted file mode 100644
index b5d2fd02..00000000
--- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/MergedIterator.java
+++ /dev/null
@@ -1,115 +0,0 @@
-package de.lmu.ifi.dbs.elki.utilities.iterator;
-
-/*
- This file is part of ELKI:
- Environment for Developing KDD-Applications Supported by Index-Structures
-
- Copyright (C) 2012
- Ludwig-Maximilians-Universität München
- Lehr- und Forschungseinheit für Datenbanksysteme
- ELKI Development Team
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Iterator;
-
-/**
- * Iterator that joins multiple existing iterators into one.
- *
- * @author Erich Schubert
- *
- * @apiviz.stereotype adapter
- * @apiviz.uses Iterator oneway
- *
- * @param <E> Entry type
- */
-public class MergedIterator<E> implements Iterator<E> {
- /**
- * All the iterators we process
- */
- final Iterator<Iterator<E>> iterators;
-
- /**
- * The iterator we are currently processing
- */
- Iterator<E> current = null;
-
- /**
- * The last iterator we returned an object for, for remove()
- */
- Iterator<E> last = null;
-
- /**
- * Main constructor.
- *
- * @param iterators Iterators
- */
- public MergedIterator(Iterator<Iterator<E>> iterators) {
- super();
- this.iterators = iterators;
- }
-
- /**
- * Auxillary constructor with Collections
- *
- * @param iterators Iterators
- */
- public MergedIterator(Collection<Iterator<E>> iterators) {
- this(iterators.iterator());
- }
-
- /**
- * Auxillary constructor with arrays
- *
- * @param iterators Iterators
- */
- public MergedIterator(Iterator<E>... iterators) {
- this(Arrays.asList(iterators).iterator());
- }
-
- @Override
- public boolean hasNext() {
- do {
- if(current != null && current.hasNext()) {
- return true;
- }
- if(!iterators.hasNext()) {
- return false;
- }
- // advance master iterator and retry
- current = iterators.next();
- }
- while(true);
- }
-
- @Override
- public E next() {
- while(!current.hasNext()) {
- current = iterators.next();
- }
- last = current;
- return current.next();
- }
-
- @Override
- public void remove() {
- if(last == null) {
- throw new RuntimeException("Iterator.remove() called without next()");
- }
- last.remove();
- }
-} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/iterator/TypeFilterIterator.java b/src/de/lmu/ifi/dbs/elki/utilities/iterator/TypeFilterIterator.java
deleted file mode 100644
index 5aa908c8..00000000
--- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/TypeFilterIterator.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package de.lmu.ifi.dbs.elki.utilities.iterator;
-
-/*
- This file is part of ELKI:
- Environment for Developing KDD-Applications Supported by Index-Structures
-
- Copyright (C) 2012
- Ludwig-Maximilians-Universität München
- Lehr- und Forschungseinheit für Datenbanksysteme
- ELKI Development Team
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-import java.util.Iterator;
-
-/**
- * Iterator that filters results by type.
- *
- * @author Erich Schubert
- *
- * @param <IN> Input datatype
- * @param <OUT> Output datatype
- */
-public class TypeFilterIterator<IN, OUT extends IN> extends AbstractFilteredIterator<IN, OUT> implements Iterator<OUT> {
- /**
- * Class restriction
- */
- private Class<? super OUT> filterClass;
-
- /**
- * Parent iterator
- */
- private Iterator<IN> parent;
-
- /**
- * Constructor.
- *
- * @param filterClass Filter
- * @param parent Parent collection
- */
- public TypeFilterIterator(Class<? super OUT> filterClass, Iterable<IN> parent) {
- super();
- this.filterClass = filterClass;
- this.parent = parent.iterator();
- }
-
- /**
- * Constructor.
- *
- * @param filterClass Filter
- * @param parent Parent iterator
- */
- public TypeFilterIterator(Class<? super OUT> filterClass, Iterator<IN> parent) {
- super();
- this.filterClass = filterClass;
- this.parent = parent;
- }
-
- @Override
- protected Iterator<IN> getParentIterator() {
- return parent;
- }
-
- @SuppressWarnings("unchecked")
- @Override
- protected OUT testFilter(IN nextobj) {
- try {
- return (OUT) filterClass.cast(nextobj);
- }
- catch(ClassCastException e) {
- return null;
- }
- }
-} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/iterator/UnmodifiableListIterator.java b/src/de/lmu/ifi/dbs/elki/utilities/iterator/UnmodifiableListIterator.java
deleted file mode 100644
index 7b9c9d79..00000000
--- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/UnmodifiableListIterator.java
+++ /dev/null
@@ -1,98 +0,0 @@
-package de.lmu.ifi.dbs.elki.utilities.iterator;
-
-/*
- This file is part of ELKI:
- Environment for Developing KDD-Applications Supported by Index-Structures
-
- Copyright (C) 2012
- Ludwig-Maximilians-Universität München
- Lehr- und Forschungseinheit für Datenbanksysteme
- ELKI Development Team
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-import java.util.ListIterator;
-
-/**
- * Iterator proxy that does not allow modifications.
- *
- * @author Erich Schubert
- *
- * @apiviz.stereotype decorator
- * @apiviz.composedOf ListIterator oneway - - decorates
- *
- * @param <T>
- */
-public final class UnmodifiableListIterator<T> implements ListIterator<T> {
- /**
- * Real iterator
- */
- private ListIterator<T> inner;
-
- /**
- * Constructor.
- *
- * @param inner Real iterator to proxy.
- */
- public UnmodifiableListIterator(ListIterator<T> inner) {
- super();
- this.inner = inner;
- }
-
- @Override
- public boolean hasNext() {
- return inner.hasNext();
- }
-
- @Override
- public T next() {
- return inner.next();
- }
-
- @Override
- public boolean hasPrevious() {
- return inner.hasPrevious();
- }
-
- @Override
- public T previous() {
- return inner.previous();
- }
-
- @Override
- public int nextIndex() {
- return inner.nextIndex();
- }
-
- @Override
- public int previousIndex() {
- return inner.previousIndex();
- }
-
- @Override
- public void remove() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void add(T e) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void set(T e) {
- throw new UnsupportedOperationException();
- }
-} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/AbstractParameterizer.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/AbstractParameterizer.java
index 0a094ced..6aa22964 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/AbstractParameterizer.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/AbstractParameterizer.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/InternalParameterizationErrors.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/InternalParameterizationErrors.java
index c8797c73..1cff200a 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/InternalParameterizationErrors.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/InternalParameterizationErrors.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -63,7 +63,7 @@ public class InternalParameterizationErrors extends ParameterException {
*/
public InternalParameterizationErrors(String message, Exception internalError) {
super(message);
- final ArrayList<Exception> errors = new ArrayList<Exception>(1);
+ final ArrayList<Exception> errors = new ArrayList<>(1);
errors.add(internalError);
this.internalErrors = errors;
}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/NoParameterValueException.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/NoParameterValueException.java
index ce422de7..53d992ff 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/NoParameterValueException.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/NoParameterValueException.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/OptionID.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/OptionID.java
index 2c9814e3..60e51a98 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/OptionID.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/OptionID.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -32,85 +32,6 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling;
*/
public final class OptionID {
/**
- * Flag to obtain help-message.
- * <p>
- * Key: {@code -h}
- * </p>
- */
- public static final OptionID HELP = new OptionID("h", "Request a help-message, either for the main-routine or for any specified algorithm. " + "Causes immediate stop of the program.");
-
- /**
- * Flag to obtain help-message.
- * <p>
- * Key: {@code -help}
- * </p>
- */
- public static final OptionID HELP_LONG = new OptionID("help", "Request a help-message, either for the main-routine or for any specified algorithm. " + "Causes immediate stop of the program.");
-
- /**
- * OptionID for {@link de.lmu.ifi.dbs.elki.workflow.AlgorithmStep}
- */
- public static final OptionID ALGORITHM = new OptionID("algorithm", "Algorithm to run.");
-
- /**
- * Optional Parameter to specify a class to obtain a description for.
- * <p>
- * Key: {@code -description}
- * </p>
- */
- public static final OptionID DESCRIPTION = new OptionID("description", "Class to obtain a description of. " + "Causes immediate stop of the program.");
-
- /**
- * Optional Parameter to specify a class to enable debugging for.
- * <p>
- * Key: {@code -enableDebug}
- * </p>
- */
- public static final OptionID DEBUG = new OptionID("enableDebug", "Parameter to enable debugging for particular packages.");
-
- /**
- * OptionID for {@link de.lmu.ifi.dbs.elki.workflow.InputStep}
- */
- public static final OptionID DATABASE = new OptionID("db", "Database class.");
-
- /**
- * OptionID for {@link de.lmu.ifi.dbs.elki.workflow.InputStep}
- */
- // TODO: move to database class?
- public static final OptionID DATABASE_CONNECTION = new OptionID("dbc", "Database connection class.");
-
- /**
- * OptionID for {@link de.lmu.ifi.dbs.elki.workflow.EvaluationStep}
- */
- public static final OptionID EVALUATOR = new OptionID("evaluator", "Class to evaluate the results with.");
-
- /**
- * OptionID for {@link de.lmu.ifi.dbs.elki.workflow.OutputStep}
- */
- public static final OptionID RESULT_HANDLER = new OptionID("resulthandler", "Result handler class.");
-
- /**
- * OptionID for the application output file/folder
- */
- public static final OptionID OUTPUT = new OptionID("out", "Directory name (or name of an existing file) to write the obtained results in. " + "If this parameter is omitted, per default the output will sequentially be given to STDOUT.");
-
- /**
- * Flag to allow verbose messages while running the application.
- * <p>
- * Key: {@code -verbose}
- * </p>
- */
- public static final OptionID VERBOSE_FLAG = new OptionID("verbose", "Enable verbose messages.");
-
- /**
- * Flag to allow verbose messages while running the application.
- * <p>
- * Key: {@code -time}
- * </p>
- */
- public static final OptionID TIME_FLAG = new OptionID("time", "Enable logging of runtime data. Do not combine with more verbose logging, since verbose logging can significantly impact performance.");
-
- /**
* Option name
*/
private String name;
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/OptionUtil.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/OptionUtil.java
index 76ae9feb..ea28aa42 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/OptionUtil.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/OptionUtil.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/ParameterException.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/ParameterException.java
index 0235b4a9..326335fd 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/ParameterException.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/ParameterException.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/Parameterizable.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/Parameterizable.java
index 13f202dd..ead565b1 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/Parameterizable.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/Parameterizable.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,8 +23,6 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import de.lmu.ifi.dbs.elki.utilities.InspectionUtilFrequentlyScanned;
-
/**
* Interface to define the required methods for command line interaction.
*
@@ -96,7 +94,7 @@ import de.lmu.ifi.dbs.elki.utilities.InspectionUtilFrequentlyScanned;
* @apiviz.uses de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization
* .Parameterization oneway
*/
-public interface Parameterizable extends InspectionUtilFrequentlyScanned {
+public interface Parameterizable {
// Empty marker interface - the \@Description / \@Title / \@Reference and
// constructor requirements cannot be specified in Java!
}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/Parameterizer.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/Parameterizer.java
index aa5c74bd..7e3a848c 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/Parameterizer.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/Parameterizer.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/UnspecifiedParameterException.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/UnspecifiedParameterException.java
index ab138704..31af6d87 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/UnspecifiedParameterException.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/UnspecifiedParameterException.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/UnusedParameterException.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/UnusedParameterException.java
index 0914c0f1..d5dbd4b2 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/UnusedParameterException.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/UnusedParameterException.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/WrongParameterValueException.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/WrongParameterValueException.java
index c51eae0e..eeb6a9e7 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/WrongParameterValueException.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/WrongParameterValueException.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/AbstractNumberConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/AbstractNumberConstraint.java
index f622aba5..fc4a673e 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/AbstractNumberConstraint.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/AbstractNumberConstraint.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/AllOrNoneMustBeSetGlobalConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/AllOrNoneMustBeSetGlobalConstraint.java
index c2448ba5..a06a06c1 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/AllOrNoneMustBeSetGlobalConstraint.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/AllOrNoneMustBeSetGlobalConstraint.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -60,8 +60,8 @@ public class AllOrNoneMustBeSetGlobalConstraint implements GlobalParameterConstr
@Override
public void test() throws ParameterException {
- ArrayList<String> set = new ArrayList<String>();
- ArrayList<String> notSet = new ArrayList<String>();
+ ArrayList<String> set = new ArrayList<>();
+ ArrayList<String> notSet = new ArrayList<>();
for(Parameter<?> p : parameterList) {
if(p.isDefined()) {
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/EqualSizeGlobalConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/EqualSizeGlobalConstraint.java
index 22d1ceb2..2ee7be9c 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/EqualSizeGlobalConstraint.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/EqualSizeGlobalConstraint.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/EqualStringConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/EqualStringConstraint.java
index 4c4a8de3..1ab35cc1 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/EqualStringConstraint.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/EqualStringConstraint.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GlobalListSizeConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GlobalListSizeConstraint.java
index 1bad7d00..bcedd342 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GlobalListSizeConstraint.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GlobalListSizeConstraint.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GlobalParameterConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GlobalParameterConstraint.java
index b59c9493..5e38b2b7 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GlobalParameterConstraint.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GlobalParameterConstraint.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GlobalVectorListElementSizeConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GlobalVectorListElementSizeConstraint.java
index 6bc9fd2d..01c99d42 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GlobalVectorListElementSizeConstraint.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GlobalVectorListElementSizeConstraint.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GreaterConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GreaterConstraint.java
index 17a9a54d..33c73fb8 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GreaterConstraint.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GreaterConstraint.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GreaterEqualConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GreaterEqualConstraint.java
index 7eb0de83..d05235c1 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GreaterEqualConstraint.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/GreaterEqualConstraint.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/IntervalConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/IntervalConstraint.java
index db6a1ed8..00c2f5ad 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/IntervalConstraint.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/IntervalConstraint.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessConstraint.java
index a8369304..5c4d0635 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessConstraint.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessConstraint.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessEqualConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessEqualConstraint.java
index e35381b3..d81c821b 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessEqualConstraint.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessEqualConstraint.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessEqualGlobalConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessEqualGlobalConstraint.java
index 9855b96d..1216e03b 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessEqualGlobalConstraint.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessEqualGlobalConstraint.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessGlobalConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessGlobalConstraint.java
index e475e92f..a722edab 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessGlobalConstraint.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/LessGlobalConstraint.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ListEachConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ListEachConstraint.java
index 7dab4006..918c59f5 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ListEachConstraint.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ListEachConstraint.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -46,7 +46,7 @@ public class ListEachConstraint<T> implements ParameterConstraint<List<T>> {
*/
public ListEachConstraint() {
super();
- this.constraints = new ArrayList<ParameterConstraint<? super T>>();
+ this.constraints = new ArrayList<>();
}
/**
@@ -56,7 +56,7 @@ public class ListEachConstraint<T> implements ParameterConstraint<List<T>> {
*/
public ListEachConstraint(ParameterConstraint<? super T> constraint) {
super();
- this.constraints = new ArrayList<ParameterConstraint<? super T>>(1);
+ this.constraints = new ArrayList<>(1);
this.constraints.add(constraint);
}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ListParameterNoDuplicateValueConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ListParameterNoDuplicateValueConstraint.java
index 6545cc9d..1ff23f80 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ListParameterNoDuplicateValueConstraint.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ListParameterNoDuplicateValueConstraint.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -57,7 +57,7 @@ public class ListParameterNoDuplicateValueConstraint<T extends Object> implement
*/
@Override
public void test(List<T> list) throws ParameterException {
- Set<T> values = new HashSet<T>();
+ Set<T> values = new HashSet<>();
for(T pv : list) {
if(!values.add(pv)) {
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ListSizeConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ListSizeConstraint.java
index 82b3ae7e..95b5214b 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ListSizeConstraint.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ListSizeConstraint.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/NoDuplicateValueGlobalConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/NoDuplicateValueGlobalConstraint.java
index 39ab2680..65b427a1 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/NoDuplicateValueGlobalConstraint.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/NoDuplicateValueGlobalConstraint.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -76,7 +76,7 @@ public class NoDuplicateValueGlobalConstraint implements GlobalParameterConstrai
*/
@Override
public void test() throws ParameterException {
- Set<Object> numbers = new HashSet<Object>();
+ Set<Object> numbers = new HashSet<>();
for(Parameter<?> param : parameters) {
if(param.isDefined()) {
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/OneMustBeSetGlobalConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/OneMustBeSetGlobalConstraint.java
index c0109ac5..e7802685 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/OneMustBeSetGlobalConstraint.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/OneMustBeSetGlobalConstraint.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,6 +23,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import java.util.Arrays;
import java.util.List;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionUtil;
@@ -54,6 +55,16 @@ public class OneMustBeSetGlobalConstraint implements GlobalParameterConstraint {
}
/**
+ * Creates a One-Must-Be-Set global parameter constraint. That is, at least
+ * one parameter value of the given list of parameters has to be set.
+ *
+ * @param params list of parameters
+ */
+ public OneMustBeSetGlobalConstraint(Parameter<?>... params) {
+ parameters = Arrays.asList(params);
+ }
+
+ /**
* Checks if at least one parameter value of the list of parameters specified
* is set. If not, a parameter exception is thrown.
*
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/OnlyOneIsAllowedToBeSetGlobalConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/OnlyOneIsAllowedToBeSetGlobalConstraint.java
index 22db8511..bdd55572 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/OnlyOneIsAllowedToBeSetGlobalConstraint.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/OnlyOneIsAllowedToBeSetGlobalConstraint.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,6 +24,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints;
*/
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionUtil;
@@ -55,17 +56,27 @@ public class OnlyOneIsAllowedToBeSetGlobalConstraint implements GlobalParameterC
}
/**
+ * Constructs a global parameter constraint for testing if only one parameter
+ * of a list of parameters is set.
+ *
+ * @param params list of parameters to be checked
+ */
+ public OnlyOneIsAllowedToBeSetGlobalConstraint(Parameter<?>... params) {
+ parameters = Arrays.asList(params);
+ }
+
+ /**
* Checks if only one parameter of a list of parameters is set. If not, a
* parameter exception is thrown.
*/
@Override
public void test() throws ParameterException {
- ArrayList<String> set = new ArrayList<String>();
- for(Parameter<?> p : parameters) {
- if(p.isDefined()) {
+ ArrayList<String> set = new ArrayList<>();
+ for (Parameter<?> p : parameters) {
+ if (p.isDefined()) {
// FIXME: Retire the use of this constraint for Flags!
- if(p instanceof Flag) {
- if (((Flag)p).getValue().booleanValue()) {
+ if (p instanceof Flag) {
+ if (((Flag) p).getValue().booleanValue()) {
set.add(p.getName());
}
} else {
@@ -73,7 +84,7 @@ public class OnlyOneIsAllowedToBeSetGlobalConstraint implements GlobalParameterC
}
}
}
- if(set.size() > 1) {
+ if (set.size() > 1) {
throw new WrongParameterValueException("Global Parameter Constraint Error.\n" + "Only one of the parameters " + OptionUtil.optionsNamesToString(parameters) + " is allowed to be set. " + "Parameters currently set: " + set.toString());
}
}
@@ -82,4 +93,4 @@ public class OnlyOneIsAllowedToBeSetGlobalConstraint implements GlobalParameterC
public String getDescription() {
return "Only one of the parameters " + OptionUtil.optionsNamesToString(parameters) + " is allowed to be set.";
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ParameterConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ParameterConstraint.java
index ff66ec05..2847260a 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ParameterConstraint.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ParameterConstraint.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ParameterFlagGlobalConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ParameterFlagGlobalConstraint.java
index ff2e6675..ab77240a 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ParameterFlagGlobalConstraint.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ParameterFlagGlobalConstraint.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -49,7 +49,7 @@ public class ParameterFlagGlobalConstraint<S> implements GlobalParameterConstrai
/**
* Parameter possibly to be checked.
*/
- private Parameter<S> param;
+ private Parameter<? extends S> param;
/**
* Flag the checking of the parameter constraints is dependent on.
@@ -64,7 +64,7 @@ public class ParameterFlagGlobalConstraint<S> implements GlobalParameterConstrai
/**
* List of parameter constraints.
*/
- private List<ParameterConstraint<? super S>> cons;
+ private List<? extends ParameterConstraint<? super S>> cons;
/**
* Constructs a global parameter constraint specifying that the testing of the
@@ -78,7 +78,7 @@ public class ParameterFlagGlobalConstraint<S> implements GlobalParameterConstrai
* @param flagConstraint indicates at which status of the flag the parameter
* is to be checked
*/
- public ParameterFlagGlobalConstraint(Parameter<S> p, List<ParameterConstraint<? super S>> c, Flag f, boolean flagConstraint) {
+ public ParameterFlagGlobalConstraint(Parameter<? extends S> p, List<? extends ParameterConstraint<? super S>> c, Flag f, boolean flagConstraint) {
param = p;
flag = f;
this.flagConstraint = flagConstraint;
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/StringLengthConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/StringLengthConstraint.java
index 84d8fa6d..ff42a21f 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/StringLengthConstraint.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/StringLengthConstraint.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/package-info.java
index 4b8c163a..e05ca2fa 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/package-info.java
index 593c11d2..e4c5489b 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/package-info.java
@@ -253,7 +253,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/AbstractParameterization.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/AbstractParameterization.java
index 7cc0055e..75a5be86 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/AbstractParameterization.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/AbstractParameterization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -46,7 +46,7 @@ public abstract class AbstractParameterization implements Parameterization {
/**
* Errors
*/
- List<ParameterException> errors = new ArrayList<ParameterException>();
+ List<ParameterException> errors = new ArrayList<>();
/**
* The logger of the class.
@@ -89,7 +89,7 @@ public abstract class AbstractParameterization implements Parameterization {
public synchronized void clearErrors() {
// Do NOT use errors.clear(), since we might have an error report
// referencing the collection!
- errors = new ArrayList<ParameterException>();
+ errors = new ArrayList<>();
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/ChainedParameterization.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/ChainedParameterization.java
index a2fd168e..97cdb51f 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/ChainedParameterization.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/ChainedParameterization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -44,7 +44,7 @@ public class ChainedParameterization extends AbstractParameterization {
/**
* Keep the list of parameterizations.
*/
- private List<Parameterization> chain = new ArrayList<Parameterization>();
+ private List<Parameterization> chain = new ArrayList<>();
/**
* Error target
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/EmptyParameterization.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/EmptyParameterization.java
index 3391ff4a..02802593 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/EmptyParameterization.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/EmptyParameterization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/ListParameterization.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/ListParameterization.java
index 7d728280..b870b57b 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/ListParameterization.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/ListParameterization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -44,7 +44,7 @@ public class ListParameterization extends AbstractParameterization {
/**
* The actual parameters, for storage
*/
- LinkedList<Pair<OptionID, Object>> parameters = new LinkedList<Pair<OptionID, Object>>();
+ LinkedList<Pair<OptionID, Object>> parameters = new LinkedList<>();
/**
* Default constructor.
@@ -52,7 +52,7 @@ public class ListParameterization extends AbstractParameterization {
public ListParameterization() {
super();
}
-
+
/**
* Constructor with an existing collection.
*
@@ -81,9 +81,9 @@ public class ListParameterization extends AbstractParameterization {
* @param value Value
*/
public void addParameter(OptionID optionid, Object value) {
- parameters.add(new Pair<OptionID, Object>(optionid, value));
+ parameters.add(new Pair<>(optionid, value));
}
-
+
/**
* Convenience - add a Flag option directly.
*
@@ -94,7 +94,7 @@ public class ListParameterization extends AbstractParameterization {
addFlag(flag.getOptionID());
}
}
-
+
/**
* Convenience - add a Parameter for forwarding
*
@@ -107,11 +107,11 @@ public class ListParameterization extends AbstractParameterization {
}
@Override
- public boolean setValueForOption(Parameter<?> opt) throws ParameterException {
+ public boolean setValueForOption(Parameter<?> opt) throws ParameterException {
Iterator<Pair<OptionID, Object>> iter = parameters.iterator();
- while(iter.hasNext()) {
+ while (iter.hasNext()) {
Pair<OptionID, Object> pair = iter.next();
- if(pair.first == opt.getOptionID()) {
+ if (pair.first == opt.getOptionID()) {
iter.remove();
opt.setValue(pair.second);
return true;
@@ -134,8 +134,8 @@ public class ListParameterization extends AbstractParameterization {
return (parameters.size() > 0);
}
- /** {@inheritDoc}
- * Default implementation, for flat parameterizations.
+ /**
+ * {@inheritDoc} Default implementation, for flat parameterizations.
*/
@Override
public Parameterization descend(Object option) {
@@ -158,11 +158,17 @@ public class ListParameterization extends AbstractParameterization {
* @return Array list of parameters
*/
public ArrayList<String> serialize() {
- ArrayList<String> params = new ArrayList<String>();
+ ArrayList<String> params = new ArrayList<>();
for (Pair<OptionID, Object> pair : parameters) {
params.add("-" + pair.getFirst().toString());
- params.add(pair.getSecond().toString());
+ if (pair.getSecond() instanceof String) {
+ params.add((String) pair.getSecond());
+ } else if (pair.getSecond() instanceof Class) {
+ params.add(((Class<?>) pair.getSecond()).getCanonicalName());
+ } else { // Fallback:
+ params.add(pair.getSecond().toString());
+ }
}
return params;
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/MergedParameterization.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/MergedParameterization.java
index 580a3371..9f765963 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/MergedParameterization.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/MergedParameterization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -69,7 +69,7 @@ public class MergedParameterization implements Parameterization {
super();
this.inner = child;
this.current = new ListParameterization();
- this.used = new ArrayList<Pair<OptionID, Object>>();
+ this.used = new ArrayList<>();
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/Parameterization.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/Parameterization.java
index 5cdff013..01c46583 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/Parameterization.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/Parameterization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/SerializedParameterization.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/SerializedParameterization.java
index b88b7dc4..b3e3f214 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/SerializedParameterization.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/SerializedParameterization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -59,7 +59,7 @@ public class SerializedParameterization extends AbstractParameterization {
*/
public SerializedParameterization() {
super();
- parameters = new LinkedList<String>();
+ parameters = new LinkedList<>();
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/TrackParameters.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/TrackParameters.java
index 424f54ee..5a20bd9e 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/TrackParameters.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/TrackParameters.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -54,18 +54,18 @@ public class TrackParameters implements Parameterization {
/**
* Tracking storage
*/
- List<Pair<Object, Parameter<?>>> options = new ArrayList<Pair<Object, Parameter<?>>>();
+ List<Pair<Object, Parameter<?>>> options = new ArrayList<>();
/**
* Tree information: parent links
*/
- Map<Object, Object> parents = new HashMap<Object, Object>();
+ Map<Object, Object> parents = new HashMap<>();
/**
* Tree information: child links
*/
// Implementation note: we need the map to support "null" keys!
- Map<Object, List<Object>> children = new HashMap<Object, List<Object>>();
+ Map<Object, List<Object>> children = new HashMap<>();
/**
* Current parent for nested parameterization
@@ -149,10 +149,10 @@ public class TrackParameters implements Parameterization {
* @return Parameters given
*/
public Collection<Pair<OptionID, Object>> getGivenParameters() {
- ArrayList<Pair<OptionID, Object>> ret = new ArrayList<Pair<OptionID, Object>>();
+ ArrayList<Pair<OptionID, Object>> ret = new ArrayList<>();
for(Pair<Object, Parameter<?>> pair : options) {
if(pair.second.isDefined() && pair.second.getGivenValue() != null) {
- ret.add(new Pair<OptionID, Object>(pair.second.getOptionID(), pair.second.getGivenValue()));
+ ret.add(new Pair<>(pair.second.getOptionID(), pair.second.getGivenValue()));
}
}
return ret;
@@ -180,7 +180,7 @@ public class TrackParameters implements Parameterization {
parents.put(opt, cur);
List<Object> c = children.get(cur);
if(c == null) {
- c = new ArrayList<Object>();
+ c = new ArrayList<>();
children.put(cur, c);
}
if(!c.contains(opt)) {
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/UnParameterization.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/UnParameterization.java
index a04b3217..2a05a766 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/UnParameterization.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/UnParameterization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -45,7 +45,7 @@ public class UnParameterization implements Parameterization {
/**
* Errors
*/
- List<ParameterException> errors = new ArrayList<ParameterException>();
+ List<ParameterException> errors = new ArrayList<>();
@Override
public boolean hasUnusedParameters() {
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/package-info.java
index 41856ad7..ce9c89b4 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/package-info.java
@@ -8,7 +8,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/AbstractParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/AbstractParameter.java
index ce4b094d..8e1b48c3 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/AbstractParameter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/AbstractParameter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -334,7 +334,7 @@ public abstract class AbstractParameter<T> implements Parameter<T> {
@Override
public void addConstraint(ParameterConstraint<? super T> constraint) {
if (constraints == null) {
- this.constraints = new ArrayList<ParameterConstraint<? super T>>(1);
+ this.constraints = new ArrayList<>(1);
}
constraints.add(constraint);
}
@@ -346,7 +346,7 @@ public abstract class AbstractParameter<T> implements Parameter<T> {
*/
public void addConstraints(Collection<? extends ParameterConstraint<? super T>> cs) {
if (constraints == null) {
- this.constraints = new ArrayList<ParameterConstraint<? super T>>(cs.size());
+ this.constraints = new ArrayList<>(cs.size());
}
constraints.addAll(cs);
}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ClassListParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ClassListParameter.java
index f87e3973..35cd0573 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ClassListParameter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ClassListParameter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -48,11 +48,6 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameteriz
// TODO: Add missing constructors. (ObjectListParameter also!)
public class ClassListParameter<C> extends ListParameter<Class<? extends C>> {
/**
- * Class loader
- */
- protected static final ClassLoader loader = ClassLoader.getSystemClassLoader();
-
- /**
* The restriction class for the list of class names.
*/
protected Class<C> restrictionClass;
@@ -88,12 +83,12 @@ public class ClassListParameter<C> extends ListParameter<Class<? extends C>> {
public String getValueAsString() {
StringBuilder buf = new StringBuilder();
final String defPackage = restrictionClass.getPackage().getName() + ".";
- for(Class<? extends C> c : getValue()) {
- if(buf.length() > 0) {
+ for (Class<? extends C> c : getValue()) {
+ if (buf.length() > 0) {
buf.append(LIST_SEP);
}
String name = c.getName();
- if(name.startsWith(defPackage)) {
+ if (name.startsWith(defPackage)) {
name = name.substring(defPackage.length());
}
buf.append(name);
@@ -107,57 +102,41 @@ public class ClassListParameter<C> extends ListParameter<Class<? extends C>> {
try {
List<?> l = List.class.cast(obj);
// do extra validation:
- for(Object o : l) {
- if(!(o instanceof Class)) {
+ for (Object o : l) {
+ if (!(o instanceof Class)) {
throw new WrongParameterValueException("Wrong parameter format for parameter \"" + getName() + "\". Given list contains objects of different type!");
}
}
// TODO: can we use reflection to get extra checks?
// TODO: Should we copy the list?
return (List<Class<? extends C>>) l;
- }
- catch(ClassCastException e) {
+ } catch (ClassCastException e) {
// continue with others
}
// Did we get a single class?
try {
- if(restrictionClass.isAssignableFrom((Class<?>) obj)) {
- List<Class<? extends C>> clss = new ArrayList<Class<? extends C>>(1);
+ if (restrictionClass.isAssignableFrom((Class<?>) obj)) {
+ List<Class<? extends C>> clss = new ArrayList<>(1);
clss.add((Class<? extends C>) obj);
return clss;
}
- }
- catch(ClassCastException e) {
+ } catch (ClassCastException e) {
// continue with others
}
- if(obj instanceof String) {
+ if (obj instanceof String) {
String[] classes = SPLIT.split((String) obj);
// TODO: allow empty lists (and list constraints) to enforce length?
- if(classes.length == 0) {
+ if (classes.length == 0) {
throw new WrongParameterValueException("Wrong parameter format! Given list of classes for parameter \"" + getName() + "\" is either empty or has the wrong format!");
}
- List<Class<? extends C>> cls = new ArrayList<Class<? extends C>>(classes.length);
- for(String cl : classes) {
- try {
- Class<?> c;
- try {
- c = loader.loadClass(cl);
- }
- catch(ClassNotFoundException e) {
- // try in package of restriction class
- c = loader.loadClass(restrictionClass.getPackage().getName() + "." + cl);
- }
- // Redundant check, also in validate(), but not expensive.
- if(!restrictionClass.isAssignableFrom(c)) {
- throw new WrongParameterValueException(this, cl, "Class \"" + cl + "\" does not extend/implement restriction class " + restrictionClass + ".\n");
- }
- else {
- cls.add((Class<? extends C>) c);
- }
- }
- catch(ClassNotFoundException e) {
- throw new WrongParameterValueException(this, cl, "Class \"" + cl + "\" not found.\n", e);
+ List<Class<? extends C>> cls = new ArrayList<>(classes.length);
+ for (String cl : classes) {
+ Class<? extends C> clz = InspectionUtil.findImplementation(restrictionClass, cl);
+ if (clz != null) {
+ cls.add(clz);
+ } else {
+ throw new WrongParameterValueException(this, (String) obj, "Class '" + cl + "' not found for given value. Must be a subclass / implementation of " + restrictionClass.getName());
}
}
return cls;
@@ -168,8 +147,8 @@ public class ClassListParameter<C> extends ListParameter<Class<? extends C>> {
@Override
protected boolean validate(List<Class<? extends C>> obj) throws ParameterException {
- for(Class<? extends C> cls : obj) {
- if(!restrictionClass.isAssignableFrom(cls)) {
+ for (Class<? extends C> cls : obj) {
+ if (!restrictionClass.isAssignableFrom(cls)) {
throw new WrongParameterValueException(this, cls.getName(), "Class \"" + cls.getName() + "\" does not extend/implement restriction class " + restrictionClass + ".\n");
}
}
@@ -217,20 +196,19 @@ public class ClassListParameter<C> extends ListParameter<Class<? extends C>> {
*/
public List<C> instantiateClasses(Parameterization config) {
config = config.descend(this);
- List<C> instances = new ArrayList<C>();
- if(getValue() == null) {
+ List<C> instances = new ArrayList<>();
+ if (getValue() == null) {
config.reportError(new UnusedParameterException("Value of parameter " + getName() + " has not been specified."));
return instances; // empty list.
}
- for(Class<? extends C> cls : getValue()) {
+ for (Class<? extends C> cls : getValue()) {
// NOTE: There is a duplication of this code in ObjectListParameter - keep
// in sync!
try {
C instance = ClassGenericsUtil.tryInstantiate(restrictionClass, cls, config);
instances.add(instance);
- }
- catch(Exception e) {
+ } catch (Exception e) {
config.reportError(new WrongParameterValueException(this, cls.getName(), e));
}
}
@@ -247,26 +225,24 @@ public class ClassListParameter<C> extends ListParameter<Class<? extends C>> {
public String restrictionString() {
String prefix = restrictionClass.getPackage().getName() + ".";
StringBuilder info = new StringBuilder();
- if(restrictionClass.isInterface()) {
+ if (restrictionClass.isInterface()) {
info.append("Implementing ");
- }
- else {
+ } else {
info.append("Extending ");
}
info.append(restrictionClass.getName());
info.append(FormatUtil.NEWLINE);
List<Class<?>> known = getKnownImplementations();
- if(!known.isEmpty()) {
+ if (!known.isEmpty()) {
info.append("Known classes (default package " + prefix + "):");
info.append(FormatUtil.NEWLINE);
- for(Class<?> c : known) {
+ for (Class<?> c : known) {
info.append("->" + FormatUtil.NONBREAKING_SPACE);
String name = c.getName();
- if(name.startsWith(prefix)) {
+ if (name.startsWith(prefix)) {
info.append(name.substring(prefix.length()));
- }
- else {
+ } else {
info.append(name);
}
info.append(FormatUtil.NEWLINE);
@@ -292,9 +268,9 @@ public class ClassListParameter<C> extends ListParameter<Class<? extends C>> {
*/
@Override
public String getValuesDescription() {
- if(restrictionClass != null && restrictionClass != Object.class) {
+ if (restrictionClass != null && restrictionClass != Object.class) {
return restrictionString();
}
return "";
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ClassParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ClassParameter.java
index 6d63f9b5..a0669fca 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ClassParameter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ClassParameter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -51,16 +51,6 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameteriz
// TODO: turn restrictionClass into a constraint?
public class ClassParameter<C> extends AbstractParameter<Class<? extends C>> {
/**
- * Class loader.
- */
- protected static final ClassLoader loader = ClassLoader.getSystemClassLoader();
-
- /**
- * Factory class postfix.
- */
- public static final String FACTORY_POSTFIX = "$Factory";
-
- /**
* The restriction class for this class parameter.
*/
protected Class<C> restrictionClass;
@@ -132,29 +122,9 @@ public class ClassParameter<C> extends AbstractParameter<Class<? extends C>> {
return (Class<? extends C>) obj;
}
if (obj instanceof String) {
- String value = (String) obj;
- try {
- // Try exact class factory first.
- try {
- return (Class<? extends C>) loader.loadClass(value + FACTORY_POSTFIX);
- } catch (ClassNotFoundException e) {
- // Ignore, retry
- }
- try {
- return (Class<? extends C>) loader.loadClass(value);
- } catch (ClassNotFoundException e) {
- // Ignore, retry
- }
- // Try factory for guessed name next
- try {
- return (Class<? extends C>) loader.loadClass(restrictionClass.getPackage().getName() + "." + value + FACTORY_POSTFIX);
- } catch (ClassNotFoundException e) {
- // Ignore, retry
- }
- // Last try: guessed name prefix only
- return (Class<? extends C>) loader.loadClass(restrictionClass.getPackage().getName() + "." + value);
- } catch (ClassNotFoundException e) {
- throw new WrongParameterValueException(this, value, "Given class \"" + value + "\" not found.", e);
+ Class<? extends C> clz = InspectionUtil.findImplementation(restrictionClass, (String) obj);
+ if (clz != null) {
+ return clz;
}
}
throw new WrongParameterValueException(this, obj.toString(), "Class not found for given value. Must be a subclass / implementation of " + restrictionClass.getName());
@@ -330,9 +300,9 @@ public class ClassParameter<C> extends AbstractParameter<Class<? extends C>> {
*/
public static String canonicalClassName(Class<?> c, Class<?> parent) {
if (parent == null) {
- return canonicalClassName(c, null, FACTORY_POSTFIX);
+ return canonicalClassName(c, null, InspectionUtil.FACTORY_POSTFIX);
}
- return canonicalClassName(c, parent.getPackage(), FACTORY_POSTFIX);
+ return canonicalClassName(c, parent.getPackage(), InspectionUtil.FACTORY_POSTFIX);
}
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/DistanceParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/DistanceParameter.java
index f9943610..e97b6d0e 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/DistanceParameter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/DistanceParameter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/DoubleListParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/DoubleListParameter.java
index 885a3bfc..89cfc345 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/DoubleListParameter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/DoubleListParameter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -81,7 +81,7 @@ public class DoubleListParameter extends ListParameter<Double> {
}
if(obj instanceof String) {
String[] values = SPLIT.split((String) obj);
- ArrayList<Double> doubleValue = new ArrayList<Double>(values.length);
+ ArrayList<Double> doubleValue = new ArrayList<>(values.length);
for(String val : values) {
doubleValue.add(Double.valueOf(val));
}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/DoubleParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/DoubleParameter.java
index 4aee3511..632e1f8c 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/DoubleParameter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/DoubleParameter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/EnumParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/EnumParameter.java
index c2e1c733..4d05753c 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/EnumParameter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/EnumParameter.java
@@ -111,14 +111,16 @@ public class EnumParameter<E extends Enum<E>> extends AbstractParameter<E> {
@Override
protected E parseValue(Object obj) throws ParameterException {
- if(obj == null) {
+ if (obj == null) {
throw new UnspecifiedParameterException(this);
}
- if(obj instanceof String) {
+ if (enumClass.isInstance(obj)) {
+ return enumClass.cast(obj);
+ }
+ if (obj instanceof String) {
try {
return Enum.valueOf(enumClass, (String) obj);
- }
- catch(IllegalArgumentException ex) {
+ } catch (IllegalArgumentException ex) {
throw new WrongParameterValueException("Enum parameter " + getName() + " is invalid (must be one of [" + joinEnumNames(", ") + "].");
}
}
@@ -138,8 +140,8 @@ public class EnumParameter<E extends Enum<E>> extends AbstractParameter<E> {
public Collection<String> getPossibleValues() {
// Convert to string array
final E[] enums = enumClass.getEnumConstants();
- ArrayList<String> values = new ArrayList<String>(enums.length);
- for(E t : enums) {
+ ArrayList<String> values = new ArrayList<>(enums.length);
+ for (E t : enums) {
values.add(t.name());
}
return values;
@@ -155,8 +157,8 @@ public class EnumParameter<E extends Enum<E>> extends AbstractParameter<E> {
private String joinEnumNames(String separator) {
E[] enumTypes = enumClass.getEnumConstants();
StringBuilder sb = new StringBuilder();
- for(int i = 0; i < enumTypes.length; ++i) {
- if(i > 0) {
+ for (int i = 0; i < enumTypes.length; ++i) {
+ if (i > 0) {
sb.append(separator);
}
sb.append(enumTypes[i].name());
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/FileListParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/FileListParameter.java
index 203712aa..eb638298 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/FileListParameter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/FileListParameter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -108,7 +108,7 @@ public class FileListParameter extends ListParameter<File> {
}
if(obj instanceof String) {
String[] values = SPLIT.split((String) obj);
- ArrayList<File> fileValue = new ArrayList<File>(values.length);
+ ArrayList<File> fileValue = new ArrayList<>(values.length);
for(String val : values) {
fileValue.add(new File(val));
}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/FileParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/FileParameter.java
index 2cc5ab37..ea3fa454 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/FileParameter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/FileParameter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -137,4 +137,13 @@ public class FileParameter extends AbstractParameter<File> {
public String getSyntax() {
return "<file>";
}
+
+ /**
+ * Get the file type (input / output)
+ *
+ * @return file type
+ */
+ public FileType getFileType() {
+ return fileType;
+ }
}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/Flag.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/Flag.java
index 90230077..7587d2a5 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/Flag.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/Flag.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/IntListParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/IntListParameter.java
index f61f8842..93012955 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/IntListParameter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/IntListParameter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -90,7 +90,7 @@ public class IntListParameter extends ListParameter<Integer> {
}
if(obj instanceof String) {
String[] values = SPLIT.split((String) obj);
- ArrayList<Integer> intValue = new ArrayList<Integer>(values.length);
+ ArrayList<Integer> intValue = new ArrayList<>(values.length);
for(String val : values) {
intValue.add(Integer.valueOf(val));
}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/IntParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/IntParameter.java
index 22823e16..30457330 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/IntParameter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/IntParameter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ListParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ListParameter.java
index e71a744e..119fb121 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ListParameter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ListParameter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/LongParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/LongParameter.java
index ac8bd62c..f5d441b5 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/LongParameter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/LongParameter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/NumberParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/NumberParameter.java
index 8928c292..a4448d30 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/NumberParameter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/NumberParameter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ObjectListParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ObjectListParameter.java
index 85a32085..ada6239a 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ObjectListParameter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ObjectListParameter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -81,8 +81,8 @@ public class ObjectListParameter<C> extends ClassListParameter<C> {
}
if (List.class.isInstance(obj)) {
List<?> l = (List<?>) obj;
- ArrayList<C> inst = new ArrayList<C>(l.size());
- ArrayList<Class<? extends C>> classes = new ArrayList<Class<? extends C>>(l.size());
+ ArrayList<C> inst = new ArrayList<>(l.size());
+ ArrayList<Class<? extends C>> classes = new ArrayList<>(l.size());
for (Object o : l) {
// does the given objects class fit?
if (restrictionClass.isInstance(o)) {
@@ -105,7 +105,7 @@ public class ObjectListParameter<C> extends ClassListParameter<C> {
// Did we get a single instance?
try {
C inst = restrictionClass.cast(obj);
- this.instances = new ArrayList<C>(1);
+ this.instances = new ArrayList<>(1);
this.instances.add(inst);
return super.parseValue(inst.getClass());
} catch (ClassCastException e) {
@@ -118,7 +118,7 @@ public class ObjectListParameter<C> extends ClassListParameter<C> {
public List<C> instantiateClasses(Parameterization config) {
if (instances == null) {
// instantiateClasses will descend itself.
- instances = new ArrayList<C>(super.instantiateClasses(config));
+ instances = new ArrayList<>(super.instantiateClasses(config));
} else {
Parameterization cfg = null;
for (int i = 0; i < instances.size(); i++) {
@@ -138,6 +138,6 @@ public class ObjectListParameter<C> extends ClassListParameter<C> {
}
}
}
- return new ArrayList<C>(instances);
+ return new ArrayList<>(instances);
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ObjectParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ObjectParameter.java
index eff80954..4166d0a2 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ObjectParameter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ObjectParameter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/Parameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/Parameter.java
index 6dadbf8f..110633b3 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/Parameter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/Parameter.java
@@ -9,7 +9,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.ParameterConstra
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/PatternParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/PatternParameter.java
index 05c99d2b..b76edbbb 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/PatternParameter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/PatternParameter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/RandomParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/RandomParameter.java
index 34d01de5..6c0668dd 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/RandomParameter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/RandomParameter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/StringParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/StringParameter.java
index 06789dba..3a9bbf11 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/StringParameter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/StringParameter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/VectorListParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/VectorListParameter.java
index a9d01f22..906bfbd8 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/VectorListParameter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/VectorListParameter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,7 +29,6 @@ import java.util.List;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.ParameterException;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.UnspecifiedParameterException;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.WrongParameterValueException;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.ParameterConstraint;
@@ -178,11 +177,11 @@ public class VectorListParameter extends ListParameter<List<Double>> {
if(vectors.length == 0) {
throw new WrongParameterValueException("Wrong parameter format! Given list of vectors for parameter \"" + getName() + "\" is empty!");
}
- ArrayList<List<Double>> vecs = new ArrayList<List<Double>>();
+ ArrayList<List<Double>> vecs = new ArrayList<>();
for(String vector : vectors) {
String[] coordinates = SPLIT.split(vector);
- ArrayList<Double> vectorCoord = new ArrayList<Double>();
+ ArrayList<Double> vectorCoord = new ArrayList<>();
for(String coordinate : coordinates) {
try {
vectorCoord.add(Double.valueOf(coordinate));
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/package-info.java
index b6ff5216..75d7c5a1 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/package-info.java
@@ -12,7 +12,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/package-info.java
index 6a8126e1..1e110d8e 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/package-info.java
@@ -38,7 +38,6 @@
* <li>{@link de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionUtil}: Managing parameter settings</li>
* <li>{@link de.lmu.ifi.dbs.elki.utilities.InspectionUtil}: class and classpath inspection.</li>
* <li>{@link de.lmu.ifi.dbs.elki.utilities.documentation.DocumentationUtil}: documentation extraction from annotations.</li>
- * <li>{@link de.lmu.ifi.dbs.elki.persistent.PageFileUtil}: reporting page file accesses.</li>
* <li>{@link de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.query.RStarTreeUtil}: reporting page file accesses.</li>
* </ul></li>
* </ul>
@@ -47,7 +46,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/pairs/CPair.java b/src/de/lmu/ifi/dbs/elki/utilities/pairs/CPair.java
index dabc623e..036eaea2 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/pairs/CPair.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/pairs/CPair.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.pairs;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/pairs/CTriple.java b/src/de/lmu/ifi/dbs/elki/utilities/pairs/CTriple.java
index 2a07fc28..88ed35eb 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/pairs/CTriple.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/pairs/CTriple.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.pairs;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,8 +23,6 @@ package de.lmu.ifi.dbs.elki.utilities.pairs;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
-
/**
* Triple with canonical comparison function.
*
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/pairs/DoubleDoublePair.java b/src/de/lmu/ifi/dbs/elki/utilities/pairs/DoubleDoublePair.java
index 143c8014..092d6635 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/pairs/DoubleDoublePair.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/pairs/DoubleDoublePair.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.pairs;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -59,6 +59,15 @@ public class DoubleDoublePair implements Comparable<DoubleDoublePair>, PairInter
}
/**
+ * Clone constructor.
+ *
+ * @param other Existing pair.
+ */
+ public DoubleDoublePair(DoubleDoublePair other) {
+ this(other.first, other.second);
+ }
+
+ /**
* Trivial equals implementation
*
* @param obj Object to compare to
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/pairs/DoubleIntPair.java b/src/de/lmu/ifi/dbs/elki/utilities/pairs/DoubleIntPair.java
index 17698454..be18c712 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/pairs/DoubleIntPair.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/pairs/DoubleIntPair.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.pairs;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/pairs/DoubleObjPair.java b/src/de/lmu/ifi/dbs/elki/utilities/pairs/DoubleObjPair.java
index 3bffd979..678d4532 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/pairs/DoubleObjPair.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/pairs/DoubleObjPair.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.pairs;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/pairs/FCPair.java b/src/de/lmu/ifi/dbs/elki/utilities/pairs/FCPair.java
index 6724ddfb..4d2f707c 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/pairs/FCPair.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/pairs/FCPair.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.pairs;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/pairs/IntDoublePair.java b/src/de/lmu/ifi/dbs/elki/utilities/pairs/IntDoublePair.java
index 368134b0..bfcf5971 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/pairs/IntDoublePair.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/pairs/IntDoublePair.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.pairs;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/pairs/IntIntPair.java b/src/de/lmu/ifi/dbs/elki/utilities/pairs/IntIntPair.java
index 108afdef..5d3210a4 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/pairs/IntIntPair.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/pairs/IntIntPair.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.pairs;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/pairs/Pair.java b/src/de/lmu/ifi/dbs/elki/utilities/pairs/Pair.java
index f682e06f..ca8db67d 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/pairs/Pair.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/pairs/Pair.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.pairs;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/pairs/PairInterface.java b/src/de/lmu/ifi/dbs/elki/utilities/pairs/PairInterface.java
index 5ea33971..fde1f3a9 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/pairs/PairInterface.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/pairs/PairInterface.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.pairs;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/pairs/PairUtil.java b/src/de/lmu/ifi/dbs/elki/utilities/pairs/PairUtil.java
index 01b27ca0..387d4f79 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/pairs/PairUtil.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/pairs/PairUtil.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.pairs;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -50,7 +50,7 @@ public final class PairUtil {
* @return Comparator
*/
public static <FIRST extends Comparable<? super FIRST>, SECOND extends Comparable<? super SECOND>> Comparator<Pair<? extends FIRST, ? extends SECOND>> comparator() {
- return new CompareNatural<FIRST, SECOND>();
+ return new CompareNatural<>();
}
/**
@@ -63,7 +63,7 @@ public final class PairUtil {
* @return Comparator
*/
public static <FIRST, SECOND> Comparator<Pair<? extends FIRST, ? extends SECOND>> comparator(Comparator<? super FIRST> c1, Comparator<? super SECOND> c2) {
- return new Compare<FIRST, SECOND>(c1, c2);
+ return new Compare<>(c1, c2);
}
/**
@@ -75,7 +75,7 @@ public final class PairUtil {
* @return Comparator
*/
public static <FIRST extends Comparable<? super FIRST>, SECOND> Comparator<Pair<? extends FIRST, ? extends SECOND>> comparatorFirst() {
- return new CompareNaturalFirst<FIRST, SECOND>();
+ return new CompareNaturalFirst<>();
}
/**
@@ -88,7 +88,7 @@ public final class PairUtil {
* @return Comparator
*/
public static <FIRST, SECOND> Comparator<Pair<? extends FIRST, ? extends SECOND>> comparatorFirst(Comparator<? super FIRST> c1) {
- return new CompareByFirst<FIRST, SECOND>(c1);
+ return new CompareByFirst<>(c1);
}
/**
@@ -100,7 +100,7 @@ public final class PairUtil {
* @return Comparator
*/
public static <FIRST, SECOND extends Comparable<? super SECOND>> Comparator<Pair<? extends FIRST, ? extends SECOND>> comparatorSecond() {
- return new CompareNaturalSecond<FIRST, SECOND>();
+ return new CompareNaturalSecond<>();
}
/**
@@ -113,7 +113,7 @@ public final class PairUtil {
* @return Comparator
*/
public static <FIRST, SECOND> Comparator<Pair<? extends FIRST, ? extends SECOND>> comparatorSecond(Comparator<? super SECOND> c2) {
- return new CompareBySecond<FIRST, SECOND>(c2);
+ return new CompareBySecond<>(c2);
}
/**
@@ -125,7 +125,7 @@ public final class PairUtil {
* @return Comparator
*/
public static <FIRST extends Comparable<? super FIRST>, SECOND extends Comparable<? super SECOND>> Comparator<Pair<? extends FIRST, ? extends SECOND>> comparatorSwapped() {
- return new CompareNaturalSwapped<FIRST, SECOND>();
+ return new CompareNaturalSwapped<>();
}
/**
@@ -139,7 +139,7 @@ public final class PairUtil {
* @return Comparator
*/
public static <FIRST, SECOND> Comparator<Pair<? extends FIRST, ? extends SECOND>> comparatorSwapped(Comparator<? super FIRST> c1, Comparator<? super SECOND> c2) {
- return new CompareSwapped<FIRST, SECOND>(c1, c2);
+ return new CompareSwapped<>(c1, c2);
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/pairs/SCPair.java b/src/de/lmu/ifi/dbs/elki/utilities/pairs/SCPair.java
index 585c7a57..90d7f738 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/pairs/SCPair.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/pairs/SCPair.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.pairs;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/pairs/Triple.java b/src/de/lmu/ifi/dbs/elki/utilities/pairs/Triple.java
index 2f75ec5a..4cac1e9c 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/pairs/Triple.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/pairs/Triple.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.pairs;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/pairs/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/pairs/package-info.java
index 2fdf3770..6a4e9501 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/pairs/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/pairs/package-info.java
@@ -37,7 +37,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/AxisBasedReferencePoints.java b/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/AxisBasedReferencePoints.java
index 26a4c7ed..24829d98 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/AxisBasedReferencePoints.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/AxisBasedReferencePoints.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.referencepoints;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -88,7 +88,7 @@ public class AxisBasedReferencePoints<V extends NumberVector<?>> implements Refe
delta[d] = spacescale * (minmax.second.doubleValue(d) - mean[d]);
}
- ArrayList<V> result = new ArrayList<V>(2 + dim);
+ ArrayList<V> result = new ArrayList<>(2 + dim);
double[] vec = new double[dim];
// Use min and max
@@ -141,7 +141,7 @@ public class AxisBasedReferencePoints<V extends NumberVector<?>> implements Refe
@Override
protected AxisBasedReferencePoints<V> makeInstance() {
- return new AxisBasedReferencePoints<V>(spacescale);
+ return new AxisBasedReferencePoints<>(spacescale);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/FullDatabaseReferencePoints.java b/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/FullDatabaseReferencePoints.java
index 335a63f8..b92d0575 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/FullDatabaseReferencePoints.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/FullDatabaseReferencePoints.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.referencepoints;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/GridBasedReferencePoints.java b/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/GridBasedReferencePoints.java
index 60e47872..b94564cf 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/GridBasedReferencePoints.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/GridBasedReferencePoints.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.referencepoints;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -102,7 +102,7 @@ public class GridBasedReferencePoints<V extends NumberVector<?>> implements Refe
}
int gridpoints = Math.max(1, (int) Math.pow(gridres + 1, dim));
- ArrayList<V> result = new ArrayList<V>(gridpoints);
+ ArrayList<V> result = new ArrayList<>(gridpoints);
double[] delta = new double[dim];
if (gridres > 0) {
double halfgrid = gridres / 2.0;
@@ -166,7 +166,7 @@ public class GridBasedReferencePoints<V extends NumberVector<?>> implements Refe
@Override
protected GridBasedReferencePoints<V> makeInstance() {
- return new GridBasedReferencePoints<V>(gridres, gridscale);
+ return new GridBasedReferencePoints<>(gridres, gridscale);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/RandomGeneratedReferencePoints.java b/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/RandomGeneratedReferencePoints.java
index 71e8e4c8..0a59d410 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/RandomGeneratedReferencePoints.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/RandomGeneratedReferencePoints.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.referencepoints;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -102,7 +102,7 @@ public class RandomGeneratedReferencePoints<V extends NumberVector<?>> implement
delta[d] = (minmax.second.doubleValue(d + 1) - minmax.first.doubleValue(d + 1));
}
- ArrayList<V> result = new ArrayList<V>(samplesize);
+ ArrayList<V> result = new ArrayList<>(samplesize);
double[] vec = new double[dim];
for (int i = 0; i < samplesize; i++) {
for (int d = 0; d < dim; d++) {
@@ -153,7 +153,7 @@ public class RandomGeneratedReferencePoints<V extends NumberVector<?>> implement
@Override
protected RandomGeneratedReferencePoints<V> makeInstance() {
- return new RandomGeneratedReferencePoints<V>(samplesize, scale);
+ return new RandomGeneratedReferencePoints<>(samplesize, scale);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/RandomSampleReferencePoints.java b/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/RandomSampleReferencePoints.java
index 2cb778b3..a2a48b30 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/RandomSampleReferencePoints.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/RandomSampleReferencePoints.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.referencepoints;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -83,14 +83,14 @@ public class RandomSampleReferencePoints<V extends NumberVector<?>> implements R
if(samplesize >= db.size()) {
LoggingUtil.warning("Sample size is larger than database size!");
- ArrayList<V> selection = new ArrayList<V>(db.size());
+ ArrayList<V> selection = new ArrayList<>(db.size());
for(DBIDIter iditer = db.iterDBIDs(); iditer.valid(); iditer.advance()) {
selection.add(db.get(iditer));
}
return selection;
}
- ArrayList<V> result = new ArrayList<V>(samplesize);
+ ArrayList<V> result = new ArrayList<>(samplesize);
int dbsize = db.size();
// Guess the memory requirements of a hashmap.
@@ -119,7 +119,7 @@ public class RandomSampleReferencePoints<V extends NumberVector<?>> implements R
ids = null; // dirty!
}
else {
- HashSet<Integer> selected = new HashSet<Integer>();
+ HashSet<Integer> selected = new HashSet<>();
for(int i = 0; i < samplesize; i++) {
int j = (int) Math.floor(Math.random() * dbsize);
// Redraw from pool.
@@ -159,7 +159,7 @@ public class RandomSampleReferencePoints<V extends NumberVector<?>> implements R
@Override
protected RandomSampleReferencePoints<V> makeInstance() {
- return new RandomSampleReferencePoints<V>(samplesize);
+ return new RandomSampleReferencePoints<>(samplesize);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/ReferencePointsHeuristic.java b/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/ReferencePointsHeuristic.java
index 70114a32..672b5240 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/ReferencePointsHeuristic.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/ReferencePointsHeuristic.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.referencepoints;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/StarBasedReferencePoints.java b/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/StarBasedReferencePoints.java
index 0e562770..611100b4 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/StarBasedReferencePoints.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/StarBasedReferencePoints.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.referencepoints;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -117,7 +117,7 @@ public class StarBasedReferencePoints<V extends NumberVector<?>> implements Refe
max[d] = (max[d] - centroid[d]) * scale + centroid[d];
}
- ArrayList<V> result = new ArrayList<V>(2 * dim + 1);
+ ArrayList<V> result = new ArrayList<>(2 * dim + 1);
if (!nocenter) {
result.add(factory.newNumberVector(centroid));
}
@@ -173,7 +173,7 @@ public class StarBasedReferencePoints<V extends NumberVector<?>> implements Refe
@Override
protected StarBasedReferencePoints<V> makeInstance() {
- return new StarBasedReferencePoints<V>(nocenter, scale);
+ return new StarBasedReferencePoints<>(nocenter, scale);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/package-info.java
index a8ce0bc5..6268d5d2 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/package-info.java
@@ -7,7 +7,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/ClipScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/ClipScaling.java
index aad0b63a..068e1230 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/ClipScaling.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/ClipScaling.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/GammaScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/GammaScaling.java
index b23b9400..daff7275 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/GammaScaling.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/GammaScaling.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/IdentityScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/IdentityScaling.java
index a2202b92..7f24431d 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/IdentityScaling.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/IdentityScaling.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/LinearScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/LinearScaling.java
index 87f42835..ef28c434 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/LinearScaling.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/LinearScaling.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/MinusLogScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/MinusLogScaling.java
index b5007ad1..8e497dd9 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/MinusLogScaling.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/MinusLogScaling.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/ScalingFunction.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/ScalingFunction.java
index 6bd0527f..c738aa9a 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/ScalingFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/ScalingFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/StaticScalingFunction.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/StaticScalingFunction.java
index 228f5f1a..27d12db4 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/StaticScalingFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/StaticScalingFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/COPOutlierScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/COPOutlierScaling.java
new file mode 100644
index 00000000..202d1044
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/COPOutlierScaling.java
@@ -0,0 +1,172 @@
+package de.lmu.ifi.dbs.elki.utilities.scaling.outlier;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import java.util.Arrays;
+
+import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.Distribution;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.meta.BestFitEstimator;
+import de.lmu.ifi.dbs.elki.result.outlier.InvertedOutlierScoreMeta;
+import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayLikeUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleParameter;
+
+/**
+ * CDF based outlier score scaling.
+ *
+ * Enhanced version of the scaling proposed in:
+ * <p>
+ * H.-P. Kriegel, P. Kröger, E. Schubert, A. Zimek<br />
+ * Interpreting and Unifying Outlier Scores<br />
+ * Proc. 11th SIAM International Conference on Data Mining (SDM), Mesa, AZ, 2011
+ * </p>
+ *
+ * See also:
+ * <p>
+ * Hans-Peter Kriegel, Peer Kröger, Erich Schubert, Arthur Zimek<br />
+ * Outlier Detection in Arbitrarily Oriented Subspaces<br />
+ * in: Proc. IEEE International Conference on Data Mining (ICDM 2012)
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@Reference(authors = "H.-P. Kriegel, P. Kröger, E. Schubert, A. Zimek", title = "Interpreting and Unifying Outlier Scores", booktitle = "Proc. 11th SIAM International Conference on Data Mining (SDM), Mesa, AZ, 2011", url = "http://siam.omnibooksonline.com/2011datamining/data/papers/018.pdf")
+public class COPOutlierScaling implements OutlierScalingFunction {
+ /**
+ * Phi parameter.
+ */
+ private double phi = 0.;
+
+ /**
+ * Score distribution.
+ */
+ private Distribution dist;
+
+ /**
+ * Inversion flag.
+ */
+ private boolean inverted = false;
+
+ /**
+ * Constructor.
+ *
+ * @param phi Phi parameter
+ */
+ public COPOutlierScaling(double phi) {
+ super();
+ this.phi = phi;
+ }
+
+ /**
+ * Secondary reference.
+ */
+ @Reference(authors = "Hans-Peter Kriegel, Peer Kröger, Erich Schubert, Arthur Zimek", title = "Outlier Detection in Arbitrarily Oriented Subspaces", booktitle = "Proc. IEEE International Conference on Data Mining (ICDM 2012)")
+ public static final void secondReference() {
+ // Dummy, reference attachment point only.
+ }
+
+ @Override
+ public double getScaled(double value) {
+ if (dist == null) {
+ throw new AbortException("Programming error: outlier scaling not initialized.");
+ }
+ double s = inverted ? (1 - dist.cdf(value)) : dist.cdf(value);
+ return (phi > 0.) ? (phi * s) / (1 - s + phi) : s;
+ }
+
+ @Override
+ public double getMin() {
+ return 0.;
+ }
+
+ @Override
+ public double getMax() {
+ return 1.;
+ }
+
+ @Override
+ public void prepare(OutlierResult or) {
+ double[] s;
+ {
+ Relation<Double> scores = or.getScores();
+ s = new double[scores.size()];
+ int i = 0;
+ for (DBIDIter id = scores.iterDBIDs(); id.valid(); id.advance(), i++) {
+ s[i] = scores.get(id);
+ }
+ }
+ Arrays.sort(s);
+ dist = BestFitEstimator.STATIC.estimate(s, ArrayLikeUtil.DOUBLEARRAYADAPTER);
+ inverted = (or.getOutlierMeta() instanceof InvertedOutlierScoreMeta);
+ }
+
+ @Override
+ public <A> void prepare(A array, NumberArrayAdapter<?, A> adapter) {
+ double[] s = ArrayLikeUtil.toPrimitiveDoubleArray(array, adapter);
+ Arrays.sort(s);
+ dist = BestFitEstimator.STATIC.estimate(s, ArrayLikeUtil.DOUBLEARRAYADAPTER);
+ inverted = false; // Not supported
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ /**
+ * Phi parameter.
+ */
+ public static final OptionID PHI_ID = new OptionID("copscaling.phi", "Phi parameter, expected rate of outliers. Set to 0 to use raw CDF values.");
+
+ /**
+ * Phi value.
+ */
+ private double phi = 0.;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ DoubleParameter phiP = new DoubleParameter(PHI_ID);
+ if (config.grab(phiP)) {
+ phi = phiP.doubleValue();
+ }
+ }
+
+ @Override
+ protected COPOutlierScaling makeInstance() {
+ return new COPOutlierScaling(phi);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/HeDESNormalizationOutlierScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/HeDESNormalizationOutlierScaling.java
index 4bf86f06..5e55c2e0 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/HeDESNormalizationOutlierScaling.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/HeDESNormalizationOutlierScaling.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,6 +28,7 @@ import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
import de.lmu.ifi.dbs.elki.math.MeanVariance;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
/**
@@ -63,9 +64,29 @@ public class HeDESNormalizationOutlierScaling implements OutlierScalingFunction
DoubleMinMax minmax = new DoubleMinMax();
Relation<Double> scores = or.getScores();
- for(DBIDIter id = scores.iterDBIDs(); id.valid(); id.advance()) {
+ for (DBIDIter id = scores.iterDBIDs(); id.valid(); id.advance()) {
double val = scores.get(id);
- if(!Double.isNaN(val) && !Double.isInfinite(val)) {
+ if (!Double.isNaN(val) && !Double.isInfinite(val)) {
+ mv.put(val);
+ minmax.put(val);
+ }
+ }
+
+ mean = mv.getMean();
+ stddev = mv.getSampleStddev();
+ scaledmax = getScaled(minmax.getMax());
+ scaledmin = getScaled(minmax.getMin());
+ }
+
+ @Override
+ public <A> void prepare(A array, NumberArrayAdapter<?, A> adapter) {
+ MeanVariance mv = new MeanVariance();
+ DoubleMinMax minmax = new DoubleMinMax();
+
+ final int size = adapter.size(array);
+ for (int i = 0; i < size; i++) {
+ double val = adapter.getDouble(array, i);
+ if (!Double.isNaN(val) && !Double.isInfinite(val)) {
mv.put(val);
minmax.put(val);
}
@@ -90,6 +111,10 @@ public class HeDESNormalizationOutlierScaling implements OutlierScalingFunction
@Override
public double getScaled(double value) {
assert (stddev > 0 || (value == mean)) : "prepare() was not run prior to using the scaling function.";
- return (value - mean) / stddev;
+ if (stddev > 0.) {
+ return (value - mean) / stddev;
+ } else {
+ return 0.;
+ }
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MinusLogGammaScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MinusLogGammaScaling.java
index f7cf0df0..effbcfe0 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MinusLogGammaScaling.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MinusLogGammaScaling.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MinusLogStandardDeviationScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MinusLogStandardDeviationScaling.java
index e34355a1..d30fbac7 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MinusLogStandardDeviationScaling.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MinusLogStandardDeviationScaling.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MixtureModelOutlierScalingFunction.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MixtureModelOutlierScalingFunction.java
index e026b211..9c5ad920 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MixtureModelOutlierScalingFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MixtureModelOutlierScalingFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -31,6 +31,7 @@ import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.math.MathUtil;
import de.lmu.ifi.dbs.elki.math.MeanVariance;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
/**
@@ -45,7 +46,7 @@ public class MixtureModelOutlierScalingFunction implements OutlierScalingFunctio
* The logger for this class.
*/
private static final Logging LOG = Logging.getLogger(MixtureModelOutlierScalingFunction.class);
-
+
/**
* Parameter mu of the gaussian distribution (outliers)
*/
@@ -122,14 +123,14 @@ public class MixtureModelOutlierScalingFunction implements OutlierScalingFunctio
// Initial parameters - are these defaults sounds?
MeanVariance mv = new MeanVariance();
Relation<Double> scores = or.getScores();
- for(DBIDIter id = scores.iterDBIDs(); id.valid(); id.advance()) {
+ for (DBIDIter id = scores.iterDBIDs(); id.valid(); id.advance()) {
double val = scores.get(id);
- if(!Double.isNaN(val) && !Double.isInfinite(val)) {
+ if (!Double.isNaN(val) && !Double.isInfinite(val)) {
mv.put(val);
}
}
double curMu = mv.getMean() * 2.;
- if(curMu == 0) {
+ if (curMu == 0) {
curMu = Double.MIN_NORMAL;
}
double curSigma = Math.max(mv.getSampleStddev(), Double.MIN_NORMAL);
@@ -141,7 +142,7 @@ public class MixtureModelOutlierScalingFunction implements OutlierScalingFunctio
int iter = 0;
// logger.debugFine("iter #-1 mu = " + curMu + " sigma = " + curSigma +
// " lambda = " + curLambda + " alpha = " + curAlpha);
- while(true) {
+ while (true) {
// E and M-Steps
// Sum of weights
double tisum = 0.0;
@@ -149,7 +150,7 @@ public class MixtureModelOutlierScalingFunction implements OutlierScalingFunctio
double wsum = 0.0;
// Weighted deviation from previous mean
double sqsum = 0.0;
- for(int i = 0; i < ids.size(); i++) {
+ for (int i = 0; i < ids.size(); i++) {
double val = or.getScores().get(ids.get(i));
// E-Step
double ti = calcPosterior(val, curAlpha, curMu, curSigma, curLambda);
@@ -158,7 +159,7 @@ public class MixtureModelOutlierScalingFunction implements OutlierScalingFunctio
wsum += ti * val;
sqsum += ti * val * val; // (val - curMu) * (val - curMu);
}
- if(tisum <= 0.0 || wsum <= 0.0) {
+ if (tisum <= 0.0 || wsum <= 0.0) {
LOG.warning("MixtureModel Outlier Scaling converged to extreme.");
break;
}
@@ -169,23 +170,115 @@ public class MixtureModelOutlierScalingFunction implements OutlierScalingFunctio
// converged?
{
boolean changed = false;
- if(Math.abs(newMu - curMu) > DELTA) {
+ if (Math.abs(newMu - curMu) > DELTA) {
+ changed = true;
+ }
+ if (Math.abs(newSigma - curSigma) > DELTA) {
+ changed = true;
+ }
+ if (Math.abs(newLambda - curLambda) > DELTA) {
+ changed = true;
+ }
+ if (Math.abs(newAlpha - curAlpha) > DELTA) {
+ changed = true;
+ }
+ if (!changed) {
+ break;
+ }
+ }
+ if (newSigma <= 0.0 || newAlpha <= 0.0) {
+ LOG.warning("MixtureModel Outlier Scaling converged to extreme.");
+ break;
+ }
+ // logger.debugFine("iter #"+iter+" mu = " + newMu + " sigma = " +
+ // newSigma + " lambda = " + newLambda + " alpha = " + newAlpha);
+ curMu = newMu;
+ curSigma = newSigma;
+ curLambda = newLambda;
+ curAlpha = newAlpha;
+
+ iter++;
+ if (iter > 100) {
+ LOG.warning("Max iterations met in mixture model fitting.");
+ break;
+ }
+ }
+ mu = curMu;
+ sigma = curSigma;
+ lambda = curLambda;
+ alpha = curAlpha;
+ // logger.debugFine("mu = " + mu + " sigma = " + sigma + " lambda = " +
+ // lambda + " alpha = " + alpha);
+ }
+
+ @Override
+ public <A> void prepare(A array, NumberArrayAdapter<?, A> adapter) {
+ // Initial parameters - are these defaults sounds?
+ MeanVariance mv = new MeanVariance();
+ final int size = adapter.size(array);
+ for (int i = 0; i < size; i++) {
+ double val = adapter.getDouble(array, i);
+ if (!Double.isNaN(val) && !Double.isInfinite(val)) {
+ mv.put(val);
+ }
+ }
+ double curMu = mv.getMean() * 2.;
+ if (curMu == 0) {
+ curMu = Double.MIN_NORMAL;
+ }
+ double curSigma = Math.max(mv.getSampleStddev(), Double.MIN_NORMAL);
+ double curLambda = Math.min(1.0 / curMu, Double.MAX_VALUE);
+ double curAlpha = 0.05;
+
+ // TODO: stop condition!
+ int iter = 0;
+ // logger.debugFine("iter #-1 mu = " + curMu + " sigma = " + curSigma +
+ // " lambda = " + curLambda + " alpha = " + curAlpha);
+ while (true) {
+ // E and M-Steps
+ // Sum of weights
+ double tisum = 0.0;
+ // Weighted sum
+ double wsum = 0.0;
+ // Weighted deviation from previous mean
+ double sqsum = 0.0;
+ for (int i = 0; i < size; i++) {
+ double val = adapter.getDouble(array, i);
+ // E-Step
+ double ti = calcPosterior(val, curAlpha, curMu, curSigma, curLambda);
+ // M-Step
+ tisum += ti;
+ wsum += ti * val;
+ sqsum += ti * val * val; // (val - curMu) * (val - curMu);
+ }
+ if (tisum <= 0.0 || wsum <= 0.0) {
+ LOG.warning("MixtureModel Outlier Scaling converged to extreme.");
+ break;
+ }
+ double newMu = wsum / tisum;
+ double newSigma = Math.max(Math.sqrt(sqsum / tisum - newMu * newMu), Double.MIN_NORMAL);
+ double newLambda = Math.min(tisum / wsum, Double.MAX_VALUE);
+ double newAlpha = tisum / size;
+ // converged?
+ {
+ boolean changed = false;
+ if (Math.abs(newMu - curMu) > DELTA) {
changed = true;
}
- if(Math.abs(newSigma - curSigma) > DELTA) {
+ if (Math.abs(newSigma - curSigma) > DELTA) {
changed = true;
}
- if(Math.abs(newLambda - curLambda) > DELTA) {
+ if (Math.abs(newLambda - curLambda) > DELTA) {
changed = true;
}
- if(Math.abs(newAlpha - curAlpha) > DELTA) {
+ if (Math.abs(newAlpha - curAlpha) > DELTA) {
changed = true;
}
- if(!changed) {
+ if (!changed) {
break;
}
}
- if(newSigma <= 0.0 || newAlpha <= 0.0) {
+ if (newSigma <= 0.0 || newAlpha <= 0.0) {
LOG.warning("MixtureModel Outlier Scaling converged to extreme.");
break;
}
@@ -197,7 +290,7 @@ public class MixtureModelOutlierScalingFunction implements OutlierScalingFunctio
curAlpha = newAlpha;
iter++;
- if(iter > 100) {
+ if (iter > 100) {
LOG.warning("Max iterations met in mixture model fitting.");
break;
}
@@ -224,9 +317,9 @@ public class MixtureModelOutlierScalingFunction implements OutlierScalingFunctio
public double getScaled(double value) {
final double val = 1.0 - calcPosterior(value, alpha, mu, sigma, lambda);
// Work around issues with unstable convergence.
- if(Double.isNaN(val)) {
+ if (Double.isNaN(val)) {
return 0.0;
}
return val;
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MultiplicativeInverseScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MultiplicativeInverseScaling.java
index 298a5853..d5cd3f40 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MultiplicativeInverseScaling.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MultiplicativeInverseScaling.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,6 +26,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
/**
@@ -68,16 +69,6 @@ public class MultiplicativeInverseScaling implements OutlierScalingFunction {
@Override
public void prepare(OutlierResult or) {
- scaleval = getScaleValue(or);
- }
-
- /**
- * Compute the scaling value in a linear scan over the annotation.
- *
- * @param or Outlier result
- * @return Scaling value.
- */
- private static double getScaleValue(OutlierResult or) {
double max = Double.MIN_VALUE;
Relation<Double> scores = or.getScores();
for(DBIDIter id = scores.iterDBIDs(); id.valid(); id.advance()) {
@@ -87,9 +78,22 @@ public class MultiplicativeInverseScaling implements OutlierScalingFunction {
max = Math.max(max, inv);
}
}
- return max;
+ scaleval = max;
}
-
+
+ @Override
+ public <A> void prepare(A array, NumberArrayAdapter<?, A> adapter) {
+ double max = Double.MIN_VALUE;
+ final int size = adapter.size(array);
+ for (int i = 0; i < size; i++) {
+ double inv = Math.abs(1.0 / adapter.getDouble(array, i));
+ if(!Double.isInfinite(inv) && !Double.isNaN(inv)) {
+ max = Math.max(max, inv);
+ }
+ }
+ scaleval = max;
+ }
+
@Override
public double getMin() {
return 0.0;
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierGammaScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierGammaScaling.java
index 07e58679..7da0c933 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierGammaScaling.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierGammaScaling.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,6 +29,7 @@ import de.lmu.ifi.dbs.elki.math.MeanVariance;
import de.lmu.ifi.dbs.elki.math.statistics.distribution.GammaDistribution;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierScoreMeta;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
@@ -91,7 +92,7 @@ public class OutlierGammaScaling implements OutlierScalingFunction {
public double getScaled(double value) {
assert (theta > 0) : "prepare() was not run prior to using the scaling function.";
value = preScale(value);
- if(Double.isNaN(value) || Double.isInfinite(value)) {
+ if (Double.isNaN(value) || Double.isInfinite(value)) {
return 1.0;
}
return Math.max(0, (GammaDistribution.regularizedGammaP(k, value / theta) - atmean) / (1 - atmean));
@@ -102,10 +103,29 @@ public class OutlierGammaScaling implements OutlierScalingFunction {
meta = or.getOutlierMeta();
MeanVariance mv = new MeanVariance();
Relation<Double> scores = or.getScores();
- for(DBIDIter id = scores.iterDBIDs(); id.valid(); id.advance()) {
+ for (DBIDIter id = scores.iterDBIDs(); id.valid(); id.advance()) {
double score = scores.get(id);
score = preScale(score);
- if(!Double.isNaN(score) && !Double.isInfinite(score)) {
+ if (!Double.isNaN(score) && !Double.isInfinite(score)) {
+ mv.put(score);
+ }
+ }
+ final double mean = mv.getMean();
+ final double var = mv.getSampleVariance();
+ k = (mean * mean) / var;
+ theta = var / mean;
+ atmean = GammaDistribution.regularizedGammaP(k, mean / theta);
+ // logger.warning("Mean:"+mean+" Var:"+var+" Theta: "+theta+" k: "+k+" valatmean"+atmean);
+ }
+
+ @Override
+ public <A> void prepare(A array, NumberArrayAdapter<?, A> adapter) {
+ MeanVariance mv = new MeanVariance();
+ final int size = adapter.size(array);
+ for (int i = 0; i < size; i++) {
+ double score = adapter.getDouble(array, i);
+ score = preScale(score);
+ if (!Double.isNaN(score) && !Double.isInfinite(score)) {
mv.put(score);
}
}
@@ -126,7 +146,7 @@ public class OutlierGammaScaling implements OutlierScalingFunction {
* @return Normalized score.
*/
protected double preScale(double score) {
- if(normalize) {
+ if (normalize) {
score = meta.normalizeScore(score);
}
return score;
@@ -156,7 +176,7 @@ public class OutlierGammaScaling implements OutlierScalingFunction {
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
Flag normalizeF = new Flag(NORMALIZE_ID);
- if(config.grab(normalizeF)) {
+ if (config.grab(normalizeF)) {
normalize = normalizeF.getValue();
}
}
@@ -166,4 +186,4 @@ public class OutlierGammaScaling implements OutlierScalingFunction {
return new OutlierGammaScaling(normalize);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierLinearScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierLinearScaling.java
index 8f008176..dfae1068 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierLinearScaling.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierLinearScaling.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -30,6 +30,7 @@ import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
import de.lmu.ifi.dbs.elki.math.MeanVariance;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GlobalParameterConstraint;
@@ -136,7 +137,7 @@ public class OutlierLinearScaling implements OutlierScalingFunction {
@Override
public double getScaled(double value) {
assert (factor != 0) : "prepare() was not run prior to using the scaling function.";
- if(value <= min) {
+ if (value <= min) {
return 0;
}
return Math.min(1, ((value - min) / factor));
@@ -144,53 +145,107 @@ public class OutlierLinearScaling implements OutlierScalingFunction {
@Override
public void prepare(OutlierResult or) {
- if(usemean) {
+ if (usemean) {
MeanVariance mv = new MeanVariance();
DoubleMinMax mm = (max == null) ? new DoubleMinMax() : null;
boolean skippedzeros = false;
Relation<Double> scores = or.getScores();
- for(DBIDIter id = scores.iterDBIDs(); id.valid(); id.advance()) {
+ for (DBIDIter id = scores.iterDBIDs(); id.valid(); id.advance()) {
double val = scores.get(id);
- if(nozeros && val == 0.0) {
+ if (nozeros && val == 0.0) {
skippedzeros = true;
continue;
}
- if(!Double.isNaN(val) && !Double.isInfinite(val)) {
+ if (!Double.isNaN(val) && !Double.isInfinite(val)) {
mv.put(val);
}
- if(max == null) {
+ if (max == null) {
mm.put(val);
}
}
- if(skippedzeros && mm.getMin() == mm.getMax()) {
+ if (skippedzeros && mm.getMin() == mm.getMax()) {
mm.put(0.0);
mv.put(0.0);
}
min = mv.getMean();
- if(max == null) {
+ if (max == null) {
max = mm.getMax();
}
- }
- else {
- if(min == null || max == null) {
+ } else {
+ if (min == null || max == null) {
boolean skippedzeros = false;
DoubleMinMax mm = new DoubleMinMax();
Relation<Double> scores = or.getScores();
- for(DBIDIter id = scores.iterDBIDs(); id.valid(); id.advance()) {
+ for (DBIDIter id = scores.iterDBIDs(); id.valid(); id.advance()) {
double val = scores.get(id);
- if(nozeros && val == 0.0) {
+ if (nozeros && val == 0.0) {
+ skippedzeros = true;
+ continue;
+ }
+ mm.put(val);
+ }
+ if (skippedzeros && mm.getMin() == mm.getMax()) {
+ mm.put(0.0);
+ }
+ if (min == null) {
+ min = mm.getMin();
+ }
+ if (max == null) {
+ max = mm.getMax();
+ }
+ }
+ }
+ factor = (max - min);
+ }
+
+ @Override
+ public <A> void prepare(A array, NumberArrayAdapter<?, A> adapter) {
+ if (usemean) {
+ MeanVariance mv = new MeanVariance();
+ DoubleMinMax mm = (max == null) ? new DoubleMinMax() : null;
+ boolean skippedzeros = false;
+ final int size = adapter.size(array);
+ for (int i = 0; i < size; i++) {
+ double val = adapter.getDouble(array, i);
+ if (nozeros && val == 0.0) {
+ skippedzeros = true;
+ continue;
+ }
+ if (!Double.isNaN(val) && !Double.isInfinite(val)) {
+ mv.put(val);
+ }
+ if (max == null) {
+ mm.put(val);
+ }
+ }
+ if (skippedzeros && mm.getMin() == mm.getMax()) {
+ mm.put(0.0);
+ mv.put(0.0);
+ }
+ min = mv.getMean();
+ if (max == null) {
+ max = mm.getMax();
+ }
+ } else {
+ if (min == null || max == null) {
+ boolean skippedzeros = false;
+ DoubleMinMax mm = new DoubleMinMax();
+ final int size = adapter.size(array);
+ for (int i = 0; i < size; i++) {
+ double val = adapter.getDouble(array, i);
+ if (nozeros && val == 0.0) {
skippedzeros = true;
continue;
}
mm.put(val);
}
- if(skippedzeros && mm.getMin() == mm.getMax()) {
+ if (skippedzeros && mm.getMin() == mm.getMax()) {
mm.put(0.0);
}
- if(min == null) {
+ if (min == null) {
min = mm.getMin();
}
- if(max == null) {
+ if (max == null) {
max = mm.getMax();
}
}
@@ -241,28 +296,28 @@ public class OutlierLinearScaling implements OutlierScalingFunction {
super.makeOptions(config);
DoubleParameter minP = new DoubleParameter(MIN_ID);
minP.setOptional(true);
- if(config.grab(minP)) {
+ if (config.grab(minP)) {
min = minP.getValue();
}
DoubleParameter maxP = new DoubleParameter(MAX_ID);
maxP.setOptional(true);
- if(config.grab(maxP)) {
+ if (config.grab(maxP)) {
max = maxP.getValue();
}
Flag meanF = new Flag(MEAN_ID);
- if(config.grab(meanF)) {
+ if (config.grab(meanF)) {
usemean = meanF.getValue();
}
Flag nozerosF = new Flag(NOZEROS_ID);
- if(config.grab(nozerosF)) {
+ if (config.grab(nozerosF)) {
nozeros = nozerosF.getValue();
}
// Use-Mean and Minimum value must not be set at the same time!
- ArrayList<Parameter<?>> minmean = new ArrayList<Parameter<?>>();
+ ArrayList<Parameter<?>> minmean = new ArrayList<>();
minmean.add(minP);
minmean.add(meanF);
GlobalParameterConstraint gpc = new OnlyOneIsAllowedToBeSetGlobalConstraint(minmean);
@@ -274,4 +329,4 @@ public class OutlierLinearScaling implements OutlierScalingFunction {
return new OutlierLinearScaling(min, max, usemean, nozeros);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierMinusLogScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierMinusLogScaling.java
index 45c6928b..f0e04913 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierMinusLogScaling.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierMinusLogScaling.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,6 +27,7 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
/**
@@ -79,13 +80,27 @@ public class OutlierMinusLogScaling implements OutlierScalingFunction {
public void prepare(OutlierResult or) {
DoubleMinMax mm = new DoubleMinMax();
Relation<Double> scores = or.getScores();
- for(DBIDIter id = scores.iterDBIDs(); id.valid(); id.advance()) {
+ for (DBIDIter id = scores.iterDBIDs(); id.valid(); id.advance()) {
double val = scores.get(id);
- if(!Double.isNaN(val) && !Double.isInfinite(val)) {
+ if (!Double.isNaN(val) && !Double.isInfinite(val)) {
mm.put(val);
}
}
max = mm.getMax();
mlogmax = -Math.log(mm.getMin() / max);
}
-} \ No newline at end of file
+
+ @Override
+ public <A> void prepare(A array, NumberArrayAdapter<?, A> adapter) {
+ DoubleMinMax mm = new DoubleMinMax();
+ final int size = adapter.size(array);
+ for (int i = 0; i < size; i++) {
+ double val = adapter.getDouble(array, i);
+ if (!Double.isNaN(val) && !Double.isInfinite(val)) {
+ mm.put(val);
+ }
+ }
+ max = mm.getMax();
+ mlogmax = -Math.log(mm.getMin() / max);
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierScalingFunction.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierScalingFunction.java
index ac774745..9de05e78 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierScalingFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierScalingFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,6 +24,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier;
*/
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
import de.lmu.ifi.dbs.elki.utilities.scaling.ScalingFunction;
/**
@@ -37,9 +38,22 @@ public interface OutlierScalingFunction extends ScalingFunction {
/**
* Prepare is called once for each data set, before getScaled() will be
* called. This function can be used to extract global parameters such as
- * means, minimums or maximums from the Database, Result or Annotation.
+ * means, minimums or maximums from the outlier scores.
*
* @param or Outlier result to use
*/
public void prepare(OutlierResult or);
+
+ /**
+ * Prepare is called once for each data set, before getScaled() will be
+ * called. This function can be used to extract global parameters such as
+ * means, minimums or maximums from the score array.
+ *
+ * The method using a full {@link OutlierResult} is preferred, as it will
+ * allow access to the metadata.
+ *
+ * @param array Data to process
+ * @param adapter Array adapter
+ */
+ public <A> void prepare(A array, NumberArrayAdapter<?, A> adapter);
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierSqrtScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierSqrtScaling.java
index 41a4d721..302602d4 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierSqrtScaling.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierSqrtScaling.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,6 +27,7 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
@@ -43,30 +44,14 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleParameter;
*/
public class OutlierSqrtScaling implements OutlierScalingFunction {
/**
- * Parameter to specify the fixed minimum to use.
- * <p>
- * Key: {@code -sqrtscale.min}
- * </p>
+ * Minimum and maximum values.
*/
- public static final OptionID MIN_ID = new OptionID("sqrtscale.min", "Fixed minimum to use in sqrt scaling.");
+ protected double min, max;
/**
- * Parameter to specify the fixed maximum to use.
- * <p>
- * Key: {@code -sqrtscale.max}
- * </p>
+ * Predefined minimum and maximum values.
*/
- public static final OptionID MAX_ID = new OptionID("sqrtscale.max", "Fixed maximum to use in sqrt scaling.");
-
- /**
- * Field storing the minimum value
- */
- protected Double min = null;
-
- /**
- * Field storing the Maximum value
- */
- protected Double max = null;
+ protected Double pmin = null, pmax = null;
/**
* Scaling factor
@@ -76,19 +61,19 @@ public class OutlierSqrtScaling implements OutlierScalingFunction {
/**
* Constructor.
*
- * @param min
- * @param max
+ * @param pmin Predefined minimum
+ * @param pmax Predefined maximum
*/
- public OutlierSqrtScaling(Double min, Double max) {
+ public OutlierSqrtScaling(Double pmin, Double pmax) {
super();
- this.min = min;
- this.max = max;
+ this.pmin = pmin;
+ this.pmax = pmax;
}
@Override
public double getScaled(double value) {
assert (factor != 0) : "prepare() was not run prior to using the scaling function.";
- if(value <= min) {
+ if (value <= min) {
return 0;
}
return Math.min(1, (Math.sqrt(value - min) / factor));
@@ -96,21 +81,34 @@ public class OutlierSqrtScaling implements OutlierScalingFunction {
@Override
public void prepare(OutlierResult or) {
- if(min == null || max == null) {
+ if (pmin == null || pmax == null) {
DoubleMinMax mm = new DoubleMinMax();
Relation<Double> scores = or.getScores();
- for(DBIDIter id = scores.iterDBIDs(); id.valid(); id.advance()) {
+ for (DBIDIter id = scores.iterDBIDs(); id.valid(); id.advance()) {
double val = scores.get(id);
- if(!Double.isNaN(val) && !Double.isInfinite(val)) {
+ if (!Double.isInfinite(val)) {
mm.put(val);
}
}
- if(min == null) {
- min = mm.getMin();
- }
- if(max == null) {
- max = mm.getMax();
+ min = (pmin == null) ? mm.getMin() : pmin;
+ max = (pmax == null) ? mm.getMax() : pmax;
+ }
+ factor = Math.sqrt(max - min);
+ }
+
+ @Override
+ public <A> void prepare(A array, NumberArrayAdapter<?, A> adapter) {
+ if (pmin == null || pmax == null) {
+ DoubleMinMax mm = new DoubleMinMax();
+ final int size = adapter.size(array);
+ for (int i = 0; i < size; i++) {
+ double val = adapter.getDouble(array, i);
+ if (!Double.isInfinite(val)) {
+ mm.put(val);
+ }
}
+ min = (pmin == null) ? mm.getMin() : pmin;
+ max = (pmax == null) ? mm.getMax() : pmax;
}
factor = Math.sqrt(max - min);
}
@@ -133,8 +131,30 @@ public class OutlierSqrtScaling implements OutlierScalingFunction {
* @apiviz.exclude
*/
public static class Parameterizer extends AbstractParameterizer {
+ /**
+ * Parameter to specify the fixed minimum to use.
+ * <p>
+ * Key: {@code -sqrtscale.min}
+ * </p>
+ */
+ public static final OptionID MIN_ID = new OptionID("sqrtscale.min", "Fixed minimum to use in sqrt scaling.");
+
+ /**
+ * Parameter to specify the fixed maximum to use.
+ * <p>
+ * Key: {@code -sqrtscale.max}
+ * </p>
+ */
+ public static final OptionID MAX_ID = new OptionID("sqrtscale.max", "Fixed maximum to use in sqrt scaling.");
+
+ /**
+ * Predefined minimum value.
+ */
protected double min;
+ /**
+ * Predefined maximum value.
+ */
protected double max;
@Override
@@ -142,12 +162,12 @@ public class OutlierSqrtScaling implements OutlierScalingFunction {
super.makeOptions(config);
DoubleParameter minP = new DoubleParameter(MIN_ID);
minP.setOptional(true);
- if(config.grab(minP)) {
+ if (config.grab(minP)) {
min = minP.getValue();
}
DoubleParameter maxP = new DoubleParameter(MAX_ID);
maxP.setOptional(true);
- if(config.grab(maxP)) {
+ if (config.grab(maxP)) {
max = maxP.getValue();
}
}
@@ -157,4 +177,4 @@ public class OutlierSqrtScaling implements OutlierScalingFunction {
return new OutlierSqrtScaling(min, max);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/RankingPseudoOutlierScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/RankingPseudoOutlierScaling.java
index 91f66587..505f2002 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/RankingPseudoOutlierScaling.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/RankingPseudoOutlierScaling.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,6 +29,8 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.result.outlier.InvertedOutlierScoreMeta;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayLikeUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
/**
@@ -69,6 +71,12 @@ public class RankingPseudoOutlierScaling implements OutlierScalingFunction {
// TODO: Inverted scores!
Arrays.sort(scores);
}
+
+ @Override
+ public <A> void prepare(A array, NumberArrayAdapter<?, A> adapter) {
+ scores = ArrayLikeUtil.toPrimitiveDoubleArray(array, adapter);
+ Arrays.sort(scores);
+ }
@Override
public double getMax() {
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/SigmoidOutlierScalingFunction.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/SigmoidOutlierScalingFunction.java
index 16115e92..34911169 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/SigmoidOutlierScalingFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/SigmoidOutlierScalingFunction.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,12 +26,14 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier;
import java.util.BitSet;
import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDArrayIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.math.MeanVariance;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
/**
@@ -46,7 +48,7 @@ public class SigmoidOutlierScalingFunction implements OutlierScalingFunction {
* The logger for this class.
*/
private static final Logging LOG = Logging.getLogger(SigmoidOutlierScalingFunction.class);
-
+
/**
* Sigmoid parameter
*/
@@ -62,30 +64,31 @@ public class SigmoidOutlierScalingFunction implements OutlierScalingFunction {
// Initial parameters - are these defaults sounds?
MeanVariance mv = new MeanVariance();
Relation<Double> scores = or.getScores();
- for(DBIDIter id = scores.iterDBIDs(); id.valid(); id.advance()) {
+ for (DBIDIter id = scores.iterDBIDs(); id.valid(); id.advance()) {
double val = scores.get(id);
mv.put(val);
}
double a = 1.0;
- double b = - mv.getMean();
+ double b = -mv.getMean();
int iter = 0;
ArrayDBIDs ids = DBIDUtil.ensureArray(or.getScores().getDBIDs());
+ DBIDArrayIter it = ids.iter();
BitSet t = new BitSet(ids.size());
boolean changing = true;
- while(changing) {
+ while (changing) {
changing = false;
// E-Step
- for(int i = 0; i < ids.size(); i++) {
- double val = or.getScores().get(ids.get(i));
+ it.seek(0);
+ for (int i = 0; i < ids.size(); i++, it.advance()) {
+ double val = or.getScores().get(it);
double targ = a * val + b;
- if(targ > 0) {
- if (!t.get(i)) {
+ if (targ > 0) {
+ if (!t.get(i)) {
t.set(i);
changing = true;
}
- }
- else {
+ } else {
if (t.get(i)) {
t.clear(i);
changing = true;
@@ -95,7 +98,7 @@ public class SigmoidOutlierScalingFunction implements OutlierScalingFunction {
if (!changing) {
break;
}
- //logger.debugFine("Number of outliers in sigmoid: " + t.cardinality());
+ // logger.debugFine("Number of outliers in sigmoid: " + t.cardinality());
// M-Step
// Implementation based on:<br />
// H.-T. Lin, C.-J. Lin, R. C. Weng:<br />
@@ -107,14 +110,74 @@ public class SigmoidOutlierScalingFunction implements OutlierScalingFunction {
}
iter++;
- if(iter > 100) {
+ if (iter > 100) {
+ LOG.warning("Max iterations met in sigmoid fitting.");
+ break;
+ }
+ }
+ Afinal = a;
+ Bfinal = b;
+ LOG.debugFine("A = " + Afinal + " B = " + Bfinal);
+ }
+
+ @Override
+ public <A> void prepare(A array, NumberArrayAdapter<?, A> adapter) {
+ // Initial parameters - are these defaults sounds?
+ MeanVariance mv = new MeanVariance();
+ final int size = adapter.size(array);
+ for (int i = 0; i < size; i++) {
+ double val = adapter.getDouble(array, i);
+ if (!Double.isInfinite(val)) {
+ mv.put(val);
+ }
+ }
+ double a = 1.0;
+ double b = -mv.getMean();
+ int iter = 0;
+
+ BitSet t = new BitSet(size);
+ boolean changing = true;
+ while (changing) {
+ changing = false;
+ // E-Step
+ for (int i = 0; i < size; i++) {
+ double val = adapter.getDouble(array, i);
+ double targ = a * val + b;
+ if (targ > 0) {
+ if (!t.get(i)) {
+ t.set(i);
+ changing = true;
+ }
+ } else {
+ if (t.get(i)) {
+ t.clear(i);
+ changing = true;
+ }
+ }
+ }
+ if (!changing) {
+ break;
+ }
+ // logger.debugFine("Number of outliers in sigmoid: " + t.cardinality());
+ // M-Step
+ // Implementation based on:<br />
+ // H.-T. Lin, C.-J. Lin, R. C. Weng:<br />
+ // A Note on Platt’s Probabilistic Outputs for Support Vector Machines
+ {
+ double[] newab = MStepLevenbergMarquardt(a, b, t, array, adapter);
+ a = newab[0];
+ b = newab[1];
+ }
+
+ iter++;
+ if (iter > 100) {
LOG.warning("Max iterations met in sigmoid fitting.");
break;
}
}
Afinal = a;
Bfinal = b;
- LOG.debugFine("A = "+Afinal+" B = "+Bfinal);
+ LOG.debugFine("A = " + Afinal + " B = " + Bfinal);
}
/**
@@ -136,6 +199,7 @@ public class SigmoidOutlierScalingFunction implements OutlierScalingFunction {
private final double[] MStepLevenbergMarquardt(double a, double b, ArrayDBIDs ids, BitSet t, Relation<Double> scores) {
final int prior1 = t.cardinality();
final int prior0 = ids.size() - prior1;
+ DBIDArrayIter iter = ids.iter();
final int maxiter = 10;
final double minstep = 1e-8;
@@ -147,38 +211,38 @@ public class SigmoidOutlierScalingFunction implements OutlierScalingFunction {
// t[i] := t.get(i) ? hiTarget : loTarget.
// Reset, or continue with previous values?
- //a = 0.0;
- //b = Math.log((prior0 + 1.0) / (prior1 + 1.0));
+ // a = 0.0;
+ // b = Math.log((prior0 + 1.0) / (prior1 + 1.0));
double fval = 0.0;
- for(int i = 0; i < ids.size(); i++) {
- final double val = scores.get(ids.get(i));
+ iter.seek(0);
+ for (int i = 0; i < ids.size(); i++, iter.advance()) {
+ final double val = scores.get(iter);
final double fApB = val * a + b;
final double ti = t.get(i) ? hiTarget : loTarget;
- if(fApB >= 0) {
+ if (fApB >= 0) {
fval += ti * fApB + Math.log(1 + Math.exp(-fApB));
- }
- else {
+ } else {
fval += (ti - 1) * fApB + Math.log(1 + Math.exp(fApB));
}
}
- for(int it = 0; it < maxiter; it++) {
- //logger.debugFinest("Iter: " + it + "a: " + a + " b: " + b);
+ for (int it = 0; it < maxiter; it++) {
+ // logger.debugFinest("Iter: " + it + "a: " + a + " b: " + b);
// Update Gradient and Hessian (use H’ = H + sigma I)
double h11 = sigma;
double h22 = sigma;
double h21 = 0.0;
double g1 = 0.0;
double g2 = 0.0;
- for(int i = 0; i < ids.size(); i++) {
- final double val = scores.get(ids.get(i));
+ iter.seek(0);
+ for (int i = 0; i < ids.size(); i++, iter.advance()) {
+ final double val = scores.get(iter);
final double fApB = val * a + b;
final double p;
final double q;
- if(fApB >= 0) {
+ if (fApB >= 0) {
p = Math.exp(-fApB) / (1.0 + Math.exp(-fApB));
q = 1.0 / (1.0 + Math.exp(-fApB));
- }
- else {
+ } else {
p = 1.0 / (1.0 + Math.exp(fApB));
q = Math.exp(fApB) / (1.0 + Math.exp(fApB));
}
@@ -191,7 +255,7 @@ public class SigmoidOutlierScalingFunction implements OutlierScalingFunction {
g2 += d1;
}
// Stop condition
- if(Math.abs(g1) < 1e-5 && Math.abs(g2) < 1e-5) {
+ if (Math.abs(g1) < 1e-5 && Math.abs(g2) < 1e-5) {
break;
}
// Compute modified Newton directions
@@ -200,36 +264,152 @@ public class SigmoidOutlierScalingFunction implements OutlierScalingFunction {
final double dB = -(-h21 * g1 + h11 * g2) / det;
final double gd = g1 * dA + g2 * dB;
double stepsize = 1.0;
- while(stepsize >= minstep) { // Line search
+ while (stepsize >= minstep) { // Line search
final double newA = a + stepsize * dA;
final double newB = b + stepsize * dB;
double newf = 0.0;
- for(int i = 0; i < ids.size(); i++) {
- final double val = scores.get(ids.get(i));
+ iter.seek(0);
+ for (int i = 0; i < ids.size(); i++, iter.advance()) {
+ final double val = scores.get(iter);
final double fApB = val * newA + newB;
final double ti = t.get(i) ? hiTarget : loTarget;
- if(fApB >= 0) {
+ if (fApB >= 0) {
newf += ti * fApB + Math.log(1 + Math.exp(-fApB));
- }
- else {
+ } else {
newf += (ti - 1) * fApB + Math.log(1 + Math.exp(fApB));
}
}
- if(newf < fval + 0.0001 * stepsize * gd) {
+ if (newf < fval + 0.0001 * stepsize * gd) {
a = newA;
b = newB;
fval = newf;
break; // Sufficient decrease satisfied
+ } else {
+ stepsize /= 2.0;
+ }
+ if (stepsize < minstep) {
+ LOG.debug("Minstep hit.");
+ break;
+ }
+ }
+ if (it + 1 >= maxiter) {
+ LOG.debug("Maximum iterations hit.");
+ break;
+ }
+ }
+ return new double[] { a, b };
+ }
+
+ /**
+ * M-Step using a modified Levenberg-Marquardt method.
+ *
+ * <p>
+ * Implementation based on:<br />
+ * H.-T. Lin, C.-J. Lin, R. C. Weng:<br />
+ * A Note on Platt’s Probabilistic Outputs for Support Vector Machines
+ * </p>
+ *
+ * @param a A parameter
+ * @param b B parameter
+ * @param t Bitset containing the assignment
+ * @param array Score array
+ * @param adapter Array adapter
+ * @return new values for A and B.
+ */
+ private final <A> double[] MStepLevenbergMarquardt(double a, double b, BitSet t, A array, NumberArrayAdapter<?, A> adapter) {
+ final int size = adapter.size(array);
+ final int prior1 = t.cardinality();
+ final int prior0 = size - prior1;
+
+ final int maxiter = 10;
+ final double minstep = 1e-8;
+ final double sigma = 1e-12;
+ // target value for "set" objects
+ final double loTarget = (prior1 + 1.0) / (prior1 + 2.0);
+ // target value for "unset" objects
+ final double hiTarget = 1.0 / (prior0 + 2.0);
+ // t[i] := t.get(i) ? hiTarget : loTarget.
+
+ // Reset, or continue with previous values?
+ // a = 0.0;
+ // b = Math.log((prior0 + 1.0) / (prior1 + 1.0));
+ double fval = 0.0;
+ for (int i = 0; i < size; i++) {
+ final double val = adapter.getDouble(array, i);
+ final double fApB = val * a + b;
+ final double ti = t.get(i) ? hiTarget : loTarget;
+ if (fApB >= 0) {
+ fval += ti * fApB + Math.log(1 + Math.exp(-fApB));
+ } else {
+ fval += (ti - 1) * fApB + Math.log(1 + Math.exp(fApB));
+ }
+ }
+ for (int it = 0; it < maxiter; it++) {
+ // logger.debugFinest("Iter: " + it + "a: " + a + " b: " + b);
+ // Update Gradient and Hessian (use H’ = H + sigma I)
+ double h11 = sigma;
+ double h22 = sigma;
+ double h21 = 0.0;
+ double g1 = 0.0;
+ double g2 = 0.0;
+ for (int i = 0; i < size; i++) {
+ final double val = adapter.getDouble(array, i);
+ final double fApB = val * a + b;
+ final double p;
+ final double q;
+ if (fApB >= 0) {
+ p = Math.exp(-fApB) / (1.0 + Math.exp(-fApB));
+ q = 1.0 / (1.0 + Math.exp(-fApB));
+ } else {
+ p = 1.0 / (1.0 + Math.exp(fApB));
+ q = Math.exp(fApB) / (1.0 + Math.exp(fApB));
+ }
+ final double d2 = p * q;
+ h11 += val * val * d2;
+ h22 += d2;
+ h21 += val * d2;
+ final double d1 = (t.get(i) ? hiTarget : loTarget) - p;
+ g1 += val * d1;
+ g2 += d1;
+ }
+ // Stop condition
+ if (Math.abs(g1) < 1e-5 && Math.abs(g2) < 1e-5) {
+ break;
+ }
+ // Compute modified Newton directions
+ final double det = h11 * h22 - h21 * h21;
+ final double dA = -(h22 * g1 - h21 * g2) / det;
+ final double dB = -(-h21 * g1 + h11 * g2) / det;
+ final double gd = g1 * dA + g2 * dB;
+ double stepsize = 1.0;
+ while (stepsize >= minstep) { // Line search
+ final double newA = a + stepsize * dA;
+ final double newB = b + stepsize * dB;
+ double newf = 0.0;
+ for (int i = 0; i < size; i++) {
+ final double val = adapter.getDouble(array, i);
+ final double fApB = val * newA + newB;
+ final double ti = t.get(i) ? hiTarget : loTarget;
+ if (fApB >= 0) {
+ newf += ti * fApB + Math.log(1 + Math.exp(-fApB));
+ } else {
+ newf += (ti - 1) * fApB + Math.log(1 + Math.exp(fApB));
+ }
}
- else {
+ if (newf < fval + 0.0001 * stepsize * gd) {
+ a = newA;
+ b = newB;
+ fval = newf;
+ break; // Sufficient decrease satisfied
+ } else {
stepsize /= 2.0;
}
- if(stepsize < minstep) {
+ if (stepsize < minstep) {
LOG.debug("Minstep hit.");
break;
}
}
- if(it + 1 >= maxiter) {
+ if (it + 1 >= maxiter) {
LOG.debug("Maximum iterations hit.");
break;
}
@@ -251,4 +431,4 @@ public class SigmoidOutlierScalingFunction implements OutlierScalingFunction {
public double getScaled(double value) {
return 1.0 / (1 + Math.exp(-Afinal * value - Bfinal));
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/SqrtStandardDeviationScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/SqrtStandardDeviationScaling.java
index 6c38c781..2110570e 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/SqrtStandardDeviationScaling.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/SqrtStandardDeviationScaling.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,11 +25,12 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
-import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
import de.lmu.ifi.dbs.elki.math.MathUtil;
-import de.lmu.ifi.dbs.elki.math.MeanVariance;
+import de.lmu.ifi.dbs.elki.math.Mean;
+import de.lmu.ifi.dbs.elki.math.MeanVarianceMinMax;
import de.lmu.ifi.dbs.elki.math.statistics.distribution.NormalDistribution;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
@@ -53,71 +54,42 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleParameter;
@Reference(authors = "H.-P. Kriegel, P. Kröger, E. Schubert, A. Zimek", title = "Interpreting and Unifying Outlier Scores", booktitle = "Proc. 11th SIAM International Conference on Data Mining (SDM), Mesa, AZ, 2011", url = "http://siam.omnibooksonline.com/2011datamining/data/papers/018.pdf")
public class SqrtStandardDeviationScaling implements OutlierScalingFunction {
/**
- * Parameter to specify the fixed minimum to use.
- * <p>
- * Key: {@code -sqrtstddevscale.min}
- * </p>
+ * Effective parameters.
*/
- public static final OptionID MIN_ID = new OptionID("sqrtstddevscale.min", "Fixed minimum to use in sqrt scaling.");
+ double min, mean, factor;
/**
- * Parameter to specify a fixed mean to use.
- * <p>
- * Key: {@code -sqrtstddevscale.mean}
- * </p>
+ * Predefined parameters.
*/
- public static final OptionID MEAN_ID = new OptionID("sqrtstddevscale.mean", "Fixed mean to use in standard deviation scaling.");
+ Double pmin = null, pmean = null;
/**
- * Parameter to specify the lambda value
- * <p>
- * Key: {@code -sqrtstddevscale.lambda}
- * </p>
+ * Predefined lambda scaling factor.
*/
- public static final OptionID LAMBDA_ID = new OptionID("sqrtstddevscale.lambda", "Significance level to use for error function.");
-
- /**
- * Field storing the lambda value
- */
- protected Double lambda = null;
-
- /**
- * Min to use
- */
- Double min = null;
-
- /**
- * Mean to use
- */
- Double mean = null;
-
- /**
- * Scaling factor to use (usually: Lambda * Stddev * Sqrt(2))
- */
- double factor;
+ double plambda;
/**
* Constructor.
*
- * @param min
- * @param mean
- * @param lambda
+ * @param pmin Predefined minimum
+ * @param pmean Predefined mean
+ * @param plambda Lambda parameter
*/
- public SqrtStandardDeviationScaling(Double min, Double mean, Double lambda) {
+ public SqrtStandardDeviationScaling(Double pmin, Double pmean, double plambda) {
super();
- this.min = min;
- this.mean = mean;
- this.lambda = lambda;
+ this.pmin = pmin;
+ this.pmean = pmean;
+ this.plambda = plambda;
}
@Override
public double getScaled(double value) {
assert (factor != 0) : "prepare() was not run prior to using the scaling function.";
- if(value <= min) {
+ if (value <= min) {
return 0;
}
value = (value <= min) ? 0 : Math.sqrt(value - min);
- if(value <= mean) {
+ if (value <= mean) {
return 0;
}
return Math.max(0, NormalDistribution.erf((value - mean) / factor));
@@ -125,39 +97,61 @@ public class SqrtStandardDeviationScaling implements OutlierScalingFunction {
@Override
public void prepare(OutlierResult or) {
- if(min == null) {
- DoubleMinMax mm = new DoubleMinMax();
- Relation<Double> scores = or.getScores();
- for(DBIDIter id = scores.iterDBIDs(); id.valid(); id.advance()) {
- double val = scores.get(id);
- if(!Double.isNaN(val) && !Double.isInfinite(val)) {
- mm.put(val);
- }
- }
- min = mm.getMin();
- }
- if(mean == null) {
- MeanVariance mv = new MeanVariance();
+ if (pmean == null) {
+ MeanVarianceMinMax mv = new MeanVarianceMinMax();
Relation<Double> scores = or.getScores();
- for(DBIDIter id = scores.iterDBIDs(); id.valid(); id.advance()) {
+ for (DBIDIter id = scores.iterDBIDs(); id.valid(); id.advance()) {
double val = scores.get(id);
val = (val <= min) ? 0 : Math.sqrt(val - min);
mv.put(val);
}
+ min = (pmin == null) ? mv.getMin() : pmin;
mean = mv.getMean();
- factor = lambda * mv.getSampleStddev() * MathUtil.SQRT2;
- }
- else {
+ factor = plambda * mv.getSampleStddev() * MathUtil.SQRT2;
+ } else {
+ mean = pmean;
double sqsum = 0;
int cnt = 0;
Relation<Double> scores = or.getScores();
- for(DBIDIter id = scores.iterDBIDs(); id.valid(); id.advance()) {
+ double mm = Double.POSITIVE_INFINITY;
+ for (DBIDIter id = scores.iterDBIDs(); id.valid(); id.advance()) {
double val = scores.get(id);
+ mm = Math.min(mm, val);
val = (val <= min) ? 0 : Math.sqrt(val - min);
sqsum += (val - mean) * (val - mean);
cnt += 1;
}
- factor = lambda * Math.sqrt(sqsum / cnt) * MathUtil.SQRT2;
+ min = (pmin == null) ? mm : pmin;
+ factor = plambda * Math.sqrt(sqsum / cnt) * MathUtil.SQRT2;
+ }
+ }
+
+ @Override
+ public <A> void prepare(A array, NumberArrayAdapter<?, A> adapter) {
+ if (pmean == null) {
+ MeanVarianceMinMax mv = new MeanVarianceMinMax();
+ final int size = adapter.size(array);
+ for (int i = 0; i < size; i++) {
+ double val = adapter.getDouble(array, i);
+ val = (val <= min) ? 0 : Math.sqrt(val - min);
+ mv.put(val);
+ }
+ min = (pmin == null) ? mv.getMin() : pmin;
+ mean = mv.getMean();
+ factor = plambda * mv.getSampleStddev() * MathUtil.SQRT2;
+ } else {
+ mean = pmean;
+ Mean sqsum = new Mean();
+ double mm = Double.POSITIVE_INFINITY;
+ final int size = adapter.size(array);
+ for (int i = 0; i < size; i++) {
+ double val = adapter.getDouble(array, i);
+ mm = Math.min(mm, val);
+ val = (val <= min) ? 0 : Math.sqrt(val - min);
+ sqsum.put((val - mean) * (val - mean));
+ }
+ min = (pmin == null) ? mm : pmin;
+ factor = plambda * Math.sqrt(sqsum.getMean()) * MathUtil.SQRT2;
}
}
@@ -179,30 +173,54 @@ public class SqrtStandardDeviationScaling implements OutlierScalingFunction {
* @apiviz.exclude
*/
public static class Parameterizer extends AbstractParameterizer {
+ /**
+ * Parameter to specify the fixed minimum to use.
+ * <p>
+ * Key: {@code -sqrtstddevscale.min}
+ * </p>
+ */
+ public static final OptionID MIN_ID = new OptionID("sqrtstddevscale.min", "Fixed minimum to use in sqrt scaling.");
+
+ /**
+ * Parameter to specify a fixed mean to use.
+ * <p>
+ * Key: {@code -sqrtstddevscale.mean}
+ * </p>
+ */
+ public static final OptionID MEAN_ID = new OptionID("sqrtstddevscale.mean", "Fixed mean to use in standard deviation scaling.");
+
+ /**
+ * Parameter to specify the lambda value
+ * <p>
+ * Key: {@code -sqrtstddevscale.lambda}
+ * </p>
+ */
+ public static final OptionID LAMBDA_ID = new OptionID("sqrtstddevscale.lambda", "Significance level to use for error function.");
+
protected Double min = null;
protected Double mean = null;
- protected Double lambda = null;
+ protected double lambda;
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
DoubleParameter minP = new DoubleParameter(MIN_ID);
minP.setOptional(true);
- if(config.grab(minP)) {
- min = minP.getValue();
+ if (config.grab(minP)) {
+ min = minP.doubleValue();
}
DoubleParameter meanP = new DoubleParameter(MEAN_ID);
meanP.setOptional(true);
- if(config.grab(meanP)) {
- mean = meanP.getValue();
+ if (config.grab(meanP)) {
+ mean = meanP.doubleValue();
}
DoubleParameter lambdaP = new DoubleParameter(LAMBDA_ID, 3.0);
- if(config.grab(lambdaP)) {
- lambda = lambdaP.getValue();
+ if (config.grab(lambdaP)) {
+ lambda = lambdaP.doubleValue();
}
}
@@ -211,4 +229,4 @@ public class SqrtStandardDeviationScaling implements OutlierScalingFunction {
return new SqrtStandardDeviationScaling(min, mean, lambda);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/StandardDeviationScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/StandardDeviationScaling.java
index c8ec0905..b0040571 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/StandardDeviationScaling.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/StandardDeviationScaling.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -30,6 +30,7 @@ import de.lmu.ifi.dbs.elki.math.Mean;
import de.lmu.ifi.dbs.elki.math.MeanVariance;
import de.lmu.ifi.dbs.elki.math.statistics.distribution.NormalDistribution;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
@@ -45,27 +46,18 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleParameter;
* Where mean can be fixed to a given value, and stddev is then computed against
* this mean.
*
+ * Reference:
+ * <p>
+ * H.-P. Kriegel, P. Kröger, E. Schubert, A. Zimek<br />
+ * Interpreting and Unifying Outlier Scores<br />
+ * Proc. 11th SIAM International Conference on Data Mining (SDM), Mesa, AZ, 2011
+ * </p>
+ *
* @author Erich Schubert
*/
-@Reference(authors="H.-P. Kriegel, P. Kröger, E. Schubert, A. Zimek", title="Interpreting and Unifying Outlier Scores", booktitle="Proc. 11th SIAM International Conference on Data Mining (SDM), Mesa, AZ, 2011", url="http://siam.omnibooksonline.com/2011datamining/data/papers/018.pdf")
+@Reference(authors = "H.-P. Kriegel, P. Kröger, E. Schubert, A. Zimek", title = "Interpreting and Unifying Outlier Scores", booktitle = "Proc. 11th SIAM International Conference on Data Mining (SDM), Mesa, AZ, 2011", url = "http://siam.omnibooksonline.com/2011datamining/data/papers/018.pdf")
public class StandardDeviationScaling implements OutlierScalingFunction {
/**
- * Parameter to specify a fixed mean to use.
- * <p>
- * Key: {@code -stddevscale.mean}
- * </p>
- */
- public static final OptionID MEAN_ID = new OptionID("stddevscale.mean", "Fixed mean to use in standard deviation scaling.");
-
- /**
- * Parameter to specify the lambda value
- * <p>
- * Key: {@code -stddevscale.lambda}
- * </p>
- */
- public static final OptionID LAMBDA_ID = new OptionID("stddevscale.lambda", "Significance level to use for error function.");
-
- /**
* Field storing the fixed mean to use
*/
protected Double fixedmean = null;
@@ -73,7 +65,7 @@ public class StandardDeviationScaling implements OutlierScalingFunction {
/**
* Field storing the lambda value
*/
- protected Double lambda = null;
+ protected double lambda;
/**
* Mean to use
@@ -88,10 +80,10 @@ public class StandardDeviationScaling implements OutlierScalingFunction {
/**
* Constructor.
*
- * @param fixedmean
- * @param lambda
+ * @param fixedmean Fixed mean
+ * @param lambda Scaling factor lambda
*/
- public StandardDeviationScaling(Double fixedmean, Double lambda) {
+ public StandardDeviationScaling(Double fixedmean, double lambda) {
super();
this.fixedmean = fixedmean;
this.lambda = lambda;
@@ -107,7 +99,7 @@ public class StandardDeviationScaling implements OutlierScalingFunction {
@Override
public double getScaled(double value) {
assert (factor != 0) : "prepare() was not run prior to using the scaling function.";
- if(value <= mean) {
+ if (value <= mean) {
return 0;
}
return Math.max(0, NormalDistribution.erf((value - mean) / factor));
@@ -115,12 +107,12 @@ public class StandardDeviationScaling implements OutlierScalingFunction {
@Override
public void prepare(OutlierResult or) {
- if(fixedmean == null) {
+ if (fixedmean == null) {
MeanVariance mv = new MeanVariance();
Relation<Double> scores = or.getScores();
- for(DBIDIter id = scores.iterDBIDs(); id.valid(); id.advance()) {
+ for (DBIDIter id = scores.iterDBIDs(); id.valid(); id.advance()) {
double val = scores.get(id);
- if(!Double.isNaN(val) && !Double.isInfinite(val)) {
+ if (!Double.isNaN(val) && !Double.isInfinite(val)) {
mv.put(val);
}
}
@@ -129,14 +121,46 @@ public class StandardDeviationScaling implements OutlierScalingFunction {
if (factor == 0.0) {
factor = Double.MIN_NORMAL;
}
- }
- else {
+ } else {
mean = fixedmean;
Mean sqsum = new Mean();
Relation<Double> scores = or.getScores();
- for(DBIDIter id = scores.iterDBIDs(); id.valid(); id.advance()) {
+ for (DBIDIter id = scores.iterDBIDs(); id.valid(); id.advance()) {
double val = scores.get(id);
- if(!Double.isNaN(val) && !Double.isInfinite(val)) {
+ if (!Double.isNaN(val) && !Double.isInfinite(val)) {
+ sqsum.put((val - mean) * (val - mean));
+ }
+ }
+ factor = lambda * Math.sqrt(sqsum.getMean()) * MathUtil.SQRT2;
+ if (factor == 0.0) {
+ factor = Double.MIN_NORMAL;
+ }
+ }
+ }
+
+ @Override
+ public <A> void prepare(A array, NumberArrayAdapter<?, A> adapter) {
+ if (fixedmean == null) {
+ MeanVariance mv = new MeanVariance();
+ final int size = adapter.size(array);
+ for (int i = 0; i < size; i++) {
+ double val = adapter.getDouble(array, i);
+ if (!Double.isInfinite(val)) {
+ mv.put(val);
+ }
+ }
+ mean = mv.getMean();
+ factor = lambda * mv.getSampleStddev() * MathUtil.SQRT2;
+ if (factor == 0.0) {
+ factor = Double.MIN_NORMAL;
+ }
+ } else {
+ mean = fixedmean;
+ Mean sqsum = new Mean();
+ final int size = adapter.size(array);
+ for (int i = 0; i < size; i++) {
+ double val = adapter.getDouble(array, i);
+ if (!Double.isInfinite(val)) {
sqsum.put((val - mean) * (val - mean));
}
}
@@ -165,20 +189,36 @@ public class StandardDeviationScaling implements OutlierScalingFunction {
* @apiviz.exclude
*/
public static class Parameterizer extends AbstractParameterizer {
+ /**
+ * Parameter to specify a fixed mean to use.
+ * <p>
+ * Key: {@code -stddevscale.mean}
+ * </p>
+ */
+ public static final OptionID MEAN_ID = new OptionID("stddevscale.mean", "Fixed mean to use in standard deviation scaling.");
+
+ /**
+ * Parameter to specify the lambda value
+ * <p>
+ * Key: {@code -stddevscale.lambda}
+ * </p>
+ */
+ public static final OptionID LAMBDA_ID = new OptionID("stddevscale.lambda", "Significance level to use for error function.");
+
protected Double fixedmean = null;
- protected Double lambda = null;
+ protected double lambda;
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
DoubleParameter meanP = new DoubleParameter(MEAN_ID);
meanP.setOptional(true);
- if(config.grab(meanP)) {
+ if (config.grab(meanP)) {
fixedmean = meanP.getValue();
}
DoubleParameter lambdaP = new DoubleParameter(LAMBDA_ID, 3.0);
- if(config.grab(lambdaP)) {
+ if (config.grab(lambdaP)) {
lambda = lambdaP.getValue();
}
}
@@ -188,4 +228,4 @@ public class StandardDeviationScaling implements OutlierScalingFunction {
return new StandardDeviationScaling(fixedmean, lambda);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/TopKOutlierScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/TopKOutlierScaling.java
index f8609f3b..25103dbc 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/TopKOutlierScaling.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/TopKOutlierScaling.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,6 +26,9 @@ package de.lmu.ifi.dbs.elki.utilities.scaling.outlier;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.QuickSelect;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayLikeUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
@@ -94,29 +97,44 @@ public class TopKOutlierScaling implements OutlierScalingFunction {
@Override
public void prepare(OutlierResult or) {
- if(k <= 0) {
+ if (k <= 0) {
LoggingUtil.warning("No k configured for Top-k outlier scaling!");
}
DBIDIter order = or.getOrdering().iter(or.getOrdering().getDBIDs()).iter();
- for(int i = 0; i < k && order.valid(); i++, order.advance()) {
+ for (int i = 0; i < k && order.valid(); i++, order.advance()) {
cutoff = or.getScores().get(order);
}
max = or.getOutlierMeta().getActualMaximum();
ground = or.getOutlierMeta().getTheoreticalBaseline();
- if(Double.isInfinite(ground) || Double.isNaN(ground)) {
+ if (Double.isInfinite(ground) || Double.isNaN(ground)) {
ground = or.getOutlierMeta().getTheoreticalMinimum();
}
- if(Double.isInfinite(ground) || Double.isNaN(ground)) {
+ if (Double.isInfinite(ground) || Double.isNaN(ground)) {
ground = or.getOutlierMeta().getActualMinimum();
}
- if(Double.isInfinite(ground) || Double.isNaN(ground)) {
+ if (Double.isInfinite(ground) || Double.isNaN(ground)) {
ground = Math.min(0.0, cutoff);
}
}
@Override
+ public <A> void prepare(A array, NumberArrayAdapter<?, A> adapter) {
+ if (k <= 0) {
+ LoggingUtil.warning("No k configured for Top-k outlier scaling!");
+ }
+ double[] scores = ArrayLikeUtil.toPrimitiveDoubleArray(array, adapter);
+ QuickSelect.quickSelect(scores, k);
+ cutoff = scores[k - 1];
+ max = Double.NEGATIVE_INFINITY;
+ for (double v : scores) {
+ max = Math.max(max, v);
+ }
+ ground = Math.min(0.0, cutoff);
+ }
+
+ @Override
public double getMax() {
- if(binary) {
+ if (binary) {
return 1.0;
}
return max;
@@ -124,7 +142,7 @@ public class TopKOutlierScaling implements OutlierScalingFunction {
@Override
public double getMin() {
- if(binary) {
+ if (binary) {
return 0.0;
}
return ground;
@@ -132,19 +150,16 @@ public class TopKOutlierScaling implements OutlierScalingFunction {
@Override
public double getScaled(double value) {
- if(binary) {
- if(value >= cutoff) {
+ if (binary) {
+ if (value >= cutoff) {
return 1;
- }
- else {
+ } else {
return 0;
}
- }
- else {
- if(value >= cutoff) {
+ } else {
+ if (value >= cutoff) {
return (value - ground) / (max - ground);
- }
- else {
+ } else {
return 0.0;
}
}
@@ -167,12 +182,12 @@ public class TopKOutlierScaling implements OutlierScalingFunction {
super.makeOptions(config);
IntParameter kP = new IntParameter(K_ID);
kP.addConstraint(new GreaterConstraint(1));
- if(config.grab(kP)) {
+ if (config.grab(kP)) {
k = kP.intValue();
}
Flag binaryF = new Flag(BINARY_ID);
- if(config.grab(binaryF)) {
+ if (config.grab(binaryF)) {
binary = binaryF.isTrue();
}
}
@@ -182,4 +197,4 @@ public class TopKOutlierScaling implements OutlierScalingFunction {
return new TopKOutlierScaling(k, binary);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/package-info.java
index c2adba6b..a34aac08 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/scaling/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/package-info.java
index 430f1bf7..633aa65a 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/scaling/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/scaling/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/xml/DOMCloner.java b/src/de/lmu/ifi/dbs/elki/utilities/xml/DOMCloner.java
index dc3b48a8..44116dfe 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/xml/DOMCloner.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/xml/DOMCloner.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.xml;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/xml/HTMLUtil.java b/src/de/lmu/ifi/dbs/elki/utilities/xml/HTMLUtil.java
index 6c65c7f9..a68631d5 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/xml/HTMLUtil.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/xml/HTMLUtil.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.xml;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/xml/XMLNodeIterator.java b/src/de/lmu/ifi/dbs/elki/utilities/xml/XMLNodeIterator.java
index a5b7cfa6..c1decfe1 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/xml/XMLNodeIterator.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/xml/XMLNodeIterator.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.xml;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/xml/XMLNodeListIterator.java b/src/de/lmu/ifi/dbs/elki/utilities/xml/XMLNodeListIterator.java
index b413d1df..1fb39663 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/xml/XMLNodeListIterator.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/xml/XMLNodeListIterator.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.xml;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/xml/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/xml/package-info.java
index 9b961687..8f6d8a04 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/xml/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/xml/package-info.java
@@ -6,7 +6,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/ExportVisualizations.java b/src/de/lmu/ifi/dbs/elki/visualization/ExportVisualizations.java
index f0a26325..4daf5246 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/ExportVisualizations.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/ExportVisualizations.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -36,6 +36,7 @@ import de.lmu.ifi.dbs.elki.result.Result;
import de.lmu.ifi.dbs.elki.result.ResultHandler;
import de.lmu.ifi.dbs.elki.result.ResultHierarchy;
import de.lmu.ifi.dbs.elki.result.ResultUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.Hierarchy;
import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
@@ -160,8 +161,8 @@ public class ExportVisualizations implements ResultHandler {
ArrayList<VisualizationTask> tasks = ResultUtil.filterResults(baseResult, VisualizationTask.class);
for (VisualizationTask task : tasks) {
boolean isprojected = false;
- for (Result parent : hier.getParents(task)) {
- if (parent instanceof Projector) {
+ for (Hierarchy.Iter<Result> iter = hier.iterParents(task); iter.valid(); iter.advance()) {
+ if (iter.get() instanceof Projector) {
isprojected = true;
break;
}
@@ -193,7 +194,7 @@ public class ExportVisualizations implements ResultHandler {
svgp.getRoot().setAttribute(SVGConstants.SVG_HEIGHT_ATTRIBUTE, (20 / ratio) + "cm");
svgp.getRoot().setAttribute(SVGConstants.SVG_VIEW_BOX_ATTRIBUTE, "0 0 " + width + " " + height);
- ArrayList<Visualization> layers = new ArrayList<Visualization>();
+ ArrayList<Visualization> layers = new ArrayList<>();
for (Iterator<VisualizationTask> iter = item.tasks.iterator(); iter.hasNext();) {
VisualizationTask task = iter.next();
if (task.nodetail || task.noexport || !task.visible) {
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/VisualizationTask.java b/src/de/lmu/ifi/dbs/elki/visualization/VisualizationTask.java
index 050c7b63..cb791905 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/VisualizationTask.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/VisualizationTask.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/VisualizerContext.java b/src/de/lmu/ifi/dbs/elki/visualization/VisualizerContext.java
index 417d6d07..d6d65f79 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/VisualizerContext.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/VisualizerContext.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/VisualizerParameterizer.java b/src/de/lmu/ifi/dbs/elki/visualization/VisualizerParameterizer.java
index 1d1a7569..f49ddde6 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/VisualizerParameterizer.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/VisualizerParameterizer.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -60,6 +60,7 @@ import de.lmu.ifi.dbs.elki.visualization.projector.ProjectorFactory;
import de.lmu.ifi.dbs.elki.visualization.style.PropertiesBasedStyleLibrary;
import de.lmu.ifi.dbs.elki.visualization.style.StyleLibrary;
import de.lmu.ifi.dbs.elki.visualization.visualizers.VisFactory;
+import de.lmu.ifi.dbs.elki.workflow.AlgorithmStep;
/**
* Utility class to determine the visualizers for a result class.
@@ -84,9 +85,22 @@ public class VisualizerParameterizer implements Parameterizable {
* Key: -visualizer.stylesheet
*
* Default: default properties file
+ * <br>
+ * included stylesheets:
+ * <ul>
+ * <li>classic</li>
+ * <li>default</li>
+ * <li>greyscale</li>
+ * <li>neon</li>
+ * <li>presentation</li>
+ * <li>print</li>
+ * </ul>
+ * These are {@code *.properties} files in the package {@link de.lmu.ifi.dbs.elki.visualization.style}.
* </p>
+ *
+ *
*/
- public static final OptionID STYLELIB_ID = new OptionID("visualizer.stylesheet", "Style properties file to use");
+ public static final OptionID STYLELIB_ID = new OptionID("visualizer.stylesheet", "Style properties file to use, included properties: classic, default, greyscale, neon, presentation, print");
/**
* Default pattern for visualizer enabling.
@@ -190,7 +204,7 @@ public class VisualizerParameterizer implements Parameterizable {
* @return generated title
*/
public static String getTitle(Database db, Result result) {
- List<Pair<Object, Parameter<?>>> settings = new ArrayList<Pair<Object, Parameter<?>>>();
+ List<Pair<Object, Parameter<?>>> settings = new ArrayList<>();
for (SettingsResult sr : ResultUtil.getSettingsResults(result)) {
settings.addAll(sr.getSettings());
}
@@ -199,7 +213,7 @@ public class VisualizerParameterizer implements Parameterizable {
String dataset = null;
for (Pair<Object, Parameter<?>> setting : settings) {
- if (setting.second.equals(OptionID.ALGORITHM)) {
+ if (setting.second.equals(AlgorithmStep.Parameterizer.ALGORITHM_ID)) {
algorithm = setting.second.getValue().toString();
}
if (setting.second.equals(AbstractDistanceBasedAlgorithm.DISTANCE_FUNCTION_ID)) {
@@ -297,7 +311,7 @@ public class VisualizerParameterizer implements Parameterizable {
* @return List of all adapters found.
*/
private static <O> Collection<ProjectorFactory> collectProjectorFactorys(MergedParameterization config, Pattern filter) {
- ArrayList<ProjectorFactory> factories = new ArrayList<ProjectorFactory>();
+ ArrayList<ProjectorFactory> factories = new ArrayList<>();
for (Class<?> c : InspectionUtil.cachedFindAllImplementations(ProjectorFactory.class)) {
if (filter != null && !filter.matcher(c.getCanonicalName()).find()) {
continue;
@@ -325,7 +339,7 @@ public class VisualizerParameterizer implements Parameterizable {
* @return List of all adapters found.
*/
private static <O> Collection<VisFactory> collectVisFactorys(MergedParameterization config, Pattern filter) {
- ArrayList<VisFactory> factories = new ArrayList<VisFactory>();
+ ArrayList<VisFactory> factories = new ArrayList<>();
for (Class<?> c : InspectionUtil.cachedFindAllImplementations(VisFactory.class)) {
if (filter != null && !filter.matcher(c.getCanonicalName()).find()) {
continue;
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/AddCSSClass.java b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/AddCSSClass.java
index 0e2db37d..1bc64b20 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/AddCSSClass.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/AddCSSClass.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.batikutil;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/AttributeModifier.java b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/AttributeModifier.java
index f52951d7..d6a48013 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/AttributeModifier.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/AttributeModifier.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.batikutil;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/BatikUtil.java b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/BatikUtil.java
index 4f9781e7..7774cde6 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/BatikUtil.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/BatikUtil.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.batikutil;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/CSSHoverClass.java b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/CSSHoverClass.java
index 54d8e7e3..021878b2 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/CSSHoverClass.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/CSSHoverClass.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.batikutil;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/CloneInlineImages.java b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/CloneInlineImages.java
index 9c53d72b..33cf6d8a 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/CloneInlineImages.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/CloneInlineImages.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.batikutil;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/DragableArea.java b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/DragableArea.java
index 42dab91b..56a7b223 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/DragableArea.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/DragableArea.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.batikutil;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -40,7 +40,7 @@ import de.lmu.ifi.dbs.elki.visualization.svg.SVGUtil;
*
* @author Erich Schubert
*
- * @apiviz.uses DragListener
+ * @apiviz.has DragListener
* @apiviz.has Element
*/
public class DragableArea implements EventListener {
@@ -208,47 +208,43 @@ public class DragableArea implements EventListener {
@Override
public void handleEvent(Event evt) {
- if(evt.getType().equals(SVGConstants.SVG_EVENT_MOUSEDOWN)) {
+ if (evt.getType().equals(SVGConstants.SVG_EVENT_MOUSEDOWN)) {
SVGPoint dragPoint = getCoordinates(evt);
- if(startDrag(dragPoint, evt)) {
+ if (startDrag(dragPoint, evt)) {
// LoggingUtil.warning("Starting drag: "+dragPoint);
startDragPoint = dragPoint;
enableStop();
}
- }
- else if(evt.getType().equals(SVGConstants.SVG_EVENT_MOUSEMOVE)) {
- if(startDragPoint != null) {
+ } else if (evt.getType().equals(SVGConstants.SVG_EVENT_MOUSEMOVE)) {
+ if (startDragPoint != null) {
SVGPoint dragPoint = getCoordinates(evt);
- if(!duringDrag(startDragPoint, dragPoint, evt, evt.getTarget() == element)) {
+ if (!duringDrag(startDragPoint, dragPoint, evt, evt.getTarget() == element)) {
// cancel the drag operation
startDragPoint = null;
disableStop();
}
}
- }
- else if(evt.getType().equals(SVGConstants.SVG_EVENT_MOUSEUP)) {
- if(startDragPoint != null) {
+ } else if (evt.getType().equals(SVGConstants.SVG_EVENT_MOUSEUP)) {
+ if (startDragPoint != null) {
SVGPoint dragPoint = getCoordinates(evt);
- if(endDrag(startDragPoint, dragPoint, evt, evt.getTarget() == element)) {
+ if (endDrag(startDragPoint, dragPoint, evt, evt.getTarget() == element)) {
// LoggingUtil.warning("Drag completed: "+dragPoint);
startDragPoint = null;
disableStop();
}
}
- }
- else if(evt.getType().equals(SVGConstants.SVG_EVENT_MOUSEOUT)) {
+ } else if (evt.getType().equals(SVGConstants.SVG_EVENT_MOUSEOUT)) {
// When leaving the document with the mouse!
- if(startDragPoint != null && evt.getTarget() == evt.getCurrentTarget()) {
+ if (startDragPoint != null && evt.getTarget() == evt.getCurrentTarget()) {
// LoggingUtil.warning("Mouseout: "+evt.getTarget().toString());
SVGPoint dragPoint = getCoordinates(evt);
- if(endDrag(startDragPoint, dragPoint, evt, false)) {
+ if (endDrag(startDragPoint, dragPoint, evt, false)) {
// LoggingUtil.warning("Drag completed: "+dragPoint);
startDragPoint = null;
disableStop();
}
}
- }
- else {
+ } else {
LoggingUtil.warning("Unrecognized event: " + evt);
}
}
@@ -271,7 +267,7 @@ public class DragableArea implements EventListener {
* @return {@code true} to start the drag operation
*/
protected boolean startDrag(SVGPoint startPoint, Event evt) {
- if(listener != null) {
+ if (listener != null) {
return listener.startDrag(startPoint, evt);
}
return true;
@@ -287,7 +283,7 @@ public class DragableArea implements EventListener {
* @return {@code true} to continue the drag
*/
protected boolean duringDrag(SVGPoint startPoint, SVGPoint dragPoint, Event evt, boolean inside) {
- if(listener != null) {
+ if (listener != null) {
return listener.duringDrag(startPoint, dragPoint, evt, inside);
}
return true;
@@ -303,7 +299,7 @@ public class DragableArea implements EventListener {
* @return {@code true} to complete the drag
*/
protected boolean endDrag(SVGPoint startPoint, SVGPoint dragPoint, Event evt, boolean inside) {
- if(listener != null) {
+ if (listener != null) {
return listener.endDrag(startPoint, dragPoint, evt, inside);
}
return true;
@@ -334,6 +330,8 @@ public class DragableArea implements EventListener {
* Listener interface for drag events.
*
* @author Erich Schubert
+ *
+ * @apiviz.excludeSubtypes
*/
public interface DragListener {
/**
@@ -367,4 +365,4 @@ public class DragableArea implements EventListener {
*/
boolean endDrag(SVGPoint startPoint, SVGPoint dragPoint, Event evt, boolean inside);
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/JSVGSynchronizedCanvas.java b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/JSVGSynchronizedCanvas.java
index 7629ae1a..2e08a2dc 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/JSVGSynchronizedCanvas.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/JSVGSynchronizedCanvas.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.batikutil;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/JSVGUpdateSynchronizer.java b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/JSVGUpdateSynchronizer.java
index 110d38ec..ab064e43 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/JSVGUpdateSynchronizer.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/JSVGUpdateSynchronizer.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.batikutil;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -51,7 +51,7 @@ class JSVGUpdateSynchronizer implements UpdateSynchronizer {
/**
* The UpdateRunner we are put into
*/
- private List<WeakReference<UpdateRunner>> updaterunner = new ArrayList<WeakReference<UpdateRunner>>();
+ private List<WeakReference<UpdateRunner>> updaterunner = new ArrayList<>();
/**
* Adapter to track component changes
@@ -71,7 +71,7 @@ class JSVGUpdateSynchronizer implements UpdateSynchronizer {
protected JSVGUpdateSynchronizer(JSVGComponent component) {
assert (component != null);
- this.cref = new WeakReference<JSVGComponent>(component);
+ this.cref = new WeakReference<>(component);
// Hook into UpdateManager creation.
component.addUpdateManagerListener(umadapter);
// makeRunnerIfNeeded();
@@ -130,7 +130,7 @@ class JSVGUpdateSynchronizer implements UpdateSynchronizer {
@Override
public void addUpdateRunner(UpdateRunner updateRunner) {
- updaterunner.add(new WeakReference<UpdateRunner>(updateRunner));
+ updaterunner.add(new WeakReference<>(updateRunner));
}
/**
@@ -140,7 +140,7 @@ class JSVGUpdateSynchronizer implements UpdateSynchronizer {
*/
// Not synchronized - private
private void setSynchronizedRunner(JSVGSynchronizedRunner newrunner) {
- syncrunner = new WeakReference<JSVGSynchronizedRunner>(newrunner);
+ syncrunner = new WeakReference<>(newrunner);
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/LazyCanvasResizer.java b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/LazyCanvasResizer.java
index b0dbfd9c..a046b4d6 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/LazyCanvasResizer.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/LazyCanvasResizer.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.batikutil;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/NodeAppendChild.java b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/NodeAppendChild.java
index a5396732..3b640c8d 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/NodeAppendChild.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/NodeAppendChild.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.batikutil;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/NodeReplaceChild.java b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/NodeReplaceChild.java
index f0fb08c5..524bf2c7 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/NodeReplaceChild.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/NodeReplaceChild.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.batikutil;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/NodeReplacer.java b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/NodeReplacer.java
index a82025df..72a42b2f 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/NodeReplacer.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/NodeReplacer.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.batikutil;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/RemoveCSSClass.java b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/RemoveCSSClass.java
index 2f75d40e..3f80117f 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/RemoveCSSClass.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/RemoveCSSClass.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.batikutil;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/ThumbnailRegistryEntry.java b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/ThumbnailRegistryEntry.java
index 83c101e3..9bab635c 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/ThumbnailRegistryEntry.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/ThumbnailRegistryEntry.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.visualization.batikutil;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -80,7 +80,7 @@ public class ThumbnailRegistryEntry extends AbstractRegistryEntry implements URL
/**
* The image cache.
*/
- private static final TIntObjectMap<SoftReference<RenderedImage>> images = new TIntObjectHashMap<SoftReference<RenderedImage>>();
+ private static final TIntObjectMap<SoftReference<RenderedImage>> images = new TIntObjectHashMap<>();
/**
* Object counter
@@ -112,7 +112,7 @@ public class ThumbnailRegistryEntry extends AbstractRegistryEntry implements URL
int key = counter;
counter++;
assert (images.get(key) == null);
- images.put(key, new SoftReference<RenderedImage>(img));
+ images.put(key, new SoftReference<>(img));
// Reorganize map, purge old entries
if(counter % 50 == 49) {
for(TIntObjectIterator<SoftReference<RenderedImage>> iter = images.iterator(); iter.hasNext();) {
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/ThumbnailTranscoder.java b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/ThumbnailTranscoder.java
index 0b2a2080..a07b42f2 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/ThumbnailTranscoder.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/ThumbnailTranscoder.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.batikutil;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/package-info.java
index 333b8b0c..88466cfd 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/package-info.java
@@ -6,7 +6,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/colors/ColorLibrary.java b/src/de/lmu/ifi/dbs/elki/visualization/colors/ColorLibrary.java
index 2d7512c8..10041b1b 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/colors/ColorLibrary.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/colors/ColorLibrary.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.colors;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/colors/ListBasedColorLibrary.java b/src/de/lmu/ifi/dbs/elki/visualization/colors/ListBasedColorLibrary.java
index 83956102..e3fadfd0 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/colors/ListBasedColorLibrary.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/colors/ListBasedColorLibrary.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.colors;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/colors/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/colors/package-info.java
index ef4a2c64..a2d3fe93 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/colors/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/colors/package-info.java
@@ -6,7 +6,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/css/CSSClass.java b/src/de/lmu/ifi/dbs/elki/visualization/css/CSSClass.java
index bb62b7ef..3f9bc095 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/css/CSSClass.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/css/CSSClass.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.css;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -59,7 +59,7 @@ public class CSSClass {
* @param statements Collection of CSS statements
*/
public CSSClass(Object owner, String name, Collection<Pair<String, String>> statements) {
- this.owner = new WeakReference<Object>(owner);
+ this.owner = new WeakReference<>(owner);
this.name = name;
this.statements = statements;
if (!checkName(name)) {
@@ -71,7 +71,7 @@ public class CSSClass {
}
} else {
// if needed, use an array list.
- this.statements = new ArrayList<Pair<String,String>>();
+ this.statements = new ArrayList<>();
}
}
@@ -93,7 +93,7 @@ public class CSSClass {
* @param other Class to clone
*/
public CSSClass(Object owner, String name, CSSClass other) {
- this(owner, name, new ArrayList<Pair<String,String>>(other.statements));
+ this(owner, name, new ArrayList<>(other.statements));
}
/**
@@ -227,7 +227,7 @@ public class CSSClass {
}
}
if (value != null) {
- statements.add(new Pair<String, String>(key, value));
+ statements.add(new Pair<>(key, value));
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/css/CSSClassManager.java b/src/de/lmu/ifi/dbs/elki/visualization/css/CSSClassManager.java
index 34debe56..4d34d9cd 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/css/CSSClassManager.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/css/CSSClassManager.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.css;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -43,7 +43,7 @@ public class CSSClassManager {
/**
* Store the contained CSS classes.
*/
- private HashMap<String, CSSClass> store = new HashMap<String, CSSClass>();
+ private HashMap<String, CSSClass> store = new HashMap<>();
/**
* Add a single class to the map.
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/css/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/css/package-info.java
index 21290f26..942f8997 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/css/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/css/package-info.java
@@ -6,7 +6,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/gui/ResultVisualizer.java b/src/de/lmu/ifi/dbs/elki/visualization/gui/ResultVisualizer.java
index 635a0466..92171f47 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/gui/ResultVisualizer.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/gui/ResultVisualizer.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.gui;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -31,6 +31,7 @@ import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
import de.lmu.ifi.dbs.elki.result.Result;
import de.lmu.ifi.dbs.elki.result.ResultHandler;
import de.lmu.ifi.dbs.elki.result.ResultUtil;
+import de.lmu.ifi.dbs.elki.utilities.Alias;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
@@ -48,6 +49,7 @@ import de.lmu.ifi.dbs.elki.visualization.VisualizerParameterizer;
* @apiviz.composedOf VisualizerParameterizer
* @apiviz.uses ResultWindow oneway
*/
+@Alias({ "visualizer", "vis", "ResultVisualizer" })
public class ResultVisualizer implements ResultHandler {
/**
* Get a logger for this class.
@@ -73,7 +75,7 @@ public class ResultVisualizer implements ResultHandler {
* </p>
*/
public static final OptionID SINGLE_ID = new OptionID("vis.window.single", "Embed visualizers in a single window, not using thumbnails and detail views.");
-
+
/**
* Stores the set title.
*/
@@ -113,11 +115,11 @@ public class ResultVisualizer implements ResultHandler {
// FIXME: not really re-entrant to generate new contexts...
final VisualizerContext context = manager.newContext(top);
- if(title == null) {
+ if (title == null) {
title = VisualizerParameterizer.getTitle(ResultUtil.findDatabase(top), result);
}
- if(title == null) {
+ if (title == null) {
title = DEFAULT_TITLE;
}
@@ -130,8 +132,7 @@ public class ResultVisualizer implements ResultHandler {
window.setVisible(true);
window.setExtendedState(window.getExtendedState() | JFrame.MAXIMIZED_BOTH);
window.showOverview();
- }
- catch(Throwable e) {
+ } catch (Throwable e) {
LOG.exception("Error in starting visualizer window.", e);
}
}
@@ -155,7 +156,7 @@ public class ResultVisualizer implements ResultHandler {
* Visualization manager.
*/
VisualizerParameterizer manager;
-
+
/**
* Single view mode.
*/
@@ -166,7 +167,7 @@ public class ResultVisualizer implements ResultHandler {
super.makeOptions(config);
StringParameter titleP = new StringParameter(WINDOW_TITLE_ID);
titleP.setOptional(true);
- if(config.grab(titleP)) {
+ if (config.grab(titleP)) {
title = titleP.getValue();
}
Flag singleF = new Flag(SINGLE_ID);
@@ -181,4 +182,4 @@ public class ResultVisualizer implements ResultHandler {
return new ResultVisualizer(title, manager, single);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/gui/ResultWindow.java b/src/de/lmu/ifi/dbs/elki/visualization/gui/ResultWindow.java
index 609932cf..0cfa5166 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/gui/ResultWindow.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/gui/ResultWindow.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.gui;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -49,6 +49,7 @@ import de.lmu.ifi.dbs.elki.result.Result;
import de.lmu.ifi.dbs.elki.result.ResultAdapter;
import de.lmu.ifi.dbs.elki.result.ResultHierarchy;
import de.lmu.ifi.dbs.elki.result.ResultListener;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.Hierarchy;
import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
import de.lmu.ifi.dbs.elki.visualization.VisualizerContext;
import de.lmu.ifi.dbs.elki.visualization.batikutil.JSVGSynchronizedCanvas;
@@ -378,8 +379,8 @@ public class ResultWindow extends JFrame implements ResultListener {
private void updateVisualizerMenus() {
visualizersMenu.removeAll();
ResultHierarchy hier = context.getHierarchy();
- for(Result child : hier.getChildren(result)) {
- recursiveBuildMenu(visualizersMenu, child);
+ for(Hierarchy.Iter<Result> iter = hier.iterChildren(result); iter.valid(); iter.advance()) {
+ recursiveBuildMenu(visualizersMenu, iter.get());
}
}
@@ -388,7 +389,7 @@ public class ResultWindow extends JFrame implements ResultListener {
// Skip "adapter" results that do not have visualizers
if(r instanceof ResultAdapter) {
- if(hier.getChildren(r).size() <= 0) {
+ if(hier.numChildren(r) <= 0) {
return false;
}
}
@@ -396,8 +397,8 @@ public class ResultWindow extends JFrame implements ResultListener {
boolean nochildren = true;
JMenu submenu = new JMenu((r.getLongName() != null) ? r.getLongName() : "unnamed");
// Add menus for any children
- for(Result child : hier.getChildren(r)) {
- if(recursiveBuildMenu(submenu, child)) {
+ for(Hierarchy.Iter<Result> iter = hier.iterChildren(r); iter.valid(); iter.advance()) {
+ if(recursiveBuildMenu(submenu, iter.get())) {
nochildren = false;
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/gui/SelectionTableWindow.java b/src/de/lmu/ifi/dbs/elki/visualization/gui/SelectionTableWindow.java
index 4fea630a..6e1b4a66 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/gui/SelectionTableWindow.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/gui/SelectionTableWindow.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.visualization.gui;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/gui/SimpleSVGViewer.java b/src/de/lmu/ifi/dbs/elki/visualization/gui/SimpleSVGViewer.java
index 7c419da7..8172de4e 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/gui/SimpleSVGViewer.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/gui/SimpleSVGViewer.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.gui;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/gui/detail/DetailView.java b/src/de/lmu/ifi/dbs/elki/visualization/gui/detail/DetailView.java
index 091bc8ca..9bcd64b9 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/gui/detail/DetailView.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/gui/detail/DetailView.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.gui.detail;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -76,7 +76,7 @@ public class DetailView extends SVGPlot implements ResultListener {
/**
* Map from visualizers to layers
*/
- Map<VisualizationTask, Visualization> layermap = new HashMap<VisualizationTask, Visualization>();
+ Map<VisualizationTask, Visualization> layermap = new HashMap<>();
/**
* The created width
@@ -141,11 +141,11 @@ public class DetailView extends SVGPlot implements ResultListener {
width = Math.sqrt(getRatio());
height = 1.0 / width;
- ArrayList<Visualization> layers = new ArrayList<Visualization>();
+ ArrayList<Visualization> layers = new ArrayList<>();
// TODO: center/arrange visualizations?
- for(Iterator<VisualizationTask> tit = visi.tasks.iterator(); tit.hasNext();) {
+ for (Iterator<VisualizationTask> tit = visi.tasks.iterator(); tit.hasNext();) {
VisualizationTask task = tit.next();
- if(task.visible) {
+ if (task.visible) {
try {
Visualization v = task.getFactory().makeVisualization(task.clone(this, context, visi.proj, width, height));
if (task.noexport) {
@@ -153,23 +153,20 @@ public class DetailView extends SVGPlot implements ResultListener {
}
layers.add(v);
layermap.put(task, v);
- }
- catch(Exception e) {
- if(Logging.getLogger(task.getFactory().getClass()).isDebugging()) {
+ } catch (Exception e) {
+ if (Logging.getLogger(task.getFactory().getClass()).isDebugging()) {
LoggingUtil.exception("Visualization failed.", e);
- }
- else {
+ } else {
LoggingUtil.warning("Visualizer " + task.getFactory().getClass().getName() + " failed - enable debugging to see details: " + e.toString());
}
}
}
}
// Arrange
- for(Visualization layer : layers) {
- if(layer.getLayer() != null) {
+ for (Visualization layer : layers) {
+ if (layer.getLayer() != null) {
getRoot().appendChild(layer.getLayer());
- }
- else {
+ } else {
LoggingUtil.warning("NULL layer seen.");
}
}
@@ -191,7 +188,7 @@ public class DetailView extends SVGPlot implements ResultListener {
}
private void destroyVisualizations() {
- for(Entry<VisualizationTask, Visualization> v : layermap.entrySet()) {
+ for (Entry<VisualizationTask, Visualization> v : layermap.entrySet()) {
v.getValue().destroy();
}
layermap.clear();
@@ -268,30 +265,28 @@ public class DetailView extends SVGPlot implements ResultListener {
@Override
public void resultChanged(Result current) {
// Make sure we are affected:
- if(!(current instanceof VisualizationTask)) {
+ if (!(current instanceof VisualizationTask)) {
return;
}
// Get the layer
final VisualizationTask task = (VisualizationTask) current;
Visualization vis = layermap.get(task);
- if(vis != null) {
+ if (vis != null) {
// Ensure visibility is as expected
boolean isHidden = SVGConstants.CSS_HIDDEN_VALUE.equals(vis.getLayer().getAttribute(SVGConstants.CSS_VISIBILITY_PROPERTY));
- if(task.visible) {
- if(isHidden) {
+ if (task.visible) {
+ if (isHidden) {
this.scheduleUpdate(new AttributeModifier(vis.getLayer(), SVGConstants.CSS_VISIBILITY_PROPERTY, SVGConstants.CSS_VISIBLE_VALUE));
}
- }
- else {
- if(!isHidden) {
+ } else {
+ if (!isHidden) {
this.scheduleUpdate(new AttributeModifier(vis.getLayer(), SVGConstants.CSS_VISIBILITY_PROPERTY, SVGConstants.CSS_HIDDEN_VALUE));
}
}
- }
- else {
+ } else {
// Only materialize when becoming visible
- if(task.visible) {
- // LoggingUtil.warning("Need to recreate a missing layer for " + v);
+ if (task.visible) {
+ // LoggingUtil.warning("Need to recreate a missing layer for " + task);
vis = task.getFactory().makeVisualization(task.clone(this, context, visi.proj, width, height));
if (task.noexport) {
vis.getLayer().setAttribute(NO_EXPORT_ATTRIBUTE, NO_EXPORT_ATTRIBUTE);
@@ -307,4 +302,4 @@ public class DetailView extends SVGPlot implements ResultListener {
public void resultRemoved(Result child, Result parent) {
// Ignore. The PlotItem will need to change.
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/gui/detail/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/gui/detail/package-info.java
index 95339ac1..91becdd2 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/gui/detail/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/gui/detail/package-info.java
@@ -6,7 +6,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/gui/overview/DetailViewSelectedEvent.java b/src/de/lmu/ifi/dbs/elki/visualization/gui/overview/DetailViewSelectedEvent.java
index 4c950225..6723c77f 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/gui/overview/DetailViewSelectedEvent.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/gui/overview/DetailViewSelectedEvent.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.gui.overview;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/gui/overview/LayerMap.java b/src/de/lmu/ifi/dbs/elki/visualization/gui/overview/LayerMap.java
index 36851b85..5fb7019e 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/gui/overview/LayerMap.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/gui/overview/LayerMap.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.visualization.gui.overview;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -41,7 +41,7 @@ public class LayerMap {
/**
* The actual map
*/
- private HashMap<Pair<PlotItem, VisualizationTask>, Pair<Element, Visualization>> map = new HashMap<Pair<PlotItem, VisualizationTask>, Pair<Element, Visualization>>();
+ private HashMap<Pair<PlotItem, VisualizationTask>, Pair<Element, Visualization>> map = new HashMap<>();
/**
* Helper function for building a key object
@@ -51,7 +51,7 @@ public class LayerMap {
* @return Key
*/
private Pair<PlotItem, VisualizationTask> key(PlotItem item, VisualizationTask task) {
- return new Pair<PlotItem, VisualizationTask>(item, task);
+ return new Pair<>(item, task);
}
/**
@@ -62,7 +62,7 @@ public class LayerMap {
* @return Value object
*/
private Pair<Element, Visualization> value(Element elem, Visualization vis) {
- return new Pair<Element, Visualization>(elem, vis);
+ return new Pair<>(elem, vis);
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/gui/overview/OverviewPlot.java b/src/de/lmu/ifi/dbs/elki/visualization/gui/overview/OverviewPlot.java
index 271a62ff..c4825b1e 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/gui/overview/OverviewPlot.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/gui/overview/OverviewPlot.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.gui.overview;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -43,6 +43,7 @@ import de.lmu.ifi.dbs.elki.result.Result;
import de.lmu.ifi.dbs.elki.result.ResultHierarchy;
import de.lmu.ifi.dbs.elki.result.ResultListener;
import de.lmu.ifi.dbs.elki.result.ResultUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.Hierarchy;
import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
import de.lmu.ifi.dbs.elki.visualization.VisualizerContext;
@@ -90,7 +91,7 @@ public class OverviewPlot extends SVGPlot implements ResultListener {
/**
* Action listeners for this plot.
*/
- private ArrayList<ActionListener> actionListeners = new ArrayList<ActionListener>();
+ private ArrayList<ActionListener> actionListeners = new ArrayList<>();
/**
* Single view mode
@@ -191,7 +192,7 @@ public class OverviewPlot extends SVGPlot implements ResultListener {
* @return Arrangement
*/
private RectangleArranger<PlotItem> arrangeVisualizations(double width, double height) {
- RectangleArranger<PlotItem> plotmap = new RectangleArranger<PlotItem>(width, height);
+ RectangleArranger<PlotItem> plotmap = new RectangleArranger<>(width, height);
ArrayList<Projector> projectors = ResultUtil.filterResults(context.getResult(), Projector.class);
// Rectangle layout
@@ -209,8 +210,11 @@ public class OverviewPlot extends SVGPlot implements ResultListener {
ResultHierarchy hier = context.getHierarchy();
ArrayList<VisualizationTask> tasks = ResultUtil.filterResults(context.getResult(), VisualizationTask.class);
nextTask: for (VisualizationTask task : tasks) {
- for (Result parent : hier.getParents(task)) {
- if (parent instanceof Projector) {
+ if (!task.visible) {
+ continue;
+ }
+ for (Hierarchy.Iter<Result> iter = hier.iterParents(task); iter.valid(); iter.advance()) {
+ if (iter.get() instanceof Projector) {
continue nextTask;
}
}
@@ -276,7 +280,7 @@ public class OverviewPlot extends SVGPlot implements ResultListener {
hasDetails |= !task.nodetail;
Pair<Element, Visualization> pair = oldlayers.remove(it, task);
if (pair == null) {
- pair = new Pair<Element, Visualization>(null, null);
+ pair = new Pair<>(null, null);
pair.first = svgElement(SVGConstants.SVG_G_TAG);
}
if (pair.second == null) {
@@ -368,7 +372,7 @@ public class OverviewPlot extends SVGPlot implements ResultListener {
// New task?
if (pair == null) {
if (visibleInOverview(task)) {
- pair = new Pair<Element, Visualization>(null, null);
+ pair = new Pair<>(null, null);
pair.first = svgElement(SVGConstants.SVG_G_TAG);
pair.second = embedOrThumbnail(thumbsize, it, task, pair.first);
vistoelem.get(it, null).first.appendChild(pair.first);
@@ -381,13 +385,6 @@ public class OverviewPlot extends SVGPlot implements ResultListener {
if (pair.first.hasAttribute(SVGConstants.CSS_VISIBILITY_PROPERTY)) {
pair.first.removeAttribute(SVGConstants.CSS_VISIBILITY_PROPERTY);
}
- // if not yet rendered, add a thumbnail
- if (!pair.first.hasChildNodes()) {
- LOG.warning("This codepath should no longer be needed.");
- Visualization visualization = embedOrThumbnail(thumbsize, it, task, pair.first);
- vistoelem.put(it, task, pair.first, visualization);
- refreshcss = true;
- }
} else {
// hide if there is anything to hide.
if (pair.first != null && pair.first.hasChildNodes()) {
@@ -562,6 +559,18 @@ public class OverviewPlot extends SVGPlot implements ResultListener {
@Override
public void resultChanged(Result current) {
LOG.debug("result changed: " + current);
+ if (current instanceof VisualizationTask) {
+ boolean relayout = true;
+ for (Hierarchy.Iter<Result> iter = context.getHierarchy().iterParents(current); iter.valid(); iter.advance()) {
+ if (iter.get() instanceof Projector) {
+ relayout = false;
+ break;
+ }
+ }
+ if (relayout) {
+ reinitOnRefresh = true;
+ }
+ }
lazyRefresh();
}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/gui/overview/PlotItem.java b/src/de/lmu/ifi/dbs/elki/visualization/gui/overview/PlotItem.java
index 73ee797e..7919e07e 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/gui/overview/PlotItem.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/gui/overview/PlotItem.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.gui.overview;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -72,12 +72,12 @@ public class PlotItem {
/**
* The visualization tasks at this location
*/
- public List<VisualizationTask> tasks = new LinkedList<VisualizationTask>();
+ public List<VisualizationTask> tasks = new LinkedList<>();
/**
* Subitems to plot
*/
- public Collection<PlotItem> subitems = new LinkedList<PlotItem>();
+ public Collection<PlotItem> subitems = new LinkedList<>();
/**
* Constructor.
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/gui/overview/RectangleArranger.java b/src/de/lmu/ifi/dbs/elki/visualization/gui/overview/RectangleArranger.java
index b5e6031e..441f7ae2 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/gui/overview/RectangleArranger.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/gui/overview/RectangleArranger.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.gui.overview;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -34,6 +34,7 @@ import java.util.Set;
import java.util.logging.Level;
import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.LoggingConfiguration;
/**
* This is a rather naive rectangle arrangement class. It will try to place
@@ -79,12 +80,12 @@ public class RectangleArranger<T> {
/**
* Map indicating which cells are used.
*/
- private ArrayList<ArrayList<Object>> usage = new ArrayList<ArrayList<Object>>();
+ private ArrayList<ArrayList<Object>> usage = new ArrayList<>();
/**
* Data
*/
- private Map<T, double[]> map = new HashMap<T, double[]>();
+ private Map<T, double[]> map = new HashMap<>();
/**
* Constructor.
@@ -108,7 +109,7 @@ public class RectangleArranger<T> {
this.widths.add(width);
this.heights.add(height);
// setup usage matrix
- ArrayList<Object> u = new ArrayList<Object>();
+ ArrayList<Object> u = new ArrayList<>();
u.add(null);
this.usage.add(u);
assertConsistent();
@@ -320,7 +321,7 @@ public class RectangleArranger<T> {
heights.insert(bestey + 1, besthi);
heights.set(bestey, heights.get(bestey) - besthi);
// Update used map
- usage.add(bestey + 1, new ArrayList<Object>(usage.get(bestey)));
+ usage.add(bestey + 1, new ArrayList<>(usage.get(bestey)));
}
protected void splitCol(int bestex, double bestwi) {
@@ -361,7 +362,7 @@ public class RectangleArranger<T> {
}
// Add row:
{
- ArrayList<Object> row = new ArrayList<Object>();
+ ArrayList<Object> row = new ArrayList<>();
for(int x = 0; x <= cols; x++) {
row.add(null);
}
@@ -521,8 +522,8 @@ public class RectangleArranger<T> {
* @param args
*/
public static void main(String[] args) {
- LOG.getWrappedLogger().setLevel(Level.FINEST);
- RectangleArranger<String> r = new RectangleArranger<String>(1.3);
+ LoggingConfiguration.setLevelFor(RectangleArranger.class.getName(), Level.FINEST.getName());
+ RectangleArranger<String> r = new RectangleArranger<>(1.3);
r.put(4., 1., "Histogram");
r.put(4., 4., "3D view");
r.put(1., 1., "Meta 1");
@@ -531,14 +532,14 @@ public class RectangleArranger<T> {
r.put(2., 2., "Meta 4");
r.put(2., 2., "Meta 5");
- r = new RectangleArranger<String>(3., 3.);
+ r = new RectangleArranger<>(3., 3.);
r.put(1., 2., "A");
r.put(2., 1., "B");
r.put(1., 2., "C");
r.put(2., 1., "D");
r.put(2., 2., "E");
- r = new RectangleArranger<String>(4 - 2.6521739130434785);
+ r = new RectangleArranger<>(4 - 2.6521739130434785);
r.put(4., .5, "A");
r.put(4., 3., "B");
r.put(4., 1., "C");
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/gui/overview/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/gui/overview/package-info.java
index 013f86ca..302654be 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/gui/overview/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/gui/overview/package-info.java
@@ -7,7 +7,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/gui/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/gui/package-info.java
index 0d026a1d..746235b5 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/gui/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/gui/package-info.java
@@ -6,7 +6,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSColorAdapter.java b/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSColorAdapter.java
index d86c1ae3..5a16c91c 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSColorAdapter.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSColorAdapter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.opticsplot;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSColorFromStylingPolicy.java b/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSColorFromStylingPolicy.java
index 53a03d3e..1f9bccdc 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSColorFromStylingPolicy.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSColorFromStylingPolicy.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.opticsplot;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSColorStatic.java b/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSColorStatic.java
index 920c6d27..b6933e63 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSColorStatic.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSColorStatic.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.opticsplot;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSCorrelationDimensionalityDistance.java b/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSCorrelationDimensionalityDistance.java
index d61c8d07..1261c668 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSCorrelationDimensionalityDistance.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSCorrelationDimensionalityDistance.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.opticsplot;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -50,4 +50,9 @@ public class OPTICSCorrelationDimensionalityDistance<D extends CorrelationDistan
}
return reachability.getCorrelationValue();
}
+
+ @Override
+ public boolean isInfinite(ClusterOrderEntry<D> coe) {
+ return coe.getReachability().isInfiniteDistance();
+ }
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSCut.java b/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSCut.java
index d5a1c043..452cf6af 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSCut.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSCut.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.opticsplot;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -58,7 +58,7 @@ public class OPTICSCut {
public static <D extends Distance<D>> Clustering<Model> makeOPTICSCut(ClusterOrderResult<D> co, OPTICSDistanceAdapter<D> adapter, double epsilon) {
List<ClusterOrderEntry<D>> order = co.getClusterOrder();
// Clustering model we are building
- Clustering<Model> clustering = new Clustering<Model>("OPTICS Cut Clustering", "optics-cut");
+ Clustering<Model> clustering = new Clustering<>("OPTICS Cut Clustering", "optics-cut");
// Collects noise elements
ModifiableDBIDs noise = DBIDUtil.newHashSet();
@@ -88,7 +88,7 @@ public class OPTICSCut {
if(!current.isEmpty()) {
// TODO: do we want a minpts restriction?
// But we get have only core points guaranteed anyway.
- clustering.addCluster(new Cluster<Model>(current, ClusterModel.CLUSTER));
+ clustering.addToplevelCluster(new Cluster<Model>(current, ClusterModel.CLUSTER));
current = DBIDUtil.newHashSet();
}
// Add to noise
@@ -97,10 +97,10 @@ public class OPTICSCut {
}
// Any unfinished cluster will also be added
if(!current.isEmpty()) {
- clustering.addCluster(new Cluster<Model>(current, ClusterModel.CLUSTER));
+ clustering.addToplevelCluster(new Cluster<Model>(current, ClusterModel.CLUSTER));
}
// Add noise
- clustering.addCluster(new Cluster<Model>(noise, true, ClusterModel.CLUSTER));
+ clustering.addToplevelCluster(new Cluster<Model>(noise, true, ClusterModel.CLUSTER));
return clustering;
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSDistanceAdapter.java b/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSDistanceAdapter.java
index 16b9a323..8a6f13ba 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSDistanceAdapter.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSDistanceAdapter.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.opticsplot;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -40,5 +40,13 @@ public interface OPTICSDistanceAdapter<D extends Distance<D>> {
* @param coe Cluster Order Entry
* @return Double value (height)
*/
- public double getDoubleForEntry(ClusterOrderEntry<D> coe);
+ double getDoubleForEntry(ClusterOrderEntry<D> coe);
+
+ /**
+ * Test whether the reachability is infinite.
+ *
+ * @param coe Cluster order entry
+ * @return true, when infinite
+ */
+ boolean isInfinite(ClusterOrderEntry<D> coe);
}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSNumberDistance.java b/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSNumberDistance.java
index 697a9fa2..ad7112f3 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSNumberDistance.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSNumberDistance.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.opticsplot;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -31,7 +31,7 @@ import de.lmu.ifi.dbs.elki.result.optics.ClusterOrderEntry;
*
* @author Erich Schubert
*/
-public class OPTICSNumberDistance<D extends NumberDistance<D,?>> implements OPTICSDistanceAdapter<D> {
+public class OPTICSNumberDistance<D extends NumberDistance<D, ?>> implements OPTICSDistanceAdapter<D> {
/**
* Default constructor.
*/
@@ -46,4 +46,9 @@ public class OPTICSNumberDistance<D extends NumberDistance<D,?>> implements OPTI
}
return coe.getReachability().doubleValue();
}
+
+ @Override
+ public boolean isInfinite(ClusterOrderEntry<D> coe) {
+ return coe.getReachability().isInfiniteDistance();
+ }
}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSPlot.java b/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSPlot.java
index b6b6fb31..4663ef1a 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSPlot.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSPlot.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.opticsplot;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -219,7 +219,7 @@ public class OPTICSPlot<D extends Distance<D>> implements Result {
// calculate range
for(ClusterOrderEntry<D> coe : order) {
double reach = distanceAdapter.getDoubleForEntry(coe);
- if(!Double.isInfinite(reach) && !Double.isNaN(reach)) {
+ if(!distanceAdapter.isInfinite(coe) && !Double.isNaN(reach)) {
range.put(reach);
}
}
@@ -348,7 +348,7 @@ public class OPTICSPlot<D extends Distance<D>> implements Result {
final StylingPolicy policy = context.getStyleResult().getStylingPolicy();
final OPTICSColorAdapter opcolor = new OPTICSColorFromStylingPolicy(policy);
- OPTICSPlot<D> opticsplot = new OPTICSPlot<D>(co, opcolor);
+ OPTICSPlot<D> opticsplot = new OPTICSPlot<>(co, opcolor);
// co.addChildResult(opticsplot);
return opticsplot;
}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/package-info.java
index 39838db1..f1837d96 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/package-info.java
@@ -6,7 +6,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/package-info.java
index f4e854e0..99df7b52 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/package-info.java
@@ -8,7 +8,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projections/AbstractFullProjection.java b/src/de/lmu/ifi/dbs/elki/visualization/projections/AbstractFullProjection.java
index e8f7a91a..5f698192 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/projections/AbstractFullProjection.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/projections/AbstractFullProjection.java
@@ -8,7 +8,7 @@ import de.lmu.ifi.dbs.elki.math.scales.LinearScale;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projections/AbstractProjection.java b/src/de/lmu/ifi/dbs/elki/visualization/projections/AbstractProjection.java
index f0eeccd4..a1629d77 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/projections/AbstractProjection.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/projections/AbstractProjection.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.projections;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projections/AbstractSimpleProjection.java b/src/de/lmu/ifi/dbs/elki/visualization/projections/AbstractSimpleProjection.java
index 4d3aec90..ea93dbda 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/projections/AbstractSimpleProjection.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/projections/AbstractSimpleProjection.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.projections;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projections/AffineProjection.java b/src/de/lmu/ifi/dbs/elki/visualization/projections/AffineProjection.java
index 0e184e32..7522b57c 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/projections/AffineProjection.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/projections/AffineProjection.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.projections;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projections/CanvasSize.java b/src/de/lmu/ifi/dbs/elki/visualization/projections/CanvasSize.java
index cfcec564..c53e62dd 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/projections/CanvasSize.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/projections/CanvasSize.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.projections;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projections/FullProjection.java b/src/de/lmu/ifi/dbs/elki/visualization/projections/FullProjection.java
index 02705355..e715e859 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/projections/FullProjection.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/projections/FullProjection.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.projections;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projections/OPTICSProjection.java b/src/de/lmu/ifi/dbs/elki/visualization/projections/OPTICSProjection.java
index 9a6dd9b8..13409ee0 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/projections/OPTICSProjection.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/projections/OPTICSProjection.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.projections;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projections/Projection.java b/src/de/lmu/ifi/dbs/elki/visualization/projections/Projection.java
index 903a5e6b..d141838e 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/projections/Projection.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/projections/Projection.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.projections;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projections/Projection1D.java b/src/de/lmu/ifi/dbs/elki/visualization/projections/Projection1D.java
index 82c9483d..a5f5e7e9 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/projections/Projection1D.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/projections/Projection1D.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.projections;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projections/Projection2D.java b/src/de/lmu/ifi/dbs/elki/visualization/projections/Projection2D.java
index acd4a829..1a8b1952 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/projections/Projection2D.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/projections/Projection2D.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.projections;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projections/ProjectionParallel.java b/src/de/lmu/ifi/dbs/elki/visualization/projections/ProjectionParallel.java
index 98c2ac33..576c3290 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/projections/ProjectionParallel.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/projections/ProjectionParallel.java
@@ -187,7 +187,7 @@ public interface ProjectionParallel extends Projection {
public double fastProjectRenderToDataSpace(double value, int axis);
/**
- * Find the axis assinged to the given dimension.
+ * Find the axis assigned to the given dimension.
*
* @param truedim Dimension
* @return Axis number
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projections/Simple1D.java b/src/de/lmu/ifi/dbs/elki/visualization/projections/Simple1D.java
index ef97fe15..97ac38cc 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/projections/Simple1D.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/projections/Simple1D.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.projections;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projections/Simple2D.java b/src/de/lmu/ifi/dbs/elki/visualization/projections/Simple2D.java
index 81821a7c..9b27af5a 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/projections/Simple2D.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/projections/Simple2D.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.projections;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projections/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/projections/package-info.java
index 7f175a43..067d9146 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/projections/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/projections/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projector/HistogramFactory.java b/src/de/lmu/ifi/dbs/elki/visualization/projector/HistogramFactory.java
index 24defc7b..61921296 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/projector/HistogramFactory.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/projector/HistogramFactory.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.projector;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -68,7 +68,7 @@ public class HistogramFactory implements ProjectorFactory {
@SuppressWarnings("unchecked")
Relation<NumberVector<?>> vrel = (Relation<NumberVector<?>>) rel;
final int dim = RelationUtil.dimensionality(vrel);
- HistogramProjector<NumberVector<?>> proj = new HistogramProjector<NumberVector<?>>(vrel, Math.min(dim, maxdim));
+ HistogramProjector<NumberVector<?>> proj = new HistogramProjector<>(vrel, Math.min(dim, maxdim));
baseResult.getHierarchy().add(vrel, proj);
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projector/HistogramProjector.java b/src/de/lmu/ifi/dbs/elki/visualization/projector/HistogramProjector.java
index 9153476b..3503692c 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/projector/HistogramProjector.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/projector/HistogramProjector.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.projector;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -76,7 +76,7 @@ public class HistogramProjector<V extends NumberVector<?>> extends AbstractHiera
@Override
public Collection<PlotItem> arrange() {
- List<PlotItem> layout = new ArrayList<PlotItem>(1 + dmax);
+ List<PlotItem> layout = new ArrayList<>(1 + dmax);
List<VisualizationTask> tasks = ResultUtil.filterResults(this, VisualizationTask.class);
if (tasks.size() > 0){
final double xoff = (dmax > 1) ? .1 : 0.;
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projector/OPTICSProjector.java b/src/de/lmu/ifi/dbs/elki/visualization/projector/OPTICSProjector.java
index 5aa43cd9..832184f0 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/projector/OPTICSProjector.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/projector/OPTICSProjector.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.projector;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -75,10 +75,10 @@ public class OPTICSProjector<D extends Distance<D>> extends AbstractHierarchical
@Override
public Collection<PlotItem> arrange() {
- List<PlotItem> col = new ArrayList<PlotItem>(1);
+ List<PlotItem> col = new ArrayList<>(1);
List<VisualizationTask> tasks = ResultUtil.filterResults(this, VisualizationTask.class);
if (tasks.size() > 0) {
- final PlotItem it = new PlotItem(4., 1., new OPTICSProjection<D>(this));
+ final PlotItem it = new PlotItem(4., 1., new OPTICSProjection<>(this));
it.tasks = tasks;
col.add(it);
}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projector/OPTICSProjectorFactory.java b/src/de/lmu/ifi/dbs/elki/visualization/projector/OPTICSProjectorFactory.java
index 488c20e0..797c4031 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/projector/OPTICSProjectorFactory.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/projector/OPTICSProjectorFactory.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.projector;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -53,7 +53,7 @@ public class OPTICSProjectorFactory implements ProjectorFactory {
for(ClusterOrderResult<?> co : cos) {
if(OPTICSPlot.canPlot(co)) {
@SuppressWarnings("unchecked")
- OPTICSProjector<?> proj = new OPTICSProjector<DoubleDistance>((ClusterOrderResult<DoubleDistance>) co);
+ OPTICSProjector<?> proj = new OPTICSProjector<>((ClusterOrderResult<DoubleDistance>) co);
baseResult.getHierarchy().add(co, proj);
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projector/ParallelPlotFactory.java b/src/de/lmu/ifi/dbs/elki/visualization/projector/ParallelPlotFactory.java
index 23ba6d3f..e744ae5b 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/projector/ParallelPlotFactory.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/projector/ParallelPlotFactory.java
@@ -55,7 +55,7 @@ public class ParallelPlotFactory implements ProjectorFactory {
if(TypeUtil.NUMBER_VECTOR_FIELD.isAssignableFromType(rel.getDataTypeInformation())) {
@SuppressWarnings("unchecked")
Relation<NumberVector<?>> vrel = (Relation<NumberVector<?>>) rel;
- ParallelPlotProjector<NumberVector<?>> proj = new ParallelPlotProjector<NumberVector<?>>(vrel);
+ ParallelPlotProjector<NumberVector<?>> proj = new ParallelPlotProjector<>(vrel);
baseResult.getHierarchy().add(vrel, proj);
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projector/ParallelPlotProjector.java b/src/de/lmu/ifi/dbs/elki/visualization/projector/ParallelPlotProjector.java
index 3e172ff9..bc981924 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/projector/ParallelPlotProjector.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/projector/ParallelPlotProjector.java
@@ -65,7 +65,7 @@ public class ParallelPlotProjector<V extends NumberVector<?>> extends AbstractHi
@Override
public Collection<PlotItem> arrange() {
- List<PlotItem> col = new ArrayList<PlotItem>(1);
+ List<PlotItem> col = new ArrayList<>(1);
List<VisualizationTask> tasks = ResultUtil.filterResults(this, VisualizationTask.class);
if(tasks.size() > 0) {
ScalesResult scales = ResultUtil.getScalesResult(rel);
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projector/Projector.java b/src/de/lmu/ifi/dbs/elki/visualization/projector/Projector.java
index 6435bf60..8febb94b 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/projector/Projector.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/projector/Projector.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.projector;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projector/ProjectorFactory.java b/src/de/lmu/ifi/dbs/elki/visualization/projector/ProjectorFactory.java
index 4fb6bf9e..25a9ddc1 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/projector/ProjectorFactory.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/projector/ProjectorFactory.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.projector;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projector/ScatterPlotFactory.java b/src/de/lmu/ifi/dbs/elki/visualization/projector/ScatterPlotFactory.java
index 0367d54b..101f52a6 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/projector/ScatterPlotFactory.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/projector/ScatterPlotFactory.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.projector;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -76,7 +76,7 @@ public class ScatterPlotFactory implements ProjectorFactory {
@SuppressWarnings("unchecked")
Relation<NumberVector<?>> vrel = (Relation<NumberVector<?>>) rel;
final int dim = RelationUtil.dimensionality(vrel);
- ScatterPlotProjector<NumberVector<?>> proj = new ScatterPlotProjector<NumberVector<?>>(vrel, Math.min(maxdim, dim));
+ ScatterPlotProjector<NumberVector<?>> proj = new ScatterPlotProjector<>(vrel, Math.min(maxdim, dim));
baseResult.getHierarchy().add(vrel, proj);
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projector/ScatterPlotProjector.java b/src/de/lmu/ifi/dbs/elki/visualization/projector/ScatterPlotProjector.java
index e97ad653..84035058 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/projector/ScatterPlotProjector.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/projector/ScatterPlotProjector.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.projector;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -78,7 +78,7 @@ public class ScatterPlotProjector<V extends NumberVector<?>> extends AbstractHie
@Override
public Collection<PlotItem> arrange() {
- List<PlotItem> layout = new ArrayList<PlotItem>(1);
+ List<PlotItem> layout = new ArrayList<>(1);
List<VisualizationTask> tasks = ResultUtil.filterResults(this, VisualizationTask.class);
if(tasks.size() > 0) {
ScalesResult scales = ResultUtil.getScalesResult(rel);
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projector/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/projector/package-info.java
index 9fbc2852..205507de 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/projector/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/projector/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/savedialog/SVGSaveDialog.java b/src/de/lmu/ifi/dbs/elki/visualization/savedialog/SVGSaveDialog.java
index 8f56c562..a12f4820 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/savedialog/SVGSaveDialog.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/savedialog/SVGSaveDialog.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.savedialog;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/savedialog/SaveOptionsPanel.java b/src/de/lmu/ifi/dbs/elki/visualization/savedialog/SaveOptionsPanel.java
index 7e77c79f..913fdee2 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/savedialog/SaveOptionsPanel.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/savedialog/SaveOptionsPanel.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.savedialog;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -114,7 +114,7 @@ public class SaveOptionsPanel extends JPanel {
protected JButton resetSizeButton;
- protected JComboBox formatSelector;
+ protected JComboBox<String> formatSelector;
// Not particularly useful for most - hide it for now.
private final boolean hasResetButton = false;
@@ -142,7 +142,7 @@ public class SaveOptionsPanel extends JPanel {
// *** Format panel
mainPanel.add(new JLabel(STR_CHOOSE_FORMAT));
- formatSelector = new JComboBox(SVGSaveDialog.getVisibleFormats());
+ formatSelector = new JComboBox<>(SVGSaveDialog.getVisibleFormats());
formatSelector.setSelectedIndex(0);
formatSelector.addItemListener(new ItemListener() {
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/savedialog/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/savedialog/package-info.java
index 6820726b..1b61055d 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/savedialog/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/savedialog/package-info.java
@@ -6,7 +6,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/style/ClassStylingPolicy.java b/src/de/lmu/ifi/dbs/elki/visualization/style/ClassStylingPolicy.java
index 82000e42..0e60b051 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/style/ClassStylingPolicy.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/style/ClassStylingPolicy.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.style;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -63,4 +63,12 @@ public interface ClassStylingPolicy extends StylingPolicy {
* @return Iterator over object IDs
*/
public DBIDIter iterateClass(int cnum);
+
+ /**
+ * Get the number of elements in the styling class.
+ *
+ * @param cnum Class number
+ * @return Size of class.
+ */
+ public int classSize(int cnum);
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/style/ClusterStylingPolicy.java b/src/de/lmu/ifi/dbs/elki/visualization/style/ClusterStylingPolicy.java
index 7adecc68..cd2fd17b 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/style/ClusterStylingPolicy.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/style/ClusterStylingPolicy.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.style;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,6 +24,8 @@ package de.lmu.ifi.dbs.elki.visualization.style;
*/
import gnu.trove.list.array.TIntArrayList;
+import gnu.trove.map.TObjectIntMap;
+import gnu.trove.map.hash.TObjectIntHashMap;
import java.awt.Color;
import java.util.ArrayList;
@@ -54,6 +56,11 @@ public class ClusterStylingPolicy implements ClassStylingPolicy {
ArrayList<DBIDs> ids;
/**
+ * Map from cluster objects to color offsets.
+ */
+ TObjectIntMap<Cluster<?>> cmap;
+
+ /**
* Colors
*/
TIntArrayList colors;
@@ -73,21 +80,22 @@ public class ClusterStylingPolicy implements ClassStylingPolicy {
this.clustering = clustering;
ColorLibrary colorset = style.getColorSet(StyleLibrary.PLOT);
List<? extends Cluster<?>> clusters = clustering.getAllClusters();
- ids = new ArrayList<DBIDs>(clusters.size());
+ ids = new ArrayList<>(clusters.size());
colors = new TIntArrayList(clusters.size());
+ cmap = new TObjectIntHashMap<>(clusters.size(), .5f, -1);
Iterator<? extends Cluster<?>> ci = clusters.iterator();
- for(int i = 0; ci.hasNext(); i++) {
+ for (int i = 0; ci.hasNext(); i++) {
Cluster<?> c = ci.next();
ids.add(DBIDUtil.ensureSet(c.getIDs()));
+ cmap.put(c, i);
Color col = SVGUtil.stringToColor(colorset.getColor(i));
- if(col != null) {
+ if (col != null) {
colors.add(col.getRGB());
- }
- else {
+ } else {
LoggingUtil.warning("Unrecognized color name: " + colorset.getColor(i));
}
- if(!ci.hasNext()) {
+ if (!ci.hasNext()) {
break;
}
}
@@ -95,8 +103,8 @@ public class ClusterStylingPolicy implements ClassStylingPolicy {
@Override
public int getStyleForDBID(DBIDRef id) {
- for(int i = 0; i < ids.size(); i++) {
- if(ids.get(i).contains(id)) {
+ for (int i = 0; i < ids.size(); i++) {
+ if (ids.get(i).contains(id)) {
return i;
}
}
@@ -105,8 +113,8 @@ public class ClusterStylingPolicy implements ClassStylingPolicy {
@Override
public int getColorForDBID(DBIDRef id) {
- for(int i = 0; i < ids.size(); i++) {
- if(ids.get(i).contains(id)) {
+ for (int i = 0; i < ids.size(); i++) {
+ if (ids.get(i).contains(id)) {
return colors.get(i);
}
}
@@ -128,6 +136,11 @@ public class ClusterStylingPolicy implements ClassStylingPolicy {
return ids.get(cnum).iter();
}
+ @Override
+ public int classSize(int cnum) {
+ return ids.get(cnum).size();
+ }
+
/**
* Get the clustering used by this styling policy
*
@@ -136,4 +149,14 @@ public class ClusterStylingPolicy implements ClassStylingPolicy {
public Clustering<?> getClustering() {
return clustering;
}
-} \ No newline at end of file
+
+ /**
+ * Get the style number for a cluster.
+ *
+ * @param c Cluster
+ * @return Style number
+ */
+ public int getStyleForCluster(Cluster<?> c) {
+ return cmap.get(c);
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/style/PropertiesBasedStyleLibrary.java b/src/de/lmu/ifi/dbs/elki/visualization/style/PropertiesBasedStyleLibrary.java
index 6b0869fb..ee9c9b3e 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/style/PropertiesBasedStyleLibrary.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/style/PropertiesBasedStyleLibrary.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.style;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,11 +26,12 @@ package de.lmu.ifi.dbs.elki.visualization.style;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
import java.util.Properties;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.utilities.FileUtil;
-import de.lmu.ifi.dbs.elki.utilities.datastructures.AnyMap;
import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
import de.lmu.ifi.dbs.elki.visualization.colors.ColorLibrary;
import de.lmu.ifi.dbs.elki.visualization.colors.ListBasedColorLibrary;
@@ -99,7 +100,7 @@ public class PropertiesBasedStyleLibrary implements StyleLibrary {
/**
* Cache
*/
- private AnyMap<String> cache = new AnyMap<String>();
+ private Map<String, Object> cache = new HashMap<>();
/**
* Line style library to use
@@ -167,7 +168,7 @@ public class PropertiesBasedStyleLibrary implements StyleLibrary {
* @return Resulting value
*/
private <T> T getCached(String prefix, String postfix, Class<T> cls) {
- return cache.get(prefix + '.' + postfix, cls);
+ return cls.cast(cache.get(prefix + '.' + postfix));
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/style/SingleObjectsStylingPolicy.java b/src/de/lmu/ifi/dbs/elki/visualization/style/SingleObjectsStylingPolicy.java
index f6ba0ccc..c367eb24 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/style/SingleObjectsStylingPolicy.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/style/SingleObjectsStylingPolicy.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.style;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/style/StyleLibrary.java b/src/de/lmu/ifi/dbs/elki/visualization/style/StyleLibrary.java
index 588c0bc8..6c7b841f 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/style/StyleLibrary.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/style/StyleLibrary.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.style;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/style/StyleResult.java b/src/de/lmu/ifi/dbs/elki/visualization/style/StyleResult.java
index e8f0d3fb..231a1cd8 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/style/StyleResult.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/style/StyleResult.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.style;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/style/StylingPolicy.java b/src/de/lmu/ifi/dbs/elki/visualization/style/StylingPolicy.java
index d2390ea0..98ed25e1 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/style/StylingPolicy.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/style/StylingPolicy.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.style;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/style/classic.properties b/src/de/lmu/ifi/dbs/elki/visualization/style/classic.properties
index fe9f3e96..66df4720 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/style/classic.properties
+++ b/src/de/lmu/ifi/dbs/elki/visualization/style/classic.properties
@@ -37,10 +37,10 @@ axis.tick.line-width=0.002
## Axis label font size
axis.label.text-size=0.02
-## Named color for the background of the key box
-key.background-color=none
## Named color for a label in the key part
-key.label.color=black
+key.text-size=0.007
+key.color=black
+key.hierarchy.line-width=0.05
## A list of color names for data lines
# We stick to primary colors first to have the least issues
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/style/default.properties b/src/de/lmu/ifi/dbs/elki/visualization/style/default.properties
index ca892a6e..bfcaaa3a 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/style/default.properties
+++ b/src/de/lmu/ifi/dbs/elki/visualization/style/default.properties
@@ -37,10 +37,10 @@ axis.tick.line-width=0.002
## Axis label font size
axis.label.text-size=0.02
-## Named color for the background of the key box
-key.background-color=none
## Named color for a label in the key part
-key.label.color=black
+key.text-size=0.007
+key.color=black
+key.hierarchy.line-width=0.1
## A list of color names for data lines
colorset=#ed420e,#fdca19,#4548a5,#7ebd3a,#a81e51,#00748b,#fa8116,#512d85,#008a7a,#fea918,#019d60,#cfde3d,#015a9c,#7b1760
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/style/greyscale.properties b/src/de/lmu/ifi/dbs/elki/visualization/style/greyscale.properties
index 0e7c96e0..f27a85a2 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/style/greyscale.properties
+++ b/src/de/lmu/ifi/dbs/elki/visualization/style/greyscale.properties
@@ -37,10 +37,10 @@ axis.tick.line-width=0.002
## Axis label font size
axis.label.text-size=0.02
-## Named color for the background of the key box
-key.background-color=none
## Named color for a label in the key part
-key.label.color=black
+key.text-size=0.007
+key.color=black
+key.hierarchy.line-width=0.05
## A list of color names for data lines
# We stick to primary colors first to have the least issues
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/style/lines/DashedLineStyleLibrary.java b/src/de/lmu/ifi/dbs/elki/visualization/style/lines/DashedLineStyleLibrary.java
index e3abd7c1..35c47eb7 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/style/lines/DashedLineStyleLibrary.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/style/lines/DashedLineStyleLibrary.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.style.lines;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/style/lines/LineStyleLibrary.java b/src/de/lmu/ifi/dbs/elki/visualization/style/lines/LineStyleLibrary.java
index 79f3eda0..6c817778 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/style/lines/LineStyleLibrary.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/style/lines/LineStyleLibrary.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.style.lines;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/style/lines/SolidLineStyleLibrary.java b/src/de/lmu/ifi/dbs/elki/visualization/style/lines/SolidLineStyleLibrary.java
index 51491db2..340381a1 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/style/lines/SolidLineStyleLibrary.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/style/lines/SolidLineStyleLibrary.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.style.lines;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/style/lines/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/style/lines/package-info.java
index 57a2ee6b..ef9d9af7 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/style/lines/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/style/lines/package-info.java
@@ -6,7 +6,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/style/marker/CircleMarkers.java b/src/de/lmu/ifi/dbs/elki/visualization/style/marker/CircleMarkers.java
index ae066c9e..f78c72de 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/style/marker/CircleMarkers.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/style/marker/CircleMarkers.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.style.marker;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/style/marker/MarkerLibrary.java b/src/de/lmu/ifi/dbs/elki/visualization/style/marker/MarkerLibrary.java
index ccddba7d..75591c93 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/style/marker/MarkerLibrary.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/style/marker/MarkerLibrary.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.style.marker;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/style/marker/MinimalMarkers.java b/src/de/lmu/ifi/dbs/elki/visualization/style/marker/MinimalMarkers.java
index b7ad6274..4111dbbc 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/style/marker/MinimalMarkers.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/style/marker/MinimalMarkers.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.style.marker;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/style/marker/PrettyMarkers.java b/src/de/lmu/ifi/dbs/elki/visualization/style/marker/PrettyMarkers.java
index 7352fea3..d99d92a7 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/style/marker/PrettyMarkers.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/style/marker/PrettyMarkers.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.style.marker;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/style/marker/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/style/marker/package-info.java
index a0672ffb..78ad8b57 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/style/marker/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/style/marker/package-info.java
@@ -6,7 +6,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/style/neon.properties b/src/de/lmu/ifi/dbs/elki/visualization/style/neon.properties
index 81515031..d18c393a 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/style/neon.properties
+++ b/src/de/lmu/ifi/dbs/elki/visualization/style/neon.properties
@@ -37,10 +37,10 @@ axis.tick.line-width=0.002
## Axis label font size
axis.label.text-size=0.02
-## Named color for the background of the key box
-key.background-color=none
## Named color for a label in the key part
-key.label.color=white
+key.text-size=0.007
+key.color=white
+key.hierarchy.line-width=0.05
## A list of color names for data lines
# We stick to primary colors first to have the least issues
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/style/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/style/package-info.java
index e45cca0f..179472f7 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/style/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/style/package-info.java
@@ -6,7 +6,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/style/presentation.properties b/src/de/lmu/ifi/dbs/elki/visualization/style/presentation.properties
index 01264673..d30667b6 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/style/presentation.properties
+++ b/src/de/lmu/ifi/dbs/elki/visualization/style/presentation.properties
@@ -37,10 +37,10 @@ axis.tick.line-width=0.004
## Axis label font size
axis.label.text-size=0.03
-## Named color for the background of the key box
-key.background-color=none
## Named color for a label in the key part
-key.label.color=black
+key.text-size=0.01
+key.color=black
+key.hierarchy.line-width=0.1
## A list of color names for data lines
# We stick to primary colors first to have the least issues
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/style/print.properties b/src/de/lmu/ifi/dbs/elki/visualization/style/print.properties
index 930a8d1c..02c19ba1 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/style/print.properties
+++ b/src/de/lmu/ifi/dbs/elki/visualization/style/print.properties
@@ -37,10 +37,10 @@ axis.tick.line-width=0.004
## Axis label font size
axis.label.text-size=0.03
-## Named color for the background of the key box
-key.background-color=none
## Named color for a label in the key part
-key.label.color=black
+key.text-size=0.007
+key.color=black
+key.hierarchy.line-width=0.05
## A list of color names for data lines
# We stick to primary colors first to have the least issues
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/style/wikipedia.properties b/src/de/lmu/ifi/dbs/elki/visualization/style/wikipedia.properties
new file mode 100644
index 00000000..e02ad985
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/style/wikipedia.properties
@@ -0,0 +1,77 @@
+## Libraries
+lines-library = SolidLineStyleLibrary
+marker-library = CircleMarkers
+
+## Default foreground color
+color=black
+## Default font family
+font-family='Times New Roman', serif
+## Default background color
+background-color=white
+## Default line width
+line-width=0.01
+## Text font size scale
+text-size=0.03
+## Text color
+text-color=black
+## Default margin (relative)
+margin.size=0.1
+
+## Named color for the page background
+page.background-color=white
+## Background color for plot area
+plot.background-color=none
+
+## Named color for a typical axis
+axis.color=black
+## Named color for a typical axis tick mark
+axis.tick.color=gray
+## Named color for a typical axis tick mark
+axis.tick.minor.color=silver
+## Named color for a typical axis label
+axis.label.color=black
+## Axis line width
+axis.line-width=0.002
+## Axis tick width
+axis.tick.line-width=0.002
+## Axis label font size
+axis.label.text-size=0.02
+
+## Named color for a label in the key part
+key.text-size=0.007
+key.color=black
+key.hierarchy.line-width=0.05
+
+## A list of color names for data lines
+# We stick to primary colors first to have the least issues
+# The first two colors are red and blue to help red-green blind people.
+# Yellow usually offers bad contrast, therefore comes late.
+# Magenta often shows up too similar to red, cyan too similar to blue in print.
+colorset=red,blue,green,orange,cyan,magenta,darkred,darkblue,darkgreen
+## Line width scaling (for graphs)
+plot.line-width=0.005
+## For the cluster order
+plot.clusterorder.line-width=0.002
+## Bubble sizes (relative)
+plot.bubble.size=0.10
+## Marker size (relative)
+plot.marker.size=0.01
+## Dot size
+plot.dot.size=0.005
+## Reference points
+plot.referencepoints.size=0.003
+plot.referencepoints.color=red
+## Polygons
+plot.polygons.line-width=0.001
+plot.polygons.color=gray
+
+## Curve vis (ROC curves) labels:
+curve.labels.text-size=0.04
+
+# Text size in overview plot
+overview.labels.text-size=0.08
+
+## Selection colors
+plot.selection.color=darkblue
+plot.selection.opacity=0.25
+plot.selection.size=0.015
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGArrow.java b/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGArrow.java
index 3859deb5..cbae03e2 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGArrow.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGArrow.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.svg;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGButton.java b/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGButton.java
index 9d71c3d6..9b69ab14 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGButton.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGButton.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.svg;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGCheckbox.java b/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGCheckbox.java
index b6cf1165..dc27b989 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGCheckbox.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGCheckbox.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.svg;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGCloneVisible.java b/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGCloneVisible.java
index 749720ee..6397348c 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGCloneVisible.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGCloneVisible.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.svg;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGEffects.java b/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGEffects.java
index 79565902..9382e0b6 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGEffects.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGEffects.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.svg;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGHyperCube.java b/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGHyperCube.java
index 656e42da..64f5e9be 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGHyperCube.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGHyperCube.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.svg;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -125,7 +125,7 @@ public class SVGHyperCube {
*/
private static ArrayList<double[]> getVisibleEdges(Projection2D proj, double[] s_min, double[] s_max) {
double[] s_deltas = VMath.minus(s_max, s_min);
- ArrayList<double[]> r_edges = new ArrayList<double[]>();
+ ArrayList<double[]> r_edges = new ArrayList<>();
for(int i = 0; i < s_min.length; i++) {
double[] delta = new double[s_min.length];
delta[i] = s_deltas[i];
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGHyperSphere.java b/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGHyperSphere.java
index 33daa56b..14acc5c3 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGHyperSphere.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGHyperSphere.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.svg;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -50,28 +50,26 @@ public class SVGHyperSphere {
/**
* Wireframe "manhattan" hypersphere
*
- * @param <D> radius
* @param svgp SVG Plot
* @param proj Visualization projection
* @param mid mean vector
- * @param rad radius
+ * @param radius radius
* @return path element
*/
- public static <D extends NumberDistance<?, ?>> Element drawManhattan(SVGPlot svgp, Projection2D proj, NumberVector<?> mid, D rad) {
- final double radius = rad.doubleValue();
+ public static Element drawManhattan(SVGPlot svgp, Projection2D proj, NumberVector<?> mid, double radius) {
final double[] v_mid = mid.getColumnVector().getArrayRef(); // a copy
final BitSet dims = proj.getVisibleDimensions2D();
SVGPath path = new SVGPath();
- for(int dim = dims.nextSetBit(0); dim >= 0; dim = dims.nextSetBit(dim + 1)) {
+ for (int dim = dims.nextSetBit(0); dim >= 0; dim = dims.nextSetBit(dim + 1)) {
v_mid[dim] += radius;
double[] p1 = proj.fastProjectDataToRenderSpace(v_mid);
v_mid[dim] -= radius;
v_mid[dim] -= radius;
double[] p2 = proj.fastProjectDataToRenderSpace(v_mid);
v_mid[dim] += radius;
- for(int dim2 = dims.nextSetBit(0); dim2 >= 0; dim2 = dims.nextSetBit(dim2 + 1)) {
- if(dim < dim2) {
+ for (int dim2 = dims.nextSetBit(0); dim2 >= 0; dim2 = dims.nextSetBit(dim2 + 1)) {
+ if (dim < dim2) {
v_mid[dim2] += radius;
double[] p3 = proj.fastProjectDataToRenderSpace(v_mid);
v_mid[dim2] -= radius;
@@ -97,20 +95,18 @@ public class SVGHyperSphere {
/**
* Wireframe "euclidean" hypersphere
*
- * @param <D> radius
* @param svgp SVG Plot
* @param proj Visualization projection
* @param mid mean vector
- * @param rad radius
+ * @param radius radius
* @return path element
*/
- public static <D extends NumberDistance<?, ?>> Element drawEuclidean(SVGPlot svgp, Projection2D proj, NumberVector<?> mid, D rad) {
- final double radius = rad.doubleValue();
+ public static Element drawEuclidean(SVGPlot svgp, Projection2D proj, NumberVector<?> mid, double radius) {
double[] v_mid = mid.getColumnVector().getArrayRef(); // a copy
BitSet dims = proj.getVisibleDimensions2D();
SVGPath path = new SVGPath();
- for(int dim = dims.nextSetBit(0); dim >= 0; dim = dims.nextSetBit(dim + 1)) {
+ for (int dim = dims.nextSetBit(0); dim >= 0; dim = dims.nextSetBit(dim + 1)) {
v_mid[dim] += radius;
double[] p1 = proj.fastProjectDataToRenderSpace(v_mid);
v_mid[dim] -= radius;
@@ -121,8 +117,8 @@ public class SVGHyperSphere {
double[] dt1 = new double[v_mid.length];
dt1[dim] = radius;
double[] d1 = proj.fastProjectRelativeDataToRenderSpace(dt1);
- for(int dim2 = dims.nextSetBit(0); dim2 >= 0; dim2 = dims.nextSetBit(dim2 + 1)) {
- if(dim < dim2) {
+ for (int dim2 = dims.nextSetBit(0); dim2 >= 0; dim2 = dims.nextSetBit(dim2 + 1)) {
+ if (dim < dim2) {
v_mid[dim2] += radius;
double[] p3 = proj.fastProjectDataToRenderSpace(v_mid);
v_mid[dim2] -= radius;
@@ -149,38 +145,34 @@ public class SVGHyperSphere {
/**
* Wireframe "Lp" hypersphere
*
- * @param <D> radius
* @param svgp SVG Plot
* @param proj Visualization projection
* @param mid mean vector
- * @param rad radius
+ * @param radius radius
* @param p L_p value
* @return path element
*/
- public static <D extends NumberDistance<?, ?>> Element drawLp(SVGPlot svgp, Projection2D proj, NumberVector<?> mid, D rad, double p) {
- final double radius = rad.doubleValue();
+ public static Element drawLp(SVGPlot svgp, Projection2D proj, NumberVector<?> mid, double radius, double p) {
final double[] v_mid = mid.getColumnVector().getArrayRef();
final BitSet dims = proj.getVisibleDimensions2D();
final double kappax, kappay;
- if(p > 1.) {
+ if (p > 1.) {
final double kappal = Math.pow(0.5, 1. / p);
kappax = Math.min(1.3, 4. * (2 * kappal - 1) / 3.);
kappay = 0;
- }
- else if(p < 1.) {
+ } else if (p < 1.) {
final double kappal = 1 - Math.pow(0.5, 1. / p);
kappax = 0;
kappay = Math.min(1.3, 4. * (2 * kappal - 1) / 3.);
- }
- else {
+ } else {
kappax = 0;
kappay = 0;
}
// LoggingUtil.warning("kappax: " + kappax + " kappay: " + kappay);
SVGPath path = new SVGPath();
- for(int dim = dims.nextSetBit(0); dim >= 0; dim = dims.nextSetBit(dim + 1)) {
+ for (int dim = dims.nextSetBit(0); dim >= 0; dim = dims.nextSetBit(dim + 1)) {
v_mid[dim] += radius;
double[] pvp0 = proj.fastProjectDataToRenderSpace(v_mid);
v_mid[dim] -= radius;
@@ -191,8 +183,8 @@ public class SVGHyperSphere {
double[] tvd0 = new double[v_mid.length];
tvd0[dim] = radius;
double[] vd0 = proj.fastProjectRelativeDataToRenderSpace(tvd0);
- for(int dim2 = dims.nextSetBit(0); dim2 >= 0; dim2 = dims.nextSetBit(dim2 + 1)) {
- if(dim < dim2) {
+ for (int dim2 = dims.nextSetBit(0); dim2 >= 0; dim2 = dims.nextSetBit(dim2 + 1)) {
+ if (dim < dim2) {
v_mid[dim2] += radius;
double[] pv0p = proj.fastProjectDataToRenderSpace(v_mid);
v_mid[dim2] -= radius;
@@ -204,7 +196,7 @@ public class SVGHyperSphere {
tv0d[dim2] = radius;
double[] v0d = proj.fastProjectRelativeDataToRenderSpace(tv0d);
- if(p > 1) {
+ if (p > 1) {
// p > 1
path.moveTo(pvp0[0], pvp0[1]);
// support points, p0 to 0p
@@ -232,8 +224,7 @@ public class SVGHyperSphere {
final double s_pm2_y = pvp0[1] - v0d[1] * kappax;
path.cubicTo(s_pm1_x, s_pm1_y, s_pm2_x, s_pm2_y, pvp0[0], pvp0[1]);
path.close();
- }
- else if(p < 1) {
+ } else if (p < 1) {
// p < 1
// support points, p0 to 0p
final double s_vp0_x = pvp0[0] - vd0[0] * kappay;
@@ -251,8 +242,7 @@ public class SVGHyperSphere {
path.cubicTo(s_vm0_x, s_vm0_y, s_v0m_x, s_v0m_y, pv0m[0], pv0m[1]);
path.cubicTo(s_v0m_x, s_v0m_y, s_vp0_x, s_vp0_y, pvp0[0], pvp0[1]);
path.close();
- }
- else {
+ } else {
// p == 1 - Manhattan
path.moveTo(pvp0[0], pvp0[1]);
path.lineTo(pv0p[0], pv0p[1]);
@@ -283,7 +273,7 @@ public class SVGHyperSphere {
final BitSet dims = proj.getVisibleDimensions2D();
SVGPath path = new SVGPath();
- for(int dim = dims.nextSetBit(0); dim >= 0; dim = dims.nextSetBit(dim + 1)) {
+ for (int dim = dims.nextSetBit(0); dim >= 0; dim = dims.nextSetBit(dim + 1)) {
v_mid[dim] += radius;
double[] p1 = proj.fastProjectDataToRenderSpace(v_mid);
v_mid[dim] -= radius;
@@ -296,4 +286,4 @@ public class SVGHyperSphere {
}
return path.makeElement(svgp);
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGPath.java b/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGPath.java
index 7c3e97e9..6937ab3e 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGPath.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGPath.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.svg;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,7 +27,9 @@ import org.apache.batik.util.SVGConstants;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
+import de.lmu.ifi.dbs.elki.data.spatial.Polygon;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.iterator.ArrayListIter;
/**
* Element used for building an SVG path using a string buffer.
@@ -132,9 +134,10 @@ public class SVGPath {
*
* @param vectors vectors
*/
- public SVGPath(Iterable<Vector> vectors) {
+ public SVGPath(Polygon vectors) {
this();
- for(Vector vec : vectors) {
+ for (ArrayListIter<Vector> it = vectors.iter(); it.valid(); it.advance()) {
+ Vector vec = it.get();
this.drawTo(vec.get(0), vec.get(1));
}
this.close();
@@ -151,10 +154,9 @@ public class SVGPath {
* @return path object, for compact syntax.
*/
public SVGPath drawTo(double x, double y) {
- if(!isStarted()) {
+ if (!isStarted()) {
moveTo(x, y);
- }
- else {
+ } else {
lineTo(x, y);
}
return this;
@@ -170,10 +172,9 @@ public class SVGPath {
* @return path object, for compact syntax.
*/
public SVGPath drawTo(double[] xy) {
- if(!isStarted()) {
+ if (!isStarted()) {
moveTo(xy);
- }
- else {
+ } else {
lineTo(xy);
}
return this;
@@ -189,10 +190,9 @@ public class SVGPath {
* @return path object, for compact syntax.
*/
public SVGPath drawTo(Vector xy) {
- if(!isStarted()) {
+ if (!isStarted()) {
moveTo(xy);
- }
- else {
+ } else {
lineTo(xy);
}
return this;
@@ -788,11 +788,11 @@ public class SVGPath {
* @param ds coordinates.
*/
private void append(String action, double... ds) {
- if(lastaction != action) {
+ if (lastaction != action) {
buf.append(action);
lastaction = action;
}
- for(double d : ds) {
+ for (double d : ds) {
buf.append(SVGUtil.FMT.format(d));
buf.append(' ');
}
@@ -804,7 +804,7 @@ public class SVGPath {
* @return path object, for compact syntax.
*/
public SVGPath close() {
- if(lastaction != SVGConstants.PATH_CLOSE) {
+ if (lastaction != SVGConstants.PATH_CLOSE) {
buf.append(SVGConstants.PATH_CLOSE);
lastaction = SVGConstants.PATH_CLOSE;
}
@@ -842,4 +842,4 @@ public class SVGPath {
public String toString() {
return buf.toString();
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGPlot.java b/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGPlot.java
index 43244047..44ec906b 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGPlot.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGPlot.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.svg;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -119,7 +119,7 @@ public class SVGPlot {
/**
* Manage objects with an id.
*/
- private HashMap<String, WeakReference<Element>> objWithId = new HashMap<String, WeakReference<Element>>();
+ private HashMap<String, WeakReference<Element>> objWithId = new HashMap<>();
/**
* Registers changes of this SVGPlot.
@@ -581,7 +581,7 @@ public class SVGPlot {
* @param obj Element
*/
public void putIdElement(String id, Element obj) {
- objWithId.put(id, new WeakReference<Element>(obj));
+ objWithId.put(id, new WeakReference<>(obj));
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGScoreBar.java b/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGScoreBar.java
index 3af2ea41..e421cafa 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGScoreBar.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGScoreBar.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.svg;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGSimpleLinearAxis.java b/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGSimpleLinearAxis.java
index 930e9e8e..3fd28d3d 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGSimpleLinearAxis.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGSimpleLinearAxis.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.svg;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGUtil.java b/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGUtil.java
index 633cb3e5..0e680e12 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGUtil.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGUtil.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.svg;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -43,6 +43,7 @@ import org.w3c.dom.svg.SVGMatrix;
import org.w3c.dom.svg.SVGPoint;
import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
+import de.lmu.ifi.dbs.elki.math.MathUtil;
/**
* Utility class for SVG processing.
@@ -87,7 +88,7 @@ public final class SVGUtil {
static {
// Build a reasonably sized hashmap. Use 0
- SVG_COLOR_NAMES = new TObjectIntHashMap<String>(90, .8f, NO_VALUE);
+ SVG_COLOR_NAMES = new TObjectIntHashMap<>(90, .8f, NO_VALUE);
// List taken from SVG specification:
// http://www.w3.org/TR/SVG/types.html#ColorKeywords
SVG_COLOR_NAMES.put("aliceblue", 0xFFF0F8FF);
@@ -512,18 +513,20 @@ public final class SVGUtil {
}
/**
- * Convert a color name from an AWT color object to CSS syntax
+ * Convert a color name from an integer RGB color to CSS syntax
*
- * Note: currently only RGB (from ARGB order) are supported.
+ * Note: currently only RGB (from ARGB order) are supported. The alpha channel
+ * will be ignored.
*
* @param col Color value
* @return Color string
*/
public static String colorToString(int col) {
- char[] buf = new char[] { '#', '0', '0', '0', '0', '0', '0' };
- for (int i = 7; i > 0; i--) {
- buf[i] += (col & 0xF);
- col >>= 4;
+ final char[] buf = new char[] { '#', 'X', 'X', 'X', 'X', 'X', 'X' };
+ for (int i = 6; i > 0; i--) {
+ final int v = (col & 0xF);
+ buf[i] = (char) ((v < 10) ? ('0' + v) : ('a' + v - 10));
+ col >>>= 4;
}
return new String(buf);
}
@@ -642,10 +645,10 @@ public final class SVGUtil {
*/
public static Element svgCircleSegment(SVGPlot svgp, double centerx, double centery, double angleStart, double angleDelta, double innerRadius, double outerRadius) {
double sin1st = Math.sin(angleStart);
- double cos1st = Math.cos(angleStart);
+ double cos1st = MathUtil.sinToCos(angleStart, sin1st);
double sin2nd = Math.sin(angleStart + angleDelta);
- double cos2nd = Math.cos(angleStart + angleDelta);
+ double cos2nd = MathUtil.sinToCos(angleStart + angleDelta, sin2nd);
double inner1stx = centerx + (innerRadius * sin1st);
double inner1sty = centery - (innerRadius * cos1st);
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/svg/UpdateRunner.java b/src/de/lmu/ifi/dbs/elki/visualization/svg/UpdateRunner.java
index 463c7c63..edf40621 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/svg/UpdateRunner.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/svg/UpdateRunner.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.svg;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -46,7 +46,7 @@ public class UpdateRunner {
/**
* The queue of pending updates
*/
- final private Queue<Runnable> queue = new ConcurrentLinkedQueue<Runnable>();
+ final private Queue<Runnable> queue = new ConcurrentLinkedQueue<>();
/**
* Synchronizer that can block events from being executed right away.
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/svg/UpdateSynchronizer.java b/src/de/lmu/ifi/dbs/elki/visualization/svg/UpdateSynchronizer.java
index 3f249871..a91fb142 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/svg/UpdateSynchronizer.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/svg/UpdateSynchronizer.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.svg;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/svg/VoronoiDraw.java b/src/de/lmu/ifi/dbs/elki/visualization/svg/VoronoiDraw.java
index 2997456d..e5824fba 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/svg/VoronoiDraw.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/svg/VoronoiDraw.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.visualization.svg;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/svg/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/svg/package-info.java
index 7811b493..7f816cff 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/svg/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/svg/package-info.java
@@ -6,7 +6,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/AbstractVisFactory.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/AbstractVisFactory.java
index 565cf784..320ecd4c 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/AbstractVisFactory.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/AbstractVisFactory.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/AbstractVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/AbstractVisualization.java
index b023827d..cad9283e 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/AbstractVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/AbstractVisualization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/StaticVisualizationInstance.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/StaticVisualizationInstance.java
index 3cd24289..8c7ad9a7 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/StaticVisualizationInstance.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/StaticVisualizationInstance.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/VisFactory.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/VisFactory.java
index eb675951..c65a1c63 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/VisFactory.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/VisFactory.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/Visualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/Visualization.java
index d2d1e5fe..5c1be0ab 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/Visualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/Visualization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/VisualizerUtil.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/VisualizerUtil.java
index 389aec52..947f5841 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/VisualizerUtil.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/VisualizerUtil.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,18 +23,9 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.Iterator;
import java.util.List;
-import de.lmu.ifi.dbs.elki.data.NumberVector;
-import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
-import de.lmu.ifi.dbs.elki.data.type.VectorFieldTypeInformation;
-import de.lmu.ifi.dbs.elki.database.relation.Relation;
-import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
-import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
-import de.lmu.ifi.dbs.elki.result.Result;
import de.lmu.ifi.dbs.elki.result.ResultUtil;
-import de.lmu.ifi.dbs.elki.utilities.iterator.AbstractFilteredIterator;
import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
import de.lmu.ifi.dbs.elki.visualization.VisualizerContext;
@@ -48,43 +39,12 @@ import de.lmu.ifi.dbs.elki.visualization.VisualizerContext;
public final class VisualizerUtil {
/**
* Fake constructor: do not instantiate.
- *
*/
private VisualizerUtil() {
// Do not instantiate.
}
/**
- * Find the visualizer context in a result tree.
- *
- * @param baseResult base result to start searching at.
- * @return Visualizer context
- */
- public static VisualizerContext getContext(HierarchicalResult baseResult) {
- List<VisualizerContext> contexts = ResultUtil.filterResults(baseResult, VisualizerContext.class);
- if (!contexts.isEmpty()) {
- return contexts.get(0);
- } else {
- return null;
- }
- }
-
- /**
- * Utility function to change Visualizer visibility.
- *
- * @param task Visualization task
- * @param visibility Visibility value
- */
- public static void setVisible(VisualizationTask task, boolean visibility) {
- VisualizerContext context = task.getContext();
- if (context != null) {
- setVisible(context, task, visibility);
- } else {
- LoggingUtil.warning("setVisible called without context in task.", new Throwable());
- }
- }
-
- /**
* Utility function to change Visualizer visibility.
*
* @param context Visualization context
@@ -104,59 +64,5 @@ public final class VisualizerUtil {
}
task.visible = visibility;
context.getHierarchy().resultChanged(task);
- }
-
- /**
- * Filter for number vector field representations.
- *
- * @param result Result to filter
- * @return Iterator over suitable representations
- */
- // TODO: move to DatabaseUtil?
- public static Iterator<Relation<? extends NumberVector<?>>> iterateVectorFieldRepresentations(final Result result) {
- List<Relation<?>> parent = ResultUtil.filterResults(result, Relation.class);
- return new VectorspaceIterator(parent.iterator());
- }
-
- /**
- * Iterate over vectorspace.
- *
- * @author Erich Schubert
- *
- * @apiviz.exclude
- */
- private static class VectorspaceIterator extends AbstractFilteredIterator<Relation<?>, Relation<? extends NumberVector<?>>> {
- /**
- * Parent iterator.
- */
- private Iterator<Relation<?>> parent;
-
- /**
- * Constructor.
- *
- * @param parent Parent iterator
- */
- public VectorspaceIterator(Iterator<Relation<?>> parent) {
- super();
- this.parent = parent;
- }
-
- @Override
- protected Iterator<Relation<?>> getParentIterator() {
- return parent;
- }
-
- @SuppressWarnings("unchecked")
- @Override
- protected Relation<? extends NumberVector<?>> testFilter(Relation<?> nextobj) {
- final SimpleTypeInformation<?> type = nextobj.getDataTypeInformation();
- if (!NumberVector.class.isAssignableFrom(type.getRestrictionClass())) {
- return null;
- }
- if (!(type instanceof VectorFieldTypeInformation)) {
- return null;
- }
- return (Relation<? extends NumberVector<?>>) nextobj;
- }
};
}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/histogram/AbstractHistogramVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/histogram/AbstractHistogramVisualization.java
index 95df9533..8d3616ac 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/histogram/AbstractHistogramVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/histogram/AbstractHistogramVisualization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.histogram;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/histogram/ColoredHistogramVisualizer.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/histogram/ColoredHistogramVisualizer.java
index 7a52c8b3..fd7edbd4 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/histogram/ColoredHistogramVisualizer.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/histogram/ColoredHistogramVisualizer.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.histogram;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/histogram/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/histogram/package-info.java
index 4489904f..0379a762 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/histogram/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/histogram/package-info.java
@@ -6,7 +6,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/AbstractOPTICSVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/AbstractOPTICSVisualization.java
index 329fc64a..d734fc9e 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/AbstractOPTICSVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/AbstractOPTICSVisualization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.optics;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -78,7 +78,7 @@ public abstract class AbstractOPTICSVisualization<D extends Distance<D>> extends
plotheight = StyleLibrary.SCALE / optics.getOPTICSPlot(context).getRatio();
final double margin = context.getStyleResult().getStyleLibrary().getSize(StyleLibrary.MARGIN);
layer = SVGUtil.svgElement(svgp.getDocument(), SVGConstants.SVG_G_TAG);
- final String transform = SVGUtil.makeMarginTransform(task.getWidth(), task.getHeight(), plotwidth, plotheight, margin * .5);
+ final String transform = SVGUtil.makeMarginTransform(task.getWidth(), task.getHeight(), plotwidth, plotheight, margin * .5, margin * .5, margin * 1.5, margin * .5);
SVGUtil.setAtt(layer, SVGConstants.SVG_TRANSFORM_ATTRIBUTE, transform);
}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSClusterVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSClusterVisualization.java
index e771e380..dd4462c9 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSClusterVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSClusterVisualization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.optics;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,7 +25,6 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.optics;
import java.util.Collection;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
import org.apache.batik.util.SVGConstants;
@@ -40,6 +39,7 @@ import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
import de.lmu.ifi.dbs.elki.result.Result;
import de.lmu.ifi.dbs.elki.result.ResultUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.Hierarchy;
import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
import de.lmu.ifi.dbs.elki.visualization.colors.ColorLibrary;
import de.lmu.ifi.dbs.elki.visualization.css.CSSClass;
@@ -80,9 +80,9 @@ public class OPTICSClusterVisualization extends AbstractVisFactory {
@Override
public void processNewResult(HierarchicalResult baseResult, Result result) {
Collection<OPTICSProjector<?>> ops = ResultUtil.filterResults(result, OPTICSProjector.class);
- for(OPTICSProjector<?> p : ops) {
+ for (OPTICSProjector<?> p : ops) {
final Clustering<OPTICSModel> ocl = findOPTICSClustering(baseResult);
- if(ocl != null) {
+ if (ocl != null) {
final VisualizationTask task = new VisualizationTask(NAME, ocl, null, this);
task.level = VisualizationTask.LEVEL_DATA;
baseResult.getHierarchy().add(p, task);
@@ -112,17 +112,16 @@ public class OPTICSClusterVisualization extends AbstractVisFactory {
@SuppressWarnings("unchecked")
protected static Clustering<OPTICSModel> findOPTICSClustering(Result result) {
Collection<Clustering<?>> cs = ResultUtil.filterResults(result, Clustering.class);
- for(Clustering<?> clus : cs) {
- if(clus.getToplevelClusters().size() == 0) {
+ for (Clustering<?> clus : cs) {
+ if (clus.getToplevelClusters().size() == 0) {
continue;
}
try {
Cluster<?> firstcluster = clus.getToplevelClusters().iterator().next();
- if(firstcluster.getModel() instanceof OPTICSModel) {
+ if (firstcluster.getModel() instanceof OPTICSModel) {
return (Clustering<OPTICSModel>) clus;
}
- }
- catch(Exception e) {
+ } catch (Exception e) {
// Empty clustering? Shouldn't happen.
LOG.warning("Clustering with no cluster detected.", e);
}
@@ -168,13 +167,13 @@ public class OPTICSClusterVisualization extends AbstractVisFactory {
addCSSClasses();
ColorLibrary colors = context.getStyleResult().getStyleLibrary().getColorSet(StyleLibrary.PLOT);
- HashMap<Cluster<?>, String> colormap = new HashMap<Cluster<?>, String>();
+ HashMap<Cluster<?>, String> colormap = new HashMap<>();
int cnum = 0;
- for(Cluster<?> c : clus.getAllClusters()) {
+ for (Cluster<?> c : clus.getAllClusters()) {
colormap.put(c, colors.getColor(cnum));
cnum++;
}
- drawClusters(clus.getToplevelClusters(), 1, colormap);
+ drawClusters(clus, clus.iterToplevelClusters(), 1, colormap);
}
/**
@@ -184,10 +183,11 @@ public class OPTICSClusterVisualization extends AbstractVisFactory {
* @param depth Recursion depth
* @param colormap Color mapping
*/
- private void drawClusters(List<Cluster<OPTICSModel>> clusters, int depth, Map<Cluster<?>, String> colormap) {
+ private void drawClusters(Clustering<OPTICSModel> clustering, Hierarchy.Iter<Cluster<OPTICSModel>> clusters, int depth, Map<Cluster<?>, String> colormap) {
final double scale = StyleLibrary.SCALE;
- for(Cluster<OPTICSModel> cluster : clusters) {
+ for (; clusters.valid(); clusters.advance()) {
+ Cluster<OPTICSModel> cluster = clusters.get();
try {
OPTICSModel model = cluster.getModel();
final double x1 = plotwidth * ((model.getStartIndex() + .25) / this.optics.getResult().getClusterOrder().size());
@@ -196,18 +196,17 @@ public class OPTICSClusterVisualization extends AbstractVisFactory {
Element e = svgp.svgLine(x1, y, x2, y);
SVGUtil.addCSSClass(e, CSS_BRACKET);
String color = colormap.get(cluster);
- if(color != null) {
+ if (color != null) {
SVGUtil.setAtt(e, SVGConstants.SVG_STYLE_ATTRIBUTE, SVGConstants.CSS_STROKE_PROPERTY + ":" + color);
}
layer.appendChild(e);
- }
- catch(ClassCastException e) {
+ } catch (ClassCastException e) {
LOG.warning("Expected OPTICSModel, got: " + cluster.getModel().getClass().getSimpleName());
}
// Descend
- final List<Cluster<OPTICSModel>> children = cluster.getChildren();
- if(children != null) {
- drawClusters(children, depth + 1, colormap);
+ final Hierarchy.Iter<Cluster<OPTICSModel>> children = clustering.getClusterHierarchy().iterChildren(cluster);
+ if (children != null) {
+ drawClusters(clustering, children, depth + 1, colormap);
}
}
}
@@ -217,7 +216,7 @@ public class OPTICSClusterVisualization extends AbstractVisFactory {
*/
private void addCSSClasses() {
// Class for the markers
- if(!svgp.getCSSClassManager().contains(CSS_BRACKET)) {
+ if (!svgp.getCSSClassManager().contains(CSS_BRACKET)) {
final CSSClass cls = new CSSClass(this, CSS_BRACKET);
final StyleLibrary style = context.getStyleResult().getStyleLibrary();
cls.setStatement(SVGConstants.CSS_STROKE_PROPERTY, style.getColor(StyleLibrary.PLOT));
@@ -226,4 +225,4 @@ public class OPTICSClusterVisualization extends AbstractVisFactory {
}
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSPlotCutVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSPlotCutVisualization.java
index 739e0ccd..e53c4c9d 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSPlotCutVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSPlotCutVisualization.java
@@ -66,6 +66,9 @@ public class OPTICSPlotCutVisualization extends AbstractVisFactory {
*/
private static final String NAME = "OPTICS Cut";
+ /**
+ * Constructor.
+ */
public OPTICSPlotCutVisualization() {
super();
}
@@ -73,7 +76,7 @@ public class OPTICSPlotCutVisualization extends AbstractVisFactory {
@Override
public void processNewResult(HierarchicalResult baseResult, Result result) {
Collection<OPTICSProjector<?>> ops = ResultUtil.filterResults(result, OPTICSProjector.class);
- for(OPTICSProjector<?> p : ops) {
+ for (OPTICSProjector<?> p : ops) {
final VisualizationTask task = new VisualizationTask(NAME, p, null, this);
task.level = VisualizationTask.LEVEL_INTERACTIVE;
baseResult.getHierarchy().add(p, task);
@@ -151,7 +154,7 @@ public class OPTICSPlotCutVisualization extends AbstractVisFactory {
@Override
protected void incrementalRedraw() {
- if(layer == null) {
+ if (layer == null) {
makeLayerElement();
addCSSClasses();
}
@@ -161,36 +164,33 @@ public class OPTICSPlotCutVisualization extends AbstractVisFactory {
// compute absolute y-value of bar
final double yAct = plotheight - getYFromEpsilon(epsilon);
- if(elemText == null) {
+ if (elemText == null) {
elemText = svgp.svgText(StyleLibrary.SCALE * 1.05, yAct, label);
SVGUtil.setAtt(elemText, SVGConstants.SVG_CLASS_ATTRIBUTE, CSS_EPSILON);
layer.appendChild(elemText);
- }
- else {
+ } else {
elemText.setTextContent(label);
SVGUtil.setAtt(elemText, SVGConstants.SVG_Y_ATTRIBUTE, yAct);
}
// line and handle
- if(elementLine == null) {
+ if (elementLine == null) {
elementLine = svgp.svgLine(0, yAct, StyleLibrary.SCALE * 1.04, yAct);
SVGUtil.addCSSClass(elementLine, CSS_LINE);
layer.appendChild(elementLine);
- }
- else {
+ } else {
SVGUtil.setAtt(elementLine, SVG12Constants.SVG_Y1_ATTRIBUTE, yAct);
SVGUtil.setAtt(elementLine, SVG12Constants.SVG_Y2_ATTRIBUTE, yAct);
}
- if(elementPoint == null) {
+ if (elementPoint == null) {
elementPoint = svgp.svgCircle(StyleLibrary.SCALE * 1.04, yAct, StyleLibrary.SCALE * 0.004);
SVGUtil.addCSSClass(elementPoint, CSS_LINE);
layer.appendChild(elementPoint);
- }
- else {
+ } else {
SVGUtil.setAtt(elementPoint, SVG12Constants.SVG_CY_ATTRIBUTE, yAct);
}
- if(eventarea == null) {
+ if (eventarea == null) {
eventarea = new DragableArea(svgp, StyleLibrary.SCALE, 0, StyleLibrary.SCALE * 0.1, plotheight, this);
layer.appendChild(eventarea.getElement());
}
@@ -209,10 +209,10 @@ public class OPTICSPlotCutVisualization extends AbstractVisFactory {
* @return epsilon
*/
protected double getEpsilonFromY(double y) {
- if(y < 0) {
+ if (y < 0) {
y = 0;
}
- if(y > plotheight) {
+ if (y > plotheight) {
y = plotheight;
}
return optics.getOPTICSPlot(context).getScale().getUnscaled(y / plotheight);
@@ -226,10 +226,10 @@ public class OPTICSPlotCutVisualization extends AbstractVisFactory {
*/
protected double getYFromEpsilon(double epsilon) {
double y = optics.getOPTICSPlot(context).getScale().getScaled(epsilon) * plotheight;
- if(y < 0) {
+ if (y < 0) {
y = 0;
}
- if(y > plotheight) {
+ if (y > plotheight) {
y = plotheight;
}
return y;
@@ -245,7 +245,7 @@ public class OPTICSPlotCutVisualization extends AbstractVisFactory {
@Override
public boolean duringDrag(SVGPoint start, SVGPoint end, Event evt, boolean inside) {
- if(inside) {
+ if (inside) {
epsilon = getEpsilonFromY(plotheight - end.getY());
}
// opvis.unsetEpsilonExcept(this);
@@ -255,7 +255,7 @@ public class OPTICSPlotCutVisualization extends AbstractVisFactory {
@Override
public boolean endDrag(SVGPoint start, SVGPoint end, Event evt, boolean inside) {
- if(inside) {
+ if (inside) {
epsilon = getEpsilonFromY(plotheight - end.getY());
// opvis.unsetEpsilonExcept(this);
@@ -264,8 +264,7 @@ public class OPTICSPlotCutVisualization extends AbstractVisFactory {
Clustering<Model> cl = OPTICSCut.makeOPTICSCut(order, optics.getOPTICSPlot(context).getDistanceAdapter(), epsilon);
order.addChildResult(cl);
}
- context.getHierarchy().resultChanged(this.task);
- // synchronizedRedraw();
+ synchronizedRedraw();
return true;
}
@@ -282,7 +281,7 @@ public class OPTICSPlotCutVisualization extends AbstractVisFactory {
private void addCSSClasses() {
// Class for the epsilon-value
final StyleLibrary style = context.getStyleResult().getStyleLibrary();
- if(!svgp.getCSSClassManager().contains(CSS_EPSILON)) {
+ if (!svgp.getCSSClassManager().contains(CSS_EPSILON)) {
final CSSClass label = new CSSClass(svgp, CSS_EPSILON);
label.setStatement(SVGConstants.CSS_FILL_PROPERTY, style.getTextColor(StyleLibrary.AXIS_LABEL));
label.setStatement(SVGConstants.CSS_FONT_FAMILY_PROPERTY, style.getFontFamily(StyleLibrary.AXIS_LABEL));
@@ -290,7 +289,7 @@ public class OPTICSPlotCutVisualization extends AbstractVisFactory {
svgp.addCSSClassOrLogError(label);
}
// Class for the epsilon cut line
- if(!svgp.getCSSClassManager().contains(CSS_LINE)) {
+ if (!svgp.getCSSClassManager().contains(CSS_LINE)) {
final CSSClass lcls = new CSSClass(svgp, CSS_LINE);
lcls.setStatement(SVGConstants.CSS_STROKE_PROPERTY, style.getColor(StyleLibrary.PLOT));
lcls.setStatement(SVGConstants.CSS_STROKE_WIDTH_PROPERTY, 0.5 * style.getLineWidth(StyleLibrary.PLOT));
@@ -298,4 +297,4 @@ public class OPTICSPlotCutVisualization extends AbstractVisFactory {
}
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSPlotVisualizer.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSPlotVisualizer.java
index cde2d89d..6a834cb8 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSPlotVisualizer.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSPlotVisualizer.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.optics;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSSteepAreaVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSSteepAreaVisualization.java
index e6e00960..d587b554 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSSteepAreaVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSSteepAreaVisualization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.optics;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -41,6 +41,7 @@ import de.lmu.ifi.dbs.elki.result.ResultUtil;
import de.lmu.ifi.dbs.elki.result.SelectionResult;
import de.lmu.ifi.dbs.elki.result.optics.ClusterOrderEntry;
import de.lmu.ifi.dbs.elki.result.optics.ClusterOrderResult;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.Hierarchy;
import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
import de.lmu.ifi.dbs.elki.visualization.css.CSSClass;
import de.lmu.ifi.dbs.elki.visualization.opticsplot.OPTICSDistanceAdapter;
@@ -76,9 +77,9 @@ public class OPTICSSteepAreaVisualization extends AbstractVisFactory {
@Override
public void processNewResult(HierarchicalResult baseResult, Result result) {
Collection<OPTICSProjector<?>> ops = ResultUtil.filterResults(result, OPTICSProjector.class);
- for(OPTICSProjector<?> p : ops) {
+ for (OPTICSProjector<?> p : ops) {
final SteepAreaResult steep = findSteepAreaResult(p.getResult());
- if(steep != null) {
+ if (steep != null) {
final VisualizationTask task = new VisualizationTask(NAME, p, null, this);
task.level = VisualizationTask.LEVEL_DATA + 1;
task.initDefaultVisibility(false);
@@ -106,9 +107,9 @@ public class OPTICSSteepAreaVisualization extends AbstractVisFactory {
* @return OPTICS clustering
*/
protected static OPTICSXi.SteepAreaResult findSteepAreaResult(ClusterOrderResult<?> co) {
- for(Result r : co.getHierarchy().getChildren(co)) {
- if(OPTICSXi.SteepAreaResult.class.isInstance(r)) {
- return (OPTICSXi.SteepAreaResult) r;
+ for (Hierarchy.Iter<Result> r = co.getHierarchy().iterChildren(co); r.valid(); r.advance()) {
+ if (OPTICSXi.SteepAreaResult.class.isInstance(r.get())) {
+ return (OPTICSXi.SteepAreaResult) r.get();
}
}
return null;
@@ -160,7 +161,7 @@ public class OPTICSSteepAreaVisualization extends AbstractVisFactory {
final OPTICSDistanceAdapter<D> adapter = opticsplot.getDistanceAdapter();
final LinearScale scale = opticsplot.getScale();
- for(OPTICSXi.SteepArea area : areas) {
+ for (OPTICSXi.SteepArea area : areas) {
final int st = area.getStartIndex();
final int en = area.getEndIndex();
// Note: make sure we are using doubles!
@@ -171,10 +172,9 @@ public class OPTICSSteepAreaVisualization extends AbstractVisFactory {
final double y1 = (!Double.isInfinite(d1) && !Double.isNaN(d1)) ? (1. - scale.getScaled(d1)) : 0.;
final double y2 = (!Double.isInfinite(d2) && !Double.isNaN(d2)) ? (1. - scale.getScaled(d2)) : 0.;
Element e = svgp.svgLine(plotwidth * x1, plotheight * y1, plotwidth * x2, plotheight * y2);
- if(area instanceof OPTICSXi.SteepDownArea) {
+ if (area instanceof OPTICSXi.SteepDownArea) {
SVGUtil.addCSSClass(e, CSS_STEEP_DOWN);
- }
- else {
+ } else {
SVGUtil.addCSSClass(e, CSS_STEEP_UP);
}
layer.appendChild(e);
@@ -187,10 +187,10 @@ public class OPTICSSteepAreaVisualization extends AbstractVisFactory {
private void addCSSClasses() {
// Class for the markers
final StyleLibrary style = context.getStyleResult().getStyleLibrary();
- if(!svgp.getCSSClassManager().contains(CSS_STEEP_DOWN)) {
+ if (!svgp.getCSSClassManager().contains(CSS_STEEP_DOWN)) {
final CSSClass cls = new CSSClass(this, CSS_STEEP_DOWN);
Color color = SVGUtil.stringToColor(style.getColor(StyleLibrary.PLOT));
- if(color == null) {
+ if (color == null) {
color = Color.BLACK;
}
color = new Color((int) (color.getRed() * 0.8), (int) (color.getGreen() * 0.8 + 0.2 * 256.), (int) (color.getBlue() * 0.8));
@@ -198,10 +198,10 @@ public class OPTICSSteepAreaVisualization extends AbstractVisFactory {
cls.setStatement(SVGConstants.CSS_STROKE_WIDTH_PROPERTY, style.getLineWidth(StyleLibrary.PLOT));
svgp.addCSSClassOrLogError(cls);
}
- if(!svgp.getCSSClassManager().contains(CSS_STEEP_UP)) {
+ if (!svgp.getCSSClassManager().contains(CSS_STEEP_UP)) {
final CSSClass cls = new CSSClass(this, CSS_STEEP_UP);
Color color = SVGUtil.stringToColor(style.getColor(StyleLibrary.PLOT));
- if(color == null) {
+ if (color == null) {
color = Color.BLACK;
}
color = new Color((int) (color.getRed() * 0.8 + 0.2 * 256.), (int) (color.getGreen() * 0.8), (int) (color.getBlue() * 0.8));
@@ -213,11 +213,11 @@ public class OPTICSSteepAreaVisualization extends AbstractVisFactory {
@Override
public void resultChanged(Result current) {
- if(current instanceof SelectionResult) {
+ if (current instanceof SelectionResult) {
synchronizedRedraw();
return;
}
super.resultChanged(current);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/package-info.java
index 642f817c..6cae6baa 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/package-info.java
index d5dad85b..486ecffc 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/package-info.java
@@ -9,7 +9,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/pairsegments/CircleSegmentsVisualizer.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/pairsegments/CircleSegmentsVisualizer.java
index 400b8ebb..9718925f 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/pairsegments/CircleSegmentsVisualizer.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/pairsegments/CircleSegmentsVisualizer.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.pairsegments;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -227,7 +227,7 @@ public class CircleSegmentsVisualizer extends AbstractVisFactory {
/**
* Map to connect segments to their visual elements
*/
- public Map<Segment, List<Element>> segmentToElements = new HashMap<Segment, List<Element>>();
+ public Map<Segment, List<Element>> segmentToElements = new HashMap<>();
/**
* Show unclustered Pairs in CircleSegments
@@ -412,7 +412,7 @@ public class CircleSegmentsVisualizer extends AbstractVisFactory {
// ITERATE OVER ALL SEGMENT-CLUSTERS
- ArrayList<Element> elems = new ArrayList<Element>(clusterings);
+ ArrayList<Element> elems = new ArrayList<>(clusterings);
segmentToElements.put(segment, elems);
// draw segment for every clustering
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/pairsegments/SegmentsStylingPolicy.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/pairsegments/SegmentsStylingPolicy.java
index 0ea700c8..4dc35180 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/pairsegments/SegmentsStylingPolicy.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/pairsegments/SegmentsStylingPolicy.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.pairsegments;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -56,12 +56,12 @@ public class SegmentsStylingPolicy implements ClassStylingPolicy, Result {
/**
* Selected segments
*/
- protected ArrayList<Segment> selectedSegments = new ArrayList<Segment>();
+ protected ArrayList<Segment> selectedSegments = new ArrayList<>();
/**
* Segments indirectly selected
*/
- protected TreeMap<Segment, Segment> indirectSelections = new TreeMap<Segment, Segment>();
+ protected TreeMap<Segment, Segment> indirectSelections = new TreeMap<>();
/**
* Not selected IDs that will be drawn in default colors.
@@ -165,6 +165,20 @@ public class SegmentsStylingPolicy implements ClassStylingPolicy, Result {
return (ids != null) ? ids.iter() : DBIDUtil.EMPTYDBIDS.iter();
}
+ @Override
+ public int classSize(int cnum) {
+ // unselected
+ if(cnum == -2) {
+ return unselectedObjects.size();
+ }
+ else if(cnum == -1) {
+ return 0;
+ }
+ // colors
+ DBIDs ids = selectedSegments.get(cnum).getDBIDs();
+ return (ids != null) ? ids.size() : 0;
+ }
+
/**
* Adds or removes the given segment to the selection. Depending on the
* clustering and cluster selected and the addToSelection option given, the
@@ -239,7 +253,7 @@ public class SegmentsStylingPolicy implements ClassStylingPolicy, Result {
*/
protected void deselectSegment(Segment segment) {
if(segment.isUnpaired()) {
- ArrayList<Segment> remove = new ArrayList<Segment>();
+ ArrayList<Segment> remove = new ArrayList<>();
// remove all object segments associated with unpaired segment from
// selection list
for(Entry<Segment, Segment> entry : indirectSelections.entrySet()) {
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/pairsegments/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/pairsegments/package-info.java
index c0c71dd3..967ed347 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/pairsegments/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/pairsegments/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/AxisVisibilityVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/AxisVisibilityVisualization.java
index ea68d660..3c78120a 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/AxisVisibilityVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/AxisVisibilityVisualization.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.parallel;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/cluster/ClusterOutlineVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/cluster/ClusterOutlineVisualization.java
index 47a6d9a8..10aa6309 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/cluster/ClusterOutlineVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/cluster/ClusterOutlineVisualization.java
@@ -35,6 +35,7 @@ import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.data.model.Model;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreListener;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
import de.lmu.ifi.dbs.elki.result.Result;
@@ -65,7 +66,7 @@ public class ClusterOutlineVisualization extends AbstractVisFactory {
/**
* A short name characterizing this Visualizer.
*/
- public static final String NAME = "Cluster Outline";
+ public static final String NAME = "Parallel Cluster Outline";
/**
* Currently unused option to enable/disable rounding
@@ -169,6 +170,10 @@ public class ClusterOutlineVisualization extends AbstractVisFactory {
Iterator<Cluster<Model>> ci = clustering.getAllClusters().iterator();
for(int cnum = 0; cnum < clustering.getAllClusters().size(); cnum++) {
Cluster<?> clus = ci.next();
+ final DBIDs ids = clus.getIDs();
+ if (ids.size() < 1) {
+ continue;
+ }
for(int i = 0; i < dim; i++) {
mms[i].reset();
if(i < dim - 1) {
@@ -178,7 +183,7 @@ public class ClusterOutlineVisualization extends AbstractVisFactory {
// Process points
// TODO: do this just once, cache the result somewhere appropriately?
- for(DBIDIter id = clus.getIDs().iter(); id.valid(); id.advance()) {
+ for(DBIDIter id = ids.iter(); id.valid(); id.advance()) {
double[] yPos = proj.fastProjectDataToRenderSpace(relation.get(id));
for(int i = 0; i < dim; i++) {
mms[i].put(yPos[i]);
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/cluster/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/cluster/package-info.java
index 7977da0c..0ae97b92 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/cluster/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/cluster/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/index/RTreeParallelVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/index/RTreeParallelVisualization.java
index 7c2c8b9f..04676905 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/index/RTreeParallelVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/index/RTreeParallelVisualization.java
@@ -96,8 +96,8 @@ public class RTreeParallelVisualization extends AbstractVisFactory {
@Override
public void processNewResult(HierarchicalResult baseResult, Result result) {
- ArrayList<AbstractRStarTree<RStarTreeNode, SpatialEntry>> trees = ResultUtil.filterResults(result, AbstractRStarTree.class);
- for(AbstractRStarTree<RStarTreeNode, SpatialEntry> tree : trees) {
+ ArrayList<AbstractRStarTree<RStarTreeNode, SpatialEntry, ?>> trees = ResultUtil.filterResults(result, AbstractRStarTree.class);
+ for(AbstractRStarTree<RStarTreeNode, SpatialEntry, ?> tree : trees) {
if(tree instanceof Result) {
Collection<ParallelPlotProjector<?>> ps = ResultUtil.filterResults(baseResult, ParallelPlotProjector.class);
for(ParallelPlotProjector<?> p : ps) {
@@ -125,7 +125,7 @@ public class RTreeParallelVisualization extends AbstractVisFactory {
/**
* The tree we visualize
*/
- protected AbstractRStarTree<N, E> tree;
+ protected AbstractRStarTree<N, E, ?> tree;
/**
* Constructor.
@@ -201,7 +201,7 @@ public class RTreeParallelVisualization extends AbstractVisFactory {
* @param entry Current entry
* @param depth Current depth
*/
- private void visualizeRTreeEntry(SVGPlot svgp, Element layer, ProjectionParallel proj, AbstractRStarTree<? extends N, E> rtree, E entry, int depth, int step) {
+ private void visualizeRTreeEntry(SVGPlot svgp, Element layer, ProjectionParallel proj, AbstractRStarTree<? extends N, E, ?> rtree, E entry, int depth, int step) {
final int dim = proj.getVisibleDimensions();
double[] min = proj.fastProjectDataToRenderSpace(SpatialUtil.getMin(entry));
double[] max = proj.fastProjectDataToRenderSpace(SpatialUtil.getMax(entry));
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/index/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/index/package-info.java
index 1cefd6f0..93c1e75b 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/index/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/index/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/package-info.java
index 0ab7d565..d46f1a94 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/package-info.java
@@ -6,7 +6,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/selection/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/selection/package-info.java
index e4589b05..52acab59 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/selection/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/selection/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/AbstractScatterplotVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/AbstractScatterplotVisualization.java
index 8cedcf0b..1f2d89d7 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/AbstractScatterplotVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/AbstractScatterplotVisualization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/AbstractTooltipVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/AbstractTooltipVisualization.java
index 107af095..332f31e1 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/AbstractTooltipVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/AbstractTooltipVisualization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/AxisVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/AxisVisualization.java
index f08c4b2d..dd3f2218 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/AxisVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/AxisVisualization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/MarkerVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/MarkerVisualization.java
index f2140502..964500ec 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/MarkerVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/MarkerVisualization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -69,7 +69,7 @@ public class MarkerVisualization extends AbstractVisFactory {
*/
public MarkerVisualization() {
super();
- thumbmask |= ThumbnailVisualization.ON_DATA | ThumbnailVisualization.ON_STYLE;
+ this.thumbmask |= ThumbnailVisualization.ON_DATA | ThumbnailVisualization.ON_STYLE;
}
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/PolygonVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/PolygonVisualization.java
index 0fc99bbc..8037eae6 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/PolygonVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/PolygonVisualization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -39,6 +39,7 @@ import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
import de.lmu.ifi.dbs.elki.result.Result;
import de.lmu.ifi.dbs.elki.result.ResultUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.iterator.ArrayListIter;
import de.lmu.ifi.dbs.elki.utilities.exceptions.ObjectNotFoundException;
import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
import de.lmu.ifi.dbs.elki.visualization.css.CSSClass;
@@ -155,11 +156,11 @@ public class PolygonVisualization extends AbstractVisFactory {
Vector first = ppoly.get(0);
double[] f = proj.fastProjectDataToRenderSpace(first.getArrayRef());
path.moveTo(f[0], f[1]);
- for(Vector v : ppoly) {
- if(v == first) {
+ for(ArrayListIter<Vector> it = ppoly.iter(); it.valid(); it.advance()) {
+ if(it.getOffset() == 0) {
continue;
}
- double[] p = proj.fastProjectDataToRenderSpace(v.getArrayRef());
+ double[] p = proj.fastProjectDataToRenderSpace(it.get().getArrayRef());
path.drawTo(p[0], p[1]);
}
// close path.
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/ReferencePointsVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/ReferencePointsVisualization.java
index 94c1c8d2..b3a66582 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/ReferencePointsVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/ReferencePointsVisualization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/ToolBox2DVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/ToolBox2DVisualization.java
index 352e79de..55727c46 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/ToolBox2DVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/ToolBox2DVisualization.java
@@ -159,7 +159,7 @@ public class ToolBox2DVisualization extends AbstractVisFactory {
double scale = StyleLibrary.SCALE;
deleteChildren(container);
- ArrayList<VisualizationTask> vis = new ArrayList<VisualizationTask>();
+ ArrayList<VisualizationTask> vis = new ArrayList<>();
Collection<VisualizationTask> visualizers = ResultUtil.filterResults(task.getResult(), VisualizationTask.class);
for(VisualizationTask task : visualizers) {
if(task.tool && !vis.contains(task)) {
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/TooltipScoreVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/TooltipScoreVisualization.java
index f3f35002..bcf0dc71 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/TooltipScoreVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/TooltipScoreVisualization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -37,6 +37,7 @@ import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
import de.lmu.ifi.dbs.elki.result.Result;
import de.lmu.ifi.dbs.elki.result.ResultUtil;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.Hierarchy;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterEqualConstraint;
@@ -113,8 +114,8 @@ public class TooltipScoreVisualization extends AbstractVisFactory {
}
// Skip if we already considered it above
boolean add = true;
- for(Result p : baseResult.getHierarchy().getChildren(r)) {
- if(p instanceof VisualizationTask && ((VisualizationTask) p).getFactory() instanceof TooltipScoreVisualization) {
+ for(Hierarchy.Iter<Result> p = baseResult.getHierarchy().iterChildren(r); p.valid(); p.advance()) {
+ if(p.get() instanceof VisualizationTask && ((VisualizationTask) p.get()).getFactory() instanceof TooltipScoreVisualization) {
add = false;
break;
}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/TooltipStringVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/TooltipStringVisualization.java
index 979ce905..42da21d9 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/TooltipStringVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/TooltipStringVisualization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/ClusterHullVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/ClusterHullVisualization.java
index ebaf9eb9..123ed7d9 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/ClusterHullVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/ClusterHullVisualization.java
@@ -25,14 +25,16 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.cluster;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.Iterator;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import org.apache.batik.util.SVGConstants;
import org.w3c.dom.Element;
import de.lmu.ifi.dbs.elki.data.Cluster;
import de.lmu.ifi.dbs.elki.data.Clustering;
+import de.lmu.ifi.dbs.elki.data.model.CoreObjectsModel;
import de.lmu.ifi.dbs.elki.data.model.Model;
import de.lmu.ifi.dbs.elki.data.spatial.Polygon;
import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil;
@@ -44,23 +46,31 @@ import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
import de.lmu.ifi.dbs.elki.result.Result;
import de.lmu.ifi.dbs.elki.result.ResultUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.Hierarchy;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.Hierarchy.Iter;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.iterator.ArrayListIter;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleParameter;
+import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleObjPair;
import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
import de.lmu.ifi.dbs.elki.visualization.colors.ColorLibrary;
import de.lmu.ifi.dbs.elki.visualization.css.CSSClass;
import de.lmu.ifi.dbs.elki.visualization.projections.CanvasSize;
import de.lmu.ifi.dbs.elki.visualization.projections.Projection;
import de.lmu.ifi.dbs.elki.visualization.projector.ScatterPlotProjector;
+import de.lmu.ifi.dbs.elki.visualization.style.ClusterStylingPolicy;
import de.lmu.ifi.dbs.elki.visualization.style.StyleLibrary;
+import de.lmu.ifi.dbs.elki.visualization.style.StyleResult;
+import de.lmu.ifi.dbs.elki.visualization.style.StylingPolicy;
import de.lmu.ifi.dbs.elki.visualization.svg.SVGPath;
import de.lmu.ifi.dbs.elki.visualization.svg.SVGPlot;
import de.lmu.ifi.dbs.elki.visualization.svg.SVGUtil;
import de.lmu.ifi.dbs.elki.visualization.visualizers.AbstractVisFactory;
import de.lmu.ifi.dbs.elki.visualization.visualizers.Visualization;
import de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.AbstractScatterplotVisualization;
+import de.lmu.ifi.dbs.elki.visualization.visualizers.thumbs.ThumbnailVisualization;
/**
* Visualizer for generating an SVG-Element containing the convex hull / alpha
@@ -91,6 +101,7 @@ public class ClusterHullVisualization extends AbstractVisFactory {
public ClusterHullVisualization(Parameterizer settings) {
super();
this.settings = settings;
+ this.thumbmask |= ThumbnailVisualization.ON_DATA | ThumbnailVisualization.ON_STYLE;
}
@Override
@@ -100,11 +111,12 @@ public class ClusterHullVisualization extends AbstractVisFactory {
@Override
public void processNewResult(HierarchicalResult baseResult, Result result) {
- // Find clusterings we can visualize:
- Collection<Clustering<?>> clusterings = ResultUtil.filterResults(result, Clustering.class);
- for(Clustering<?> c : clusterings) {
+ // We attach ourselves to the style library, not the clustering, so there is
+ // only one hull.
+ Collection<StyleResult> styleres = ResultUtil.filterResults(result, StyleResult.class);
+ for (StyleResult c : styleres) {
Collection<ScatterPlotProjector<?>> ps = ResultUtil.filterResults(baseResult, ScatterPlotProjector.class);
- for(ScatterPlotProjector<?> p : ps) {
+ for (ScatterPlotProjector<?> p : ps) {
final VisualizationTask task = new VisualizationTask(NAME, c, p.getRelation(), this);
task.level = VisualizationTask.LEVEL_DATA - 1;
task.initDefaultVisibility(false);
@@ -132,9 +144,9 @@ public class ClusterHullVisualization extends AbstractVisFactory {
public static final String CLUSTERHULL = "cluster-hull";
/**
- * The result we work on
+ * The result we visualize
*/
- Clustering<Model> clustering;
+ private StyleResult style;
/**
* Constructor
@@ -143,60 +155,97 @@ public class ClusterHullVisualization extends AbstractVisFactory {
*/
public Instance(VisualizationTask task) {
super(task);
- this.clustering = task.getResult();
+ this.style = task.getResult();
incrementalRedraw();
}
@Override
protected void redraw() {
+ final StylingPolicy spol = style.getStylingPolicy();
+ if (!(spol instanceof ClusterStylingPolicy)) {
+ return;
+ }
+ final ClusterStylingPolicy cpol = (ClusterStylingPolicy) spol;
+ @SuppressWarnings("unchecked")
+ Clustering<Model> clustering = (Clustering<Model>) cpol.getClustering();
+
// Viewport size, for "relative size" computations
final CanvasSize viewp = proj.estimateViewport();
double projarea = viewp.getDiffX() * viewp.getDiffY();
- double opacity = 0.25;
-
- Iterator<Cluster<Model>> ci = clustering.getAllClusters().iterator();
-
- for(int cnum = 0; cnum < clustering.getAllClusters().size(); cnum++) {
- Cluster<?> clus = ci.next();
- final DBIDs ids = clus.getIDs();
+ List<Cluster<Model>> clusters = clustering.getAllClusters();
+ List<Cluster<Model>> topc = clustering.getToplevelClusters();
+ Hierarchy<Cluster<Model>> hier = clustering.getClusterHierarchy();
+ boolean flat = (clusters.size() == topc.size());
+ // Heuristic value for transparency:
+ double baseopacity = flat ? 0.5 : 0.5;
+
+ // Convex hull mode:
+ if (settings.alpha >= Double.POSITIVE_INFINITY) {
+ // Build the convex hulls (reusing the hulls of nested clusters!)
+ Map<Object, DoubleObjPair<Polygon>> hullmap = new HashMap<>(clusters.size());
+ for (Cluster<Model> clu : topc) {
+ buildHullsRecursively(clu, hier, hullmap);
+ }
- if(settings.alpha >= Double.POSITIVE_INFINITY) {
- GrahamScanConvexHull2D hull = new GrahamScanConvexHull2D();
+ // This way, we draw each cluster only once.
+ // Unfortunately, not depth ordered (TODO!)
+ for (Cluster<Model> clu : clusters) {
+ DoubleObjPair<Polygon> pair = hullmap.get(clu), mpair = hullmap.get(clu.getModel());
+ ;
+ // Plot the convex hull:
+ if (pair != null && pair.second != null && pair.second.size() > 1) {
+ SVGPath path = new SVGPath(pair.second);
+ // Approximate area (using bounding box)
+ double hullarea = SpatialUtil.volume(pair.second);
+ final double relativeArea = 1 - (hullarea / projarea);
+ final double relativeSize = pair.first / rel.size();
+ final double corefact = (mpair == null) ? 1.0 : .5;
+ final double opacity = corefact * baseopacity * Math.sqrt(relativeSize * relativeArea);
+ addCSSClasses(svgp, cpol.getStyleForCluster(clu), opacity);
- for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
- double[] projP = proj.fastProjectDataToRenderSpace(rel.get(iter));
- hull.add(new Vector(projP));
+ Element hulls = path.makeElement(svgp);
+ SVGUtil.addCSSClass(hulls, CLUSTERHULL + cpol.getStyleForCluster(clu));
+ layer.appendChild(hulls);
}
- Polygon chres = hull.getHull();
-
- // Plot the convex hull:
- if(chres != null && chres.size() > 1) {
- SVGPath path = new SVGPath(chres);
+ // For core density models, over-plot the core:
+ if (mpair != null && mpair.second != null && mpair.second.size() > 1) {
+ SVGPath path = new SVGPath(mpair.second);
// Approximate area (using bounding box)
- double hullarea = SpatialUtil.volume(chres);
- final double relativeArea = (projarea - hullarea) / projarea;
- final double relativeSize = (double) ids.size() / rel.size();
- opacity = Math.sqrt(relativeSize * relativeArea);
+ double hullarea = SpatialUtil.volume(mpair.second);
+ final double relativeArea = 1 - (hullarea / projarea);
+ final double relativeSize = mpair.first / rel.size();
+ final double opacity = .5 * baseopacity * Math.sqrt(relativeSize * relativeArea);
+ addCSSClasses(svgp, cpol.getStyleForCluster(clu), opacity);
Element hulls = path.makeElement(svgp);
- addCSSClasses(svgp, cnum, opacity);
- SVGUtil.addCSSClass(hulls, CLUSTERHULL + cnum);
+ SVGUtil.addCSSClass(hulls, CLUSTERHULL + cpol.getStyleForCluster(clu));
layer.appendChild(hulls);
}
}
- else {
- ArrayList<Vector> ps = new ArrayList<Vector>(ids.size());
- for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
- double[] projP = proj.fastProjectDataToRenderSpace(rel.get(iter));
- ps.add(new Vector(projP));
+ } else {
+ // Alpha shape mode.
+ // For alpha shapes we can't use the shortcut of convex hulls,
+ // but have to revisit all child clusters.
+ for (Cluster<Model> clu : clusters) {
+ ArrayList<Vector> ps = new ArrayList<>();
+ double weight = addRecursively(ps, hier, clu);
+ List<Polygon> polys;
+ if (ps.size() < 1) {
+ continue;
}
- List<Polygon> polys = (new AlphaShape(ps, settings.alpha * Projection.SCALE)).compute();
- for(Polygon p : polys) {
+ if (ps.size() > 2) {
+ polys = (new AlphaShape(ps, settings.alpha * Projection.SCALE)).compute();
+ } else {
+ // Trivial polygon. Might still degenerate to a single point though.
+ polys = new ArrayList<>(1);
+ polys.add(new Polygon(ps));
+ }
+ for (Polygon p : polys) {
SVGPath path = new SVGPath(p);
Element hulls = path.makeElement(svgp);
- addCSSClasses(svgp, cnum, 0.5);
- SVGUtil.addCSSClass(hulls, CLUSTERHULL + cnum);
+ addCSSClasses(svgp, cpol.getStyleForCluster(clu), baseopacity * weight / rel.size());
+ SVGUtil.addCSSClass(hulls, CLUSTERHULL + cpol.getStyleForCluster(clu));
layer.appendChild(hulls);
}
}
@@ -204,6 +253,89 @@ public class ClusterHullVisualization extends AbstractVisFactory {
}
/**
+ * Recursively step through the clusters to build the hulls.
+ *
+ * @param clu Current cluster
+ * @param hier Clustering hierarchy
+ * @param hulls Hull map
+ */
+ private DoubleObjPair<Polygon> buildHullsRecursively(Cluster<Model> clu, Hierarchy<Cluster<Model>> hier, Map<Object, DoubleObjPair<Polygon>> hulls) {
+ final Model model = clu.getModel();
+ final DBIDs ids = clu.getIDs();
+ boolean coremodel = false;
+ DBIDs cids = null;
+ if (model instanceof CoreObjectsModel) {
+ cids = ((CoreObjectsModel) model).getCoreObjects();
+ coremodel = cids.size() > 0;
+ }
+
+ GrahamScanConvexHull2D hull = new GrahamScanConvexHull2D();
+ GrahamScanConvexHull2D hull2 = coremodel ? new GrahamScanConvexHull2D() : null;
+ for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
+ Vector projP = new Vector(proj.fastProjectDataToRenderSpace(rel.get(iter)));
+ hull.add(projP);
+ if (coremodel && cids.contains(iter)) {
+ hull2.add(projP);
+ }
+ }
+ double weight = ids.size(), cweight = coremodel ? cids.size() : 0.0;
+ if (hier != null && hulls != null) {
+ final int numc = hier.numChildren(clu);
+ if (numc > 0) {
+ for (Iter<Cluster<Model>> iter = hier.iterChildren(clu); iter.valid(); iter.advance()) {
+ final Cluster<Model> iclu = iter.get();
+ DoubleObjPair<Polygon> poly = hulls.get(iclu);
+ if (poly == null) {
+ poly = buildHullsRecursively(iclu, hier, hulls);
+ }
+ // Add inner convex hull to outer convex hull.
+ for (ArrayListIter<Vector> vi = poly.second.iter(); vi.valid(); vi.advance()) {
+ hull.add(vi.get());
+ }
+ // For a core model, include the inner core, too.
+ if (coremodel) {
+ DoubleObjPair<Polygon> ipoly = hulls.get(iclu.getModel());
+ if (ipoly != null) {
+ for (ArrayListIter<Vector> vi = ipoly.second.iter(); vi.valid(); vi.advance()) {
+ hull2.add(vi.get());
+ }
+ cweight += ipoly.first / numc;
+ }
+ }
+ weight += poly.first / numc;
+ }
+ }
+ }
+ DoubleObjPair<Polygon> pair = new DoubleObjPair<>(weight, hull.getHull());
+ hulls.put(clu, pair);
+ if (coremodel) {
+ hulls.put(model, new DoubleObjPair<>(cweight, hull2.getHull()));
+ }
+ return pair;
+ }
+
+ /**
+ * Recursively add a cluster and its children.
+ *
+ * @param hull Hull to add to
+ * @param hier Cluster hierarchy
+ * @param clus Current cluster
+ * @return Weight for visualization
+ */
+ private double addRecursively(ArrayList<Vector> hull, Hierarchy<Cluster<Model>> hier, Cluster<Model> clus) {
+ final DBIDs ids = clus.getIDs();
+ double weight = ids.size();
+ for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
+ double[] projP = proj.fastProjectDataToRenderSpace(rel.get(iter));
+ hull.add(new Vector(projP));
+ }
+ for (Iter<Cluster<Model>> iter = hier.iterChildren(clus); iter.valid(); iter.advance()) {
+ weight += .5 * addRecursively(hull, hier, iter.get());
+ }
+ return weight;
+ }
+
+ /**
* Adds the required CSS-Classes
*
* @param svgp SVG-Plot
@@ -215,13 +347,7 @@ public class ClusterHullVisualization extends AbstractVisFactory {
CSSClass cls = new CSSClass(this, CLUSTERHULL + clusterID);
cls.setStatement(SVGConstants.CSS_STROKE_WIDTH_PROPERTY, style.getLineWidth(StyleLibrary.PLOT));
- final String color;
- if(clustering.getAllClusters().size() == 1) {
- color = "black";
- }
- else {
- color = colors.getColor(clusterID);
- }
+ final String color = colors.getColor(clusterID);
cls.setStatement(SVGConstants.CSS_STROKE_PROPERTY, color);
cls.setStatement(SVGConstants.CSS_FILL_PROPERTY, color);
cls.setStatement(SVGConstants.CSS_FILL_OPACITY_PROPERTY, opac);
@@ -256,7 +382,7 @@ public class ClusterHullVisualization extends AbstractVisFactory {
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
DoubleParameter alphaP = new DoubleParameter(ALPHA_ID, Double.POSITIVE_INFINITY);
- if(config.grab(alphaP)) {
+ if (config.grab(alphaP)) {
alpha = alphaP.doubleValue();
}
}
@@ -266,4 +392,4 @@ public class ClusterHullVisualization extends AbstractVisFactory {
return new ClusterHullVisualization(this);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/ClusterOrderVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/ClusterOrderVisualization.java
index bd173e80..bdc77006 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/ClusterOrderVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/ClusterOrderVisualization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.cluster;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/EMClusterVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/EMClusterVisualization.java
index 2806812a..9a5df4e4 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/EMClusterVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/EMClusterVisualization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.cluster;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -93,7 +93,7 @@ public class EMClusterVisualization extends AbstractVisFactory {
@Override
public Instance<DoubleVector> makeVisualization(VisualizationTask task) {
- return new Instance<DoubleVector>(task);
+ return new Instance<>(task);
}
@Override
@@ -346,7 +346,7 @@ public class EMClusterVisualization extends AbstractVisFactory {
for(int i = 1; i <= times; i++) {
SVGPath path = new SVGPath();
- ArrayList<Vector> delta = new ArrayList<Vector>(chres.size());
+ ArrayList<Vector> delta = new ArrayList<>(chres.size());
for(int p = 0; p < chres.size(); p++) {
Vector prev = chres.get((p - 1 + chres.size()) % chres.size());
Vector curr = chres.get(p);
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/VoronoiVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/VoronoiVisualization.java
index 7ae28f42..7c4b57f2 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/VoronoiVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/VoronoiVisualization.java
@@ -203,7 +203,7 @@ public class VoronoiVisualization extends AbstractVisFactory {
// Collect cluster means
if (clusters.size() == 2) {
- ArrayList<double[]> means = new ArrayList<double[]>(clusters.size());
+ ArrayList<double[]> means = new ArrayList<>(clusters.size());
{
for (Cluster<Model> clus : clusters) {
Model model = clus.getModel();
@@ -232,8 +232,8 @@ public class VoronoiVisualization extends AbstractVisFactory {
layer.appendChild(path);
}
} else {
- ArrayList<Vector> vmeans = new ArrayList<Vector>(clusters.size());
- ArrayList<double[]> means = new ArrayList<double[]>(clusters.size());
+ ArrayList<Vector> vmeans = new ArrayList<>(clusters.size());
+ ArrayList<double[]> means = new ArrayList<>(clusters.size());
{
for (Cluster<Model> clus : clusters) {
Model model = clus.getModel();
@@ -313,7 +313,7 @@ public class VoronoiVisualization extends AbstractVisFactory {
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- EnumParameter<Mode> modeP = new EnumParameter<Mode>(MODE_ID, Mode.class, Mode.VORONOI);
+ EnumParameter<Mode> modeP = new EnumParameter<>(MODE_ID, Mode.class, Mode.VORONOI);
if (config.grab(modeP)) {
mode = modeP.getValue();
}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/package-info.java
index 0f232498..076b6563 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/density/DensityEstimationOverlay.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/density/DensityEstimationOverlay.java
index 96658910..a2b34e0e 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/density/DensityEstimationOverlay.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/density/DensityEstimationOverlay.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.density;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/density/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/density/package-info.java
index b9771aed..3b6385f3 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/density/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/density/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/index/TreeMBRVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/index/TreeMBRVisualization.java
index 9d466a8f..438eddb8 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/index/TreeMBRVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/index/TreeMBRVisualization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.index;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -96,8 +96,8 @@ public class TreeMBRVisualization extends AbstractVisFactory {
@Override
public void processNewResult(HierarchicalResult baseResult, Result result) {
- Collection<AbstractRStarTree<RStarTreeNode, SpatialEntry>> trees = ResultUtil.filterResults(result, AbstractRStarTree.class);
- for(AbstractRStarTree<RStarTreeNode, SpatialEntry> tree : trees) {
+ Collection<AbstractRStarTree<RStarTreeNode, SpatialEntry, ?>> trees = ResultUtil.filterResults(result, AbstractRStarTree.class);
+ for(AbstractRStarTree<RStarTreeNode, SpatialEntry, ?> tree : trees) {
if(tree instanceof Result) {
Collection<ScatterPlotProjector<?>> ps = ResultUtil.filterResults(baseResult, ScatterPlotProjector.class);
for(ScatterPlotProjector<?> p : ps) {
@@ -126,7 +126,7 @@ public class TreeMBRVisualization extends AbstractVisFactory {
/**
* The tree we visualize
*/
- protected AbstractRStarTree<N, E> tree;
+ protected AbstractRStarTree<N, E, ?> tree;
/**
* Constructor.
@@ -182,7 +182,7 @@ public class TreeMBRVisualization extends AbstractVisFactory {
* @param entry Current entry
* @param depth Current depth
*/
- private void visualizeRTreeEntry(SVGPlot svgp, Element layer, Projection2D proj, AbstractRStarTree<? extends N, E> rtree, E entry, int depth) {
+ private void visualizeRTreeEntry(SVGPlot svgp, Element layer, Projection2D proj, AbstractRStarTree<? extends N, E, ?> rtree, E entry, int depth) {
SpatialComparable mbr = entry;
if(settings.fill) {
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/index/TreeSphereVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/index/TreeSphereVisualization.java
index e89be028..4ced6de1 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/index/TreeSphereVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/index/TreeSphereVisualization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.index;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -32,9 +32,9 @@ import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreListener;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.LPNormDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.ManhattanDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.LPNormDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.ManhattanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree;
@@ -107,8 +107,8 @@ public class TreeSphereVisualization extends AbstractVisFactory {
public void processNewResult(HierarchicalResult baseResult, Result result) {
Collection<ScatterPlotProjector<?>> ps = ResultUtil.filterResults(baseResult, ScatterPlotProjector.class);
for (ScatterPlotProjector<?> p : ps) {
- Collection<AbstractMTree<?, DoubleDistance, ?, ?>> trees = ResultUtil.filterResults(result, AbstractMTree.class);
- for (AbstractMTree<?, DoubleDistance, ?, ?> tree : trees) {
+ Collection<AbstractMTree<?, DoubleDistance, ?, ?, ?>> trees = ResultUtil.filterResults(result, AbstractMTree.class);
+ for (AbstractMTree<?, DoubleDistance, ?, ?, ?> tree : trees) {
if (canVisualize(tree) && tree instanceof Result) {
final VisualizationTask task = new VisualizationTask(NAME, (Result) tree, p.getRelation(), this);
task.level = VisualizationTask.LEVEL_BACKGROUND + 1;
@@ -121,7 +121,7 @@ public class TreeSphereVisualization extends AbstractVisFactory {
@Override
public Visualization makeVisualization(VisualizationTask task) {
- return new Instance<DoubleDistance, MTreeNode<Object, DoubleDistance>, MTreeEntry<DoubleDistance>>(task);
+ return new Instance<DoubleDistance, MTreeNode<Object, DoubleDistance>, MTreeEntry>(task);
}
/**
@@ -130,10 +130,10 @@ public class TreeSphereVisualization extends AbstractVisFactory {
* @param tree Tree to visualize
* @return p value
*/
- public static double getLPNormP(AbstractMTree<?, ?, ?, ?> tree) {
+ public static double getLPNormP(AbstractMTree<?, ?, ?, ?, ?> tree) {
// Note: we deliberately lose generics here, so the compilers complain
// less on the next typecheck and cast!
- DistanceFunction<?, ?> distanceFunction = tree.getDistanceQuery().getDistanceFunction();
+ DistanceFunction<?, ?> distanceFunction = tree.getDistanceFunction();
if (LPNormDistanceFunction.class.isInstance(distanceFunction)) {
return ((LPNormDistanceFunction) distanceFunction).getP();
}
@@ -146,7 +146,7 @@ public class TreeSphereVisualization extends AbstractVisFactory {
* @param tree Tree to visualize
* @return whether the tree is visualizable
*/
- public static boolean canVisualize(AbstractMTree<?, ?, ?, ?> tree) {
+ public static boolean canVisualize(AbstractMTree<?, ?, ?, ?, ?> tree) {
return getLPNormP(tree) > 0;
}
@@ -162,7 +162,7 @@ public class TreeSphereVisualization extends AbstractVisFactory {
* @param <E> Tree entry type
*/
// TODO: listen for tree changes!
- public class Instance<D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<?, D, N, E>, E extends MTreeEntry<D>> extends AbstractScatterplotVisualization implements DataStoreListener {
+ public class Instance<D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<?, D, N, E>, E extends MTreeEntry> extends AbstractScatterplotVisualization implements DataStoreListener {
protected double p;
/**
@@ -173,7 +173,7 @@ public class TreeSphereVisualization extends AbstractVisFactory {
/**
* The tree we visualize
*/
- protected AbstractMTree<?, D, N, E> tree;
+ protected AbstractMTree<?, D, N, E, ?> tree;
/**
* Constructor
@@ -197,9 +197,9 @@ public class TreeSphereVisualization extends AbstractVisFactory {
p = getLPNormP(tree);
if (tree != null) {
- if (ManhattanDistanceFunction.class.isInstance(tree.getDistanceQuery())) {
+ if (ManhattanDistanceFunction.class.isInstance(tree.getDistanceFunction())) {
dist = Modus.MANHATTAN;
- } else if (EuclideanDistanceFunction.class.isInstance(tree.getDistanceQuery())) {
+ } else if (EuclideanDistanceFunction.class.isInstance(tree.getDistanceFunction())) {
dist = Modus.EUCLIDEAN;
} else {
dist = Modus.LPCROSS;
@@ -240,11 +240,11 @@ public class TreeSphereVisualization extends AbstractVisFactory {
* @param entry Current entry
* @param depth Current depth
*/
- private void visualizeMTreeEntry(SVGPlot svgp, Element layer, Projection2D proj, AbstractMTree<?, D, N, E> mtree, E entry, int depth) {
+ private void visualizeMTreeEntry(SVGPlot svgp, Element layer, Projection2D proj, AbstractMTree<?, D, N, E, ?> mtree, E entry, int depth) {
DBID roid = entry.getRoutingObjectID();
if (roid != null) {
NumberVector<?> ro = rel.get(roid);
- D rad = entry.getCoveringRadius();
+ double rad = entry.getCoveringRadius();
final Element r;
if (dist == Modus.MANHATTAN) {
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/index/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/index/package-info.java
index a4b3c0c9..b82e9359 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/index/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/index/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/outlier/BubbleVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/outlier/BubbleVisualization.java
index ebe9612d..5051d019 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/outlier/BubbleVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/outlier/BubbleVisualization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -36,6 +36,7 @@ import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
import de.lmu.ifi.dbs.elki.result.Result;
import de.lmu.ifi.dbs.elki.result.ResultUtil;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.Hierarchy;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
@@ -100,7 +101,7 @@ public class BubbleVisualization extends AbstractVisFactory {
@Override
public Visualization makeVisualization(VisualizationTask task) {
- if(settings.scaling != null && settings.scaling instanceof OutlierScalingFunction) {
+ if (settings.scaling != null && settings.scaling instanceof OutlierScalingFunction) {
final OutlierResult outlierResult = task.getResult();
((OutlierScalingFunction) settings.scaling).prepare(outlierResult);
}
@@ -110,21 +111,21 @@ public class BubbleVisualization extends AbstractVisFactory {
@Override
public void processNewResult(HierarchicalResult baseResult, Result result) {
Collection<OutlierResult> ors = ResultUtil.filterResults(result, OutlierResult.class);
- for(OutlierResult o : ors) {
+ for (OutlierResult o : ors) {
Collection<ScatterPlotProjector<?>> ps = ResultUtil.filterResults(baseResult, ScatterPlotProjector.class);
boolean vis = true;
// Quick and dirty hack: hide if parent result is also an outlier result
// Since that probably is already visible and we're redundant.
- for(Result r : o.getHierarchy().getParents(o)) {
- if(r instanceof OutlierResult) {
+ for (Hierarchy.Iter<Result> r = o.getHierarchy().iterParents(o); r.valid(); r.advance()) {
+ if (r.get() instanceof OutlierResult) {
vis = false;
break;
}
}
- for(ScatterPlotProjector<?> p : ps) {
+ for (ScatterPlotProjector<?> p : ps) {
final VisualizationTask task = new VisualizationTask(NAME, o, p.getRelation(), this);
task.level = VisualizationTask.LEVEL_DATA;
- if(!vis) {
+ if (!vis) {
task.initDefaultVisibility(false);
}
baseResult.getHierarchy().add(o, task);
@@ -172,15 +173,15 @@ public class BubbleVisualization extends AbstractVisFactory {
StylingPolicy stylepolicy = style.getStylingPolicy();
// bubble size
final double bubble_size = style.getStyleLibrary().getSize(StyleLibrary.BUBBLEPLOT);
- if(stylepolicy instanceof ClassStylingPolicy) {
+ if (stylepolicy instanceof ClassStylingPolicy) {
ClassStylingPolicy colors = (ClassStylingPolicy) stylepolicy;
setupCSS(svgp, colors);
// draw data
- for(DBIDIter objId = sample.getSample().iter(); objId.valid(); objId.advance()) {
+ for (DBIDIter objId = sample.getSample().iter(); objId.valid(); objId.advance()) {
final double radius = getScaledForId(objId);
- if(radius > 0.01 && !Double.isInfinite(radius)) {
+ if (radius > 0.01 && !Double.isInfinite(radius)) {
final NumberVector<?> vec = rel.get(objId);
- if(vec != null) {
+ if (vec != null) {
double[] v = proj.fastProjectDataToRenderSpace(vec);
Element circle = svgp.svgCircle(v[0], v[1], radius * bubble_size);
SVGUtil.addCSSClass(circle, BUBBLE + colors.getStyleForDBID(objId));
@@ -188,23 +189,21 @@ public class BubbleVisualization extends AbstractVisFactory {
}
}
}
- }
- else {
+ } else {
// draw data
- for(DBIDIter objId = sample.getSample().iter(); objId.valid(); objId.advance()) {
+ for (DBIDIter objId = sample.getSample().iter(); objId.valid(); objId.advance()) {
final double radius = getScaledForId(objId);
- if(radius > 0.01 && !Double.isInfinite(radius)) {
+ if (radius > 0.01 && !Double.isInfinite(radius)) {
final NumberVector<?> vec = rel.get(objId);
- if(vec != null) {
+ if (vec != null) {
double[] v = proj.fastProjectDataToRenderSpace(vec);
Element circle = svgp.svgCircle(v[0], v[1], radius * bubble_size);
int color = stylepolicy.getColorForDBID(objId);
final StringBuilder cssstyle = new StringBuilder();
- if(settings.fill) {
+ if (settings.fill) {
cssstyle.append(SVGConstants.CSS_FILL_PROPERTY).append(':').append(SVGUtil.colorToString(color));
cssstyle.append(SVGConstants.CSS_FILL_OPACITY_PROPERTY).append(":0.5");
- }
- else {
+ } else {
cssstyle.append(SVGConstants.CSS_STROKE_VALUE).append(':').append(SVGUtil.colorToString(color));
cssstyle.append(SVGConstants.CSS_FILL_PROPERTY).append(':').append(SVGConstants.CSS_NONE_VALUE);
}
@@ -219,7 +218,7 @@ public class BubbleVisualization extends AbstractVisFactory {
@Override
public void resultChanged(Result current) {
super.resultChanged(current);
- if(sample == current || context.getStyleResult() == current) {
+ if (sample == current || context.getStyleResult() == current) {
synchronizedRedraw();
}
}
@@ -235,17 +234,16 @@ public class BubbleVisualization extends AbstractVisFactory {
ColorLibrary colors = style.getColorSet(StyleLibrary.PLOT);
// creating IDs manually because cluster often return a null-ID.
- for(int clusterID = policy.getMinStyle(); clusterID < policy.getMaxStyle(); clusterID++) {
+ for (int clusterID = policy.getMinStyle(); clusterID < policy.getMaxStyle(); clusterID++) {
CSSClass bubble = new CSSClass(svgp, BUBBLE + clusterID);
bubble.setStatement(SVGConstants.CSS_STROKE_WIDTH_PROPERTY, style.getLineWidth(StyleLibrary.PLOT));
String color = colors.getColor(clusterID);
- if(settings.fill) {
+ if (settings.fill) {
bubble.setStatement(SVGConstants.CSS_FILL_PROPERTY, color);
bubble.setStatement(SVGConstants.CSS_FILL_OPACITY_PROPERTY, 0.5);
- }
- else {
+ } else {
// for diamond-shaped strokes, see bugs.sun.com, bug ID 6294396
bubble.setStatement(SVGConstants.CSS_STROKE_VALUE, color);
bubble.setStatement(SVGConstants.CSS_FILL_PROPERTY, SVGConstants.CSS_NONE_VALUE);
@@ -264,13 +262,12 @@ public class BubbleVisualization extends AbstractVisFactory {
*/
protected double getScaledForId(DBIDRef id) {
double d = result.getScores().get(id).doubleValue();
- if(Double.isNaN(d) || Double.isInfinite(d)) {
+ if (Double.isNaN(d) || Double.isInfinite(d)) {
return 0.0;
}
- if(settings.scaling == null) {
+ if (settings.scaling == null) {
return result.getOutlierMeta().normalizeScore(d);
- }
- else {
+ } else {
return settings.scaling.getScaled(d);
}
}
@@ -316,12 +313,12 @@ public class BubbleVisualization extends AbstractVisFactory {
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
Flag fillF = new Flag(FILL_ID);
- if(config.grab(fillF)) {
+ if (config.grab(fillF)) {
fill = fillF.isTrue();
}
- ObjectParameter<ScalingFunction> scalingP = new ObjectParameter<ScalingFunction>(SCALING_ID, OutlierScalingFunction.class, true);
- if(config.grab(scalingP)) {
+ ObjectParameter<ScalingFunction> scalingP = new ObjectParameter<>(SCALING_ID, OutlierScalingFunction.class, true);
+ if (config.grab(scalingP)) {
scaling = scalingP.instantiateClass(config);
}
}
@@ -331,4 +328,4 @@ public class BubbleVisualization extends AbstractVisFactory {
return new BubbleVisualization(this);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/outlier/COPVectorVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/outlier/COPVectorVisualization.java
index e953f9ae..c3346c02 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/outlier/COPVectorVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/outlier/COPVectorVisualization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.outlier;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/outlier/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/outlier/package-info.java
index 7332fcb0..f8da2afd 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/outlier/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/outlier/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/package-info.java
index 805379d7..66d9b609 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/package-info.java
@@ -12,7 +12,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/selection/DistanceFunctionVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/selection/DistanceFunctionVisualization.java
index 257a3c54..d9b860de 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/selection/DistanceFunctionVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/selection/DistanceFunctionVisualization.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.selection;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -32,17 +32,18 @@ import de.lmu.ifi.dbs.elki.data.VectorUtil;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreListener;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
-import de.lmu.ifi.dbs.elki.database.ids.DistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDPair;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.distance.distancefunction.ArcCosineDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancefunction.CosineDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.LPNormDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultIter;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.LPNormDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.index.preprocessed.knn.AbstractMaterializeKNNPreprocessor;
import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
+import de.lmu.ifi.dbs.elki.math.MathUtil;
import de.lmu.ifi.dbs.elki.math.linearalgebra.VMath;
import de.lmu.ifi.dbs.elki.result.DBIDSelection;
import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
@@ -180,7 +181,7 @@ public class DistanceFunctionVisualization extends AbstractVisFactory {
double l1 = VMath.scalarProduct(pm, p1), l2 = VMath.scalarProduct(pm, p2);
// Rotate projection by + and - angle
// Using sin(-x) = -sin(x) and cos(-x)=cos(x)
- final double cangle = Math.cos(angle), sangle = Math.sin(angle);
+ final double cangle = Math.cos(angle), sangle = MathUtil.cosToSin(angle, cangle);
double r11 = +cangle * l1 - sangle * l2, r12 = +sangle * l1 + cangle * l2;
double r21 = +cangle * l1 + sangle * l2, r22 = -sangle * l1 + cangle * l2;
// Build rotated vectors - remove projected component, add rotated
@@ -276,8 +277,8 @@ public class DistanceFunctionVisualization extends AbstractVisFactory {
DBIDs selection = selContext.getSelectedIds();
for(DBIDIter i = selection.iter(); i.valid(); i.advance()) {
- final KNNResult<D> knn = result.get(i);
- for(DistanceDBIDResultIter<D> iter = knn.iter(); iter.valid(); iter.advance()) {
+ final KNNList<D> knn = result.get(i);
+ for(DistanceDBIDListIter<D> iter = knn.iter(); iter.valid(); iter.advance()) {
try {
double[] v = proj.fastProjectDataToRenderSpace(rel.get(iter));
Element dot = svgp.svgCircle(v[0], v[1], size);
@@ -298,13 +299,13 @@ public class DistanceFunctionVisualization extends AbstractVisFactory {
{
final Element dist;
if(p == 1.0) {
- dist = SVGHyperSphere.drawManhattan(svgp, proj, rel.get(i), last.getDistance());
+ dist = SVGHyperSphere.drawManhattan(svgp, proj, rel.get(i), last.getDistance().doubleValue());
}
else if(p == 2.0) {
- dist = SVGHyperSphere.drawEuclidean(svgp, proj, rel.get(i), last.getDistance());
+ dist = SVGHyperSphere.drawEuclidean(svgp, proj, rel.get(i), last.getDistance().doubleValue());
}
else if(!Double.isNaN(p)) {
- dist = SVGHyperSphere.drawLp(svgp, proj, rel.get(i), last.getDistance(), p);
+ dist = SVGHyperSphere.drawLp(svgp, proj, rel.get(i), last.getDistance().doubleValue(), p);
}
else if(angular) {
final NumberVector<?> refvec = rel.get(i);
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/selection/MoveObjectsToolVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/selection/MoveObjectsToolVisualization.java
index c2282bf1..84659848 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/selection/MoveObjectsToolVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/selection/MoveObjectsToolVisualization.java
@@ -30,7 +30,6 @@ import org.w3c.dom.Element;
import org.w3c.dom.events.Event;
import org.w3c.dom.svg.SVGPoint;
-import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.database.UpdatableDatabase;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
@@ -159,9 +158,9 @@ public class MoveObjectsToolVisualization extends AbstractVisFactory {
*/
// TODO: move to DatabaseUtil?
private void updateDB(DBIDs dbids, Vector movingVector) {
- NumberVector<?> nv = null;
throw new AbortException("FIXME: INCOMPLETE TRANSITION");
/*
+ * NumberVector<?> nv = null;
* database.accumulateDataStoreEvents();
* Representation<DatabaseObjectMetadata> mrep =
* database.getMetadataQuery(); for(DBID dbid : dbids) { NV obj =
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/selection/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/selection/package-info.java
index 3710de5c..86214f53 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/selection/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/selection/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/thumbs/ThumbnailThread.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/thumbs/ThumbnailThread.java
index 8d045138..bf210fce 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/thumbs/ThumbnailThread.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/thumbs/ThumbnailThread.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.thumbs;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -37,7 +37,7 @@ public class ThumbnailThread extends Thread {
/**
* Queue of thumbnails to generate.
*/
- private Queue<Task> queue = new ConcurrentLinkedQueue<Task>();
+ private Queue<Task> queue = new ConcurrentLinkedQueue<>();
/**
* Flag to signal shutdown.
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/thumbs/ThumbnailVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/thumbs/ThumbnailVisualization.java
index dd502146..651f41c0 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/thumbs/ThumbnailVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/thumbs/ThumbnailVisualization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.thumbs;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/thumbs/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/thumbs/package-info.java
index 64676bb3..c32b9f19 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/thumbs/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/thumbs/package-info.java
@@ -6,7 +6,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/ClusterEvaluationVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/ClusterEvaluationVisualization.java
index 4b57a503..8d87945e 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/ClusterEvaluationVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/ClusterEvaluationVisualization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.visunproj;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,7 +24,6 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.visunproj;
*/
import java.util.ArrayList;
-import java.util.List;
import org.apache.batik.util.SVGConstants;
import org.w3c.dom.Element;
@@ -42,6 +41,7 @@ import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
import de.lmu.ifi.dbs.elki.result.Result;
import de.lmu.ifi.dbs.elki.result.ResultUtil;
import de.lmu.ifi.dbs.elki.utilities.FormatUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.Hierarchy;
import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
import de.lmu.ifi.dbs.elki.visualization.style.StyleLibrary;
import de.lmu.ifi.dbs.elki.visualization.svg.SVGPlot;
@@ -59,7 +59,9 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.Visualization;
*
* @apiviz.stereotype factory
* @apiviz.uses StaticVisualizationInstance oneway - - «create»
- * @apiviz.has de.lmu.ifi.dbs.elki.evaluation.clustering.EvaluateClustering.ScoreResult oneway - - visualizes
+ * @apiviz.has
+ * de.lmu.ifi.dbs.elki.evaluation.clustering.EvaluateClustering.ScoreResult
+ * oneway - - visualizes
*/
public class ClusterEvaluationVisualization extends AbstractVisFactory {
/**
@@ -87,10 +89,10 @@ public class ClusterEvaluationVisualization extends AbstractVisFactory {
@Override
public void processNewResult(HierarchicalResult baseResult, Result newResult) {
final ArrayList<EvaluateClustering.ScoreResult> srs = ResultUtil.filterResults(newResult, EvaluateClustering.ScoreResult.class);
- for(EvaluateClustering.ScoreResult sr : srs) {
+ for (EvaluateClustering.ScoreResult sr : srs) {
final VisualizationTask task = new VisualizationTask(NAME, sr, null, this);
- task.width = .5;
- task.height = 2.0;
+ task.width = .4;
+ task.height = 1.5;
task.level = VisualizationTask.LEVEL_STATIC;
baseResult.getHierarchy().add(sr, task);
}
@@ -118,17 +120,16 @@ public class ClusterEvaluationVisualization extends AbstractVisFactory {
@Override
public Visualization makeVisualization(VisualizationTask task) {
// TODO: make a utility class to wrap SVGPlot + parent layer + ypos.
-
+
double ypos = -.5; // Skip space before first header
SVGPlot svgp = task.getPlot();
Element parent = svgp.svgElement(SVGConstants.SVG_G_TAG);
EvaluateClustering.ScoreResult sr = task.getResult();
ClusterContingencyTable cont = sr.getContingencyTable();
- List<Result> parents = task.getContext().getHierarchy().getParents(sr);
-
- for(Result r : parents) {
- if(r instanceof Clustering) {
+ for (Hierarchy.Iter<Result> parents = task.getContext().getHierarchy().iterParents(sr); parents.valid(); parents.advance()) {
+ Result r = parents.get();
+ if (r instanceof Clustering) {
ypos = addHeader(svgp, parent, ypos, r.getLongName());
}
}
@@ -194,4 +195,4 @@ public class ClusterEvaluationVisualization extends AbstractVisFactory {
// Don't use thumbnails
return false;
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/HistogramVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/HistogramVisualization.java
index d97b5117..77f096fb 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/HistogramVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/HistogramVisualization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.visunproj;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/KeyVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/KeyVisualization.java
index f21e4df6..f18ef371 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/KeyVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/KeyVisualization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.visunproj;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,6 +23,9 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.visunproj;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import gnu.trove.map.TObjectIntMap;
+import gnu.trove.map.hash.TObjectIntHashMap;
+
import java.util.Collection;
import java.util.List;
@@ -38,7 +41,11 @@ import de.lmu.ifi.dbs.elki.data.model.Model;
import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
import de.lmu.ifi.dbs.elki.result.Result;
import de.lmu.ifi.dbs.elki.result.ResultUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.Hierarchy;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.Hierarchy.Iter;
+import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleDoublePair;
import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
+import de.lmu.ifi.dbs.elki.visualization.css.CSSClass;
import de.lmu.ifi.dbs.elki.visualization.style.ClusterStylingPolicy;
import de.lmu.ifi.dbs.elki.visualization.style.StyleLibrary;
import de.lmu.ifi.dbs.elki.visualization.style.StylingPolicy;
@@ -52,7 +59,7 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.Visualization;
/**
* Visualizer, displaying the key for a clustering.
- *
+ *
* @author Erich Schubert
*
* @apiviz.stereotype factory
@@ -68,24 +75,65 @@ public class KeyVisualization extends AbstractVisFactory {
public void processNewResult(HierarchicalResult baseResult, Result newResult) {
// Find clusterings we can visualize:
Collection<Clustering<?>> clusterings = ResultUtil.filterResults(newResult, Clustering.class);
- for(Clustering<?> c : clusterings) {
+ for (Clustering<?> c : clusterings) {
final int numc = c.getAllClusters().size();
- if(numc > 0) {
- // FIXME: compute from labels?
- final double maxwidth = 10.;
+ final int topc = c.getToplevelClusters().size();
+ if (numc > 0) {
final VisualizationTask task = new VisualizationTask(NAME, c, null, this);
- final int cols = getPreferredColumns(1.0, 1.0, numc, maxwidth);
- final int rows = (int) Math.ceil(numc / (double) cols);
- final double div = Math.max(2. + rows, cols * maxwidth);
- task.width = cols * maxwidth / div;
- task.height = (2. + rows) / div;
+ if (numc == topc) {
+ // FIXME: compute from labels?
+ final double maxwidth = 10.;
+ // Flat clustering.
+ final int cols = getPreferredColumns(1.0, 1.0, numc, maxwidth);
+ final int rows = (int) Math.ceil(numc / (double) cols);
+ final double ratio = cols * maxwidth / (2. + rows);
+ task.width = (ratio >= 1.) ? 1 : 1. / ratio;
+ task.height = (ratio >= 1.) ? 1. / ratio : 1;
+ if (numc > 100) {
+ task.width *= 2;
+ task.height *= 2;
+ }
+ } else {
+ // Hierarchical clustering.
+ final int[] shape = findDepth(c);
+ final double maxwidth = 8.;
+ final double ratio = shape[0] * maxwidth / (2. + shape[1]);
+ task.width = (ratio >= 1.) ? 1 : 1. / ratio;
+ task.height = (ratio >= 1.) ? 1. / ratio : 1;
+ if (shape[0] * maxwidth > 20 || shape[1] > 18) {
+ task.width *= 2;
+ task.height *= 2;
+ }
+ }
task.level = VisualizationTask.LEVEL_STATIC;
- task.nodetail = true;
+ if (numc < 20) {
+ task.nodetail = true;
+ }
baseResult.getHierarchy().add(c, task);
}
}
}
+ private static <M extends Model> int[] findDepth(Clustering<M> c) {
+ final Hierarchy<Cluster<M>> hier = c.getClusterHierarchy();
+ int[] size = { 0, 0 };
+ for (Iter<Cluster<M>> iter = c.iterToplevelClusters(); iter.valid(); iter.advance()) {
+ findDepth(hier, iter.get(), size);
+ }
+ return size;
+ }
+
+ private static <M extends Model> void findDepth(Hierarchy<Cluster<M>> hier, Cluster<M> cluster, int[] size) {
+ if (hier.numChildren(cluster) > 0) {
+ for (Iter<Cluster<M>> iter = hier.iterChildren(cluster); iter.valid(); iter.advance()) {
+ findDepth(hier, iter.get(), size);
+ }
+ size[0] += 1; // Depth
+ } else {
+ size[1] += 1; // Leaves
+ }
+ }
+
/**
* Compute the preferred number of columns.
*
@@ -123,6 +171,21 @@ public class KeyVisualization extends AbstractVisFactory {
*/
public class Instance extends AbstractVisualization {
/**
+ * CSS class for key captions.
+ */
+ private static final String KEY_CAPTION = "key-caption";
+
+ /**
+ * CSS class for key entries.
+ */
+ private static final String KEY_ENTRY = "key-entry";
+
+ /**
+ * CSS class for hierarchy plot lines
+ */
+ private static final String KEY_HIERLINE = "key-hierarchy";
+
+ /**
* Clustering to display
*/
private Clustering<Model> clustering;
@@ -147,59 +210,84 @@ public class KeyVisualization extends AbstractVisFactory {
@Override
public void resultChanged(Result current) {
super.resultChanged(current);
- if(current == context.getStyleResult()) {
+ if (current == context.getStyleResult()) {
incrementalRedraw();
}
}
@Override
protected void redraw() {
- SVGPlot svgp = task.getPlot();
StyleLibrary style = context.getStyleResult().getStyleLibrary();
MarkerLibrary ml = style.markers();
- // Maximum width (compared to height) of labels - guess.
- // FIXME: compute from labels?
- final double maxwidth = 10.;
-
final List<Cluster<Model>> allcs = clustering.getAllClusters();
- final int numc = allcs.size();
- final int cols = getPreferredColumns(task.getWidth(), task.getHeight(), numc, maxwidth);
- final int rows = 2 + (int) Math.ceil(numc / (double) cols);
- // We use a coordinate system based on rows, so columns are at c*maxwidth
+ final List<Cluster<Model>> topcs = clustering.getToplevelClusters();
+ setupCSS(svgp);
layer = svgp.svgElement(SVGConstants.SVG_G_TAG);
// Add a label for the clustering.
{
Element label = svgp.svgText(0.1, 0.7, clustering.getLongName());
- label.setAttribute(SVGConstants.SVG_STYLE_ATTRIBUTE, "font-size: 0.4; fill: " + style.getTextColor(StyleLibrary.DEFAULT));
+ SVGUtil.setCSSClass(label, KEY_CAPTION);
layer.appendChild(label);
}
- int i = 0;
- for(Cluster<Model> c : allcs) {
- final int col = i / rows;
- final int row = i % rows;
- ml.useMarker(svgp, layer, 0.3 + maxwidth * col, row + 1.5, i, 0.3);
- Element label = svgp.svgText(0.7 + maxwidth * col, row + 1.7, c.getNameAutomatic());
- label.setAttribute(SVGConstants.SVG_STYLE_ATTRIBUTE, "font-size: 0.6; fill: " + style.getTextColor(StyleLibrary.DEFAULT));
- layer.appendChild(label);
- i++;
+ final int extrarows = 2;
+ double kwi, khe;
+ if (allcs.size() == topcs.size()) {
+ // Maximum width (compared to height) of labels - guess.
+ // FIXME: compute from labels?
+ final double maxwidth = 10.;
+
+ // Flat clustering. Use multiple columns.
+ final int numc = allcs.size();
+ final int cols = getPreferredColumns(task.getWidth(), task.getHeight(), numc, maxwidth);
+ final int rows = (int) Math.ceil(numc / (double) cols);
+ // We use a coordinate system based on rows, so columns are at
+ // c*maxwidth
+
+ int i = 0;
+ for (Cluster<Model> c : allcs) {
+ final int col = i / rows;
+ final int row = i % rows;
+ ml.useMarker(svgp, layer, 0.3 + maxwidth * col, row + 1.5, i, 0.3);
+ Element label = svgp.svgText(0.7 + maxwidth * col, row + 1.7, c.getNameAutomatic());
+ SVGUtil.setCSSClass(label, KEY_ENTRY);
+ layer.appendChild(label);
+ i++;
+ }
+ kwi = cols * maxwidth;
+ khe = rows;
+ } else {
+ // For consistent keying:
+ TObjectIntMap<Cluster<Model>> cnum = new TObjectIntHashMap<>(allcs.size());
+ int i = 0;
+ for (Cluster<Model> c : allcs) {
+ cnum.put(c, i);
+ i++;
+ }
+ // Hierarchical clustering. Draw recursively.
+ DoubleDoublePair size = new DoubleDoublePair(0., 1.), pos = new DoubleDoublePair(0., 1.);
+ Hierarchy<Cluster<Model>> hier = clustering.getClusterHierarchy();
+ for (Cluster<Model> cluster : topcs) {
+ drawHierarchy(svgp, ml, size, pos, 0, cluster, cnum, hier);
+ }
+ kwi = size.first;
+ khe = size.second;
}
// Add a button to set style policy
{
StylingPolicy sp = context.getStyleResult().getStylingPolicy();
- if(sp instanceof ClusterStylingPolicy && ((ClusterStylingPolicy) sp).getClustering() == clustering) {
+ if (sp instanceof ClusterStylingPolicy && ((ClusterStylingPolicy) sp).getClustering() == clustering) {
// Don't show the button when active. May confuse people more than the
// disappearing button?
// SVGButton button = new SVGButton(.1, rows + 1.1, 3.8, .7, .2);
// button.setTitle("Active style", "darkgray");
// layer.appendChild(button.render(svgp));
- }
- else {
- SVGButton button = new SVGButton(.1, rows + 1.1, 3.8, .7, .2);
+ } else {
+ SVGButton button = new SVGButton(.1, khe + 1.1, 3.8, .7, .2);
button.setTitle("Set style", "black");
Element elem = button.render(svgp);
// Attach listener
@@ -214,14 +302,44 @@ public class KeyVisualization extends AbstractVisFactory {
}
}
- // int rows = i + 2;
- // int cols = Math.max(6, (int) (rows * task.getHeight() /
- // task.getWidth()));
final double margin = style.getSize(StyleLibrary.MARGIN);
- final String transform = SVGUtil.makeMarginTransform(task.getWidth(), task.getHeight(), cols * maxwidth, rows, margin / StyleLibrary.SCALE);
+ final String transform = SVGUtil.makeMarginTransform(task.getWidth(), task.getHeight(), kwi, khe + extrarows, margin / StyleLibrary.SCALE);
SVGUtil.setAtt(layer, SVGConstants.SVG_TRANSFORM_ATTRIBUTE, transform);
}
+ private double drawHierarchy(SVGPlot svgp, MarkerLibrary ml, DoubleDoublePair size, DoubleDoublePair pos, int depth, Cluster<Model> cluster, TObjectIntMap<Cluster<Model>> cnum, Hierarchy<Cluster<Model>> hier) {
+ final double maxwidth = 8.;
+ DoubleDoublePair subpos = new DoubleDoublePair(pos.first + maxwidth, pos.second);
+ int numc = hier.numChildren(cluster);
+ double posy;
+ if (numc > 0) {
+ double[] mids = new double[numc];
+ Iter<Cluster<Model>> iter = hier.iterChildren(cluster);
+ for (int i = 0; iter.valid(); iter.advance(), i++) {
+ mids[i] = drawHierarchy(svgp, ml, size, subpos, depth, iter.get(), cnum, hier);
+ }
+ // Center:
+ posy = (pos.second + subpos.second) * .5;
+ for (int i = 0; i < numc; i++) {
+ Element line = svgp.svgLine(pos.first + maxwidth - 1., posy + .5, pos.first + maxwidth, mids[i] + .5);
+ SVGUtil.setCSSClass(line, KEY_HIERLINE);
+ layer.appendChild(line);
+ }
+ // Use vertical extends of children:
+ pos.second = subpos.second;
+ } else {
+ posy = pos.second + .5;
+ pos.second += 1.;
+ }
+ ml.useMarker(svgp, layer, 0.3 + pos.first, posy + 0.5, cnum.get(cluster), 0.3);
+ Element label = svgp.svgText(0.7 + pos.first, posy + 0.7, cluster.getNameAutomatic());
+ SVGUtil.setCSSClass(label, KEY_ENTRY);
+ layer.appendChild(label);
+ size.first = Math.max(size.first, pos.first + maxwidth);
+ size.second = Math.max(size.second, pos.second);
+ return posy;
+ }
+
/**
* Trigger a style change.
*/
@@ -229,5 +347,37 @@ public class KeyVisualization extends AbstractVisFactory {
context.getStyleResult().setStylingPolicy(new ClusterStylingPolicy(clustering, context.getStyleResult().getStyleLibrary()));
context.getHierarchy().resultChanged(context.getStyleResult());
}
+
+ /**
+ * Registers the Tooltip-CSS-Class at a SVGPlot.
+ *
+ * @param svgp the SVGPlot to register the Tooltip-CSS-Class.
+ */
+ protected void setupCSS(SVGPlot svgp) {
+ final StyleLibrary style = context.getStyleResult().getStyleLibrary();
+ final double fontsize = style.getTextSize(StyleLibrary.KEY);
+ final String fontfamily = style.getFontFamily(StyleLibrary.KEY);
+ final String color = style.getColor(StyleLibrary.KEY);
+
+ CSSClass keycaption = new CSSClass(svgp, KEY_CAPTION);
+ keycaption.setStatement(SVGConstants.CSS_FONT_SIZE_PROPERTY, fontsize);
+ keycaption.setStatement(SVGConstants.CSS_FONT_FAMILY_PROPERTY, fontfamily);
+ keycaption.setStatement(SVGConstants.CSS_FILL_PROPERTY, color);
+ keycaption.setStatement(SVGConstants.CSS_FONT_WEIGHT_PROPERTY, SVGConstants.CSS_BOLD_VALUE);
+ svgp.addCSSClassOrLogError(keycaption);
+
+ CSSClass keyentry = new CSSClass(svgp, KEY_ENTRY);
+ keyentry.setStatement(SVGConstants.CSS_FONT_SIZE_PROPERTY, fontsize);
+ keyentry.setStatement(SVGConstants.CSS_FONT_FAMILY_PROPERTY, fontfamily);
+ keyentry.setStatement(SVGConstants.CSS_FILL_PROPERTY, color);
+ svgp.addCSSClassOrLogError(keyentry);
+
+ CSSClass hierline = new CSSClass(svgp, KEY_HIERLINE);
+ hierline.setStatement(SVGConstants.CSS_STROKE_PROPERTY, color);
+ hierline.setStatement(SVGConstants.CSS_STROKE_WIDTH_PROPERTY, style.getLineWidth("key.hierarchy") / StyleLibrary.SCALE);
+ svgp.addCSSClassOrLogError(hierline);
+
+ svgp.updateStyleElement();
+ }
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/LabelVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/LabelVisualization.java
index d29a6467..0fe96e50 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/LabelVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/LabelVisualization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.visunproj;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/PixmapVisualizer.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/PixmapVisualizer.java
index 19cc6254..60080373 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/PixmapVisualizer.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/PixmapVisualizer.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.visunproj;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/SettingsVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/SettingsVisualization.java
index 736f28e7..d39d5bfd 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/SettingsVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/SettingsVisualization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.visunproj;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -143,6 +143,7 @@ public class SettingsVisualization extends AbstractVisFactory {
task.width = 1.0;
task.height = 1.0;
task.level = VisualizationTask.LEVEL_STATIC;
+ task.initDefaultVisibility(false);
baseResult.getHierarchy().add(sr, task);
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/SimilarityMatrixVisualizer.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/SimilarityMatrixVisualizer.java
index f1404050..b4570a32 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/SimilarityMatrixVisualizer.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/SimilarityMatrixVisualizer.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.visunproj;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,6 +29,7 @@ import java.util.Collection;
import org.apache.batik.util.SVGConstants;
import org.w3c.dom.Element;
+import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.evaluation.similaritymatrix.ComputeSimilarityMatrixImage;
@@ -145,7 +146,8 @@ public class SimilarityMatrixVisualizer extends AbstractVisFactory {
final double hlsize = StyleLibrary.SCALE * zoom * iratio / size;
final double vlsize = StyleLibrary.SCALE * zoom / size;
int i = 0;
- final Relation<String> lrep = DatabaseUtil.guessObjectLabelRepresentation(result.getRelation().getDatabase());
+ Database database = ResultUtil.findDatabase(context.getResult());
+ final Relation<String> lrep = DatabaseUtil.guessObjectLabelRepresentation(database);
for(DBIDIter id = result.getIDs().iter(); id.valid(); id.advance()) {
String label = lrep.get(id);
if(label != null) {
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/XYCurveVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/XYCurveVisualization.java
index 76ce7c09..691ab925 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/XYCurveVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/XYCurveVisualization.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.visunproj;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -133,7 +133,7 @@ public class XYCurveVisualization extends AbstractVisFactory {
// Add AUC value when found
if(curve instanceof ROCResult) {
double rocauc = ((ROCResult) curve).getAUC();
- String lt = OutlierROCCurve.ROCAUC_LABEL + ": " + FormatUtil.NF8.format(rocauc);
+ String lt = OutlierROCCurve.ROCAUC_LABEL + ": " + FormatUtil.NF.format(rocauc);
if(rocauc <= 0.5) {
Element auclbl = svgp.svgText(sizex * 0.5, sizey * 0.10, lt);
SVGUtil.setCSSClass(auclbl, CSS_AXIS_LABEL);
@@ -147,7 +147,7 @@ public class XYCurveVisualization extends AbstractVisFactory {
}
if(curve instanceof PRCurve) {
double prauc = ((PRCurve) curve).getAUC();
- String lt = PRCurve.PRAUC_LABEL + ": " + FormatUtil.NF8.format(prauc);
+ String lt = PRCurve.PRAUC_LABEL + ": " + FormatUtil.NF.format(prauc);
if(prauc <= 0.5) {
Element auclbl = svgp.svgText(sizex * 0.5, sizey * 0.10, lt);
SVGUtil.setCSSClass(auclbl, CSS_AXIS_LABEL);
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/package-info.java
index 30042923..ff45c35e 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/package-info.java
@@ -6,7 +6,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/workflow/AlgorithmStep.java b/src/de/lmu/ifi/dbs/elki/workflow/AlgorithmStep.java
index cdaf702d..9367eb30 100644
--- a/src/de/lmu/ifi/dbs/elki/workflow/AlgorithmStep.java
+++ b/src/de/lmu/ifi/dbs/elki/workflow/AlgorithmStep.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.workflow;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -30,12 +30,10 @@ import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.index.Index;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.LoggingConfiguration;
-import de.lmu.ifi.dbs.elki.persistent.PageFileStatistics;
-import de.lmu.ifi.dbs.elki.persistent.PageFileUtil;
+import de.lmu.ifi.dbs.elki.logging.statistics.Duration;
import de.lmu.ifi.dbs.elki.result.BasicResult;
import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
import de.lmu.ifi.dbs.elki.result.Result;
-import de.lmu.ifi.dbs.elki.utilities.FormatUtil;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
@@ -86,31 +84,29 @@ public class AlgorithmStep implements WorkflowStep {
public HierarchicalResult runAlgorithms(Database database) {
result = new BasicResult("Algorithm Step", "main");
result.addChildResult(database);
- if(LOG.isVerbose() && database.getIndexes().size() > 0) {
- StringBuilder buf = new StringBuilder();
- buf.append("Index statistics before running algorithms:").append(FormatUtil.NEWLINE);
- for(Index idx : database.getIndexes()) {
- PageFileStatistics stat = idx.getPageFileStatistics();
- PageFileUtil.appendPageFileStatistics(buf, stat);
+ if (LOG.isStatistics() && database.getIndexes().size() > 0) {
+ LOG.statistics("Index statistics before running algorithms:");
+ for (Index idx : database.getIndexes()) {
+ idx.logStatistics();
}
- LOG.verbose(buf.toString());
}
- for(Algorithm algorithm : algorithms) {
- long start = System.currentTimeMillis();
+ for (Algorithm algorithm : algorithms) {
+ Duration duration = LOG.isStatistics() ? LOG.newDuration(algorithm.getClass().getName()+".runtime") : null;
+ if (duration != null) {
+ duration.begin();
+ }
Result res = algorithm.run(database);
- long end = System.currentTimeMillis();
- if(LOG.isVerbose()) {
- long elapsedTime = end - start;
- StringBuilder buf = new StringBuilder();
- buf.append(algorithm.getClass().getName()).append(" runtime : ");
- buf.append(elapsedTime).append(" milliseconds.").append(FormatUtil.NEWLINE);
- for(Index idx : database.getIndexes()) {
- PageFileStatistics stat = idx.getPageFileStatistics();
- PageFileUtil.appendPageFileStatistics(buf, stat);
+ if (duration != null) {
+ duration.end();
+ LOG.statistics(duration);
+ }
+ if (LOG.isStatistics()) {
+ LOG.statistics("Index statistics after running algorithms:");
+ for (Index idx : database.getIndexes()) {
+ idx.logStatistics();
}
- LOG.verbose(buf.toString());
}
- if(res != null) {
+ if (res != null) {
result.addChildResult(res);
}
}
@@ -144,25 +140,43 @@ public class AlgorithmStep implements WorkflowStep {
*/
protected List<Algorithm> algorithms;
+ /**
+ * Flag to allow verbose messages while running the application.
+ * <p>
+ * Key: {@code -time}
+ * </p>
+ */
+ public static final OptionID TIME_ID = new OptionID("time", "Enable logging of runtime data. Do not combine with more verbose logging, since verbose logging can significantly impact performance.");
+
+ /**
+ * Parameter to specify the algorithm to run.
+ * <p>
+ * Key: {@code -algorithm}
+ * </p>
+ */
+ public static final OptionID ALGORITHM_ID = new OptionID("algorithm", "Algorithm to run.");
+
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
// Time parameter
- final Flag timeF = new Flag(OptionID.TIME_FLAG);
- if(config.grab(timeF)) {
+ final Flag timeF = new Flag(TIME_ID);
+ if (config.grab(timeF)) {
time = timeF.getValue();
}
// parameter algorithm
- final ObjectListParameter<Algorithm> ALGORITHM_PARAM = new ObjectListParameter<Algorithm>(OptionID.ALGORITHM, Algorithm.class);
- if(config.grab(ALGORITHM_PARAM)) {
+ final ObjectListParameter<Algorithm> ALGORITHM_PARAM = new ObjectListParameter<>(ALGORITHM_ID, Algorithm.class);
+ if (config.grab(ALGORITHM_PARAM)) {
algorithms = ALGORITHM_PARAM.instantiateClasses(config);
}
}
@Override
protected AlgorithmStep makeInstance() {
- LoggingConfiguration.setTime(time);
+ if (time) {
+ LoggingConfiguration.setStatistics();
+ }
return new AlgorithmStep(algorithms);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/workflow/EvaluationStep.java b/src/de/lmu/ifi/dbs/elki/workflow/EvaluationStep.java
index fdc1f201..0b6c9f8f 100644
--- a/src/de/lmu/ifi/dbs/elki/workflow/EvaluationStep.java
+++ b/src/de/lmu/ifi/dbs/elki/workflow/EvaluationStep.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.workflow;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -68,7 +68,7 @@ public class EvaluationStep implements WorkflowStep {
public void runEvaluators(HierarchicalResult r, Database db) {
// Run evaluation helpers
- if(evaluators != null) {
+ if (evaluators != null) {
new Evaluation(r, evaluators).update(r);
}
this.result = r;
@@ -111,7 +111,7 @@ public class EvaluationStep implements WorkflowStep {
* @param r Result
*/
public void update(Result r) {
- for(Evaluator evaluator : evaluators) {
+ for (Evaluator evaluator : evaluators) {
/*
* if(normalizationUndo) { evaluator.setNormalization(normalization); }
*/
@@ -153,15 +153,25 @@ public class EvaluationStep implements WorkflowStep {
*/
private List<Evaluator> evaluators = null;
+ /**
+ * Parameter ID to specify the evaluators to run.
+ *
+ * Key:
+ * <p>
+ * {@code -evaluator}
+ * </p>
+ */
+ public static final OptionID EVALUATOR_ID = new OptionID("evaluator", "Class to evaluate the results with.");
+
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- List<Class<? extends Evaluator>> def = new ArrayList<Class<? extends Evaluator>>(1);
+ List<Class<? extends Evaluator>> def = new ArrayList<>(1);
def.add(AutomaticEvaluation.class);
// evaluator parameter
- final ObjectListParameter<Evaluator> evaluatorP = new ObjectListParameter<Evaluator>(OptionID.EVALUATOR, Evaluator.class);
+ final ObjectListParameter<Evaluator> evaluatorP = new ObjectListParameter<>(EVALUATOR_ID, Evaluator.class);
evaluatorP.setDefaultValue(def);
- if(config.grab(evaluatorP)) {
+ if (config.grab(evaluatorP)) {
evaluators = evaluatorP.instantiateClasses(config);
}
}
@@ -171,4 +181,4 @@ public class EvaluationStep implements WorkflowStep {
return new EvaluationStep(evaluators);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/workflow/InputStep.java b/src/de/lmu/ifi/dbs/elki/workflow/InputStep.java
index 95a58f60..ea258889 100644
--- a/src/de/lmu/ifi/dbs/elki/workflow/InputStep.java
+++ b/src/de/lmu/ifi/dbs/elki/workflow/InputStep.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.workflow;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -45,7 +45,7 @@ public class InputStep implements WorkflowStep {
/**
* Constructor.
- *
+ *
* @param database Database to use
*/
public InputStep(Database database) {
@@ -62,7 +62,7 @@ public class InputStep implements WorkflowStep {
database.initialize();
return database;
}
-
+
/**
* Parameterization class.
*
@@ -76,13 +76,23 @@ public class InputStep implements WorkflowStep {
*/
protected Database database = null;
+ /**
+ * Option ID to specify the database type
+ *
+ * Key:
+ * <p>
+ * {@code -db}
+ * </p>
+ */
+ public static final OptionID DATABASE_ID = new OptionID("db", "Database class.");
+
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- final ObjectParameter<Database> dbP = new ObjectParameter<Database>(OptionID.DATABASE, Database.class, StaticArrayDatabase.class);
- if(config.grab(dbP)) {
+ final ObjectParameter<Database> dbP = new ObjectParameter<>(DATABASE_ID, Database.class, StaticArrayDatabase.class);
+ if (config.grab(dbP)) {
database = dbP.instantiateClass(config);
- }
+ }
}
@Override
@@ -90,4 +100,4 @@ public class InputStep implements WorkflowStep {
return new InputStep(database);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/workflow/LoggingStep.java b/src/de/lmu/ifi/dbs/elki/workflow/LoggingStep.java
index b4f6070b..9b598b0a 100644
--- a/src/de/lmu/ifi/dbs/elki/workflow/LoggingStep.java
+++ b/src/de/lmu/ifi/dbs/elki/workflow/LoggingStep.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.workflow;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,13 +23,12 @@ package de.lmu.ifi.dbs.elki.workflow;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.logging.Level;
-
+import de.lmu.ifi.dbs.elki.application.AbstractApplication;
import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.Logging.Level;
import de.lmu.ifi.dbs.elki.logging.LoggingConfiguration;
import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.WrongParameterValueException;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Flag;
@@ -54,30 +53,33 @@ public class LoggingStep implements WorkflowStep {
* @param verbose Verbose flag
* @param levels Level settings array
*/
- public LoggingStep(boolean verbose, String[][] levels) {
+ public LoggingStep(int verbose, String[][] levels) {
super();
- LoggingConfiguration.setVerbose(verbose);
- if(levels != null) {
- for(String[] pair : levels) {
+ if (verbose <= 0) {
+ LoggingConfiguration.setVerbose(Level.WARNING);
+ } else if (verbose == 1) {
+ LoggingConfiguration.setVerbose(Level.VERBOSE);
+ } else if (verbose > 1) {
+ // Extra verbosity - do not call with "false" to not undo!
+ LoggingConfiguration.setVerbose(Level.VERYVERBOSE);
+ }
+ if (levels != null) {
+ for (String[] pair : levels) {
try {
- if(pair.length == 1) {
+ if (pair.length == 1) {
// Try to parse as level:
try {
- Level level = Level.parse(pair[0]);
+ java.util.logging.Level level = Level.parse(pair[0]);
LoggingConfiguration.setDefaultLevel(level);
- }
- catch(IllegalArgumentException e) {
+ } catch (IllegalArgumentException e) {
LoggingConfiguration.setLevelFor(pair[0], Level.FINEST.getName());
}
- }
- else if(pair.length == 2) {
+ } else if (pair.length == 2) {
LoggingConfiguration.setLevelFor(pair[0], pair[1]);
- }
- else {
+ } else {
throw new AbortException("Invalid logging settings");
}
- }
- catch(IllegalArgumentException e) {
+ } catch (IllegalArgumentException e) {
LOG.warning("Invalid logging statement for package " + pair[0] + ": " + e.getMessage());
}
}
@@ -93,10 +95,10 @@ public class LoggingStep implements WorkflowStep {
*/
public static class Parameterizer extends AbstractParameterizer {
/**
- * Verbose mode
+ * Verbose mode.
*/
- protected boolean verbose = false;
-
+ protected int verbose = 0;
+
/**
* Enable logging levels manually
*/
@@ -105,19 +107,23 @@ public class LoggingStep implements WorkflowStep {
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- final Flag verboseF = new Flag(OptionID.VERBOSE_FLAG);
- if(config.grab(verboseF)) {
- verbose = verboseF.getValue();
+ final Flag verboseF = new Flag(AbstractApplication.Parameterizer.VERBOSE_ID);
+ if (config.grab(verboseF) && verboseF.isTrue()) {
+ verbose++;
+ final Flag verbose2F = new Flag(AbstractApplication.Parameterizer.VERBOSE_ID);
+ if (config.grab(verbose2F) && verbose2F.isTrue()) {
+ verbose++;
+ }
}
- final StringParameter debugP = new StringParameter(OptionID.DEBUG);
+ final StringParameter debugP = new StringParameter(AbstractApplication.Parameterizer.DEBUG_ID);
debugP.setOptional(true);
- if(config.grab(debugP)) {
+ if (config.grab(debugP)) {
String[] opts = debugP.getValue().split(",");
levels = new String[opts.length][];
int i = 0;
- for(String opt : opts) {
+ for (String opt : opts) {
String[] chunks = opt.split("=");
- if(chunks.length != 1 && chunks.length != 2) {
+ if (chunks.length != 1 && chunks.length != 2) {
config.reportError(new WrongParameterValueException(debugP, debugP.getValue(), "Invalid debug option."));
break;
}
@@ -132,4 +138,4 @@ public class LoggingStep implements WorkflowStep {
return new LoggingStep(verbose, levels);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/workflow/OutputStep.java b/src/de/lmu/ifi/dbs/elki/workflow/OutputStep.java
index b7289f95..a196c752 100644
--- a/src/de/lmu/ifi/dbs/elki/workflow/OutputStep.java
+++ b/src/de/lmu/ifi/dbs/elki/workflow/OutputStep.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.workflow;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -66,7 +66,7 @@ public class OutputStep implements WorkflowStep {
*/
public void runResultHandlers(HierarchicalResult result) {
// Run result handlers
- for(ResultHandler resulthandler : resulthandlers) {
+ for (ResultHandler resulthandler : resulthandlers) {
resulthandler.processNewResult(result, result);
}
}
@@ -75,7 +75,7 @@ public class OutputStep implements WorkflowStep {
* Set the default handler to the {@link ResultWriter}.
*/
public static void setDefaultHandlerWriter() {
- defaultHandlers = new ArrayList<Class<? extends ResultHandler>>(1);
+ defaultHandlers = new ArrayList<>(1);
defaultHandlers.add(ResultWriter.class);
}
@@ -83,10 +83,10 @@ public class OutputStep implements WorkflowStep {
* Set the default handler to the {@link ResultVisualizer}.
*/
public static void setDefaultHandlerVisualizer() {
- defaultHandlers = new ArrayList<Class<? extends ResultHandler>>(1);
+ defaultHandlers = new ArrayList<>(1);
defaultHandlers.add(ResultVisualizer.class);
}
-
+
protected static ArrayList<Class<? extends ResultHandler>> defaultHandlers = null;
/**
@@ -102,15 +102,37 @@ public class OutputStep implements WorkflowStep {
*/
private List<ResultHandler> resulthandlers = null;
+ /**
+ * Parameter to specify the result handler classes.
+ *
+ * Key:
+ * <p>
+ * {@code -resulthandler}
+ * </p>
+ */
+ public static final OptionID RESULT_HANDLER_ID = new OptionID("resulthandler", "Result handler class.");
+
+ /**
+ * OptionID for the application output file/folder.
+ *
+ * Key:
+ * <p>
+ * {@code -out}
+ * </p>
+ */
+ public static final OptionID OUTPUT_ID = new OptionID("out", //
+ "Directory name (or name of an existing file) to write the obtained results in. " + //
+ "If this parameter is omitted, per default the output will sequentially be given to STDOUT.");
+
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
// result handlers
- final ObjectListParameter<ResultHandler> resultHandlerParam = new ObjectListParameter<ResultHandler>(OptionID.RESULT_HANDLER, ResultHandler.class);
+ final ObjectListParameter<ResultHandler> resultHandlerParam = new ObjectListParameter<>(RESULT_HANDLER_ID, ResultHandler.class);
if (defaultHandlers != null) {
resultHandlerParam.setDefaultValue(defaultHandlers);
}
- if(config.grab(resultHandlerParam)) {
+ if (config.grab(resultHandlerParam)) {
resulthandlers = resultHandlerParam.instantiateClasses(config);
}
}
@@ -120,4 +142,4 @@ public class OutputStep implements WorkflowStep {
return new OutputStep(resulthandlers);
}
}
-} \ No newline at end of file
+}
diff --git a/src/de/lmu/ifi/dbs/elki/workflow/WorkflowStep.java b/src/de/lmu/ifi/dbs/elki/workflow/WorkflowStep.java
index 6117e3d6..9f9b54bf 100644
--- a/src/de/lmu/ifi/dbs/elki/workflow/WorkflowStep.java
+++ b/src/de/lmu/ifi/dbs/elki/workflow/WorkflowStep.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.workflow;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/workflow/package-info.java b/src/de/lmu/ifi/dbs/elki/workflow/package-info.java
index 17cefb27..3e4396dd 100644
--- a/src/de/lmu/ifi/dbs/elki/workflow/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/workflow/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2012
+Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/tutorial/clustering/NaiveAgglomerativeHierarchicalClustering1.java b/src/tutorial/clustering/NaiveAgglomerativeHierarchicalClustering1.java
new file mode 100644
index 00000000..ad620d0e
--- /dev/null
+++ b/src/tutorial/clustering/NaiveAgglomerativeHierarchicalClustering1.java
@@ -0,0 +1,241 @@
+package tutorial.clustering;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import gnu.trove.map.TIntObjectMap;
+import gnu.trove.map.hash.TIntObjectHashMap;
+
+import java.util.Arrays;
+
+import de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm;
+import de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical.ExtractFlatClusteringFromHierarchy;
+import de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical.SLINK;
+import de.lmu.ifi.dbs.elki.data.Cluster;
+import de.lmu.ifi.dbs.elki.data.Clustering;
+import de.lmu.ifi.dbs.elki.data.model.Model;
+import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
+import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.database.Database;
+import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDArrayIter;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
+import de.lmu.ifi.dbs.elki.result.Result;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterEqualConstraint;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
+
+/**
+ * This tutorial will step you through implementing a well known clustering
+ * algorithm, agglomerative hierarchical clustering, in multiple steps.
+ *
+ * This is the first step, where we implement it with single linkage only, and
+ * extract a fixed number of clusters. The follow up variants will be made more
+ * flexible.
+ *
+ * This is the naive O(n^3) algorithm. See {@link SLINK} for a much faster
+ * algorithm (however, only for single-linkage).
+ *
+ * @author Erich Schubert
+ *
+ * @param <O> Object type
+ */
+public class NaiveAgglomerativeHierarchicalClustering1<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBasedAlgorithm<O, D, Result> {
+ /**
+ * Class logger
+ */
+ private static final Logging LOG = Logging.getLogger(NaiveAgglomerativeHierarchicalClustering1.class);
+
+ /**
+ * Threshold, how many clusters to extract.
+ */
+ int numclusters;
+
+ /**
+ * Constructor.
+ *
+ * @param distanceFunction Distance function to use
+ * @param numclusters Number of clusters
+ */
+ public NaiveAgglomerativeHierarchicalClustering1(DistanceFunction<? super O, D> distanceFunction, int numclusters) {
+ super(distanceFunction);
+ this.numclusters = numclusters;
+ }
+
+ /**
+ * Run the algorithm
+ *
+ * @param db Database
+ * @param relation Relation
+ * @return Clustering hierarchy
+ */
+ public Result run(Database db, Relation<O> relation) {
+ DistanceQuery<O, D> dq = db.getDistanceQuery(relation, getDistanceFunction());
+ ArrayDBIDs ids = DBIDUtil.ensureArray(relation.getDBIDs());
+ final int size = ids.size();
+
+ LOG.verbose("Notice: SLINK is a much faster algorithm for single-linkage clustering!");
+
+ // Compute the initial distance matrix.
+ double[][] matrix = new double[size][size];
+ DBIDArrayIter ix = ids.iter(), iy = ids.iter();
+ for (int x = 0; ix.valid(); x++, ix.advance()) {
+ iy.seek(0);
+ for (int y = 0; y < x; y++, iy.advance()) {
+ final double dist = dq.distance(ix, iy).doubleValue();
+ matrix[x][y] = dist;
+ matrix[y][x] = dist;
+ }
+ }
+
+ // Initialize space for result:
+ double[] height = new double[size];
+ Arrays.fill(height, Double.POSITIVE_INFINITY);
+ // Parent node, to track merges
+ // have every object point to itself initially
+ ArrayModifiableDBIDs parent = DBIDUtil.newArray(ids);
+ // Active clusters, when not trivial.
+ TIntObjectMap<ModifiableDBIDs> clusters = new TIntObjectHashMap<>();
+
+ // Repeat until everything merged, except the desired number of clusters:
+ final int stop = size - numclusters;
+ FiniteProgress prog = LOG.isVerbose() ? new FiniteProgress("Agglomerative clustering", stop, LOG) : null;
+ for (int i = 0; i < stop; i++) {
+ double min = Double.POSITIVE_INFINITY;
+ int minx = -1, miny = -1;
+ for (int x = 0; x < size; x++) {
+ if (height[x] < Double.POSITIVE_INFINITY) {
+ continue;
+ }
+ for (int y = 0; y < x; y++) {
+ if (height[y] < Double.POSITIVE_INFINITY) {
+ continue;
+ }
+ if (matrix[x][y] < min) {
+ min = matrix[x][y];
+ minx = x;
+ miny = y;
+ }
+ }
+ }
+ assert (minx >= 0 && miny >= 0);
+ // Avoid allocating memory, by reusing existing iterators:
+ ix.seek(minx);
+ iy.seek(miny);
+ // Perform merge in data structure: x -> y
+ // Since y < x, prefer keeping y, dropping x.
+ height[minx] = min;
+ parent.set(minx, iy);
+ // Merge into cluster
+ ModifiableDBIDs cx = clusters.get(minx);
+ ModifiableDBIDs cy = clusters.get(miny);
+ if (cy == null) {
+ cy = DBIDUtil.newHashSet();
+ cy.add(iy);
+ }
+ if (cx == null) {
+ cy.add(ix);
+ } else {
+ cy.addDBIDs(cx);
+ clusters.remove(minx);
+ }
+ clusters.put(miny, cy);
+ // Update distance matrix for y:
+ for (int j = 0; j < size; j++) {
+ matrix[j][miny] = Math.min(matrix[j][minx], matrix[j][miny]);
+ matrix[miny][j] = Math.min(matrix[minx][j], matrix[miny][j]);
+ }
+ if (prog != null) {
+ prog.incrementProcessed(LOG);
+ }
+ }
+ if (prog != null) {
+ prog.ensureCompleted(LOG);
+ }
+
+ // Build the clustering result
+ final Clustering<Model> dendrogram = new Clustering<>("Hierarchical-Clustering", "hierarchical-clustering");
+ for (int x = 0; x < size; x++) {
+ if (height[x] < Double.POSITIVE_INFINITY) {
+ DBIDs cids = clusters.get(x);
+ if (cids == null) {
+ ix.seek(x);
+ cids = DBIDUtil.deref(ix);
+ }
+ Cluster<Model> cluster = new Cluster<>("Cluster", cids);
+ dendrogram.addToplevelCluster(cluster);
+ }
+ }
+ return dendrogram;
+ }
+
+ @Override
+ public TypeInformation[] getInputTypeRestriction() {
+ // The input relation must match our distance function:
+ return TypeUtil.array(getDistanceFunction().getInputTypeRestriction());
+ }
+
+ @Override
+ protected Logging getLogger() {
+ return LOG;
+ }
+
+ /**
+ * Parameterization class
+ *
+ * @author Erich Schubert
+ *
+ * @param <O> Object type
+ * @param <D> Distance type
+ */
+ public static class Parameterizer<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBasedAlgorithm.Parameterizer<O, D> {
+ /**
+ * Desired number of clusters.
+ */
+ int numclusters = 0;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ IntParameter numclustersP = new IntParameter(ExtractFlatClusteringFromHierarchy.Parameterizer.MINCLUSTERS_ID);
+ numclustersP.addConstraint(new GreaterEqualConstraint(1));
+ if (config.grab(numclustersP)) {
+ numclusters = numclustersP.intValue();
+ }
+ }
+
+ @Override
+ protected NaiveAgglomerativeHierarchicalClustering1<O, D> makeInstance() {
+ return new NaiveAgglomerativeHierarchicalClustering1<>(distanceFunction, numclusters);
+ }
+ }
+}
diff --git a/src/tutorial/clustering/NaiveAgglomerativeHierarchicalClustering2.java b/src/tutorial/clustering/NaiveAgglomerativeHierarchicalClustering2.java
new file mode 100644
index 00000000..88dc4bab
--- /dev/null
+++ b/src/tutorial/clustering/NaiveAgglomerativeHierarchicalClustering2.java
@@ -0,0 +1,278 @@
+package tutorial.clustering;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import gnu.trove.map.TIntObjectMap;
+import gnu.trove.map.hash.TIntObjectHashMap;
+
+import java.util.Arrays;
+
+import de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm;
+import de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical.ExtractFlatClusteringFromHierarchy;
+import de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical.SLINK;
+import de.lmu.ifi.dbs.elki.data.Cluster;
+import de.lmu.ifi.dbs.elki.data.Clustering;
+import de.lmu.ifi.dbs.elki.data.model.Model;
+import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
+import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.database.Database;
+import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDArrayIter;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
+import de.lmu.ifi.dbs.elki.result.Result;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterEqualConstraint;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
+
+/**
+ * This tutorial will step you through implementing a well known clustering
+ * algorithm, agglomerative hierarchical clustering, in multiple steps.
+ *
+ * This is the second step, where we increase the performance of the algorithm
+ * by using an improved linear memory layout instead of ragged arrays.
+ *
+ * This is the naive O(n^3) algorithm. See {@link SLINK} for a much faster
+ * algorithm (however, only for single-linkage).
+ *
+ * @author Erich Schubert
+ *
+ * @param <O> Object type
+ */
+public class NaiveAgglomerativeHierarchicalClustering2<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBasedAlgorithm<O, D, Result> {
+ /**
+ * Class logger
+ */
+ private static final Logging LOG = Logging.getLogger(NaiveAgglomerativeHierarchicalClustering2.class);
+
+ /**
+ * Threshold, how many clusters to extract.
+ */
+ int numclusters;
+
+ /**
+ * Constructor.
+ *
+ * @param distanceFunction Distance function to use
+ * @param numclusters Number of clusters
+ */
+ public NaiveAgglomerativeHierarchicalClustering2(DistanceFunction<? super O, D> distanceFunction, int numclusters) {
+ super(distanceFunction);
+ this.numclusters = numclusters;
+ }
+
+ /**
+ * Run the algorithm
+ *
+ * @param db Database
+ * @param relation Relation
+ * @return Clustering hierarchy
+ */
+ public Result run(Database db, Relation<O> relation) {
+ DistanceQuery<O, D> dq = db.getDistanceQuery(relation, getDistanceFunction());
+ ArrayDBIDs ids = DBIDUtil.ensureArray(relation.getDBIDs());
+ final int size = ids.size();
+
+ if (size > 0x10000) {
+ throw new AbortException("This implementation does not scale to data sets larger than " + 0x10000 + " instances (~17 GB RAM), which results in an integer overflow.");
+ }
+ LOG.verbose("Notice: SLINK is a much faster algorithm for single-linkage clustering!");
+
+ // Compute the initial (lower triangular) distance matrix.
+ double[] scratch = new double[triangleSize(size)];
+ DBIDArrayIter ix = ids.iter(), iy = ids.iter();
+ // Position counter - must agree with computeOffset!
+ int pos = 0;
+ for (int x = 0; ix.valid(); x++, ix.advance()) {
+ iy.seek(0);
+ for (int y = 0; y < x; y++, iy.advance()) {
+ scratch[pos] = dq.distance(ix, iy).doubleValue();
+ pos++;
+ }
+ }
+
+ // Initialize space for result:
+ double[] height = new double[size];
+ Arrays.fill(height, Double.POSITIVE_INFINITY);
+ // Parent node, to track merges
+ // have every object point to itself initially
+ ArrayModifiableDBIDs parent = DBIDUtil.newArray(ids);
+ // Active clusters, when not trivial.
+ TIntObjectMap<ModifiableDBIDs> clusters = new TIntObjectHashMap<>();
+
+ // Repeat until everything merged, except the desired number of clusters:
+ final int stop = size - numclusters;
+ FiniteProgress prog = LOG.isVerbose() ? new FiniteProgress("Agglomerative clustering", stop, LOG) : null;
+ for (int i = 0; i < stop; i++) {
+ double min = Double.POSITIVE_INFINITY;
+ int minx = -1, miny = -1;
+ for (int x = 0; x < size; x++) {
+ if (height[x] < Double.POSITIVE_INFINITY) {
+ continue;
+ }
+ final int xbase = triangleSize(x);
+ for (int y = 0; y < x; y++) {
+ if (height[y] < Double.POSITIVE_INFINITY) {
+ continue;
+ }
+ final int idx = xbase + y;
+ if (scratch[idx] < min) {
+ min = scratch[idx];
+ minx = x;
+ miny = y;
+ }
+ }
+ }
+ assert (minx >= 0 && miny >= 0);
+ // Avoid allocating memory, by reusing existing iterators:
+ ix.seek(minx);
+ iy.seek(miny);
+ // Perform merge in data structure: x -> y
+ // Since y < x, prefer keeping y, dropping x.
+ height[minx] = min;
+ parent.set(minx, iy);
+ // Merge into cluster
+ ModifiableDBIDs cx = clusters.get(minx);
+ ModifiableDBIDs cy = clusters.get(miny);
+ if (cy == null) {
+ cy = DBIDUtil.newHashSet();
+ cy.add(iy);
+ }
+ if (cx == null) {
+ cy.add(ix);
+ } else {
+ cy.addDBIDs(cx);
+ clusters.remove(minx);
+ }
+ clusters.put(miny, cy);
+ // Update distance matrix. Note: miny < minx
+ final int xbase = triangleSize(minx), ybase = triangleSize(miny);
+ // Write to (y, j), with j < y
+ for (int j = 0; j < miny; j++) {
+ if (height[j] < Double.POSITIVE_INFINITY) {
+ continue;
+ }
+ scratch[ybase + j] = Math.min(scratch[xbase + j], scratch[ybase + j]);
+ }
+ // Write to (j, y), with y < j < x
+ for (int j = miny + 1; j < minx; j++) {
+ if (height[j] < Double.POSITIVE_INFINITY) {
+ continue;
+ }
+ final int jbase = triangleSize(j);
+ scratch[jbase + miny] = Math.min(scratch[xbase + j], scratch[jbase + miny]);
+ }
+ // Write to (j, y), with y < x < j
+ for (int j = minx + 1; j < size; j++) {
+ if (height[j] < Double.POSITIVE_INFINITY) {
+ continue;
+ }
+ final int jbase = triangleSize(j);
+ scratch[jbase + miny] = Math.min(scratch[jbase + minx], scratch[jbase + miny]);
+ }
+ if (prog != null) {
+ prog.incrementProcessed(LOG);
+ }
+ }
+ if (prog != null) {
+ prog.ensureCompleted(LOG);
+ }
+
+ // Build the clustering result
+ final Clustering<Model> dendrogram = new Clustering<>("Hierarchical-Clustering", "hierarchical-clustering");
+ for (int x = 0; x < size; x++) {
+ if (height[x] < Double.POSITIVE_INFINITY) {
+ DBIDs cids = clusters.get(x);
+ if (cids == null) {
+ ix.seek(x);
+ cids = DBIDUtil.deref(ix);
+ }
+ Cluster<Model> cluster = new Cluster<>("Cluster", cids);
+ dendrogram.addToplevelCluster(cluster);
+ }
+ }
+
+ return dendrogram;
+ }
+
+ /**
+ * Compute the size of a complete x by x triangle (minus diagonal)
+ *
+ * @param x Offset
+ * @return Size of complete triangle
+ */
+ protected static int triangleSize(int x) {
+ return (x * (x - 1)) >>> 1;
+ }
+
+ @Override
+ public TypeInformation[] getInputTypeRestriction() {
+ // The input relation must match our distance function:
+ return TypeUtil.array(getDistanceFunction().getInputTypeRestriction());
+ }
+
+ @Override
+ protected Logging getLogger() {
+ return LOG;
+ }
+
+ /**
+ * Parameterization class
+ *
+ * @author Erich Schubert
+ *
+ * @param <O> Object type
+ * @param <D> Distance type
+ */
+ public static class Parameterizer<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBasedAlgorithm.Parameterizer<O, D> {
+ /**
+ * Desired number of clusters.
+ */
+ int numclusters = 0;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ IntParameter numclustersP = new IntParameter(ExtractFlatClusteringFromHierarchy.Parameterizer.MINCLUSTERS_ID);
+ numclustersP.addConstraint(new GreaterEqualConstraint(1));
+ if (config.grab(numclustersP)) {
+ numclusters = numclustersP.intValue();
+ }
+ }
+
+ @Override
+ protected NaiveAgglomerativeHierarchicalClustering2<O, D> makeInstance() {
+ return new NaiveAgglomerativeHierarchicalClustering2<>(distanceFunction, numclusters);
+ }
+ }
+}
diff --git a/src/tutorial/clustering/NaiveAgglomerativeHierarchicalClustering3.java b/src/tutorial/clustering/NaiveAgglomerativeHierarchicalClustering3.java
new file mode 100644
index 00000000..ae571358
--- /dev/null
+++ b/src/tutorial/clustering/NaiveAgglomerativeHierarchicalClustering3.java
@@ -0,0 +1,398 @@
+package tutorial.clustering;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import gnu.trove.map.TIntObjectMap;
+import gnu.trove.map.hash.TIntObjectHashMap;
+
+import java.util.Arrays;
+
+import de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm;
+import de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical.ExtractFlatClusteringFromHierarchy;
+import de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical.SLINK;
+import de.lmu.ifi.dbs.elki.data.Cluster;
+import de.lmu.ifi.dbs.elki.data.Clustering;
+import de.lmu.ifi.dbs.elki.data.model.Model;
+import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
+import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.database.Database;
+import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDArrayIter;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SquaredEuclideanDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
+import de.lmu.ifi.dbs.elki.result.Result;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterEqualConstraint;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.EnumParameter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
+
+/**
+ * This tutorial will step you through implementing a well known clustering
+ * algorithm, agglomerative hierarchical clustering, in multiple steps.
+ *
+ * This is the third step, where we add support for different linkage
+ * strategies.
+ *
+ * This is the naive O(n^3) algorithm. See {@link SLINK} for a much faster
+ * algorithm (however, only for single-linkage).
+ *
+ * Reference (for the update formulas):
+ * <p>
+ * A Review of Classification<br />
+ * R. M. Cormack<br />
+ * Journal of the Royal Statistical Society. Series A, Vol. 134, No. 3
+ * </p>
+ *
+ * @author Erich Schubert
+ *
+ * @param <O> Object type
+ */
+@Reference(title = "A Review of Classification", authors = "R. M. Cormack", booktitle = "Journal of the Royal Statistical Society. Series A, Vol. 134, No. 3", url = "http://www.jstor.org/stable/2344237")
+public class NaiveAgglomerativeHierarchicalClustering3<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBasedAlgorithm<O, D, Result> {
+ /**
+ * Class logger
+ */
+ private static final Logging LOG = Logging.getLogger(NaiveAgglomerativeHierarchicalClustering3.class);
+
+ /**
+ * Different linkage strategies.
+ *
+ * The update formulas here come from:<br />
+ * R. M. Cormack, A Review of Classification
+ *
+ * @author Erich Schubert
+ */
+ public static enum Linkage {//
+ SINGLE {
+ @Override
+ public double combine(int sizex, double dx, int sizey, double dy, int sizej, double dxy) {
+ return Math.min(dx, dy);
+ }
+ }, // single-linkage hierarchical clustering
+ COMPLETE {
+ @Override
+ public double combine(int sizex, double dx, int sizey, double dy, int sizej, double dxy) {
+ return Math.max(dx, dy);
+ }
+ }, // complete-linkage hierarchical clustering
+ GROUP_AVERAGE {
+ @Override
+ public double combine(int sizex, double dx, int sizey, double dy, int sizej, double dxy) {
+ final double wx = sizex / (double) (sizex + sizey);
+ final double wy = sizey / (double) (sizex + sizey);
+ return wx * dx + wy * dy;
+ }
+ }, // average-linkage hierarchical clustering
+ WEIGHTED_AVERAGE {
+ @Override
+ public double combine(int sizex, double dx, int sizey, double dy, int sizej, double dxy) {
+ return .5 * (dx + dy);
+ }
+ }, // a more naive variant, McQuitty (1966)
+ CENTROID {
+ @Override
+ public double combine(int sizex, double dx, int sizey, double dy, int sizej, double dxy) {
+ final double wx = sizex / (double) (sizex + sizey);
+ final double wy = sizey / (double) (sizex + sizey);
+ final double beta = (sizex * sizey) / (double) ((sizex + sizey) * (sizex + sizey));
+ return wx * dx + wy * dy - beta * dxy;
+ }
+ }, // Sokal and Michener (1958), Gower (1967)
+ MEDIAN {
+ @Override
+ public double combine(int sizex, double dx, int sizey, double dy, int sizej, double dxy) {
+ return .5 * (dx + dy) - .25 * dxy;
+ }
+ }, // Gower (1967)
+ WARD {
+ @Override
+ public double combine(int sizex, double dx, int sizey, double dy, int sizej, double dxy) {
+ final double wx = (sizex + sizej) / (double) (sizex + sizey + sizej);
+ final double wy = (sizey + sizej) / (double) (sizex + sizey + sizej);
+ final double beta = sizej / (double) (sizex + sizey + sizej);
+ return wx * dx + wy * dy - beta * dxy;
+ }
+ }, // Minimum Variance, Wishart (1969), Anderson (1971)
+ ;
+
+ abstract public double combine(int sizex, double dx, int sizey, double dy, int sizej, double dxy);
+ }
+
+ /**
+ * Threshold, how many clusters to extract.
+ */
+ int numclusters;
+
+ /**
+ * Current linkage in use.
+ */
+ Linkage linkage = Linkage.WARD;
+
+ /**
+ * Constructor.
+ *
+ * @param distanceFunction Distance function to use
+ * @param numclusters Number of clusters
+ * @param linkage Linkage strategy
+ */
+ public NaiveAgglomerativeHierarchicalClustering3(DistanceFunction<? super O, D> distanceFunction, int numclusters, Linkage linkage) {
+ super(distanceFunction);
+ this.numclusters = numclusters;
+ this.linkage = linkage;
+ }
+
+ /**
+ * Run the algorithm
+ *
+ * @param db Database
+ * @param relation Relation
+ * @return Clustering hierarchy
+ */
+ public Result run(Database db, Relation<O> relation) {
+ DistanceQuery<O, D> dq = db.getDistanceQuery(relation, getDistanceFunction());
+ ArrayDBIDs ids = DBIDUtil.ensureArray(relation.getDBIDs());
+ final int size = ids.size();
+
+ if (size > 0x10000) {
+ throw new AbortException("This implementation does not scale to data sets larger than " + 0x10000 + " instances (~17 GB RAM), which results in an integer overflow.");
+ }
+ if (Linkage.SINGLE.equals(linkage)) {
+ LOG.verbose("Notice: SLINK is a much faster algorithm for single-linkage clustering!");
+ }
+
+ // Compute the initial (lower triangular) distance matrix.
+ double[] scratch = new double[triangleSize(size)];
+ DBIDArrayIter ix = ids.iter(), iy = ids.iter();
+ // Position counter - must agree with computeOffset!
+ int pos = 0;
+ boolean square = Linkage.WARD.equals(linkage) && !(SquaredEuclideanDistanceFunction.class.isInstance(getDistanceFunction()));
+ for (int x = 0; ix.valid(); x++, ix.advance()) {
+ iy.seek(0);
+ for (int y = 0; y < x; y++, iy.advance()) {
+ scratch[pos] = dq.distance(ix, iy).doubleValue();
+ // Ward uses variances -- i.e. squared values
+ if (square) {
+ scratch[pos] *= scratch[pos];
+ }
+ pos++;
+ }
+ }
+
+ // Initialize space for result:
+ double[] height = new double[size];
+ Arrays.fill(height, Double.POSITIVE_INFINITY);
+ // Parent node, to track merges
+ // have every object point to itself initially
+ ArrayModifiableDBIDs parent = DBIDUtil.newArray(ids);
+ // Active clusters, when not trivial.
+ TIntObjectMap<ModifiableDBIDs> clusters = new TIntObjectHashMap<>();
+
+ // Repeat until everything merged, except the desired number of clusters:
+ final int stop = size - numclusters;
+ FiniteProgress prog = LOG.isVerbose() ? new FiniteProgress("Agglomerative clustering", stop, LOG) : null;
+ for (int i = 0; i < stop; i++) {
+ double min = Double.POSITIVE_INFINITY;
+ int minx = -1, miny = -1;
+ for (int x = 0; x < size; x++) {
+ if (height[x] < Double.POSITIVE_INFINITY) {
+ continue;
+ }
+ final int xbase = triangleSize(x);
+ for (int y = 0; y < x; y++) {
+ if (height[y] < Double.POSITIVE_INFINITY) {
+ continue;
+ }
+ final int idx = xbase + y;
+ if (scratch[idx] < min) {
+ min = scratch[idx];
+ minx = x;
+ miny = y;
+ }
+ }
+ }
+ assert (minx >= 0 && miny >= 0);
+ // Avoid allocating memory, by reusing existing iterators:
+ ix.seek(minx);
+ iy.seek(miny);
+ // Perform merge in data structure: x -> y
+ // Since y < x, prefer keeping y, dropping x.
+ height[minx] = min;
+ parent.set(minx, iy);
+ // Merge into cluster
+ ModifiableDBIDs cx = clusters.get(minx);
+ ModifiableDBIDs cy = clusters.get(miny);
+ int sizex = 1, sizey = 1; // cluster sizes, for averaging
+ if (cy == null) {
+ cy = DBIDUtil.newHashSet();
+ cy.add(iy);
+ } else {
+ sizey = cy.size();
+ }
+ if (cx == null) {
+ cy.add(ix);
+ } else {
+ sizex = cx.size();
+ cy.addDBIDs(cx);
+ clusters.remove(minx);
+ }
+ clusters.put(miny, cy);
+
+ // Update distance matrix. Note: miny < minx
+
+ // Implementation note: most will not need sizej, and could save the
+ // hashmap lookup.
+ final int xbase = triangleSize(minx), ybase = triangleSize(miny);
+ // Write to (y, j), with j < y
+ for (int j = 0; j < miny; j++) {
+ if (height[j] < Double.POSITIVE_INFINITY) {
+ continue;
+ }
+ final DBIDs idsj = clusters.get(j);
+ final int sizej = (idsj == null) ? 1 : idsj.size();
+ scratch[ybase + j] = linkage.combine(sizex, scratch[xbase + j], sizey, scratch[ybase + j], sizej, min);
+ }
+ // Write to (j, y), with y < j < x
+ for (int j = miny + 1; j < minx; j++) {
+ if (height[j] < Double.POSITIVE_INFINITY) {
+ continue;
+ }
+ final int jbase = triangleSize(j);
+ final DBIDs idsj = clusters.get(j);
+ final int sizej = (idsj == null) ? 1 : idsj.size();
+ scratch[jbase + miny] = linkage.combine(sizex, scratch[xbase + j], sizey, scratch[jbase + miny], sizej, min);
+ }
+ // Write to (j, y), with y < x < j
+ for (int j = minx + 1; j < size; j++) {
+ if (height[j] < Double.POSITIVE_INFINITY) {
+ continue;
+ }
+ final DBIDs idsj = clusters.get(j);
+ final int sizej = (idsj == null) ? 1 : idsj.size();
+ final int jbase = triangleSize(j);
+ scratch[jbase + miny] = linkage.combine(sizex, scratch[jbase + minx], sizey, scratch[jbase + miny], sizej, min);
+ }
+ if (prog != null) {
+ prog.incrementProcessed(LOG);
+ }
+ }
+ if (prog != null) {
+ prog.ensureCompleted(LOG);
+ }
+
+ // Build the clustering result
+ final Clustering<Model> dendrogram = new Clustering<>("Hierarchical-Clustering", "hierarchical-clustering");
+ for (int x = 0; x < size; x++) {
+ if (height[x] < Double.POSITIVE_INFINITY) {
+ DBIDs cids = clusters.get(x);
+ if (cids == null) {
+ ix.seek(x);
+ cids = DBIDUtil.deref(ix);
+ }
+ Cluster<Model> cluster = new Cluster<>("Cluster", cids);
+ dendrogram.addToplevelCluster(cluster);
+ }
+ }
+
+ return dendrogram;
+ }
+
+ /**
+ * Compute the size of a complete x by x triangle (minus diagonal)
+ *
+ * @param x Offset
+ * @return Size of complete triangle
+ */
+ protected static int triangleSize(int x) {
+ return (x * (x - 1)) >>> 1;
+ }
+
+ @Override
+ public TypeInformation[] getInputTypeRestriction() {
+ // The input relation must match our distance function:
+ return TypeUtil.array(getDistanceFunction().getInputTypeRestriction());
+ }
+
+ @Override
+ protected Logging getLogger() {
+ return LOG;
+ }
+
+ /**
+ * Parameterization class
+ *
+ * @author Erich Schubert
+ *
+ * @param <O> Object type
+ * @param <D> Distance type
+ */
+ public static class Parameterizer<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBasedAlgorithm.Parameterizer<O, D> {
+ /**
+ * Option ID for linkage parameter.
+ */
+ private static final OptionID LINKAGE_ID = new OptionID("hierarchical.linkage", "Parameter to choose the linkage strategy.");
+
+ /**
+ * Desired number of clusters.
+ */
+ int numclusters = 0;
+
+ /**
+ * Current linkage in use.
+ */
+ protected Linkage linkage = Linkage.SINGLE;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ IntParameter numclustersP = new IntParameter(ExtractFlatClusteringFromHierarchy.Parameterizer.MINCLUSTERS_ID);
+ numclustersP.addConstraint(new GreaterEqualConstraint(1));
+ if (config.grab(numclustersP)) {
+ numclusters = numclustersP.intValue();
+ }
+
+ EnumParameter<Linkage> linkageP = new EnumParameter<>(LINKAGE_ID, Linkage.class);
+ linkageP.setDefaultValue(Linkage.WARD);
+ if (config.grab(linkageP)) {
+ linkage = linkageP.getValue();
+ }
+ }
+
+ @Override
+ protected NaiveAgglomerativeHierarchicalClustering3<O, D> makeInstance() {
+ return new NaiveAgglomerativeHierarchicalClustering3<>(distanceFunction, numclusters, linkage);
+ }
+ }
+}
diff --git a/src/tutorial/clustering/NaiveAgglomerativeHierarchicalClustering4.java b/src/tutorial/clustering/NaiveAgglomerativeHierarchicalClustering4.java
new file mode 100644
index 00000000..23678ccc
--- /dev/null
+++ b/src/tutorial/clustering/NaiveAgglomerativeHierarchicalClustering4.java
@@ -0,0 +1,343 @@
+package tutorial.clustering;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm;
+import de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical.HierarchicalClusteringAlgorithm;
+import de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical.PointerHierarchyRepresentationResult;
+import de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical.SLINK;
+import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
+import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.database.Database;
+import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory;
+import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
+import de.lmu.ifi.dbs.elki.database.datastore.WritableDBIDDataStore;
+import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDistanceDataStore;
+import de.lmu.ifi.dbs.elki.database.datastore.WritableIntegerDataStore;
+import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDArrayIter;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SquaredEuclideanDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.EnumParameter;
+
+/**
+ * This tutorial will step you through implementing a well known clustering
+ * algorithm, agglomerative hierarchical clustering, in multiple steps.
+ *
+ * This is the third step, where we add support for different linkage
+ * strategies.
+ *
+ * This is the naive O(n^3) algorithm. See {@link SLINK} for a much faster
+ * algorithm (however, only for single-linkage).
+ *
+ * Reference (for the update formulas):
+ * <p>
+ * A Review of Classification<br />
+ * R. M. Cormack<br />
+ * Journal of the Royal Statistical Society. Series A, Vol. 134, No. 3
+ * </p>
+ *
+ * @author Erich Schubert
+ *
+ * @param <O> Object type
+ */
+@Reference(title = "A Review of Classification", authors = "R. M. Cormack", booktitle = "Journal of the Royal Statistical Society. Series A, Vol. 134, No. 3", url = "http://www.jstor.org/stable/2344237")
+public class NaiveAgglomerativeHierarchicalClustering4<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBasedAlgorithm<O, D, PointerHierarchyRepresentationResult<DoubleDistance>> implements HierarchicalClusteringAlgorithm<DoubleDistance> {
+ /**
+ * Class logger
+ */
+ private static final Logging LOG = Logging.getLogger(NaiveAgglomerativeHierarchicalClustering4.class);
+
+ /**
+ * Different linkage strategies.
+ *
+ * The update formulas here come from:<br />
+ * R. M. Cormack, A Review of Classification
+ *
+ * @author Erich Schubert
+ */
+ public static enum Linkage {//
+ SINGLE {
+ @Override
+ public double combine(int sizex, double dx, int sizey, double dy, int sizej, double dxy) {
+ return Math.min(dx, dy);
+ }
+ }, // single-linkage hierarchical clustering
+ COMPLETE {
+ @Override
+ public double combine(int sizex, double dx, int sizey, double dy, int sizej, double dxy) {
+ return Math.max(dx, dy);
+ }
+ }, // complete-linkage hierarchical clustering
+ GROUP_AVERAGE {
+ @Override
+ public double combine(int sizex, double dx, int sizey, double dy, int sizej, double dxy) {
+ final double wx = sizex / (double) (sizex + sizey);
+ final double wy = sizey / (double) (sizex + sizey);
+ return wx * dx + wy * dy;
+ }
+ }, // average-linkage hierarchical clustering
+ WEIGHTED_AVERAGE {
+ @Override
+ public double combine(int sizex, double dx, int sizey, double dy, int sizej, double dxy) {
+ return .5 * (dx + dy);
+ }
+ }, // a more naive variant, McQuitty (1966)
+ CENTROID {
+ @Override
+ public double combine(int sizex, double dx, int sizey, double dy, int sizej, double dxy) {
+ final double wx = sizex / (double) (sizex + sizey);
+ final double wy = sizey / (double) (sizex + sizey);
+ final double beta = (sizex * sizey) / (double) ((sizex + sizey) * (sizex + sizey));
+ return wx * dx + wy * dy - beta * dxy;
+ }
+ }, // Sokal and Michener (1958), Gower (1967)
+ MEDIAN {
+ @Override
+ public double combine(int sizex, double dx, int sizey, double dy, int sizej, double dxy) {
+ return .5 * (dx + dy) - .25 * dxy;
+ }
+ }, // Gower (1967)
+ WARD {
+ @Override
+ public double combine(int sizex, double dx, int sizey, double dy, int sizej, double dxy) {
+ final double wx = (sizex + sizej) / (double) (sizex + sizey + sizej);
+ final double wy = (sizey + sizej) / (double) (sizex + sizey + sizej);
+ final double beta = sizej / (double) (sizex + sizey + sizej);
+ return wx * dx + wy * dy - beta * dxy;
+ }
+ }, // Minimum Variance, Wishart (1969), Anderson (1971)
+ ;
+
+ abstract public double combine(int sizex, double dx, int sizey, double dy, int sizej, double dxy);
+ }
+
+ /**
+ * Current linkage in use.
+ */
+ Linkage linkage = Linkage.WARD;
+
+ /**
+ * Constructor.
+ *
+ * @param distanceFunction Distance function to use
+ * @param linkage Linkage strategy
+ */
+ public NaiveAgglomerativeHierarchicalClustering4(DistanceFunction<? super O, D> distanceFunction, Linkage linkage) {
+ super(distanceFunction);
+ this.linkage = linkage;
+ }
+
+ /**
+ * Run the algorithm
+ *
+ * @param db Database
+ * @param relation Relation
+ * @return Clustering hierarchy
+ */
+ public PointerHierarchyRepresentationResult<DoubleDistance> run(Database db, Relation<O> relation) {
+ DistanceQuery<O, D> dq = db.getDistanceQuery(relation, getDistanceFunction());
+ ArrayDBIDs ids = DBIDUtil.ensureArray(relation.getDBIDs());
+ final int size = ids.size();
+
+ if (size > 0x10000) {
+ throw new AbortException("This implementation does not scale to data sets larger than " + 0x10000 + " instances (~17 GB RAM), which results in an integer overflow.");
+ }
+ if (Linkage.SINGLE.equals(linkage)) {
+ LOG.verbose("Notice: SLINK is a much faster algorithm for single-linkage clustering!");
+ }
+
+ // Compute the initial (lower triangular) distance matrix.
+ double[] scratch = new double[triangleSize(size)];
+ DBIDArrayIter ix = ids.iter(), iy = ids.iter(), ij = ids.iter();
+ // Position counter - must agree with computeOffset!
+ int pos = 0;
+ boolean square = Linkage.WARD.equals(linkage) && !(SquaredEuclideanDistanceFunction.class.isInstance(getDistanceFunction()));
+ for (int x = 0; ix.valid(); x++, ix.advance()) {
+ iy.seek(0);
+ for (int y = 0; y < x; y++, iy.advance()) {
+ scratch[pos] = dq.distance(ix, iy).doubleValue();
+ // Ward uses variances -- i.e. squared values
+ if (square) {
+ scratch[pos] *= scratch[pos];
+ }
+ pos++;
+ }
+ }
+
+ // Initialize space for result:
+ WritableDBIDDataStore parent = DataStoreUtil.makeDBIDStorage(ids, DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_STATIC);
+ WritableDoubleDistanceDataStore height = DataStoreUtil.makeDoubleDistanceStorage(ids, DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_STATIC);
+ WritableIntegerDataStore csize = DataStoreUtil.makeIntegerStorage(ids, DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP);
+ for (DBIDIter it = ids.iter(); it.valid(); it.advance()) {
+ parent.put(it, it);
+ height.put(it, Double.POSITIVE_INFINITY);
+ csize.put(it, 1);
+ }
+
+ // Repeat until everything merged, except the desired number of clusters:
+ FiniteProgress prog = LOG.isVerbose() ? new FiniteProgress("Agglomerative clustering", size - 1, LOG) : null;
+ for (int i = 1; i < size; i++) {
+ double min = Double.POSITIVE_INFINITY;
+ int minx = -1, miny = -1;
+ for (ix.seek(0); ix.valid(); ix.advance()) {
+ if (height.doubleValue(ix) < Double.POSITIVE_INFINITY) {
+ continue;
+ }
+ final int xbase = triangleSize(ix.getOffset());
+ for (iy.seek(0); iy.getOffset() < ix.getOffset(); iy.advance()) {
+ if (height.doubleValue(iy) < Double.POSITIVE_INFINITY) {
+ continue;
+ }
+ final int idx = xbase + iy.getOffset();
+ if (scratch[idx] <= min) {
+ min = scratch[idx];
+ minx = ix.getOffset();
+ miny = iy.getOffset();
+ }
+ }
+ }
+ assert (minx >= 0 && miny >= 0);
+ // Avoid allocating memory, by reusing existing iterators:
+ ix.seek(minx);
+ iy.seek(miny);
+ // Perform merge in data structure: x -> y
+ // Since y < x, prefer keeping y, dropping x.
+ int sizex = csize.intValue(ix), sizey = csize.intValue(iy);
+ height.put(ix, min);
+ parent.put(ix, iy);
+ csize.put(iy, sizex + sizey);
+
+ // Update distance matrix. Note: miny < minx
+ final int xbase = triangleSize(minx), ybase = triangleSize(miny);
+ // Write to (y, j), with j < y
+ for (ij.seek(0); ij.getOffset() < miny; ij.advance()) {
+ if (height.doubleValue(ij) < Double.POSITIVE_INFINITY) {
+ continue;
+ }
+ final int sizej = csize.intValue(ij);
+ scratch[ybase + ij.getOffset()] = linkage.combine(sizex, scratch[xbase + ij.getOffset()], sizey, scratch[ybase + ij.getOffset()], sizej, min);
+ }
+ // Write to (j, y), with y < j < x
+ for (ij.seek(miny + 1); ij.getOffset() < minx; ij.advance()) {
+ if (height.doubleValue(ij) < Double.POSITIVE_INFINITY) {
+ continue;
+ }
+ final int jbase = triangleSize(ij.getOffset());
+ final int sizej = csize.intValue(ij);
+ scratch[jbase + miny] = linkage.combine(sizex, scratch[xbase + ij.getOffset()], sizey, scratch[jbase + miny], sizej, min);
+ }
+ // Write to (j, y), with y < x < j
+ for (ij.seek(minx + 1); ij.valid(); ij.advance()) {
+ if (height.doubleValue(ij) < Double.POSITIVE_INFINITY) {
+ continue;
+ }
+ final int jbase = triangleSize(ij.getOffset());
+ final int sizej = csize.intValue(ij);
+ scratch[jbase + miny] = linkage.combine(sizex, scratch[jbase + minx], sizey, scratch[jbase + miny], sizej, min);
+ }
+ if (prog != null) {
+ prog.incrementProcessed(LOG);
+ }
+ }
+ if (prog != null) {
+ prog.ensureCompleted(LOG);
+ }
+
+ return new PointerHierarchyRepresentationResult<>(ids, parent, height);
+ }
+
+ /**
+ * Compute the size of a complete x by x triangle (minus diagonal)
+ *
+ * @param x Offset
+ * @return Size of complete triangle
+ */
+ protected static int triangleSize(int x) {
+ return (x * (x - 1)) >>> 1;
+ }
+
+ @Override
+ public TypeInformation[] getInputTypeRestriction() {
+ // The input relation must match our distance function:
+ return TypeUtil.array(getDistanceFunction().getInputTypeRestriction());
+ }
+
+ @Override
+ protected Logging getLogger() {
+ return LOG;
+ }
+
+ @Override
+ public DoubleDistance getDistanceFactory() {
+ return DoubleDistance.FACTORY;
+ }
+
+ /**
+ * Parameterization class
+ *
+ * @author Erich Schubert
+ *
+ * @param <O> Object type
+ * @param <D> Distance type
+ */
+ public static class Parameterizer<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBasedAlgorithm.Parameterizer<O, D> {
+ /**
+ * Option ID for linkage parameter.
+ */
+ private static final OptionID LINKAGE_ID = new OptionID("hierarchical.linkage", "Parameter to choose the linkage strategy.");
+
+ /**
+ * Current linkage in use.
+ */
+ protected Linkage linkage = Linkage.SINGLE;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ EnumParameter<Linkage> linkageP = new EnumParameter<>(LINKAGE_ID, Linkage.class);
+ linkageP.setDefaultValue(Linkage.WARD);
+ if (config.grab(linkageP)) {
+ linkage = linkageP.getValue();
+ }
+ }
+
+ @Override
+ protected NaiveAgglomerativeHierarchicalClustering4<O, D> makeInstance() {
+ return new NaiveAgglomerativeHierarchicalClustering4<>(distanceFunction, linkage);
+ }
+ }
+}
diff --git a/src/tutorial/clustering/SameSizeKMeansAlgorithm.java b/src/tutorial/clustering/SameSizeKMeansAlgorithm.java
index c85af2e9..574a02e9 100644
--- a/src/tutorial/clustering/SameSizeKMeansAlgorithm.java
+++ b/src/tutorial/clustering/SameSizeKMeansAlgorithm.java
@@ -4,7 +4,7 @@ package tutorial.clustering;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -49,9 +49,9 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.database.relation.RelationUtil;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.SquaredEuclideanDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SquaredEuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.utilities.datastructures.arrays.IntegerArrayQuickSort;
@@ -104,13 +104,14 @@ public class SameSizeKMeansAlgorithm<V extends NumberVector<?>> extends Abstract
* @param relation relation to use
* @return result
*/
+ @Override
public Clustering<MeanModel<V>> run(Database database, Relation<V> relation) {
// Database objects to process
final DBIDs ids = relation.getDBIDs();
// Choose initial means
- List<? extends NumberVector<?>> means = initializer.chooseInitialMeans(relation, k, getDistanceFunction());
+ List<? extends NumberVector<?>> means = initializer.chooseInitialMeans(database, relation, k, getDistanceFunction());
// Setup cluster assignment store
- List<ModifiableDBIDs> clusters = new ArrayList<ModifiableDBIDs>();
+ List<ModifiableDBIDs> clusters = new ArrayList<>();
for (int i = 0; i < k; i++) {
clusters.add(DBIDUtil.newHashSet(relation.size() / k + 2));
}
@@ -125,12 +126,11 @@ public class SameSizeKMeansAlgorithm<V extends NumberVector<?>> extends Abstract
means = refineResult(relation, means, clusters, metas, tids);
// Wrap result
- Clustering<MeanModel<V>> result = new Clustering<MeanModel<V>>("k-Means Samesize Clustering", "kmeans-samesize-clustering");
+ Clustering<MeanModel<V>> result = new Clustering<>("k-Means Samesize Clustering", "kmeans-samesize-clustering");
final NumberVector.Factory<V, ?> factory = RelationUtil.getNumberVectorFactory(relation);
for (int i = 0; i < clusters.size(); i++) {
V mean = factory.newNumberVector(means.get(i).getColumnVector().getArrayRef());
- MeanModel<V> model = new MeanModel<V>(mean);
- result.addCluster(new Cluster<MeanModel<V>>(clusters.get(i), model));
+ result.addToplevelCluster(new Cluster<>(clusters.get(i), new MeanModel<>(mean)));
}
return result;
}
@@ -499,7 +499,7 @@ public class SameSizeKMeansAlgorithm<V extends NumberVector<?>> extends Abstract
k = kP.getValue();
}
- ObjectParameter<KMeansInitialization<V>> initialP = new ObjectParameter<KMeansInitialization<V>>(INIT_ID, KMeansInitialization.class, KMeansPlusPlusInitialMeans.class);
+ ObjectParameter<KMeansInitialization<V>> initialP = new ObjectParameter<>(INIT_ID, KMeansInitialization.class, KMeansPlusPlusInitialMeans.class);
if (config.grab(initialP)) {
initializer = initialP.instantiateClass(config);
}
@@ -513,7 +513,7 @@ public class SameSizeKMeansAlgorithm<V extends NumberVector<?>> extends Abstract
@Override
protected SameSizeKMeansAlgorithm<V> makeInstance() {
- return new SameSizeKMeansAlgorithm<V>(distanceFunction, k, maxiter, initializer);
+ return new SameSizeKMeansAlgorithm<>(distanceFunction, k, maxiter, initializer);
}
}
}
diff --git a/src/tutorial/clustering/package-info.java b/src/tutorial/clustering/package-info.java
index 2dd893ab..ac7ab950 100644
--- a/src/tutorial/clustering/package-info.java
+++ b/src/tutorial/clustering/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/tutorial/distancefunction/MultiLPNorm.java b/src/tutorial/distancefunction/MultiLPNorm.java
index 4dca1a93..b3a96ecb 100644
--- a/src/tutorial/distancefunction/MultiLPNorm.java
+++ b/src/tutorial/distancefunction/MultiLPNorm.java
@@ -14,7 +14,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleListParamet
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -88,7 +88,7 @@ public class MultiLPNorm extends AbstractVectorDoubleDistanceFunction {
@Override
public SimpleTypeInformation<? super NumberVector<?>> getInputTypeRestriction() {
- return new VectorFieldTypeInformation<NumberVector<?>>(NumberVector.class, ps.length);
+ return new VectorFieldTypeInformation<>(NumberVector.class, ps.length);
}
/**
diff --git a/src/tutorial/distancefunction/TutorialDistanceFunction.java b/src/tutorial/distancefunction/TutorialDistanceFunction.java
index e41f8093..5e2fbcb6 100644
--- a/src/tutorial/distancefunction/TutorialDistanceFunction.java
+++ b/src/tutorial/distancefunction/TutorialDistanceFunction.java
@@ -1,15 +1,10 @@
package tutorial.distancefunction;
-import de.lmu.ifi.dbs.elki.data.NumberVector;
-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.AbstractVectorDoubleDistanceFunction;
-
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,10 +23,17 @@ import de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractVectorDoubleDistanc
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+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.AbstractVectorDoubleDistanceFunction;
+
/**
* Tutorial example for ELKI.
*
- * See <a href="http://elki.dbs.ifi.lmu.de/wiki/Tutorial/DistanceFunctions">Distance function tutorial</a>
+ * See <a
+ * href="http://elki.dbs.ifi.lmu.de/wiki/Tutorial/DistanceFunctions">Distance
+ * function tutorial</a>
*
* @author Erich Schubert
*/
@@ -45,6 +47,6 @@ public class TutorialDistanceFunction extends AbstractVectorDoubleDistanceFuncti
@Override
public SimpleTypeInformation<? super NumberVector<?>> getInputTypeRestriction() {
- return new VectorFieldTypeInformation<NumberVector<?>>(NumberVector.class, 2);
+ return new VectorFieldTypeInformation<>(NumberVector.class, 2);
}
-} \ No newline at end of file
+}
diff --git a/src/tutorial/distancefunction/package-info.java b/src/tutorial/distancefunction/package-info.java
index eec5b38c..ba64b6bd 100644
--- a/src/tutorial/distancefunction/package-info.java
+++ b/src/tutorial/distancefunction/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/tutorial/outlier/DistanceStddevOutlier.java b/src/tutorial/outlier/DistanceStddevOutlier.java
index 97b9898c..e0a5e244 100644
--- a/src/tutorial/outlier/DistanceStddevOutlier.java
+++ b/src/tutorial/outlier/DistanceStddevOutlier.java
@@ -11,12 +11,12 @@ import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultIter;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
@@ -77,10 +77,10 @@ public class DistanceStddevOutlier<O, D extends NumberDistance<D, ?>> extends Ab
// Iterate over all objects
for(DBIDIter iter = relation.iterDBIDs(); iter.valid(); iter.advance()) {
- KNNResult<D> neighbors = knnq.getKNNForDBID(iter, k);
+ KNNList<D> neighbors = knnq.getKNNForDBID(iter, k);
// Aggregate distances
MeanVariance mv = new MeanVariance();
- for(DistanceDBIDResultIter<D> neighbor = neighbors.iter(); neighbor.valid(); neighbor.advance()) {
+ for(DistanceDBIDListIter<D> neighbor = neighbors.iter(); neighbor.valid(); neighbor.advance()) {
// Skip the object itself. The 0 is not very informative.
if(DBIDUtil.equal(iter, neighbor)) {
continue;
@@ -94,7 +94,7 @@ public class DistanceStddevOutlier<O, D extends NumberDistance<D, ?>> extends Ab
// Wrap the result in the standard containers
// Actual min-max, theoretical min-max!
OutlierScoreMeta meta = new BasicOutlierScoreMeta(minmax.getMin(), minmax.getMax(), 0, Double.POSITIVE_INFINITY);
- Relation<Double> rel = new MaterializedRelation<Double>(database, TypeUtil.DOUBLE, relation.getDBIDs(), "stddev-outlier", scores);
+ Relation<Double> rel = new MaterializedRelation<>(database, TypeUtil.DOUBLE, relation.getDBIDs(), "stddev-outlier", scores);
return new OutlierResult(meta, rel);
}
@@ -142,7 +142,7 @@ public class DistanceStddevOutlier<O, D extends NumberDistance<D, ?>> extends Ab
@Override
protected DistanceStddevOutlier<O, D> makeInstance() {
- return new DistanceStddevOutlier<O, D>(distanceFunction, k);
+ return new DistanceStddevOutlier<>(distanceFunction, k);
}
}
} \ No newline at end of file
diff --git a/src/tutorial/outlier/ODIN.java b/src/tutorial/outlier/ODIN.java
new file mode 100644
index 00000000..a8996305
--- /dev/null
+++ b/src/tutorial/outlier/ODIN.java
@@ -0,0 +1,196 @@
+package tutorial.outlier;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm;
+import de.lmu.ifi.dbs.elki.algorithm.outlier.OutlierAlgorithm;
+import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
+import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.database.Database;
+import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory;
+import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
+import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
+import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
+import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
+import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.result.outlier.InvertedOutlierScoreMeta;
+import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
+import de.lmu.ifi.dbs.elki.result.outlier.OutlierScoreMeta;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
+
+/**
+ * Outlier detection based on the in-degree of the kNN graph.
+ *
+ * This is a curried version: instead of using a threshold T to obtain a binary
+ * decision, we use the computed value as outlier score.
+ *
+ * Reference:
+ * <p>
+ * V. Hautamäki and I. Kärkkäinen and P Fränti<br />
+ * Outlier detection using k-nearest neighbour graph<br />
+ * Proc. 17th Int. Conf. Pattern Recognition, ICPR 2004 <br />
+ * </p>
+ *
+ * @author Erich Schubert
+ *
+ * @param <O> Object type
+ * @param <D> Distance type
+ */
+@Reference(authors = "V. Hautamäki and I. Kärkkäinen and P Fränti", title = "Outlier detection using k-nearest neighbour graph", booktitle = "Proc. 17th Int. Conf. Pattern Recognition, ICPR 2004", url = "http://dx.doi.org/10.1109/ICPR.2004.1334558")
+public class ODIN<O, D extends Distance<D>> extends AbstractDistanceBasedAlgorithm<O, D, OutlierResult> implements OutlierAlgorithm {
+ /**
+ * Class logger.
+ */
+ private static final Logging LOG = Logging.getLogger(ODIN.class);
+
+ /**
+ * Number of neighbors for kNN graph.
+ */
+ int k;
+
+ /**
+ * Constructor.
+ *
+ * @param distanceFunction Distance function
+ * @param k k parameter
+ */
+ public ODIN(DistanceFunction<? super O, D> distanceFunction, int k) {
+ super(distanceFunction);
+ this.k = k;
+ }
+
+ /**
+ * Run the ODIN algorithm
+ *
+ * Tutorial note: the <em>signature</em> of this method depends on the types
+ * that we requested in the {@link #getInputTypeRestriction} method. Here we
+ * requested a single relation of type {@code O} , the data type of our
+ * distance function.
+ *
+ * @param database Database to run on.
+ * @param relation Relation to process.
+ * @return ODIN outlier result.
+ */
+ public OutlierResult run(Database database, Relation<O> relation) {
+ // Get the query functions:
+ DistanceQuery<O, D> dq = database.getDistanceQuery(relation, getDistanceFunction());
+ KNNQuery<O, D> knnq = database.getKNNQuery(dq, k);
+
+ // Get the objects to process, and a data storage for counting and output:
+ DBIDs ids = relation.getDBIDs();
+ WritableDoubleDataStore scores = DataStoreUtil.makeDoubleStorage(ids, DataStoreFactory.HINT_DB, 0.);
+
+ // Process all objects
+ for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
+ // Find the nearest neighbors (using an index, if available!)
+ KNNList<D> neighbors = knnq.getKNNForDBID(iter, k);
+ // For each neighbor, except ourselves, increase the in-degree:
+ for (DBIDIter nei = neighbors.iter(); nei.valid(); nei.advance()) {
+ if (DBIDUtil.equal(iter, nei)) {
+ continue;
+ }
+ scores.put(nei, scores.doubleValue(nei) + 1);
+ }
+ }
+
+ // Compute maximum
+ double min = Double.POSITIVE_INFINITY, max = 0.0;
+ for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
+ min = Math.min(min, scores.doubleValue(iter));
+ max = Math.max(max, scores.doubleValue(iter));
+ }
+ // Wrap the result and add metadata.
+ // By actually specifying theoretical min, max and baseline, we get a better
+ // visualization (try it out - or see the screenshots in the tutorial)!
+ OutlierScoreMeta meta = new InvertedOutlierScoreMeta(min, max, 0., ids.size() - 1, k);
+ Relation<Double> rel = new MaterializedRelation<>("ODIN In-Degree", "odin", TypeUtil.DOUBLE, scores, ids);
+ return new OutlierResult(meta, rel);
+ }
+
+ @Override
+ public TypeInformation[] getInputTypeRestriction() {
+ return TypeUtil.array(getDistanceFunction().getInputTypeRestriction());
+ }
+
+ @Override
+ protected Logging getLogger() {
+ return LOG;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ *
+ * @param <O> Object type
+ * @param <D> Distance type
+ */
+ public static class Parameterizer<O, D extends Distance<D>> extends AbstractDistanceBasedAlgorithm.Parameterizer<O, D> {
+ /**
+ * Parameter for the number of nearest neighbors:
+ *
+ * <pre>
+ * -odin.k &lt;int&gt;
+ * </pre>
+ */
+ public static final OptionID K_ID = new OptionID("odin.k", "Number of neighbors to use for kNN graph.");
+
+ /**
+ * Number of nearest neighbors to use.
+ */
+ int k;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+
+ IntParameter param = new IntParameter(K_ID);
+ // Since in a database context, the 1 nearest neighbor
+ // will usually be the query object itself, we require
+ // this value to be at least 2.
+ param.addConstraint(new GreaterConstraint(1));
+ if (config.grab(param)) {
+ k = param.intValue();
+ }
+ }
+
+ @Override
+ protected ODIN<O, D> makeInstance() {
+ return new ODIN<>(distanceFunction, k);
+ }
+ }
+}
diff --git a/src/tutorial/outlier/SimpleScoreDumper.java b/src/tutorial/outlier/SimpleScoreDumper.java
new file mode 100644
index 00000000..49c1de0b
--- /dev/null
+++ b/src/tutorial/outlier/SimpleScoreDumper.java
@@ -0,0 +1,53 @@
+package tutorial.outlier;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import java.util.ArrayList;
+
+import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
+import de.lmu.ifi.dbs.elki.result.Result;
+import de.lmu.ifi.dbs.elki.result.ResultHandler;
+import de.lmu.ifi.dbs.elki.result.ResultUtil;
+import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
+
+/**
+ * Simple example output handler for processing outlier scores.
+ *
+ * @author Erich Schubert
+ */
+public class SimpleScoreDumper implements ResultHandler {
+ @Override
+ public void processNewResult(HierarchicalResult baseResult, Result newResult) {
+ // Get all new outlier results
+ ArrayList<OutlierResult> ors = ResultUtil.filterResults(newResult, OutlierResult.class);
+ for (OutlierResult o : ors) {
+ Relation<Double> scores = o.getScores();
+ for (DBIDIter iter = scores.iterDBIDs(); iter.valid(); iter.advance()) {
+ System.out.println(DBIDUtil.toString(iter) + " " + scores.get(iter));
+ }
+ }
+ }
+}
diff --git a/src/tutorial/package-info.java b/src/tutorial/package-info.java
index ede5b3a2..e37e53f2 100644
--- a/src/tutorial/package-info.java
+++ b/src/tutorial/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2012
+ Copyright (C) 2013
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/test/de/lmu/ifi/dbs/elki/algorithm/AbstractSimpleAlgorithmTest.java b/test/de/lmu/ifi/dbs/elki/algorithm/AbstractSimpleAlgorithmTest.java
index b33a8432..8b0507f0 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/AbstractSimpleAlgorithmTest.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/AbstractSimpleAlgorithmTest.java
@@ -78,10 +78,10 @@ public abstract class AbstractSimpleAlgorithmTest {
* @param config Parameterization to test
*/
protected void testParameterizationOk(ListParameterization config) {
- if(config.hasUnusedParameters()) {
+ if (config.hasUnusedParameters()) {
fail("Unused parameters: " + config.getRemainingParameters());
}
- if(config.hasErrors()) {
+ if (config.hasErrors()) {
config.logAndClearReportedErrors();
fail("Parameterization errors.");
}
@@ -99,10 +99,10 @@ public abstract class AbstractSimpleAlgorithmTest {
org.junit.Assert.assertTrue("Test data set not found: " + filename, (new File(filename)).exists());
params.addParameter(FileBasedDatabaseConnection.INPUT_ID, filename);
- List<Class<?>> filterlist = new ArrayList<Class<?>>();
+ List<Class<?>> filterlist = new ArrayList<>();
filterlist.add(FixedDBIDsFilter.class);
- if(filters != null) {
- for(Class<?> filter : filters) {
+ if (filters != null) {
+ for (Class<?> filter : filters) {
filterlist.add(filter);
}
}
@@ -157,7 +157,7 @@ public abstract class AbstractSimpleAlgorithmTest {
ClusterContingencyTable ct = new ClusterContingencyTable(true, false);
ct.process(clustering, rbl);
double score = ct.getPaircount().f1Measure();
- if(logger.isVerbose()) {
+ if (logger.isVerbose()) {
logger.verbose(this.getClass().getSimpleName() + " score: " + score + " expect: " + expected);
}
org.junit.Assert.assertEquals(this.getClass().getSimpleName() + ": Score does not match.", expected, score, 0.0001);
@@ -170,8 +170,8 @@ public abstract class AbstractSimpleAlgorithmTest {
* @param expected Expected cluster sizes
*/
protected void testClusterSizes(Clustering<?> clustering, int[] expected) {
- List<Integer> sizes = new java.util.ArrayList<Integer>();
- for(Cluster<?> cl : clustering.getAllClusters()) {
+ List<Integer> sizes = new java.util.ArrayList<>();
+ for (Cluster<?> cl : clustering.getAllClusters()) {
sizes.add(cl.size());
}
// Sort both
@@ -181,8 +181,8 @@ public abstract class AbstractSimpleAlgorithmTest {
// if(logger.isVerbose()) {
StringBuilder buf = new StringBuilder();
buf.append("Cluster sizes: [");
- for(int i = 0; i < sizes.size(); i++) {
- if(i > 0) {
+ for (int i = 0; i < sizes.size(); i++) {
+ if (i > 0) {
buf.append(", ");
}
buf.append(sizes.get(i));
@@ -190,9 +190,9 @@ public abstract class AbstractSimpleAlgorithmTest {
buf.append("]");
// }
// Test
- org.junit.Assert.assertEquals("Number of clusters does not match expectations." + buf.toString(), expected.length, sizes.size());
- for(int i = 0; i < expected.length; i++) {
- org.junit.Assert.assertEquals("Cluster size does not match at position " + i, expected[i], (int) sizes.get(i));
+ org.junit.Assert.assertEquals("Number of clusters does not match expectations. " + buf.toString(), expected.length, sizes.size());
+ for (int i = 0; i < expected.length; i++) {
+ org.junit.Assert.assertEquals("Cluster size does not match at position " + i + " in " + buf.toString(), expected[i], (int) sizes.get(i));
}
}
@@ -210,7 +210,7 @@ public abstract class AbstractSimpleAlgorithmTest {
OutlierROCCurve rocCurve = ClassGenericsUtil.parameterizeOrAbort(OutlierROCCurve.class, params);
// Ensure the result has been added to the hierarchy:
- if(db.getHierarchy().getParents(result).size() < 1) {
+ if (db.getHierarchy().numParents(result) < 1) {
db.getHierarchy().add(db, result);
}
@@ -239,4 +239,4 @@ public abstract class AbstractSimpleAlgorithmTest {
double actual = result.getScores().get(dbid);
org.junit.Assert.assertEquals("Outlier score of object " + id + " doesn't match.", expected, actual, 0.0001);
}
-} \ No newline at end of file
+}
diff --git a/test/de/lmu/ifi/dbs/elki/algorithm/TestKNNJoin.java b/test/de/lmu/ifi/dbs/elki/algorithm/TestKNNJoin.java
index f38f3dad..3d8ef366 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/TestKNNJoin.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/TestKNNJoin.java
@@ -37,16 +37,15 @@ import de.lmu.ifi.dbs.elki.database.QueryUtil;
import de.lmu.ifi.dbs.elki.database.StaticArrayDatabase;
import de.lmu.ifi.dbs.elki.database.datastore.DataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.datasource.FileBasedDatabaseConnection;
import de.lmu.ifi.dbs.elki.datasource.filter.FixedDBIDsFilter;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.ManhattanDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.ManhattanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
-import de.lmu.ifi.dbs.elki.index.tree.TreeIndexFactory;
import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry;
import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.deliclu.DeLiCluTree;
import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.deliclu.DeLiCluTreeFactory;
@@ -54,6 +53,7 @@ import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rstar.RStarTree;
import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rstar.RStarTreeFactory;
import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rstar.RStarTreeNode;
import de.lmu.ifi.dbs.elki.math.MeanVariance;
+import de.lmu.ifi.dbs.elki.persistent.AbstractPageFileFactory;
import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.ParameterException;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.ListParameterization;
@@ -101,7 +101,7 @@ public class TestKNNJoin implements JUnit4Test {
MeanVariance meansize = new MeanVariance();
for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
- KNNResult<DoubleDistance> knnlist = knnq.getKNNForDBID(iditer, 2);
+ KNNList<DoubleDistance> knnlist = knnq.getKNNForDBID(iditer, 2);
meansize.put(knnlist.size());
}
org.junit.Assert.assertEquals("Euclidean mean 2NN", mean2nnEuclid, meansize.getMean(), 0.00001);
@@ -114,7 +114,7 @@ public class TestKNNJoin implements JUnit4Test {
MeanVariance meansize = new MeanVariance();
for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
- KNNResult<DoubleDistance> knnlist = knnq.getKNNForDBID(iditer, 2);
+ KNNList<DoubleDistance> knnlist = knnq.getKNNForDBID(iditer, 2);
meansize.put(knnlist.size());
}
org.junit.Assert.assertEquals("Manhattan mean 2NN", mean2nnManhattan, meansize.getMean(), 0.00001);
@@ -131,7 +131,7 @@ public class TestKNNJoin implements JUnit4Test {
public void testKNNJoinRtreeMini() {
ListParameterization spatparams = new ListParameterization();
spatparams.addParameter(StaticArrayDatabase.INDEX_ID, RStarTreeFactory.class);
- spatparams.addParameter(TreeIndexFactory.PAGE_SIZE_ID, 200);
+ spatparams.addParameter(AbstractPageFileFactory.Parameterizer.PAGE_SIZE_ID, 200);
doKNNJoin(spatparams);
}
@@ -145,7 +145,7 @@ public class TestKNNJoin implements JUnit4Test {
public void testKNNJoinRtreeMaxi() {
ListParameterization spatparams = new ListParameterization();
spatparams.addParameter(StaticArrayDatabase.INDEX_ID, RStarTreeFactory.class);
- spatparams.addParameter(TreeIndexFactory.PAGE_SIZE_ID, 2000);
+ spatparams.addParameter(AbstractPageFileFactory.Parameterizer.PAGE_SIZE_ID, 2000);
doKNNJoin(spatparams);
}
@@ -159,7 +159,7 @@ public class TestKNNJoin implements JUnit4Test {
public void testKNNJoinDeLiCluTreeMini() {
ListParameterization spatparams = new ListParameterization();
spatparams.addParameter(StaticArrayDatabase.INDEX_ID, DeLiCluTreeFactory.class);
- spatparams.addParameter(TreeIndexFactory.PAGE_SIZE_ID, 200);
+ spatparams.addParameter(AbstractPageFileFactory.Parameterizer.PAGE_SIZE_ID, 200);
doKNNJoin(spatparams);
}
@@ -188,24 +188,24 @@ public class TestKNNJoin implements JUnit4Test {
// Euclidean
{
KNNJoin<DoubleVector, DoubleDistance, ?, ?> knnjoin = new KNNJoin<DoubleVector, DoubleDistance, RStarTreeNode, SpatialEntry>(EuclideanDistanceFunction.STATIC, 2);
- DataStore<KNNResult<DoubleDistance>> result = knnjoin.run(db);
+ DataStore<KNNList<DoubleDistance>> result = knnjoin.run(db);
MeanVariance meansize = new MeanVariance();
for(DBIDIter id = relation.getDBIDs().iter(); id.valid(); id.advance()) {
- KNNResult<DoubleDistance> knnlist = result.get(id);
+ KNNList<DoubleDistance> knnlist = result.get(id);
meansize.put(knnlist.size());
}
- org.junit.Assert.assertEquals("Euclidean mean 2NN", mean2nnEuclid, meansize.getMean(), 0.00001);
+ org.junit.Assert.assertEquals("Euclidean mean 2NN set size", mean2nnEuclid, meansize.getMean(), 0.00001);
org.junit.Assert.assertEquals("Euclidean variance 2NN", var2nnEuclid, meansize.getSampleVariance(), 0.00001);
}
// Manhattan
{
KNNJoin<DoubleVector, DoubleDistance, ?, ?> knnjoin = new KNNJoin<DoubleVector, DoubleDistance, RStarTreeNode, SpatialEntry>(ManhattanDistanceFunction.STATIC, 2);
- DataStore<KNNResult<DoubleDistance>> result = knnjoin.run(db);
+ DataStore<KNNList<DoubleDistance>> result = knnjoin.run(db);
MeanVariance meansize = new MeanVariance();
for(DBIDIter id = relation.getDBIDs().iter(); id.valid(); id.advance()) {
- KNNResult<DoubleDistance> knnlist = result.get(id);
+ KNNList<DoubleDistance> knnlist = result.get(id);
meansize.put(knnlist.size());
}
org.junit.Assert.assertEquals("Manhattan mean 2NN", mean2nnManhattan, meansize.getMean(), 0.00001);
diff --git a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestDeLiCluResults.java b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestDeLiCluResults.java
index a4fadeb2..1323c5fa 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestDeLiCluResults.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestDeLiCluResults.java
@@ -37,6 +37,7 @@ import de.lmu.ifi.dbs.elki.database.StaticArrayDatabase;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.evaluation.clustering.ClusterContingencyTable;
import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.deliclu.DeLiCluTreeFactory;
+import de.lmu.ifi.dbs.elki.persistent.AbstractPageFileFactory;
import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.ParameterException;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.ListParameterization;
@@ -62,7 +63,7 @@ public class TestDeLiCluResults extends AbstractSimpleAlgorithmTest implements J
ListParameterization indexparams = new ListParameterization();
// We need a special index for this algorithm:
indexparams.addParameter(StaticArrayDatabase.INDEX_ID, DeLiCluTreeFactory.class);
- indexparams.addParameter(DeLiCluTreeFactory.PAGE_SIZE_ID, 1000);
+ indexparams.addParameter(AbstractPageFileFactory.Parameterizer.PAGE_SIZE_ID, 1000);
Database db = makeSimpleDatabase(UNITTEST + "hierarchical-2d.ascii", 710, indexparams, null);
// Setup actual algorithm
diff --git a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/TestCASHResults.java b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/TestCASHResults.java
index ad11e6d2..62791b68 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/TestCASHResults.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/TestCASHResults.java
@@ -66,7 +66,7 @@ public class TestCASHResults extends AbstractSimpleAlgorithmTest implements JUni
// run CASH on database
Clustering<Model> result = cash.run(db);
- testFMeasure(db, result, 0.49055); // with hierarchical pairs: 0.64102
+ testFMeasure(db, result, 0.490551); // with hierarchical pairs: 0.64102
testClusterSizes(result, new int[] { 37, 71, 76, 442 });
}
diff --git a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/TestNaiveAgglomerativeHierarchicalClustering.java b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/TestNaiveAgglomerativeHierarchicalClustering.java
new file mode 100644
index 00000000..8ed18823
--- /dev/null
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/TestNaiveAgglomerativeHierarchicalClustering.java
@@ -0,0 +1,140 @@
+package de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2012
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import org.junit.Test;
+
+import de.lmu.ifi.dbs.elki.JUnit4Test;
+import de.lmu.ifi.dbs.elki.algorithm.AbstractSimpleAlgorithmTest;
+import de.lmu.ifi.dbs.elki.data.Clustering;
+import de.lmu.ifi.dbs.elki.database.Database;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+import de.lmu.ifi.dbs.elki.result.Result;
+import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.ListParameterization;
+import de.lmu.ifi.dbs.elki.workflow.AlgorithmStep;
+
+/**
+ * Perform agglomerative hierarchical clustering, using the naive algorithm.
+ *
+ * @author Erich Schubert
+ */
+public class TestNaiveAgglomerativeHierarchicalClustering extends AbstractSimpleAlgorithmTest implements JUnit4Test {
+ // TODO: add more data sets.
+
+ /**
+ * Run agglomerative hierarchical clustering with fixed parameters and compare
+ * the result to a golden standard.
+ */
+ @Test
+ public void testSingleLink() {
+ Database db = makeSimpleDatabase(UNITTEST + "single-link-effect.ascii", 638);
+
+ // Setup algorithm
+ ListParameterization params = new ListParameterization();
+ params.addParameter(ExtractFlatClusteringFromHierarchy.Parameterizer.OUTPUTMODE_ID, ExtractFlatClusteringFromHierarchy.OutputMode.STRICT_PARTITIONS);
+ params.addParameter(ExtractFlatClusteringFromHierarchy.Parameterizer.MINCLUSTERS_ID, 3);
+ params.addParameter(AlgorithmStep.Parameterizer.ALGORITHM_ID, NaiveAgglomerativeHierarchicalClustering.class);
+ params.addParameter(NaiveAgglomerativeHierarchicalClustering.Parameterizer.LINKAGE_ID, SingleLinkageMethod.class);
+ ExtractFlatClusteringFromHierarchy<DoubleDistance> c = ClassGenericsUtil.parameterizeOrAbort(ExtractFlatClusteringFromHierarchy.class, params);
+ testParameterizationOk(params);
+
+ // run clustering algorithm on database
+ Result result = c.run(db);
+ Clustering<?> clustering = findSingleClustering(result);
+ testFMeasure(db, clustering, 0.6829722);
+ testClusterSizes(clustering, new int[] { 9, 200, 429 });
+ }
+
+ /**
+ * Run agglomerative hierarchical clustering with fixed parameters and compare
+ * the result to a golden standard.
+ */
+ @Test
+ public void testWard() {
+ Database db = makeSimpleDatabase(UNITTEST + "single-link-effect.ascii", 638);
+
+ // Setup algorithm
+ ListParameterization params = new ListParameterization();
+ params.addParameter(ExtractFlatClusteringFromHierarchy.Parameterizer.OUTPUTMODE_ID, ExtractFlatClusteringFromHierarchy.OutputMode.STRICT_PARTITIONS);
+ params.addParameter(ExtractFlatClusteringFromHierarchy.Parameterizer.MINCLUSTERS_ID, 3);
+ params.addParameter(AlgorithmStep.Parameterizer.ALGORITHM_ID, NaiveAgglomerativeHierarchicalClustering.class);
+ ExtractFlatClusteringFromHierarchy<DoubleDistance> c = ClassGenericsUtil.parameterizeOrAbort(ExtractFlatClusteringFromHierarchy.class, params);
+ testParameterizationOk(params);
+
+ // run clustering algorithm on database
+ Result result = c.run(db);
+ Clustering<?> clustering = findSingleClustering(result);
+ testFMeasure(db, clustering, 0.93866265);
+ testClusterSizes(clustering, new int[] { 200, 211, 227 });
+ }
+
+ /**
+ * Run agglomerative hierarchical clustering with fixed parameters and compare
+ * the result to a golden standard.
+ */
+ @Test
+ public void testGroupAverage() {
+ Database db = makeSimpleDatabase(UNITTEST + "single-link-effect.ascii", 638);
+
+ // Setup algorithm
+ ListParameterization params = new ListParameterization();
+ params.addParameter(ExtractFlatClusteringFromHierarchy.Parameterizer.OUTPUTMODE_ID, ExtractFlatClusteringFromHierarchy.OutputMode.STRICT_PARTITIONS);
+ params.addParameter(ExtractFlatClusteringFromHierarchy.Parameterizer.MINCLUSTERS_ID, 3);
+ params.addParameter(AlgorithmStep.Parameterizer.ALGORITHM_ID, NaiveAgglomerativeHierarchicalClustering.class);
+ params.addParameter(NaiveAgglomerativeHierarchicalClustering.Parameterizer.LINKAGE_ID, GroupAverageLinkageMethod.class);
+ ExtractFlatClusteringFromHierarchy<DoubleDistance> c = ClassGenericsUtil.parameterizeOrAbort(ExtractFlatClusteringFromHierarchy.class, params);
+ testParameterizationOk(params);
+
+ // run clustering algorithm on database
+ Result result = c.run(db);
+ Clustering<?> clustering = findSingleClustering(result);
+ testFMeasure(db, clustering, 0.93866265);
+ testClusterSizes(clustering, new int[] { 200, 211, 227 });
+ }
+
+ /**
+ * Run agglomerative hierarchical clustering with fixed parameters and compare
+ * the result to a golden standard.
+ */
+ @Test
+ public void testCompleteLink() {
+ Database db = makeSimpleDatabase(UNITTEST + "single-link-effect.ascii", 638);
+
+ // Setup algorithm
+ ListParameterization params = new ListParameterization();
+ params.addParameter(ExtractFlatClusteringFromHierarchy.Parameterizer.OUTPUTMODE_ID, ExtractFlatClusteringFromHierarchy.OutputMode.STRICT_PARTITIONS);
+ params.addParameter(ExtractFlatClusteringFromHierarchy.Parameterizer.MINCLUSTERS_ID, 3);
+ params.addParameter(AlgorithmStep.Parameterizer.ALGORITHM_ID, NaiveAgglomerativeHierarchicalClustering.class);
+ params.addParameter(NaiveAgglomerativeHierarchicalClustering.Parameterizer.LINKAGE_ID, CompleteLinkageMethod.class);
+ ExtractFlatClusteringFromHierarchy<DoubleDistance> c = ClassGenericsUtil.parameterizeOrAbort(ExtractFlatClusteringFromHierarchy.class, params);
+ testParameterizationOk(params);
+
+ // run clustering algorithm on database
+ Result result = c.run(db);
+ Clustering<?> clustering = findSingleClustering(result);
+ testFMeasure(db, clustering, 0.938167802);
+ testClusterSizes(clustering, new int[] { 200, 217, 221 });
+ }
+}
diff --git a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestSLINKResults.java b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/TestSLINKResults.java
index 44160dd0..8b25cf9c 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestSLINKResults.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/hierarchical/TestSLINKResults.java
@@ -1,4 +1,4 @@
-package de.lmu.ifi.dbs.elki.algorithm.clustering;
+package de.lmu.ifi.dbs.elki.algorithm.clustering.hierarchical;
/*
This file is part of ELKI:
@@ -28,13 +28,13 @@ import org.junit.Test;
import de.lmu.ifi.dbs.elki.JUnit4Test;
import de.lmu.ifi.dbs.elki.algorithm.AbstractSimpleAlgorithmTest;
import de.lmu.ifi.dbs.elki.data.Clustering;
-import de.lmu.ifi.dbs.elki.data.DoubleVector;
import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.result.Result;
import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.ParameterException;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.ListParameterization;
+import de.lmu.ifi.dbs.elki.workflow.AlgorithmStep;
/**
* Performs a full SLINK run, and compares the result with a clustering derived
@@ -60,14 +60,16 @@ public class TestSLINKResults extends AbstractSimpleAlgorithmTest implements JUn
// Setup algorithm
ListParameterization params = new ListParameterization();
- params.addParameter(SLINK.Parameterizer.SLINK_MINCLUSTERS_ID, 3);
- SLINK<DoubleVector, DoubleDistance> slink = ClassGenericsUtil.parameterizeOrAbort(SLINK.class, params);
+ params.addParameter(ExtractFlatClusteringFromHierarchy.Parameterizer.OUTPUTMODE_ID, ExtractFlatClusteringFromHierarchy.OutputMode.STRICT_PARTITIONS);
+ params.addParameter(ExtractFlatClusteringFromHierarchy.Parameterizer.MINCLUSTERS_ID, 3);
+ params.addParameter(AlgorithmStep.Parameterizer.ALGORITHM_ID, SLINK.class);
+ ExtractFlatClusteringFromHierarchy<DoubleDistance> slink = ClassGenericsUtil.parameterizeOrAbort(ExtractFlatClusteringFromHierarchy.class, params);
testParameterizationOk(params);
// run SLINK on database
Result result = slink.run(db);
Clustering<?> clustering = findSingleClustering(result);
testFMeasure(db, clustering, 0.6829722);
- testClusterSizes(clustering, new int[] { 0, 0, 9, 200, 429 });
+ testClusterSizes(clustering, new int[] { 9, 200, 429 });
}
-} \ No newline at end of file
+}
diff --git a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/TestKMeansBisecting.java b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/TestKMeansBisecting.java
new file mode 100644
index 00000000..d678981d
--- /dev/null
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/TestKMeansBisecting.java
@@ -0,0 +1,90 @@
+package de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import org.junit.Test;
+
+import de.lmu.ifi.dbs.elki.JUnit4Test;
+import de.lmu.ifi.dbs.elki.algorithm.AbstractSimpleAlgorithmTest;
+import de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.quality.WithinClusterVarianceQualityMeasure;
+import de.lmu.ifi.dbs.elki.data.Clustering;
+import de.lmu.ifi.dbs.elki.data.DoubleVector;
+import de.lmu.ifi.dbs.elki.data.model.MeanModel;
+import de.lmu.ifi.dbs.elki.database.Database;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.ListParameterization;
+
+/**
+ * Tests the KMeansBisecting
+ *
+ * @author Stephan Baier
+ */
+public class TestKMeansBisecting extends AbstractSimpleAlgorithmTest implements JUnit4Test {
+ /**
+ * Run KMeansBisecting with fixed parameters and compare cluster size to
+ * expected value.
+ */
+ @Test
+ public void testKMeansBisectingClusterSize() {
+ Database db = makeSimpleDatabase(UNITTEST + "bisecting-test.csv", 300);
+
+ // Setup algorithm
+ ListParameterization params = new ListParameterization();
+ params.addParameter(KMeans.K_ID, 3);
+ params.addParameter(BestOfMultipleKMeans.Parameterizer.TRIALS_ID, 5);
+ params.addParameter(BestOfMultipleKMeans.Parameterizer.KMEANS_ID, KMeansLloyd.class);
+ params.addParameter(BestOfMultipleKMeans.Parameterizer.QUALITYMEASURE_ID, WithinClusterVarianceQualityMeasure.class);
+
+ KMeansBisecting<DoubleVector, DoubleDistance, MeanModel<DoubleVector>> kmeans = ClassGenericsUtil.parameterizeOrAbort(KMeansBisecting.class, params);
+ testParameterizationOk(params);
+
+ // run KMedians on database
+ Clustering<MeanModel<DoubleVector>> result = kmeans.run(db);
+ testClusterSizes(result, new int[] { 103, 97, 100 });
+ }
+
+ /**
+ * Run KMeansBisecting with fixed parameters (k = 2) and compare f-measure to
+ * golden standard.
+ */
+ @Test
+ public void testKMeansBisectingFMeasure() {
+ Database db = makeSimpleDatabase(UNITTEST + "bisecting-test.csv", 300);
+
+ // Setup algorithm
+ ListParameterization params = new ListParameterization();
+ params.addParameter(KMeans.K_ID, 2);
+ params.addParameter(BestOfMultipleKMeans.Parameterizer.TRIALS_ID, 5);
+ params.addParameter(BestOfMultipleKMeans.Parameterizer.KMEANS_ID, KMeansLloyd.class);
+ params.addParameter(BestOfMultipleKMeans.Parameterizer.QUALITYMEASURE_ID, WithinClusterVarianceQualityMeasure.class);
+
+ KMeansBisecting<DoubleVector, DoubleDistance, MeanModel<DoubleVector>> kmeans = ClassGenericsUtil.parameterizeOrAbort(KMeansBisecting.class, params);
+ testParameterizationOk(params);
+
+ // run KMedians on database
+ Clustering<MeanModel<DoubleVector>> result = kmeans.run(db);
+ testFMeasure(db, result, 0.7408);
+ }
+}
diff --git a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/TestKMeansQualityMeasure.java b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/TestKMeansQualityMeasure.java
new file mode 100644
index 00000000..44603617
--- /dev/null
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/TestKMeansQualityMeasure.java
@@ -0,0 +1,110 @@
+package de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans;
+
+/*
+ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+import de.lmu.ifi.dbs.elki.JUnit4Test;
+import de.lmu.ifi.dbs.elki.algorithm.AbstractSimpleAlgorithmTest;
+import de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.quality.KMeansQualityMeasure;
+import de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.quality.WithinClusterMeanDistanceQualityMeasure;
+import de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.quality.WithinClusterVarianceQualityMeasure;
+import de.lmu.ifi.dbs.elki.data.Clustering;
+import de.lmu.ifi.dbs.elki.data.DoubleVector;
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.model.MeanModel;
+import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.database.Database;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.ListParameterization;
+
+/**
+ * Test cluster quality measure computations.
+ *
+ * @author Stephan Baier
+ */
+public class TestKMeansQualityMeasure extends AbstractSimpleAlgorithmTest implements JUnit4Test {
+ /**
+ * Test cluster variance.
+ */
+ @Test
+ public void testVariance() {
+ Database db = makeSimpleDatabase(UNITTEST + "quality-measure-test.csv", 7);
+ Relation<DoubleVector> rel = db.getRelation(TypeUtil.DOUBLE_VECTOR_FIELD);
+
+ // Setup algorithm
+ ListParameterization params = new ListParameterization();
+ params = new ListParameterization();
+ params.addParameter(KMeans.K_ID, 2);
+ params.addParameter(KMeans.INIT_ID, FirstKInitialMeans.class);
+ AbstractKMeans<DoubleVector, DoubleDistance, ?> kmeans = ClassGenericsUtil.parameterizeOrAbort(KMeansLloyd.class, params);
+ testParameterizationOk(params);
+
+ // run KMeans on database
+ @SuppressWarnings("unchecked")
+ Clustering<MeanModel<DoubleVector>> result2 = (Clustering<MeanModel<DoubleVector>>) kmeans.run(db);
+
+ // Test Cluster Variance
+ KMeansQualityMeasure<? super DoubleVector, ? super DoubleDistance> variance = new WithinClusterVarianceQualityMeasure();
+ @SuppressWarnings("unchecked")
+ final PrimitiveDoubleDistanceFunction<NumberVector<?>> dist = (PrimitiveDoubleDistanceFunction<NumberVector<?>>) kmeans.getDistanceFunction();
+
+ final double quality = variance.calculateCost(result2, dist, rel);
+ assertEquals("Within cluster variance incorrect", 3.16666666666, quality, 1e-10);
+ }
+
+ /**
+ * Test cluster average overall distance.
+ */
+ @Test
+ public void testOverallDistance() {
+
+ Database db = makeSimpleDatabase(UNITTEST + "quality-measure-test.csv", 7);
+ Relation<DoubleVector> rel = db.getRelation(TypeUtil.DOUBLE_VECTOR_FIELD);
+
+ // Setup algorithm
+ ListParameterization params = new ListParameterization();
+ params = new ListParameterization();
+ params.addParameter(KMeans.K_ID, 2);
+ params.addParameter(KMeans.INIT_ID, FirstKInitialMeans.class);
+ AbstractKMeans<DoubleVector, DoubleDistance, ?> kmeans = ClassGenericsUtil.parameterizeOrAbort(KMeansLloyd.class, params);
+ testParameterizationOk(params);
+
+ // run KMeans on database
+ @SuppressWarnings("unchecked")
+ Clustering<MeanModel<DoubleVector>> result = (Clustering<MeanModel<DoubleVector>>) kmeans.run(db);
+ @SuppressWarnings("unchecked")
+ final PrimitiveDoubleDistanceFunction<NumberVector<?>> dist = (PrimitiveDoubleDistanceFunction<NumberVector<?>>) kmeans.getDistanceFunction();
+
+ // Test Cluster Average Overall Distance
+ KMeansQualityMeasure<? super DoubleVector, ? super DoubleDistance> overall = new WithinClusterMeanDistanceQualityMeasure();
+ final double quality = overall.calculateCost(result, dist, rel);
+
+ assertEquals("Avarage overall distance not as expected.", 0.8888888888888888, quality, 1e-10);
+ }
+}
diff --git a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/TestKMeansResults.java b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/TestKMeansResults.java
index bfe57052..3419352a 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/TestKMeansResults.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/TestKMeansResults.java
@@ -61,7 +61,7 @@ public class TestKMeansResults extends AbstractSimpleAlgorithmTest implements JU
// Setup algorithm
ListParameterization params = new ListParameterization();
params.addParameter(KMeans.K_ID, 5);
- params.addParameter(KMeans.SEED_ID, 3);
+ params.addParameter(KMeans.INIT_ID, FirstKInitialMeans.class);
AbstractKMeans<DoubleVector, DoubleDistance, ?> kmeans = ClassGenericsUtil.parameterizeOrAbort(KMeansLloyd.class, params);
testParameterizationOk(params);
@@ -84,7 +84,7 @@ public class TestKMeansResults extends AbstractSimpleAlgorithmTest implements JU
// Setup algorithm
ListParameterization params = new ListParameterization();
params.addParameter(KMeans.K_ID, 5);
- params.addParameter(KMeans.SEED_ID, 3);
+ params.addParameter(KMeans.INIT_ID, FirstKInitialMeans.class);
AbstractKMeans<DoubleVector, DoubleDistance, ?> kmeans = ClassGenericsUtil.parameterizeOrAbort(KMeansMacQueen.class, params);
testParameterizationOk(params);
@@ -107,7 +107,7 @@ public class TestKMeansResults extends AbstractSimpleAlgorithmTest implements JU
// Setup algorithm
ListParameterization params = new ListParameterization();
params.addParameter(KMeans.K_ID, 5);
- params.addParameter(KMeans.SEED_ID, 3);
+ params.addParameter(KMeans.INIT_ID, FirstKInitialMeans.class);
AbstractKMeans<DoubleVector, DoubleDistance, ?> kmedians = ClassGenericsUtil.parameterizeOrAbort(KMediansLloyd.class, params);
testParameterizationOk(params);
diff --git a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/TestPROCLUSResults.java b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/TestPROCLUSResults.java
index b7dde28e..bfb94ee3 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/TestPROCLUSResults.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/TestPROCLUSResults.java
@@ -58,7 +58,8 @@ public class TestPROCLUSResults extends AbstractSimpleAlgorithmTest implements J
ListParameterization params = new ListParameterization();
params.addParameter(PROCLUS.Parameterizer.L_ID, 1);
params.addParameter(PROCLUS.Parameterizer.K_ID, 4);
- params.addParameter(PROCLUS.Parameterizer.SEED_ID, 2);
+ // NOTE: PROCLUS quality heavily depends on random...
+ params.addParameter(PROCLUS.Parameterizer.SEED_ID, 0);
// setup algorithm
PROCLUS<DoubleVector> proclus = ClassGenericsUtil.parameterizeOrAbort(PROCLUS.class, params);
@@ -67,8 +68,8 @@ public class TestPROCLUSResults extends AbstractSimpleAlgorithmTest implements J
// run PROCLUS on database
Clustering<?> result = proclus.run(db);
- testFMeasure(db, result, 0.900947932);
- testClusterSizes(result, new int[] { 15, 35, 200, 350 });
+ testFMeasure(db, result, 0.6946958);
+ testClusterSizes(result, new int[] { 45, 151, 200, 204 });
}
/**
@@ -85,13 +86,14 @@ public class TestPROCLUSResults extends AbstractSimpleAlgorithmTest implements J
ListParameterization params = new ListParameterization();
params.addParameter(PROCLUS.Parameterizer.L_ID, 2);
params.addParameter(PROCLUS.Parameterizer.K_ID, 3);
- params.addParameter(PROCLUS.Parameterizer.SEED_ID, 0);
+ // NOTE: PROCLUS quality heavily depends on random...
+ params.addParameter(PROCLUS.Parameterizer.SEED_ID, 1);
PROCLUS<DoubleVector> proclus = ClassGenericsUtil.parameterizeOrAbort(PROCLUS.class, params);
testParameterizationOk(params);
// run PROCLUS on database
Clustering<?> result = proclus.run(db);
- testFMeasure(db, result, 0.739931511);
- testClusterSizes(result, new int[] { 146, 259, 445 });
+ testFMeasure(db, result, 0.7812455);
+ testClusterSizes(result, new int[] { 111, 269, 470 });
}
} \ No newline at end of file
diff --git a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestINFLO.java b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/TestINFLO.java
index 8a1e84ef..99b97d92 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestINFLO.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/TestINFLO.java
@@ -1,4 +1,4 @@
-package de.lmu.ifi.dbs.elki.algorithm.outlier;
+package de.lmu.ifi.dbs.elki.algorithm.outlier.lof;
/*
This file is part of ELKI:
@@ -27,6 +27,7 @@ import org.junit.Test;
import de.lmu.ifi.dbs.elki.JUnit4Test;
import de.lmu.ifi.dbs.elki.algorithm.AbstractSimpleAlgorithmTest;
+import de.lmu.ifi.dbs.elki.algorithm.outlier.lof.INFLO;
import de.lmu.ifi.dbs.elki.data.DoubleVector;
import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
diff --git a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestLDOF.java b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/TestLDOF.java
index 70a5b170..370054ea 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestLDOF.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/TestLDOF.java
@@ -1,4 +1,4 @@
-package de.lmu.ifi.dbs.elki.algorithm.outlier;
+package de.lmu.ifi.dbs.elki.algorithm.outlier.lof;
/*
This file is part of ELKI:
@@ -27,6 +27,7 @@ import org.junit.Test;
import de.lmu.ifi.dbs.elki.JUnit4Test;
import de.lmu.ifi.dbs.elki.algorithm.AbstractSimpleAlgorithmTest;
+import de.lmu.ifi.dbs.elki.algorithm.outlier.lof.LDOF;
import de.lmu.ifi.dbs.elki.data.DoubleVector;
import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
diff --git a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestLOCI.java b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/TestLOCI.java
index d95b362c..05206f55 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestLOCI.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/TestLOCI.java
@@ -1,4 +1,4 @@
-package de.lmu.ifi.dbs.elki.algorithm.outlier;
+package de.lmu.ifi.dbs.elki.algorithm.outlier.lof;
/*
This file is part of ELKI:
@@ -27,6 +27,7 @@ import org.junit.Test;
import de.lmu.ifi.dbs.elki.JUnit4Test;
import de.lmu.ifi.dbs.elki.algorithm.AbstractSimpleAlgorithmTest;
+import de.lmu.ifi.dbs.elki.algorithm.outlier.lof.LOCI;
import de.lmu.ifi.dbs.elki.data.DoubleVector;
import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
diff --git a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestLOF.java b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/TestLOF.java
index a1ef967b..2c7bbd1d 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestLOF.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/TestLOF.java
@@ -1,4 +1,4 @@
-package de.lmu.ifi.dbs.elki.algorithm.outlier;
+package de.lmu.ifi.dbs.elki.algorithm.outlier.lof;
/*
This file is part of ELKI:
@@ -27,6 +27,7 @@ import org.junit.Test;
import de.lmu.ifi.dbs.elki.JUnit4Test;
import de.lmu.ifi.dbs.elki.algorithm.AbstractSimpleAlgorithmTest;
+import de.lmu.ifi.dbs.elki.algorithm.outlier.lof.LOF;
import de.lmu.ifi.dbs.elki.data.DoubleVector;
import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
@@ -46,7 +47,7 @@ public class TestLOF extends AbstractSimpleAlgorithmTest implements JUnit4Test {
// Parameterization
ListParameterization params = new ListParameterization();
- params.addParameter(LOF.K_ID, 10);
+ params.addParameter(LOF.Parameterizer.K_ID, 10);
// setup Algorithm
LOF<DoubleVector, DoubleDistance> lof = ClassGenericsUtil.parameterizeOrAbort(LOF.class, params);
diff --git a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestLoOP.java b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/TestLoOP.java
index 653f4a29..e6670eb7 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestLoOP.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/TestLoOP.java
@@ -1,4 +1,4 @@
-package de.lmu.ifi.dbs.elki.algorithm.outlier;
+package de.lmu.ifi.dbs.elki.algorithm.outlier.lof;
/*
This file is part of ELKI:
@@ -27,6 +27,7 @@ import org.junit.Test;
import de.lmu.ifi.dbs.elki.JUnit4Test;
import de.lmu.ifi.dbs.elki.algorithm.AbstractSimpleAlgorithmTest;
+import de.lmu.ifi.dbs.elki.algorithm.outlier.lof.LoOP;
import de.lmu.ifi.dbs.elki.data.DoubleVector;
import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
diff --git a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestOnlineLOF.java b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/TestOnlineLOF.java
index 5b9881e3..cd60a58f 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestOnlineLOF.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/lof/TestOnlineLOF.java
@@ -1,4 +1,4 @@
-package de.lmu.ifi.dbs.elki.algorithm.outlier;
+package de.lmu.ifi.dbs.elki.algorithm.outlier.lof;
/*
This file is part of ELKI:
@@ -32,6 +32,9 @@ import java.util.Random;
import org.junit.Test;
import de.lmu.ifi.dbs.elki.JUnit4Test;
+import de.lmu.ifi.dbs.elki.algorithm.outlier.lof.FlexibleLOF;
+import de.lmu.ifi.dbs.elki.algorithm.outlier.lof.LOF;
+import de.lmu.ifi.dbs.elki.algorithm.outlier.lof.OnlineLOF;
import de.lmu.ifi.dbs.elki.data.DoubleVector;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.data.VectorUtil;
@@ -47,7 +50,7 @@ import de.lmu.ifi.dbs.elki.datasource.FileBasedDatabaseConnection;
import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle;
import de.lmu.ifi.dbs.elki.distance.distancefunction.CosineDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
@@ -97,7 +100,7 @@ public class TestOnlineLOF implements JUnit4Test {
UpdatableDatabase db = getDatabase();
// 1. Run LOF
- LOF<DoubleVector, DoubleDistance> lof = new LOF<DoubleVector, DoubleDistance>(k, neighborhoodDistanceFunction, reachabilityDistanceFunction);
+ FlexibleLOF<DoubleVector, DoubleDistance> lof = new FlexibleLOF<>(k, k, neighborhoodDistanceFunction, reachabilityDistanceFunction);
OutlierResult result1 = lof.run(db);
// 2. Run OnlineLOF (with insertions and removals) on database
@@ -122,13 +125,13 @@ public class TestOnlineLOF implements JUnit4Test {
Relation<DoubleVector> rep = db.getRelation(TypeUtil.DOUBLE_VECTOR_FIELD);
// setup algorithm
- OnlineLOF<DoubleVector, DoubleDistance> lof = new OnlineLOF<DoubleVector, DoubleDistance>(k, neighborhoodDistanceFunction, reachabilityDistanceFunction);
+ OnlineLOF<DoubleVector, DoubleDistance> lof = new OnlineLOF<>(k, k, neighborhoodDistanceFunction, reachabilityDistanceFunction);
// run OnlineLOF on database
OutlierResult result = lof.run(db);
// insert new objects
- ArrayList<DoubleVector> insertions = new ArrayList<DoubleVector>();
+ ArrayList<DoubleVector> insertions = new ArrayList<>();
NumberVector.Factory<DoubleVector, ?> o = RelationUtil.getNumberVectorFactory(rep);
int dim = RelationUtil.dimensionality(rep);
Random random = new Random(seed);
diff --git a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/TestFeatureBagging.java b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/TestFeatureBagging.java
index 18e5c6ac..c3d9f7a0 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/TestFeatureBagging.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/TestFeatureBagging.java
@@ -27,7 +27,7 @@ import org.junit.Test;
import de.lmu.ifi.dbs.elki.JUnit4Test;
import de.lmu.ifi.dbs.elki.algorithm.AbstractSimpleAlgorithmTest;
-import de.lmu.ifi.dbs.elki.algorithm.outlier.LOF;
+import de.lmu.ifi.dbs.elki.algorithm.outlier.lof.LOF;
import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
@@ -45,7 +45,7 @@ public class TestFeatureBagging extends AbstractSimpleAlgorithmTest implements J
// Parameterization
ListParameterization params = new ListParameterization();
- params.addParameter(LOF.K_ID, 10);
+ params.addParameter(LOF.Parameterizer.K_ID, 10);
params.addParameter(FeatureBagging.Parameterizer.NUM_ID, 10);
params.addParameter(FeatureBagging.Parameterizer.SEED_ID, 1);
@@ -66,7 +66,7 @@ public class TestFeatureBagging extends AbstractSimpleAlgorithmTest implements J
// Parameterization
ListParameterization params = new ListParameterization();
- params.addParameter(LOF.K_ID, 10);
+ params.addParameter(LOF.Parameterizer.K_ID, 10);
params.addParameter(FeatureBagging.Parameterizer.NUM_ID, 10);
params.addParameter(FeatureBagging.Parameterizer.SEED_ID, 5);
params.addFlag(FeatureBagging.Parameterizer.BREADTH_ID);
diff --git a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/TestHiCS.java b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/TestHiCS.java
index 40240ec4..e1ed1f37 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/TestHiCS.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/TestHiCS.java
@@ -27,7 +27,7 @@ import org.junit.Test;
import de.lmu.ifi.dbs.elki.JUnit4Test;
import de.lmu.ifi.dbs.elki.algorithm.AbstractSimpleAlgorithmTest;
-import de.lmu.ifi.dbs.elki.algorithm.outlier.LOF;
+import de.lmu.ifi.dbs.elki.algorithm.outlier.lof.LOF;
import de.lmu.ifi.dbs.elki.data.DoubleVector;
import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.math.statistics.tests.KolmogorovSmirnovTest;
@@ -48,7 +48,7 @@ public class TestHiCS extends AbstractSimpleAlgorithmTest implements JUnit4Test
// Parameterization
ListParameterization params = new ListParameterization();
- params.addParameter(LOF.K_ID, 10);
+ params.addParameter(LOF.Parameterizer.K_ID, 10);
params.addParameter(HiCS.Parameterizer.LIMIT_ID, 10);
params.addParameter(HiCS.Parameterizer.SEED_ID, 0);
params.addParameter(HiCS.Parameterizer.TEST_ID, KolmogorovSmirnovTest.STATIC);
@@ -60,8 +60,8 @@ public class TestHiCS extends AbstractSimpleAlgorithmTest implements JUnit4Test
// run HiCS on database
OutlierResult result = fb.run(db);
- testAUC(db, "Noise", result, 0.9024537815126049);
- testSingleScore(result, 1293, 5.0754391836);
+ testAUC(db, "Noise", result, 0.85340056);
+ testSingleScore(result, 1293, 4.935802);
}
@Test
@@ -70,7 +70,7 @@ public class TestHiCS extends AbstractSimpleAlgorithmTest implements JUnit4Test
// Parameterization
ListParameterization params = new ListParameterization();
- params.addParameter(LOF.K_ID, 10);
+ params.addParameter(LOF.Parameterizer.K_ID, 10);
params.addParameter(HiCS.Parameterizer.LIMIT_ID, 10);
params.addParameter(HiCS.Parameterizer.SEED_ID, 0);
params.addParameter(HiCS.Parameterizer.TEST_ID, WelchTTest.STATIC);
@@ -82,7 +82,7 @@ public class TestHiCS extends AbstractSimpleAlgorithmTest implements JUnit4Test
// run HiCS on database
OutlierResult result = fb.run(db);
- testAUC(db, "Noise", result, 0.6597983193);
- testSingleScore(result, 1293, 2.6993476951);
+ testAUC(db, "Noise", result, 0.6255238);
+ testSingleScore(result, 1293, 2.542272);
}
} \ No newline at end of file
diff --git a/test/de/lmu/ifi/dbs/elki/data/spatial/TestPolygon.java b/test/de/lmu/ifi/dbs/elki/data/spatial/TestPolygon.java
index 60d7f678..9403946a 100644
--- a/test/de/lmu/ifi/dbs/elki/data/spatial/TestPolygon.java
+++ b/test/de/lmu/ifi/dbs/elki/data/spatial/TestPolygon.java
@@ -38,21 +38,21 @@ public class TestPolygon implements JUnit4Test {
public void testPolygonContainment() {
final Polygon p1, p2, p3;
{
- List<Vector> v1 = new ArrayList<Vector>();
+ List<Vector> v1 = new ArrayList<>();
v1.add(new Vector(0, 0));
v1.add(new Vector(.9, 0));
v1.add(new Vector(0, .9));
p1 = new Polygon(v1);
}
{
- List<Vector> v2 = new ArrayList<Vector>();
+ List<Vector> v2 = new ArrayList<>();
v2.add(new Vector(1, 1));
v2.add(new Vector(1, .1));
v2.add(new Vector(.1, 1));
p2 = new Polygon(v2);
}
{
- List<Vector> v3 = new ArrayList<Vector>();
+ List<Vector> v3 = new ArrayList<>();
v3.add(new Vector(.1, .1));
v3.add(new Vector(.1, .9));
v3.add(new Vector(.9, .9));
diff --git a/test/de/lmu/ifi/dbs/elki/datasource/parser/TestTermFrequencyParser.java b/test/de/lmu/ifi/dbs/elki/datasource/parser/TestTermFrequencyParser.java
new file mode 100644
index 00000000..bf5e2791
--- /dev/null
+++ b/test/de/lmu/ifi/dbs/elki/datasource/parser/TestTermFrequencyParser.java
@@ -0,0 +1,129 @@
+package de.lmu.ifi.dbs.elki.datasource.parser;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+
+import org.junit.Test;
+
+import de.lmu.ifi.dbs.elki.JUnit4Test;
+import de.lmu.ifi.dbs.elki.data.SparseNumberVector;
+import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.database.Database;
+import de.lmu.ifi.dbs.elki.database.StaticArrayDatabase;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.datasource.AbstractDatabaseConnection;
+import de.lmu.ifi.dbs.elki.datasource.FileBasedDatabaseConnection;
+import de.lmu.ifi.dbs.elki.datasource.filter.SparseVectorFieldFilter;
+import de.lmu.ifi.dbs.elki.datasource.filter.normalization.TFIDFNormalization;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.ArcCosineDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SparseEuclideanDistanceFunction;
+import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.ListParameterization;
+
+/**
+ * Unit test the term frequency parser by loading an example data set derived
+ * from DBLP.
+ *
+ * TODO: maybe also run an example algorithm?
+ *
+ * @author Erich Schubert
+ */
+public class TestTermFrequencyParser implements JUnit4Test {
+ /** Test data set to use. */
+ public static String DBLP_DATA = "data/testdata/parsing/termfreq-dblp.ascii.gz";
+
+ @Test
+ public void testDBLPData() {
+ ListParameterization config = new ListParameterization();
+ config.addParameter(AbstractDatabaseConnection.PARSER_ID, TermFrequencyParser.class);
+ config.addParameter(FileBasedDatabaseConnection.INPUT_ID, DBLP_DATA);
+
+ ArrayList<Object> filters = new ArrayList<>();
+ filters.add(TFIDFNormalization.class);
+ // Note: this filter is needed for the non-sparse euclidean distance below.
+ filters.add(SparseVectorFieldFilter.class);
+ config.addParameter(AbstractDatabaseConnection.FILTERS_ID, filters);
+
+ Database db = ClassGenericsUtil.parameterizeOrAbort(StaticArrayDatabase.class, config);
+
+ if (config.hasUnusedParameters()) {
+ fail("Unused parameters: " + config.getRemainingParameters());
+ }
+ if (config.hasErrors()) {
+ config.logAndClearReportedErrors();
+ fail("Parameterization errors.");
+ }
+
+ db.initialize();
+
+ Relation<SparseNumberVector<?>> rel = db.getRelation(TypeUtil.SPARSE_VECTOR_FIELD);
+
+ // Get first three objects:
+ DBIDIter iter = rel.iterDBIDs();
+ SparseNumberVector<?> v1 = rel.get(iter);
+ iter.advance();
+ SparseNumberVector<?> v2 = rel.get(iter);
+ iter.advance();
+ SparseNumberVector<?> v3 = rel.get(iter);
+
+ // "Dense" euclidean distance:
+ double euclid1_12 = EuclideanDistanceFunction.STATIC.doubleDistance(v1, v2);
+ double euclid1_13 = EuclideanDistanceFunction.STATIC.doubleDistance(v1, v3);
+ double euclid1_23 = EuclideanDistanceFunction.STATIC.doubleDistance(v2, v3);
+ double euclid1_21 = EuclideanDistanceFunction.STATIC.doubleDistance(v2, v1);
+ // Sparse euclidean distance:
+ double euclid2_12 = SparseEuclideanDistanceFunction.STATIC.doubleDistance(v1, v2);
+ double euclid2_13 = SparseEuclideanDistanceFunction.STATIC.doubleDistance(v1, v3);
+ double euclid2_23 = SparseEuclideanDistanceFunction.STATIC.doubleDistance(v2, v3);
+ double euclid2_21 = SparseEuclideanDistanceFunction.STATIC.doubleDistance(v2, v1);
+ // (Auto-switching) angular distance:
+ double arccos_12 = ArcCosineDistanceFunction.STATIC.doubleDistance(v1, v2);
+ double arccos_13 = ArcCosineDistanceFunction.STATIC.doubleDistance(v1, v3);
+ double arccos_23 = ArcCosineDistanceFunction.STATIC.doubleDistance(v2, v3);
+ double arccos_21 = ArcCosineDistanceFunction.STATIC.doubleDistance(v2, v1);
+
+ assertEquals("Euclidean self-distance is not 0.", 0., EuclideanDistanceFunction.STATIC.doubleDistance(v1, v1), Double.MIN_VALUE);
+ assertEquals("Sparse Euclidean self-distance is not 0.", 0., SparseEuclideanDistanceFunction.STATIC.doubleDistance(v1, v1), Double.MIN_VALUE);
+ assertEquals("Arccos self-distance is not 0.", 0., ArcCosineDistanceFunction.STATIC.doubleDistance(v1, v1), Double.MIN_VALUE);
+ assertEquals("Euclidean distance not symmetric.", euclid1_12, euclid1_21, Double.MIN_VALUE);
+ assertEquals("Sparse Euclidean distance not symmetric.", euclid2_12, euclid2_21, Double.MIN_VALUE);
+ assertEquals("Arccos distance not symmetric.", arccos_12, arccos_21, Double.MIN_VALUE);
+
+ assertEquals("Euclidean distance 1-2 not as expected.", 684.4165398352088, euclid1_12, 1e-20);
+ assertEquals("Sparse Euclidean distance 1-2 not as expected.", 684.4165398352088, euclid2_12, 1e-20);
+ assertEquals("Arccos distance 1-2 not as expected.", 0.1901934493141418, arccos_12, 1e-20);
+ assertEquals("Euclidean distance 1-3 not as expected.", 654.9862593978594, euclid1_13, 1e-20);
+ assertEquals("Sparse Euclidean distance 1-3 not as expected.", 654.9862593978594, euclid2_13, 1e-20);
+ assertEquals("Arccos distance 1-3 not as expected.", 0.18654347641726107, arccos_13, 1e-20);
+ assertEquals("Euclidean distance 2-3 not as expected.", 231.78653972998518, euclid1_23, 1e-20);
+ assertEquals("Sparse Euclidean distance 2-3 not as expected.", 231.78653972998518, euclid2_23, 1e-20);
+ assertEquals("Arccos distance 2-3 not as expected.", 0.11138352337990769, arccos_23, 1e-20);
+ }
+}
diff --git a/test/de/lmu/ifi/dbs/elki/distance/distancefunction/SpatialPrimitiveDistanceFunctionTest.java b/test/de/lmu/ifi/dbs/elki/distance/distancefunction/SpatialPrimitiveDistanceFunctionTest.java
index 7309cbbf..81512abd 100644
--- a/test/de/lmu/ifi/dbs/elki/distance/distancefunction/SpatialPrimitiveDistanceFunctionTest.java
+++ b/test/de/lmu/ifi/dbs/elki/distance/distancefunction/SpatialPrimitiveDistanceFunctionTest.java
@@ -36,6 +36,12 @@ import de.lmu.ifi.dbs.elki.JUnit4Test;
import de.lmu.ifi.dbs.elki.data.ModifiableHyperBoundingBox;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.distance.distancefunction.colorhistogram.HistogramIntersectionDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.LPNormDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.ManhattanDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.MaximumDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.MinimumDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SquaredEuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
@@ -53,7 +59,7 @@ public class SpatialPrimitiveDistanceFunctionTest implements JUnit4Test {
final int dim = 7;
final int iters = 10000;
- List<SpatialPrimitiveDistanceFunction<? super NumberVector<?>, ?>> dists = new ArrayList<SpatialPrimitiveDistanceFunction<? super NumberVector<?>, ?>>();
+ List<SpatialPrimitiveDistanceFunction<? super NumberVector<?>, ?>> dists = new ArrayList<>();
dists.add(EuclideanDistanceFunction.STATIC);
dists.add(ManhattanDistanceFunction.STATIC);
dists.add(MaximumDistanceFunction.STATIC);
@@ -99,7 +105,7 @@ public class SpatialPrimitiveDistanceFunctionTest implements JUnit4Test {
final int dim = 7;
final int iters = 10000;
- List<SpatialPrimitiveDistanceFunction<? super NumberVector<?>, ?>> dists = new ArrayList<SpatialPrimitiveDistanceFunction<? super NumberVector<?>, ?>>();
+ List<SpatialPrimitiveDistanceFunction<? super NumberVector<?>, ?>> dists = new ArrayList<>();
dists.add(EuclideanDistanceFunction.STATIC);
dists.add(ManhattanDistanceFunction.STATIC);
dists.add(MaximumDistanceFunction.STATIC);
diff --git a/test/de/lmu/ifi/dbs/elki/distance/distancefunction/strings/LevenshteinDistanceFunctionTest.java b/test/de/lmu/ifi/dbs/elki/distance/distancefunction/strings/LevenshteinDistanceFunctionTest.java
new file mode 100644
index 00000000..7aa8208a
--- /dev/null
+++ b/test/de/lmu/ifi/dbs/elki/distance/distancefunction/strings/LevenshteinDistanceFunctionTest.java
@@ -0,0 +1,66 @@
+package de.lmu.ifi.dbs.elki.distance.distancefunction.strings;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+import de.lmu.ifi.dbs.elki.JUnit4Test;
+
+/**
+ * Unit test for Levenshtein distance.
+ *
+ * @author Erich Schubert
+ */
+public class LevenshteinDistanceFunctionTest implements JUnit4Test {
+ /**
+ * Some test strings, from the Wikipedia article.
+ */
+ final String[][] TESTS = { //
+ { "kitten", "sitting" }, //
+ { "Saturday", "Sunday" }, //
+ { "tier", "tor" }, //
+ { "abcz", "zabc" }, //
+ { "zabc", "abcz" }, //
+ };
+
+ /**
+ * The associated scores.
+ */
+ final int[] SCORES = { //
+ 3, // kitten <-> sitting
+ 3, // Saturday <-> Sunday
+ 2, // Tier <-> Tor
+ 2, // abcz <-> zabc
+ 2, // zabc <-> abcz
+ };
+
+ @Test
+ public void testStringLevenshtein() {
+ LevenshteinDistanceFunction f = LevenshteinDistanceFunction.STATIC_SENSITIVE;
+ for (int i = 0; i < TESTS.length; i++) {
+ assertEquals("Distance does not agree: " + TESTS[i][0] + " <-> " + TESTS[i][1], SCORES[i], f.distance(TESTS[i][0], TESTS[i][1]).intValue());
+ }
+ }
+}
diff --git a/test/de/lmu/ifi/dbs/elki/distance/distancefunction/strings/NormalizedLevenshteinDistanceFunctionTest.java b/test/de/lmu/ifi/dbs/elki/distance/distancefunction/strings/NormalizedLevenshteinDistanceFunctionTest.java
new file mode 100644
index 00000000..57260e76
--- /dev/null
+++ b/test/de/lmu/ifi/dbs/elki/distance/distancefunction/strings/NormalizedLevenshteinDistanceFunctionTest.java
@@ -0,0 +1,66 @@
+package de.lmu.ifi.dbs.elki.distance.distancefunction.strings;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+import de.lmu.ifi.dbs.elki.JUnit4Test;
+
+/**
+ * Unit test for Levenshtein distance.
+ *
+ * @author Erich Schubert
+ */
+public class NormalizedLevenshteinDistanceFunctionTest implements JUnit4Test {
+ /**
+ * Some test strings, from the Wikipedia article.
+ */
+ final String[][] TESTS = { //
+ { "kitten", "sitting" }, //
+ { "Saturday", "Sunday" }, //
+ { "tier", "tor" }, //
+ { "abcz", "zabc" }, //
+ { "zabc", "abcz" }, //
+ };
+
+ /**
+ * The associated scores.
+ */
+ final double[] SCORES = { //
+ 3. / 6.5, // kitten <-> sitting
+ 3. / 7., // Saturday <-> Sunday
+ 2. / 3.5, // tier <-> tor
+ 2. / 4., // abcz <-> zabc
+ 2. / 4., // zabc <-> abcz
+ };
+
+ @Test
+ public void testStringLevenshtein() {
+ NormalizedLevenshteinDistanceFunction f = NormalizedLevenshteinDistanceFunction.STATIC_SENSITIVE;
+ for (int i = 0; i < TESTS.length; i++) {
+ assertEquals("Distance does not agree: " + TESTS[i][0] + " <-> " + TESTS[i][1], SCORES[i], f.distance(TESTS[i][0], TESTS[i][1]).doubleValue(), 1E-10);
+ }
+ }
+}
diff --git a/test/de/lmu/ifi/dbs/elki/evaluation/roc/TestComputeROC.java b/test/de/lmu/ifi/dbs/elki/evaluation/roc/TestComputeROC.java
index 6a6157a1..1988f060 100644
--- a/test/de/lmu/ifi/dbs/elki/evaluation/roc/TestComputeROC.java
+++ b/test/de/lmu/ifi/dbs/elki/evaluation/roc/TestComputeROC.java
@@ -23,18 +23,15 @@ package de.lmu.ifi.dbs.elki.evaluation.roc;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.ArrayList;
-
import junit.framework.Assert;
import org.junit.Test;
import de.lmu.ifi.dbs.elki.JUnit4Test;
-import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.HashSetModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPairList;
import de.lmu.ifi.dbs.elki.math.geometry.XYCurve;
-import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
/**
* Test to validate ROC curve computation.
@@ -54,19 +51,20 @@ public class TestComputeROC implements JUnit4Test {
positive.add(DBIDUtil.importInteger(4));
positive.add(DBIDUtil.importInteger(5));
- ArrayList<Pair<Double, DBID>> distances = new ArrayList<Pair<Double, DBID>>();
- distances.add(new Pair<Double, DBID>(0.0, DBIDUtil.importInteger(1)));
- distances.add(new Pair<Double, DBID>(1.0, DBIDUtil.importInteger(2)));
- distances.add(new Pair<Double, DBID>(2.0, DBIDUtil.importInteger(6)));
- distances.add(new Pair<Double, DBID>(3.0, DBIDUtil.importInteger(7)));
- distances.add(new Pair<Double, DBID>(3.0, DBIDUtil.importInteger(3)));
- distances.add(new Pair<Double, DBID>(4.0, DBIDUtil.importInteger(8)));
- distances.add(new Pair<Double, DBID>(4.0, DBIDUtil.importInteger(4)));
- distances.add(new Pair<Double, DBID>(5.0, DBIDUtil.importInteger(9)));
- distances.add(new Pair<Double, DBID>(6.0, DBIDUtil.importInteger(5)));
+ final DoubleDistanceDBIDPairList distances = new DoubleDistanceDBIDPairList();
+ // Starting point: ................................ 0.0,0. ++
+ distances.add(0.0, DBIDUtil.importInteger(1)); // + 0.0,.2 -- redundant
+ distances.add(1.0, DBIDUtil.importInteger(2)); // + 0.0,.4 ++
+ distances.add(2.0, DBIDUtil.importInteger(6)); // - .25,.4 ++
+ distances.add(3.0, DBIDUtil.importInteger(7)); // -
+ distances.add(3.0, DBIDUtil.importInteger(3)); // + .50,.6 -- redundant
+ distances.add(4.0, DBIDUtil.importInteger(8)); // -
+ distances.add(4.0, DBIDUtil.importInteger(4)); // + .75,.8 ++
+ distances.add(5.0, DBIDUtil.importInteger(9)); // - 1.0,.8 ++
+ distances.add(6.0, DBIDUtil.importInteger(5)); // + 1.0,1. ++
- XYCurve roccurve = ROC.materializeROC(9, positive, distances.iterator());
- System.out.println(roccurve);
+ XYCurve roccurve = ROC.materializeROC(new ROC.DBIDsTest(positive), new ROC.DistanceResultAdapter<>(distances.iter()));
+ // System.err.println(roccurve);
Assert.assertEquals("ROC curve too complex", 6, roccurve.size());
double auc = XYCurve.areaUnderCurve(roccurve);
diff --git a/test/de/lmu/ifi/dbs/elki/index/TestIndexStructures.java b/test/de/lmu/ifi/dbs/elki/index/TestIndexStructures.java
index 0b0b12d5..1623bcfa 100644
--- a/test/de/lmu/ifi/dbs/elki/index/TestIndexStructures.java
+++ b/test/de/lmu/ifi/dbs/elki/index/TestIndexStructures.java
@@ -33,6 +33,9 @@ import de.lmu.ifi.dbs.elki.data.DoubleVector;
import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.database.StaticArrayDatabase;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.LinearScanKNNQuery;
@@ -40,12 +43,8 @@ import de.lmu.ifi.dbs.elki.database.query.range.LinearScanRangeQuery;
import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.datasource.FileBasedDatabaseConnection;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultIter;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
-import de.lmu.ifi.dbs.elki.index.tree.TreeIndexFactory;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mtree.MTree;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mtree.MTreeFactory;
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query.DoubleDistanceMetricalIndexKNNQuery;
@@ -58,8 +57,8 @@ import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rstar.RStarTreeFacto
import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert.ApproximativeLeastOverlapInsertionStrategy;
import de.lmu.ifi.dbs.elki.index.vafile.PartialVAFile;
import de.lmu.ifi.dbs.elki.index.vafile.VAFile;
+import de.lmu.ifi.dbs.elki.persistent.AbstractPageFileFactory;
import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.ParameterException;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.ListParameterization;
/**
@@ -109,7 +108,7 @@ public class TestIndexStructures implements JUnit4Test {
public void testMetrical() {
ListParameterization metparams = new ListParameterization();
metparams.addParameter(StaticArrayDatabase.INDEX_ID, MTreeFactory.class);
- metparams.addParameter(TreeIndexFactory.PAGE_SIZE_ID, 100);
+ metparams.addParameter(AbstractPageFileFactory.Parameterizer.PAGE_SIZE_ID, 300);
testFileBasedDatabaseConnection(metparams, DoubleDistanceMetricalIndexKNNQuery.class, DoubleDistanceMetricalIndexRangeQuery.class);
}
@@ -120,7 +119,7 @@ public class TestIndexStructures implements JUnit4Test {
public void testRStarTree() {
ListParameterization spatparams = new ListParameterization();
spatparams.addParameter(StaticArrayDatabase.INDEX_ID, RStarTreeFactory.class);
- spatparams.addParameter(TreeIndexFactory.PAGE_SIZE_ID, 300);
+ spatparams.addParameter(AbstractPageFileFactory.Parameterizer.PAGE_SIZE_ID, 300);
testFileBasedDatabaseConnection(spatparams, DoubleDistanceRStarTreeKNNQuery.class, DoubleDistanceRStarTreeRangeQuery.class);
}
@@ -155,9 +154,9 @@ public class TestIndexStructures implements JUnit4Test {
public void testRStarTreeFast() {
ListParameterization spatparams = new ListParameterization();
spatparams.addParameter(StaticArrayDatabase.INDEX_ID, RStarTreeFactory.class);
- spatparams.addParameter(AbstractRStarTreeFactory.INSERTION_STRATEGY_ID, ApproximativeLeastOverlapInsertionStrategy.class);
+ spatparams.addParameter(AbstractRStarTreeFactory.Parameterizer.INSERTION_STRATEGY_ID, ApproximativeLeastOverlapInsertionStrategy.class);
spatparams.addParameter(ApproximativeLeastOverlapInsertionStrategy.Parameterizer.INSERTION_CANDIDATES_ID, 1);
- spatparams.addParameter(TreeIndexFactory.PAGE_SIZE_ID, 300);
+ spatparams.addParameter(AbstractPageFileFactory.Parameterizer.PAGE_SIZE_ID, 300);
testFileBasedDatabaseConnection(spatparams, DoubleDistanceRStarTreeKNNQuery.class, DoubleDistanceRStarTreeRangeQuery.class);
}
@@ -197,12 +196,12 @@ public class TestIndexStructures implements JUnit4Test {
DoubleVector dv = new DoubleVector(querypoint);
KNNQuery<DoubleVector, DoubleDistance> knnq = db.getKNNQuery(dist, k);
assertTrue("Returned knn query is not of expected class.", expectKNNQuery.isAssignableFrom(knnq.getClass()));
- KNNResult<DoubleDistance> ids = knnq.getKNNForObject(dv, k);
+ KNNList<DoubleDistance> ids = knnq.getKNNForObject(dv, k);
assertEquals("Result size does not match expectation!", shouldd.length, ids.size());
// verify that the neighbors match.
int i = 0;
- for(DistanceDBIDResultIter<DoubleDistance> res = ids.iter(); res.valid(); res.advance(), i++) {
+ for (DistanceDBIDListIter<DoubleDistance> res = ids.iter(); res.valid(); res.advance(), i++) {
// Verify distance
assertEquals("Expected distance doesn't match.", shouldd[i], res.getDistance().doubleValue());
// verify vector
@@ -216,12 +215,12 @@ public class TestIndexStructures implements JUnit4Test {
DoubleVector dv = new DoubleVector(querypoint);
RangeQuery<DoubleVector, DoubleDistance> rangeq = db.getRangeQuery(dist, eps);
assertTrue("Returned range query is not of expected class.", expectRangeQuery.isAssignableFrom(rangeq.getClass()));
- DistanceDBIDResult<DoubleDistance> ids = rangeq.getRangeForObject(dv, eps);
+ DistanceDBIDList<DoubleDistance> ids = rangeq.getRangeForObject(dv, eps);
assertEquals("Result size does not match expectation!", shouldd.length, ids.size());
// verify that the neighbors match.
int i = 0;
- for(DistanceDBIDResultIter<DoubleDistance> res = ids.iter(); res.valid(); res.advance(), i++) {
+ for (DistanceDBIDListIter<DoubleDistance> res = ids.iter(); res.valid(); res.advance(), i++) {
// Verify distance
assertEquals("Expected distance doesn't match.", shouldd[i], res.getDistance().doubleValue());
// verify vector
@@ -231,4 +230,4 @@ public class TestIndexStructures implements JUnit4Test {
}
}
}
-} \ No newline at end of file
+}
diff --git a/test/de/lmu/ifi/dbs/elki/index/preprocessed/TestMaterializedKNNAndRKNNPreprocessor.java b/test/de/lmu/ifi/dbs/elki/index/preprocessed/TestMaterializedKNNAndRKNNPreprocessor.java
index 3d6e1ba7..68202213 100644
--- a/test/de/lmu/ifi/dbs/elki/index/preprocessed/TestMaterializedKNNAndRKNNPreprocessor.java
+++ b/test/de/lmu/ifi/dbs/elki/index/preprocessed/TestMaterializedKNNAndRKNNPreprocessor.java
@@ -42,6 +42,9 @@ import de.lmu.ifi.dbs.elki.database.UpdatableDatabase;
import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.LinearScanKNNQuery;
@@ -51,10 +54,7 @@ import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.database.relation.RelationUtil;
import de.lmu.ifi.dbs.elki.datasource.FileBasedDatabaseConnection;
import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultIter;
-import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNAndRKNNPreprocessor;
import de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNPreprocessor;
@@ -110,14 +110,14 @@ public class TestMaterializedKNNAndRKNNPreprocessor implements JUnit4Test {
assertEquals("Data set size doesn't match parameters.", shoulds, rep.size());
// get linear queries
- LinearScanKNNQuery<DoubleVector, DoubleDistance> lin_knn_query = new LinearScanKNNQuery<DoubleVector, DoubleDistance>(distanceQuery);
- LinearScanRKNNQuery<DoubleVector, DoubleDistance> lin_rknn_query = new LinearScanRKNNQuery<DoubleVector, DoubleDistance>(distanceQuery, lin_knn_query, k);
+ LinearScanKNNQuery<DoubleVector, DoubleDistance> lin_knn_query = new LinearScanKNNQuery<>(distanceQuery);
+ LinearScanRKNNQuery<DoubleVector, DoubleDistance> lin_rknn_query = new LinearScanRKNNQuery<>(distanceQuery, lin_knn_query, k);
// get preprocessed queries
ListParameterization config = new ListParameterization();
config.addParameter(MaterializeKNNPreprocessor.Factory.DISTANCE_FUNCTION_ID, distanceQuery.getDistanceFunction());
config.addParameter(MaterializeKNNPreprocessor.Factory.K_ID, k);
- MaterializeKNNAndRKNNPreprocessor<DoubleVector, DoubleDistance> preproc = new MaterializeKNNAndRKNNPreprocessor<DoubleVector, DoubleDistance>(rep, distanceQuery.getDistanceFunction(), k);
+ MaterializeKNNAndRKNNPreprocessor<DoubleVector, DoubleDistance> preproc = new MaterializeKNNAndRKNNPreprocessor<>(rep, distanceQuery.getDistanceFunction(), k);
KNNQuery<DoubleVector, DoubleDistance> preproc_knn_query = preproc.getKNNQuery(distanceQuery, k);
RKNNQuery<DoubleVector, DoubleDistance> preproc_rknn_query = preproc.getRKNNQuery(distanceQuery);
// add as index
@@ -132,7 +132,7 @@ public class TestMaterializedKNNAndRKNNPreprocessor implements JUnit4Test {
testKNNQueries(rep, lin_knn_query, preproc_knn_query, k / 2);
// insert new objects
- List<DoubleVector> insertions = new ArrayList<DoubleVector>();
+ List<DoubleVector> insertions = new ArrayList<>();
NumberVector.Factory<DoubleVector, ?> o = RelationUtil.getNumberVectorFactory(rep);
int dim = RelationUtil.dimensionality(rep);
Random random = new Random(seed);
@@ -159,12 +159,12 @@ public class TestMaterializedKNNAndRKNNPreprocessor implements JUnit4Test {
private void testKNNQueries(Relation<DoubleVector> rep, KNNQuery<DoubleVector, DoubleDistance> lin_knn_query, KNNQuery<DoubleVector, DoubleDistance> preproc_knn_query, int k) {
ArrayDBIDs sample = DBIDUtil.ensureArray(rep.getDBIDs());
- List<? extends KNNResult<DoubleDistance>> lin_knn_ids = lin_knn_query.getKNNForBulkDBIDs(sample, k);
- List<? extends KNNResult<DoubleDistance>> preproc_knn_ids = preproc_knn_query.getKNNForBulkDBIDs(sample, k);
+ List<? extends KNNList<DoubleDistance>> lin_knn_ids = lin_knn_query.getKNNForBulkDBIDs(sample, k);
+ List<? extends KNNList<DoubleDistance>> preproc_knn_ids = preproc_knn_query.getKNNForBulkDBIDs(sample, k);
for(int i = 0; i < rep.size(); i++) {
- KNNResult<DoubleDistance> lin_knn = lin_knn_ids.get(i);
- KNNResult<DoubleDistance> pre_knn = preproc_knn_ids.get(i);
- DistanceDBIDResultIter<DoubleDistance> lin = lin_knn.iter(), pre = pre_knn.iter();
+ KNNList<DoubleDistance> lin_knn = lin_knn_ids.get(i);
+ KNNList<DoubleDistance> pre_knn = preproc_knn_ids.get(i);
+ DistanceDBIDListIter<DoubleDistance> lin = lin_knn.iter(), pre = pre_knn.iter();
for(; lin.valid() && pre.valid(); lin.advance(), pre.advance(), i++) {
if(!DBIDUtil.equal(lin, pre) && lin.getDistance().compareTo(pre.getDistance()) != 0) {
System.out.print("LIN kNN #" + i + " " + lin.getDistancePair());
@@ -185,13 +185,13 @@ public class TestMaterializedKNNAndRKNNPreprocessor implements JUnit4Test {
private void testRKNNQueries(Relation<DoubleVector> rep, RKNNQuery<DoubleVector, DoubleDistance> lin_rknn_query, RKNNQuery<DoubleVector, DoubleDistance> preproc_rknn_query, int k) {
ArrayDBIDs sample = DBIDUtil.ensureArray(rep.getDBIDs());
- List<? extends DistanceDBIDResult<DoubleDistance>> lin_rknn_ids = lin_rknn_query.getRKNNForBulkDBIDs(sample, k);
- List<? extends DistanceDBIDResult<DoubleDistance>> preproc_rknn_ids = preproc_rknn_query.getRKNNForBulkDBIDs(sample, k);
+ List<? extends DistanceDBIDList<DoubleDistance>> lin_rknn_ids = lin_rknn_query.getRKNNForBulkDBIDs(sample, k);
+ List<? extends DistanceDBIDList<DoubleDistance>> preproc_rknn_ids = preproc_rknn_query.getRKNNForBulkDBIDs(sample, k);
for(int i = 0; i < rep.size(); i++) {
- DistanceDBIDResult<DoubleDistance> lin_rknn = lin_rknn_ids.get(i);
- DistanceDBIDResult<DoubleDistance> pre_rknn = preproc_rknn_ids.get(i);
+ DistanceDBIDList<DoubleDistance> lin_rknn = lin_rknn_ids.get(i);
+ DistanceDBIDList<DoubleDistance> pre_rknn = preproc_rknn_ids.get(i);
- DistanceDBIDResultIter<DoubleDistance> lin = lin_rknn.iter(), pre = pre_rknn.iter();
+ DistanceDBIDListIter<DoubleDistance> lin = lin_rknn.iter(), pre = pre_rknn.iter();
for(; lin.valid() && pre.valid(); lin.advance(), pre.advance(), i++) {
if(!DBIDUtil.equal(lin, pre) || lin.getDistance().compareTo(pre.getDistance()) != 0) {
System.out.print("LIN RkNN #" + i + " " + lin);
diff --git a/test/de/lmu/ifi/dbs/elki/logging/TestOutputStreamLogger.java b/test/de/lmu/ifi/dbs/elki/logging/TestOutputStreamLogger.java
index 1ae0e71d..5742cb2d 100644
--- a/test/de/lmu/ifi/dbs/elki/logging/TestOutputStreamLogger.java
+++ b/test/de/lmu/ifi/dbs/elki/logging/TestOutputStreamLogger.java
@@ -57,5 +57,6 @@ public class TestOutputStreamLogger implements JUnit4Test {
wri.write("Test.");
String should = "Test." + OutputStreamLogger.NEWLINE + "\r123\r \r23\r \r3" + OutputStreamLogger.NEWLINE + "Test.";
assertEquals("Output doesn't match requirements.", should, buf.toString());
+ wri.close();
}
}
diff --git a/test/de/lmu/ifi/dbs/elki/math/TestKernelDensityFitting.java b/test/de/lmu/ifi/dbs/elki/math/TestKernelDensityFitting.java
index 86058abe..795b7c94 100644
--- a/test/de/lmu/ifi/dbs/elki/math/TestKernelDensityFitting.java
+++ b/test/de/lmu/ifi/dbs/elki/math/TestKernelDensityFitting.java
@@ -40,9 +40,9 @@ import de.lmu.ifi.dbs.elki.datasource.FileBasedDatabaseConnection;
import de.lmu.ifi.dbs.elki.math.linearalgebra.fitting.FittingFunction;
import de.lmu.ifi.dbs.elki.math.linearalgebra.fitting.GaussianFittingFunction;
import de.lmu.ifi.dbs.elki.math.linearalgebra.fitting.LevenbergMarquardtMethod;
-import de.lmu.ifi.dbs.elki.math.statistics.GaussianKernelDensityFunction;
import de.lmu.ifi.dbs.elki.math.statistics.KernelDensityEstimator;
import de.lmu.ifi.dbs.elki.math.statistics.distribution.NormalDistribution;
+import de.lmu.ifi.dbs.elki.math.statistics.kernelfunctions.GaussianKernelDensityFunction;
import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.ParameterException;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.ListParameterization;
@@ -148,9 +148,9 @@ public class TestKernelDensityFitting implements JUnit4Test {
}
private double[] run(double[] data, double[] params) {
- FittingFunction func = new GaussianFittingFunction();
+ FittingFunction func = GaussianFittingFunction.STATIC;
boolean[] dofit = { true, true, true };
- KernelDensityEstimator de = new KernelDensityEstimator(data, GaussianKernelDensityFunction.KERNEL);
+ KernelDensityEstimator de = new KernelDensityEstimator(data, GaussianKernelDensityFunction.KERNEL, 1e-10);
LevenbergMarquardtMethod fit = new LevenbergMarquardtMethod(func, params, dofit, data, de.getDensity(), de.getVariance());
// for(int i = 0; i < 100; i++) {
// fit.iterate();
diff --git a/test/de/lmu/ifi/dbs/elki/math/TestLevenbergMarquardtGaussianFitting.java b/test/de/lmu/ifi/dbs/elki/math/TestLevenbergMarquardtGaussianFitting.java
index 54376c52..039b7179 100644
--- a/test/de/lmu/ifi/dbs/elki/math/TestLevenbergMarquardtGaussianFitting.java
+++ b/test/de/lmu/ifi/dbs/elki/math/TestLevenbergMarquardtGaussianFitting.java
@@ -51,20 +51,19 @@ public class TestLevenbergMarquardtGaussianFitting implements JUnit4Test {
double[] testy = { 0.25319163934, 0.210993032783, 0.26122946916, 0.301418618261, 0.309456448082, 0.319503735357, 0.327541565177, 0.285342958621, 0.371749629189, 0.345626682273, 0.357683427004, 0.343617224818, 0.365721256824, 0.363711799369, 0.39586311865, 0.389834746285, 0.456146842302, 0.434042810296, 0.39586311865, 0.40390094847, 0.442080640117, 0.375768544099, 0.355673969549, 0.373759086644, 0.39586311865, 0.371749629189, 0.345626682273, 0.361702341914, 0.381796916465, 0.357683427004, 0.405910405925, 0.353664512093, 0.349645597183, 0.267257841525, 0.263238926615, 0.313475362992, 0.243144352064, 0.25721055425, 0.221040320058 };
double mean = 0.122895805963;
double stddev = 0.542856090502;
- double stddevq = stddev * Math.sqrt(2);
double[] s = new double[testx.length];
for(int i = 0; i < testx.length; i++) {
s[i] = 1.0;
}
- double[] params = { mean, stddevq, 1 };
+ double[] params = { mean, stddev, 1 };
boolean[] dofit = { true, true, false };
- LevenbergMarquardtMethod fit = new LevenbergMarquardtMethod(new GaussianFittingFunction(), params, dofit, testx, testy, s);
+ LevenbergMarquardtMethod fit = new LevenbergMarquardtMethod(GaussianFittingFunction.STATIC, params, dofit, testx, testy, s);
for(int i = 0; i < 50; i++) {
fit.iterate();
}
double[] ps = fit.getParams();
// compare results.
- double[] should = { 0.152986763079, 1.00115077, 1 };
+ double[] should = { 0.1503920, 0.9788814, 1 };
assertEquals("Mean doesn't match.", should[0], ps[0], 0.0001);
assertEquals("Stddev doesn't match.", should[1], ps[1], 0.0001);
assertEquals("Scaling doesn't match.", should[2], ps[2], 0.0001);
@@ -80,20 +79,19 @@ public class TestLevenbergMarquardtGaussianFitting implements JUnit4Test {
double[] testy = { 0.40390094847, 0.442080640117, 0.375768544099, 0.355673969549, 0.373759086644, 0.39586311865, 0.371749629189, 0.345626682273, 0.361702341914, 0.381796916465, 0.357683427004, 0.405910405925, 0.353664512093, 0.349645597183, 0.267257841525, 0.263238926615, 0.313475362992, 0.243144352064, 0.25721055425, 0.221040320058, 0.247163266974, 0.219030862603, 0.267257841525, 0.186879543322, 0.184870085867, 0.160756596406, 0.202955202963, 0.132624192035, 0.150709309131, 0.158747138951, 0.100472872754, 0.124586362215, 0.116548532394, 0.132624192035, 0.078368840748, 0.0843972131132, 0.0582742661972, 0.0763593832929, 0.100472872754, 0.052245893832, 0.0562648087421, 0.0462175214668, 0.0321513192812, 0.0421986065566, 0.026122946916, 0.0321513192812, 0.0140662021855, 0.0120567447305, 0.0241134894609, 0.0140662021855, 0.0160756596406, 0.0140662021855, 0.00803782982031, 0.00602837236523, 0.0120567447305, 0.00803782982031, 0.00803782982031, 0.00602837236523, 0.0100472872754, 0.00200945745508 };
double mean = 0.951868470698;
double stddev = 0.571932920001;
- double stddevq = stddev * Math.sqrt(2);
double[] s = new double[testx.length];
for(int i = 0; i < testx.length; i++) {
s[i] = 1.0;
}
- double[] params = { mean, stddevq, 1 };
+ double[] params = { mean, stddev, 1 };
boolean[] dofit = { true, true, false };
- LevenbergMarquardtMethod fit = new LevenbergMarquardtMethod(new GaussianFittingFunction(), params, dofit, testx, testy, s);
+ LevenbergMarquardtMethod fit = new LevenbergMarquardtMethod(GaussianFittingFunction.STATIC, params, dofit, testx, testy, s);
for(int i = 0; i < 50; i++) {
fit.iterate();
}
double[] ps = fit.getParams();
// compare results.
- double[] should = { 0.1557811515, 1.006463733, 1 };
+ double[] should = { 0.132165, 1.027699, 1 };
assertEquals("Mean doesn't match.", should[0], ps[0], 0.0001);
assertEquals("Stddev doesn't match.", should[1], ps[1], 0.0001);
assertEquals("Scaling doesn't match.", should[2], ps[2], 0.0001);
diff --git a/test/de/lmu/ifi/dbs/elki/math/TestMathUtil.java b/test/de/lmu/ifi/dbs/elki/math/TestMathUtil.java
index 58441623..90112694 100644
--- a/test/de/lmu/ifi/dbs/elki/math/TestMathUtil.java
+++ b/test/de/lmu/ifi/dbs/elki/math/TestMathUtil.java
@@ -1,14 +1,5 @@
package de.lmu.ifi.dbs.elki.math;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.util.Random;
-
-import org.junit.Test;
-
-import de.lmu.ifi.dbs.elki.JUnit4Test;
-
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
@@ -32,8 +23,21 @@ import de.lmu.ifi.dbs.elki.JUnit4Test;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-public class TestMathUtil implements JUnit4Test {
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Random;
+
+import org.junit.Test;
+
+import de.lmu.ifi.dbs.elki.JUnit4Test;
+/**
+ * Unit test for some basic math functions.
+ *
+ * @author Erich Schubert
+ */
+public class TestMathUtil implements JUnit4Test {
@Test
public void testPearsonCorrelation() {
final int size = 1000;
diff --git a/test/de/lmu/ifi/dbs/elki/math/TestSlidingVariance.java b/test/de/lmu/ifi/dbs/elki/math/TestSlidingVariance.java
new file mode 100644
index 00000000..58824142
--- /dev/null
+++ b/test/de/lmu/ifi/dbs/elki/math/TestSlidingVariance.java
@@ -0,0 +1,68 @@
+package de.lmu.ifi.dbs.elki.math;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Random;
+
+import org.junit.Test;
+
+import de.lmu.ifi.dbs.elki.JUnit4Test;
+
+/**
+ * Unit test {@link MeanVariance} with negative weights.
+ *
+ * @author Erich Schubert
+ */
+public class TestSlidingVariance implements JUnit4Test {
+ /**
+ * Size of test data set.
+ */
+ private static final int SIZE = 100000;
+
+ /**
+ * Sliding window size.
+ */
+ private static final int WINDOWSIZE = 100;
+
+ @Test
+ public void testSlidingWindowVariance() {
+ MeanVariance mv = new MeanVariance();
+ MeanVariance mc = new MeanVariance();
+
+ Random r = new Random(0);
+ double[] data = new double[SIZE];
+ for(int i = 0; i < data.length; i++) {
+ data[i] = r.nextDouble();
+ }
+ // Arrays.sort(data);
+
+ // Pre-roll:
+ for(int i = 0; i < WINDOWSIZE; i++) {
+ mv.put(data[i]);
+ }
+ // Compare to window approach
+ for(int i = WINDOWSIZE; i < data.length; i++) {
+ mv.put(data[i - WINDOWSIZE], -1.); // Remove
+ mv.put(data[i]);
+
+ mc.reset(); // Reset statistics
+ for(int j = i + 1 - WINDOWSIZE; j <= i; j++) {
+ mc.put(data[j]);
+ }
+ // Fully manual statistics, exact two-pass algorithm:
+ double mean = 0.0;
+ for(int j = i + 1 - WINDOWSIZE; j <= i; j++) {
+ mean += data[j];
+ }
+ mean /= WINDOWSIZE;
+ double var = 0.0;
+ for(int j = i + 1 - WINDOWSIZE; j <= i; j++) {
+ double v = data[j] - mean;
+ var += v * v;
+ }
+ var /= (WINDOWSIZE - 1);
+ assertEquals("Variance does not agree at i=" + i, mv.getSampleVariance(), mc.getSampleVariance(), 1e-14);
+ assertEquals("Variance does not agree at i=" + i, mv.getSampleVariance(), var, 1e-14);
+ }
+ }
+}
diff --git a/test/de/lmu/ifi/dbs/elki/math/TestStatisticalMoments.java b/test/de/lmu/ifi/dbs/elki/math/TestStatisticalMoments.java
new file mode 100644
index 00000000..fe63b707
--- /dev/null
+++ b/test/de/lmu/ifi/dbs/elki/math/TestStatisticalMoments.java
@@ -0,0 +1,120 @@
+package de.lmu.ifi.dbs.elki.math;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2012
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+import de.lmu.ifi.dbs.elki.JUnit4Test;
+
+/**
+ * Unit test to check our statistical moments class for correctness.
+ *
+ * @author Erich Schubert
+ */
+public class TestStatisticalMoments implements JUnit4Test {
+ @Test
+ public void testTiny() {
+ double[] data = new double[] { 222, 1122, 45444 };
+ StatisticalMoments m = new StatisticalMoments();
+ for (double d : data) {
+ m.put(d);
+ }
+ // Validated with R package "e1071" and scipy.
+ // Looks as we might be closer to scipys result!
+ // skewness(c(222,1122,45444), type = 1) = 0.70614285367114104
+ // scipy.stats.skew([222, 1122, 45444], bias=True) = 0.7061428536711412
+ assertEquals("Naive skewness does not match.", 0.70614285367114104, m.getNaiveSkewness(), 1e-15);
+ // skewness(c(222,1122,45444), type = 2) = 1.7296896770071024
+ // scipy.stats.skew([222, 1122, 45444], bias=False) = 1.7296896770071026
+ assertEquals("Sample skewness does not match.", 1.7296896770071024, m.getSampleSkewness(), 1e-15);
+ // Type 3 skewness is not in ELKI.
+
+ // kurtosis(c(222,1122,45444), type = 1) = -1.5
+ assertEquals("Naive kurtosis does not match.", -1.5, m.getNaiveExcessKurtosis(), 1e-15);
+ assertEquals("Naive kurtosis does not match.", -1.5 + 3.0, m.getNaiveKurtosis(), 1e-15);
+ // type = 2 needs 4 observations - so do we!
+ }
+
+ @Test
+ public void testGamma() {
+ double[] data = new double[] { // 100 Gamma(5,5) distributed random values.
+ 0.6388530607016163, 0.9782442336324599, 0.8882176966052615, 0.7849646645745156, 2.0633275427120497, //
+ 0.9545195282320902, 1.092390620469477, 0.7258265676258062, 1.378026049091643, 0.8310918468931533,//
+ 0.9495339766440013, 0.7126363476416752, 0.5608700366395489, 0.31408795273142415, 1.4909322345449254, //
+ 0.46625313007571856, 1.1870054487101156, 0.7640843133327799, 2.235582041645692, 1.5812487824715005, //
+ 1.512895069952923, 0.606517358771931, 1.1961880366469766, 0.7854465499137, 0.8084781536051177, //
+ 0.7615405607968533, 1.6614435713861262, 1.4869842072109933, 0.43465864880894045, 2.007341464773332, //
+ 0.33478515273215137, 1.9093706181977907, 0.3539177300096471, 0.44888559667524086, 1.0249621186169293, //
+ 0.38784905783431306, 0.7632290555534638, 0.9941038353388855, 0.6358745449186729, 0.5750658437507069, //
+ 0.9565742499910938, 1.2221328658541637, 0.9389920544737386, 1.21461175894598, 1.5713316877580166, //
+ 0.3470088915002977, 0.4419291224056868, 2.343465732285217, 1.0612049261527454, 0.9960347794653911, //
+ 0.5433216826433932, 1.006345176861023, 1.034059277904943, 0.7199916430119295, 1.218878192200847, //
+ 1.0023101563986212, 1.093784991451296, 0.9748868952634213, 1.81732410812918, 0.5259404003069172, //
+ 1.5179842038671814, 0.7461497981977685, 0.47530253061596, 0.810558795121139, 0.9383514512691828, //
+ 0.42371144806092004, 0.8698616597894346, 0.4541860955288436, 0.3136304450065802, 0.8799371863836344, //
+ 0.9854734113277808, 0.8651302802119106, 0.7981146204118504, 0.5255964404563404, 0.8570668629471919, //
+ 1.0294303406520284, 1.4592029352371467, 1.1034285928922425, 1.0042662401564635, 0.6443339212869743, //
+ 1.4096313764251664, 0.9328112988095885, 2.0874718257265483, 1.063702918067901, 0.5885221900074733, //
+ 1.216856018361022, 0.5572986786142953, 0.6620626132872955, 0.7357210048560157, 1.5174141129183254, //
+ 1.2293542801457167, 1.490026433254134, 1.4307462549666328, 1.381520418446136, 0.48400651328811123, //
+ 0.8448303085270435, 1.1514319532981445, 0.8944580168473978, 0.5003052782124537, 1.1457096934062219 };
+ StatisticalMoments m = new StatisticalMoments();
+ for (double d : data) {
+ m.put(d);
+ }
+ // Validated with R package "e1071" and scipy:
+ // Looks as we might be closer to scipys result!
+ // skewness(data, type = 1) = 0.8553563631726689
+ // scipy.stats.skew(data, bias=True) = 0.8553563631726712
+ assertEquals("Naive skewness does not match.", 0.8553563631726689, m.getNaiveSkewness(), 1e-14);
+ // skewness(data, type = 2) = 0.868437587353074
+ // scipy.stats.skew(data, bias=False) = 0.868437587353077
+ assertEquals("Sample skewness does not match.", 0.868437587353074, m.getSampleSkewness(), 1e-14);
+ // Type 3 skewness is not in ELKI.
+
+ // kurtosis(data, type = 1) = 0.4778717586207377
+ // scipy.stats.kurtosis(data, fisher=True) = 0.4778717586207377
+ assertEquals("Naive kurtosis does not match.", 0.4778717586207377, m.getNaiveExcessKurtosis(), 1e-14);
+ assertEquals("Naive kurtosis does not match.", 0.4778717586207377 + 3.0, m.getNaiveKurtosis(), 1e-14);
+ // kurtosis(data, type = 2) = 0.565141985530060675
+ // scipy.stats.kurtosis(data, fisher=True, bias=False) = 0.5651419855300603
+ // scipy.stats.kurtosis(data, fisher=True, bias=False) = 0.5651419855300603
+ // scipy.stats.kurtosis(data, fisher=False, bias=False) = 3.5651419855300603
+ assertEquals("Sample kurtosis does not match.", 0.565141985530060675, m.getSampleExcessKurtosis(), 1e-14);
+ assertEquals("Sample kurtosis does not match.", 3.565141985530060675, m.getSampleKurtosis(), 1e-14);
+
+ // numpy.array(data).mean() = 0.98342960290360215
+ assertEquals("Mean does not match.", 0.98342960290360215, m.getMean(), 1e-15);
+ // numpy.array(data).std() = 0.44953213330440578
+ assertEquals("Naive stddev does not match.", 0.44953213330440578, m.getNaiveStddev(), 1e-15);
+ // numpy.array(data).std(ddof=1) = 0.45179679314507293
+ assertEquals("Sample stddev does not match.", 0.45179679314507293, m.getSampleStddev(), 1e-15);
+ // numpy.array(data).min() = 0.31363044500658022
+ assertEquals("Min does not match.", 0.31363044500658022, m.getMin(), 1e-16);
+ // numpy.array(data).max() = 2.343465732285217
+ assertEquals("Max does not match.", 2.343465732285217, m.getMax(), 1e-16);
+ }
+}
diff --git a/test/de/lmu/ifi/dbs/elki/math/geodesy/TestEarthModels.java b/test/de/lmu/ifi/dbs/elki/math/geodesy/TestEarthModels.java
new file mode 100644
index 00000000..62628512
--- /dev/null
+++ b/test/de/lmu/ifi/dbs/elki/math/geodesy/TestEarthModels.java
@@ -0,0 +1,385 @@
+package de.lmu.ifi.dbs.elki.math.geodesy;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import org.junit.Test;
+
+import de.lmu.ifi.dbs.elki.JUnit4Test;
+
+/**
+ * Unit test that cross-validates some distance computations with different
+ * implementations. Note that it is common to see some difference in these
+ * computations, unfortunately - even within R: "sp", "SDMTools" and "geosphere"
+ * give different values. But in the end, it's always just an approximation.
+ *
+ * @author Erich Schubert
+ */
+public class TestEarthModels implements JUnit4Test {
+ // New York City
+ final double[] NEW_YORK = new double[] { 40.67, -73.94 };
+
+ // Munich City
+ final double[] MUNICH = new double[] { 48.133333, 11.566667 };
+
+ // Close to Munich city.
+ final double[] MUNICH_AIRPORT = new double[] { 48.353889, 11.786111 };
+
+ // Beijing
+ final double[] BEIJING = new double[] { 39.913889, 116.391667 };
+
+ // Sydney
+ final double[] SYDNEY = new double[] { -33.859972, 151.211111 };
+
+ // South pole
+ final double[] SOUTH = new double[] { -90., 123. };
+
+ // North pole
+ final double[] NORTH = new double[] { 90., -11. };
+
+ // Null
+ final double[] NULL = new double[] { 0., 0. };
+
+ // Antipodal of New York
+ final double[] ANEW_YORK = new double[] { -40.67, 180. + -73.94 };
+
+ // The full data set
+ final double[][] DATA = new double[][] { NEW_YORK, MUNICH, MUNICH_AIRPORT, BEIJING, SYDNEY, SOUTH, NORTH, ANEW_YORK, NULL };
+
+ // Names, for reporting
+ final String[] NAMES = new String[] { "New York", "Munich", "Munich Airport", "Beijing", "Sydney", "South Pole", "North Pole", "AnitpodalNY", "Null" };
+
+ // Distance matrix, as computed by R "sp" package.
+ final double[][] R_SP_WGS84 = new double[][] { //
+ { 0.00000000e+00, 6.50366148e+06, 6.50686263e+06, //
+ 1.10191059e+07, 1.59817953e+07, 1.44857385e+07, //
+ 5.49643716e+06, 2.00089752e+07, 8.65713703e+06, //
+ }, //
+ { 6.50366148e+06, 0.00000000e+00, 2.94317181e+04, //
+ 7.77130051e+06, 1.63129394e+07, 1.53127242e+07, //
+ 4.66770838e+06, 1.34974501e+07, 5.44172321e+06, //
+ }, //
+ { 6.50686263e+06, 2.94317181e+04, 0.00000000e+00, //
+ 7.74340170e+06, 1.62922795e+07, 1.53371802e+07, //
+ 4.64319863e+06, 1.34940877e+07, 5.46970119e+06, //
+ }, //
+ { 1.10191059e+07, 7.77130051e+06, 7.74340170e+06, //
+ 0.00000000e+00, 8.90595105e+06, 1.44020175e+07, //
+ 5.58032509e+06, 8.97021429e+06, 1.22298940e+07, //
+ }, //
+ { 1.59817953e+07, 1.63129394e+07, 1.62922795e+07, //
+ 8.90595105e+06, 0.00000000e+00, 6.25152406e+06, //
+ 1.37320772e+07, 4.03034506e+06, 1.52087327e+07, //
+ }, //
+ { 1.44857385e+07, 1.53127242e+07, 1.53371802e+07, //
+ 1.44020175e+07, 6.25152406e+06, 0.00000000e+00, //
+ 1.99703264e+07, 5.49643716e+06, 9.99356093e+06, //
+ }, //
+ { 5.49643716e+06, 4.66770838e+06, 4.64319863e+06, //
+ 5.58032509e+06, 1.37320772e+07, 1.99703264e+07, //
+ 0.00000000e+00, 1.44857385e+07, 9.99356093e+06, //
+ }, //
+ { 2.00089752e+07, 1.34974501e+07, 1.34940877e+07, //
+ 8.97021429e+06, 4.03034506e+06, 5.49643716e+06, //
+ 1.44857385e+07, 0.00000000e+00, 1.13581966e+07, //
+ }, //
+ { 8.65713703e+06, 5.44172321e+06, 5.46970119e+06, //
+ 1.22298940e+07, 1.52087327e+07, 9.99356093e+06, //
+ 9.99356093e+06, 1.13581966e+07, 0.00000000e+00, //
+ }, //
+ };
+
+ // Distance matrix, as computed by R "SDMTools" with avoiding segfaults
+ final double[][] SDM_WGS84 = new double[][] { //
+ { 0.00000000e+00, 6.49607649e+06, 6.49934560e+06, //
+ 1.10186899e+07, 1.59618991e+07, 1.45058923e+07, //
+ 5.49803918e+06, 1.99845542e+07, 8.64487707e+06, //
+ }, //
+ { 6.49607649e+06, 0.00000000e+00, 2.94333400e+04, //
+ 7.76413413e+06, 1.63019586e+07, 1.53352188e+07, //
+ 4.66871262e+06, 1.34959988e+07, 5.44849943e+06, //
+ }, //
+ { 6.49934560e+06, 2.94333400e+04, 0.00000000e+00, //
+ 7.73629144e+06, 1.62815962e+07, 1.53597436e+07, //
+ 4.64418788e+06, 1.34928316e+07, 5.47647977e+06, //
+ }, //
+ { 1.10186899e+07, 7.76413413e+06, 7.73629144e+06, //
+ 0.00000000e+00, 8.91481946e+06, 1.44219335e+07, //
+ 5.58199793e+06, 8.98486478e+06, 1.22110932e+07, //
+ }, //
+ { 1.59618991e+07, 1.63019586e+07, 1.62815962e+07, //
+ 8.91481946e+06, 0.00000000e+00, 6.25383635e+06, //
+ 1.37500951e+07, 4.02274801e+06, 1.51936337e+07, //
+ }, //
+ { 1.45058923e+07, 1.53352188e+07, 1.53597436e+07, //
+ 1.44219335e+07, 6.25383635e+06, 0.00000000e+00, //
+ 2.00039315e+07, 5.49803918e+06, 1.00019657e+07, //
+ }, //
+ { 5.49803918e+06, 4.66871262e+06, 4.64418788e+06, //
+ 5.58199793e+06, 1.37500951e+07, 2.00039315e+07, //
+ 0.00000000e+00, 1.45058923e+07, 1.00019657e+07, //
+ }, //
+ { 1.99845542e+07, 1.34959988e+07, 1.34928316e+07, //
+ 8.98486478e+06, 4.02274801e+06, 5.49803918e+06, //
+ 1.45058923e+07, 0.00000000e+00, 1.13403339e+07, //
+ }, //
+ { 8.64487707e+06, 5.44849943e+06, 5.47647977e+06, //
+ 1.22110932e+07, 1.51936337e+07, 1.00019657e+07, //
+ 1.00019657e+07, 1.13403339e+07, 0.00000000e+00, //
+ }, //
+ };
+
+ // Distance matrix, cosine distance in "geosphere" package:
+ final double[][] GEOSPHERE_COSINE = new double[][] { //
+ { 0.000000000000000e+00, 6.486356338365966e+06, 6.489535193201737e+06, //
+ 1.099371420315689e+07, 1.599344217645813e+07, 1.452986159024009e+07, //
+ 5.485253480114362e+06, 2.001511507035445e+07, 8.660734833379321e+06, //
+ }, //
+ { 6.486356338365966e+06, 0.000000000000000e+00, 2.941993519886598e+04, //
+ 7.750900176348899e+06, 1.632910711431917e+07, 1.535974752803661e+07, //
+ 4.655367542317842e+06, 1.352875873198849e+07, 5.467217714777914e+06, //
+ }, //
+ { 6.489535193201737e+06, 2.941993519886598e+04, 0.000000000000000e+00, //
+ 7.723050836613588e+06, 1.630864631433774e+07, 1.538427227092249e+07, //
+ 4.630842799431969e+06, 1.352557987715272e+07, 5.495190660363145e+06, //
+ }, //
+ { 1.099371420315689e+07, 7.750900176348899e+06, 7.723050836613588e+06, //
+ 0.000000000000000e+00, 8.948985711203361e+06, 1.444578576429031e+07, //
+ 5.569329306064145e+06, 9.021400867197569e+06, 1.222413440358347e+07, //
+ }, //
+ { 1.599344217645813e+07, 1.632910711431917e+07, 1.630864631433774e+07, //
+ 8.948985711203361e+06, 0.000000000000000e+00, 6.242495113738451e+06, //
+ 1.377261995661600e+07, 4.021672893896329e+06, 1.520028800598781e+07, //
+ }, //
+ { 1.452986159024009e+07, 1.535974752803661e+07, 1.538427227092249e+07, //
+ 1.444578576429031e+07, 6.242495113738451e+06, 0.000000000000000e+00, //
+ 2.001511507035445e+07, 5.485253480114362e+06, 1.000755753517723e+07, //
+ }, //
+ { 5.485253480114362e+06, 4.655367542317842e+06, 4.630842799431969e+06, //
+ 5.569329306064145e+06, 1.377261995661600e+07, 2.001511507035445e+07, //
+ 0.000000000000000e+00, 1.452986159024009e+07, 1.000755753517723e+07, //
+ }, //
+ { 2.001511507035445e+07, 1.352875873198849e+07, 1.352557987715272e+07, //
+ 9.021400867197569e+06, 4.021672893896329e+06, 5.485253480114362e+06, //
+ 1.452986159024009e+07, 0.000000000000000e+00, 1.135438023697513e+07, //
+ }, //
+ { 8.660734833379321e+06, 5.467217714777914e+06, 5.495190660363145e+06, //
+ 1.222413440358347e+07, 1.520028800598781e+07, 1.000755753517723e+07, //
+ 1.000755753517723e+07, 1.135438023697513e+07, 0.000000000000000e+00, //
+ }, //
+ };
+
+ // Distance matrix, cosine distance in "geosphere" package:
+ final double[][] GEOSPHERE_HAVERSINE = new double[][] { //
+ { 0.000000000000000e+00, 6.486356338365965e+06, 6.489535193201736e+06, //
+ 1.099371420315688e+07, 1.599344217645813e+07, 1.452986159024009e+07, //
+ 5.485253480114363e+06, 2.001511507035445e+07, 8.660734833379321e+06, //
+ }, //
+ { 6.486356338365965e+06, 0.000000000000000e+00, 2.941993519893691e+04, //
+ 7.750900176348901e+06, 1.632910711431917e+07, 1.535974752803662e+07, //
+ 4.655367542317841e+06, 1.352875873198849e+07, 5.467217714777914e+06, //
+ }, //
+ { 6.489535193201736e+06, 2.941993519893691e+04, 0.000000000000000e+00, //
+ 7.723050836613588e+06, 1.630864631433774e+07, 1.538427227092249e+07, //
+ 4.630842799431968e+06, 1.352557987715272e+07, 5.495190660363145e+06, //
+ }, //
+ { 1.099371420315688e+07, 7.750900176348901e+06, 7.723050836613588e+06, //
+ 0.000000000000000e+00, 8.948985711203359e+06, 1.444578576429031e+07, //
+ 5.569329306064145e+06, 9.021400867197569e+06, 1.222413440358347e+07, //
+ }, //
+ { 1.599344217645813e+07, 1.632910711431917e+07, 1.630864631433774e+07, //
+ 8.948985711203359e+06, 0.000000000000000e+00, 6.242495113738450e+06, //
+ 1.377261995661600e+07, 4.021672893896329e+06, 1.520028800598781e+07, //
+ }, //
+ { 1.452986159024009e+07, 1.535974752803662e+07, 1.538427227092249e+07, //
+ 1.444578576429031e+07, 6.242495113738450e+06, 0.000000000000000e+00, //
+ 2.001511507035445e+07, 5.485253480114363e+06, 1.000755753517723e+07, //
+ }, //
+ { 5.485253480114363e+06, 4.655367542317841e+06, 4.630842799431968e+06, //
+ 5.569329306064145e+06, 1.377261995661600e+07, 2.001511507035445e+07, //
+ 0.000000000000000e+00, 1.452986159024009e+07, 1.000755753517723e+07, //
+ }, //
+ { 2.001511507035445e+07, 1.352875873198849e+07, 1.352557987715272e+07, //
+ 9.021400867197569e+06, 4.021672893896329e+06, 5.485253480114363e+06, //
+ 1.452986159024009e+07, 0.000000000000000e+00, 1.135438023697513e+07, //
+ }, //
+ { 8.660734833379321e+06, 5.467217714777914e+06, 5.495190660363145e+06, //
+ 1.222413440358347e+07, 1.520028800598781e+07, 1.000755753517723e+07, //
+ 1.000755753517723e+07, 1.135438023697513e+07, 0.000000000000000e+00, //
+ }, //
+ };
+
+ // Distance matrix, cosine distance in "geosphere" package:
+ final double[][] GEOSPHERE_VINCENTY_SPHERE = new double[][] { //
+ { 0.000000000000000e+00, 6.486356338365965e+06, 6.489535193201737e+06, //
+ 1.099371420315689e+07, 1.599344217645813e+07, 1.452986159024009e+07, //
+ 5.485253480114362e+06, 2.001511507035445e+07, 8.660734833379321e+06, //
+ }, //
+ { 6.486356338365966e+06, 0.000000000000000e+00, 2.941993519893652e+04, //
+ 7.750900176348899e+06, 1.632910711431917e+07, 1.535974752803661e+07, //
+ 4.655367542317842e+06, 1.352875873198849e+07, 5.467217714777914e+06, //
+ }, //
+ { 6.489535193201737e+06, 2.941993519893681e+04, 0.000000000000000e+00, //
+ 7.723050836613588e+06, 1.630864631433774e+07, 1.538427227092249e+07, //
+ 4.630842799431969e+06, 1.352557987715272e+07, 5.495190660363145e+06, //
+ }, //
+ { 1.099371420315689e+07, 7.750900176348899e+06, 7.723050836613588e+06, //
+ 0.000000000000000e+00, 8.948985711203361e+06, 1.444578576429031e+07, //
+ 5.569329306064145e+06, 9.021400867197569e+06, 1.222413440358347e+07, //
+ }, //
+ { 1.599344217645813e+07, 1.632910711431917e+07, 1.630864631433774e+07, //
+ 8.948985711203361e+06, 0.000000000000000e+00, 6.242495113738451e+06, //
+ 1.377261995661600e+07, 4.021672893896329e+06, 1.520028800598781e+07, //
+ }, //
+ { 1.452986159024009e+07, 1.535974752803661e+07, 1.538427227092249e+07, //
+ 1.444578576429031e+07, 6.242495113738451e+06, 0.000000000000000e+00, //
+ 2.001511507035445e+07, 5.485253480114362e+06, 1.000755753517723e+07, //
+ }, //
+ { 5.485253480114362e+06, 4.655367542317842e+06, 4.630842799431969e+06, //
+ 5.569329306064145e+06, 1.377261995661600e+07, 2.001511507035445e+07, //
+ 0.000000000000000e+00, 1.452986159024009e+07, 1.000755753517723e+07, //
+ }, //
+ { 2.001511507035445e+07, 1.352875873198849e+07, 1.352557987715272e+07, //
+ 9.021400867197569e+06, 4.021672893896328e+06, 5.485253480114362e+06, //
+ 1.452986159024009e+07, 0.000000000000000e+00, 1.135438023697513e+07, //
+ }, //
+ { 8.660734833379321e+06, 5.467217714777914e+06, 5.495190660363145e+06, //
+ 1.222413440358347e+07, 1.520028800598781e+07, 1.000755753517723e+07, //
+ 1.000755753517723e+07, 1.135438023697513e+07, 0.000000000000000e+00, //
+ }, //
+ };
+
+ // Distance matrix, cosine distance in "geosphere" package:
+ final double[][] GEOSPHERE_VINCENTY_WGS84 = new double[][] { //
+ { 0.000000000000000e+00, 6.503767848090770e+06, 6.506974602807214e+06, //
+ 1.101910369872154e+07, 1.599270764104164e+07, 1.450589228275554e+07, //
+ 5.498039175797141e+06, Double.NaN, 8.661075093360968e+06, //
+ }, //
+ { 6.503767848090770e+06, 0.000000000000000e+00, 2.944678565227988e+04, //
+ 7.771413604903577e+06, 1.632562828361734e+07, 1.533521883690098e+07, //
+ 4.668712621651703e+06, 1.351202375815323e+07, 5.449076622477260e+06, //
+ }, //
+ { 6.506974602807214e+06, 2.944678565227961e+04, 0.000000000000000e+00, //
+ 7.743520548885130e+06, 1.630501450760304e+07, 1.535974357438163e+07, //
+ 4.644187884171052e+06, 1.350871506702908e+07, 5.477072159975932e+06, //
+ }, //
+ { 1.101910369872154e+07, 7.771413604903577e+06, 7.743520548885130e+06, //
+ 0.000000000000000e+00, 8.918923554119145e+06, 1.442193352759095e+07, //
+ 5.581997930961725e+06, 8.985204289439090e+06, 1.223306246456788e+07, //
+ }, //
+ { 1.599270764104165e+07, 1.632562828361734e+07, 1.630501450760304e+07, //
+ 8.918923554119145e+06, 0.000000000000000e+00, 6.253836350029638e+06, //
+ 1.375009510852304e+07, 4.030502513001381e+06, 1.521100587039189e+07, //
+ }, //
+ { 1.450589228275554e+07, 1.533521883690098e+07, 1.535974357438163e+07, //
+ 1.442193352759095e+07, 6.253836350029638e+06, 0.000000000000000e+00, //
+ 2.000393145855268e+07, 5.498039175797141e+06, 1.000196572927634e+07, //
+ }, //
+ { 5.498039175797141e+06, 4.668712621651703e+06, 4.644187884171051e+06, //
+ 5.581997930961725e+06, 1.375009510852304e+07, 2.000393145855268e+07, //
+ 0.000000000000000e+00, 1.450589228275554e+07, 1.000196572927634e+07, //
+ }, //
+ { Double.NaN, 1.351202375815323e+07, 1.350871506702908e+07, //
+ 8.985204289439090e+06, 4.030502513001381e+06, 5.498039175797141e+06, //
+ 1.450589228275554e+07, 0.000000000000000e+00, 1.136156548644650e+07, //
+ }, //
+ { 8.661075093360968e+06, 5.449076622477260e+06, 5.477072159975932e+06, //
+ 1.223306246456788e+07, 1.521100587039189e+07, 1.000196572927634e+07, //
+ 1.000196572927634e+07, 1.136156548644650e+07, 0.000000000000000e+00, //
+ }, //
+ };
+
+ @Test
+ public void testWGS84SpheroidEarth() {
+ // WGS84 Vincenty to WGS84 Haversine: .3% error on test set.
+ testEarthModel(WGS84SpheroidEarthModel.STATIC, R_SP_WGS84, .00316, 1e-12);
+ // WGS84 Vincenty to WGS84 Vincenty: also .2% error on test set.
+ testEarthModel(WGS84SpheroidEarthModel.STATIC, SDM_WGS84, .001936, 1e-12);
+ // WGS84 Vincenty to WGS84 Vincenty: with "geosphere" we have a high
+ // agreement.
+ testEarthModel(WGS84SpheroidEarthModel.STATIC, GEOSPHERE_VINCENTY_WGS84, 6.1763e-12, 1e-12);
+ }
+
+ @Test
+ public void testHaversineEarth() {
+ // Spherical Haversine to WGS84 Haversine: .6% error on test set.
+ testEarthModel(SphericalHaversineEarthModel.STATIC, R_SP_WGS84, .005674, 1e-12);
+ // Spherical Haversine to WGS84 Vincenty: .4% error on test set.
+ testEarthModel(SphericalHaversineEarthModel.STATIC, SDM_WGS84, .00405, 1e-12);
+ // WGS84 Vincenty to WGS84 Vincenty: with "geosphere" we have a high
+ // agreement.
+ testEarthModel(SphericalHaversineEarthModel.STATIC, GEOSPHERE_HAVERSINE, 6.662e-16, 1e-12);
+ }
+
+ @Test
+ public void testCosineEarth() {
+ // Spherical Cosine to WGS84 Haversine: 0% error on test set.
+ testEarthModel(SphericalCosineEarthModel.STATIC, R_SP_WGS84, .005674, 0.0);
+ // Spherical Cosine to WGS84 Vincenty: 0% error on test set.
+ testEarthModel(SphericalCosineEarthModel.STATIC, SDM_WGS84, .00405, 0.0);
+ // Spherical Cosine to Cosine: with "geosphere" we have a high agreement.
+ testEarthModel(SphericalCosineEarthModel.STATIC, GEOSPHERE_COSINE, 4.4409e-16, 1e-12);
+ }
+
+ @Test
+ public void testSphericalEarth() {
+ // Spherical Vincenty to WGS84 Haversine: .6% error on test set.
+ testEarthModel(SphericalVincentyEarthModel.STATIC, R_SP_WGS84, .005674, 1e-12);
+ // Spherical Vincenty to WGS84 Vincenty: .4% error on test set.
+ testEarthModel(SphericalVincentyEarthModel.STATIC, SDM_WGS84, .00405, 1e-12);
+ // Spherical Vincenty to Spherical Vincenty: with "geosphere" we have a high
+ // agreement.
+ testEarthModel(SphericalVincentyEarthModel.STATIC, GEOSPHERE_VINCENTY_SPHERE, 4.441e-16, 1e-12);
+ }
+
+ protected void testEarthModel(EarthModel model, final double[][] ref, final double relerror, final double abserror) {
+ double maxrel = 0.0, maxabs = 0.0;
+ for (int i = 0; i < DATA.length; i++) {
+ for (int j = i; j < DATA.length; j++) {
+ if (Double.isNaN(ref[i][j])) {
+ continue;
+ }
+ double d = model.distanceDeg(DATA[i][0], DATA[i][1], DATA[j][0], DATA[j][1]);
+ assertFalse("NaN in distance " + NAMES[i] + " to " + NAMES[j], Double.isNaN(d));
+ double test = (d > 0) ? (ref[i][j] / d) : (ref[i][j] - d + 1.0);
+ if (Math.abs(d - ref[i][j]) > abserror) {
+ if (Math.abs(test - 1.0) > relerror) {
+ assertEquals("Distances do not agree for " + NAMES[i] + " to " + NAMES[j] + " " + Math.abs(test - 1.0), ref[i][j], d, abserror);
+ }
+ if (Math.abs(test - 1.0) > maxrel) {
+ maxrel = Math.abs(test - 1.0);
+ }
+ } else {
+ if (Math.abs(ref[i][j] - d) > maxabs) {
+ maxabs = Math.abs(ref[i][j] - d);
+ }
+ }
+ }
+ }
+ assertEquals("Relative error bound not tight.", maxrel, relerror, 1e-3 * relerror + 1e-12);
+ assertEquals("Absolute error bound not tight.", maxabs, abserror, 1e-3 * abserror + 1e-12);
+ }
+}
diff --git a/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/AbstractDistributionTest.java b/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/AbstractDistributionTest.java
index fd975c15..3e613e4a 100644
--- a/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/AbstractDistributionTest.java
+++ b/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/AbstractDistributionTest.java
@@ -56,6 +56,9 @@ public class AbstractDistributionTest {
public void checkQuantile(Distribution d, double[] x, double[] expected, double err) {
int maxerrlev = Integer.MIN_VALUE;
for(int i = 0; i < x.length; i++) {
+ if (Double.isNaN(expected[i])) {
+ continue;
+ }
double val = d.quantile(x[i]);
if(val == expected[i]) {
continue;
diff --git a/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestBetaDistribution.java b/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestBetaDistribution.java
index f5efdce0..8746ea8b 100644
--- a/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestBetaDistribution.java
+++ b/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestBetaDistribution.java
@@ -3742,6 +3742,34 @@ public class TestBetaDistribution extends AbstractDistributionTest implements JU
9.57815943995298235691393529123160988092422485351562e-01, // 0.999900
};
+ public static final double[] SCIPY_BETA_QUANT_5000_10000 = { //
+ 3.19116827168564931582750432426109910011291503906250e-01, // 0.000100
+ 3.21504012263543914595942396772443316876888275146484e-01, // 0.001000
+ 3.24412567280382702072927258996060118079185485839844e-01, // 0.010000
+ 3.28405475125335688524330635118531063199043273925781e-01, // 0.100000
+ 3.30733175792180755792060153908096253871917724609375e-01, // 0.250000
+ 3.33325925743107376320040202699601650238037109375000e-01, // 0.500000
+ 3.35925416008591048999676331732189282774925231933594e-01, // 0.750000
+ 3.38270709107204470278418284578947350382804870605469e-01, // 0.900000
+ 3.42319458459627412594272755086421966552734375000000e-01, // 0.990000
+ 3.45289298443524073078947367321234196424484252929688e-01, // 0.999000
+ 3.47739889112688382866167557949665933847427368164062e-01, // 0.999900
+ };
+
+ public static final double[] GNUR_BETA_QUANT_5000_10000 = { //
+ 3.19116827168544670012551023319247178733348846435547e-01, // 0.000100
+ 3.21504012263524707737616381564293988049030303955078e-01, // 0.001000
+ 3.24412567280357388987965805426938459277153015136719e-01, // 0.010000
+ 3.28405475125304435746187436961918137967586517333984e-01, // 0.100000
+ 3.30733175792131905978976647020317614078521728515625e-01, // 0.250000
+ 3.33325925743034268133868636141414754092693328857422e-01, // 0.500000
+ 3.35925416008648558552351914840983226895332336425781e-01, // 0.750000
+ 3.38270709107251876801569778763223439455032348632812e-01, // 0.900000
+ 3.42319458459653502835351446265121921896934509277344e-01, // 0.990000
+ 3.45289298443550274342328521015588194131851196289062e-01, // 0.999000
+ 3.47739889112697708739574409264605492353439331054688e-01, // 0.999900
+ };
+
@Test
public void testPDF() {
checkPDF(new BetaDistribution(1., 1.), P_CDFPDF, SCIPY_BETA_PDF_1_1, 1e-15);
@@ -3879,6 +3907,7 @@ public class TestBetaDistribution extends AbstractDistributionTest implements JU
checkQuantile(new BetaDistribution(4., .5), P_QUANT, SCIPY_BETA_QUANT_4_05, 1e-15);
checkQuantile(new BetaDistribution(.1, .5), P_QUANT, SCIPY_BETA_QUANT_01_05, 1e-14);
checkQuantile(new BetaDistribution(.5, .5), P_QUANT, SCIPY_BETA_QUANT_05_05, 1e-14);
+ checkQuantile(new BetaDistribution(5000, 10000), P_QUANT, SCIPY_BETA_QUANT_5000_10000, 1e-13);
checkQuantile(new BetaDistribution(1., 1.), P_QUANT, GNUR_BETA_QUANT_1_1, 1e-15);
checkQuantile(new BetaDistribution(2., 1.), P_QUANT, GNUR_BETA_QUANT_2_1, 1e-15);
@@ -3905,5 +3934,6 @@ public class TestBetaDistribution extends AbstractDistributionTest implements JU
checkQuantile(new BetaDistribution(4., .5), P_QUANT, GNUR_BETA_QUANT_4_05, 1e-15);
checkQuantile(new BetaDistribution(.1, .5), P_QUANT, GNUR_BETA_QUANT_01_05, 1e-14);
checkQuantile(new BetaDistribution(.5, .5), P_QUANT, GNUR_BETA_QUANT_05_05, 1e-14);
+ checkQuantile(new BetaDistribution(5000, 10000), P_QUANT, GNUR_BETA_QUANT_5000_10000, 1e-13);
}
-} \ No newline at end of file
+}
diff --git a/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestExponentiallyModifiedGaussianDistribution.java b/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestExponentiallyModifiedGaussianDistribution.java
new file mode 100644
index 00000000..b50f1b07
--- /dev/null
+++ b/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestExponentiallyModifiedGaussianDistribution.java
@@ -0,0 +1,110 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2012
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import org.junit.Test;
+
+import de.lmu.ifi.dbs.elki.JUnit4Test;
+
+/**
+ * Unit test for the Normal distribution in ELKI.
+ *
+ * The reference values were computed using GNU R and SciPy.
+ *
+ * @author Erich Schubert
+ */
+public class TestExponentiallyModifiedGaussianDistribution extends AbstractDistributionTest implements JUnit4Test {
+ public static final double[] P_CDFPDF = { //
+ 1e-10, 1e-05, 0.1, 0.1234567, 0.2, 0.2718281828459045, 0.3, 0.3141592653589793, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.718281828459045, 3.141592653589793 //
+ };
+
+ public static final double[] GNUR_EXGAUSS_PDF_1_3_05 = { //
+ 8.47499457587128773861e-02, // 0.000000
+ 8.47501509788143592150e-02, // 0.000010
+ 8.67850439453969474402e-02, // 0.100000
+ 8.72571793172293719287e-02, // 0.123457
+ 8.87828480833198901978e-02, // 0.200000
+ 9.01922765508967883008e-02, // 0.271828
+ 9.07388117440050406826e-02, // 0.300000
+ 9.10121196636441698313e-02, // 0.314159
+ 9.26484294233294591869e-02, // 0.400000
+ 9.45072549271919470915e-02, // 0.500000
+ 9.63109197365605573804e-02, // 0.600000
+ 9.80551512388879997761e-02, // 0.700000
+ 9.97357907145074162880e-02, // 0.800000
+ 1.01348810967098704183e-01, // 0.900000
+ 1.02890333488697346964e-01, // 1.000000
+ 1.04356645052008520369e-01, // 1.100000
+ 1.05744213625967600767e-01, // 1.200000
+ 1.07049703514534744198e-01, // 1.300000
+ 1.08269989623592619021e-01, // 1.400000
+ 1.09402170766494374887e-01, // 1.500000
+ 1.10443581925230030483e-01, // 1.600000
+ 1.11391805391289122618e-01, // 1.700000
+ 1.12244680718037018186e-01, // 1.800000
+ 1.13000313424705317589e-01, // 1.900000
+ 1.13657082400870648731e-01, // 2.000000
+ 1.15388290567157214550e-01, // 2.718282
+ 1.13959589524871160449e-01, // 3.141593
+ };
+
+ public static final double[] GNUR_EXGAUSS_CDF_1_3_05 = { //
+ 1.99941448676917293836e-01, // 0.000000
+ 1.99942296168926059163e-01, // 0.000010
+ 2.08518489920253430325e-01, // 0.100000
+ 2.10559722098245583055e-01, // 0.123457
+ 2.17297214297385354875e-01, // 0.200000
+ 2.23725077521963966465e-01, // 0.271828
+ 2.26273664808885194288e-01, // 0.300000
+ 2.27560395746384258597e-01, // 0.314159
+ 2.35443431714238121666e-01, // 0.400000
+ 2.44801657534712419073e-01, // 0.500000
+ 2.54343043903264842687e-01, // 0.600000
+ 2.64061860245194957031e-01, // 0.700000
+ 2.73951954270620134935e-01, // 0.800000
+ 2.84006764248710408260e-01, // 0.900000
+ 2.94219333022605278316e-01, // 1.000000
+ 3.04582323713075031613e-01, // 1.100000
+ 3.15088037048429803200e-01, // 1.200000
+ 3.25728430247959499511e-01, // 1.300000
+ 3.36495137376428721243e-01, // 1.400000
+ 3.47379491077914881458e-01, // 1.500000
+ 3.58372545588643010017e-01, // 1.600000
+ 3.69465100920526368089e-01, // 1.700000
+ 3.80647728099900828358e-01, // 1.800000
+ 3.91910795339542039617e-01, // 1.900000
+ 4.03244495016495063666e-01, // 2.000000
+ 4.85820022244521587673e-01, // 2.718282
+ 5.34425248272120123616e-01, // 3.141593
+ };
+
+ @Test
+ public void testPDF() {
+ checkPDF(new ExponentiallyModifiedGaussianDistribution(1., 3., .5), P_CDFPDF, GNUR_EXGAUSS_PDF_1_3_05, 1e-13);
+ }
+
+ @Test
+ public void testCDF() {
+ checkCDF(new ExponentiallyModifiedGaussianDistribution(1., 3., .5), P_CDFPDF, GNUR_EXGAUSS_CDF_1_3_05, 1e-12);
+ }
+}
diff --git a/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestGammaDistribution.java b/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestGammaDistribution.java
index 8ec972f3..a0895298 100644
--- a/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestGammaDistribution.java
+++ b/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestGammaDistribution.java
@@ -29,6 +29,8 @@ import java.util.Random;
import org.junit.Test;
import de.lmu.ifi.dbs.elki.JUnit4Test;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.estimator.GammaChoiWetteEstimator;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayLikeUtil;
/**
* Unit test for the Gamma distribution in ELKI.
@@ -1294,11 +1296,22 @@ public class TestGammaDistribution extends AbstractDistributionTest implements J
public void testRandomAndEstimation() {
GammaDistribution g = new GammaDistribution(1.2345, 0.12345, new Random(0));
double[] data = new double[10000];
- for(int i = 0; i < data.length; i++) {
+ for (int i = 0; i < data.length; i++) {
data[i] = g.nextRandom();
}
- GammaDistribution g2 = GammaDistribution.estimate(data);
+ GammaDistribution g2 = GammaChoiWetteEstimator.STATIC.estimate(data, ArrayLikeUtil.DOUBLEARRAYADAPTER);
assertEquals("k does not match.", g.getK(), g2.getK(), 1E-2);
assertEquals("theta does not match.", g.getTheta(), g2.getTheta(), 1E-5);
}
-} \ No newline at end of file
+
+ @Test
+ public void extremeValues() {
+ // TODO: tested values
+ GammaDistribution dist = new GammaDistribution(1.1987906546993674E12, 1.1987905236089673E12);
+ assertEquals(0.0, dist.cdf(Double.MIN_VALUE), 1e-50);
+ // FIXME: NEITHER OF THESE VALUE IS NOT VERIFIED.
+ // THIS IS SOLELY A REGRESSION TEST.
+ // assertEquals(0.45430463189141745, dist.cdf(1.0), 1e-15);
+ assertEquals(3.6330826914761E-4, dist.cdf(1.0), 1e-15);
+ }
+}
diff --git a/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestGeneralizedExtremeValueDistribution.java b/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestGeneralizedExtremeValueDistribution.java
new file mode 100644
index 00000000..7c66107b
--- /dev/null
+++ b/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestGeneralizedExtremeValueDistribution.java
@@ -0,0 +1,1294 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2012
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import org.junit.Test;
+
+import de.lmu.ifi.dbs.elki.JUnit4Test;
+
+/**
+ * Unit test for the Generalized Extreme Value (GEV) distribution in ELKI.
+ *
+ * The reference values were computed using SciPy.
+ *
+ * @author Erich Schubert
+ */
+public class TestGeneralizedExtremeValueDistribution extends AbstractDistributionTest implements JUnit4Test {
+ public static final double[] P_CDFPDF = { //
+ 1e-10, 1e-05, 0.1, 0.1234567, 0.2, 0.271828182846, 0.3, 0.314159265359, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.71828182846, 3.14159265359 //
+ };
+
+ public static final double[] SCIPY_GUMBEL_CDF_1_1 = { //
+ 6.59880358632499303128682299757201690226793289184570e-02, // 0.000000
+ 6.59898296015106466949617924910853616893291473388672e-02, // 0.000010
+ 8.54688658759459179981021748062630649656057357788086e-02, // 0.100000
+ 9.04841721928088676962786962576501537114381790161133e-02, // 0.123457
+ 1.08008977696591554340521668109431630000472068786621e-01, // 0.200000
+ 1.26023050723474722145667215045250486582517623901367e-01, // 0.271828
+ 1.33486796658083856081944418292550835758447647094727e-01, // 0.300000
+ 1.37320130159857167750914186399313621222972869873047e-01, // 0.314159
+ 1.61682814145126474425495644027250818908214569091797e-01, // 0.400000
+ 1.92295645547964910715421638087718747556209564208984e-01, // 0.500000
+ 2.24961793549918465107140264080953784286975860595703e-01, // 0.600000
+ 2.59276865990827554142583721841219812631607055664062e-01, // 0.700000
+ 2.94816320729158143354453613937948830425739288330078e-01, // 0.800000
+ 3.31154277152908960157873252683202736079692840576172e-01, // 0.900000
+ 3.67879441171442334024277442949824035167694091796875e-01, // 1.000000
+ 4.04607661664131867951255117077380418777465820312500e-01, // 1.100000
+ 4.40991025942982617369381159733165986835956573486328e-01, // 1.200000
+ 4.76723690714594083850386141421040520071983337402344e-01, // 1.300000
+ 5.11544833689041578139722332707606256008148193359375e-01, // 1.400000
+ 5.45239211892605046827497972117271274328231811523438e-01, // 1.500000
+ 5.77635844258915676086019175272667780518531799316406e-01, // 1.600000
+ 6.08605317804406409365469698968809098005294799804688e-01, // 1.700000
+ 6.38056166582018691180167024867841973900794982910156e-01, // 1.800000
+ 6.65930705440122117089174480497604236006736755371094e-01, // 1.900000
+ 6.92200627555346392760782237019157037138938903808594e-01, // 2.000000
+ 8.35793188453588298258978284138720482587814331054688e-01, // 2.718282
+ 8.89169312582892001906031964608700945973396301269531e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_GUMBEL_PDF_1_1 = { //
+ 1.79374078764838684740823282481869682669639587402344e-01, // 0.000000
+ 1.79377160888317427334115450321405660361051559448242e-01, // 0.000010
+ 2.10219488415532645975147829631168860942125320434570e-01, // 0.100000
+ 2.17395492872112461313349740521516650915145874023438e-01, // 0.123457
+ 2.40378400508394624024433028353087138384580612182617e-01, // 0.200000
+ 2.61030341003925192566725854703690856695175170898438e-01, // 0.271828
+ 2.68809398181777348124654736238881014287471771240234e-01, // 0.300000
+ 2.72640929007956611673790803251904435455799102783203e-01, // 0.314159
+ 2.94605295353879470532376672053942456841468811035156e-01, // 0.400000
+ 3.17041921077942157047857563156867399811744689941406e-01, // 0.500000
+ 3.35603559643445015225893257593270391225814819335938e-01, // 0.600000
+ 3.49987161158421655748895773285767063498497009277344e-01, // 0.700000
+ 3.60089467289227027624320953691494651138782501220703e-01, // 0.800000
+ 3.65982076505757814022246066087973304092884063720703e-01, // 0.900000
+ 3.67879441171442334024277442949824035167694091796875e-01, // 1.000000
+ 3.66104151897740148768889412167482078075408935546875e-01, // 1.100000
+ 3.61052914770930044596752850338816642761230468750000e-01, // 1.200000
+ 3.53165596312007168400270984420785680413246154785156e-01, // 1.300000
+ 3.42898756467731824493228032224578782916069030761719e-01, // 1.400000
+ 3.30704298890418080247854959452524781227111816406250e-01, // 1.500000
+ 3.17013272754289754384871002912404946982860565185547e-01, // 1.600000
+ 3.02224456630968474346587981926859356462955474853516e-01, // 1.700000
+ 2.86697116378903826827695411338936537504196166992188e-01, // 1.800000
+ 2.70747220321607640070027400724939070641994476318359e-01, // 1.900000
+ 2.54646380043582531982337968656793236732482910156250e-01, // 2.000000
+ 1.49919633191029216812140134607034269720315933227539e-01, // 2.718282
+ 1.04448592925595828972973322379402816295623779296875e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_GUMBEL_CDF_2_1 = { //
+ 6.17978989787721657254981888485190211213193833827972e-04, // 0.000000
+ 6.18024653604032120531031058163762281765230000019073e-04, // 0.000010
+ 1.24839763464425581619698935043061283067800104618073e-03, // 0.100000
+ 1.45770722707259806419366476859522663289681077003479e-03, // 0.123457
+ 2.35869338329322553171607523836428299546241760253906e-03, // 0.200000
+ 3.58731530475635143964674433902928285533562302589417e-03, // 0.271828
+ 4.19464154138938540017367273549098172225058078765869e-03, // 0.300000
+ 4.53021237372840286650177432647979003377258777618408e-03, // 0.314159
+ 7.06196156220941038267335798650492506567388772964478e-03, // 0.400000
+ 1.13142863804596271321001310639076109509915113449097e-02, // 0.500000
+ 1.73320140087645062354493319389803218655288219451904e-02, // 0.600000
+ 2.54943946757241260425708162529190303757786750793457e-02, // 0.700000
+ 3.61486049131355194341530534529738361015915870666504e-02, // 0.800000
+ 4.95800856955669819181586888134916080161929130554199e-02, // 0.900000
+ 6.59880358453125426265728492580819875001907348632812e-02, // 1.000000
+ 8.54688658759459596314655982496333308517932891845703e-02, // 1.100000
+ 1.08008977696591554340521668109431630000472068786621e-01, // 1.200000
+ 1.33486796658083856081944418292550835758447647094727e-01, // 1.300000
+ 1.61682814145126418914344412769423797726631164550781e-01, // 1.400000
+ 1.92295645547964910715421638087718747556209564208984e-01, // 1.500000
+ 2.24961793549918520618291495338780805468559265136719e-01, // 1.600000
+ 2.59276865990827554142583721841219812631607055664062e-01, // 1.700000
+ 2.94816320729158143354453613937948830425739288330078e-01, // 1.800000
+ 3.31154277152908849135570790167548693716526031494141e-01, // 1.900000
+ 3.67879441171442334024277442949824035167694091796875e-01, // 2.000000
+ 6.14105034982032282897534969379194080829620361328125e-01, // 2.718282
+ 7.26650204627822926539693071390502154827117919921875e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_GUMBEL_PDF_2_1 = { //
+ 4.56628142304533850281966778084097313694655895233154e-03, // 0.000000
+ 4.56657317004234564183917655100231058895587921142578e-03, // 0.000010
+ 8.34665480722261536594697162172451498918235301971436e-03, // 0.100000
+ 9.52012623739182869964103872462146682664752006530762e-03, // 0.123457
+ 1.42692634455674552396153842437342973425984382629395e-02, // 0.200000
+ 2.01978449671180448898866188756073825061321258544922e-02, // 0.271828
+ 2.29612471247189892098461427849542815238237380981445e-02, // 0.300000
+ 2.44494948372630735433652660049119731411337852478027e-02, // 0.314159
+ 3.49781245974551888155978929262346355244517326354980e-02, // 0.400000
+ 5.07071136099807306951703367303707636892795562744141e-02, // 0.500000
+ 7.02847826336932546276159428089158609509468078613281e-02, // 0.600000
+ 9.35464974266043414186100335427909158170223236083984e-02, // 0.700000
+ 1.20017594905418731321411485168937360867857933044434e-01, // 0.800000
+ 1.48946808910974892725675999827217310667037963867188e-01, // 0.900000
+ 1.79374078734017200487116383555985521525144577026367e-01, // 1.000000
+ 2.10219488415532701486299060888995882123708724975586e-01, // 1.100000
+ 2.40378400508394624024433028353087138384580612182617e-01, // 1.200000
+ 2.68809398181777348124654736238881014287471771240234e-01, // 1.300000
+ 2.94605295353879415021225440796115435659885406494141e-01, // 1.400000
+ 3.17041921077942157047857563156867399811744689941406e-01, // 1.500000
+ 3.35603559643445015225893257593270391225814819335938e-01, // 1.600000
+ 3.49987161158421655748895773285767063498497009277344e-01, // 1.700000
+ 3.60089467289227027624320953691494651138782501220703e-01, // 1.800000
+ 3.65982076505757758511094834830146282911300659179688e-01, // 1.900000
+ 3.67879441171442334024277442949824035167694091796875e-01, // 2.000000
+ 2.99431043346856384790299898668308742344379425048828e-01, // 2.718282
+ 2.32026725020700291812758564446994569152593612670898e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_GUMBEL_CDF_4_1 = { //
+ 1.94233761556120265073609843858010169210640550320133e-24, // 0.000000
+ 1.94339836960486498321475838226799834065378487714337e-24, // 0.000010
+ 3.50581472625786942134053009067093603336708158078897e-22, // 0.100000
+ 1.10204869082170943883948227538294176292737847487482e-21, // 0.123457
+ 3.85942175009585124493227078787604613125739296999845e-20, // 0.200000
+ 8.55175072212361792537222183911253732406541162804661e-19, // 0.271828
+ 2.71618226092945448511767238087193692507249743561641e-18, // 0.300000
+ 4.79654546206938212109880845109838654258082904740905e-18, // 0.314159
+ 1.27523062451624426541224412921385568571695936319552e-16, // 0.400000
+ 4.15089692010904525288672126361021019245556122612140e-15, // 0.500000
+ 9.69966408521639154441452223525895873820334286419254e-14, // 0.600000
+ 1.67930865740466120726981233244263965733930610291225e-12, // 0.700000
+ 2.21644780341866066467927092510455566905236413077773e-11, // 0.800000
+ 2.28850701972651310101286108247299871248925384747963e-10, // 0.900000
+ 1.89217869483829244811168274588777937772476889222162e-09, // 1.000000
+ 1.27958444708893479866928830448492837579266279135481e-08, // 1.100000
+ 7.21407495654723266621612446335143342679430134012364e-08, // 1.200000
+ 3.44996444807882075559481984891596617615050490712747e-07, // 1.300000
+ 1.42158510896623277238609052430806656275308341719210e-06, // 1.400000
+ 5.11929429867073290303346178031773661132319830358028e-06, // 1.500000
+ 1.63190669761509105832684302095358930273505393415689e-05, // 1.600000
+ 4.65873061192628793976758250217073964449809864163399e-05, // 1.700000
+ 1.20361180348421196420645451485853527628933079540730e-04, // 1.800000
+ 2.84104078721292101477463587499983077577780932188034e-04, // 1.900000
+ 6.17978989331093432439689916435554550844244658946991e-04, // 2.000000
+ 2.72466505377139643628847665013381629250943660736084e-02, // 2.718282
+ 9.44768930014186492094552249909611418843269348144531e-02, // 3.141593
+ };
+
+ public static final double[] SCIPY_GUMBEL_PDF_4_1 = { //
+ 1.06048040538825383895657084905076034872528558503039e-22, // 0.000000
+ 1.06104894703602011823679422569673096865235426708292e-22, // 0.000010
+ 1.73195833587372556877622009550080809725453568188831e-20, // 0.100000
+ 5.31816915757311281533262916149991462179401939316581e-20, // 0.123457
+ 1.72520723688492552379661823003568327945291845918510e-18, // 0.200000
+ 3.55778320603558542628503187787223104575572232312602e-17, // 0.271828
+ 1.09862250605229655196224903219933069216592916588111e-16, // 0.300000
+ 1.91279689150650823875815251444059610432563375858640e-16, // 0.314159
+ 4.66711893658034022812779722242683120807921724748635e-15, // 0.400000
+ 1.37458827543354963946170620516550599064667728677058e-13, // 0.500000
+ 2.90641705075567549607614189502246106536209602211329e-12, // 0.600000
+ 4.55304892645473537813182015220254180570824686924425e-11, // 0.700000
+ 5.43750726676849818042246906675497505889715910143423e-10, // 0.800000
+ 5.08001673311263319774744418142083113298923535694485e-09, // 0.900000
+ 3.80054250404435749527446645589651152974397518846672e-08, // 1.000000
+ 2.32553537538727241913236328495206972633013720042072e-07, // 1.100000
+ 1.18632914440636535453432297976261722283197741489857e-06, // 1.200000
+ 5.13345454477618321902391770872320364560437155887485e-06, // 1.300000
+ 1.91398495015806936032053131579999671885161660611629e-05, // 1.400000
+ 6.23657718766199291749591226974303026509005576372147e-05, // 1.500000
+ 1.79887953645615079585964868336134259152458980679512e-04, // 1.600000
+ 4.64670291311834173994532726226225349819287657737732e-04, // 1.700000
+ 1.08626127745232634556893369648378211422823369503021e-03, // 1.800000
+ 2.32004217969156720582923902895799983525648713111877e-03, // 1.900000
+ 4.56628142012791525539139314560088678263127803802490e-03, // 2.000000
+ 9.81649050447965243471060148294782266020774841308594e-02, // 2.718282
+ 2.22908780675388440428719150077085942029953002929688e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_GUMBEL_CDF_4_10 = { //
+ 2.24961793553274530532704034158086869865655899047852e-01, // 0.000000
+ 2.24962129153560647099041602814395446330308914184570e-01, // 0.000010
+ 2.28326012057771948748907675508235115557909011840820e-01, // 0.100000
+ 2.29117491320003585641984500398393720388412475585938e-01, // 0.123457
+ 2.31706315790068034798920848515990655869245529174805e-01, // 0.200000
+ 2.34144016800101217867791092430707067251205444335938e-01, // 0.271828
+ 2.35102282543562940420045492828649003058671951293945e-01, // 0.300000
+ 2.35584367949729117652779564195952843874692916870117e-01, // 0.314159
+ 2.38513488532688416876581527503731194883584976196289e-01, // 0.400000
+ 2.41939508585804652351924914910341612994670867919922e-01, // 0.500000
+ 2.45379916339054454654799997115333098918199539184570e-01, // 0.600000
+ 2.48834284427714574894352494993654545396566390991211e-01, // 0.700000
+ 2.52302184674948581921682944084750488400459289550781e-01, // 0.800000
+ 2.55783188277869832916167069924995303153991699218750e-01, // 0.900000
+ 2.59276865990827554142583721841219812631607055664062e-01, // 1.000000
+ 2.62782788305835623976491888242890127003192901611328e-01, // 1.100000
+ 2.66300525630066620141889188744244165718555450439453e-01, // 1.200000
+ 2.69829648460341131599449226996512152254581451416016e-01, // 1.300000
+ 2.73369727554544250658352666505379602313041687011719e-01, // 1.400000
+ 2.76920334099908960201474883433547802269458770751953e-01, // 1.500000
+ 2.80481039878108018292834913154365494847297668457031e-01, // 1.600000
+ 2.84051417427103602975080320902634412050247192382812e-01, // 1.700000
+ 2.87631040199704479665143708189134486019611358642578e-01, // 1.800000
+ 2.91219482718789723918462186702527105808258056640625e-01, // 1.900000
+ 2.94816320729158143354453613937948830425739288330078e-01, // 2.000000
+ 3.20860670367920819412432820172398351132869720458984e-01, // 2.718282
+ 3.36339983908659712064093127992236986756324768066406e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_GUMBEL_PDF_4_10 = { //
+ 3.35603559645095625429966901265288470312952995300293e-02, // 0.000000
+ 3.35603724701354494408533923888171557337045669555664e-02, // 0.000010
+ 3.37233134553145824652276019151031505316495895385742e-02, // 0.100000
+ 3.37609284733200315509193956131639424711465835571289e-02, // 0.123457
+ 3.38820574854396400210632123162213247269392013549805e-02, // 0.200000
+ 3.39934708099677296289087280456442385911941528320312e-02, // 0.271828
+ 3.40365712424673116931472804935765452682971954345703e-02, // 0.300000
+ 3.40581064819283629852009198657469823956489562988281e-02, // 0.314159
+ 3.41868398883302671009687401237897574901580810546875e-02, // 0.400000
+ 3.43328505356715121821231662124773720279335975646973e-02, // 0.500000
+ 3.44745922233250789989966733628534711897373199462891e-02, // 0.600000
+ 3.46120558908042108559044436333351768553256988525391e-02, // 0.700000
+ 3.47452343518489734086607256813294952735304832458496e-02, // 0.800000
+ 3.48741222670847020315143538482516305521130561828613e-02, // 0.900000
+ 3.49987161158421683504471388914680574089288711547852e-02, // 1.000000
+ 3.51190141671897312902750343255320331081748008728027e-02, // 1.100000
+ 3.52350164502270857269650150556117296218872070312500e-02, // 1.200000
+ 3.53467247236895973361292533354571787640452384948730e-02, // 1.300000
+ 3.54541424449113518058140925859333947300910949707031e-02, // 1.400000
+ 3.55572747381944151423560640523646725341677665710449e-02, // 1.500000
+ 3.56561283626308858640818755247892113402485847473145e-02, // 1.600000
+ 3.57507116794234872103608324778178939595818519592285e-02, // 1.700000
+ 3.58410346187495246206289323254168266430497169494629e-02, // 1.800000
+ 3.59271086462122773985683465980400796979665756225586e-02, // 1.900000
+ 3.60089467289226999868745338062581140547990798950195e-02, // 2.000000
+ 3.64737821185050284378270646357123041525483131408691e-02, // 2.718282
+ 3.66487069582701815995129379643913125619292259216309e-02, // 3.141593
+ };
+
+ public static final double[] SCIPY_GUMBEL_CDF_01_10 = { //
+ 3.64200708229312053454407305252971127629280090332031e-01, // 0.000000
+ 3.64201076086621500227380465730675496160984039306641e-01, // 0.000010
+ 3.67879441171442334024277442949824035167694091796875e-01, // 0.100000
+ 3.68742364149354184821305580044281668961048126220703e-01, // 0.123457
+ 3.71558174423808174058336817324743606150150299072266e-01, // 0.200000
+ 3.74200337049799547362027851704624481499195098876953e-01, // 0.271828
+ 3.75236541960806024853525286744115874171257019042969e-01, // 0.300000
+ 3.75757321275714095687447979798889718949794769287109e-01, // 0.314159
+ 3.78914181510685010856320786842843517661094665527344e-01, // 0.400000
+ 3.82590734620523953424253704724833369255065917968750e-01, // 0.500000
+ 3.86265846721645655925669871066929772496223449707031e-01, // 0.600000
+ 3.89939167191828084391147513088071718811988830566406e-01, // 0.700000
+ 3.93610349414351023966673892573453485965728759765625e-01, // 0.800000
+ 3.97279050833918845331282909683068282902240753173828e-01, // 0.900000
+ 4.00944933009500681375669728367938660085201263427734e-01, // 1.000000
+ 4.04607661664131867951255117077380418777465820312500e-01, // 1.100000
+ 4.08266906731719725343054960831068456172943115234375e-01, // 1.200000
+ 4.11922342400900476366842895004083402454853057861328e-01, // 1.300000
+ 4.15573647155991876545044760860037058591842651367188e-01, // 1.400000
+ 4.19220503815090905774809471040498465299606323242188e-01, // 1.500000
+ 4.22862599565362817788383154038456268608570098876953e-01, // 1.600000
+ 4.26499625995571840508802097247098572552204132080078e-01, // 1.700000
+ 4.30131279125902432625139226729515939950942993164062e-01, // 1.800000
+ 4.33757259435121944601831955878878943622112274169922e-01, // 1.900000
+ 4.37377271885135254780863078849506564438343048095703e-01, // 2.000000
+ 4.63178277570029439669241355659323744475841522216797e-01, // 2.718282
+ 4.78191805551566095910942522095865570008754730224609e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_GUMBEL_PDF_01_10 = { //
+ 3.67860986195510386576046357731684111058712005615234e-02, // 0.000000
+ 3.67860989892352038821421444936277111992239952087402e-02, // 0.000010
+ 3.67879441171442347902065250764280790463089942932129e-02, // 0.100000
+ 3.67878429896495301454351078973559197038412094116211e-02, // 0.123457
+ 3.67861108816435675161748974915099097415804862976074e-02, // 0.200000
+ 3.67825446794351126889033309907972579821944236755371e-02, // 0.271828
+ 3.67806360606196675044898825035488698631525039672852e-02, // 0.300000
+ 3.67795687265079010441759521654603304341435432434082e-02, // 0.314159
+ 3.67715575045233014628287548930529737845063209533691e-02, // 0.400000
+ 3.67589137340928531760830821895069675520062446594238e-02, // 0.500000
+ 3.67427439081312035007442773348884657025337219238281e-02, // 0.600000
+ 3.67230877916642356462162410934979561716318130493164e-02, // 0.700000
+ 3.66999857244961757984924588527064770460128784179688e-02, // 0.800000
+ 3.66734785901757648352017326942586805671453475952148e-02, // 0.900000
+ 3.66436077853866115638936662435298785567283630371094e-02, // 1.000000
+ 3.66104151897740162646677219981938833370804786682129e-02, // 1.100000
+ 3.65739431362198524899653762076923158019781112670898e-02, // 1.200000
+ 3.65342343815761166903044454556948039680719375610352e-02, // 1.300000
+ 3.64913320778669988952991332098463317379355430603027e-02, // 1.400000
+ 3.64452797439685782787677226224332116544246673583984e-02, // 1.500000
+ 3.63961212377742968082650065753114176914095878601074e-02, // 1.600000
+ 3.63439007288538645790154646419978234916925430297852e-02, // 1.700000
+ 3.62886626716122442926071300917101325467228889465332e-02, // 1.800000
+ 3.62304517789548280459754892035562079399824142456055e-02, // 1.900000
+ 3.61693129964641910123468449000938562676310539245605e-02, // 2.000000
+ 3.56482034999189151269760600371228065341711044311523e-02, // 2.718282
+ 3.52782829415396598227161462091316934674978256225586e-02, // 3.141593
+ };
+
+ public static final double[] SCIPY_GUMBEL_CDF_01_20 = { //
+ 3.66040051641140451454958792965044267475605010986328e-01, // 0.000000
+ 3.66040235576718830934339621308026835322380065917969e-01, // 0.000010
+ 3.67879441171442334024277442949824035167694091796875e-01, // 0.100000
+ 3.68310902956942021191366620769258588552474975585938e-01, // 0.123457
+ 3.69718830722743807548624772607581689953804016113281e-01, // 0.200000
+ 3.71040005167483422088281486139749176800251007080078e-01, // 0.271828
+ 3.71558174423808174058336817324743606150150299072266e-01, // 0.300000
+ 3.71818605637736554481165285324095748364925384521484e-01, // 0.314159
+ 3.73397426637427698459248404105892404913902282714844e-01, // 0.400000
+ 3.75236541960806024853525286744115874171257019042969e-01, // 0.500000
+ 3.77075475227729051130864945662324316799640655517578e-01, // 0.600000
+ 3.78914181510685010856320786842843517661094665527344e-01, // 0.700000
+ 3.80752616122933373876691121040494181215763092041016e-01, // 0.800000
+ 3.82590734620523953424253704724833369255065917968750e-01, // 0.900000
+ 3.84428492804265664606333530173287726938724517822266e-01, // 1.000000
+ 3.86265846721645655925669871066929772496223449707031e-01, // 1.100000
+ 3.88102752668698702809280121073243208229541778564453e-01, // 1.200000
+ 3.89939167191828084391147513088071718811988830566406e-01, // 1.300000
+ 3.91775047089576777814556862722383812069892883300781e-01, // 1.400000
+ 3.93610349414351023966673892573453485965728759765625e-01, // 1.500000
+ 3.95445031474095209933494743381743319332599639892578e-01, // 1.600000
+ 3.97279050833918845331282909683068282902240753173828e-01, // 1.700000
+ 3.99112365317676576204064531339099630713462829589844e-01, // 1.800000
+ 4.00944933009500681375669728367938660085201263427734e-01, // 1.900000
+ 4.02776712255286439834378597879549488425254821777344e-01, // 2.000000
+ 4.15907192667703928812272806680994108319282531738281e-01, // 2.718282
+ 4.23619395109240293173513691726839169859886169433594e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_GUMBEL_PDF_01_20 = { //
+ 1.83937417516764276093077512541640317067503929138184e-02, // 0.000000
+ 1.83937417977731651475004071016883244737982749938965e-02, // 0.000010
+ 1.83939720585721173951032625382140395231544971466064e-02, // 0.100000
+ 1.83939594126808145246876335932029178366065025329590e-02, // 0.123457
+ 1.83937425180828485749007228378104628063738346099854e-02, // 0.200000
+ 1.83932951601603437985499311935200239531695842742920e-02, // 0.271828
+ 1.83930554408217837580874487457549548707902431488037e-02, // 0.300000
+ 1.83929213116811943184991662292304681614041328430176e-02, // 0.314159
+ 1.83919131598794319271128472337295534089207649230957e-02, // 0.400000
+ 1.83903180303098337522449412517744349315762519836426e-02, // 0.500000
+ 1.83882724286199075725001250702916877344250679016113e-02, // 0.600000
+ 1.83857787522616507314143774465264868922531604766846e-02, // 0.700000
+ 1.83828394191271268787168935432418948039412498474121e-02, // 0.800000
+ 1.83794568670464265880415410947534837760031223297119e-02, // 0.900000
+ 1.83756335532885978212291888667095918208360671997070e-02, // 1.000000
+ 1.83713719540656017503721386674442328512668609619141e-02, // 1.100000
+ 1.83666745640393841432214117048715706914663314819336e-02, // 1.200000
+ 1.83615438958321178231081205467489780858159065246582e-02, // 1.300000
+ 1.83559824795396266117197825451512471772730350494385e-02, // 1.400000
+ 1.83499928622480878992462294263532385230064392089844e-02, // 1.500000
+ 1.83435776075540693530463443039479898288846015930176e-02, // 1.600000
+ 1.83367392950878824176008663471293402835726737976074e-02, // 1.700000
+ 1.83294805200404052614171490631633787415921688079834e-02, // 1.800000
+ 1.83218038926933057819468331217649392783641815185547e-02, // 1.900000
+ 1.83137120379528138547353677267892635427415370941162e-02, // 2.000000
+ 1.82436263119165158197443332710463437251746654510498e-02, // 2.718282
+ 1.81927559990815723711676810125936754047870635986328e-02, // 3.141593
+ };
+
+ public static final double[] SCIPY_GUMBEL_CDF_01_4 = { //
+ 3.58683419097346689596861324389465153217315673828125e-01, // 0.000000
+ 3.58684338497014365554349524245481006801128387451172e-01, // 0.000010
+ 3.67879441171442334024277442949824035167694091796875e-01, // 0.100000
+ 3.70036738247086438580168987755314446985721588134766e-01, // 0.123457
+ 3.77075475227729051130864945662324316799640655517578e-01, // 0.200000
+ 3.83677647968239443621030204667476937174797058105469e-01, // 0.271828
+ 3.86265846721645655925669871066929772496223449707031e-01, // 0.300000
+ 3.87566357530248317697640914047951810061931610107422e-01, // 0.314159
+ 3.95445031474095209933494743381743319332599639892578e-01, // 0.400000
+ 4.04607661664131867951255117077380418777465820312500e-01, // 0.500000
+ 4.13748531068576341773734839080134406685829162597656e-01, // 0.600000
+ 4.22862599565362817788383154038456268608570098876953e-01, // 0.700000
+ 4.31944996928375679612344129054690711200237274169922e-01, // 0.800000
+ 4.40991025942982672880532390990993008017539978027344e-01, // 0.900000
+ 4.49996164872620063590602512704208493232727050781250e-01, // 1.000000
+ 4.58956069307663805378894039677106775343418121337891e-01, // 1.100000
+ 4.67866573428437237947008497940259985625743865966797e-01, // 1.200000
+ 4.76723690714594083850386141421040520071983337402344e-01, // 1.300000
+ 4.85523614133279490800987332477234303951263427734375e-01, // 1.400000
+ 4.94262715838446498040070764545816928148269653320312e-01, // 1.500000
+ 5.02937546413495417674255349993472918868064880371094e-01, // 1.600000
+ 5.11544833689041578139722332707606256008148193359375e-01, // 1.700000
+ 5.20081481167105397211969375348417088389396667480469e-01, // 1.800000
+ 5.28544566082388089789390051009831950068473815917969e-01, // 1.900000
+ 5.36931337130553965053536558116320520639419555664062e-01, // 2.000000
+ 5.94719607054730259321217999968212097883224487304688e-01, // 2.718282
+ 6.26579099505278791504281343804905191063880920410156e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_GUMBEL_PDF_01_4 = { //
+ 9.19408832681790494367746191528567578643560409545898e-02, // 0.000000
+ 9.19408890865627964616990652757522184401750564575195e-02, // 0.000010
+ 9.19698602928605835060693607374560087919235229492188e-02, // 0.100000
+ 9.19682820379929405474328518721449654549360275268555e-02, // 0.123457
+ 9.19413621430995309236067214442300610244274139404297e-02, // 0.200000
+ 9.18862440991995849115525629713374655693769454956055e-02, // 0.271828
+ 9.18568597703280087518606933372211642563343048095703e-02, // 0.300000
+ 9.18404563854176708703747067374933976680040359497070e-02, // 0.314159
+ 9.17178880377703537041256254269683267921209335327148e-02, // 0.400000
+ 9.15260379744350371922223530418705195188522338867188e-02, // 0.500000
+ 9.12829492792362195974220639982377178966999053955078e-02, // 0.600000
+ 9.09903030944357454901094683918927330523729324340820e-02, // 0.700000
+ 9.06498150644146627463726417772704735398292541503906e-02, // 0.800000
+ 9.02632286927325111491882125847041606903076171875000e-02, // 0.900000
+ 8.98323090075764524309320790962374303489923477172852e-02, // 1.000000
+ 8.93588365430456332827446885858080349862575531005859e-02, // 1.100000
+ 8.88446016412571676346132676371780689805746078491211e-02, // 1.200000
+ 8.82913990780017921000677461051964201033115386962891e-02, // 1.300000
+ 8.77010230126132606098821042905910871922969818115234e-02, // 1.400000
+ 8.70752622608445409069233278387400787323713302612305e-02, // 1.500000
+ 8.64158958878580990559115093674336094409227371215820e-02, // 1.600000
+ 8.57246891169329561233070080561446957290172576904297e-02, // 1.700000
+ 8.50033895481578094521779576098197139799594879150391e-02, // 1.800000
+ 8.42537236802113342903908232983667403459548950195312e-02, // 1.900000
+ 8.34773937273183275209476050804369151592254638671875e-02, // 2.000000
+ 7.72637758157185411400647012669651303440332412719727e-02, // 2.718282
+ 7.32283395263601255553709279411123134195804595947266e-02, // 3.141593
+ };
+
+ public static final double[] SCIPY_GUMBEL_CDF_01_1 = { //
+ 3.31154277189507073586582919233478605747222900390625e-01, // 0.000000
+ 3.31157936975598421458499842628953047096729278564453e-01, // 0.000010
+ 3.67879441171442334024277442949824035167694091796875e-01, // 0.100000
+ 3.76507892217193051997981001477455720305442810058594e-01, // 0.123457
+ 4.04607661664131867951255117077380418777465820312500e-01, // 0.200000
+ 4.30794607123086759070673679161700420081615447998047e-01, // 0.271828
+ 4.40991025942982672880532390990993008017539978027344e-01, // 0.300000
+ 4.46096575846239407070470406324602663516998291015625e-01, // 0.314159
+ 4.76723690714594083850386141421040520071983337402344e-01, // 0.400000
+ 5.11544833689041578139722332707606256008148193359375e-01, // 0.500000
+ 5.45239211892605046827497972117271274328231811523438e-01, // 0.600000
+ 5.77635844258915676086019175272667780518531799316406e-01, // 0.700000
+ 6.08605317804406409365469698968809098005294799804688e-01, // 0.800000
+ 6.38056166582018691180167024867841973900794982910156e-01, // 0.900000
+ 6.65930705440122117089174480497604236006736755371094e-01, // 1.000000
+ 6.92200627555346392760782237019157037138938903808594e-01, // 1.100000
+ 7.16862603474862081220919662882806733250617980957031e-01, // 1.200000
+ 7.39934054783606187655209396325517445802688598632812e-01, // 1.300000
+ 7.61449220009415284060594331094762310385704040527344e-01, // 1.400000
+ 7.81455584849563456018017859605606645345687866210938e-01, // 1.500000
+ 8.00010713004353557487036141537828370928764343261719e-01, // 1.600000
+ 8.17179486939028754122205100429710000753402709960938e-01, // 1.700000
+ 8.33031748536220639778093755012378096580505371093750e-01, // 1.800000
+ 8.47640316515773317718185353442095220088958740234375e-01, // 1.900000
+ 8.61079349396833837460007998743094503879547119140625e-01, // 2.000000
+ 9.29667709628290483969692559185205027461051940917969e-01, // 2.718282
+ 9.53363743354765147408613756851991638541221618652344e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_GUMBEL_PDF_01_1 = { //
+ 3.65982076509606846226319021297967992722988128662109e-01, // 0.000000
+ 3.65982461392446445369586172091658227145671844482422e-01, // 0.000010
+ 3.67879441171442334024277442949824035167694091796875e-01, // 0.100000
+ 3.67779034862618203760575852356851100921630859375000e-01, // 0.123457
+ 3.66104151897740148768889412167482078075408935546875e-01, // 0.200000
+ 3.62782413998306907387814135290682315826416015625000e-01, // 0.271828
+ 3.61052914770930044596752850338816642761230468750000e-01, // 0.300000
+ 3.60097994370001339703435405681375414133071899414062e-01, // 0.314159
+ 3.53165596312007168400270984420785680413246154785156e-01, // 0.400000
+ 3.42898756467731824493228032224578782916069030761719e-01, // 0.500000
+ 3.30704298890418080247854959452524781227111816406250e-01, // 0.600000
+ 3.17013272754289754384871002912404946982860565185547e-01, // 0.700000
+ 3.02224456630968474346587981926859356462955474853516e-01, // 0.800000
+ 2.86697116378903826827695411338936537504196166992188e-01, // 0.900000
+ 2.70747220321607584558876169467112049460411071777344e-01, // 1.000000
+ 2.54646380043582531982337968656793236732482910156250e-01, // 1.100000
+ 2.38622831681304076179017670256143901497125625610352e-01, // 1.200000
+ 2.22863854497548474764556658556102775037288665771484e-01, // 1.300000
+ 2.07519121233516318225653662921104114502668380737305e-01, // 1.400000
+ 1.92704574679114809532265439884213265031576156616211e-01, // 1.500000
+ 1.78506518513120937541316379792988300323486328125000e-01, // 1.600000
+ 1.64985692989648907724742343816615175455808639526367e-01, // 1.700000
+ 1.52181175470408269756461550059611909091472625732422e-01, // 1.800000
+ 1.40114001931851056559352741714974399656057357788086e-01, // 1.900000
+ 1.28790449330409367822980470918992068618535995483398e-01, // 2.000000
+ 6.77988607946176241592084465992229524999856948852539e-02, // 2.718282
+ 4.55314756659847622022319058032735483720898628234863e-02, // 3.141593
+ };
+
+ public static final double[] SCIPY_GEV_CDF_1_05_1 = { //
+ 2.23130160170742858349868242839875165373086929321289e-01, // 0.000000
+ 2.23132391461187878922700633665954228490591049194336e-01, // 0.000010
+ 2.46596963941606434067566056000941898673772811889648e-01, // 0.100000
+ 2.52449689405203292480450727452989667654037475585938e-01, // 0.123457
+ 2.72531793034012592702453048332245089113712310791016e-01, // 0.200000
+ 2.92827430712962133441124024102464318275451660156250e-01, // 0.271828
+ 3.01194211912202136627314530414878390729427337646484e-01, // 0.300000
+ 3.05489236119981799610911821218905970454216003417969e-01, // 0.314159
+ 3.32871083698079606172370858985232189297676086425781e-01, // 0.400000
+ 3.67879441171442334024277442949824035167694091796875e-01, // 0.500000
+ 4.06569659740599109731817861757008358836174011230469e-01, // 0.600000
+ 4.49328964117221563157045238767750561237335205078125e-01, // 0.700000
+ 4.96585303791409526930067386274458840489387512207031e-01, // 0.800000
+ 5.48811636094026389365296836331253871321678161621094e-01, // 0.900000
+ 6.06530659712633424263117376540321856737136840820312e-01, // 1.000000
+ 6.70320046035639327541844068036880344152450561523438e-01, // 1.100000
+ 7.40818220681717876097138741897651925683021545410156e-01, // 1.200000
+ 8.18730753077981820986508409987436607480049133300781e-01, // 1.300000
+ 9.04837418035959517581545696884859353303909301757812e-01, // 1.400000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.500000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.600000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.700000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.800000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.900000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 2.000000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 2.718282
+ 1.00000000000000000000000000000000000000000000000000e+00, // 3.141593
+ };
+
+ public static final double[] SCIPY_GEV_PDF_1_05_1 = { //
+ 2.23130160170742858349868242839875165373086929321289e-01, // 0.000000
+ 2.23132391461187878922700633665954228490591049194336e-01, // 0.000010
+ 2.46596963941606434067566056000941898673772811889648e-01, // 0.100000
+ 2.52449689405203292480450727452989667654037475585938e-01, // 0.123457
+ 2.72531793034012592702453048332245089113712310791016e-01, // 0.200000
+ 2.92827430712962133441124024102464318275451660156250e-01, // 0.271828
+ 3.01194211912202136627314530414878390729427337646484e-01, // 0.300000
+ 3.05489236119981799610911821218905970454216003417969e-01, // 0.314159
+ 3.32871083698079606172370858985232189297676086425781e-01, // 0.400000
+ 3.67879441171442334024277442949824035167694091796875e-01, // 0.500000
+ 4.06569659740599165242969093014835380017757415771484e-01, // 0.600000
+ 4.49328964117221563157045238767750561237335205078125e-01, // 0.700000
+ 4.96585303791409526930067386274458840489387512207031e-01, // 0.800000
+ 5.48811636094026500387599298846907913684844970703125e-01, // 0.900000
+ 6.06530659712633313240814914024667814373970031738281e-01, // 1.000000
+ 6.70320046035639327541844068036880344152450561523438e-01, // 1.100000
+ 7.40818220681717876097138741897651925683021545410156e-01, // 1.200000
+ 8.18730753077981932008810872503090649843215942382812e-01, // 1.300000
+ 9.04837418035959517581545696884859353303909301757812e-01, // 1.400000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.500000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.600000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.700000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.800000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.900000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 2.000000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 2.718282
+ 0.00000000000000000000000000000000000000000000000000e+00, // 3.141593
+ };
+
+ public static final double[] SCIPY_GEV_CDF_1_05_05 = { //
+ 1.35335283263679745369145734912308398634195327758789e-01, // 0.000000
+ 1.35337989969344651974836324370699003338813781738281e-01, // 0.000010
+ 1.65298888221586531832585365009435918182134628295898e-01, // 0.100000
+ 1.73238399726401759437521832296624779701232910156250e-01, // 0.123457
+ 2.01896517994655383398949766160512808710336685180664e-01, // 0.200000
+ 2.33086969755381512303671343033784069120883941650391e-01, // 0.271828
+ 2.46596963941606434067566056000941898673772811889648e-01, // 0.300000
+ 2.53680045527954645123713817156385630369186401367188e-01, // 0.314159
+ 3.01194211912202136627314530414878390729427337646484e-01, // 0.400000
+ 3.67879441171442334024277442949824035167694091796875e-01, // 0.500000
+ 4.49328964117221563157045238767750561237335205078125e-01, // 0.600000
+ 5.48811636094026389365296836331253871321678161621094e-01, // 0.700000
+ 6.70320046035639327541844068036880344152450561523438e-01, // 0.800000
+ 8.18730753077981820986508409987436607480049133300781e-01, // 0.900000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.000000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.100000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.200000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.300000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.400000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.500000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.600000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.700000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.800000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.900000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 2.000000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 2.718282
+ 1.00000000000000000000000000000000000000000000000000e+00, // 3.141593
+ };
+
+ public static final double[] SCIPY_GEV_PDF_1_05_05 = { //
+ 2.70670566527359490738291469824616797268390655517578e-01, // 0.000000
+ 2.70675979938689359460823879999225027859210968017578e-01, // 0.000010
+ 3.30597776443173063665170730018871836364269256591797e-01, // 0.100000
+ 3.46476799452803518875043664593249559402465820312500e-01, // 0.123457
+ 4.03793035989310766797899532321025617420673370361328e-01, // 0.200000
+ 4.66173939510763024607342686067568138241767883300781e-01, // 0.271828
+ 4.93193927883212868135132112001883797347545623779297e-01, // 0.300000
+ 5.07360091055909290247427634312771260738372802734375e-01, // 0.314159
+ 6.02388423824404273254629060829756781458854675292969e-01, // 0.400000
+ 7.35758882342884668048554885899648070335388183593750e-01, // 0.500000
+ 8.98657928234443126314090477535501122474670410156250e-01, // 0.600000
+ 1.09762327218805277873059367266250774264335632324219e+00, // 0.700000
+ 1.34064009207127865508368813607376068830490112304688e+00, // 0.800000
+ 1.63746150615596386401762174500618129968643188476562e+00, // 0.900000
+ 2.00000000000000000000000000000000000000000000000000e+00, // 1.000000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.100000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.200000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.300000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.400000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.500000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.600000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.700000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.800000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.900000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 2.000000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 2.718282
+ 0.00000000000000000000000000000000000000000000000000e+00, // 3.141593
+ };
+
+ public static final double[] SCIPY_GEV_CDF_2_05_05 = { //
+ 1.76921206338193331975006117318116594105958938598633e-01, // 0.000000
+ 1.76923249246490665864683933250489644706249237060547e-01, // 0.000010
+ 1.99398179844168382812696904693439137190580368041992e-01, // 0.100000
+ 2.05339665992123637794364299224980641156435012817383e-01, // 0.123457
+ 2.26901404464795231064044855884276330471038818359375e-01, // 0.200000
+ 2.50825105377308843479511324403574690222740173339844e-01, // 0.271828
+ 2.61416388017453427128344856100738979876041412353516e-01, // 0.300000
+ 2.67037895731317531655690800107549875974655151367188e-01, // 0.314159
+ 3.06292130801829320940754541879869066178798675537109e-01, // 0.400000
+ 3.67879441171442334024277442949824035167694091796875e-01, // 0.500000
+ 4.60889634482101295809286511939717456698417663574219e-01, // 0.600000
+ 6.39407319161896969816893943061586469411849975585938e-01, // 0.700000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 0.800000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 0.900000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.000000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.100000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.200000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.300000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.400000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.500000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.600000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.700000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.800000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.900000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 2.000000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 2.718282
+ 1.00000000000000000000000000000000000000000000000000e+00, // 3.141593
+ };
+
+ public static final double[] SCIPY_GEV_PDF_2_05_05 = { //
+ 2.04291012223037887762799869051377754658460617065430e-01, // 0.000000
+ 2.04294733126156702329723202637978829443454742431641e-01, // 0.000010
+ 2.47323003145426822957375634359777905046939849853516e-01, // 0.100000
+ 2.59416327106311739303379226839751936495304107666016e-01, // 0.123457
+ 3.05953791365762839404851547442376613616943359375000e-01, // 0.200000
+ 3.62726274623251354611852548259776085615158081054688e-01, // 0.271828
+ 3.89696542692991587664153030345914885401725769042969e-01, // 0.300000
+ 4.04491116610953882481993559849797748029232025146484e-01, // 0.314159
+ 5.17728195074058872293676358822267502546310424804688e-01, // 0.400000
+ 7.35758882342884668048554885899648070335388183593750e-01, // 0.500000
+ 1.19001191919253446194204570929287001490592956542969e+00, // 0.600000
+ 2.85951646191380959294292551930993795394897460937500e+00, // 0.700000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.800000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.900000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.000000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.100000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.200000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.300000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.400000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.500000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.600000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.700000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.800000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.900000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 2.000000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 2.718282
+ 0.00000000000000000000000000000000000000000000000000e+00, // 3.141593
+ };
+
+ public static final double[] SCIPY_GEV_CDF_4_05_05 = { //
+ 2.24170404679878587650421195576200261712074279785156e-01, // 0.000000
+ 2.24171745530291038894787902790994849056005477905273e-01, // 0.000010
+ 2.38933711623939531998317420402599964290857315063477e-01, // 0.100000
+ 2.42851877427009699150772803477593697607517242431641e-01, // 0.123457
+ 2.57198770047239844149800092054647393524646759033203e-01, // 0.200000
+ 2.73490194806388475790015490929363295435905456542969e-01, // 0.271828
+ 2.80881211900971317074748867526068352162837982177734e-01, // 0.300000
+ 2.84858998476642533148606162285432219505310058593750e-01, // 0.314159
+ 3.14022014616371969442099043590133078396320343017578e-01, // 0.400000
+ 3.67879441171442334024277442949824035167694091796875e-01, // 0.500000
+ 5.12353580703692079723055030626710504293441772460938e-01, // 0.600000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 0.700000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 0.800000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 0.900000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.000000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.100000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.200000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.300000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.400000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.500000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.600000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.700000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.800000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.900000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 2.000000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 2.718282
+ 1.00000000000000000000000000000000000000000000000000e+00, // 3.141593
+ };
+
+ public static final double[] SCIPY_GEV_PDF_4_05_05 = { //
+ 1.34085176585659937575911726526101119816303253173828e-01, // 0.000000
+ 1.34087587639451499832432546099880710244178771972656e-01, // 0.000010
+ 1.62881011401559666618155119977018330246210098266602e-01, // 0.100000
+ 1.71325751629594402736245228879852220416069030761719e-01, // 0.123457
+ 2.05442218066886145289018372750433627516031265258789e-01, // 0.200000
+ 2.50994806945743553772132372614578343927860260009766e-01, // 0.271828
+ 2.74361188164238878339773464176687411963939666748047e-01, // 0.300000
+ 2.87699431311843278891160480270627886056900024414062e-01, // 0.314159
+ 4.04143606154024670473745572962798178195953369140625e-01, // 0.400000
+ 7.35758882342884668048554885899648070335388183593750e-01, // 0.500000
+ 3.42631489815548651023391357739455997943878173828125e+00, // 0.600000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.700000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.800000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.900000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.000000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.100000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.200000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.300000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.400000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.500000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.600000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.700000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.800000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.900000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 2.000000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 2.718282
+ 0.00000000000000000000000000000000000000000000000000e+00, // 3.141593
+ };
+
+ public static final double[] SCIPY_GEV_CDF_M1_05_1 = { //
+ 1.35335283290746816176053357594355475157499313354492e-01, // 0.000000
+ 1.35340696647941433061745897248329129070043563842773e-01, // 0.000010
+ 1.88875602837561828994950019477983005344867706298828e-01, // 0.100000
+ 2.01098462456466814396449649393616709858179092407227e-01, // 0.123457
+ 2.39651036441775794338937544125656131654977798461914e-01, // 0.200000
+ 2.73726692426692841397795064040110446512699127197266e-01, // 0.271828
+ 2.86504796860190091845055349040194414556026458740234e-01, // 0.300000
+ 2.92801343101584787831370704225264489650726318359375e-01, // 0.314159
+ 3.29192987807905568242716753957211039960384368896484e-01, // 0.400000
+ 3.67879441171442334024277442949824035167694091796875e-01, // 0.500000
+ 4.02890321529133010880485699090058915317058563232422e-01, // 0.600000
+ 4.34598208507078198614692610135534778237342834472656e-01, // 0.700000
+ 4.63369369231175276535594775850768201053142547607422e-01, // 0.800000
+ 4.89541659556953112630850455389008857309818267822266e-01, // 0.900000
+ 5.13417119032592017546789975313004106283187866210938e-01, // 1.000000
+ 5.35261428518990278746514377417042851448059082031250e-01, // 1.100000
+ 5.55306373001950515089220061781816184520721435546875e-01, // 1.200000
+ 5.73753420737432739962002870015567168593406677246094e-01, // 1.300000
+ 5.90777513901231565718319416191661730408668518066406e-01, // 1.400000
+ 6.06530659712633424263117376540321856737136840820312e-01, // 1.500000
+ 6.21145157615451526389449554699240252375602722167969e-01, // 1.600000
+ 6.34736418940281876821529749577166512608528137207031e-01, // 1.700000
+ 6.47405392083911013223485042544780299067497253417969e-01, // 1.800000
+ 6.59240630200443766817386403999989852309226989746094e-01, // 1.900000
+ 6.70320046035639327541844068036880344152450561523438e-01, // 2.000000
+ 7.32915541350616539517659475677646696567535400390625e-01, // 2.718282
+ 7.59872119711751947690459019213449209928512573242188e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_GEV_PDF_M1_05_1 = { //
+ 5.41341132946450809271254911436699330806732177734375e-01, // 0.000000
+ 5.41341132729920015975721980794332921504974365234375e-01, // 0.000010
+ 5.24654452326560716279857388144591823220252990722656e-01, // 0.100000
+ 5.17363942213228455990758902771631255745887756347656e-01, // 0.123457
+ 4.89083747840358629144219548834371380507946014404297e-01, // 0.200000
+ 4.59489810014122646020240381403709761798381805419922e-01, // 0.271828
+ 4.47663745094046994221770319200004450976848602294922e-01, // 0.300000
+ 4.41727385996091959086129463685210794210433959960938e-01, // 0.314159
+ 4.06411096059142717962231472483836114406585693359375e-01, // 0.400000
+ 3.67879441171442334024277442949824035167694091796875e-01, // 0.500000
+ 3.32967207875316584253511109636747278273105621337891e-01, // 0.600000
+ 3.01804311463248764457745210165739990770816802978516e-01, // 0.700000
+ 2.74183058716671756993576991590089164674282073974609e-01, // 0.800000
+ 2.49766152835180110791668539604870602488517761230469e-01, // 0.900000
+ 2.28185386236707560270176031735900323837995529174805e-01, // 1.000000
+ 2.09086495515230508246418139606248587369918823242188e-01, // 1.100000
+ 1.92147533910709572557706792395038064569234848022461e-01, // 1.200000
+ 1.77084389116491575100198474501667078584432601928711e-01, // 1.300000
+ 1.63650280859066965533088477968703955411911010742188e-01, // 1.400000
+ 1.51632664928158328310203728506166953593492507934570e-01, // 1.500000
+ 1.40849242089671561339869754192477557808160781860352e-01, // 1.600000
+ 1.31143888210802028737589353113435208797454833984375e-01, // 1.700000
+ 1.22382871849510632689117528570932336151599884033203e-01, // 1.800000
+ 1.14451498298688142396528633071284275501966476440430e-01, // 1.900000
+ 1.07251207365702289076025977010431233793497085571289e-01, // 2.000000
+ 7.07629263898439941904427996632875874638557434082031e-02, // 2.718282
+ 5.73004168913721634304181407060241326689720153808594e-02, // 3.141593
+ };
+
+ public static final double[] SCIPY_GEV_CDF_M1_05_05 = { //
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.000000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.000010
+ 6.73794699908546092931294069217074138578027486801147e-03, // 0.100000
+ 1.74223231302814106358223256165729253552854061126709e-02, // 0.123457
+ 8.20849986238987999742633405730884987860918045043945e-02, // 0.200000
+ 1.58913189180960978674761463480535894632339477539062e-01, // 0.271828
+ 1.88875602837561828994950019477983005344867706298828e-01, // 0.300000
+ 2.03609887745644979606396418603253550827503204345703e-01, // 0.314159
+ 2.86504796860190091845055349040194414556026458740234e-01, // 0.400000
+ 3.67879441171442334024277442949824035167694091796875e-01, // 0.500000
+ 4.34598208507078198614692610135534778237342834472656e-01, // 0.600000
+ 4.89541659556953112630850455389008857309818267822266e-01, // 0.700000
+ 5.35261428518990278746514377417042851448059082031250e-01, // 0.800000
+ 5.73753420737432739962002870015567168593406677246094e-01, // 0.900000
+ 6.06530659712633424263117376540321856737136840820312e-01, // 1.000000
+ 6.34736418940281876821529749577166512608528137207031e-01, // 1.100000
+ 6.59240630200443766817386403999989852309226989746094e-01, // 1.200000
+ 6.80712398323385370346727540891151875257492065429688e-01, // 1.300000
+ 6.99672537375130243475496172322891652584075927734375e-01, // 1.400000
+ 7.16531310573789270712552479380974546074867248535156e-01, // 1.500000
+ 7.31615628946641782803794740175362676382064819335938e-01, // 1.600000
+ 7.45188817013480497841726446495158597826957702636719e-01, // 1.700000
+ 7.57465128396966447255067578225862234830856323242188e-01, // 1.800000
+ 7.68620526593735697851172972150379791855812072753906e-01, // 1.900000
+ 7.78800783071404878477039801509818062186241149902344e-01, // 2.000000
+ 8.31985953941138611789085643977159634232521057128906e-01, // 2.718282
+ 8.52864203314464663918670339626260101795196533203125e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_GEV_PDF_M1_05_05 = { //
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.000000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.000010
+ 3.36897349954273117589309549657627940177917480468750e-01, // 0.100000
+ 5.71540144737188726686838435853132978081703186035156e-01, // 0.123457
+ 1.02606248279873502049497346888529136776924133300781e+00, // 0.200000
+ 1.07532807339193881013272857671836391091346740722656e+00, // 0.271828
+ 1.04930890465312143255971477628918364644050598144531e+00, // 0.300000
+ 1.03149974138361355535664642957272008061408996582031e+00, // 0.314159
+ 8.95327490188093988443540638400008901953697204589844e-01, // 0.400000
+ 7.35758882342884668048554885899648070335388183593750e-01, // 0.500000
+ 6.03608622926497528915490420331479981541633605957031e-01, // 0.600000
+ 4.99532305670360443627942004241049289703369140625000e-01, // 0.700000
+ 4.18172991030461016492836279212497174739837646484375e-01, // 0.800000
+ 3.54168778232983150200396949003334157168865203857422e-01, // 0.900000
+ 3.03265329856316656620407457012333907186985015869141e-01, // 1.000000
+ 2.62287776421604057475178706226870417594909667968750e-01, // 1.100000
+ 2.28902996597376284793057266142568551003932952880859e-01, // 1.200000
+ 2.01394200687392110893370045232586562633514404296875e-01, // 1.300000
+ 1.78487892187533275789590447857335675507783889770508e-01, // 1.400000
+ 1.59229180127508751496634431532584130764007568359375e-01, // 1.500000
+ 1.42893677528640961060801828352850861847400665283203e-01, // 1.600000
+ 1.28925400867384215564115379493159707635641098022461e-01, // 1.700000
+ 1.16892766727926894487765707708604168146848678588867e-01, // 1.800000
+ 1.06457136647331848666730991226359037682414054870605e-01, // 1.900000
+ 9.73500978839256236874177830031840130686759948730469e-02, // 2.000000
+ 5.62985273627536753071609609833103604614734649658203e-02, // 2.718282
+ 4.32066052830005001283986132420977810397744178771973e-02, // 3.141593
+ };
+
+ public static final double[] SCIPY_GEV_CDF_M2_05_05 = { //
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.000000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.000010
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.100000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.123457
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.200000
+ 3.39033836807548852321225751893507549539208412170410e-02, // 0.271828
+ 1.06877925660385744710545452562655555084347724914551e-01, // 0.300000
+ 1.38904458384038836937790506453893613070249557495117e-01, // 0.314159
+ 2.74997176473929239026716686566942371428012847900391e-01, // 0.400000
+ 3.67879441171442334024277442949824035167694091796875e-01, // 0.500000
+ 4.29491102067359131755353018888854421675205230712891e-01, // 0.600000
+ 4.74565328167800615233318239916115999221801757812500e-01, // 0.700000
+ 5.09563978801319317213369686214718967676162719726562e-01, // 0.800000
+ 5.37851019311739397821270358690526336431503295898438e-01, // 0.900000
+ 5.61383913798928158023215928551508113741874694824219e-01, // 1.000000
+ 5.81394271093278680595517471374478191137313842773438e-01, // 1.100000
+ 5.98703271909381884441359034099150449037551879882812e-01, // 1.200000
+ 6.13883544062845620814528047048952430486679077148438e-01, // 1.300000
+ 6.27348918610303951659545873553724959492683410644531e-01, // 1.400000
+ 6.39407319161897080839196405577240511775016784667969e-01, // 1.500000
+ 6.50293497809677822907303834654157981276512145996094e-01, // 1.600000
+ 6.60190136880002498287467460613697767257690429687500e-01, // 1.700000
+ 6.69241923627019841269714106601895764470100402832031e-01, // 1.800000
+ 6.77565215323516878420662123971851542592048645019531e-01, // 1.900000
+ 6.85254845275987456432176259113475680351257324218750e-01, // 2.000000
+ 7.27418661477164829598507367336424067616462707519531e-01, // 2.718282
+ 7.45249186715569389427571422856999561190605163574219e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_GEV_PDF_M2_05_05 = { //
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.000000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.000010
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.100000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.123457
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.200000
+ 2.62818951667170752628521768201608210802078247070312e+00, // 0.271828
+ 2.38986307070791648143881502619478851556777954101562e+00, // 0.300000
+ 2.13681596745114710245161404600366950035095214843750e+00, // 0.314159
+ 1.18339942748621074208870140864746645092964172363281e+00, // 0.400000
+ 7.35758882342884668048554885899648070335388183593750e-01, // 0.500000
+ 5.18551760400383088267517450731247663497924804687500e-01, // 0.600000
+ 3.93022345758406721483169121711398474872112274169922e-01, // 0.700000
+ 3.12316331294610671776013077760580927133560180664062e-01, // 0.800000
+ 2.56585417034103147049250992495217360556125640869141e-01, // 0.900000
+ 2.16076769167024562712242641282500699162483215332031e-01, // 1.000000
+ 1.85473713825601238536222581387846730649471282958984e-01, // 1.100000
+ 1.61646472710941485617652801920485217124223709106445e-01, // 1.200000
+ 1.42640237007817916037311078980565071105957031250000e-01, // 1.300000
+ 1.27175191967058648367938644696550909429788589477539e-01, // 1.400000
+ 1.14380658476552446445317912093742052093148231506348e-01, // 1.500000
+ 1.03645098237195559809364908687712159007787704467773e-01, // 1.600000
+ 9.45272529515622100815264161610684823244810104370117e-02, // 1.700000
+ 8.67012981885665195980195107949839439243078231811523e-02, // 1.800000
+ 7.99217885954443957308157564511930104345083236694336e-02, // 1.900000
+ 7.40005675633594872664389185956679284572601318359375e-02, // 2.000000
+ 4.68956249886947687532945394650596426799893379211426e-02, // 2.718282
+ 3.78909810913142866550806786563043715432286262512207e-02, // 3.141593
+ };
+
+ public static final double[] SCIPY_GEV_CDF_M4_05_05 = { //
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.000000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.000010
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.100000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.123457
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.200000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.271828
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.300000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.314159
+ 2.24170404666470146626267023748368956148624420166016e-01, // 0.400000
+ 3.67879441171442334024277442949824035167694091796875e-01, // 0.500000
+ 4.21751069637636921694223701706505380570888519287109e-01, // 0.600000
+ 4.54975793697936503612311298638815060257911682128906e-01, // 0.700000
+ 4.78821231609222464076225378448725678026676177978516e-01, // 0.800000
+ 4.97313729450705732659798741224221885204315185546875e-01, // 0.900000
+ 5.12353580703692190745357493142364546656608581542969e-01, // 1.000000
+ 5.24987194441984716952731560013489797711372375488281e-01, // 1.100000
+ 5.35851286369152468580523418495431542396545410156250e-01, // 1.200000
+ 5.45361563592452358584239391348091885447502136230469e-01, // 1.300000
+ 5.53804088898205759683435189799638465046882629394531e-01, // 1.400000
+ 5.61383913798928158023215928551508113741874694824219e-01, // 1.500000
+ 5.68252899326986526951088762871222570538520812988281e-01, // 1.600000
+ 5.74526561677133451588872503634775057435035705566406e-01, // 1.700000
+ 5.80294753258350115565633586811600252985954284667969e-01, // 1.800000
+ 5.85628698455619600693466964003164321184158325195312e-01, // 1.900000
+ 5.90585779600685034651519345061387866735458374023438e-01, // 2.000000
+ 6.18420715153379818573853299312759190797805786132812e-01, // 2.718282
+ 6.30625716653393175725739183690166100859642028808594e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_GEV_PDF_M4_05_05 = { //
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.000000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.000010
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.100000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.123457
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.200000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.271828
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.300000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.314159
+ 3.35212941403873543322333716787397861480712890625000e+00, // 0.400000
+ 7.35758882342884668048554885899648070335388183593750e-01, // 0.500000
+ 4.04571752748853263881301245419308543205261230468750e-01, // 0.600000
+ 2.75614208099633994919486212893389165401458740234375e-01, // 0.700000
+ 2.07421967170040077999004779485403560101985931396484e-01, // 0.800000
+ 1.65424119506986211369792272307677194476127624511719e-01, // 0.900000
+ 1.37052595926219600297457645865506492555141448974609e-01, // 1.000000
+ 1.16652409536449619409381739387754350900650024414062e-01, // 1.100000
+ 1.01308142799496639363532324296102160587906837463379e-01, // 1.200000
+ 8.93665252759350547950845111699891276657581329345703e-02, // 1.300000
+ 7.98213076346705047159346690932579804211854934692383e-02, // 1.400000
+ 7.20255897223414931485052647985867224633693695068359e-02, // 1.500000
+ 6.55449235573613425698269452368549536913633346557617e-02, // 1.600000
+ 6.00769361394048809210666206581663573160767555236816e-02, // 1.700000
+ 5.54048234603983710822028285747364861890673637390137e-02, // 1.800000
+ 5.13691711403654951983988041774864541366696357727051e-02, // 1.900000
+ 4.78502036963653620826875112470588646829128265380859e-02, // 2.000000
+ 3.17081485900912798947537396543339127674698829650879e-02, // 2.718282
+ 2.62728789480732756456138332623595488257706165313721e-02, // 3.141593
+ };
+
+ public static final double[] P_QUANT = { //
+ 0.0001, 0.001, 0.01, 0.1, 0.25, 0.5, 0.75, 0.9, 0.99, 0.999, 0.9999 //
+ };
+
+ public static final double[] SCIPY_GUMBEL_QUANT_1_1 = { //
+ -1.22032680636784629513158506597392261028289794921875e+00, // 0.000100
+ -9.32644733916065504786274686921387910842895507812500e-01, // 0.001000
+ -5.27179625807901119927123545494396239519119262695312e-01, // 0.010000
+ 1.65967554752044277321942900016438215970993041992188e-01, // 0.100000
+ 6.73365740021719005881095654331147670745849609375000e-01, // 0.250000
+ 1.36651292058166440313016209984198212623596191406250e+00, // 0.500000
+ 2.24589932370723843746418424416333436965942382812500e+00, // 0.750000
+ 3.25036732731244537575321373878978192806243896484375e+00, // 0.900000
+ 5.60014922677657889238389543606899678707122802734375e+00, // 0.990000
+ 7.90725507052371590077655127970501780509948730468750e+00, // 0.999000
+ 1.02102903698928351161612226860597729682922363281250e+01, // 0.999900
+ };
+
+ public static final double[] SCIPY_GUMBEL_QUANT_2_1 = { //
+ -2.20326806367846295131585065973922610282897949218750e-01, // 0.000100
+ 6.73552660839344952137253130786120891571044921875000e-02, // 0.001000
+ 4.72820374192098880072876454505603760480880737304688e-01, // 0.010000
+ 1.16596755475204427732194290001643821597099304199219e+00, // 0.100000
+ 1.67336574002171900588109565433114767074584960937500e+00, // 0.250000
+ 2.36651292058166440313016209984198212623596191406250e+00, // 0.500000
+ 3.24589932370723843746418424416333436965942382812500e+00, // 0.750000
+ 4.25036732731244537575321373878978192806243896484375e+00, // 0.900000
+ 6.60014922677657889238389543606899678707122802734375e+00, // 0.990000
+ 8.90725507052371590077655127970501780509948730468750e+00, // 0.999000
+ 1.12102903698928351161612226860597729682922363281250e+01, // 0.999900
+ };
+
+ public static final double[] SCIPY_GUMBEL_QUANT_4_1 = { //
+ 1.77967319363215370486841493402607738971710205078125e+00, // 0.000100
+ 2.06735526608393449521372531307861208915710449218750e+00, // 0.001000
+ 2.47282037419209910211748137953691184520721435546875e+00, // 0.010000
+ 3.16596755475204449936654782504774630069732666015625e+00, // 0.100000
+ 3.67336574002171900588109565433114767074584960937500e+00, // 0.250000
+ 4.36651292058166440313016209984198212623596191406250e+00, // 0.500000
+ 5.24589932370723843746418424416333436965942382812500e+00, // 0.750000
+ 6.25036732731244537575321373878978192806243896484375e+00, // 0.900000
+ 8.60014922677657978056231513619422912597656250000000e+00, // 0.990000
+ 1.09072550705237159007765512797050178050994873046875e+01, // 0.999000
+ 1.32102903698928351161612226860597729682922363281250e+01, // 0.999900
+ };
+
+ public static final double[] SCIPY_GUMBEL_QUANT_4_10 = { //
+ -1.82032680636784647276726900599896907806396484375000e+01, // 0.000100
+ -1.53264473391606550478627468692138791084289550781250e+01, // 0.001000
+ -1.12717962580790107551820256048813462257385253906250e+01, // 0.010000
+ -4.34032445247955678269136114977300167083740234375000e+00, // 0.100000
+ 7.33657400217190502900166393374092876911163330078125e-01, // 0.250000
+ 7.66512920581664403130162099841982126235961914062500e+00, // 0.500000
+ 1.64589932370723843746418424416333436965942382812500e+01, // 0.750000
+ 2.65036732731244555338889767881482839584350585937500e+01, // 0.900000
+ 5.00014922677657907001957937609404325485229492187500e+01, // 0.990000
+ 7.30725507052371625604791915975511074066162109375000e+01, // 0.999000
+ 9.61029036989283440561848692595958709716796875000000e+01, // 0.999900
+ };
+
+ public static final double[] SCIPY_GUMBEL_QUANT_01_10 = { //
+ -2.21032680636784633065872185397893190383911132812500e+01, // 0.000100
+ -1.92264473391606536267772753490135073661804199218750e+01, // 0.001000
+ -1.51717962580790111104533934849314391613006591796875e+01, // 0.010000
+ -8.24032445247955713796272902982309460639953613281250e+00, // 0.100000
+ -3.16634259978280940828199163661338388919830322265625e+00, // 0.250000
+ 3.76512920581664367603025311836972832679748535156250e+00, // 0.500000
+ 1.25589932370723822430136351613327860832214355468750e+01, // 0.750000
+ 2.26036732731244569549744483083486557006835937500000e+01, // 0.900000
+ 4.61014922677657921212812652811408042907714843750000e+01, // 0.990000
+ 6.91725507052371568761373055167496204376220703125000e+01, // 0.999000
+ 9.22029036989283383718429831787943840026855468750000e+01, // 0.999900
+ };
+
+ public static final double[] SCIPY_GUMBEL_QUANT_01_20 = { //
+ -4.43065361273569280342599085997790098190307617187500e+01, // 0.000100
+ -3.85528946783213086746400222182273864746093750000000e+01, // 0.001000
+ -3.04435925161580200892785796895623207092285156250000e+01, // 0.010000
+ -1.65806489049591121442972507793456315994262695312500e+01, // 0.100000
+ -6.43268519956561934947103509330190718173980712890625e+00, // 0.250000
+ 7.43025841163328681915345441666431725025177001953125e+00, // 0.500000
+ 2.50179864741447666176554776029661297798156738281250e+01, // 0.750000
+ 4.51073465462489124888634250964969396591186523437500e+01, // 0.900000
+ 9.21029845355315757160497014410793781280517578125000e+01, // 0.990000
+ 1.38245101410474319436616497114300727844238281250000e+02, // 0.999000
+ 1.84305807397856682428027852438390254974365234375000e+02, // 0.999900
+ };
+
+ public static final double[] SCIPY_GUMBEL_QUANT_01_4 = { //
+ -8.78130722547138553579770814394578337669372558593750e+00, // 0.000100
+ -7.63057893566426237441646662773564457893371582031250e+00, // 0.001000
+ -6.00871850323160483497986206202767789363861083984375e+00, // 0.010000
+ -3.23612978099182280189438642992172390222549438476562e+00, // 0.100000
+ -1.20653703991312366561317048763157799839973449707031e+00, // 0.250000
+ 1.56605168232665747929388544434914365410804748535156e+00, // 0.500000
+ 5.08359729482895250640694939647801220417022705078125e+00, // 0.750000
+ 9.10146930924978114774148707510903477668762207031250e+00, // 0.900000
+ 1.85005969071063169906210532644763588905334472656250e+01, // 0.990000
+ 2.77290202820948650241916766390204429626464843750000e+01, // 0.999000
+ 3.69411614795713418857303622644394636154174804687500e+01, // 0.999900
+ };
+
+ public static final double[] SCIPY_GUMBEL_QUANT_01_1 = { //
+ -2.12032680636784620631374309596139937639236450195312e+00, // 0.000100
+ -1.83264473391606541596843271690886467695236206054688e+00, // 0.001000
+ -1.42717962580790103110928157548187300562858581542969e+00, // 0.010000
+ -7.34032445247955744882517592486692592501640319824219e-01, // 0.100000
+ -2.26634259978280933056637991285242605954408645629883e-01, // 0.250000
+ 4.66512920581664380925701607338851317763328552246094e-01, // 0.500000
+ 1.34589932370723830423742128914454951882362365722656e+00, // 0.750000
+ 2.35036732731244546457105570880230516195297241210938e+00, // 0.900000
+ 4.70014922677657853711252755601890385150909423828125e+00, // 0.990000
+ 7.00725507052371554550518339965492486953735351562500e+00, // 0.999000
+ 9.31029036989283476088985480600968003273010253906250e+00, // 0.999900
+ };
+
+ public static final double[] SCIPY_GEV_QUANT_1_05_1 = { //
+ -7.71034037197618182801761577138677239418029785156250e+00, // 0.000100
+ -5.40775527898213681510242167860269546508789062500000e+00, // 0.001000
+ -3.10517018598809135809801773575600236654281616210938e+00, // 0.010000
+ -8.02585092994045457004403942846693098545074462890625e-01, // 0.100000
+ 1.13705638880109427546472034009639173746109008789062e-01, // 0.250000
+ 8.06852819440054713773236017004819586873054504394531e-01, // 0.500000
+ 1.21231792754821920965468962094746530055999755859375e+00, // 0.750000
+ 1.39463948434217366312282138096634298563003540039062e+00, // 0.900000
+ 1.48994966414649843144957230833824723958969116210938e+00, // 0.990000
+ 1.49899949966641643506193304347107186913490295410156e+00, // 0.999000
+ 1.49989999499966675244877478689886629581451416015625e+00, // 0.999900
+ };
+
+ public static final double[] SCIPY_GEV_QUANT_1_05_05 = { //
+ -3.60517018598809091400880788569338619709014892578125e+00, // 0.000100
+ -2.45387763949106840755121083930134773254394531250000e+00, // 0.001000
+ -1.30258509299404567904900886787800118327140808105469e+00, // 0.010000
+ -1.51292546497022728502201971423346549272537231445312e-01, // 0.100000
+ 3.06852819440054713773236017004819586873054504394531e-01, // 0.250000
+ 6.53426409720027301375466777244582772254943847656250e-01, // 0.500000
+ 8.56158963774109604827344810473732650279998779296875e-01, // 0.750000
+ 9.47319742171086831561410690483171492815017700195312e-01, // 0.900000
+ 9.94974832073249215724786154169123619794845581054688e-01, // 0.990000
+ 9.99499749833208217530966521735535934567451477050781e-01, // 0.999000
+ 9.99949997499833376224387393449433147907257080078125e-01, // 0.999900
+ };
+
+ public static final double[] SCIPY_GEV_QUANT_2_05_05 = { //
+ -2.04575924419135866116903343936428427696228027343750e+01, // 0.000100
+ -1.11792707485763962438340968219563364982604980468750e+01, // 0.001000
+ -4.55189811047839842927942299866117537021636962890625e+00, // 0.010000
+ -5.75474527619599385275250824633985757827758789062500e-01, // 0.100000
+ 2.69546986081798611856186198565410450100898742675781e-01, // 0.250000
+ 6.29886746520449625208470934012439101934432983398438e-01, // 0.500000
+ 7.29309756297462086216398802207550033926963806152344e-01, // 0.750000
+ 7.47224790435079277983732026768848299980163574218750e-01, // 0.900000
+ 7.49974747687307985444249425199814140796661376953125e-01, // 0.990000
+ 7.49999749749770572293527948204427957534790039062500e-01, // 0.999000
+ 7.49999997499749992968531842052470892667770385742188e-01, // 0.999900
+ };
+
+ public static final double[] SCIPY_GEV_QUANT_4_05_05 = { //
+ -8.98898954364620522028417326509952545166015625000000e+02, // 0.000100
+ -2.83990001185680910111841512843966484069824218750000e+02, // 0.001000
+ -5.55952471477888181539128709118813276290893554687500e+01, // 0.010000
+ -2.88876544673679980235192488180473446846008300781250e+00, // 0.100000
+ 1.63329802833833193087542667853995226323604583740234e-01, // 0.250000
+ 5.96145612677114522526267137436661869287490844726562e-01, // 0.500000
+ 6.24143827631059133764779289776924997568130493164062e-01, // 0.750000
+ 6.24984596423741489701342288753949105739593505859375e-01, // 0.900000
+ 6.24999998724641403491375513112870976328849792480469e-01, // 0.990000
+ 6.24999999999874766842822282342240214347839355468750e-01, // 0.999000
+ 6.25000000000000000000000000000000000000000000000000e-01, // 0.999900
+ };
+
+ public static final double[] SCIPY_GEV_QUANT_M1_05_1 = { //
+ -3.91426379524187018077441280183847993612289428710938e-01, // 0.000100
+ -3.55235172698916024103255040245130658149719238281250e-01, // 0.001000
+ -2.82852759048374036154882560367695987224578857421875e-01, // 0.010000
+ -6.57055180967481833320675832510460168123245239257812e-02, // 0.100000
+ 2.21347520444481749013476701293257065117359161376953e-01, // 0.250000
+ 9.42695040888963387004650940070860087871551513671875e-01, // 0.500000
+ 2.97605949678220671472672620438970625400543212890625e+00, // 0.750000
+ 8.99122158102990454153768951073288917541503906250000e+00, // 0.900000
+ 9.89991624734220607706447481177747249603271484375000e+01, // 0.990000
+ 9.98999916624973025136569049209356307983398437500000e+02, // 0.999000
+ 9.99899999166735688049811869859695434570312500000000e+03, // 0.999900
+ };
+
+ public static final double[] SCIPY_GEV_QUANT_M1_05_05 = { //
+ 5.42868102379064909612793599080760031938552856445312e-02, // 0.000100
+ 7.23824136505419879483724798774346709251403808593750e-02, // 0.001000
+ 1.08573620475812981922558719816152006387710571289062e-01, // 0.010000
+ 2.17147240951625908333966208374476991593837738037109e-01, // 0.100000
+ 3.60673760222240846751162735017715021967887878417969e-01, // 0.250000
+ 7.21347520444481693502325470035430043935775756835938e-01, // 0.500000
+ 1.73802974839110335736336310219485312700271606445312e+00, // 0.750000
+ 4.74561079051495227076884475536644458770751953125000e+00, // 0.900000
+ 4.97495812367110303853223740588873624801635742187500e+01, // 0.990000
+ 4.99749958312486512568284524604678153991699218750000e+02, // 0.999000
+ 4.99974999583367844024905934929847717285156250000000e+03, // 0.999900
+ };
+
+ public static final double[] SCIPY_GEV_QUANT_M2_05_05 = { //
+ 2.52947057765806504470162963116308674216270446777344e-01, // 0.000100
+ 2.55239213805878162322215985113871283829212188720703e-01, // 0.001000
+ 2.61788231063225906858349389949580654501914978027344e-01, // 0.010000
+ 2.97152924252903516411095097282668575644493103027344e-01, // 0.100000
+ 3.80085561312850483961511827146750874817371368408203e-01, // 0.250000
+ 7.70342245251401935846047308587003499269485473632812e-01, // 0.500000
+ 3.27074740629244242740014669834636151790618896484375e+00, // 0.750000
+ 2.27708217750519459343649941729381680488586425781250e+01, // 0.900000
+ 2.47527083322811040488886646926403045654296875000000e+03, // 0.990000
+ 2.49750270833332004258409142494201660156250000000000e+05, // 0.999000
+ 2.49975002708388678729534149169921875000000000000000e+07, // 0.999900
+ };
+
+ public static final double[] SCIPY_GEV_QUANT_M4_05_05 = { //
+ 3.75017370298949992424297761317575350403785705566406e-01, // 0.000100
+ 3.75054898722607388261707228593877516686916351318359e-01, // 0.001000
+ 3.75277924783199989811066643596859648823738098144531e-01, // 0.010000
+ 3.79446796531200114532822453838889487087726593017578e-01, // 0.100000
+ 4.08844506524158768367982474956079386174678802490234e-01, // 0.250000
+ 9.16512104386540293887719599297270178794860839843750e-01, // 0.500000
+ 1.86248297852450370726273831678554415702819824218750e+01, // 0.750000
+ 1.01474982684730787241278449073433876037597656250000e+03, // 0.900000
+ 1.22514566248263381421566009521484375000000000000000e+07, // 0.990000
+ 1.24750145812874526977539062500000000000000000000000e+11, // 0.999000
+ 1.24975001458367900000000000000000000000000000000000e+15, // 0.999900
+ };
+
+ @Test
+ public void testPDF() {
+ // Gumbel case:
+ checkPDF(new GeneralizedExtremeValueDistribution(1., 1., 0.), P_CDFPDF, SCIPY_GUMBEL_PDF_1_1, 1e-12);
+ checkPDF(new GeneralizedExtremeValueDistribution(2., 1., 0.), P_CDFPDF, SCIPY_GUMBEL_PDF_2_1, 1e-12);
+ checkPDF(new GeneralizedExtremeValueDistribution(4., 1., 0.), P_CDFPDF, SCIPY_GUMBEL_PDF_4_1, 1e-11);
+ checkPDF(new GeneralizedExtremeValueDistribution(4., 10., 0.), P_CDFPDF, SCIPY_GUMBEL_PDF_4_10, 1e-13);
+ checkPDF(new GeneralizedExtremeValueDistribution(.1, 1., 0.), P_CDFPDF, SCIPY_GUMBEL_PDF_01_1, 1e-12);
+ checkPDF(new GeneralizedExtremeValueDistribution(.1, 4., 0.), P_CDFPDF, SCIPY_GUMBEL_PDF_01_4, 1e-12);
+ checkPDF(new GeneralizedExtremeValueDistribution(.1, 10., 0.), P_CDFPDF, SCIPY_GUMBEL_PDF_01_10, 1e-13);
+ checkPDF(new GeneralizedExtremeValueDistribution(.1, 20., 0.), P_CDFPDF, SCIPY_GUMBEL_PDF_01_20, 1e-14);
+ // Regular:
+ checkPDF(new GeneralizedExtremeValueDistribution(.5, 1, -1.), P_CDFPDF, SCIPY_GEV_PDF_1_05_1, 1e-13);
+ checkPDF(new GeneralizedExtremeValueDistribution(.5, .5, -1.), P_CDFPDF, SCIPY_GEV_PDF_1_05_05, 1e-12);
+ checkPDF(new GeneralizedExtremeValueDistribution(.5, .5, -2.), P_CDFPDF, SCIPY_GEV_PDF_2_05_05, 1e-12);
+ checkPDF(new GeneralizedExtremeValueDistribution(.5, .5, -4.), P_CDFPDF, SCIPY_GEV_PDF_4_05_05, 1e-12);
+ checkPDF(new GeneralizedExtremeValueDistribution(.5, 1, 1.), P_CDFPDF, SCIPY_GEV_PDF_M1_05_1, 1e-12);
+ checkPDF(new GeneralizedExtremeValueDistribution(.5, .5, 1.), P_CDFPDF, SCIPY_GEV_PDF_M1_05_05, 1e-12);
+ checkPDF(new GeneralizedExtremeValueDistribution(.5, .5, 2.), P_CDFPDF, SCIPY_GEV_PDF_M2_05_05, 1e-12);
+ checkPDF(new GeneralizedExtremeValueDistribution(.5, .5, 4.), P_CDFPDF, SCIPY_GEV_PDF_M4_05_05, 1e-12);
+ }
+
+ @Test
+ public void testCDF() {
+ // Gumbel case.
+ checkCDF(new GeneralizedExtremeValueDistribution(1., 1., 0.), P_CDFPDF, SCIPY_GUMBEL_CDF_1_1, 1e-12);
+ checkCDF(new GeneralizedExtremeValueDistribution(2., 1., 0.), P_CDFPDF, SCIPY_GUMBEL_CDF_2_1, 1e-12);
+ checkCDF(new GeneralizedExtremeValueDistribution(4., 1., 0.), P_CDFPDF, SCIPY_GUMBEL_CDF_4_1, 1e-11);
+ checkCDF(new GeneralizedExtremeValueDistribution(4., 10., 0.), P_CDFPDF, SCIPY_GUMBEL_CDF_4_10, 1e-12);
+ checkCDF(new GeneralizedExtremeValueDistribution(.1, 1., 0.), P_CDFPDF, SCIPY_GUMBEL_CDF_01_1, 1e-13);
+ checkCDF(new GeneralizedExtremeValueDistribution(.1, 4., 0.), P_CDFPDF, SCIPY_GUMBEL_CDF_01_4, 1e-13);
+ checkCDF(new GeneralizedExtremeValueDistribution(.1, 10., 0.), P_CDFPDF, SCIPY_GUMBEL_CDF_01_10, 1e-13);
+ checkCDF(new GeneralizedExtremeValueDistribution(.1, 20., 0.), P_CDFPDF, SCIPY_GUMBEL_CDF_01_20, 1e-13);
+ // Regular:
+ checkCDF(new GeneralizedExtremeValueDistribution(.5, 1., -1.), P_CDFPDF, SCIPY_GEV_CDF_1_05_1, 1e-13);
+ checkCDF(new GeneralizedExtremeValueDistribution(.5, .5, -1.), P_CDFPDF, SCIPY_GEV_CDF_1_05_05, 1e-12);
+ checkCDF(new GeneralizedExtremeValueDistribution(.5, .5, -2.), P_CDFPDF, SCIPY_GEV_CDF_2_05_05, 1e-12);
+ checkCDF(new GeneralizedExtremeValueDistribution(.5, .5, -4.), P_CDFPDF, SCIPY_GEV_CDF_4_05_05, 1e-13);
+ checkCDF(new GeneralizedExtremeValueDistribution(.5, 1., 1.), P_CDFPDF, SCIPY_GEV_CDF_M1_05_1, 1e-12);
+ checkCDF(new GeneralizedExtremeValueDistribution(.5, .5, 1.), P_CDFPDF, SCIPY_GEV_CDF_M1_05_05, 1e-12);
+ checkCDF(new GeneralizedExtremeValueDistribution(.5, .5, 2.), P_CDFPDF, SCIPY_GEV_CDF_M2_05_05, 1e-12);
+ checkCDF(new GeneralizedExtremeValueDistribution(.5, .5, 4.), P_CDFPDF, SCIPY_GEV_CDF_M4_05_05, 1e-13);
+ }
+
+ @Test
+ public void testQuantile() {
+ // Gumbel case:
+ checkQuantile(new GeneralizedExtremeValueDistribution(1., 1., 0.), P_QUANT, SCIPY_GUMBEL_QUANT_1_1, 1e-13);
+ checkQuantile(new GeneralizedExtremeValueDistribution(2., 1., 0.), P_QUANT, SCIPY_GUMBEL_QUANT_2_1, 1e-13);
+ checkQuantile(new GeneralizedExtremeValueDistribution(4., 1., 0.), P_QUANT, SCIPY_GUMBEL_QUANT_4_1, 1e-13);
+ checkQuantile(new GeneralizedExtremeValueDistribution(4., 10., 0.), P_QUANT, SCIPY_GUMBEL_QUANT_4_10, 1e-13);
+ checkQuantile(new GeneralizedExtremeValueDistribution(.1, 1., 0.), P_QUANT, SCIPY_GUMBEL_QUANT_01_1, 1e-13);
+ checkQuantile(new GeneralizedExtremeValueDistribution(.1, 4., 0.), P_QUANT, SCIPY_GUMBEL_QUANT_01_4, 1e-13);
+ checkQuantile(new GeneralizedExtremeValueDistribution(.1, 10., 0.), P_QUANT, SCIPY_GUMBEL_QUANT_01_10, 1e-13);
+ checkQuantile(new GeneralizedExtremeValueDistribution(.1, 20., 0.), P_QUANT, SCIPY_GUMBEL_QUANT_01_20, 1e-13);
+ // Regular:
+ checkQuantile(new GeneralizedExtremeValueDistribution(.5, 1., -1.), P_QUANT, SCIPY_GEV_QUANT_1_05_1, 1e-13);
+ checkQuantile(new GeneralizedExtremeValueDistribution(.5, .5, -1.), P_QUANT, SCIPY_GEV_QUANT_1_05_05, 1e-13);
+ checkQuantile(new GeneralizedExtremeValueDistribution(.5, .5, -2.), P_QUANT, SCIPY_GEV_QUANT_2_05_05, 1e-13);
+ checkQuantile(new GeneralizedExtremeValueDistribution(.5, .5, -4.), P_QUANT, SCIPY_GEV_QUANT_4_05_05, 1e-13);
+ checkQuantile(new GeneralizedExtremeValueDistribution(.5, 1., 1.), P_QUANT, SCIPY_GEV_QUANT_M1_05_1, 1e-13);
+ checkQuantile(new GeneralizedExtremeValueDistribution(.5, .5, 1.), P_QUANT, SCIPY_GEV_QUANT_M1_05_05, 1e-15);
+ checkQuantile(new GeneralizedExtremeValueDistribution(.5, .5, 2.), P_QUANT, SCIPY_GEV_QUANT_M2_05_05, 1e-14);
+ checkQuantile(new GeneralizedExtremeValueDistribution(.5, .5, 4.), P_QUANT, SCIPY_GEV_QUANT_M4_05_05, 1e-14);
+ }
+}
diff --git a/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestGeneralizedLogisticDistribution.java b/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestGeneralizedLogisticDistribution.java
new file mode 100644
index 00000000..3aa83362
--- /dev/null
+++ b/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestGeneralizedLogisticDistribution.java
@@ -0,0 +1,364 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2012
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import org.junit.Test;
+
+import de.lmu.ifi.dbs.elki.JUnit4Test;
+
+/**
+ * Unit test for the Generalized Logistic distribution in ELKI.
+ *
+ * The reference values were computed using GNU R and SciPy.
+ *
+ * @author Erich Schubert
+ */
+public class TestGeneralizedLogisticDistribution extends AbstractDistributionTest implements JUnit4Test {
+ public static final double[] P_CDFPDF = { //
+ 1e-10, 1e-05, 0.1, 0.1234567, 0.2, 0.271828182846, 0.3, 0.314159265359, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.71828182846, 3.14159265359 //
+ };
+
+ public static final double[] SCIPY_LOGISTIC_CDF_05 = { //
+ 3.77540668821645775121709220911725424230098724365234e-01, // 0.000000
+ 3.77543018838145283400109519789111800491809844970703e-01, // 0.000010
+ 4.01312339887547997463457249978091567754745483398438e-01, // 0.100000
+ 4.06960880864213336849388724658638238906860351562500e-01, // 0.123457
+ 4.25557483188341023616629854586790315806865692138672e-01, // 0.200000
+ 4.43203246664875705196351418635458685457706451416016e-01, // 0.271828
+ 4.50166002687522159853017456043744459748268127441406e-01, // 0.300000
+ 4.53673071561317309274841136357281357049942016601562e-01, // 0.314159
+ 4.75020812521059987432181515032425522804260253906250e-01, // 0.400000
+ 5.00000000000000000000000000000000000000000000000000e-01, // 0.500000
+ 5.24979187478939901545516022451920434832572937011719e-01, // 0.600000
+ 5.49833997312477840146982543956255540251731872558594e-01, // 0.700000
+ 5.74442516811659031894521376671036705374717712402344e-01, // 0.800000
+ 5.98687660112452002536542750021908432245254516601562e-01, // 0.900000
+ 6.22459331201854593196287623868556693196296691894531e-01, // 1.000000
+ 6.45656306225795395548061605950351804494857788085938e-01, // 1.100000
+ 6.68187772168166160824398502882104367017745971679688e-01, // 1.200000
+ 6.89974481127612504494095446716528385877609252929688e-01, // 1.300000
+ 7.10949502625003892930521942616906017065048217773438e-01, // 1.400000
+ 7.31058578630004896048433238320285454392433166503906e-01, // 1.500000
+ 7.50260105595117687826700603181961923837661743164062e-01, // 1.600000
+ 7.68524783499017538623832024313742294907569885253906e-01, // 1.700000
+ 7.85834983042558610222272363898809999227523803710938e-01, // 1.800000
+ 8.02183888558581692507232219213619828224182128906250e-01, // 1.900000
+ 8.17574476193643651100728675373829901218414306640625e-01, // 2.000000
+ 9.01879254389253204315934908663621172308921813964844e-01, // 2.718282
+ 9.33490913616609740977025921893073245882987976074219e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_LOGISTIC_PDF_05 = { //
+ 2.35003712207350168306163595843827351927757263183594e-01, // 0.000000
+ 2.35004287764725150466915692959446460008621215820312e-01, // 0.000010
+ 2.40260745741529169183792191688553430140018463134766e-01, // 0.100000
+ 2.41343722310436908928821253539354074746370315551758e-01, // 0.123457
+ 2.44458311690745860866869065830542240291833877563477e-01, // 0.200000
+ 2.46774128810589049587420618081523571163415908813477e-01, // 0.271828
+ 2.47516572711860005640005510940682142972946166992188e-01, // 0.300000
+ 2.47853815701437218965708098039613105356693267822266e-01, // 0.314159
+ 2.49376040192891945679320997442118823528289794921875e-01, // 0.400000
+ 2.50000000000000000000000000000000000000000000000000e-01, // 0.500000
+ 2.49376040192891945679320997442118823528289794921875e-01, // 0.600000
+ 2.47516572711859950128854279682855121791362762451172e-01, // 0.700000
+ 2.44458311690745888622444681459455750882625579833984e-01, // 0.800000
+ 2.40260745741529169183792191688553430140018463134766e-01, // 0.900000
+ 2.35003712201594494590750628049136139452457427978516e-01, // 1.000000
+ 2.28784240456657267381856968313513789325952529907227e-01, // 1.100000
+ 2.21712873293109097305730870175466407090425491333008e-01, // 1.200000
+ 2.13909696520294428934150232635147403925657272338867e-01, // 1.300000
+ 2.05500307342263432985873805591836571693420410156250e-01, // 1.400000
+ 1.96611933241481878775758218580449465662240982055664e-01, // 1.500000
+ 1.87369879547520601370536041940795257687568664550781e-01, // 1.600000
+ 1.77894440646805707118005557276774197816848754882812e-01, // 1.700000
+ 1.68298362469060241997098614774586167186498641967773e-01, // 1.800000
+ 1.58684897495614651852235965634463354945182800292969e-01, // 1.900000
+ 1.49146452070332835582178176991874352097511291503906e-01, // 2.000000
+ 8.84930648915379924890345364474342204630374908447266e-02, // 2.718282
+ 6.20856278118370533136705091692419955506920814514160e-02, // 3.141593
+ };
+
+ public static final double[] GNUR_LOGISTIC_CDF_05 = { //
+ 3.77540668821645775121709220911725424230098724365234e-01, // 0.000000
+ 3.77543018838145283400109519789111800491809844970703e-01, // 0.000010
+ 4.01312339887547997463457249978091567754745483398438e-01, // 0.100000
+ 4.06960880864213336849388724658638238906860351562500e-01, // 0.123457
+ 4.25557483188341023616629854586790315806865692138672e-01, // 0.200000
+ 4.43203246664899241924473471954115666449069976806641e-01, // 0.271828
+ 4.50166002687522159853017456043744459748268127441406e-01, // 0.300000
+ 4.53673071561322416300754412077367305755615234375000e-01, // 0.314159
+ 4.75020812521059987432181515032425522804260253906250e-01, // 0.400000
+ 5.00000000000000000000000000000000000000000000000000e-01, // 0.500000
+ 5.24979187478939901545516022451920434832572937011719e-01, // 0.600000
+ 5.49833997312477840146982543956255540251731872558594e-01, // 0.700000
+ 5.74442516811659031894521376671036705374717712402344e-01, // 0.800000
+ 5.98687660112452002536542750021908432245254516601562e-01, // 0.900000
+ 6.22459331201854593196287623868556693196296691894531e-01, // 1.000000
+ 6.45656306225795395548061605950351804494857788085938e-01, // 1.100000
+ 6.68187772168166160824398502882104367017745971679688e-01, // 1.200000
+ 6.89974481127612504494095446716528385877609252929688e-01, // 1.300000
+ 7.10949502625003892930521942616906017065048217773438e-01, // 1.400000
+ 7.31058578630004896048433238320285454392433166503906e-01, // 1.500000
+ 7.50260105595117687826700603181961923837661743164062e-01, // 1.600000
+ 7.68524783499017538623832024313742294907569885253906e-01, // 1.700000
+ 7.85834983042558610222272363898809999227523803710938e-01, // 1.800000
+ 8.02183888558581692507232219213619828224182128906250e-01, // 1.900000
+ 8.17574476193643651100728675373829901218414306640625e-01, // 2.000000
+ 9.01879254389337470243503958045039325952529907226562e-01, // 2.718282
+ 9.33490913616622508541809111193288117647171020507812e-01, // 3.141593
+ };
+
+ public static final double[] GNUR_LOGISTIC_PDF_05 = { //
+ 2.35003712207350168306163595843827351927757263183594e-01, // 0.000000
+ 2.35004287764725178222491308588359970599412918090820e-01, // 0.000010
+ 2.40260745741529169183792191688553430140018463134766e-01, // 0.100000
+ 2.41343722310436908928821253539354074746370315551758e-01, // 0.123457
+ 2.44458311690745888622444681459455750882625579833984e-01, // 0.200000
+ 2.46774128810591714122679718457220587879419326782227e-01, // 0.271828
+ 2.47516572711859977884429895311768632382154464721680e-01, // 0.300000
+ 2.47853815701437635299342332473315764218568801879883e-01, // 0.314159
+ 2.49376040192891945679320997442118823528289794921875e-01, // 0.400000
+ 2.50000000000000000000000000000000000000000000000000e-01, // 0.500000
+ 2.49376040192891945679320997442118823528289794921875e-01, // 0.600000
+ 2.47516572711859950128854279682855121791362762451172e-01, // 0.700000
+ 2.44458311690745888622444681459455750882625579833984e-01, // 0.800000
+ 2.40260745741529169183792191688553430140018463134766e-01, // 0.900000
+ 2.35003712201594494590750628049136139452457427978516e-01, // 1.000000
+ 2.28784240456657267381856968313513789325952529907227e-01, // 1.100000
+ 2.21712873293109097305730870175466407090425491333008e-01, // 1.200000
+ 2.13909696520294428934150232635147403925657272338867e-01, // 1.300000
+ 2.05500307342263432985873805591836571693420410156250e-01, // 1.400000
+ 1.96611933241481878775758218580449465662240982055664e-01, // 1.500000
+ 1.87369879547520601370536041940795257687568664550781e-01, // 1.600000
+ 1.77894440646805707118005557276774197816848754882812e-01, // 1.700000
+ 1.68298362469060241997098614774586167186498641967773e-01, // 1.800000
+ 1.58684897495614651852235965634463354945182800292969e-01, // 1.900000
+ 1.49146452070332835582178176991874352097511291503906e-01, // 2.000000
+ 8.84930648914700607177152846816170495003461837768555e-02, // 2.718282
+ 6.20856278118259094500608341604674933478236198425293e-02, // 3.141593
+ };
+
+ public static final double[] SCIPY_GLOGISTIC_CDF_2_05 = { //
+ 1.42536956614295634571121240696811582893133163452148e-01, // 0.000000
+ 1.42538731073420105177618211200751829892396926879883e-01, // 0.000010
+ 1.61051594146018856035240673918451648205518722534180e-01, // 0.100000
+ 1.65617158553776427920567471119284164160490036010742e-01, // 0.123457
+ 1.81099171497595134994185173127334564924240112304688e-01, // 0.200000
+ 1.96429117854286627853355184925021603703498840332031e-01, // 0.271828
+ 2.02649429975662181968587560731975827366113662719727e-01, // 0.300000
+ 2.05819255859880118064708653946581762284040451049805e-01, // 0.314159
+ 2.25644772328168013997284901961393188685178756713867e-01, // 0.400000
+ 2.50000000000000000000000000000000000000000000000000e-01, // 0.500000
+ 2.75603147286047955866195025009801611304283142089844e-01, // 0.600000
+ 3.02317424600617945529279495531227439641952514648438e-01, // 0.700000
+ 3.29984205120913143272076695211580954492092132568359e-01, // 0.800000
+ 3.58426914370922833352750558333355002105236053466797e-01, // 0.900000
+ 3.87455619000260098605536995819420553743839263916016e-01, // 1.000000
+ 4.16872065769138100410629022007924504578113555908203e-01, // 1.100000
+ 4.46474898875057091274243248335551470518112182617188e-01, // 1.200000
+ 4.76064784607318047804369598452467471361160278320312e-01, // 1.300000
+ 5.05449195282740459944648137025069445371627807617188e-01, // 1.400000
+ 5.34446645388523045028250635368749499320983886718750e-01, // 1.500000
+ 5.62890226047597086456164561241166666150093078613281e-01, // 1.600000
+ 5.90630342852211831505826467036968097090721130371094e-01, // 1.700000
+ 6.17536620573498451491900596010964363813400268554688e-01, // 1.800000
+ 6.43498991062967040654996253579156473278999328613281e-01, // 1.900000
+ 6.68428024123310704496248035866301506757736206054688e-01, // 2.000000
+ 8.13386189497715239582475987845100462436676025390625e-01, // 2.718282
+ 8.71405285804772722357824932259973138570785522460938e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_GLOGISTIC_PDF_2_05 = { //
+ 1.77446917364665113225896675430703908205032348632812e-01, // 0.000000
+ 1.77448456485205074972810734834638424217700958251953e-01, // 0.000010
+ 1.92839204113320589195623711020743940025568008422852e-01, // 0.100000
+ 1.96434907645006984200364286152762360870838165283203e-01, // 0.123457
+ 2.08062127735169605236009715554246213287115097045898e-01, // 0.200000
+ 2.18742190163498606558789560949662700295448303222656e-01, // 0.271828
+ 2.22847092273226854430845378374215215444564819335938e-01, // 0.300000
+ 2.24889203734927378697250333061674609780311584472656e-01, // 0.314159
+ 2.36917618471424035186956302823091391474008560180664e-01, // 0.400000
+ 2.50000000000000000000000000000000000000000000000000e-01, // 0.500000
+ 2.61834461914359772904958845174405723810195922851562e-01, // 0.600000
+ 2.72186053150493101338014412249322049319744110107422e-01, // 0.700000
+ 2.80854495646322144253304031735751777887344360351562e-01, // 0.800000
+ 2.87682287369737721416385056727449409663677215576172e-01, // 0.900000
+ 2.92560507053915230812890513334423303604125976562500e-01, // 1.000000
+ 2.95431975231839061279970337636768817901611328125000e-01, // 1.100000
+ 2.96291661733450895077623954421142116189002990722656e-01, // 1.200000
+ 2.95184463729510404572664583611185662448406219482422e-01, // 1.300000
+ 2.92200682588535265438167698448523879051208496093750e-01, // 1.400000
+ 2.87469680914430258944491924921749159693717956542969e-01, // 1.500000
+ 2.81152291229334549971241585808456875383853912353516e-01, // 1.600000
+ 2.73432572967530318486240048514446243643760681152344e-01, // 1.700000
+ 2.64509481633928678068201634232536889612674713134766e-01, // 1.800000
+ 2.54588936257104159199826654003118164837360382080078e-01, // 1.900000
+ 2.43876664855085467653594832881935872137546539306641e-01, // 2.000000
+ 1.59620118766000157473072817992942873388528823852539e-01, // 2.718282
+ 1.15912738857065128472711990070820320397615432739258e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_GLOGISTIC_CDF_05_05 = { //
+ 6.14443381298591106975948150648036971688270568847656e-01, // 0.000000
+ 6.14445293608914644423180106969084590673446655273438e-01, // 0.000010
+ 6.33492178237070269197772631741827353835105895996094e-01, // 0.100000
+ 6.37934856285666040953685751446755602955818176269531e-01, // 0.123457
+ 6.52347670485869834955394708231324329972267150878906e-01, // 0.200000
+ 6.65735117494094419399175421858672052621841430664062e-01, // 0.271828
+ 6.70944112939015346874782608210807666182518005371094e-01, // 0.300000
+ 6.73552575202053027680904051521793007850646972656250e-01, // 0.314159
+ 6.89217536428854971042312627105275169014930725097656e-01, // 0.400000
+ 7.07106781186547572737310929369414225220680236816406e-01, // 0.500000
+ 7.24554475163144640070811419718666002154350280761719e-01, // 0.600000
+ 7.41507921274262460364923299493966624140739440917969e-01, // 0.700000
+ 7.57919861734510202921910604345612227916717529296875e-01, // 0.800000
+ 7.73749093771651574868997158773709088563919067382812e-01, // 0.900000
+ 7.88960918678393463565612364618573337793350219726562e-01, // 1.000000
+ 8.03527414731940226033657381776720285415649414062500e-01, // 1.100000
+ 8.17427533282410356818559193925466388463973999023438e-01, // 1.200000
+ 8.30647025593670873533369558572303503751754760742188e-01, // 1.300000
+ 8.43178215222027627184786524594528600573539733886719e-01, // 1.400000
+ 8.55019636400243698837186911987373605370521545410156e-01, // 1.500000
+ 8.66175562801859255657177527609746903181076049804688e-01, // 1.600000
+ 8.76655453127976325156112125114304944872856140136719e-01, // 1.700000
+ 8.86473340288673639086880484683206304907798767089844e-01, // 1.800000
+ 8.95647189778755237199447947205044329166412353515625e-01, // 1.900000
+ 9.04198250492470045891479912825161591172218322753906e-01, // 2.000000
+ 9.49673235586458552859312476357445120811462402343750e-01, // 2.718282
+ 9.66173335181948478300739679980324581265449523925781e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_GLOGISTIC_PDF_05_05 = { //
+ 1.91233008085043759693988363324024248868227005004883e-01, // 0.000000
+ 1.91232881274457228171215206202759873121976852416992e-01, // 0.000010
+ 1.89631974944145992312272142044093925505876541137695e-01, // 0.100000
+ 1.89160162618833033176812818965117912739515304565430e-01, // 0.123457
+ 1.87368118835062935634283576291636563837528228759766e-01, // 0.200000
+ 1.85339576000944639133649616269394755363464355468750e-01, // 0.271828
+ 1.84453941795266723735480240975448396056890487670898e-01, // 0.300000
+ 1.83989954776051262141933761995460372418165206909180e-01, // 0.314159
+ 1.80912431135328455322763829826726578176021575927734e-01, // 0.400000
+ 1.76776695296636865428752116713440045714378356933594e-01, // 0.500000
+ 1.72089227753883550198210627968364860862493515014648e-01, // 0.600000
+ 1.66900828440584320100370518957788590341806411743164e-01, // 0.700000
+ 1.61269234409096795523907985625555738806724548339844e-01, // 0.800000
+ 1.55257529653685638626470222334319259971380233764648e-01, // 0.900000
+ 1.48932416446719950720023462054086849093437194824219e-01, // 1.000000
+ 1.42362436092476424276398461188364308327436447143555e-01, // 1.100000
+ 1.35616225454758571045132953258871566504240036010742e-01, // 1.200000
+ 1.28760887554741604299479718065413180738687515258789e-01, // 1.300000
+ 1.21860541242844275244827656479174038395285606384277e-01, // 1.400000
+ 1.14975098156368985002906413228629389777779579162598e-01, // 1.500000
+ 1.08159296795112963573970432662463281303644180297852e-01, // 1.600000
+ 1.01462005404782576456490517102793091908097267150879e-01, // 1.700000
+ 9.49257889776217583799322596860292833298444747924805e-02, // 1.800000
+ 8.85867221527336656805573511519469320774078369140625e-02, // 1.900000
+ 8.24744197354399105615030407534504774957895278930664e-02, // 2.000000
+ 4.65913229811568962990264708423637785017490386962891e-02, // 2.718282
+ 3.21296529054722751483907927649852354079484939575195e-02, // 3.141593
+ };
+
+ public static final double[] P_QUANT = { //
+ 0.0001, 0.001, 0.01, 0.1, 0.25, 0.5, 0.75, 0.9, 0.99, 0.999, 0.9999 //
+ };
+
+ public static final double[] SCIPY_LOGISTIC_QUANT_05 = { //
+ -8.71024036697584946864481025841087102890014648437500e+00, // 0.000100
+ -6.40675477864855391629816949716769158840179443359375e+00, // 0.001000
+ -4.09511985013458978954759004409424960613250732421875e+00, // 0.010000
+ -1.69722457733621956421643517387565225362777709960938e+00, // 0.100000
+ -5.98612288668109782108217586937826126813888549804688e-01, // 0.250000
+ 5.00000000000000000000000000000000000000000000000000e-01, // 0.500000
+ 1.59861228866811000415282251196913421154022216796875e+00, // 0.750000
+ 2.69722457733621912012722532381303608417510986328125e+00, // 0.900000
+ 5.09511985013458357229865214321762323379516601562500e+00, // 0.990000
+ 7.40675477864846509845619948464445769786834716796875e+00, // 0.999000
+ 9.71024036697667902728881017537787556648254394531250e+00, // 0.999900
+ };
+
+ public static final double[] GNUR_LOGISTIC_QUANT_05 = { //
+ -8.71024036697584946864481025841087102890014648437500e+00, // 0.000100
+ -6.40675477864855391629816949716769158840179443359375e+00, // 0.001000
+ -4.09511985013458978954759004409424960613250732421875e+00, // 0.010000
+ -1.69722457733621912012722532381303608417510986328125e+00, // 0.100000
+ -5.98612288668109782108217586937826126813888549804688e-01, // 0.250000
+ 5.00000000000000000000000000000000000000000000000000e-01, // 0.500000
+ 1.59861228866810978210821758693782612681388854980469e+00, // 0.750000
+ 2.69722457733621956421643517387565225362777709960938e+00, // 0.900000
+ 5.09511985013458890136917034396901726722717285156250e+00, // 0.990000
+ 7.40675477864855302811974979704245924949645996093750e+00, // 0.999000
+ 9.71024036697595960276885307393968105316162109375000e+00, // 0.999900
+ };
+
+ public static final double[] SCIPY_GLOGISTIC_QUANT_2_05 = { //
+ -4.09511985013458978954759004409424960613250732421875e+00, // 0.000100
+ -2.92174406546798248740515191457234323024749755859375e+00, // 0.001000
+ -1.69722457733621956421643517387565225362777709960938e+00, // 0.010000
+ -2.71162138430851129555776424240320920944213867187500e-01, // 0.100000
+ 5.00000000000000000000000000000000000000000000000000e-01, // 0.250000
+ 1.38137358701954271467116086569149047136306762695312e+00, // 0.500000
+ 2.36626404125887201956857097684405744075775146484375e+00, // 0.750000
+ 3.41705874790017549713638800312764942646026611328125e+00, // 0.900000
+ 5.79078277119367168523922373424284160137176513671875e+00, // 0.990000
+ 8.10015211557315417678637459175661206245422363281250e+00, // 0.999000
+ 1.04034125490967461757918499642983078956604003906250e+01, // 0.999900
+ };
+
+ public static final double[] SCIPY_GLOGISTIC_QUANT_05_05 = { //
+ -1.79206807339523663813452003523707389831542968750000e+01, // 0.000100
+ -1.33155095579637734459765852079726755619049072265625e+01, // 0.001000
+ -8.71024036697584946864481025841087102890014648437500e+00, // 0.010000
+ -4.09511985013458978954759004409424960613250732421875e+00, // 0.100000
+ -2.20805020110221006390816000930499285459518432617188e+00, // 0.250000
+ -5.98612288668109782108217586937826126813888549804688e-01, // 0.500000
+ 7.51314428280906221324642046965891495347023010253906e-01, // 0.750000
+ 1.95001017550599864414095918618841096758842468261719e+00, // 0.900000
+ 4.39693487554469086830977175850421190261840820312500e+00, // 0.990000
+ 6.71310722279666993728142188047058880329132080078125e+00, // 0.999000
+ 9.01704318266624582633994577918201684951782226562500e+00, // 0.999900
+ };
+
+ @Test
+ public void testPDF() {
+ checkPDF(new GeneralizedLogisticDistribution(.5, 1., 1.), P_CDFPDF, SCIPY_LOGISTIC_PDF_05, 1e-12);
+ checkPDF(new GeneralizedLogisticDistribution(.5, 1., 1.), P_CDFPDF, GNUR_LOGISTIC_PDF_05, 1e-15);
+ checkPDF(new GeneralizedLogisticDistribution(.5, 1., 2.), P_CDFPDF, SCIPY_GLOGISTIC_PDF_2_05, 1e-12);
+ checkPDF(new GeneralizedLogisticDistribution(.5, 1., .5), P_CDFPDF, SCIPY_GLOGISTIC_PDF_05_05, 1e-12);
+ }
+
+ @Test
+ public void testCDF() {
+ checkCDF(new GeneralizedLogisticDistribution(.5, 1., 1.), P_CDFPDF, SCIPY_LOGISTIC_CDF_05, 1e-13);
+ checkCDF(new GeneralizedLogisticDistribution(.5, 1., 1.), P_CDFPDF, GNUR_LOGISTIC_CDF_05, 0.);
+ checkCDF(new GeneralizedLogisticDistribution(.5, 1., 2.), P_CDFPDF, SCIPY_GLOGISTIC_CDF_2_05, 1e-12);
+ checkCDF(new GeneralizedLogisticDistribution(.5, 1., .5), P_CDFPDF, SCIPY_GLOGISTIC_CDF_05_05, 1e-13);
+ }
+
+ @Test
+ public void testProbit() {
+ checkQuantile(new GeneralizedLogisticDistribution(.5, 1., 1.), P_QUANT, SCIPY_LOGISTIC_QUANT_05, 0.);
+ checkQuantile(new GeneralizedLogisticDistribution(.5, 1., 1.), P_QUANT, GNUR_LOGISTIC_QUANT_05, 1e-13);
+ checkQuantile(new GeneralizedLogisticDistribution(.5, 1., 2.), P_QUANT, SCIPY_GLOGISTIC_QUANT_2_05, 1e-15);
+ checkQuantile(new GeneralizedLogisticDistribution(.5, 1., .5), P_QUANT, SCIPY_GLOGISTIC_QUANT_05_05, 0.);
+ }
+}
diff --git a/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestGumbelDistribution.java b/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestGumbelDistribution.java
new file mode 100644
index 00000000..54243d79
--- /dev/null
+++ b/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestGumbelDistribution.java
@@ -0,0 +1,672 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2012
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import org.junit.Test;
+
+import de.lmu.ifi.dbs.elki.JUnit4Test;
+
+/**
+ * Unit test for the Gumbel distribution in ELKI.
+ *
+ * The reference values were computed using SciPy.
+ *
+ * @author Erich Schubert
+ */
+public class TestGumbelDistribution extends AbstractDistributionTest implements JUnit4Test {
+ public static final double[] P_CDFPDF = { //
+ 1e-10, 1e-05, 0.1, 0.1234567, 0.2, 0.271828182846, 0.3, 0.314159265359, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.71828182846, 3.14159265359 //
+ };
+
+ public static final double[] SCIPY_GUMBEL_CDF_1_1 = { //
+ 6.59880358632499303128682299757201690226793289184570e-02, // 0.000000
+ 6.59898296015106466949617924910853616893291473388672e-02, // 0.000010
+ 8.54688658759459179981021748062630649656057357788086e-02, // 0.100000
+ 9.04841721928088676962786962576501537114381790161133e-02, // 0.123457
+ 1.08008977696591554340521668109431630000472068786621e-01, // 0.200000
+ 1.26023050723474722145667215045250486582517623901367e-01, // 0.271828
+ 1.33486796658083856081944418292550835758447647094727e-01, // 0.300000
+ 1.37320130159857167750914186399313621222972869873047e-01, // 0.314159
+ 1.61682814145126474425495644027250818908214569091797e-01, // 0.400000
+ 1.92295645547964910715421638087718747556209564208984e-01, // 0.500000
+ 2.24961793549918465107140264080953784286975860595703e-01, // 0.600000
+ 2.59276865990827554142583721841219812631607055664062e-01, // 0.700000
+ 2.94816320729158143354453613937948830425739288330078e-01, // 0.800000
+ 3.31154277152908960157873252683202736079692840576172e-01, // 0.900000
+ 3.67879441171442334024277442949824035167694091796875e-01, // 1.000000
+ 4.04607661664131867951255117077380418777465820312500e-01, // 1.100000
+ 4.40991025942982617369381159733165986835956573486328e-01, // 1.200000
+ 4.76723690714594083850386141421040520071983337402344e-01, // 1.300000
+ 5.11544833689041578139722332707606256008148193359375e-01, // 1.400000
+ 5.45239211892605046827497972117271274328231811523438e-01, // 1.500000
+ 5.77635844258915676086019175272667780518531799316406e-01, // 1.600000
+ 6.08605317804406409365469698968809098005294799804688e-01, // 1.700000
+ 6.38056166582018691180167024867841973900794982910156e-01, // 1.800000
+ 6.65930705440122117089174480497604236006736755371094e-01, // 1.900000
+ 6.92200627555346392760782237019157037138938903808594e-01, // 2.000000
+ 8.35793188453588298258978284138720482587814331054688e-01, // 2.718282
+ 8.89169312582892001906031964608700945973396301269531e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_GUMBEL_PDF_1_1 = { //
+ 1.79374078764838684740823282481869682669639587402344e-01, // 0.000000
+ 1.79377160888317427334115450321405660361051559448242e-01, // 0.000010
+ 2.10219488415532645975147829631168860942125320434570e-01, // 0.100000
+ 2.17395492872112461313349740521516650915145874023438e-01, // 0.123457
+ 2.40378400508394624024433028353087138384580612182617e-01, // 0.200000
+ 2.61030341003925192566725854703690856695175170898438e-01, // 0.271828
+ 2.68809398181777348124654736238881014287471771240234e-01, // 0.300000
+ 2.72640929007956611673790803251904435455799102783203e-01, // 0.314159
+ 2.94605295353879470532376672053942456841468811035156e-01, // 0.400000
+ 3.17041921077942157047857563156867399811744689941406e-01, // 0.500000
+ 3.35603559643445015225893257593270391225814819335938e-01, // 0.600000
+ 3.49987161158421655748895773285767063498497009277344e-01, // 0.700000
+ 3.60089467289227027624320953691494651138782501220703e-01, // 0.800000
+ 3.65982076505757814022246066087973304092884063720703e-01, // 0.900000
+ 3.67879441171442334024277442949824035167694091796875e-01, // 1.000000
+ 3.66104151897740148768889412167482078075408935546875e-01, // 1.100000
+ 3.61052914770930044596752850338816642761230468750000e-01, // 1.200000
+ 3.53165596312007168400270984420785680413246154785156e-01, // 1.300000
+ 3.42898756467731824493228032224578782916069030761719e-01, // 1.400000
+ 3.30704298890418080247854959452524781227111816406250e-01, // 1.500000
+ 3.17013272754289754384871002912404946982860565185547e-01, // 1.600000
+ 3.02224456630968474346587981926859356462955474853516e-01, // 1.700000
+ 2.86697116378903826827695411338936537504196166992188e-01, // 1.800000
+ 2.70747220321607640070027400724939070641994476318359e-01, // 1.900000
+ 2.54646380043582531982337968656793236732482910156250e-01, // 2.000000
+ 1.49919633191029216812140134607034269720315933227539e-01, // 2.718282
+ 1.04448592925595828972973322379402816295623779296875e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_GUMBEL_CDF_2_1 = { //
+ 6.17978989787721657254981888485190211213193833827972e-04, // 0.000000
+ 6.18024653604032120531031058163762281765230000019073e-04, // 0.000010
+ 1.24839763464425581619698935043061283067800104618073e-03, // 0.100000
+ 1.45770722707259806419366476859522663289681077003479e-03, // 0.123457
+ 2.35869338329322553171607523836428299546241760253906e-03, // 0.200000
+ 3.58731530475635143964674433902928285533562302589417e-03, // 0.271828
+ 4.19464154138938540017367273549098172225058078765869e-03, // 0.300000
+ 4.53021237372840286650177432647979003377258777618408e-03, // 0.314159
+ 7.06196156220941038267335798650492506567388772964478e-03, // 0.400000
+ 1.13142863804596271321001310639076109509915113449097e-02, // 0.500000
+ 1.73320140087645062354493319389803218655288219451904e-02, // 0.600000
+ 2.54943946757241260425708162529190303757786750793457e-02, // 0.700000
+ 3.61486049131355194341530534529738361015915870666504e-02, // 0.800000
+ 4.95800856955669819181586888134916080161929130554199e-02, // 0.900000
+ 6.59880358453125426265728492580819875001907348632812e-02, // 1.000000
+ 8.54688658759459596314655982496333308517932891845703e-02, // 1.100000
+ 1.08008977696591554340521668109431630000472068786621e-01, // 1.200000
+ 1.33486796658083856081944418292550835758447647094727e-01, // 1.300000
+ 1.61682814145126418914344412769423797726631164550781e-01, // 1.400000
+ 1.92295645547964910715421638087718747556209564208984e-01, // 1.500000
+ 2.24961793549918520618291495338780805468559265136719e-01, // 1.600000
+ 2.59276865990827554142583721841219812631607055664062e-01, // 1.700000
+ 2.94816320729158143354453613937948830425739288330078e-01, // 1.800000
+ 3.31154277152908849135570790167548693716526031494141e-01, // 1.900000
+ 3.67879441171442334024277442949824035167694091796875e-01, // 2.000000
+ 6.14105034982032282897534969379194080829620361328125e-01, // 2.718282
+ 7.26650204627822926539693071390502154827117919921875e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_GUMBEL_PDF_2_1 = { //
+ 4.56628142304533850281966778084097313694655895233154e-03, // 0.000000
+ 4.56657317004234564183917655100231058895587921142578e-03, // 0.000010
+ 8.34665480722261536594697162172451498918235301971436e-03, // 0.100000
+ 9.52012623739182869964103872462146682664752006530762e-03, // 0.123457
+ 1.42692634455674552396153842437342973425984382629395e-02, // 0.200000
+ 2.01978449671180448898866188756073825061321258544922e-02, // 0.271828
+ 2.29612471247189892098461427849542815238237380981445e-02, // 0.300000
+ 2.44494948372630735433652660049119731411337852478027e-02, // 0.314159
+ 3.49781245974551888155978929262346355244517326354980e-02, // 0.400000
+ 5.07071136099807306951703367303707636892795562744141e-02, // 0.500000
+ 7.02847826336932546276159428089158609509468078613281e-02, // 0.600000
+ 9.35464974266043414186100335427909158170223236083984e-02, // 0.700000
+ 1.20017594905418731321411485168937360867857933044434e-01, // 0.800000
+ 1.48946808910974892725675999827217310667037963867188e-01, // 0.900000
+ 1.79374078734017200487116383555985521525144577026367e-01, // 1.000000
+ 2.10219488415532701486299060888995882123708724975586e-01, // 1.100000
+ 2.40378400508394624024433028353087138384580612182617e-01, // 1.200000
+ 2.68809398181777348124654736238881014287471771240234e-01, // 1.300000
+ 2.94605295353879415021225440796115435659885406494141e-01, // 1.400000
+ 3.17041921077942157047857563156867399811744689941406e-01, // 1.500000
+ 3.35603559643445015225893257593270391225814819335938e-01, // 1.600000
+ 3.49987161158421655748895773285767063498497009277344e-01, // 1.700000
+ 3.60089467289227027624320953691494651138782501220703e-01, // 1.800000
+ 3.65982076505757758511094834830146282911300659179688e-01, // 1.900000
+ 3.67879441171442334024277442949824035167694091796875e-01, // 2.000000
+ 2.99431043346856384790299898668308742344379425048828e-01, // 2.718282
+ 2.32026725020700291812758564446994569152593612670898e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_GUMBEL_CDF_4_1 = { //
+ 1.94233761556120265073609843858010169210640550320133e-24, // 0.000000
+ 1.94339836960486498321475838226799834065378487714337e-24, // 0.000010
+ 3.50581472625786942134053009067093603336708158078897e-22, // 0.100000
+ 1.10204869082170943883948227538294176292737847487482e-21, // 0.123457
+ 3.85942175009585124493227078787604613125739296999845e-20, // 0.200000
+ 8.55175072212361792537222183911253732406541162804661e-19, // 0.271828
+ 2.71618226092945448511767238087193692507249743561641e-18, // 0.300000
+ 4.79654546206938212109880845109838654258082904740905e-18, // 0.314159
+ 1.27523062451624426541224412921385568571695936319552e-16, // 0.400000
+ 4.15089692010904525288672126361021019245556122612140e-15, // 0.500000
+ 9.69966408521639154441452223525895873820334286419254e-14, // 0.600000
+ 1.67930865740466120726981233244263965733930610291225e-12, // 0.700000
+ 2.21644780341866066467927092510455566905236413077773e-11, // 0.800000
+ 2.28850701972651310101286108247299871248925384747963e-10, // 0.900000
+ 1.89217869483829244811168274588777937772476889222162e-09, // 1.000000
+ 1.27958444708893479866928830448492837579266279135481e-08, // 1.100000
+ 7.21407495654723266621612446335143342679430134012364e-08, // 1.200000
+ 3.44996444807882075559481984891596617615050490712747e-07, // 1.300000
+ 1.42158510896623277238609052430806656275308341719210e-06, // 1.400000
+ 5.11929429867073290303346178031773661132319830358028e-06, // 1.500000
+ 1.63190669761509105832684302095358930273505393415689e-05, // 1.600000
+ 4.65873061192628793976758250217073964449809864163399e-05, // 1.700000
+ 1.20361180348421196420645451485853527628933079540730e-04, // 1.800000
+ 2.84104078721292101477463587499983077577780932188034e-04, // 1.900000
+ 6.17978989331093432439689916435554550844244658946991e-04, // 2.000000
+ 2.72466505377139643628847665013381629250943660736084e-02, // 2.718282
+ 9.44768930014186492094552249909611418843269348144531e-02, // 3.141593
+ };
+
+ public static final double[] SCIPY_GUMBEL_PDF_4_1 = { //
+ 1.06048040538825383895657084905076034872528558503039e-22, // 0.000000
+ 1.06104894703602011823679422569673096865235426708292e-22, // 0.000010
+ 1.73195833587372556877622009550080809725453568188831e-20, // 0.100000
+ 5.31816915757311281533262916149991462179401939316581e-20, // 0.123457
+ 1.72520723688492552379661823003568327945291845918510e-18, // 0.200000
+ 3.55778320603558542628503187787223104575572232312602e-17, // 0.271828
+ 1.09862250605229655196224903219933069216592916588111e-16, // 0.300000
+ 1.91279689150650823875815251444059610432563375858640e-16, // 0.314159
+ 4.66711893658034022812779722242683120807921724748635e-15, // 0.400000
+ 1.37458827543354963946170620516550599064667728677058e-13, // 0.500000
+ 2.90641705075567549607614189502246106536209602211329e-12, // 0.600000
+ 4.55304892645473537813182015220254180570824686924425e-11, // 0.700000
+ 5.43750726676849818042246906675497505889715910143423e-10, // 0.800000
+ 5.08001673311263319774744418142083113298923535694485e-09, // 0.900000
+ 3.80054250404435749527446645589651152974397518846672e-08, // 1.000000
+ 2.32553537538727241913236328495206972633013720042072e-07, // 1.100000
+ 1.18632914440636535453432297976261722283197741489857e-06, // 1.200000
+ 5.13345454477618321902391770872320364560437155887485e-06, // 1.300000
+ 1.91398495015806936032053131579999671885161660611629e-05, // 1.400000
+ 6.23657718766199291749591226974303026509005576372147e-05, // 1.500000
+ 1.79887953645615079585964868336134259152458980679512e-04, // 1.600000
+ 4.64670291311834173994532726226225349819287657737732e-04, // 1.700000
+ 1.08626127745232634556893369648378211422823369503021e-03, // 1.800000
+ 2.32004217969156720582923902895799983525648713111877e-03, // 1.900000
+ 4.56628142012791525539139314560088678263127803802490e-03, // 2.000000
+ 9.81649050447965243471060148294782266020774841308594e-02, // 2.718282
+ 2.22908780675388440428719150077085942029953002929688e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_GUMBEL_CDF_4_10 = { //
+ 2.24961793553274530532704034158086869865655899047852e-01, // 0.000000
+ 2.24962129153560647099041602814395446330308914184570e-01, // 0.000010
+ 2.28326012057771948748907675508235115557909011840820e-01, // 0.100000
+ 2.29117491320003585641984500398393720388412475585938e-01, // 0.123457
+ 2.31706315790068034798920848515990655869245529174805e-01, // 0.200000
+ 2.34144016800101217867791092430707067251205444335938e-01, // 0.271828
+ 2.35102282543562940420045492828649003058671951293945e-01, // 0.300000
+ 2.35584367949729117652779564195952843874692916870117e-01, // 0.314159
+ 2.38513488532688416876581527503731194883584976196289e-01, // 0.400000
+ 2.41939508585804652351924914910341612994670867919922e-01, // 0.500000
+ 2.45379916339054454654799997115333098918199539184570e-01, // 0.600000
+ 2.48834284427714574894352494993654545396566390991211e-01, // 0.700000
+ 2.52302184674948581921682944084750488400459289550781e-01, // 0.800000
+ 2.55783188277869832916167069924995303153991699218750e-01, // 0.900000
+ 2.59276865990827554142583721841219812631607055664062e-01, // 1.000000
+ 2.62782788305835623976491888242890127003192901611328e-01, // 1.100000
+ 2.66300525630066620141889188744244165718555450439453e-01, // 1.200000
+ 2.69829648460341131599449226996512152254581451416016e-01, // 1.300000
+ 2.73369727554544250658352666505379602313041687011719e-01, // 1.400000
+ 2.76920334099908960201474883433547802269458770751953e-01, // 1.500000
+ 2.80481039878108018292834913154365494847297668457031e-01, // 1.600000
+ 2.84051417427103602975080320902634412050247192382812e-01, // 1.700000
+ 2.87631040199704479665143708189134486019611358642578e-01, // 1.800000
+ 2.91219482718789723918462186702527105808258056640625e-01, // 1.900000
+ 2.94816320729158143354453613937948830425739288330078e-01, // 2.000000
+ 3.20860670367920819412432820172398351132869720458984e-01, // 2.718282
+ 3.36339983908659712064093127992236986756324768066406e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_GUMBEL_PDF_4_10 = { //
+ 3.35603559645095625429966901265288470312952995300293e-02, // 0.000000
+ 3.35603724701354494408533923888171557337045669555664e-02, // 0.000010
+ 3.37233134553145824652276019151031505316495895385742e-02, // 0.100000
+ 3.37609284733200315509193956131639424711465835571289e-02, // 0.123457
+ 3.38820574854396400210632123162213247269392013549805e-02, // 0.200000
+ 3.39934708099677296289087280456442385911941528320312e-02, // 0.271828
+ 3.40365712424673116931472804935765452682971954345703e-02, // 0.300000
+ 3.40581064819283629852009198657469823956489562988281e-02, // 0.314159
+ 3.41868398883302671009687401237897574901580810546875e-02, // 0.400000
+ 3.43328505356715121821231662124773720279335975646973e-02, // 0.500000
+ 3.44745922233250789989966733628534711897373199462891e-02, // 0.600000
+ 3.46120558908042108559044436333351768553256988525391e-02, // 0.700000
+ 3.47452343518489734086607256813294952735304832458496e-02, // 0.800000
+ 3.48741222670847020315143538482516305521130561828613e-02, // 0.900000
+ 3.49987161158421683504471388914680574089288711547852e-02, // 1.000000
+ 3.51190141671897312902750343255320331081748008728027e-02, // 1.100000
+ 3.52350164502270857269650150556117296218872070312500e-02, // 1.200000
+ 3.53467247236895973361292533354571787640452384948730e-02, // 1.300000
+ 3.54541424449113518058140925859333947300910949707031e-02, // 1.400000
+ 3.55572747381944151423560640523646725341677665710449e-02, // 1.500000
+ 3.56561283626308858640818755247892113402485847473145e-02, // 1.600000
+ 3.57507116794234872103608324778178939595818519592285e-02, // 1.700000
+ 3.58410346187495246206289323254168266430497169494629e-02, // 1.800000
+ 3.59271086462122773985683465980400796979665756225586e-02, // 1.900000
+ 3.60089467289226999868745338062581140547990798950195e-02, // 2.000000
+ 3.64737821185050284378270646357123041525483131408691e-02, // 2.718282
+ 3.66487069582701815995129379643913125619292259216309e-02, // 3.141593
+ };
+
+ public static final double[] SCIPY_GUMBEL_CDF_01_10 = { //
+ 3.64200708229312053454407305252971127629280090332031e-01, // 0.000000
+ 3.64201076086621500227380465730675496160984039306641e-01, // 0.000010
+ 3.67879441171442334024277442949824035167694091796875e-01, // 0.100000
+ 3.68742364149354184821305580044281668961048126220703e-01, // 0.123457
+ 3.71558174423808174058336817324743606150150299072266e-01, // 0.200000
+ 3.74200337049799547362027851704624481499195098876953e-01, // 0.271828
+ 3.75236541960806024853525286744115874171257019042969e-01, // 0.300000
+ 3.75757321275714095687447979798889718949794769287109e-01, // 0.314159
+ 3.78914181510685010856320786842843517661094665527344e-01, // 0.400000
+ 3.82590734620523953424253704724833369255065917968750e-01, // 0.500000
+ 3.86265846721645655925669871066929772496223449707031e-01, // 0.600000
+ 3.89939167191828084391147513088071718811988830566406e-01, // 0.700000
+ 3.93610349414351023966673892573453485965728759765625e-01, // 0.800000
+ 3.97279050833918845331282909683068282902240753173828e-01, // 0.900000
+ 4.00944933009500681375669728367938660085201263427734e-01, // 1.000000
+ 4.04607661664131867951255117077380418777465820312500e-01, // 1.100000
+ 4.08266906731719725343054960831068456172943115234375e-01, // 1.200000
+ 4.11922342400900476366842895004083402454853057861328e-01, // 1.300000
+ 4.15573647155991876545044760860037058591842651367188e-01, // 1.400000
+ 4.19220503815090905774809471040498465299606323242188e-01, // 1.500000
+ 4.22862599565362817788383154038456268608570098876953e-01, // 1.600000
+ 4.26499625995571840508802097247098572552204132080078e-01, // 1.700000
+ 4.30131279125902432625139226729515939950942993164062e-01, // 1.800000
+ 4.33757259435121944601831955878878943622112274169922e-01, // 1.900000
+ 4.37377271885135254780863078849506564438343048095703e-01, // 2.000000
+ 4.63178277570029439669241355659323744475841522216797e-01, // 2.718282
+ 4.78191805551566095910942522095865570008754730224609e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_GUMBEL_PDF_01_10 = { //
+ 3.67860986195510386576046357731684111058712005615234e-02, // 0.000000
+ 3.67860989892352038821421444936277111992239952087402e-02, // 0.000010
+ 3.67879441171442347902065250764280790463089942932129e-02, // 0.100000
+ 3.67878429896495301454351078973559197038412094116211e-02, // 0.123457
+ 3.67861108816435675161748974915099097415804862976074e-02, // 0.200000
+ 3.67825446794351126889033309907972579821944236755371e-02, // 0.271828
+ 3.67806360606196675044898825035488698631525039672852e-02, // 0.300000
+ 3.67795687265079010441759521654603304341435432434082e-02, // 0.314159
+ 3.67715575045233014628287548930529737845063209533691e-02, // 0.400000
+ 3.67589137340928531760830821895069675520062446594238e-02, // 0.500000
+ 3.67427439081312035007442773348884657025337219238281e-02, // 0.600000
+ 3.67230877916642356462162410934979561716318130493164e-02, // 0.700000
+ 3.66999857244961757984924588527064770460128784179688e-02, // 0.800000
+ 3.66734785901757648352017326942586805671453475952148e-02, // 0.900000
+ 3.66436077853866115638936662435298785567283630371094e-02, // 1.000000
+ 3.66104151897740162646677219981938833370804786682129e-02, // 1.100000
+ 3.65739431362198524899653762076923158019781112670898e-02, // 1.200000
+ 3.65342343815761166903044454556948039680719375610352e-02, // 1.300000
+ 3.64913320778669988952991332098463317379355430603027e-02, // 1.400000
+ 3.64452797439685782787677226224332116544246673583984e-02, // 1.500000
+ 3.63961212377742968082650065753114176914095878601074e-02, // 1.600000
+ 3.63439007288538645790154646419978234916925430297852e-02, // 1.700000
+ 3.62886626716122442926071300917101325467228889465332e-02, // 1.800000
+ 3.62304517789548280459754892035562079399824142456055e-02, // 1.900000
+ 3.61693129964641910123468449000938562676310539245605e-02, // 2.000000
+ 3.56482034999189151269760600371228065341711044311523e-02, // 2.718282
+ 3.52782829415396598227161462091316934674978256225586e-02, // 3.141593
+ };
+
+ public static final double[] SCIPY_GUMBEL_CDF_01_20 = { //
+ 3.66040051641140451454958792965044267475605010986328e-01, // 0.000000
+ 3.66040235576718830934339621308026835322380065917969e-01, // 0.000010
+ 3.67879441171442334024277442949824035167694091796875e-01, // 0.100000
+ 3.68310902956942021191366620769258588552474975585938e-01, // 0.123457
+ 3.69718830722743807548624772607581689953804016113281e-01, // 0.200000
+ 3.71040005167483422088281486139749176800251007080078e-01, // 0.271828
+ 3.71558174423808174058336817324743606150150299072266e-01, // 0.300000
+ 3.71818605637736554481165285324095748364925384521484e-01, // 0.314159
+ 3.73397426637427698459248404105892404913902282714844e-01, // 0.400000
+ 3.75236541960806024853525286744115874171257019042969e-01, // 0.500000
+ 3.77075475227729051130864945662324316799640655517578e-01, // 0.600000
+ 3.78914181510685010856320786842843517661094665527344e-01, // 0.700000
+ 3.80752616122933373876691121040494181215763092041016e-01, // 0.800000
+ 3.82590734620523953424253704724833369255065917968750e-01, // 0.900000
+ 3.84428492804265664606333530173287726938724517822266e-01, // 1.000000
+ 3.86265846721645655925669871066929772496223449707031e-01, // 1.100000
+ 3.88102752668698702809280121073243208229541778564453e-01, // 1.200000
+ 3.89939167191828084391147513088071718811988830566406e-01, // 1.300000
+ 3.91775047089576777814556862722383812069892883300781e-01, // 1.400000
+ 3.93610349414351023966673892573453485965728759765625e-01, // 1.500000
+ 3.95445031474095209933494743381743319332599639892578e-01, // 1.600000
+ 3.97279050833918845331282909683068282902240753173828e-01, // 1.700000
+ 3.99112365317676576204064531339099630713462829589844e-01, // 1.800000
+ 4.00944933009500681375669728367938660085201263427734e-01, // 1.900000
+ 4.02776712255286439834378597879549488425254821777344e-01, // 2.000000
+ 4.15907192667703928812272806680994108319282531738281e-01, // 2.718282
+ 4.23619395109240293173513691726839169859886169433594e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_GUMBEL_PDF_01_20 = { //
+ 1.83937417516764276093077512541640317067503929138184e-02, // 0.000000
+ 1.83937417977731651475004071016883244737982749938965e-02, // 0.000010
+ 1.83939720585721173951032625382140395231544971466064e-02, // 0.100000
+ 1.83939594126808145246876335932029178366065025329590e-02, // 0.123457
+ 1.83937425180828485749007228378104628063738346099854e-02, // 0.200000
+ 1.83932951601603437985499311935200239531695842742920e-02, // 0.271828
+ 1.83930554408217837580874487457549548707902431488037e-02, // 0.300000
+ 1.83929213116811943184991662292304681614041328430176e-02, // 0.314159
+ 1.83919131598794319271128472337295534089207649230957e-02, // 0.400000
+ 1.83903180303098337522449412517744349315762519836426e-02, // 0.500000
+ 1.83882724286199075725001250702916877344250679016113e-02, // 0.600000
+ 1.83857787522616507314143774465264868922531604766846e-02, // 0.700000
+ 1.83828394191271268787168935432418948039412498474121e-02, // 0.800000
+ 1.83794568670464265880415410947534837760031223297119e-02, // 0.900000
+ 1.83756335532885978212291888667095918208360671997070e-02, // 1.000000
+ 1.83713719540656017503721386674442328512668609619141e-02, // 1.100000
+ 1.83666745640393841432214117048715706914663314819336e-02, // 1.200000
+ 1.83615438958321178231081205467489780858159065246582e-02, // 1.300000
+ 1.83559824795396266117197825451512471772730350494385e-02, // 1.400000
+ 1.83499928622480878992462294263532385230064392089844e-02, // 1.500000
+ 1.83435776075540693530463443039479898288846015930176e-02, // 1.600000
+ 1.83367392950878824176008663471293402835726737976074e-02, // 1.700000
+ 1.83294805200404052614171490631633787415921688079834e-02, // 1.800000
+ 1.83218038926933057819468331217649392783641815185547e-02, // 1.900000
+ 1.83137120379528138547353677267892635427415370941162e-02, // 2.000000
+ 1.82436263119165158197443332710463437251746654510498e-02, // 2.718282
+ 1.81927559990815723711676810125936754047870635986328e-02, // 3.141593
+ };
+
+ public static final double[] SCIPY_GUMBEL_CDF_01_4 = { //
+ 3.58683419097346689596861324389465153217315673828125e-01, // 0.000000
+ 3.58684338497014365554349524245481006801128387451172e-01, // 0.000010
+ 3.67879441171442334024277442949824035167694091796875e-01, // 0.100000
+ 3.70036738247086438580168987755314446985721588134766e-01, // 0.123457
+ 3.77075475227729051130864945662324316799640655517578e-01, // 0.200000
+ 3.83677647968239443621030204667476937174797058105469e-01, // 0.271828
+ 3.86265846721645655925669871066929772496223449707031e-01, // 0.300000
+ 3.87566357530248317697640914047951810061931610107422e-01, // 0.314159
+ 3.95445031474095209933494743381743319332599639892578e-01, // 0.400000
+ 4.04607661664131867951255117077380418777465820312500e-01, // 0.500000
+ 4.13748531068576341773734839080134406685829162597656e-01, // 0.600000
+ 4.22862599565362817788383154038456268608570098876953e-01, // 0.700000
+ 4.31944996928375679612344129054690711200237274169922e-01, // 0.800000
+ 4.40991025942982672880532390990993008017539978027344e-01, // 0.900000
+ 4.49996164872620063590602512704208493232727050781250e-01, // 1.000000
+ 4.58956069307663805378894039677106775343418121337891e-01, // 1.100000
+ 4.67866573428437237947008497940259985625743865966797e-01, // 1.200000
+ 4.76723690714594083850386141421040520071983337402344e-01, // 1.300000
+ 4.85523614133279490800987332477234303951263427734375e-01, // 1.400000
+ 4.94262715838446498040070764545816928148269653320312e-01, // 1.500000
+ 5.02937546413495417674255349993472918868064880371094e-01, // 1.600000
+ 5.11544833689041578139722332707606256008148193359375e-01, // 1.700000
+ 5.20081481167105397211969375348417088389396667480469e-01, // 1.800000
+ 5.28544566082388089789390051009831950068473815917969e-01, // 1.900000
+ 5.36931337130553965053536558116320520639419555664062e-01, // 2.000000
+ 5.94719607054730259321217999968212097883224487304688e-01, // 2.718282
+ 6.26579099505278791504281343804905191063880920410156e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_GUMBEL_PDF_01_4 = { //
+ 9.19408832681790494367746191528567578643560409545898e-02, // 0.000000
+ 9.19408890865627964616990652757522184401750564575195e-02, // 0.000010
+ 9.19698602928605835060693607374560087919235229492188e-02, // 0.100000
+ 9.19682820379929405474328518721449654549360275268555e-02, // 0.123457
+ 9.19413621430995309236067214442300610244274139404297e-02, // 0.200000
+ 9.18862440991995849115525629713374655693769454956055e-02, // 0.271828
+ 9.18568597703280087518606933372211642563343048095703e-02, // 0.300000
+ 9.18404563854176708703747067374933976680040359497070e-02, // 0.314159
+ 9.17178880377703537041256254269683267921209335327148e-02, // 0.400000
+ 9.15260379744350371922223530418705195188522338867188e-02, // 0.500000
+ 9.12829492792362195974220639982377178966999053955078e-02, // 0.600000
+ 9.09903030944357454901094683918927330523729324340820e-02, // 0.700000
+ 9.06498150644146627463726417772704735398292541503906e-02, // 0.800000
+ 9.02632286927325111491882125847041606903076171875000e-02, // 0.900000
+ 8.98323090075764524309320790962374303489923477172852e-02, // 1.000000
+ 8.93588365430456332827446885858080349862575531005859e-02, // 1.100000
+ 8.88446016412571676346132676371780689805746078491211e-02, // 1.200000
+ 8.82913990780017921000677461051964201033115386962891e-02, // 1.300000
+ 8.77010230126132606098821042905910871922969818115234e-02, // 1.400000
+ 8.70752622608445409069233278387400787323713302612305e-02, // 1.500000
+ 8.64158958878580990559115093674336094409227371215820e-02, // 1.600000
+ 8.57246891169329561233070080561446957290172576904297e-02, // 1.700000
+ 8.50033895481578094521779576098197139799594879150391e-02, // 1.800000
+ 8.42537236802113342903908232983667403459548950195312e-02, // 1.900000
+ 8.34773937273183275209476050804369151592254638671875e-02, // 2.000000
+ 7.72637758157185411400647012669651303440332412719727e-02, // 2.718282
+ 7.32283395263601255553709279411123134195804595947266e-02, // 3.141593
+ };
+
+ public static final double[] SCIPY_GUMBEL_CDF_01_1 = { //
+ 3.31154277189507073586582919233478605747222900390625e-01, // 0.000000
+ 3.31157936975598421458499842628953047096729278564453e-01, // 0.000010
+ 3.67879441171442334024277442949824035167694091796875e-01, // 0.100000
+ 3.76507892217193051997981001477455720305442810058594e-01, // 0.123457
+ 4.04607661664131867951255117077380418777465820312500e-01, // 0.200000
+ 4.30794607123086759070673679161700420081615447998047e-01, // 0.271828
+ 4.40991025942982672880532390990993008017539978027344e-01, // 0.300000
+ 4.46096575846239407070470406324602663516998291015625e-01, // 0.314159
+ 4.76723690714594083850386141421040520071983337402344e-01, // 0.400000
+ 5.11544833689041578139722332707606256008148193359375e-01, // 0.500000
+ 5.45239211892605046827497972117271274328231811523438e-01, // 0.600000
+ 5.77635844258915676086019175272667780518531799316406e-01, // 0.700000
+ 6.08605317804406409365469698968809098005294799804688e-01, // 0.800000
+ 6.38056166582018691180167024867841973900794982910156e-01, // 0.900000
+ 6.65930705440122117089174480497604236006736755371094e-01, // 1.000000
+ 6.92200627555346392760782237019157037138938903808594e-01, // 1.100000
+ 7.16862603474862081220919662882806733250617980957031e-01, // 1.200000
+ 7.39934054783606187655209396325517445802688598632812e-01, // 1.300000
+ 7.61449220009415284060594331094762310385704040527344e-01, // 1.400000
+ 7.81455584849563456018017859605606645345687866210938e-01, // 1.500000
+ 8.00010713004353557487036141537828370928764343261719e-01, // 1.600000
+ 8.17179486939028754122205100429710000753402709960938e-01, // 1.700000
+ 8.33031748536220639778093755012378096580505371093750e-01, // 1.800000
+ 8.47640316515773317718185353442095220088958740234375e-01, // 1.900000
+ 8.61079349396833837460007998743094503879547119140625e-01, // 2.000000
+ 9.29667709628290483969692559185205027461051940917969e-01, // 2.718282
+ 9.53363743354765147408613756851991638541221618652344e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_GUMBEL_PDF_01_1 = { //
+ 3.65982076509606846226319021297967992722988128662109e-01, // 0.000000
+ 3.65982461392446445369586172091658227145671844482422e-01, // 0.000010
+ 3.67879441171442334024277442949824035167694091796875e-01, // 0.100000
+ 3.67779034862618203760575852356851100921630859375000e-01, // 0.123457
+ 3.66104151897740148768889412167482078075408935546875e-01, // 0.200000
+ 3.62782413998306907387814135290682315826416015625000e-01, // 0.271828
+ 3.61052914770930044596752850338816642761230468750000e-01, // 0.300000
+ 3.60097994370001339703435405681375414133071899414062e-01, // 0.314159
+ 3.53165596312007168400270984420785680413246154785156e-01, // 0.400000
+ 3.42898756467731824493228032224578782916069030761719e-01, // 0.500000
+ 3.30704298890418080247854959452524781227111816406250e-01, // 0.600000
+ 3.17013272754289754384871002912404946982860565185547e-01, // 0.700000
+ 3.02224456630968474346587981926859356462955474853516e-01, // 0.800000
+ 2.86697116378903826827695411338936537504196166992188e-01, // 0.900000
+ 2.70747220321607584558876169467112049460411071777344e-01, // 1.000000
+ 2.54646380043582531982337968656793236732482910156250e-01, // 1.100000
+ 2.38622831681304076179017670256143901497125625610352e-01, // 1.200000
+ 2.22863854497548474764556658556102775037288665771484e-01, // 1.300000
+ 2.07519121233516318225653662921104114502668380737305e-01, // 1.400000
+ 1.92704574679114809532265439884213265031576156616211e-01, // 1.500000
+ 1.78506518513120937541316379792988300323486328125000e-01, // 1.600000
+ 1.64985692989648907724742343816615175455808639526367e-01, // 1.700000
+ 1.52181175470408269756461550059611909091472625732422e-01, // 1.800000
+ 1.40114001931851056559352741714974399656057357788086e-01, // 1.900000
+ 1.28790449330409367822980470918992068618535995483398e-01, // 2.000000
+ 6.77988607946176241592084465992229524999856948852539e-02, // 2.718282
+ 4.55314756659847622022319058032735483720898628234863e-02, // 3.141593
+ };
+
+ public static final double[] P_QUANT = { //
+ 0.0001, 0.001, 0.01, 0.1, 0.25, 0.5, 0.75, 0.9, 0.99, 0.999, 0.9999 //
+ };
+
+ public static final double[] SCIPY_GUMBEL_QUANT_1_1 = { //
+ -1.22032680636784629513158506597392261028289794921875e+00, // 0.000100
+ -9.32644733916065504786274686921387910842895507812500e-01, // 0.001000
+ -5.27179625807901119927123545494396239519119262695312e-01, // 0.010000
+ 1.65967554752044277321942900016438215970993041992188e-01, // 0.100000
+ 6.73365740021719005881095654331147670745849609375000e-01, // 0.250000
+ 1.36651292058166440313016209984198212623596191406250e+00, // 0.500000
+ 2.24589932370723843746418424416333436965942382812500e+00, // 0.750000
+ 3.25036732731244537575321373878978192806243896484375e+00, // 0.900000
+ 5.60014922677657889238389543606899678707122802734375e+00, // 0.990000
+ 7.90725507052371590077655127970501780509948730468750e+00, // 0.999000
+ 1.02102903698928351161612226860597729682922363281250e+01, // 0.999900
+ };
+
+ public static final double[] SCIPY_GUMBEL_QUANT_2_1 = { //
+ -2.20326806367846295131585065973922610282897949218750e-01, // 0.000100
+ 6.73552660839344952137253130786120891571044921875000e-02, // 0.001000
+ 4.72820374192098880072876454505603760480880737304688e-01, // 0.010000
+ 1.16596755475204427732194290001643821597099304199219e+00, // 0.100000
+ 1.67336574002171900588109565433114767074584960937500e+00, // 0.250000
+ 2.36651292058166440313016209984198212623596191406250e+00, // 0.500000
+ 3.24589932370723843746418424416333436965942382812500e+00, // 0.750000
+ 4.25036732731244537575321373878978192806243896484375e+00, // 0.900000
+ 6.60014922677657889238389543606899678707122802734375e+00, // 0.990000
+ 8.90725507052371590077655127970501780509948730468750e+00, // 0.999000
+ 1.12102903698928351161612226860597729682922363281250e+01, // 0.999900
+ };
+
+ public static final double[] SCIPY_GUMBEL_QUANT_4_1 = { //
+ 1.77967319363215370486841493402607738971710205078125e+00, // 0.000100
+ 2.06735526608393449521372531307861208915710449218750e+00, // 0.001000
+ 2.47282037419209910211748137953691184520721435546875e+00, // 0.010000
+ 3.16596755475204449936654782504774630069732666015625e+00, // 0.100000
+ 3.67336574002171900588109565433114767074584960937500e+00, // 0.250000
+ 4.36651292058166440313016209984198212623596191406250e+00, // 0.500000
+ 5.24589932370723843746418424416333436965942382812500e+00, // 0.750000
+ 6.25036732731244537575321373878978192806243896484375e+00, // 0.900000
+ 8.60014922677657978056231513619422912597656250000000e+00, // 0.990000
+ 1.09072550705237159007765512797050178050994873046875e+01, // 0.999000
+ 1.32102903698928351161612226860597729682922363281250e+01, // 0.999900
+ };
+
+ public static final double[] SCIPY_GUMBEL_QUANT_4_10 = { //
+ -1.82032680636784647276726900599896907806396484375000e+01, // 0.000100
+ -1.53264473391606550478627468692138791084289550781250e+01, // 0.001000
+ -1.12717962580790107551820256048813462257385253906250e+01, // 0.010000
+ -4.34032445247955678269136114977300167083740234375000e+00, // 0.100000
+ 7.33657400217190502900166393374092876911163330078125e-01, // 0.250000
+ 7.66512920581664403130162099841982126235961914062500e+00, // 0.500000
+ 1.64589932370723843746418424416333436965942382812500e+01, // 0.750000
+ 2.65036732731244555338889767881482839584350585937500e+01, // 0.900000
+ 5.00014922677657907001957937609404325485229492187500e+01, // 0.990000
+ 7.30725507052371625604791915975511074066162109375000e+01, // 0.999000
+ 9.61029036989283440561848692595958709716796875000000e+01, // 0.999900
+ };
+
+ public static final double[] SCIPY_GUMBEL_QUANT_01_10 = { //
+ -2.21032680636784633065872185397893190383911132812500e+01, // 0.000100
+ -1.92264473391606536267772753490135073661804199218750e+01, // 0.001000
+ -1.51717962580790111104533934849314391613006591796875e+01, // 0.010000
+ -8.24032445247955713796272902982309460639953613281250e+00, // 0.100000
+ -3.16634259978280940828199163661338388919830322265625e+00, // 0.250000
+ 3.76512920581664367603025311836972832679748535156250e+00, // 0.500000
+ 1.25589932370723822430136351613327860832214355468750e+01, // 0.750000
+ 2.26036732731244569549744483083486557006835937500000e+01, // 0.900000
+ 4.61014922677657921212812652811408042907714843750000e+01, // 0.990000
+ 6.91725507052371568761373055167496204376220703125000e+01, // 0.999000
+ 9.22029036989283383718429831787943840026855468750000e+01, // 0.999900
+ };
+
+ public static final double[] SCIPY_GUMBEL_QUANT_01_20 = { //
+ -4.43065361273569280342599085997790098190307617187500e+01, // 0.000100
+ -3.85528946783213086746400222182273864746093750000000e+01, // 0.001000
+ -3.04435925161580200892785796895623207092285156250000e+01, // 0.010000
+ -1.65806489049591121442972507793456315994262695312500e+01, // 0.100000
+ -6.43268519956561934947103509330190718173980712890625e+00, // 0.250000
+ 7.43025841163328681915345441666431725025177001953125e+00, // 0.500000
+ 2.50179864741447666176554776029661297798156738281250e+01, // 0.750000
+ 4.51073465462489124888634250964969396591186523437500e+01, // 0.900000
+ 9.21029845355315757160497014410793781280517578125000e+01, // 0.990000
+ 1.38245101410474319436616497114300727844238281250000e+02, // 0.999000
+ 1.84305807397856682428027852438390254974365234375000e+02, // 0.999900
+ };
+
+ public static final double[] SCIPY_GUMBEL_QUANT_01_4 = { //
+ -8.78130722547138553579770814394578337669372558593750e+00, // 0.000100
+ -7.63057893566426237441646662773564457893371582031250e+00, // 0.001000
+ -6.00871850323160483497986206202767789363861083984375e+00, // 0.010000
+ -3.23612978099182280189438642992172390222549438476562e+00, // 0.100000
+ -1.20653703991312366561317048763157799839973449707031e+00, // 0.250000
+ 1.56605168232665747929388544434914365410804748535156e+00, // 0.500000
+ 5.08359729482895250640694939647801220417022705078125e+00, // 0.750000
+ 9.10146930924978114774148707510903477668762207031250e+00, // 0.900000
+ 1.85005969071063169906210532644763588905334472656250e+01, // 0.990000
+ 2.77290202820948650241916766390204429626464843750000e+01, // 0.999000
+ 3.69411614795713418857303622644394636154174804687500e+01, // 0.999900
+ };
+
+ public static final double[] SCIPY_GUMBEL_QUANT_01_1 = { //
+ -2.12032680636784620631374309596139937639236450195312e+00, // 0.000100
+ -1.83264473391606541596843271690886467695236206054688e+00, // 0.001000
+ -1.42717962580790103110928157548187300562858581542969e+00, // 0.010000
+ -7.34032445247955744882517592486692592501640319824219e-01, // 0.100000
+ -2.26634259978280933056637991285242605954408645629883e-01, // 0.250000
+ 4.66512920581664380925701607338851317763328552246094e-01, // 0.500000
+ 1.34589932370723830423742128914454951882362365722656e+00, // 0.750000
+ 2.35036732731244546457105570880230516195297241210938e+00, // 0.900000
+ 4.70014922677657853711252755601890385150909423828125e+00, // 0.990000
+ 7.00725507052371554550518339965492486953735351562500e+00, // 0.999000
+ 9.31029036989283476088985480600968003273010253906250e+00, // 0.999900
+ };
+
+ @Test
+ public void testPDF() {
+ checkPDF(new GumbelDistribution(1., 1.), P_CDFPDF, SCIPY_GUMBEL_PDF_1_1, 1e-12);
+ checkPDF(new GumbelDistribution(2., 1.), P_CDFPDF, SCIPY_GUMBEL_PDF_2_1, 1e-12);
+ checkPDF(new GumbelDistribution(4., 1.), P_CDFPDF, SCIPY_GUMBEL_PDF_4_1, 1e-11);
+ checkPDF(new GumbelDistribution(4., 10.), P_CDFPDF, SCIPY_GUMBEL_PDF_4_10, 1e-13);
+ checkPDF(new GumbelDistribution(.1, 1.), P_CDFPDF, SCIPY_GUMBEL_PDF_01_1, 1e-12);
+ checkPDF(new GumbelDistribution(.1, 4.), P_CDFPDF, SCIPY_GUMBEL_PDF_01_4, 1e-12);
+ checkPDF(new GumbelDistribution(.1, 10.), P_CDFPDF, SCIPY_GUMBEL_PDF_01_10, 1e-13);
+ checkPDF(new GumbelDistribution(.1, 20.), P_CDFPDF, SCIPY_GUMBEL_PDF_01_20, 1e-14);
+ }
+
+ @Test
+ public void testCDF() {
+ checkCDF(new GumbelDistribution(1., 1.), P_CDFPDF, SCIPY_GUMBEL_CDF_1_1, 1e-12);
+ checkCDF(new GumbelDistribution(2., 1.), P_CDFPDF, SCIPY_GUMBEL_CDF_2_1, 1e-12);
+ checkCDF(new GumbelDistribution(4., 1.), P_CDFPDF, SCIPY_GUMBEL_CDF_4_1, 1e-11);
+ checkCDF(new GumbelDistribution(4., 10.), P_CDFPDF, SCIPY_GUMBEL_CDF_4_10, 1e-12);
+ checkCDF(new GumbelDistribution(.1, 1.), P_CDFPDF, SCIPY_GUMBEL_CDF_01_1, 1e-13);
+ checkCDF(new GumbelDistribution(.1, 4.), P_CDFPDF, SCIPY_GUMBEL_CDF_01_4, 1e-13);
+ checkCDF(new GumbelDistribution(.1, 10.), P_CDFPDF, SCIPY_GUMBEL_CDF_01_10, 1e-13);
+ checkCDF(new GumbelDistribution(.1, 20.), P_CDFPDF, SCIPY_GUMBEL_CDF_01_20, 1e-13);
+ }
+
+ @Test
+ public void testQuantile() {
+ checkQuantile(new GumbelDistribution(1., 1.), P_QUANT, SCIPY_GUMBEL_QUANT_1_1, 1e-13);
+ checkQuantile(new GumbelDistribution(2., 1.), P_QUANT, SCIPY_GUMBEL_QUANT_2_1, 1e-13);
+ checkQuantile(new GumbelDistribution(4., 1.), P_QUANT, SCIPY_GUMBEL_QUANT_4_1, 1e-13);
+ checkQuantile(new GumbelDistribution(4., 10.), P_QUANT, SCIPY_GUMBEL_QUANT_4_10, 1e-13);
+ checkQuantile(new GumbelDistribution(.1, 1.), P_QUANT, SCIPY_GUMBEL_QUANT_01_1, 1e-13);
+ checkQuantile(new GumbelDistribution(.1, 4.), P_QUANT, SCIPY_GUMBEL_QUANT_01_4, 1e-13);
+ checkQuantile(new GumbelDistribution(.1, 10.), P_QUANT, SCIPY_GUMBEL_QUANT_01_10, 1e-13);
+ checkQuantile(new GumbelDistribution(.1, 20.), P_QUANT, SCIPY_GUMBEL_QUANT_01_20, 1e-13);
+ }
+}
diff --git a/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestLogGammaAlternateDistribution.java b/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestLogGammaAlternateDistribution.java
new file mode 100644
index 00000000..07f111e5
--- /dev/null
+++ b/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestLogGammaAlternateDistribution.java
@@ -0,0 +1,672 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2012
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import org.junit.Test;
+
+import de.lmu.ifi.dbs.elki.JUnit4Test;
+
+/**
+ * Unit test for the LogGamma distribution in ELKI.
+ *
+ * The reference values were computed using GNU R and SciPy.
+ *
+ * @author Erich Schubert
+ */
+public class TestLogGammaAlternateDistribution extends AbstractDistributionTest implements JUnit4Test {
+ public static final double[] P_CDFPDF = { //
+ 1e-10, 1e-05, 0.1, 0.1234567, 0.2, 0.271828182846, 0.3, 0.314159265359, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.71828182846, 3.14159265359 //
+ };
+
+ public static final double[] SCIPY_LOGGAMMA_CDF_1_1 = { //
+ 6.32120558865345572030491894111037254333496093750000e-01, // 0.000000
+ 6.32124237622968987437843679799698293209075927734375e-01, // 0.000010
+ 6.68845722847090984330975516058970242738723754882812e-01, // 0.100000
+ 6.77419000750269617583398940041661262512207031250000e-01, // 0.123457
+ 7.05183679270841912156697617319878190755844116210938e-01, // 0.200000
+ 7.30816370768268552815527527855010703206062316894531e-01, // 0.271828
+ 7.40723134009172445857416278158780187368392944335938e-01, // 0.300000
+ 7.45666217579490364641969790682196617126464843750000e-01, // 0.314159
+ 7.75038206450081590404010967176873236894607543945312e-01, // 0.400000
+ 8.07704354452035144795729593170108273625373840332031e-01, // 0.500000
+ 8.38317185854873470063353124714922159910202026367188e-01, // 0.600000
+ 8.66513203341916171673631197336362674832344055175781e-01, // 0.700000
+ 8.91991022303408431781690524076111614704132080078125e-01, // 0.800000
+ 9.14531134124054068124110017379280179738998413085938e-01, // 0.900000
+ 9.34011964154687457373427150741918012499809265136719e-01, // 1.000000
+ 9.50419914304432955631796176021452993154525756835938e-01, // 1.100000
+ 9.63851395086864459749165234825341030955314636230469e-01, // 1.200000
+ 9.74505605324275880896323087654309347271919250488281e-01, // 1.300000
+ 9.82667985991235504172891523921862244606018066406250e-01, // 1.400000
+ 9.88685713619540385010964200773742049932479858398438e-01, // 1.500000
+ 9.92938038437790604362476187816355377435684204101562e-01, // 1.600000
+ 9.95805358458610623273443707148544490337371826171875e-01, // 1.700000
+ 9.97641306616706802223859540390549227595329284667969e-01, // 1.800000
+ 9.98751602365355761747878204914741218090057373046875e-01, // 1.900000
+ 9.99382021010668863958414931403240188956260681152344e-01, // 2.000000
+ 9.99999737827261037104165097844088450074195861816406e-01, // 2.718282
+ 9.99999999910849313167204854835290461778640747070312e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_LOGGAMMA_PDF_1_1 = { //
+ 3.67879441171442334024277442949824035167694091796875e-01, // 0.000000
+ 3.67879441153048325485741543161566369235515594482422e-01, // 0.000010
+ 3.65982076505757758511094834830146282911300659179688e-01, // 0.100000
+ 3.64968469589419641785354997409740462899208068847656e-01, // 0.123457
+ 3.60089467289227027624320953691494651138782501220703e-01, // 0.200000
+ 3.53266230282285820241128249108442105352878570556641e-01, // 0.271828
+ 3.49987161158421655748895773285767063498497009277344e-01, // 0.300000
+ 3.48210357844328799448163636043318547308444976806641e-01, // 0.314159
+ 3.35603559643444959714742026335443370044231414794922e-01, // 0.400000
+ 3.17041921077942157047857563156867399811744689941406e-01, // 0.500000
+ 2.94605295353879415021225440796115435659885406494141e-01, // 0.600000
+ 2.68809398181777292613503504981053993105888366699219e-01, // 0.700000
+ 2.40378400508394596268857412724173627793788909912109e-01, // 0.800000
+ 2.10219488415532618219572214002255350351333618164062e-01, // 0.900000
+ 1.79374078734017200487116383555985521525144577026367e-01, // 1.000000
+ 1.48946808910974892725675999827217310667037963867188e-01, // 1.100000
+ 1.20017594905418772954774908612307626754045486450195e-01, // 1.200000
+ 9.35464974266043275408222257283341605216264724731445e-02, // 1.300000
+ 7.02847826336932546276159428089158609509468078613281e-02, // 1.400000
+ 5.07071136099807306951703367303707636892795562744141e-02, // 1.500000
+ 3.49781245974551888155978929262346355244517326354980e-02, // 1.600000
+ 2.29612471247189892098461427849542815238237380981445e-02, // 1.700000
+ 1.42692634455674535048919082669272029306739568710327e-02, // 1.800000
+ 8.34665480722261883539392357533870381303131580352783e-03, // 1.900000
+ 4.56628142012791525539139314560088678263127803802490e-03, // 2.000000
+ 3.97303443855662314872830703782469186080561485141516e-06, // 2.718282
+ 2.06300953864877018550080075740774804282651189168973e-09, // 3.141593
+ };
+
+ public static final double[] SCIPY_LOGGAMMA_CDF_2_1 = { //
+ 2.64241117693903238006214451161213219165802001953125e-01, // 0.000000
+ 2.64244796469920995019009524185094051063060760498047e-01, // 0.000010
+ 3.02863646341333336842183143744478002190589904785156e-01, // 0.100000
+ 3.12450531160849975798043942631920799612998962402344e-01, // 0.123457
+ 3.45094211981614884532376663628383539617061614990234e-01, // 0.200000
+ 3.77550140485982788085550510004395619034767150878906e-01, // 0.271828
+ 3.90735972850750901130822967388667166233062744140625e-01, // 0.300000
+ 3.97455859735161454171503692123224027454853057861328e-01, // 0.314159
+ 4.39434646806636519666966478325775824487209320068359e-01, // 0.400000
+ 4.90662433374092876725569567497586831450462341308594e-01, // 0.500000
+ 5.43711890500994221575581377692287787795066833496094e-01, // 0.600000
+ 5.97703805160138879060127692355308681726455688476562e-01, // 0.700000
+ 6.51612621795013780001681880094110965728759765625000e-01, // 0.800000
+ 7.04311645708521449904537803377024829387664794921875e-01, // 0.900000
+ 7.54637885420670229130735151557018980383872985839844e-01, // 1.000000
+ 8.01473105393458062906120176194235682487487792968750e-01, // 1.100000
+ 8.43833800181445714549965941841946914792060852050781e-01, // 1.200000
+ 8.80959107897671511722137438482604920864105224609375e-01, // 1.300000
+ 9.12383203357542194034124349855119362473487854003906e-01, // 1.400000
+ 9.37978600009559682071369479672284796833992004394531e-01, // 1.500000
+ 9.57959913840335408607984390982892364263534545898438e-01, // 1.600000
+ 9.72844111333891592430234140920219942927360534667969e-01, // 1.700000
+ 9.83372043171139353923138060054043307900428771972656e-01, // 1.800000
+ 9.90404947558133130769419949501752853393554687500000e-01, // 1.900000
+ 9.94815739590541037173920813074801117181777954101562e-01, // 2.000000
+ 9.99995764792822483535417177336057648062705993652344e-01, // 2.718282
+ 9.99999997847839772191491647390648722648620605468750e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_LOGGAMMA_PDF_2_1 = { //
+ 3.67879441208230295590198011268512345850467681884766e-01, // 0.000000
+ 3.67883119965853877531003490730654448270797729492188e-01, // 0.000010
+ 4.04472747491100181882472952565876767039299011230469e-01, // 0.100000
+ 4.12925696504904959915904782974394038319587707519531e-01, // 0.123457
+ 4.39814268531488139490903677142341621220111846923828e-01, // 0.200000
+ 4.63612998361142059078332522403798066079616546630859e-01, // 0.271828
+ 4.72433252028217454121516993836848996579647064208984e-01, // 0.300000
+ 4.76737506736729155232268340114387683570384979248047e-01, // 0.314159
+ 5.00661678892416417419042318215360864996910095214844e-01, // 0.400000
+ 5.22713758984834520049389539053663611412048339843750e-01, // 0.500000
+ 5.36805847358902354926613043062388896942138671875000e-01, // 0.600000
+ 5.41315653382063444176708344457438215613365173339844e-01, // 0.700000
+ 5.34971968656986818224652324715862050652503967285156e-01, // 0.800000
+ 5.17056507732666426058187880698824301362037658691406e-01, // 0.900000
+ 4.87589298719261043935091493040090426802635192871094e-01, // 1.000000
+ 4.47460942705592668033887093770317733287811279296875e-01, // 1.100000
+ 3.98472447871620394366232176253106445074081420898438e-01, // 1.200000
+ 3.43249851274891548680301411877735517919063568115234e-01, // 1.300000
+ 2.85018848205838060128058941700146533548831939697266e-01, // 1.400000
+ 2.27253516854241194300456641030905302613973617553711e-01, // 1.500000
+ 1.73247785275727900211606424818455707281827926635742e-01, // 1.600000
+ 1.25688658809159137241806547535816207528114318847656e-01, // 1.700000
+ 8.63240134225174982063322204339783638715744018554688e-02, // 1.800000
+ 5.58048529872332277346202999979141168296337127685547e-02, // 1.900000
+ 3.37405095768298773917237554087478201836347579956055e-02, // 2.000000
+ 6.02084057763153639316298926242865263702697120606899e-05, // 2.718282
+ 4.77394696323629441641945875696856349534868968476076e-08, // 3.141593
+ };
+
+ public static final double[] SCIPY_LOGGAMMA_CDF_4_1 = { //
+ 1.89881568822851329314538304515735944733023643493652e-02, // 0.000000
+ 1.89887700177528255529590950345664168708026409149170e-02, // 0.000010
+ 2.61253529822300795126821526537241879850625991821289e-02, // 0.100000
+ 2.81235909655702942533395116697647608816623687744141e-02, // 0.123457
+ 3.56553509387778355677056651984457857906818389892578e-02, // 0.200000
+ 4.43389999778885657288896027239388786256313323974609e-02, // 0.271828
+ 4.82329824629648754030775137380260275676846504211426e-02, // 0.300000
+ 5.03029355298684754949078978825127705931663513183594e-02, // 0.314159
+ 6.46205644047200128410324282413057517260313034057617e-02, // 0.400000
+ 8.56706717273561235703738248048466630280017852783203e-02, // 0.500000
+ 1.12288295716173991412034638415207155048847198486328e-01, // 0.600000
+ 1.45366668036726959245541479504026938229799270629883e-01, // 0.700000
+ 1.85692968826134785498283008564612828195095062255859e-01, // 0.800000
+ 2.33824425998319124220259368485130835324525833129883e-01, // 0.900000
+ 2.89942380984430481127844814182026311755180358886719e-01, // 1.000000
+ 3.53701473854131198670813773787813261151313781738281e-01, // 1.100000
+ 4.24101723341831882141406140362960286438465118408203e-01, // 1.200000
+ 4.99419926352932252999750062372186221182346343994141e-01, // 1.300000
+ 5.77239041955553089380259734753053635358810424804688e-01, // 1.400000
+ 6.54605241135515658612575862207449972629547119140625e-01, // 1.500000
+ 7.28319038214917613416332642373163253068923950195312e-01, // 1.600000
+ 7.95330930919631029496486007701605558395385742187500e-01, // 1.700000
+ 8.53171728306633569971495489880908280611038208007812e-01, // 1.800000
+ 9.00318294991257483950164441921515390276908874511719e-01, // 1.900000
+ 9.36393731790508887513624358689412474632263183593750e-01, // 2.000000
+ 9.99813591594888362301674078480573371052742004394531e-01, // 2.718282
+ 9.99999789857372700652149433153681457042694091796875e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_LOGGAMMA_PDF_4_1 = { //
+ 6.13132402136343651610772553794959094375371932983398e-02, // 0.000000
+ 6.13150796169717390848852289764181477949023246765137e-02, // 0.000010
+ 8.23373548977086172628858662392303813248872756958008e-02, // 0.100000
+ 8.80955125640966868472148121327336411923170089721680e-02, // 0.123457
+ 1.09354298028383978280686505968333221971988677978516e-01, // 0.200000
+ 1.33079546765686368425818386640457902103662490844727e-01, // 0.271828
+ 1.43471585075040430901083254866534844040870666503906e-01, // 0.300000
+ 1.48937253613819708952803466672776266932487487792969e-01, // 0.314159
+ 1.85707176283804342720173963243723846971988677978516e-01, // 0.400000
+ 2.36813885422332809360668193221499677747488021850586e-01, // 0.500000
+ 2.97043029673370651000396946983528323471546173095703e-01, // 0.600000
+ 3.65857203274574493967463695298647508025169372558594e-01, // 0.700000
+ 4.41622251150090516791379968708497472107410430908203e-01, // 0.800000
+ 5.21334931827189818065448889683466404676437377929688e-01, // 0.900000
+ 6.00470780245812463249421853106468915939331054687500e-01, // 1.000000
+ 6.73056841397915439628718559106346219778060913085938e-01, // 1.100000
+ 7.32072012619148004830549325561150908470153808593750e-01, // 1.200000
+ 7.70237679686405218859590604552067816257476806640625e-01, // 1.300000
+ 7.81172380308322367170603683916851878166198730468750e-01, // 1.400000
+ 7.60751483950018791979630350397201254963874816894531e-01, // 1.500000
+ 7.08367753976518632619274740136461332440376281738281e-01, // 1.600000
+ 6.27691257896798693316497974592493847012519836425781e-01, // 1.700000
+ 5.26551080226083545454685008735395967960357666015625e-01, // 1.800000
+ 4.15757171500640287931105376628693193197250366210938e-01, // 1.900000
+ 3.07028234011749667775603711561416275799274444580078e-01, // 2.000000
+ 2.30449342972448420127640211774178169434890151023865e-03, // 2.718282
+ 4.26068127121804497963591940035144034482073038816452e-06, // 3.141593
+ };
+
+ public static final double[] SCIPY_LOGGAMMA_CDF_4_10 = { //
+ 1.89881569374670579330999231615351163782179355621338e-02, // 0.000000
+ 1.89942891199536868784836229906431981362402439117432e-02, // 0.000010
+ 2.89942380984430481127844814182026311755180358886719e-01, // 0.100000
+ 4.49689791586118492450196981735643930733203887939453e-01, // 0.123457
+ 9.36393731790508887513624358689412474632263183593750e-01, // 0.200000
+ 9.99813591594888362301674078480573371052742004394531e-01, // 0.271828
+ 9.99997023008917240716186825011391192674636840820312e-01, // 0.300000
+ 9.99999789857372700652149433153681457042694091796875e-01, // 0.314159
+ 1.00000000000000000000000000000000000000000000000000e+00, // 0.400000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 0.500000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 0.600000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 0.700000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 0.800000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 0.900000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.000000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.100000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.200000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.300000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.400000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.500000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.600000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.700000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.800000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.900000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 2.000000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 2.718282
+ 1.00000000000000000000000000000000000000000000000000e+00, // 3.141593
+ };
+
+ public static final double[] SCIPY_LOGGAMMA_PDF_4_10 = { //
+ 6.13132403791800895120900349866133183240890502929688e-01, // 0.000000
+ 6.13316366200022833332639038417255505919456481933594e-01, // 0.000010
+ 6.00470780245812463249421853106468915939331054687500e+00, // 0.100000
+ 7.47978163723896560810544542619027197360992431640625e+00, // 0.123457
+ 3.07028234011749656673373465309850871562957763671875e+00, // 0.200000
+ 2.30449342972449608413221255887037841603159904479980e-02, // 0.271828
+ 5.13268581343153621615593706906111037824302911758423e-04, // 0.300000
+ 4.26068127121804497963591940035144034482073038816452e-05, // 0.314159
+ 2.87663777096353381165139848770654588739438492245738e-17, // 0.400000
+ 2.83610527480158774910577794815980995977618360070194e-56, // 0.500000
+ 2.74168439726173051715348577927730977333274164887227e-165, // 0.600000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.700000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.800000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.900000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.000000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.100000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.200000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.300000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.400000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.500000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.600000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.700000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.800000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.900000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 2.000000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 2.718282
+ 0.00000000000000000000000000000000000000000000000000e+00, // 3.141593
+ };
+
+ public static final double[] SCIPY_LOGGAMMA_CDF_01_10 = { //
+ 9.75872656312341435480561813164968043565750122070312e-01, // 0.000000
+ 9.75876523016603880655850389302941039204597473144531e-01, // 0.000010
+ 9.97771302397556292262947863491717725992202758789062e-01, // 0.100000
+ 9.99085373345744098827481138869188725948333740234375e-01, // 0.123457
+ 9.99990322880914939140950536966556683182716369628906e-01, // 0.200000
+ 9.99999997740172674731695678929099813103675842285156e-01, // 0.271828
+ 9.99999999987182364158400105225155130028724670410156e-01, // 0.300000
+ 9.99999999999465538635945449641440063714981079101562e-01, // 0.314159
+ 1.00000000000000000000000000000000000000000000000000e+00, // 0.400000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 0.500000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 0.600000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 0.700000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 0.800000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 0.900000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.000000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.100000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.200000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.300000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.400000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.500000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.600000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.700000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.800000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.900000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 2.000000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 2.718282
+ 1.00000000000000000000000000000000000000000000000000e+00, // 3.141593
+ };
+
+ public static final double[] SCIPY_LOGGAMMA_PDF_01_10 = { //
+ 3.86691694055001200513999037866597063839435577392578e-01, // 0.000000
+ 3.86656891783232925519087075372226536273956298828125e-01, // 0.000010
+ 7.66573807128762413354294835698965471237897872924805e-02, // 0.100000
+ 3.82519444836298613821234937404369702562689781188965e-02, // 0.123457
+ 7.93399517782126173157108972588957840343937277793884e-04, // 0.200000
+ 3.61659882683325373483495179458002688477336050709710e-07, // 0.271828
+ 2.68478689210771182002679843229143302751893429558550e-09, // 0.300000
+ 1.28298578206074916753204354692176596824948475727979e-10, // 0.314159
+ 3.04580319059060921083886090465841494937109628893572e-24, // 0.400000
+ 6.07841750487491422247162425697089017615956979567134e-65, // 0.500000
+ 1.18942526811122497186251097706497282965193428534428e-175, // 0.600000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.700000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.800000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.900000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.000000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.100000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.200000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.300000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.400000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.500000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.600000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.700000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.800000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.900000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 2.000000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 2.718282
+ 0.00000000000000000000000000000000000000000000000000e+00, // 3.141593
+ };
+
+ public static final double[] SCIPY_LOGGAMMA_CDF_01_20 = { //
+ 9.75872656351010503428256015467923134565353393554688e-01, // 0.000000
+ 9.75880389411505455576900658343220129609107971191406e-01, // 0.000010
+ 9.99990322880914939140950536966556683182716369628906e-01, // 0.100000
+ 9.99999921146446313358069346577394753694534301757812e-01, // 0.123457
+ 1.00000000000000000000000000000000000000000000000000e+00, // 0.200000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 0.271828
+ 1.00000000000000000000000000000000000000000000000000e+00, // 0.300000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 0.314159
+ 1.00000000000000000000000000000000000000000000000000e+00, // 0.400000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 0.500000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 0.600000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 0.700000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 0.800000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 0.900000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.000000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.100000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.200000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.300000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.400000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.500000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.600000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.700000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.800000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.900000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 2.000000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 2.718282
+ 1.00000000000000000000000000000000000000000000000000e+00, // 3.141593
+ };
+
+ public static final double[] SCIPY_LOGGAMMA_PDF_01_20 = { //
+ 7.73383387413957290590360571513883769512176513671875e-01, // 0.000000
+ 7.73244176858206899716208226891467347741127014160156e-01, // 0.000010
+ 1.58679903556425234631421794517791568068787455558777e-03, // 0.100000
+ 1.99500277683705806545944039243067891220562160015106e-05, // 0.123457
+ 6.09160638118121842167772180931682989874219257787145e-24, // 0.200000
+ 6.64271790906281664176004049075875506156745355852006e-100, // 0.271828
+ 2.37885053622244994372502195412994565930386857068856e-175, // 0.300000
+ 1.08266349311588655483576215872042725531821155344122e-232, // 0.314159
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.400000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.500000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.600000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.700000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.800000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.900000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.000000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.100000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.200000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.300000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.400000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.500000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.600000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.700000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.800000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.900000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 2.000000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 2.718282
+ 0.00000000000000000000000000000000000000000000000000e+00, // 3.141593
+ };
+
+ public static final double[] SCIPY_LOGGAMMA_CDF_01_4 = { //
+ 9.75872656289139994711945291783194988965988159179688e-01, // 0.000000
+ 9.75874203012607965845859325781930238008499145507812e-01, // 0.000010
+ 9.88521989554807967159888448804849758744239807128906e-01, // 0.100000
+ 9.90682106581839194703320572443772107362747192382812e-01, // 0.123457
+ 9.95795137017725928707534421846503391861915588378906e-01, // 0.200000
+ 9.98367638432702042550204168946947902441024780273438e-01, // 0.271828
+ 9.98945317922235953567167143773986026644706726074219e-01, // 0.300000
+ 9.99166739486790800306437176914187148213386535644531e-01, // 0.314159
+ 9.99848025621776881344260345940710976719856262207031e-01, // 0.400000
+ 9.99990322880914939140950536966556683182716369628906e-01, // 0.500000
+ 9.99999816093564919405878299585310742259025573730469e-01, // 0.600000
+ 9.99999999419964535896099278033943846821784973144531e-01, // 0.700000
+ 9.99999999999873656619797657185699790716171264648438e-01, // 0.800000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 0.900000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.000000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.100000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.200000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.300000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.400000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.500000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.600000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.700000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.800000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 1.900000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 2.000000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 2.718282
+ 1.00000000000000000000000000000000000000000000000000e+00, // 3.141593
+ };
+
+ public static final double[] SCIPY_LOGGAMMA_PDF_01_4 = { //
+ 1.54676677705525900119454263403895311057567596435547e-01, // 0.000000
+ 1.54671109377300830534096576229785569012165069580078e-01, // 0.000010
+ 9.84464052270282996559558341687079519033432006835938e-02, // 0.100000
+ 8.58108052000031706896265859541017562150955200195312e-02, // 0.123457
+ 4.91952001039043101959791215449513401836156845092773e-02, // 0.200000
+ 2.41377289439051283259640712230975623242557048797607e-02, // 0.271828
+ 1.71366606385362704734198757705598836764693260192871e-02, // 0.300000
+ 1.42024583125499245794820524224633118137717247009277e-02, // 0.314159
+ 3.48443031793151504829642028937541908817365765571594e-03, // 0.400000
+ 3.17359807112850480104865313890627476212102919816971e-04, // 0.500000
+ 8.72258716114687767772921389575202510968665592372417e-06, // 0.600000
+ 4.01330737127810106150866157823098312462661851895973e-08, // 0.700000
+ 1.28336756744997760816790662079631580184263528465749e-11, // 0.800000
+ 7.68518036611483919318729926999253387631177034870593e-17, // 0.900000
+ 1.21832127623624368433554436186336597974843851557429e-24, // 1.000000
+ 2.76150657747027996328471734486001464284084376015250e-36, // 1.100000
+ 1.15047410120420279456129534473030897392716993393999e-53, // 1.200000
+ 1.33050980492765102664431323936746771679614454246348e-79, // 1.300000
+ 2.64379466050064674479079986745942626514867284146420e-118, // 1.400000
+ 4.75770107244327689646329016597701524441576128422297e-176, // 1.500000
+ 3.33955712784524322177202771066577131845898338987944e-262, // 1.600000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.700000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.800000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 1.900000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 2.000000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 2.718282
+ 0.00000000000000000000000000000000000000000000000000e+00, // 3.141593
+ };
+
+ public static final double[] SCIPY_LOGGAMMA_CDF_01_1 = { //
+ 9.75872656277539052283032106061000376939773559570312e-01, // 0.000000
+ 9.75873042963626202705995638098102062940597534179688e-01, // 0.000010
+ 9.79564498296314867253897773480275645852088928222656e-01, // 0.100000
+ 9.80379475959243795735176263406174257397651672363281e-01, // 0.123457
+ 9.82903290234357296384359869989566504955291748046875e-01, // 0.200000
+ 9.85082822462057028367610200803028419613838195800781e-01, // 0.271828
+ 9.85887936645999274354323915758868679404258728027344e-01, // 0.300000
+ 9.86282063361266780887603999872226268053054809570312e-01, // 0.314159
+ 9.88521989554807967159888448804849758744239807128906e-01, // 0.400000
+ 9.90813910099314409940518544317455962300300598144531e-01, // 0.500000
+ 9.92777145076669365053589899616781622171401977539062e-01, // 0.600000
+ 9.94429979424373611252008231531362980604171752929688e-01, // 0.700000
+ 9.95795137017725928707534421846503391861915588378906e-01, // 0.800000
+ 9.96899120167219043864292871148791164159774780273438e-01, // 0.900000
+ 9.97771302397556292262947863491717725992202758789062e-01, // 1.000000
+ 9.98442817593759524008589778532041236758232116699219e-01, // 1.100000
+ 9.98945317922235953567167143773986026644706726074219e-01, // 1.200000
+ 9.99309698140446789338398048130329698324203491210938e-01, // 1.300000
+ 9.99564899282052388151953437045449391007423400878906e-01, // 1.400000
+ 9.99736904974793616496242520952364429831504821777344e-01, // 1.500000
+ 9.99848025621776881344260345940710976719856262207031e-01, // 1.600000
+ 9.99916529849280033559466573933605104684829711914062e-01, // 1.700000
+ 9.99956634133785438045549653907073661684989929199219e-01, // 1.800000
+ 9.99978809766067122666299837874248623847961425781250e-01, // 1.900000
+ 9.99990322880914939140950536966556683182716369628906e-01, // 2.000000
+ 9.99999997740172674731695678929099813103675842285156e-01, // 2.718282
+ 9.99999999999465538635945449641440063714981079101562e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_LOGGAMMA_PDF_01_1 = { //
+ 3.86691694368221511313166161016852129250764846801758e-02, // 0.000000
+ 3.86688214174100569620051714991859626024961471557617e-02, // 0.000010
+ 3.51586863187947004649736015835514990612864494323730e-02, // 0.100000
+ 3.43288903336685033429453994813229655846953392028809e-02, // 0.123457
+ 3.16152585351597847918014849710743874311447143554688e-02, // 0.200000
+ 2.90745711878013547713184294707389199174940586090088e-02, // 0.271828
+ 2.80835450574022579828259438272652914747595787048340e-02, // 0.300000
+ 2.75871692713388766415860686720407102257013320922852e-02, // 0.314159
+ 2.46116013067570749139889585421769879758358001708984e-02, // 0.400000
+ 2.12492448134385600311269115536561002954840660095215e-02, // 0.500000
+ 1.80459959087036214686605717361089773476123809814453e-02, // 0.600000
+ 1.50486745835341825111575175810685323085635900497437e-02, // 0.700000
+ 1.22988000259760775489947803862378350459039211273193e-02, // 0.800000
+ 9.83000572039229893184231201530565158464014530181885e-03, // 0.900000
+ 7.66573807128762517437703394307391135953366756439209e-03, // 1.000000
+ 5.81753483010033056038734500248210679274052381515503e-03, // 1.100000
+ 4.28416515963406761835496894263997091911733150482178e-03, // 1.200000
+ 3.05184388261519690468959176143926015356555581092834e-03, // 1.300000
+ 2.09560576678758086338616450916561007034033536911011e-03, // 1.400000
+ 1.38175379315578074172765621341341102379374206066132e-03, // 1.500000
+ 8.71107579482878762074105072343854772043414413928986e-04, // 1.600000
+ 5.22617853061128857447559248328161629615351557731628e-04, // 1.700000
+ 2.96827286233691963433789506865423390991054475307465e-04, // 1.800000
+ 1.58682200637844659282110759690453960502054542303085e-04, // 1.900000
+ 7.93399517782126200262163284726568690530257299542427e-05, // 2.000000
+ 3.61659882683322792679984014011657089682216792425606e-08, // 2.718282
+ 1.28298578206074919984378622477440951791388679126271e-11, // 3.141593
+ };
+
+ public static final double[] P_QUANT = { //
+ 0.0001, 0.001, 0.01, 0.1, 0.25, 0.5, 0.75, 0.9, 0.99, 0.999, 0.9999 //
+ };
+
+ public static final double[] SCIPY_LOGGAMMA_QUANT_1_1 = { //
+ -9.21029036989272320568034047028049826622009277343750e+00, // 0.000100
+ -6.90725507052371678895497097983025014400482177734375e+00, // 0.001000
+ -4.60014922677657978056231513619422912597656250000000e+00, // 0.010000
+ -2.25036732731244493166400388872716575860977172851562e+00, // 0.100000
+ -1.24589932370723799337497439410071820020675659179688e+00, // 0.250000
+ -3.66512920581664347619010868584155105054378509521484e-01, // 0.500000
+ 3.26634259978281105141206808184506371617317199707031e-01, // 0.750000
+ 8.34032445247955944722662025014869868755340576171875e-01, // 0.900000
+ 1.52717962580790089788251862046308815479278564453125e+00, // 0.990000
+ 1.93264473391606528274166976189007982611656188964844e+00, // 0.999000
+ 2.22032680636785828554025101766455918550491333007812e+00, // 0.999900
+ };
+
+ public static final double[] SCIPY_LOGGAMMA_QUANT_2_1 = { //
+ -4.25386298913733185145247261971235275268554687500000e+00, // 0.000100
+ -3.09219873066056738508677881327457726001739501953125e+00, // 0.001000
+ -1.90680176742938400913374152878532186150550842285156e+00, // 0.010000
+ -6.31465971924031865825099885114468634128570556640625e-01, // 0.100000
+ -3.94908359938028266644671759877383010461926460266113e-02, // 0.250000
+ 5.17809374519952236859410277247661724686622619628906e-01, // 0.500000
+ 9.90520093104668930550360528286546468734741210937500e-01, // 0.750000
+ 1.35833721927612582902611393365077674388885498046875e+00, // 0.900000
+ 1.89286375015490904161197249777615070343017578125000e+00, // 0.990000
+ 2.22282880424761364324126589053776115179061889648438e+00, // 0.999000
+ 2.46439532533742688968914080760441720485687255859375e+00, // 0.999900
+ };
+
+ public static final double[] SCIPY_LOGGAMMA_QUANT_4_1 = { //
+ -1.46189374258889248636705815442837774753570556640625e+00, // 0.000100
+ -8.47342229571847793678784910298418253660202026367188e-01, // 0.001000
+ -1.94496953420364770970252266124589368700981140136719e-01, // 0.010000
+ 5.56622491246540618270444156223675236105918884277344e-01, // 0.100000
+ 9.30319945397308112333689678052905946969985961914062e-01, // 0.250000
+ 1.30075301642610718921844181750202551484107971191406e+00, // 0.500000
+ 1.63108735980254726527505226840730756521224975585938e+00, // 0.750000
+ 1.89923520646495491703831248742062598466873168945312e+00, // 0.900000
+ 2.30708669703685576024554393370635807514190673828125e+00, // 0.990000
+ 2.56972568487266350700792827410623431205749511718750e+00, // 0.999000
+ 2.76718753710466591755334775371011346578598022460938e+00, // 0.999900
+ };
+
+ public static final double[] SCIPY_LOGGAMMA_QUANT_4_10 = { //
+ -1.46189374258889254187820938568620476871728897094727e-01, // 0.000100
+ -8.47342229571847876945511757185158785432577133178711e-02, // 0.001000
+ -1.94496953420364784848040073939046123996376991271973e-02, // 0.010000
+ 5.56622491246540618270444156223675236105918884277344e-02, // 0.100000
+ 9.30319945397308223355992140568559989333152770996094e-02, // 0.250000
+ 1.30075301642610718921844181750202551484107971191406e-01, // 0.500000
+ 1.63108735980254743180850596218078862875699996948242e-01, // 0.750000
+ 1.89923520646495508357176618119410704821348190307617e-01, // 0.900000
+ 2.30708669703685587126784639622201211750507354736328e-01, // 0.990000
+ 2.56972568487266350700792827410623431205749511718750e-01, // 0.999000
+ 2.76718753710466613959795267874142155051231384277344e-01, // 0.999900
+ };
+
+ public static final double[] SCIPY_LOGGAMMA_QUANT_01_10 = { //
+ Double.NaN, // 0.000100
+ Double.NaN, // 0.001000
+ Double.NaN, // 0.010000
+ -2.35245753424830494893171817238908261060714721679688e+00, // 0.100000
+ -1.43616674972779789776211600837996229529380798339844e+00, // 0.250000
+ -7.42965684101831946861693722894415259361267089843750e-01, // 0.500000
+ -3.34369221586346410113321780954720452427864074707031e-01, // 0.750000
+ -1.32367810983911204925078664018656127154827117919922e-01, // 0.900000
+ 4.62776210468462748104379045344103360548615455627441e-02, // 0.990000
+ 1.21303472433787085105194591960753314197063446044922e-01, // 0.999000
+ 1.67076694072213816077976389351533725857734680175781e-01, // 0.999900
+ };
+
+ public static final double[] SCIPY_LOGGAMMA_QUANT_01_20 = { //
+ Double.NaN, // 0.000100
+ Double.NaN, // 0.001000
+ Double.NaN, // 0.010000
+ -1.17622876712415247446585908619454130530357360839844e+00, // 0.100000
+ -7.18083374863898948881058004189981147646903991699219e-01, // 0.250000
+ -3.71482842050915973430846861447207629680633544921875e-01, // 0.500000
+ -1.67184610793173205056660890477360226213932037353516e-01, // 0.750000
+ -6.61839054919556024625393320093280635774135589599609e-02, // 0.900000
+ 2.31388105234231374052189522672051680274307727813721e-02, // 0.990000
+ 6.06517362168935425525972959803766570985317230224609e-02, // 0.999000
+ 8.35383470361069080389881946757668629288673400878906e-02, // 0.999900
+ };
+
+ public static final double[] SCIPY_LOGGAMMA_QUANT_01_4 = { //
+ Double.NaN, // 0.000100
+ Double.NaN, // 0.001000
+ Double.NaN, // 0.010000
+ -5.88114383562076259437390035600401461124420166015625e+00, // 0.100000
+ -3.59041687431949441133838263340294361114501953125000e+00, // 0.250000
+ -1.85741421025457964510962938220473006367683410644531e+00, // 0.500000
+ -8.35923053965865969772153221128974109888076782226562e-01, // 0.750000
+ -3.30919527459777984557121044417726807296276092529297e-01, // 0.900000
+ 1.15694052617115683556647809382411651313304901123047e-01, // 0.990000
+ 3.03258681084467685007410864272969774901866912841797e-01, // 0.999000
+ 4.17691735180534484683789742121007293462753295898438e-01, // 0.999900
+ };
+
+ public static final double[] SCIPY_LOGGAMMA_QUANT_01_1 = { //
+ Double.NaN, // 0.000100
+ Double.NaN, // 0.001000
+ Double.NaN, // 0.010000
+ -2.35245753424830503774956014240160584449768066406250e+01, // 0.100000
+ -1.43616674972779776453535305336117744445800781250000e+01, // 0.250000
+ -7.42965684101831858043851752881892025470733642578125e+00, // 0.500000
+ -3.34369221586346387908861288451589643955230712890625e+00, // 0.750000
+ -1.32367810983911193822848417767090722918510437011719e+00, // 0.900000
+ 4.62776210468462734226591237529646605253219604492188e-01, // 0.990000
+ 1.21303472433787074002964345709187909960746765136719e+00, // 0.999000
+ 1.67076694072213793873515896848402917385101318359375e+00, // 0.999900
+ };
+
+ @Test
+ public void testPDF() {
+ checkPDF(new LogGammaAlternateDistribution(1., 1., 0.), P_CDFPDF, SCIPY_LOGGAMMA_PDF_1_1, 1e-10);
+ checkPDF(new LogGammaAlternateDistribution(2., 1., 0.), P_CDFPDF, SCIPY_LOGGAMMA_PDF_2_1, 1e-12);
+ checkPDF(new LogGammaAlternateDistribution(4., 1., 0.), P_CDFPDF, SCIPY_LOGGAMMA_PDF_4_1, 1e-12);
+ checkPDF(new LogGammaAlternateDistribution(4., 10, 0.), P_CDFPDF, SCIPY_LOGGAMMA_PDF_4_10, 1e-10);
+ checkPDF(new LogGammaAlternateDistribution(.1, 10, 0.), P_CDFPDF, SCIPY_LOGGAMMA_PDF_01_10, 1e-11);
+ checkPDF(new LogGammaAlternateDistribution(.1, 20, 0.), P_CDFPDF, SCIPY_LOGGAMMA_PDF_01_20, 1e-14);
+ checkPDF(new LogGammaAlternateDistribution(.1, 4., 0.), P_CDFPDF, SCIPY_LOGGAMMA_PDF_01_4, 1e-12);
+ checkPDF(new LogGammaAlternateDistribution(.1, 1., 0.), P_CDFPDF, SCIPY_LOGGAMMA_PDF_01_1, 1e-12);
+ }
+
+ @Test
+ public void testCDF() {
+ checkCDF(new LogGammaAlternateDistribution(1., 1., 0.), P_CDFPDF, SCIPY_LOGGAMMA_CDF_1_1, 1e-13);
+ checkCDF(new LogGammaAlternateDistribution(2., 1., 0.), P_CDFPDF, SCIPY_LOGGAMMA_CDF_2_1, 1e-12);
+ checkCDF(new LogGammaAlternateDistribution(4., 1., 0.), P_CDFPDF, SCIPY_LOGGAMMA_CDF_4_1, 1e-12);
+ checkCDF(new LogGammaAlternateDistribution(4., 10, 0.), P_CDFPDF, SCIPY_LOGGAMMA_CDF_4_10, 1e-14);
+ checkCDF(new LogGammaAlternateDistribution(.1, 10, 0.), P_CDFPDF, SCIPY_LOGGAMMA_CDF_01_10, 1e-15);
+ checkCDF(new LogGammaAlternateDistribution(.1, 20, 0.), P_CDFPDF, SCIPY_LOGGAMMA_CDF_01_20, 1e-15);
+ checkCDF(new LogGammaAlternateDistribution(.1, 4., 0.), P_CDFPDF, SCIPY_LOGGAMMA_CDF_01_4, 1e-14);
+ checkCDF(new LogGammaAlternateDistribution(.1, 1., 0.), P_CDFPDF, SCIPY_LOGGAMMA_CDF_01_1, 1e-14);
+ }
+
+ @Test
+ public void testProbit() {
+ checkQuantile(new LogGammaAlternateDistribution(1., 1., 0.), P_QUANT, SCIPY_LOGGAMMA_QUANT_1_1, 1e-14);
+ checkQuantile(new LogGammaAlternateDistribution(2., 1., 0.), P_QUANT, SCIPY_LOGGAMMA_QUANT_2_1, 1e-13);
+ checkQuantile(new LogGammaAlternateDistribution(4., 1., 0.), P_QUANT, SCIPY_LOGGAMMA_QUANT_4_1, 1e-13);
+ checkQuantile(new LogGammaAlternateDistribution(4., 10, 0.), P_QUANT, SCIPY_LOGGAMMA_QUANT_4_10, 1e-13);
+ checkQuantile(new LogGammaAlternateDistribution(.1, 10, 0.), P_QUANT, SCIPY_LOGGAMMA_QUANT_01_10, 1e-13);
+ checkQuantile(new LogGammaAlternateDistribution(.1, 20, 0.), P_QUANT, SCIPY_LOGGAMMA_QUANT_01_20, 1e-14);
+ checkQuantile(new LogGammaAlternateDistribution(.1, 4., 0.), P_QUANT, SCIPY_LOGGAMMA_QUANT_01_4, 1e-13);
+ checkQuantile(new LogGammaAlternateDistribution(.1, 1., 0.), P_QUANT, SCIPY_LOGGAMMA_QUANT_01_1, 1e-13);
+ }
+}
diff --git a/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestLogNormalDistribution.java b/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestLogNormalDistribution.java
new file mode 100644
index 00000000..61ad82b0
--- /dev/null
+++ b/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestLogNormalDistribution.java
@@ -0,0 +1,518 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2012
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import org.junit.Test;
+
+import de.lmu.ifi.dbs.elki.JUnit4Test;
+
+/**
+ * Unit test for the Normal distribution in ELKI.
+ *
+ * The reference values were computed using GNU R and SciPy.
+ *
+ * @author Erich Schubert
+ */
+public class TestLogNormalDistribution extends AbstractDistributionTest implements JUnit4Test {
+ public static final double[] P_CDFPDF = { //
+ 1e-10, 1e-05, 0.1, 0.1234567, 0.2, 0.271828182846, 0.3, 0.314159265359, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.71828182846, 3.14159265359 //
+ };
+
+ public static final double[] SCIPY_LOGNORM_CDF_0_1 = { //
+ 1.28417563064343188586946855334205034593745303926717e-117, // 0.000000
+ 5.67797929684089614274940495423182419605501044534498e-31, // 0.000010
+ 1.06510993417001289390588780747748387511819601058960e-02, // 0.100000
+ 1.82253062118146111347805060631799278780817985534668e-02, // 0.123457
+ 5.37603104516631360998424327135580824688076972961426e-02, // 0.200000
+ 9.63582248817356212811091609182767570018768310546875e-02, // 0.271828
+ 1.14300045049151532960962640572688542306423187255859e-01, // 0.300000
+ 1.23461564770417142611336203117389231920242309570312e-01, // 0.314159
+ 1.79757213895785417090422697583562694489955902099609e-01, // 0.400000
+ 2.44108595785582749293496362952282652258872985839844e-01, // 0.500000
+ 3.04736582510231668319278242051950655877590179443359e-01, // 0.600000
+ 3.60667582622649085521970846457406878471374511718750e-01, // 0.700000
+ 4.11711891857454936882731999503448605537414550781250e-01, // 0.800000
+ 4.58044872785658863101332372025353834033012390136719e-01, // 0.900000
+ 5.00000000000000000000000000000000000000000000000000e-01, // 1.000000
+ 5.37965771424616989726530391635606065392494201660156e-01, // 1.100000
+ 5.72334808836768349493695495766587555408477783203125e-01, // 1.200000
+ 6.03479689632151705680485065386164933443069458007812e-01, // 1.300000
+ 6.31742607836675351684618817671434953808784484863281e-01, // 1.400000
+ 6.57432169485154149768391107500065118074417114257812e-01, // 1.500000
+ 6.80823787674826652605020171904470771551132202148438e-01, // 1.600000
+ 7.02161792699145248519698725431226193904876708984375e-01, // 1.700000
+ 7.21662252065084608432243840070441365242004394531250e-01, // 1.800000
+ 7.39515971034705121844865516322897747159004211425781e-01, // 1.900000
+ 7.55891404214417250706503637047717347741127014160156e-01, // 2.000000
+ 8.41344746068542925776512220181757584214210510253906e-01, // 2.718282
+ 8.73839466286804089634188130730763077735900878906250e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_LOGNORM_PDF_0_1 = { //
+ 2.96247992534875871443606538046919616608519359260632e-106, // 0.000000
+ 6.58561599261676419576702545979628229597991165133025e-25, // 0.000010
+ 2.81590189015268332894947889144532382488250732421875e-01, // 0.100000
+ 3.62394132775150645819906003453070297837257385253906e-01, // 0.123457
+ 5.46267870758180063006648197188042104244232177734375e-01, // 0.200000
+ 6.28312639712034104455540273193037137389183044433594e-01, // 0.271828
+ 6.44203257359199588094611499400343745946884155273438e-01, // 0.300000
+ 6.49600535087859753957673092372715473175048828125000e-01, // 0.314159
+ 6.55444168060311471712964248581556603312492370605469e-01, // 0.400000
+ 6.27496077115924366651711352460552006959915161132812e-01, // 0.500000
+ 5.83573822594503965888179664034396409988403320312500e-01, // 0.600000
+ 5.34794832076919912644541454938007518649101257324219e-01, // 0.700000
+ 4.86415781111553480187126297096256166696548461914062e-01, // 0.800000
+ 4.40815685912026689052822803205344825983047485351562e-01, // 0.900000
+ 3.98942280401432702863218082711682654917240142822266e-01, // 1.000000
+ 3.61031261229040001392576186844962649047374725341797e-01, // 1.100000
+ 3.26972024074255740444527873478364199399948120117188e-01, // 1.200000
+ 2.96496370636105011087124694313388317823410034179688e-01, // 1.300000
+ 2.69276228949932749934248477075016126036643981933594e-01, // 1.400000
+ 2.44973651710509943146831801641383208334445953369141e-01, // 1.500000
+ 2.23265447430299024400568441706127487123012542724609e-01, // 1.600000
+ 2.03854259497871476147778935228416230529546737670898e-01, // 1.700000
+ 1.86472448538908153192750205562333576381206512451172e-01, // 1.800000
+ 1.70882238241215372864800770003057550638914108276367e-01, // 1.900000
+ 1.56874019278981091662927838115138001739978790283203e-01, // 2.000000
+ 8.90160549159514924433267424319637939333915710449219e-02, // 2.718282
+ 6.59491245186608343598066994672990404069423675537109e-02, // 3.141593
+ };
+
+ public static final double[] GNUR_LOGNORM_CDF_0_1 = { //
+ 1.28417563064351817736427131462082407099073717791586e-117, // 0.000000
+ 5.67797929684099160620728708239478087513287207088142e-31, // 0.000010
+ 1.06510993417001341432293060051961219869554042816162e-02, // 0.100000
+ 1.82253062118146215431213619240224943496286869049072e-02, // 0.123457
+ 5.37603104516631430387363366207864601165056228637695e-02, // 0.200000
+ 9.63582248817956288355901506292866542935371398925781e-02, // 0.271828
+ 1.14300045049151519083174832758231787011027336120605e-01, // 0.300000
+ 1.23461564770430590187721975325985113158822059631348e-01, // 0.314159
+ 1.79757213895785389334847081954649183899164199829102e-01, // 0.400000
+ 2.44108595785582721537920747323369141668081283569336e-01, // 0.500000
+ 3.04736582510231668319278242051950655877590179443359e-01, // 0.600000
+ 3.60667582622649085521970846457406878471374511718750e-01, // 0.700000
+ 4.11711891857454936882731999503448605537414550781250e-01, // 0.800000
+ 4.58044872785658863101332372025353834033012390136719e-01, // 0.900000
+ 5.00000000000000000000000000000000000000000000000000e-01, // 1.000000
+ 5.37965771424616989726530391635606065392494201660156e-01, // 1.100000
+ 5.72334808836768349493695495766587555408477783203125e-01, // 1.200000
+ 6.03479689632151705680485065386164933443069458007812e-01, // 1.300000
+ 6.31742607836675351684618817671434953808784484863281e-01, // 1.400000
+ 6.57432169485154149768391107500065118074417114257812e-01, // 1.500000
+ 6.80823787674826763627322634420124813914299011230469e-01, // 1.600000
+ 7.02161792699145248519698725431226193904876708984375e-01, // 1.700000
+ 7.21662252065084608432243840070441365242004394531250e-01, // 1.800000
+ 7.39515971034705121844865516322897747159004211425781e-01, // 1.900000
+ 7.55891404214417250706503637047717347741127014160156e-01, // 2.000000
+ 8.41344746068627968860198507172754034399986267089844e-01, // 2.718282
+ 8.73839466286817856399693482671864330768585205078125e-01, // 3.141593
+ };
+
+ public static final double[] GNUR_LOGNORM_PDF_0_1 = { //
+ 2.96247992534875823036207602430441206383136443181234e-106, // 0.000000
+ 6.58561599261676327741206387988416669540449194645082e-25, // 0.000010
+ 2.81590189015268332894947889144532382488250732421875e-01, // 0.100000
+ 3.62394132775150590308754772195243276655673980712891e-01, // 0.123457
+ 5.46267870758180063006648197188042104244232177734375e-01, // 0.200000
+ 6.28312639712100828859320245101116597652435302734375e-01, // 0.271828
+ 6.44203257359199588094611499400343745946884155273438e-01, // 0.300000
+ 6.49600535087866637340425768343266099691390991210938e-01, // 0.314159
+ 6.55444168060311471712964248581556603312492370605469e-01, // 0.400000
+ 6.27496077115924366651711352460552006959915161132812e-01, // 0.500000
+ 5.83573822594503965888179664034396409988403320312500e-01, // 0.600000
+ 5.34794832076919912644541454938007518649101257324219e-01, // 0.700000
+ 4.86415781111553424675975065838429145514965057373047e-01, // 0.800000
+ 4.40815685912026689052822803205344825983047485351562e-01, // 0.900000
+ 3.98942280401432702863218082711682654917240142822266e-01, // 1.000000
+ 3.61031261229040001392576186844962649047374725341797e-01, // 1.100000
+ 3.26972024074255740444527873478364199399948120117188e-01, // 1.200000
+ 2.96496370636105011087124694313388317823410034179688e-01, // 1.300000
+ 2.69276228949932694423097245817189104855060577392578e-01, // 1.400000
+ 2.44973651710509915391256186012469697743654251098633e-01, // 1.500000
+ 2.23265447430298996644992826077213976532220840454102e-01, // 1.600000
+ 2.03854259497871476147778935228416230529546737670898e-01, // 1.700000
+ 1.86472448538908125437174589933420065790414810180664e-01, // 1.800000
+ 1.70882238241215372864800770003057550638914108276367e-01, // 1.900000
+ 1.56874019278981091662927838115138001739978790283203e-01, // 2.000000
+ 8.90160549158889452536769226753676775842905044555664e-02, // 2.718282
+ 6.59491245186515084863998481523594819009304046630859e-02, // 3.141593
+ };
+
+ public static final double[] SCIPY_LOGNORM_CDF_1_3 = { //
+ 5.80027942989772828348821244410095933142208312997823e-16, // 0.000000
+ 1.51649466283750378246646117741391890376689843833447e-05, // 0.000010
+ 1.35478427197421924521592018209048546850681304931641e-01, // 0.100000
+ 1.51359152068233360211024773889221251010894775390625e-01, // 0.123457
+ 1.92201402041897895234257021002122201025485992431641e-01, // 0.200000
+ 2.21383717792045020544833278108853846788406372070312e-01, // 0.271828
+ 2.31274023997502686800231685992912389338016510009766e-01, // 0.300000
+ 2.35982646811182916746219007109175436198711395263672e-01, // 0.314159
+ 2.61488373016912578616910423079389147460460662841797e-01, // 0.400000
+ 2.86246959246035603818825165944872424006462097167969e-01, // 0.500000
+ 3.07268244645081289867505347501719370484352111816406e-01, // 0.600000
+ 3.25553456641869298771041485451860353350639343261719e-01, // 0.700000
+ 3.41741639131648788918482750887051224708557128906250e-01, // 0.800000
+ 3.56267553868274411410510538189555518329143524169922e-01, // 0.900000
+ 3.69441340181763666628000919445184990763664245605469e-01, // 1.000000
+ 3.81492504412193622620463884231867268681526184082031e-01, // 1.100000
+ 3.92595931185516167083449090569047257304191589355469e-01, // 1.200000
+ 4.02888113368478295583940962387714534997940063476562e-01, // 1.300000
+ 4.12477728576550517480825419625034555792808532714844e-01, // 1.400000
+ 4.21452783486494730880167480790987610816955566406250e-01, // 1.500000
+ 4.29885587708867089595798915979685261845588684082031e-01, // 1.600000
+ 4.37836307018417136838195347081637009978294372558594e-01, // 1.700000
+ 4.45355558873167967082196128103532828390598297119141e-01, // 1.800000
+ 4.52486345581900428758359566927538253366947174072266e-01, // 1.900000
+ 4.59265519021804791144347746012499555945396423339844e-01, // 2.000000
+ 5.00000000000000000000000000000000000000000000000000e-01, // 2.718282
+ 5.19238827154144821918180241482332348823547363281250e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_LOGNORM_PDF_1_3 = { //
+ 1.57184900048158173423151762193583635962568223476410e-05, // 0.000000
+ 2.21855874552272958055709750624373555183410644531250e+00, // 0.000010
+ 7.25485663598960939246751422615488991141319274902344e-01, // 0.100000
+ 6.33321891615805876440958854800555855035781860351562e-01, // 0.123457
+ 4.55481616703077685226475068702711723744869232177734e-01, // 0.200000
+ 3.64395441271923081760775176007882691919803619384766e-01, // 0.271828
+ 3.38429691850187064350308219218277372419834136962891e-01, // 0.300000
+ 3.26808430238364144848617343086516484618186950683594e-01, // 0.314159
+ 2.71099452010358343834184324805391952395439147949219e-01, // 0.400000
+ 2.26804382443861807239215977460844442248344421386719e-01, // 0.500000
+ 1.95237994591654751008746870866161771118640899658203e-01, // 0.600000
+ 1.71507274769319928431343669217312708497047424316406e-01, // 0.700000
+ 1.52968565294889946581946560399956069886684417724609e-01, // 0.800000
+ 1.38059669586597599799659974451060406863689422607422e-01, // 0.900000
+ 1.25794409230997716875322112173307687044143676757812e-01, // 1.000000
+ 1.15517735625617068428994116402463987469673156738281e-01, // 1.100000
+ 1.06776574753620304147894159996212692931294441223145e-01, // 1.200000
+ 9.92470359816487873727552937452855985611677169799805e-02, // 1.300000
+ 9.26911340280602569219325914673390798270702362060547e-02, // 1.400000
+ 8.69298985658228523520918429312587250024080276489258e-02, // 1.500000
+ 8.18260363727473238881771067099180072546005249023438e-02, // 1.600000
+ 7.72723945276378165747388493400649167597293853759766e-02, // 1.700000
+ 7.31840719845132658960551452764775604009628295898438e-02, // 1.800000
+ 6.94928962728491861344792823729221709072589874267578e-02, // 1.900000
+ 6.61434746059730849232494165335083380341529846191406e-02, // 2.000000
+ 4.89208877245799755861810353962937369942665100097656e-02, // 2.718282
+ 4.22798605814237726807647277382784523069858551025391e-02, // 3.141593
+ };
+
+ public static final double[] GNUR_LOGNORM_CDF_1_3 = { //
+ 5.80027942989774504678244839060182433065409538918561e-16, // 0.000000
+ 1.51649466283750666237848184203507173606340074911714e-05, // 0.000010
+ 1.35478427197421869010440786951221525669097900390625e-01, // 0.100000
+ 1.51359152068233387966600389518134761601686477661133e-01, // 0.123457
+ 1.92201402041897867478681405373208690434694290161133e-01, // 0.200000
+ 2.21383717792079853792230892395309638231992721557617e-01, // 0.271828
+ 2.31274023997502603533504839106171857565641403198242e-01, // 0.300000
+ 2.35982646811189716862244836192985530942678451538086e-01, // 0.314159
+ 2.61488373016912634128061654337216168642044067382812e-01, // 0.400000
+ 2.86246959246035659329976397202699445188045501708984e-01, // 0.500000
+ 3.07268244645081289867505347501719370484352111816406e-01, // 0.600000
+ 3.25553456641869243259890254194033332169055938720703e-01, // 0.700000
+ 3.41741639131648788918482750887051224708557128906250e-01, // 0.800000
+ 3.56267553868274355899359306931728497147560119628906e-01, // 0.900000
+ 3.69441340181763666628000919445184990763664245605469e-01, // 1.000000
+ 3.81492504412193622620463884231867268681526184082031e-01, // 1.100000
+ 3.92595931185516167083449090569047257304191589355469e-01, // 1.200000
+ 4.02888113368478295583940962387714534997940063476562e-01, // 1.300000
+ 4.12477728576550517480825419625034555792808532714844e-01, // 1.400000
+ 4.21452783486494730880167480790987610816955566406250e-01, // 1.500000
+ 4.29885587708867089595798915979685261845588684082031e-01, // 1.600000
+ 4.37836307018417136838195347081637009978294372558594e-01, // 1.700000
+ 4.45355558873167967082196128103532828390598297119141e-01, // 1.800000
+ 4.52486345581900428758359566927538253366947174072266e-01, // 1.900000
+ 4.59265519021804791144347746012499555945396423339844e-01, // 2.000000
+ 5.00000000000046740389336719090351834893226623535156e-01, // 2.718282
+ 5.19238827154153592680074780219001695513725280761719e-01, // 3.141593
+ };
+
+ public static final double[] GNUR_LOGNORM_PDF_1_3 = { //
+ 1.57184900048159257625324247698017643415369093418121e-05, // 0.000000
+ 2.21855874552272913646788765618111938238143920898438e+00, // 0.000010
+ 7.25485663598960717202146497584180906414985656738281e-01, // 0.100000
+ 6.33321891615805654396353929769247770309448242187500e-01, // 0.123457
+ 4.55481616703077685226475068702711723744869232177734e-01, // 0.200000
+ 3.64395441271827880136413568834541365504264831542969e-01, // 0.271828
+ 3.38429691850187008839156987960450351238250732421875e-01, // 0.300000
+ 3.26808430238347880081306584543199278414249420166016e-01, // 0.314159
+ 2.71099452010358343834184324805391952395439147949219e-01, // 0.400000
+ 2.26804382443861779483640361831930931657552719116211e-01, // 0.500000
+ 1.95237994591654723253171255237248260527849197387695e-01, // 0.600000
+ 1.71507274769319928431343669217312708497047424316406e-01, // 0.700000
+ 1.52968565294889946581946560399956069886684417724609e-01, // 0.800000
+ 1.38059669586597572044084358822146896272897720336914e-01, // 0.900000
+ 1.25794409230997716875322112173307687044143676757812e-01, // 1.000000
+ 1.15517735625617040673418500773550476878881454467773e-01, // 1.100000
+ 1.06776574753620290270106352181755937635898590087891e-01, // 1.200000
+ 9.92470359816487596171796781163720879703760147094727e-02, // 1.300000
+ 9.26911340280602569219325914673390798270702362060547e-02, // 1.400000
+ 8.69298985658228384743040351168019697070121765136719e-02, // 1.500000
+ 8.18260363727473238881771067099180072546005249023438e-02, // 1.600000
+ 7.72723945276378165747388493400649167597293853759766e-02, // 1.700000
+ 7.31840719845132658960551452764775604009628295898438e-02, // 1.800000
+ 6.94928962728491861344792823729221709072589874267578e-02, // 1.900000
+ 6.61434746059730849232494165335083380341529846191406e-02, // 2.000000
+ 4.89208877245627948848749610988306812942028045654297e-02, // 2.718282
+ 4.22798605814209346731580296818719943985342979431152e-02, // 3.141593
+ };
+
+ public static final double[] SCIPY_LOGNORM_CDF_01_01 = { //
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.000000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.000010
+ 7.46586729512055156851629424736742001201359883385653e-128, // 0.100000
+ 8.62525588462026443966250245228507150042446838603379e-107, // 0.123457
+ 8.17136334615500295339422451815302932260019361648268e-66, // 0.200000
+ 5.41526143458555017502898041505360963321909770679929e-45, // 0.271828
+ 3.63579783587386242094605540612077634804949224374312e-39, // 0.300000
+ 1.38530749241422417511125868885806575792955358046047e-36, // 0.314159
+ 1.45144331736744006446530515598948213843059576725939e-24, // 0.400000
+ 1.08281884688449672381822010295852147196911971320510e-15, // 0.500000
+ 5.03627752858171494558555774501791210684409350051283e-10, // 0.600000
+ 2.47672755812896728362052650718183599565236363559961e-06, // 0.700000
+ 6.15850565794841134717452213465094246203079819679260e-04, // 0.800000
+ 2.00069613308373993321165329462019144557416439056396e-02, // 0.900000
+ 1.58655253931456963201185317302588373422622680664062e-01, // 1.000000
+ 4.81297180574880578696195243537658825516700744628906e-01, // 1.100000
+ 7.94807291306340868430879709194414317607879638671875e-01, // 1.200000
+ 9.47773950742736737140603509033098816871643066406250e-01, // 1.300000
+ 9.90978204147032748494439147179946303367614746093750e-01, // 1.400000
+ 9.98873387527683287423485580802662298083305358886719e-01, // 1.500000
+ 9.99892215681807416949311573262093588709831237792969e-01, // 1.600000
+ 9.99991698949889484815400919615058228373527526855469e-01, // 1.700000
+ 9.99999463803087018654025541763985529541969299316406e-01, // 1.800000
+ 9.99999969955960299472508268081583082675933837890625e-01, // 1.900000
+ 9.99999998498844355765413638437166810035705566406250e-01, // 2.000000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 2.718282
+ 1.00000000000000000000000000000000000000000000000000e+00, // 3.141593
+ };
+
+ public static final double[] SCIPY_LOGNORM_PDF_01_01 = { //
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.000000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.000010
+ 1.79683490350738681626883878695903692927320056006734e-124, // 0.100000
+ 1.53451240609964396752170892833443226944498342251986e-103, // 0.123457
+ 7.00795903038145442928847865311558208490483375898988e-63, // 0.200000
+ 2.80824126786686071155513246881328889371784643139373e-42, // 0.271828
+ 1.58951508355228437334280261322875927189162769346195e-36, // 0.300000
+ 5.58122798783872171035008357202465427911692811792789e-34, // 0.314159
+ 3.72276530194518232247109146801702251947511489941735e-22, // 0.400000
+ 1.74416764530574268824702660517399569335391176783112e-13, // 0.500000
+ 5.25802665152593504051015431063897942465246160281822e-08, // 0.600000
+ 1.68718532893121360123969698641133163619088008999825e-04, // 0.700000
+ 2.69358375879647123085636195582992513664066791534424e-02, // 0.800000
+ 5.38138135622016955394997239636722952127456665039062e-01, // 0.900000
+ 2.41970724519143187691838647879194468259811401367188e+00, // 1.000000
+ 3.62276178615723765119582822080701589584350585937500e+00, // 1.100000
+ 2.36903587207174082251981417357455939054489135742188e+00, // 1.200000
+ 8.21334006428800944554780016915174201130867004394531e-01, // 1.300000
+ 1.73985796664595016025600671127904206514358520507812e-01, // 1.400000
+ 2.50403898972403581024703811408471665345132350921631e-02, // 1.500000
+ 2.65452021073224507866084032059461605967953801155090e-03, // 1.600000
+ 2.20631598630764908571672000547891911992337554693222e-04, // 1.700000
+ 1.50982513130951377124371742821651309895969461649656e-05, // 1.800000
+ 8.84282704123672517376785005144279594446743431035429e-07, // 1.900000
+ 4.57223083211032647909217801161785299512985147885047e-08, // 2.000000
+ 3.78171735691457591044937145833685229912833032037698e-18, // 2.718282
+ 2.52927370006418196229588945092783163653520317423423e-24, // 3.141593
+ };
+
+ public static final double[] GNUR_LOGNORM_CDF_01_01 = { //
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.000000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.000010
+ 7.46586729512139622334915485545022576086084233165236e-128, // 0.100000
+ 8.62525588462074367291196505542133273171533757207493e-107, // 0.123457
+ 8.17136334615526229146362798902434829752185485895027e-66, // 0.200000
+ 5.41526143485395691388299267636695240314190437945746e-45, // 0.271828
+ 3.63579783587375997366590782928570699643197691594649e-39, // 0.300000
+ 1.38530749242582464214423634101122722133110779968500e-36, // 0.314159
+ 1.45144331736743767674240504821798157693450453457286e-24, // 0.400000
+ 1.08281884688450796508611950237674858910117499290887e-15, // 0.500000
+ 5.03627752858173148919780880557140953501793489976990e-10, // 0.600000
+ 2.47672755812898803592773423754014316955363028682768e-06, // 0.700000
+ 6.15850565794842218919624698969528253655880689620972e-04, // 0.800000
+ 2.00069613308374652516086200648715021088719367980957e-02, // 0.900000
+ 1.58655253931457046467912164189328905194997787475586e-01, // 1.000000
+ 4.81297180574880967274253862342447973787784576416016e-01, // 1.100000
+ 7.94807291306340868430879709194414317607879638671875e-01, // 1.200000
+ 9.47773950742736737140603509033098816871643066406250e-01, // 1.300000
+ 9.90978204147032748494439147179946303367614746093750e-01, // 1.400000
+ 9.98873387527683287423485580802662298083305358886719e-01, // 1.500000
+ 9.99892215681807416949311573262093588709831237792969e-01, // 1.600000
+ 9.99991698949889484815400919615058228373527526855469e-01, // 1.700000
+ 9.99999463803087018654025541763985529541969299316406e-01, // 1.800000
+ 9.99999969955960299472508268081583082675933837890625e-01, // 1.900000
+ 9.99999998498844355765413638437166810035705566406250e-01, // 2.000000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 2.718282
+ 1.00000000000000000000000000000000000000000000000000e+00, // 3.141593
+ };
+
+ public static final double[] GNUR_LOGNORM_PDF_01_01 = { //
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.000000
+ 0.00000000000000000000000000000000000000000000000000e+00, // 0.000010
+ 1.79683490350738660633521042548751343580552590537274e-124, // 0.100000
+ 1.53451240609960034664638006561340724714793008505265e-103, // 0.123457
+ 7.00795903038125471789064209408362002551800649974979e-63, // 0.200000
+ 2.80824126800431268164764045127534069443724460598013e-42, // 0.271828
+ 1.58951508355223927043831980742723065033874451220525e-36, // 0.300000
+ 5.58122798788467359181540305857831591200353537133688e-34, // 0.314159
+ 3.72276530194518138207561081018701614448588512162081e-22, // 0.400000
+ 1.74416764530575505758602047063910454925781540191920e-13, // 0.500000
+ 5.25802665152591651166443312281906230509775923565030e-08, // 0.600000
+ 1.68718532893122579851413744833621422003488987684250e-04, // 0.700000
+ 2.69358375879647331252453312799843843095004558563232e-02, // 0.800000
+ 5.38138135622017954595719402277609333395957946777344e-01, // 0.900000
+ 2.41970724519143365327522587904240936040878295898438e+00, // 1.000000
+ 3.62276178615723720710661837074439972639083862304688e+00, // 1.100000
+ 2.36903587207174037843060432351194322109222412109375e+00, // 1.200000
+ 8.21334006428800944554780016915174201130867004394531e-01, // 1.300000
+ 1.73985796664594405402937127291806973516941070556641e-01, // 1.400000
+ 2.50403898972401985079105912745944806374609470367432e-02, // 1.500000
+ 2.65452021073223987449041239017333282390609383583069e-03, // 1.600000
+ 2.20631598630763743054336578630625353980576619505882e-04, // 1.700000
+ 1.50982513130949767761771959651007080083218170329928e-05, // 1.800000
+ 8.84282704123670929190008903331143841342054656706750e-07, // 1.900000
+ 4.57223083211027817174440491480164050486223459301982e-08, // 2.000000
+ 3.78171735679367296188854058553106900541344188905750e-18, // 2.718282
+ 2.52927370004658260781217201514446220919197886472664e-24, // 3.141593
+ };
+
+ public static final double[] P_PROBIT = { //
+ 0.0001, 0.001, 0.01, 0.1, 0.25, 0.5, 0.75, 0.9, 0.99, 0.999, 0.9999 //
+ };
+
+ public static final double[] SCIPY_LOGNORM_QUANT_0_1 = { //
+ 2.42578140301463428263328836465007043443620204925537e-02, // 0.000100
+ 4.54913852476535249258482451750751351937651634216309e-02, // 0.001000
+ 9.76517330703359914823025178520765621215105056762695e-02, // 0.010000
+ 2.77606241852009827386638107782346196472644805908203e-01, // 0.100000
+ 5.09416283863277530308266705105779692530632019042969e-01, // 0.250000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 0.500000
+ 1.96303108415825700028278788522584363818168640136719e+00, // 0.750000
+ 3.60222447927915734311454798444174230098724365234375e+00, // 0.900000
+ 1.02404736563121314674162931623868644237518310546875e+01, // 0.990000
+ 2.19821839795828282149159349501132965087890625000000e+01, // 0.999000
+ 4.12238299278443065531973843462765216827392578125000e+01, // 0.999900
+ };
+
+ public static final double[] GNUR_LOGNORM_QUANT_0_1 = { //
+ 2.42578140301463567041206914609574596397578716278076e-02, // 0.000100
+ 4.54913852476535249258482451750751351937651634216309e-02, // 0.001000
+ 9.76517330703359914823025178520765621215105056762695e-02, // 0.010000
+ 2.77606241852009716364335645266692154109477996826172e-01, // 0.100000
+ 5.09416283863277530308266705105779692530632019042969e-01, // 0.250000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 0.500000
+ 1.96303108415825700028278788522584363818168640136719e+00, // 0.750000
+ 3.60222447927915911947138738469220697879791259765625e+00, // 0.900000
+ 1.02404736563121314674162931623868644237518310546875e+01, // 0.990000
+ 2.19821839795828282149159349501132965087890625000000e+01, // 0.999000
+ 4.12238299278442923423426691442728042602539062500000e+01, // 0.999900
+ };
+
+ public static final double[] SCIPY_LOGNORM_QUANT_1_3 = { //
+ 3.88015852051401416715654957290126958469045348465443e-05, // 0.000100
+ 2.55906882854475099201702059659169208316598087549210e-04, // 0.001000
+ 2.53124596262631687548783077090774895623326301574707e-03, // 0.010000
+ 5.81543441640198222053470544778974726796150207519531e-02, // 0.100000
+ 3.59346113463704264212594807759160175919532775878906e-01, // 0.250000
+ 2.71828182845904509079559829842764884233474731445312e+00, // 0.500000
+ 2.05625045661638417016092716949060559272766113281250e+01, // 0.750000
+ 1.27059400379280148740690492559224367141723632812500e+02, // 0.900000
+ 2.91913792971113252860959619283676147460937500000000e+03, // 0.990000
+ 2.88740029830793428118340671062469482421875000000000e+04, // 0.999000
+ 1.90431809934209391940385103225708007812500000000000e+05, // 0.999900
+ };
+
+ public static final double[] GNUR_LOGNORM_QUANT_1_3 = { //
+ 3.88015852051401484478290737634154083934845402836800e-05, // 0.000100
+ 2.55906882854475099201702059659169208316598087549210e-04, // 0.001000
+ 2.53124596262631687548783077090774895623326301574707e-03, // 0.010000
+ 5.81543441640197528164080154056136962026357650756836e-02, // 0.100000
+ 3.59346113463704319723746039016987197101116180419922e-01, // 0.250000
+ 2.71828182845904509079559829842764884233474731445312e+00, // 0.500000
+ 2.05625045661638417016092716949060559272766113281250e+01, // 0.750000
+ 1.27059400379280333481801790185272693634033203125000e+02, // 0.900000
+ 2.91913792971113298335694707930088043212890625000000e+03, // 0.990000
+ 2.88740029830793428118340671062469482421875000000000e+04, // 0.999000
+ 1.90431809934209421044215559959411621093750000000000e+05, // 0.999900
+ };
+
+ public static final double[] SCIPY_LOGNORM_QUANT_01_01 = { //
+ 7.61929194249313157527581097383517771959304809570312e-01, // 0.000100
+ 8.11376386650571768122119920008117333054542541503906e-01, // 0.001000
+ 8.75784881379674473578234028536826372146606445312500e-01, // 0.010000
+ 9.72237506076474744531878968700766563415527343750000e-01, // 0.100000
+ 1.03308660502291438376687437994405627250671386718750e+00, // 0.250000
+ 1.10517091807564771244187795673497021198272705078125e+00, // 0.500000
+ 1.18228496257879456265982298646122217178344726562500e+00, // 0.750000
+ 1.25628023042354852734092673927079886198043823242188e+00, // 0.900000
+ 1.39463786613445961393153993412852287292480468750000e+00, // 0.990000
+ 1.50534669021145739442602007329696789383888244628906e+00, // 0.999000
+ 1.60303971468576467174216304556466639041900634765625e+00, // 0.999900
+ };
+
+ public static final double[] GNUR_LOGNORM_QUANT_01_01 = { //
+ 7.61929194249313157527581097383517771959304809570312e-01, // 0.000100
+ 8.11376386650571768122119920008117333054542541503906e-01, // 0.001000
+ 8.75784881379674362555931566021172329783439636230469e-01, // 0.010000
+ 9.72237506076474744531878968700766563415527343750000e-01, // 0.100000
+ 1.03308660502291416172226945491274818778038024902344e+00, // 0.250000
+ 1.10517091807564771244187795673497021198272705078125e+00, // 0.500000
+ 1.18228496257879434061521806142991408705711364746094e+00, // 0.750000
+ 1.25628023042354852734092673927079886198043823242188e+00, // 0.900000
+ 1.39463786613445961393153993412852287292480468750000e+00, // 0.990000
+ 1.50534669021145739442602007329696789383888244628906e+00, // 0.999000
+ 1.60303971468576444969755812053335830569267272949219e+00, // 0.999900
+ };
+
+ @Test
+ public void testPDF() {
+ checkPDF(new LogNormalDistribution(0., 1., 0), P_CDFPDF, GNUR_LOGNORM_PDF_0_1, 1e-15);
+ checkPDF(new LogNormalDistribution(1., 3., 0), P_CDFPDF, GNUR_LOGNORM_PDF_1_3, 1e-15);
+ checkPDF(new LogNormalDistribution(.1, .1, 0), P_CDFPDF, GNUR_LOGNORM_PDF_01_01, 1e-15);
+ checkPDF(new LogNormalDistribution(0., 1., 0), P_CDFPDF, SCIPY_LOGNORM_PDF_0_1, 1e-12);
+ checkPDF(new LogNormalDistribution(1., 3., 0), P_CDFPDF, SCIPY_LOGNORM_PDF_1_3, 1e-12);
+ checkPDF(new LogNormalDistribution(.1, .1, 0), P_CDFPDF, SCIPY_LOGNORM_PDF_01_01, 1e-14);
+ }
+
+ @Test
+ public void testCDF() {
+ checkCDF(new LogNormalDistribution(0., 1., 0), P_CDFPDF, GNUR_LOGNORM_CDF_0_1, 1e-15);
+ checkCDF(new LogNormalDistribution(1., 3., 0), P_CDFPDF, GNUR_LOGNORM_CDF_1_3, 1e-15);
+ checkCDF(new LogNormalDistribution(.1, .1, 0), P_CDFPDF, GNUR_LOGNORM_CDF_01_01, 1e-15);
+ checkCDF(new LogNormalDistribution(0., 1., 0), P_CDFPDF, SCIPY_LOGNORM_CDF_0_1, 1e-12);
+ checkCDF(new LogNormalDistribution(1., 3., 0), P_CDFPDF, SCIPY_LOGNORM_CDF_1_3, 1e-12);
+ checkCDF(new LogNormalDistribution(.1, .1, 0), P_CDFPDF, SCIPY_LOGNORM_CDF_01_01, 1e-15);
+ }
+
+ @Test
+ public void testProbit() {
+ checkQuantile(new LogNormalDistribution(0., 1., 0), P_PROBIT, GNUR_LOGNORM_QUANT_0_1, 1e-8);
+ checkQuantile(new LogNormalDistribution(1., 3., 0), P_PROBIT, GNUR_LOGNORM_QUANT_1_3, 1e-8);
+ checkQuantile(new LogNormalDistribution(.1, .1, 0), P_PROBIT, GNUR_LOGNORM_QUANT_01_01, 1e-9);
+ checkQuantile(new LogNormalDistribution(0., 1., 0), P_PROBIT, SCIPY_LOGNORM_QUANT_0_1, 1e-8);
+ checkQuantile(new LogNormalDistribution(1., 3., 0), P_PROBIT, SCIPY_LOGNORM_QUANT_1_3, 1e-8);
+ checkQuantile(new LogNormalDistribution(.1, .1, 0), P_PROBIT, SCIPY_LOGNORM_QUANT_01_01, 1e-9);
+ }
+}
diff --git a/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestLogisticDistribution.java b/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestLogisticDistribution.java
new file mode 100644
index 00000000..2a16d24b
--- /dev/null
+++ b/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestLogisticDistribution.java
@@ -0,0 +1,210 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2012
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import org.junit.Test;
+
+import de.lmu.ifi.dbs.elki.JUnit4Test;
+
+/**
+ * Unit test for the Logistic distribution in ELKI.
+ *
+ * The reference values were computed using GNU R and SciPy.
+ *
+ * @author Erich Schubert
+ */
+public class TestLogisticDistribution extends AbstractDistributionTest implements JUnit4Test {
+ public static final double[] P_CDFPDF = { //
+ 1e-10, 1e-05, 0.1, 0.1234567, 0.2, 0.271828182846, 0.3, 0.314159265359, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.71828182846, 3.14159265359 //
+ };
+
+ public static final double[] SCIPY_LOGISTIC_CDF_05 = { //
+ 3.77540668821645775121709220911725424230098724365234e-01, // 0.000000
+ 3.77543018838145283400109519789111800491809844970703e-01, // 0.000010
+ 4.01312339887547997463457249978091567754745483398438e-01, // 0.100000
+ 4.06960880864213336849388724658638238906860351562500e-01, // 0.123457
+ 4.25557483188341023616629854586790315806865692138672e-01, // 0.200000
+ 4.43203246664875705196351418635458685457706451416016e-01, // 0.271828
+ 4.50166002687522159853017456043744459748268127441406e-01, // 0.300000
+ 4.53673071561317309274841136357281357049942016601562e-01, // 0.314159
+ 4.75020812521059987432181515032425522804260253906250e-01, // 0.400000
+ 5.00000000000000000000000000000000000000000000000000e-01, // 0.500000
+ 5.24979187478939901545516022451920434832572937011719e-01, // 0.600000
+ 5.49833997312477840146982543956255540251731872558594e-01, // 0.700000
+ 5.74442516811659031894521376671036705374717712402344e-01, // 0.800000
+ 5.98687660112452002536542750021908432245254516601562e-01, // 0.900000
+ 6.22459331201854593196287623868556693196296691894531e-01, // 1.000000
+ 6.45656306225795395548061605950351804494857788085938e-01, // 1.100000
+ 6.68187772168166160824398502882104367017745971679688e-01, // 1.200000
+ 6.89974481127612504494095446716528385877609252929688e-01, // 1.300000
+ 7.10949502625003892930521942616906017065048217773438e-01, // 1.400000
+ 7.31058578630004896048433238320285454392433166503906e-01, // 1.500000
+ 7.50260105595117687826700603181961923837661743164062e-01, // 1.600000
+ 7.68524783499017538623832024313742294907569885253906e-01, // 1.700000
+ 7.85834983042558610222272363898809999227523803710938e-01, // 1.800000
+ 8.02183888558581692507232219213619828224182128906250e-01, // 1.900000
+ 8.17574476193643651100728675373829901218414306640625e-01, // 2.000000
+ 9.01879254389253204315934908663621172308921813964844e-01, // 2.718282
+ 9.33490913616609740977025921893073245882987976074219e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_LOGISTIC_PDF_05 = { //
+ 2.35003712207350168306163595843827351927757263183594e-01, // 0.000000
+ 2.35004287764725150466915692959446460008621215820312e-01, // 0.000010
+ 2.40260745741529169183792191688553430140018463134766e-01, // 0.100000
+ 2.41343722310436908928821253539354074746370315551758e-01, // 0.123457
+ 2.44458311690745860866869065830542240291833877563477e-01, // 0.200000
+ 2.46774128810589049587420618081523571163415908813477e-01, // 0.271828
+ 2.47516572711860005640005510940682142972946166992188e-01, // 0.300000
+ 2.47853815701437218965708098039613105356693267822266e-01, // 0.314159
+ 2.49376040192891945679320997442118823528289794921875e-01, // 0.400000
+ 2.50000000000000000000000000000000000000000000000000e-01, // 0.500000
+ 2.49376040192891945679320997442118823528289794921875e-01, // 0.600000
+ 2.47516572711859950128854279682855121791362762451172e-01, // 0.700000
+ 2.44458311690745888622444681459455750882625579833984e-01, // 0.800000
+ 2.40260745741529169183792191688553430140018463134766e-01, // 0.900000
+ 2.35003712201594494590750628049136139452457427978516e-01, // 1.000000
+ 2.28784240456657267381856968313513789325952529907227e-01, // 1.100000
+ 2.21712873293109097305730870175466407090425491333008e-01, // 1.200000
+ 2.13909696520294428934150232635147403925657272338867e-01, // 1.300000
+ 2.05500307342263432985873805591836571693420410156250e-01, // 1.400000
+ 1.96611933241481878775758218580449465662240982055664e-01, // 1.500000
+ 1.87369879547520601370536041940795257687568664550781e-01, // 1.600000
+ 1.77894440646805707118005557276774197816848754882812e-01, // 1.700000
+ 1.68298362469060241997098614774586167186498641967773e-01, // 1.800000
+ 1.58684897495614651852235965634463354945182800292969e-01, // 1.900000
+ 1.49146452070332835582178176991874352097511291503906e-01, // 2.000000
+ 8.84930648915379924890345364474342204630374908447266e-02, // 2.718282
+ 6.20856278118370533136705091692419955506920814514160e-02, // 3.141593
+ };
+
+ public static final double[] GNUR_LOGISTIC_CDF_05 = { //
+ 3.77540668821645775121709220911725424230098724365234e-01, // 0.000000
+ 3.77543018838145283400109519789111800491809844970703e-01, // 0.000010
+ 4.01312339887547997463457249978091567754745483398438e-01, // 0.100000
+ 4.06960880864213336849388724658638238906860351562500e-01, // 0.123457
+ 4.25557483188341023616629854586790315806865692138672e-01, // 0.200000
+ 4.43203246664899241924473471954115666449069976806641e-01, // 0.271828
+ 4.50166002687522159853017456043744459748268127441406e-01, // 0.300000
+ 4.53673071561322416300754412077367305755615234375000e-01, // 0.314159
+ 4.75020812521059987432181515032425522804260253906250e-01, // 0.400000
+ 5.00000000000000000000000000000000000000000000000000e-01, // 0.500000
+ 5.24979187478939901545516022451920434832572937011719e-01, // 0.600000
+ 5.49833997312477840146982543956255540251731872558594e-01, // 0.700000
+ 5.74442516811659031894521376671036705374717712402344e-01, // 0.800000
+ 5.98687660112452002536542750021908432245254516601562e-01, // 0.900000
+ 6.22459331201854593196287623868556693196296691894531e-01, // 1.000000
+ 6.45656306225795395548061605950351804494857788085938e-01, // 1.100000
+ 6.68187772168166160824398502882104367017745971679688e-01, // 1.200000
+ 6.89974481127612504494095446716528385877609252929688e-01, // 1.300000
+ 7.10949502625003892930521942616906017065048217773438e-01, // 1.400000
+ 7.31058578630004896048433238320285454392433166503906e-01, // 1.500000
+ 7.50260105595117687826700603181961923837661743164062e-01, // 1.600000
+ 7.68524783499017538623832024313742294907569885253906e-01, // 1.700000
+ 7.85834983042558610222272363898809999227523803710938e-01, // 1.800000
+ 8.02183888558581692507232219213619828224182128906250e-01, // 1.900000
+ 8.17574476193643651100728675373829901218414306640625e-01, // 2.000000
+ 9.01879254389337470243503958045039325952529907226562e-01, // 2.718282
+ 9.33490913616622508541809111193288117647171020507812e-01, // 3.141593
+ };
+
+ public static final double[] GNUR_LOGISTIC_PDF_05 = { //
+ 2.35003712207350168306163595843827351927757263183594e-01, // 0.000000
+ 2.35004287764725178222491308588359970599412918090820e-01, // 0.000010
+ 2.40260745741529169183792191688553430140018463134766e-01, // 0.100000
+ 2.41343722310436908928821253539354074746370315551758e-01, // 0.123457
+ 2.44458311690745888622444681459455750882625579833984e-01, // 0.200000
+ 2.46774128810591714122679718457220587879419326782227e-01, // 0.271828
+ 2.47516572711859977884429895311768632382154464721680e-01, // 0.300000
+ 2.47853815701437635299342332473315764218568801879883e-01, // 0.314159
+ 2.49376040192891945679320997442118823528289794921875e-01, // 0.400000
+ 2.50000000000000000000000000000000000000000000000000e-01, // 0.500000
+ 2.49376040192891945679320997442118823528289794921875e-01, // 0.600000
+ 2.47516572711859950128854279682855121791362762451172e-01, // 0.700000
+ 2.44458311690745888622444681459455750882625579833984e-01, // 0.800000
+ 2.40260745741529169183792191688553430140018463134766e-01, // 0.900000
+ 2.35003712201594494590750628049136139452457427978516e-01, // 1.000000
+ 2.28784240456657267381856968313513789325952529907227e-01, // 1.100000
+ 2.21712873293109097305730870175466407090425491333008e-01, // 1.200000
+ 2.13909696520294428934150232635147403925657272338867e-01, // 1.300000
+ 2.05500307342263432985873805591836571693420410156250e-01, // 1.400000
+ 1.96611933241481878775758218580449465662240982055664e-01, // 1.500000
+ 1.87369879547520601370536041940795257687568664550781e-01, // 1.600000
+ 1.77894440646805707118005557276774197816848754882812e-01, // 1.700000
+ 1.68298362469060241997098614774586167186498641967773e-01, // 1.800000
+ 1.58684897495614651852235965634463354945182800292969e-01, // 1.900000
+ 1.49146452070332835582178176991874352097511291503906e-01, // 2.000000
+ 8.84930648914700607177152846816170495003461837768555e-02, // 2.718282
+ 6.20856278118259094500608341604674933478236198425293e-02, // 3.141593
+ };
+
+ public static final double[] P_QUANT = { //
+ 0.0001, 0.001, 0.01, 0.1, 0.25, 0.5, 0.75, 0.9, 0.99, 0.999, 0.9999 //
+ };
+
+ public static final double[] SCIPY_LOGISTIC_QUANT_05 = { //
+ -8.71024036697584946864481025841087102890014648437500e+00, // 0.000100
+ -6.40675477864855391629816949716769158840179443359375e+00, // 0.001000
+ -4.09511985013458978954759004409424960613250732421875e+00, // 0.010000
+ -1.69722457733621956421643517387565225362777709960938e+00, // 0.100000
+ -5.98612288668109782108217586937826126813888549804688e-01, // 0.250000
+ 5.00000000000000000000000000000000000000000000000000e-01, // 0.500000
+ 1.59861228866811000415282251196913421154022216796875e+00, // 0.750000
+ 2.69722457733621912012722532381303608417510986328125e+00, // 0.900000
+ 5.09511985013458357229865214321762323379516601562500e+00, // 0.990000
+ 7.40675477864846509845619948464445769786834716796875e+00, // 0.999000
+ 9.71024036697667902728881017537787556648254394531250e+00, // 0.999900
+ };
+
+ public static final double[] GNUR_LOGISTIC_QUANT_05 = { //
+ -8.71024036697584946864481025841087102890014648437500e+00, // 0.000100
+ -6.40675477864855391629816949716769158840179443359375e+00, // 0.001000
+ -4.09511985013458978954759004409424960613250732421875e+00, // 0.010000
+ -1.69722457733621912012722532381303608417510986328125e+00, // 0.100000
+ -5.98612288668109782108217586937826126813888549804688e-01, // 0.250000
+ 5.00000000000000000000000000000000000000000000000000e-01, // 0.500000
+ 1.59861228866810978210821758693782612681388854980469e+00, // 0.750000
+ 2.69722457733621956421643517387565225362777709960938e+00, // 0.900000
+ 5.09511985013458890136917034396901726722717285156250e+00, // 0.990000
+ 7.40675477864855302811974979704245924949645996093750e+00, // 0.999000
+ 9.71024036697595960276885307393968105316162109375000e+00, // 0.999900
+ };
+
+ @Test
+ public void testPDF() {
+ checkPDF(new LogisticDistribution(.5, 1.), P_CDFPDF, SCIPY_LOGISTIC_PDF_05, 1e-12);
+ checkPDF(new LogisticDistribution(.5, 1.), P_CDFPDF, GNUR_LOGISTIC_PDF_05, 1e-15);
+ }
+
+ @Test
+ public void testCDF() {
+ checkCDF(new LogisticDistribution(.5, 1.), P_CDFPDF, SCIPY_LOGISTIC_CDF_05, 1e-13);
+ checkCDF(new LogisticDistribution(.5, 1.), P_CDFPDF, GNUR_LOGISTIC_CDF_05, 0.);
+ }
+
+ @Test
+ public void testProbit() {
+ checkQuantile(new LogisticDistribution(.5, 1.), P_QUANT, SCIPY_LOGISTIC_QUANT_05, 1e-13);
+ checkQuantile(new LogisticDistribution(.5, 1.), P_QUANT, GNUR_LOGISTIC_QUANT_05, 0.);
+ }
+}
diff --git a/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestWeibullDistribution.java b/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestWeibullDistribution.java
new file mode 100644
index 00000000..15d06c40
--- /dev/null
+++ b/test/de/lmu/ifi/dbs/elki/math/statistics/distribution/TestWeibullDistribution.java
@@ -0,0 +1,1291 @@
+package de.lmu.ifi.dbs.elki.math.statistics.distribution;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2012
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+import org.junit.Test;
+
+import de.lmu.ifi.dbs.elki.JUnit4Test;
+
+/**
+ * Unit test for the Weibull distribution in ELKI.
+ *
+ * The reference values were computed using GNU R and SciPy.
+ *
+ * @author Erich Schubert
+ */
+public class TestWeibullDistribution extends AbstractDistributionTest implements JUnit4Test {
+ public static final double[] P_CDFPDF = { //
+ 1e-10, 1e-05, 0.1, 0.1234567, 0.2, 0.271828182846, 0.3, 0.314159265359, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.71828182846, 3.14159265359 //
+ };
+
+ public static final double[] SCIPY_WEIBULL_CDF_1_1 = { //
+ 9.99999999950000070330663866405545691512513073462287e-11, // 0.000000
+ 9.99995000016666629922851977640974041605659294873476e-06, // 0.000010
+ 9.51625819640404269073030718573136255145072937011719e-02, // 0.100000
+ 1.16140088450309583723019102308171568438410758972168e-01, // 0.123457
+ 1.81269246922018151257915974383649881929159164428711e-01, // 0.200000
+ 2.38014828033141334628908225568011403083801269531250e-01, // 0.271828
+ 2.59181779318282123902861258102348074316978454589844e-01, // 0.300000
+ 2.69597308951354364126018481329083442687988281250000e-01, // 0.314159
+ 3.29679953964360727969307163220946677029132843017578e-01, // 0.400000
+ 3.93469340287366575736882623459678143262863159179688e-01, // 0.500000
+ 4.51188363905973555123551932410919107496738433837891e-01, // 0.600000
+ 5.03414696208590473069932613725541159510612487792969e-01, // 0.700000
+ 5.50671035882778436842954761232249438762664794921875e-01, // 0.800000
+ 5.93430340259400890268182138242991641163825988769531e-01, // 0.900000
+ 6.32120558828557665975722557050175964832305908203125e-01, // 1.000000
+ 6.67128916301920504849931603530421853065490722656250e-01, // 1.100000
+ 6.98805788087797918883836700842948630452156066894531e-01, // 1.200000
+ 7.27468206965987462808698182925581932067871093750000e-01, // 1.300000
+ 7.53403036058393538176858328370144590735435485839844e-01, // 1.400000
+ 7.76869839851570209710018843907164409756660461425781e-01, // 1.500000
+ 7.98103482005344644356625849468400701880455017089844e-01, // 1.600000
+ 8.17316475947265308477085454796906560659408569335938e-01, // 1.700000
+ 8.34701111778413440411839019361650571227073669433594e-01, // 1.800000
+ 8.50431380777364909206994525447953492403030395507812e-01, // 1.900000
+ 8.64664716763387297682186272140825167298316955566406e-01, // 2.000000
+ 9.34011964154687457373427150741918012499809265136719e-01, // 2.718282
+ 9.56786081736227700389463279861956834793090820312500e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_WEIBULL_PDF_1_1 = { //
+ 9.99999999899999991725962900090962648391723632812500e-01, // 0.000000
+ 9.99990000049999827602675850357627496123313903808594e-01, // 0.000010
+ 9.04837418035959517581545696884859353303909301757812e-01, // 0.100000
+ 8.83859911549690457910344321135198697447776794433594e-01, // 0.123457
+ 8.18730753077981820986508409987436607480049133300781e-01, // 0.200000
+ 7.61985171966858665371091774431988596916198730468750e-01, // 0.271828
+ 7.40818220681717876097138741897651925683021545410156e-01, // 0.300000
+ 7.30402691048645635873981518670916557312011718750000e-01, // 0.314159
+ 6.70320046035639327541844068036880344152450561523438e-01, // 0.400000
+ 6.06530659712633424263117376540321856737136840820312e-01, // 0.500000
+ 5.48811636094026389365296836331253871321678161621094e-01, // 0.600000
+ 4.96585303791409526930067386274458840489387512207031e-01, // 0.700000
+ 4.49328964117221563157045238767750561237335205078125e-01, // 0.800000
+ 4.06569659740599109731817861757008358836174011230469e-01, // 0.900000
+ 3.67879441171442334024277442949824035167694091796875e-01, // 1.000000
+ 3.32871083698079550661219627727405168116092681884766e-01, // 1.100000
+ 3.01194211912202136627314530414878390729427337646484e-01, // 1.200000
+ 2.72531793034012592702453048332245089113712310791016e-01, // 1.300000
+ 2.46596963941606489578717287258768919855356216430664e-01, // 1.400000
+ 2.23130160148429818045556771721749100834131240844727e-01, // 1.500000
+ 2.01896517994655383398949766160512808710336685180664e-01, // 1.600000
+ 1.82683524052734663767338929574179928749799728393555e-01, // 1.700000
+ 1.65298888221586531832585365009435918182134628295898e-01, // 1.800000
+ 1.49568619222635063037429858923132997006177902221680e-01, // 1.900000
+ 1.35335283236612702317813727859174832701683044433594e-01, // 2.000000
+ 6.59880358453125426265728492580819875001907348632812e-02, // 2.718282
+ 4.32139182637722579771732966946728993207216262817383e-02, // 3.141593
+ };
+
+ public static final double[] GNUR_WEIBULL_CDF_1_1 = { //
+ 9.99999999950000070330663866405545691512513073462287e-11, // 0.000000
+ 9.99995000016666629922851977640974041605659294873476e-06, // 0.000010
+ 9.51625819640404269073030718573136255145072937011719e-02, // 0.100000
+ 1.16140088450309583723019102308171568438410758972168e-01, // 0.123457
+ 1.81269246922018151257915974383649881929159164428711e-01, // 0.200000
+ 2.38014828033214137503748020208149682730436325073242e-01, // 0.271828
+ 2.59181779318282123902861258102348074316978454589844e-01, // 0.300000
+ 2.69597308951369518670304614715860225260257720947266e-01, // 0.314159
+ 3.29679953964360727969307163220946677029132843017578e-01, // 0.400000
+ 3.93469340287366575736882623459678143262863159179688e-01, // 0.500000
+ 4.51188363905973555123551932410919107496738433837891e-01, // 0.600000
+ 5.03414696208590473069932613725541159510612487792969e-01, // 0.700000
+ 5.50671035882778436842954761232249438762664794921875e-01, // 0.800000
+ 5.93430340259400890268182138242991641163825988769531e-01, // 0.900000
+ 6.32120558828557665975722557050175964832305908203125e-01, // 1.000000
+ 6.67128916301920504849931603530421853065490722656250e-01, // 1.100000
+ 6.98805788087797918883836700842948630452156066894531e-01, // 1.200000
+ 7.27468206965987462808698182925581932067871093750000e-01, // 1.300000
+ 7.53403036058393538176858328370144590735435485839844e-01, // 1.400000
+ 7.76869839851570209710018843907164409756660461425781e-01, // 1.500000
+ 7.98103482005344644356625849468400701880455017089844e-01, // 1.600000
+ 8.17316475947265308477085454796906560659408569335938e-01, // 1.700000
+ 8.34701111778413440411839019361650571227073669433594e-01, // 1.800000
+ 8.50431380777364909206994525447953492403030395507812e-01, // 1.900000
+ 8.64664716763387297682186272140825167298316955566406e-01, // 2.000000
+ 9.34011964154750407018923397117760032415390014648438e-01, // 2.718282
+ 9.56786081736236693195962743629934266209602355957031e-01, // 3.141593
+ };
+
+ public static final double[] GNUR_WEIBULL_PDF_1_1 = { //
+ 9.99999999899999991725962900090962648391723632812500e-01, // 0.000000
+ 9.99990000049999827602675850357627496123313903808594e-01, // 0.000010
+ 9.04837418035959517581545696884859353303909301757812e-01, // 0.100000
+ 8.83859911549690457910344321135198697447776794433594e-01, // 0.123457
+ 8.18730753077981820986508409987436607480049133300781e-01, // 0.200000
+ 7.61985171966785834740676364162936806678771972656250e-01, // 0.271828
+ 7.40818220681717876097138741897651925683021545410156e-01, // 0.300000
+ 7.30402691048630536840846616541966795921325683593750e-01, // 0.314159
+ 6.70320046035639327541844068036880344152450561523438e-01, // 0.400000
+ 6.06530659712633424263117376540321856737136840820312e-01, // 0.500000
+ 5.48811636094026389365296836331253871321678161621094e-01, // 0.600000
+ 4.96585303791409526930067386274458840489387512207031e-01, // 0.700000
+ 4.49328964117221563157045238767750561237335205078125e-01, // 0.800000
+ 4.06569659740599109731817861757008358836174011230469e-01, // 0.900000
+ 3.67879441171442334024277442949824035167694091796875e-01, // 1.000000
+ 3.32871083698079550661219627727405168116092681884766e-01, // 1.100000
+ 3.01194211912202136627314530414878390729427337646484e-01, // 1.200000
+ 2.72531793034012592702453048332245089113712310791016e-01, // 1.300000
+ 2.46596963941606489578717287258768919855356216430664e-01, // 1.400000
+ 2.23130160148429818045556771721749100834131240844727e-01, // 1.500000
+ 2.01896517994655383398949766160512808710336685180664e-01, // 1.600000
+ 1.82683524052734663767338929574179928749799728393555e-01, // 1.700000
+ 1.65298888221586531832585365009435918182134628295898e-01, // 1.800000
+ 1.49568619222635063037429858923132997006177902221680e-01, // 1.900000
+ 1.35335283236612702317813727859174832701683044433594e-01, // 2.000000
+ 6.59880358452495374699253716244129464030265808105469e-02, // 2.718282
+ 4.32139182637633137429311602772941114380955696105957e-02, // 3.141593
+ };
+
+ public static final double[] SCIPY_WEIBULL_CDF_2_1 = { //
+ 1.00000000000000009561654835946237267172778046723484e-20, // 0.000000
+ 9.99999999950000199577634577816119890170121209393983e-11, // 0.000010
+ 9.95016625083194883316650702909100800752639770507812e-03, // 0.100000
+ 1.51259921218065002124220086443528998643159866333008e-02, // 0.123457
+ 3.92105608476767952819130869102082215249538421630859e-02, // 0.200000
+ 7.12266676857742225825731452459876891225576400756836e-02, // 0.271828
+ 8.60688147287718141598134025116451084613800048828125e-02, // 0.300000
+ 9.39819442110770147946752217649191152304410934448242e-02, // 0.314159
+ 1.47856211033788681463718717168376315385103225708008e-01, // 0.400000
+ 2.21199216928595121522960198490181937813758850097656e-01, // 0.500000
+ 3.02323673928968916779780329306959174573421478271484e-01, // 0.600000
+ 3.87373605815583887945763308380264788866043090820312e-01, // 0.700000
+ 4.72707575956951508988623800178174860775470733642578e-01, // 0.800000
+ 5.55141933777058893539901873737107962369918823242188e-01, // 0.900000
+ 6.32120558828557665975722557050175964832305908203125e-01, // 1.000000
+ 7.01802720570112725795297592412680387496948242187500e-01, // 1.100000
+ 7.63072241317878208199942946521332487463951110839844e-01, // 1.200000
+ 8.15480476007010790517881559935631230473518371582031e-01, // 1.300000
+ 8.59141579078954942261248106660787016153335571289062e-01, // 1.400000
+ 8.94600775438135653594429186341585591435432434082031e-01, // 1.500000
+ 9.22695259556700286829311608016723766922950744628906e-01, // 1.600000
+ 9.44423787388516955410011632920941337943077087402344e-01, // 1.700000
+ 9.60836104901012899581758119893493130803108215332031e-01, // 1.800000
+ 9.72948153133649573653940478834556415677070617675781e-01, // 1.900000
+ 9.81684361111265779697987454710528254508972167968750e-01, // 2.000000
+ 9.99382021010668863958414931403240188956260681152344e-01, // 2.718282
+ 9.99948276813796166351266947458498179912567138671875e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_WEIBULL_PDF_2_1 = { //
+ 2.00000000000000007286439463099548315833109413119928e-10, // 0.000000
+ 1.99999999980000009935313803888234929218015167862177e-05, // 0.000010
+ 1.98009966749833621335596944845747202634811401367188e-01, // 0.100000
+ 2.43178589856831550708449185549397952854633331298828e-01, // 0.123457
+ 3.84315775660929281887234765235916711390018463134766e-01, // 0.200000
+ 5.04933534397422723039028369385050609707832336425781e-01, // 0.271828
+ 5.48358711162736933708572450996143743395805358886719e-01, // 0.300000
+ 5.69267933617237598120652819488896057009696960449219e-01, // 0.314159
+ 6.81715031172969165851327488780952990055084228515625e-01, // 0.400000
+ 7.78800783071404878477039801509818062186241149902344e-01, // 0.500000
+ 8.37211591285237255455342619825387373566627502441406e-01, // 0.600000
+ 8.57676951858182490262549890758236870169639587402344e-01, // 0.700000
+ 8.43667878468877696640504382230574265122413635253906e-01, // 0.800000
+ 8.00744519201293969423716134770074859261512756347656e-01, // 0.900000
+ 7.35758882342884668048554885899648070335388183593750e-01, // 1.000000
+ 6.56034014745752180886029236717149615287780761718750e-01, // 1.100000
+ 5.68626620837092255911215943342540413141250610351562e-01, // 1.200000
+ 4.79750762381772055675810406683012843132019042968750e-01, // 1.300000
+ 3.94403578578926050646202838834142312407493591308594e-01, // 1.400000
+ 3.16197673685592983705561209717416204512119293212891e-01, // 1.500000
+ 2.47375169418559082146202854346483945846557617187500e-01, // 1.600000
+ 1.88959122879042484832723403087584301829338073730469e-01, // 1.700000
+ 1.40990022356353439381138059616205282509326934814453e-01, // 1.800000
+ 1.02797018092131570154990072296641301363706588745117e-01, // 1.900000
+ 7.32625555549367146745964873844059184193611145019531e-02, // 2.000000
+ 3.35968211413639750162474229000508785247802734375000e-03, // 2.718282
+ 3.24986363596307557474740512759581179125234484672546e-04, // 3.141593
+ };
+
+ public static final double[] GNUR_WEIBULL_CDF_2_1 = { //
+ 1.00000000000000009561654835946237267172778046723484e-20, // 0.000000
+ 9.99999999950000199577634577816119890170121209393983e-11, // 0.000010
+ 9.95016625083194883316650702909100800752639770507812e-03, // 0.100000
+ 1.51259921218065002124220086443528998643159866333008e-02, // 0.123457
+ 3.92105608476767952819130869102082215249538421630859e-02, // 0.200000
+ 7.12266676858224756507809161121258512139320373535156e-02, // 0.271828
+ 8.60688147287718141598134025116451084613800048828125e-02, // 0.300000
+ 9.39819442110888109143118640531611163169145584106445e-02, // 0.314159
+ 1.47856211033788681463718717168376315385103225708008e-01, // 0.400000
+ 2.21199216928595121522960198490181937813758850097656e-01, // 0.500000
+ 3.02323673928968916779780329306959174573421478271484e-01, // 0.600000
+ 3.87373605815583887945763308380264788866043090820312e-01, // 0.700000
+ 4.72707575956951508988623800178174860775470733642578e-01, // 0.800000
+ 5.55141933777058893539901873737107962369918823242188e-01, // 0.900000
+ 6.32120558828557665975722557050175964832305908203125e-01, // 1.000000
+ 7.01802720570112725795297592412680387496948242187500e-01, // 1.100000
+ 7.63072241317878208199942946521332487463951110839844e-01, // 1.200000
+ 8.15480476007010790517881559935631230473518371582031e-01, // 1.300000
+ 8.59141579078954942261248106660787016153335571289062e-01, // 1.400000
+ 8.94600775438135653594429186341585591435432434082031e-01, // 1.500000
+ 9.22695259556700286829311608016723766922950744628906e-01, // 1.600000
+ 9.44423787388516955410011632920941337943077087402344e-01, // 1.700000
+ 9.60836104901012899581758119893493130803108215332031e-01, // 1.800000
+ 9.72948153133649573653940478834556415677070617675781e-01, // 1.900000
+ 9.81684361111265779697987454710528254508972167968750e-01, // 2.000000
+ 9.99382021010672083605186344357207417488098144531250e-01, // 2.718282
+ 9.99948276813796277373569409974152222275733947753906e-01, // 3.141593
+ };
+
+ public static final double[] GNUR_WEIBULL_PDF_2_1 = { //
+ 2.00000000000000007286439463099548315833109413119928e-10, // 0.000000
+ 1.99999999980000009935313803888234929218015167862177e-05, // 0.000010
+ 1.98009966749833621335596944845747202634811401367188e-01, // 0.100000
+ 2.43178589856831550708449185549397952854633331298828e-01, // 0.123457
+ 3.84315775660929281887234765235916711390018463134766e-01, // 0.200000
+ 5.04933534397574046437284778221510350704193115234375e-01, // 0.271828
+ 5.48358711162736933708572450996143743395805358886719e-01, // 0.300000
+ 5.69267933617267685164620161231141537427902221679688e-01, // 0.314159
+ 6.81715031172969165851327488780952990055084228515625e-01, // 0.400000
+ 7.78800783071404878477039801509818062186241149902344e-01, // 0.500000
+ 8.37211591285237255455342619825387373566627502441406e-01, // 0.600000
+ 8.57676951858182490262549890758236870169639587402344e-01, // 0.700000
+ 8.43667878468877696640504382230574265122413635253906e-01, // 0.800000
+ 8.00744519201293969423716134770074859261512756347656e-01, // 0.900000
+ 7.35758882342884668048554885899648070335388183593750e-01, // 1.000000
+ 6.56034014745752180886029236717149615287780761718750e-01, // 1.100000
+ 5.68626620837092255911215943342540413141250610351562e-01, // 1.200000
+ 4.79750762381772055675810406683012843132019042968750e-01, // 1.300000
+ 3.94403578578926050646202838834142312407493591308594e-01, // 1.400000
+ 3.16197673685592983705561209717416204512119293212891e-01, // 1.500000
+ 2.47375169418559082146202854346483945846557617187500e-01, // 1.600000
+ 1.88959122879042484832723403087584301829338073730469e-01, // 1.700000
+ 1.40990022356353439381138059616205282509326934814453e-01, // 1.800000
+ 1.02797018092131570154990072296641301363706588745117e-01, // 1.900000
+ 7.32625555549367146745964873844059184193611145019531e-02, // 2.000000
+ 3.35968211412013880584614966551271209027618169784546e-03, // 2.718282
+ 3.24986363595906402670920876118998421588912606239319e-04, // 3.141593
+ };
+
+ public static final double[] SCIPY_WEIBULL_CDF_4_1 = { //
+ 1.00000000000000013320864402483403646202733603332908e-40, // 0.000000
+ 1.00000000000000039654310216996797471172433399612973e-20, // 0.000010
+ 9.99950001666625217910250311703634906734805554151535e-05, // 0.100000
+ 2.32278072192682402295413335302498580858809873461723e-04, // 0.123457
+ 1.59872068239368765249497350566798559157177805900574e-03, // 0.200000
+ 5.44493730219271481612919316717125184368342161178589e-03, // 0.271828
+ 8.06728339442883482512947068698849761858582496643066e-03, // 0.300000
+ 9.69362011877886869948284243037051055580377578735352e-03, // 0.314159
+ 2.52750983982060611898745605685689952224493026733398e-02, // 0.400000
+ 6.05869371865242131725004526288103079423308372497559e-02, // 0.500000
+ 1.21553260650068689630032281456806231290102005004883e-01, // 0.600000
+ 2.13450797786544993472901410314079839736223220825195e-01, // 0.700000
+ 3.36084236664526470050873285799752920866012573242188e-01, // 0.800000
+ 4.81129009534547624760136841359781101346015930175781e-01, // 0.900000
+ 6.32120558828557665975722557050175964832305908203125e-01, // 1.000000
+ 7.68713944715671448904004137148149311542510986328125e-01, // 1.100000
+ 8.74267670405572072667155225644819438457489013671875e-01, // 1.200000
+ 9.42507455473835520365355478134006261825561523437500e-01, // 1.300000
+ 9.78540760919919594407190288620768114924430847167969e-01, // 1.400000
+ 9.93670284572514272980470195761881768703460693359375e-01, // 1.500000
+ 9.98575023561807495475761697889538481831550598144531e-01, // 1.600000
+ 9.99764099393370408996872811258072033524513244628906e-01, // 1.700000
+ 9.99972397383803390802370358869666233658790588378906e-01, // 1.800000
+ 9.99997811074995079927418828447116538882255554199219e-01, // 1.900000
+ 9.99999887464825265581680469040293246507644653320312e-01, // 2.000000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 2.718282
+ 1.00000000000000000000000000000000000000000000000000e+00, // 3.141593
+ };
+
+ public static final double[] SCIPY_WEIBULL_PDF_4_1 = { //
+ 4.00000000000000033334568243034394140372534410747462e-30, // 0.000000
+ 4.00000000000000109968250472765612236495730768756629e-15, // 0.000010
+ 3.99960001999933451033442111111071426421403884887695e-03, // 0.100000
+ 7.52494092430275145211293619240677799098193645477295e-03, // 0.123457
+ 3.19488409381634141936956439167261123657226562500000e-02, // 0.200000
+ 7.99046897358400981525861084264761302620172500610352e-02, // 0.271828
+ 1.07128733393401662232768956073414301499724388122559e-01, // 0.300000
+ 1.22822854451452953550294466822379035875201225280762e-01, // 0.314159
+ 2.49529574810059301404052689576928969472646713256836e-01, // 0.400000
+ 4.69706531406737903822090629546437412500381469726562e-01, // 0.500000
+ 7.58977982798340611303444802615558728575706481933594e-01, // 0.600000
+ 1.07914550543685994199449851294048130512237548828125e+00, // 0.700000
+ 1.35969948331105006111840793892042711377143859863281e+00, // 0.800000
+ 1.51302780819725923855401106266072019934654235839844e+00, // 0.900000
+ 1.47151776468576933609710977179929614067077636718750e+00, // 1.000000
+ 1.23136695833376563768979394808411598205566406250000e+00, // 1.100000
+ 8.69061862156685571711989268806064501404762268066406e-01, // 1.200000
+ 5.05244481295933911546569561323849484324455261230469e-01, // 1.300000
+ 2.35536608142962594625302585882309358566999435424805e-01, // 1.400000
+ 8.54511582710575784416207056892744731158018112182617e-02, // 1.500000
+ 2.33468139633453281023278691463929135352373123168945e-02, // 1.600000
+ 4.63591872148445566931274086641678877640515565872192e-03, // 1.700000
+ 6.43913830635281774633638107729893818031996488571167e-04, // 1.800000
+ 6.00553464339657769527694441968890259886393323540688e-05, // 1.900000
+ 3.60112559101629172664759369337783567743827006779611e-06, // 2.000000
+ 1.56051574726592369321459464025011473518080818529307e-22, // 2.718282
+ 6.15572040972424438967743933644082832917854496729035e-41, // 3.141593
+ };
+
+ public static final double[] GNUR_WEIBULL_CDF_4_1 = { //
+ 1.00000000000000013320864402483403646202733603332908e-40, // 0.000000
+ 1.00000000000000039654310216996797471172433399612973e-20, // 0.000010
+ 9.99950001666625217910250311703634906734805554151535e-05, // 0.100000
+ 2.32278072192682402295413335302498580858809873461723e-04, // 0.123457
+ 1.59872068239368765249497350566798559157177805900574e-03, // 0.200000
+ 5.44493730220034933414696709519375872332602739334106e-03, // 0.271828
+ 8.06728339442883482512947068698849761858582496643066e-03, // 0.300000
+ 9.69362011878141006937514845276382402516901493072510e-03, // 0.314159
+ 2.52750983982060611898745605685689952224493026733398e-02, // 0.400000
+ 6.05869371865242131725004526288103079423308372497559e-02, // 0.500000
+ 1.21553260650068689630032281456806231290102005004883e-01, // 0.600000
+ 2.13450797786544993472901410314079839736223220825195e-01, // 0.700000
+ 3.36084236664526470050873285799752920866012573242188e-01, // 0.800000
+ 4.81129009534547624760136841359781101346015930175781e-01, // 0.900000
+ 6.32120558828557665975722557050175964832305908203125e-01, // 1.000000
+ 7.68713944715671448904004137148149311542510986328125e-01, // 1.100000
+ 8.74267670405572072667155225644819438457489013671875e-01, // 1.200000
+ 9.42507455473835520365355478134006261825561523437500e-01, // 1.300000
+ 9.78540760919919594407190288620768114924430847167969e-01, // 1.400000
+ 9.93670284572514272980470195761881768703460693359375e-01, // 1.500000
+ 9.98575023561807495475761697889538481831550598144531e-01, // 1.600000
+ 9.99764099393370408996872811258072033524513244628906e-01, // 1.700000
+ 9.99972397383803390802370358869666233658790588378906e-01, // 1.800000
+ 9.99997811074995079927418828447116538882255554199219e-01, // 1.900000
+ 9.99999887464825265581680469040293246507644653320312e-01, // 2.000000
+ 1.00000000000000000000000000000000000000000000000000e+00, // 2.718282
+ 1.00000000000000000000000000000000000000000000000000e+00, // 3.141593
+ };
+
+ public static final double[] GNUR_WEIBULL_PDF_4_1 = { //
+ 4.00000000000000033334568243034394140372534410747462e-30, // 0.000000
+ 4.00000000000000109968250472765612236495730768756629e-15, // 0.000010
+ 3.99960001999933451033442111111071426421403884887695e-03, // 0.100000
+ 7.52494092430275145211293619240677799098193645477295e-03, // 0.123457
+ 3.19488409381634141936956439167261123657226562500000e-02, // 0.200000
+ 7.99046897359237395797038061573402956128120422363281e-02, // 0.271828
+ 1.07128733393401662232768956073414301499724388122559e-01, // 0.300000
+ 1.22822854451476920489838562389195431023836135864258e-01, // 0.314159
+ 2.49529574810059301404052689576928969472646713256836e-01, // 0.400000
+ 4.69706531406737903822090629546437412500381469726562e-01, // 0.500000
+ 7.58977982798340611303444802615558728575706481933594e-01, // 0.600000
+ 1.07914550543685994199449851294048130512237548828125e+00, // 0.700000
+ 1.35969948331104983907380301388911902904510498046875e+00, // 0.800000
+ 1.51302780819725901650940613762941211462020874023438e+00, // 0.900000
+ 1.47151776468576933609710977179929614067077636718750e+00, // 1.000000
+ 1.23136695833376519360058409802149981260299682617188e+00, // 1.100000
+ 8.69061862156685904778896656353026628494262695312500e-01, // 1.200000
+ 5.05244481295934022568872023839503526687622070312500e-01, // 1.300000
+ 2.35536608142962705647605048397963400930166244506836e-01, // 1.400000
+ 8.54511582710575784416207056892744731158018112182617e-02, // 1.500000
+ 2.33468139633453072856461574247077805921435356140137e-02, // 1.600000
+ 4.63591872148445566931274086641678877640515565872192e-03, // 1.700000
+ 6.43913830635280690431465622225459810579195618629456e-04, // 1.800000
+ 6.00553464339657769527694441968890259886393323540688e-05, // 1.900000
+ 3.60112559101629172664759369337783567743827006779611e-06, // 2.000000
+ 1.56051574714787161674795427931483364971526738525937e-22, // 2.718282
+ 6.15572040956738830521263230405220044059347242007796e-41, // 3.141593
+ };
+
+ public static final double[] SCIPY_WEIBULL_CDF_4_10 = { //
+ 1.00000000000000045083134380686670919466036533826663e-44, // 0.000000
+ 1.00000000000000065838446881563251711176039766238496e-24, // 0.000010
+ 9.99999995000000102046765708798184424388466595701175e-09, // 0.100000
+ 2.32305050223913381984605750103789478799853895907290e-08, // 0.123457
+ 1.59999987200000687481607052758958431581959303002805e-07, // 0.200000
+ 5.45981351283569954638893052117909476805834856349975e-07, // 0.271828
+ 8.09999671950088426490164863341680856478888017591089e-07, // 0.300000
+ 9.74090435913627788344247224183725109014631016179919e-07, // 0.314159
+ 2.55999672320279633532034806175925467641718569211662e-06, // 0.400000
+ 6.24998046879069103125628470429830940702231600880623e-06, // 0.500000
+ 1.29599160195627932342429117218429723834560718387365e-05, // 0.600000
+ 2.40097117622568567696633018426766170705377589911222e-05, // 0.700000
+ 4.09591611506531300059170963567822809636709280312061e-05, // 0.800000
+ 6.56078477110208019762102593652741688856622204184532e-05, // 0.900000
+ 9.99950001666625217910250311703634906734805554151535e-05, // 1.000000
+ 1.46399282579002344489502163149552416143706068396568e-04, // 1.100000
+ 2.07338502401139678377878228232589208346325904130936e-04, // 1.200000
+ 2.85569217346686983569764572976623639988247305154800e-04, // 1.300000
+ 3.84086219995277808499090088645289142732508480548859e-04, // 1.400000
+ 5.06121877090403020534037370481428297352977097034454e-04, // 1.500000
+ 6.55145298540010952680068267994784037000499665737152e-04, // 1.600000
+ 8.34861309211383712837462045541769839474000036716461e-04, // 1.700000
+ 1.04920919472584086955257998141632924671284854412079e-03, // 1.800000
+ 1.30236119061361726480241518544289647252298891544342e-03, // 1.900000
+ 1.59872068239368765249497350566798559157177805900574e-03, // 2.000000
+ 5.44493730219271481612919316717125184368342161178589e-03, // 2.718282
+ 9.69362011877886869948284243037051055580377578735352e-03, // 3.141593
+ };
+
+ public static final double[] SCIPY_WEIBULL_PDF_4_10 = { //
+ 4.00000000000000056598312279676865044379763820833960e-34, // 0.000000
+ 4.00000000000000182691365172827638047889457880763485e-19, // 0.000010
+ 3.99999996000000073268388234987158469380119640845805e-07, // 0.100000
+ 7.52668903431345566337837965642520998699183110147715e-07, // 0.123457
+ 3.19999948800004119659748033632773456247377907857299e-06, // 0.200000
+ 8.03421038274362870484652382474521914446086157113314e-06, // 0.271828
+ 1.07999912520035405629360153456630655455228406935930e-05, // 0.300000
+ 1.24024985909529048835279324558555913426971528679132e-05, // 0.314159
+ 2.55999344640838884224441629466895165023743174970150e-05, // 0.400000
+ 4.99996875009765654775117926789107514196075499057770e-05, // 0.500000
+ 8.63988802632558908862689395213863008393673226237297e-05, // 0.600000
+ 1.37196705867546154882993802992530163464834913611412e-04, // 0.700000
+ 2.04791611563796387964972445239197895716642960906029e-04, // 0.800000
+ 2.91580868751607432971112432440463635430205613374710e-04, // 0.900000
+ 3.99960001999933461875463835966115766495931893587112e-04, // 1.000000
+ 5.32322057021955194998363847247446756227873265743256e-04, // 1.100000
+ 6.91056687627140129107083943438283313298597931861877e-04, // 1.200000
+ 8.78549041771795719522886169983166837482713162899017e-04, // 1.300000
+ 1.09717842696493267894142231710929991095326840877533e-03, // 1.400000
+ 1.34931673546592788628939452166832779766991734504700e-03, // 1.500000
+ 1.63732660994287239700217817528482555644586682319641e-03, // 1.600000
+ 1.96355933055513721952056727104718447662889957427979e-03, // 1.700000
+ 2.33035240479054304302275468785410339478403329849243e-03, // 1.800000
+ 2.74002684183743266954635942056484054774045944213867e-03, // 1.900000
+ 3.19488409381634124589721679399190179537981748580933e-03, // 2.000000
+ 7.99046897358400912136922045192477526143193244934082e-03, // 2.718282
+ 1.22822854451452960489188370729607413522899150848389e-02, // 3.141593
+ };
+
+ public static final double[] GNUR_WEIBULL_CDF_4_10 = { //
+ 1.00000000000000045083134380686670919466036533826663e-44, // 0.000000
+ 1.00000000000000065838446881563251711176039766238496e-24, // 0.000010
+ 9.99999995000000102046765708798184424388466595701175e-09, // 0.100000
+ 2.32305050223913381984605750103789478799853895907290e-08, // 0.123457
+ 1.59999987200000687481607052758958431581959303002805e-07, // 0.200000
+ 5.45981351284337366489105448225105376991450611967593e-07, // 0.271828
+ 8.09999671950088426490164863341680856478888017591089e-07, // 0.300000
+ 9.74090435913884227569028463611378043651711777783930e-07, // 0.314159
+ 2.55999672320279633532034806175925467641718569211662e-06, // 0.400000
+ 6.24998046879069103125628470429830940702231600880623e-06, // 0.500000
+ 1.29599160195627932342429117218429723834560718387365e-05, // 0.600000
+ 2.40097117622568567696633018426766170705377589911222e-05, // 0.700000
+ 4.09591611506531300059170963567822809636709280312061e-05, // 0.800000
+ 6.56078477110208019762102593652741688856622204184532e-05, // 0.900000
+ 9.99950001666625217910250311703634906734805554151535e-05, // 1.000000
+ 1.46399282579002344489502163149552416143706068396568e-04, // 1.100000
+ 2.07338502401139678377878228232589208346325904130936e-04, // 1.200000
+ 2.85569217346686983569764572976623639988247305154800e-04, // 1.300000
+ 3.84086219995277808499090088645289142732508480548859e-04, // 1.400000
+ 5.06121877090403020534037370481428297352977097034454e-04, // 1.500000
+ 6.55145298540010952680068267994784037000499665737152e-04, // 1.600000
+ 8.34861309211383712837462045541769839474000036716461e-04, // 1.700000
+ 1.04920919472584086955257998141632924671284854412079e-03, // 1.800000
+ 1.30236119061361726480241518544289647252298891544342e-03, // 1.900000
+ 1.59872068239368765249497350566798559157177805900574e-03, // 2.000000
+ 5.44493730220034412997653916477247548755258321762085e-03, // 2.718282
+ 9.69362011878141006937514845276382402516901493072510e-03, // 3.141593
+ };
+
+ public static final double[] GNUR_WEIBULL_PDF_4_10 = { //
+ 4.00000000000000056598312279676865044379763820833960e-34, // 0.000000
+ 4.00000000000000182691365172827638047889457880763485e-19, // 0.000010
+ 3.99999996000000073268388234987158469380119640845805e-07, // 0.100000
+ 7.52668903431345566337837965642520998699183110147715e-07, // 0.123457
+ 3.19999948800004119659748033632773456247377907857299e-06, // 0.200000
+ 8.03421038275209734025317231953522423282265663146973e-06, // 0.271828
+ 1.07999912520035405629360153456630655455228406935930e-05, // 0.300000
+ 1.24024985909553511146796028752348206580791156738997e-05, // 0.314159
+ 2.55999344640838884224441629466895165023743174970150e-05, // 0.400000
+ 4.99996875009765654775117926789107514196075499057770e-05, // 0.500000
+ 8.63988802632558908862689395213863008393673226237297e-05, // 0.600000
+ 1.37196705867546154882993802992530163464834913611412e-04, // 0.700000
+ 2.04791611563796387964972445239197895716642960906029e-04, // 0.800000
+ 2.91580868751607432971112432440463635430205613374710e-04, // 0.900000
+ 3.99960001999933461875463835966115766495931893587112e-04, // 1.000000
+ 5.32322057021955194998363847247446756227873265743256e-04, // 1.100000
+ 6.91056687627140129107083943438283313298597931861877e-04, // 1.200000
+ 8.78549041771795719522886169983166837482713162899017e-04, // 1.300000
+ 1.09717842696493267894142231710929991095326840877533e-03, // 1.400000
+ 1.34931673546592788628939452166832779766991734504700e-03, // 1.500000
+ 1.63732660994287239700217817528482555644586682319641e-03, // 1.600000
+ 1.96355933055513721952056727104718447662889957427979e-03, // 1.700000
+ 2.33035240479054304302275468785410339478403329849243e-03, // 1.800000
+ 2.74002684183743266954635942056484054774045944213867e-03, // 1.900000
+ 3.19488409381634124589721679399190179537981748580933e-03, // 2.000000
+ 7.99046897359236875379995268531274632550776004791260e-03, // 2.718282
+ 1.22822854451476917020391610435581242199987173080444e-02, // 3.141593
+ };
+
+ public static final double[] SCIPY_WEIBULL_CDF_01_10 = { //
+ 7.63599351831150269243053685386257711797952651977539e-02, // 0.000000
+ 2.22124383190155039180524454422993585467338562011719e-01, // 0.000010
+ 4.67917828829414239599771008215611800551414489746094e-01, // 0.100000
+ 4.75019399203212733251433519399142824113368988037109e-01, // 0.123457
+ 4.91476239432907469062428162942524068057537078857422e-01, // 0.200000
+ 5.02079925428299933543030419968999922275543212890625e-01, // 0.271828
+ 5.05508894037498435203303870366653427481651306152344e-01, // 0.300000
+ 5.07115955277961494296334876707987859845161437988281e-01, // 0.314159
+ 5.15568704992931170494330217479728162288665771484375e-01, // 0.400000
+ 5.23427039033618868302255577873438596725463867187500e-01, // 0.500000
+ 5.29881674984790551619084908452350646257400512695312e-01, // 0.600000
+ 5.35361615308103777621795416052918881177902221679688e-01, // 0.700000
+ 5.40124560432196254566861171042546629905700683593750e-01, // 0.800000
+ 5.44337595924840766947738757153274491429328918457031e-01, // 0.900000
+ 5.48115306569588400797954363952158018946647644042969e-01, // 1.000000
+ 5.51539729658985344862287547584855929017066955566406e-01, // 1.100000
+ 5.54671638850380399610173753899289295077323913574219e-01, // 1.200000
+ 5.57557321771014247069331304373918101191520690917969e-01, // 1.300000
+ 5.60232853193344815245779955148464068770408630371094e-01, // 1.400000
+ 5.62726898877477954563630646589444950222969055175781e-01, // 1.500000
+ 5.65062617878835049545216406841063871979713439941406e-01, // 1.600000
+ 5.67258990450220990098273432522546499967575073242188e-01, // 1.700000
+ 5.69331767989112891292791118758032098412513732910156e-01, // 1.800000
+ 5.71294167272651032263297565805260092020034790039062e-01, // 1.900000
+ 5.73157387426872722002713089750614017248153686523438e-01, // 2.000000
+ 5.84332020844404609327682464936515316367149353027344e-01, // 2.718282
+ 5.89617748244351203013025042309891432523727416992188e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_WEIBULL_PDF_01_10 = { //
+ 7.33673382206617593765258789062500000000000000000000e+07, // 0.000000
+ 1.95393520726679525978397578001022338867187500000000e+03, // 0.000010
+ 3.35721153767048474669820734561653807759284973144531e-01, // 0.100000
+ 2.74018609307649319006827681732829660177230834960938e-01, // 0.123457
+ 1.71942902599836300314706249992013908922672271728516e-01, // 0.200000
+ 1.27730497083068800234784134772780817002058029174805e-01, // 0.271828
+ 1.16077849986715483932009362888493342325091361999512e-01, // 0.300000
+ 1.10996650714204211918278986104269279167056083679199e-01, // 0.314159
+ 8.77764877675434873616211461921920999884605407714844e-02, // 0.400000
+ 7.06409277770171650789876593989902175962924957275391e-02, // 0.500000
+ 5.91386021268343400891787098316854098811745643615723e-02, // 0.600000
+ 5.08776272124714656897026543447282165288925170898438e-02, // 0.700000
+ 4.46538827467651763813982768169807968661189079284668e-02, // 0.800000
+ 3.97946728437166968861404825474892277270555496215820e-02, // 0.900000
+ 3.58944770831502030228321586946549359709024429321289e-02, // 1.000000
+ 3.26941881616923946118902222224278375506401062011719e-02, // 1.100000
+ 3.00204524249116540268733643870291416533291339874268e-02, // 1.200000
+ 2.77528760154124205794534674396345508284866809844971e-02, // 1.300000
+ 2.58052190382604060281401814336277311667799949645996e-02, // 1.400000
+ 2.41140762238259073746426963680278277024626731872559e-02, // 1.500000
+ 2.26317820314968741468586443943422636948525905609131e-02, // 1.600000
+ 2.13218078236213533227516592205574852414429187774658e-02, // 1.700000
+ 2.01556859486728690011858589059556834399700164794922e-02, // 1.800000
+ 1.91109005040240170769649807880341541022062301635742e-02, // 1.900000
+ 1.81694078358287762486877880974134313873946666717529e-02, // 2.000000
+ 1.34239874155454609605531146598877967335283756256104e-02, // 2.718282
+ 1.16346596858789251560661881512714899145066738128662e-02, // 3.141593
+ };
+
+ public static final double[] GNUR_WEIBULL_CDF_01_10 = { //
+ 7.63599351831150269243053685386257711797952651977539e-02, // 0.000000
+ 2.22124383190155039180524454422993585467338562011719e-01, // 0.000010
+ 4.67917828829414239599771008215611800551414489746094e-01, // 0.100000
+ 4.75019399203212733251433519399142824113368988037109e-01, // 0.123457
+ 4.91476239432907469062428162942524068057537078857422e-01, // 0.200000
+ 5.02079925428312145996301296690944582223892211914062e-01, // 0.271828
+ 5.05508894037498435203303870366653427481651306152344e-01, // 0.300000
+ 5.07115955277963825764686589536722749471664428710938e-01, // 0.314159
+ 5.15568704992931170494330217479728162288665771484375e-01, // 0.400000
+ 5.23427039033618868302255577873438596725463867187500e-01, // 0.500000
+ 5.29881674984790551619084908452350646257400512695312e-01, // 0.600000
+ 5.35361615308103777621795416052918881177902221679688e-01, // 0.700000
+ 5.40124560432196254566861171042546629905700683593750e-01, // 0.800000
+ 5.44337595924840766947738757153274491429328918457031e-01, // 0.900000
+ 5.48115306569588400797954363952158018946647644042969e-01, // 1.000000
+ 5.51539729658985344862287547584855929017066955566406e-01, // 1.100000
+ 5.54671638850380399610173753899289295077323913574219e-01, // 1.200000
+ 5.57557321771014247069331304373918101191520690917969e-01, // 1.300000
+ 5.60232853193344815245779955148464068770408630371094e-01, // 1.400000
+ 5.62726898877477954563630646589444950222969055175781e-01, // 1.500000
+ 5.65062617878835049545216406841063871979713439941406e-01, // 1.600000
+ 5.67258990450220990098273432522546499967575073242188e-01, // 1.700000
+ 5.69331767989112891292791118758032098412513732910156e-01, // 1.800000
+ 5.71294167272651032263297565805260092020034790039062e-01, // 1.900000
+ 5.73157387426872722002713089750614017248153686523438e-01, // 2.000000
+ 5.84332020844417376892465654236730188131332397460938e-01, // 2.718282
+ 5.89617748244353534481376755138626322150230407714844e-01, // 3.141593
+ };
+
+ public static final double[] GNUR_WEIBULL_PDF_01_10 = { //
+ 7.33673382206617444753646850585937500000000000000000e+07, // 0.000000
+ 1.95393520726679525978397578001022338867187500000000e+03, // 0.000010
+ 3.35721153767048474669820734561653807759284973144531e-01, // 0.100000
+ 2.74018609307649374517978912990656681358814239501953e-01, // 0.123457
+ 1.71942902599836300314706249992013908922672271728516e-01, // 0.200000
+ 1.27730497083025279492218828636396210640668869018555e-01, // 0.271828
+ 1.16077849986715470054221555074036587029695510864258e-01, // 0.300000
+ 1.10996650714197092613133577287953812628984451293945e-01, // 0.314159
+ 8.77764877675434734838333383777353446930646896362305e-02, // 0.400000
+ 7.06409277770171650789876593989902175962924957275391e-02, // 0.500000
+ 5.91386021268343470280726137389137875288724899291992e-02, // 0.600000
+ 5.08776272124714656897026543447282165288925170898438e-02, // 0.700000
+ 4.46538827467651833202921807242091745138168334960938e-02, // 0.800000
+ 3.97946728437166968861404825474892277270555496215820e-02, // 0.900000
+ 3.58944770831502030228321586946549359709024429321289e-02, // 1.000000
+ 3.26941881616924015507841261296562151983380317687988e-02, // 1.100000
+ 3.00204524249116540268733643870291416533291339874268e-02, // 1.200000
+ 2.77528760154124205794534674396345508284866809844971e-02, // 1.300000
+ 2.58052190382604025586932294800135423429310321807861e-02, // 1.400000
+ 2.41140762238259073746426963680278277024626731872559e-02, // 1.500000
+ 2.26317820314968706774116924407280748710036277770996e-02, // 1.600000
+ 2.13218078236213498533047072669432964175939559936523e-02, // 1.700000
+ 2.01556859486728690011858589059556834399700164794922e-02, // 1.800000
+ 1.91109005040240136075180288344199652783572673797607e-02, // 1.900000
+ 1.81694078358287727792408361437992425635457038879395e-02, // 2.000000
+ 1.34239874155408032280201169328393007162958383560181e-02, // 2.718282
+ 1.16346596858781688166306622633783263154327869415283e-02, // 3.141593
+ };
+
+ public static final double[] SCIPY_WEIBULL_CDF_01_20 = { //
+ 7.14336532604261248424748487195756752043962478637695e-02, // 0.000000
+ 2.08928790931204783065666674701787997037172317504883e-01, // 0.000010
+ 4.44953851727799498672055733550223521888256072998047e-01, // 0.100000
+ 4.51868924426242546399379307331400923430919647216797e-01, // 0.123457
+ 4.67917828829414239599771008215611800551414489746094e-01, // 0.200000
+ 4.78277040424782917682478000642731785774230957031250e-01, // 0.271828
+ 4.81630099462710015156829967963858507573604583740234e-01, // 0.300000
+ 4.83202119329382395740424271934898570179939270019531e-01, // 0.314159
+ 4.91476239432907469062428162942524068057537078857422e-01, // 0.400000
+ 4.99177179518956792847461656492669135332107543945312e-01, // 0.500000
+ 5.05508894037498435203303870366653427481651306152344e-01, // 0.600000
+ 5.10889043159064359933552168513415381312370300292969e-01, // 0.700000
+ 5.15568704992931170494330217479728162288665771484375e-01, // 0.800000
+ 5.19710777811082103028184064896777272224426269531250e-01, // 0.900000
+ 5.23427039033618868302255577873438596725463867187500e-01, // 1.000000
+ 5.26797557160076923565839024377055466175079345703125e-01, // 1.100000
+ 5.29881674984790551619084908452350646257400512695312e-01, // 1.200000
+ 5.32724609600441545431692702550208196043968200683594e-01, // 1.300000
+ 5.35361615308103777621795416052918881177902221679688e-01, // 1.400000
+ 5.37820716140765320290029194438830018043518066406250e-01, // 1.500000
+ 5.40124560432196254566861171042546629905700683593750e-01, // 1.600000
+ 5.42291715817192598869667108374414965510368347167969e-01, // 1.700000
+ 5.44337595924840766947738757153274491429328918457031e-01, // 1.800000
+ 5.46275137813967970323858480696799233555793762207031e-01, // 1.900000
+ 5.48115306569588400797954363952158018946647644042969e-01, // 2.000000
+ 5.59163067520781487118597397056873887777328491210938e-01, // 2.718282
+ 5.64395683719495666608167994127143174409866333007812e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_WEIBULL_PDF_01_20 = { //
+ 6.88192507850085347890853881835937500000000000000000e+07, // 0.000000
+ 1.85401216383494602268910966813564300537109375000000e+03, // 0.000010
+ 3.26757898025421766874387685675173997879028320312500e-01, // 0.100000
+ 2.66942809682530424186808204467524774372577667236328e-01, // 0.123457
+ 1.67860576883524237334910367280826903879642486572266e-01, // 0.200000
+ 1.24873969109886198691761194368154974654316902160645e-01, // 0.271828
+ 1.13534446544550443602972222834068816155195236206055e-01, // 0.300000
+ 1.08588251220167866795129896217986242845654487609863e-01, // 0.314159
+ 8.59714512999181501573531249960069544613361358642578e-02, // 0.400000
+ 6.92640857666013964877294029065524227917194366455078e-02, // 0.500000
+ 5.80389249933577419660046814442466711625456809997559e-02, // 0.600000
+ 4.99707831949509073687920590600697323679924011230469e-02, // 0.700000
+ 4.38882438837717436808105730960960499942302703857422e-02, // 0.800000
+ 3.91364638781799556443985466103185899555683135986328e-02, // 0.900000
+ 3.53204638885085825394938296994951087981462478637695e-02, // 1.000000
+ 3.21877457163609673185256099259277107194066047668457e-02, // 1.100000
+ 2.95693010634171700445893549158427049405872821807861e-02, // 1.200000
+ 2.73477053682244612697882502061474951915442943572998e-02, // 1.300000
+ 2.54388136062357328448513271723641082644462585449219e-02, // 1.400000
+ 2.37807387894387115001570975891809212043881416320801e-02, // 1.500000
+ 2.23269413733825881906991384084903984330594539642334e-02, // 1.600000
+ 2.10417445599888272567135061308363219723105430603027e-02, // 1.700000
+ 1.98973364218583484430702412737446138635277748107910e-02, // 1.800000
+ 1.88717135986907202926943227794254198670387268066406e-02, // 1.900000
+ 1.79472385415751015114160793473274679854512214660645e-02, // 2.000000
+ 1.32834210371973356068497906790071283467113971710205e-02, // 2.718282
+ 1.15227009149735971915706755908104241825640201568604e-02, // 3.141593
+ };
+
+ public static final double[] GNUR_WEIBULL_CDF_01_20 = { //
+ 7.14336532604261248424748487195756752043962478637695e-02, // 0.000000
+ 2.08928790931204783065666674701787997037172317504883e-01, // 0.000010
+ 4.44953851727799498672055733550223521888256072998047e-01, // 0.100000
+ 4.51868924426242546399379307331400923430919647216797e-01, // 0.123457
+ 4.67917828829414239599771008215611800551414489746094e-01, // 0.200000
+ 4.78277040424794852579992721075541339814662933349609e-01, // 0.271828
+ 4.81630099462710015156829967963858507573604583740234e-01, // 0.300000
+ 4.83202119329384616186473522247979417443275451660156e-01, // 0.314159
+ 4.91476239432907469062428162942524068057537078857422e-01, // 0.400000
+ 4.99177179518956792847461656492669135332107543945312e-01, // 0.500000
+ 5.05508894037498435203303870366653427481651306152344e-01, // 0.600000
+ 5.10889043159064359933552168513415381312370300292969e-01, // 0.700000
+ 5.15568704992931170494330217479728162288665771484375e-01, // 0.800000
+ 5.19710777811082103028184064896777272224426269531250e-01, // 0.900000
+ 5.23427039033618868302255577873438596725463867187500e-01, // 1.000000
+ 5.26797557160076923565839024377055466175079345703125e-01, // 1.100000
+ 5.29881674984790551619084908452350646257400512695312e-01, // 1.200000
+ 5.32724609600441545431692702550208196043968200683594e-01, // 1.300000
+ 5.35361615308103777621795416052918881177902221679688e-01, // 1.400000
+ 5.37820716140765320290029194438830018043518066406250e-01, // 1.500000
+ 5.40124560432196254566861171042546629905700683593750e-01, // 1.600000
+ 5.42291715817192598869667108374414965510368347167969e-01, // 1.700000
+ 5.44337595924840766947738757153274491429328918457031e-01, // 1.800000
+ 5.46275137813967970323858480696799233555793762207031e-01, // 1.900000
+ 5.48115306569588400797954363952158018946647644042969e-01, // 2.000000
+ 5.59163067520794143661078123841434717178344726562500e-01, // 2.718282
+ 5.64395683719498109098822169471532106399536132812500e-01, // 3.141593
+ };
+
+ public static final double[] GNUR_WEIBULL_PDF_01_20 = { //
+ 6.88192507850085496902465820312500000000000000000000e+07, // 0.000000
+ 1.85401216383494602268910966813564300537109375000000e+03, // 0.000010
+ 3.26757898025421711363236454417346976697444915771484e-01, // 0.100000
+ 2.66942809682530313164505741951870732009410858154297e-01, // 0.123457
+ 1.67860576883524237334910367280826903879642486572266e-01, // 0.200000
+ 1.24873969109843857561159552460594568401575088500977e-01, // 0.271828
+ 1.13534446544550429725184415019612060859799385070801e-01, // 0.300000
+ 1.08588251220160983412377220247435616329312324523926e-01, // 0.314159
+ 8.59714512999181501573531249960069544613361358642578e-02, // 0.400000
+ 6.92640857666013964877294029065524227917194366455078e-02, // 0.500000
+ 5.80389249933577350271107775370182935148477554321289e-02, // 0.600000
+ 4.99707831949509143076859629672981100156903266906738e-02, // 0.700000
+ 4.38882438837717367419166691888676723465323448181152e-02, // 0.800000
+ 3.91364638781799487055046427030902123078703880310059e-02, // 0.900000
+ 3.53204638885085825394938296994951087981462478637695e-02, // 1.000000
+ 3.21877457163609673185256099259277107194066047668457e-02, // 1.100000
+ 2.95693010634171735140363068694568937644362449645996e-02, // 1.200000
+ 2.73477053682244578003412982525333063676953315734863e-02, // 1.300000
+ 2.54388136062357328448513271723641082644462585449219e-02, // 1.400000
+ 2.37807387894387115001570975891809212043881416320801e-02, // 1.500000
+ 2.23269413733825916601460903621045872569084167480469e-02, // 1.600000
+ 2.10417445599888272567135061308363219723105430603027e-02, // 1.700000
+ 1.98973364218583484430702412737446138635277748107910e-02, // 1.800000
+ 1.88717135986907202926943227794254198670387268066406e-02, // 1.900000
+ 1.79472385415751015114160793473274679854512214660645e-02, // 2.000000
+ 1.32834210371927524674262599546636920422315597534180e-02, // 2.718282
+ 1.15227009149728529951994815405669214669615030288696e-02, // 3.141593
+ };
+
+ public static final double[] SCIPY_WEIBULL_CDF_01_4 = { //
+ 8.33733718538829660094080509225022979080677032470703e-02, // 0.000000
+ 2.40649836762494045983018509105022531002759933471680e-01, // 0.000010
+ 4.99177179518956792847461656492669135332107543945312e-01, // 0.100000
+ 5.06498248113537830050745469634421169757843017578125e-01, // 0.123457
+ 5.23427039033618868302255577873438596725463867187500e-01, // 0.200000
+ 5.34307105228540524244351672678021714091300964355469e-01, // 0.271828
+ 5.37820716140765320290029194438830018043518066406250e-01, // 0.300000
+ 5.39466643360843156607131732016569003462791442871094e-01, // 0.314159
+ 5.48115306569588400797954363952158018946647644042969e-01, // 0.400000
+ 5.56142802864377228111436579638393595814704895019531e-01, // 0.500000
+ 5.62726898877477954563630646589444950222969055175781e-01, // 0.600000
+ 5.68309949920494883457422474748454988002777099609375e-01, // 0.700000
+ 5.73157387426872722002713089750614017248153686523438e-01, // 0.800000
+ 5.77441148174444141005778874387033283710479736328125e-01, // 0.900000
+ 5.81279046613597527581873691815417259931564331054688e-01, // 1.000000
+ 5.84755370118739237206284542480716481804847717285156e-01, // 1.100000
+ 5.87932517498272577682882911176420748233795166015625e-01, // 1.200000
+ 5.90857985095490256810535356635227799415588378906250e-01, // 1.300000
+ 5.93568768820695535914921947551192715764045715332031e-01, // 1.400000
+ 5.96094250977751372033708321396261453628540039062500e-01, // 1.500000
+ 5.98458157890379149890236476494465023279190063476562e-01, // 1.600000
+ 6.00679925779863399526448120013810694217681884765625e-01, // 1.700000
+ 6.02775677450659741474225938873132690787315368652344e-01, // 1.800000
+ 6.04758935771455119478900996909942477941513061523438e-01, // 1.900000
+ 6.06641154768875257019544733338989317417144775390625e-01, // 2.000000
+ 6.17913083162751508581322923419065773487091064453125e-01, // 2.718282
+ 6.23234757420644713832302841183263808488845825195312e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_WEIBULL_PDF_01_4 = { //
+ 7.97969827464829683303833007812500000000000000000000e+07, // 0.000000
+ 2.09043222444361890666186809539794921875000000000000e+03, // 0.000010
+ 3.46320428833006954683071398903848603367805480957031e-01, // 0.100000
+ 2.82305605668253523088395695594954304397106170654297e-01, // 0.123457
+ 1.76602319442542926575256956311932299286127090454102e-01, // 0.200000
+ 1.30926807720308208127235616302641574293375015258789e-01, // 0.271828
+ 1.18903693947193564439679391853132983669638633728027e-01, // 0.300000
+ 1.13663285983750791952040515297994716092944145202637e-01, // 0.314159
+ 8.97361927078755006181864928294089622795581817626953e-02, // 0.400000
+ 7.21048144026743415002655979151313658803701400756836e-02, // 0.500000
+ 6.02851905595647649671597889664553804323077201843262e-02, // 0.600000
+ 5.18057307044127585138326708147360477596521377563477e-02, // 0.700000
+ 4.54235195895719423564429462203406728804111480712891e-02, // 0.800000
+ 4.04448236551064599364480045551317743957042694091797e-02, // 0.900000
+ 3.64517761834422873712391321987524861469864845275879e-02, // 1.000000
+ 3.31775726553523511719312466539122397080063819885254e-02, // 1.100000
+ 3.04438254891350006114958404168646666221320629119873e-02, // 1.200000
+ 2.81267182882828474521641481942424434237182140350342e-02, // 1.300000
+ 2.61376080752830329545499665755414753220975399017334e-02, // 1.400000
+ 2.44113559017523976124586226887913653627038002014160e-02, // 1.500000
+ 2.28990161555940596738167869261815212666988372802734e-02, // 1.600000
+ 2.15630959198551165612034452578882337547838687896729e-02, // 1.700000
+ 2.03743883245797278991329193331694114021956920623779e-02, // 1.800000
+ 1.93098019737789824978868580274138366803526878356934e-02, // 1.900000
+ 1.83508390056730183448330251394509105011820793151855e-02, // 2.000000
+ 1.35235631786254032610239406153596064541488885879517e-02, // 2.718282
+ 1.17065775592872373112030004449479747563600540161133e-02, // 3.141593
+ };
+
+ public static final double[] GNUR_WEIBULL_CDF_01_4 = { //
+ 8.33733718538829660094080509225022979080677032470703e-02, // 0.000000
+ 2.40649836762494045983018509105022531002759933471680e-01, // 0.000010
+ 4.99177179518956792847461656492669135332107543945312e-01, // 0.100000
+ 5.06498248113537830050745469634421169757843017578125e-01, // 0.123457
+ 5.23427039033618868302255577873438596725463867187500e-01, // 0.200000
+ 5.34307105228552958742227474431274458765983581542969e-01, // 0.271828
+ 5.37820716140765320290029194438830018043518066406250e-01, // 0.300000
+ 5.39466643360845488075483444845303893089294433593750e-01, // 0.314159
+ 5.48115306569588400797954363952158018946647644042969e-01, // 0.400000
+ 5.56142802864377228111436579638393595814704895019531e-01, // 0.500000
+ 5.62726898877477954563630646589444950222969055175781e-01, // 0.600000
+ 5.68309949920494883457422474748454988002777099609375e-01, // 0.700000
+ 5.73157387426872722002713089750614017248153686523438e-01, // 0.800000
+ 5.77441148174444141005778874387033283710479736328125e-01, // 0.900000
+ 5.81279046613597527581873691815417259931564331054688e-01, // 1.000000
+ 5.84755370118739237206284542480716481804847717285156e-01, // 1.100000
+ 5.87932517498272577682882911176420748233795166015625e-01, // 1.200000
+ 5.90857985095490256810535356635227799415588378906250e-01, // 1.300000
+ 5.93568768820695535914921947551192715764045715332031e-01, // 1.400000
+ 5.96094250977751372033708321396261453628540039062500e-01, // 1.500000
+ 5.98458157890379149890236476494465023279190063476562e-01, // 1.600000
+ 6.00679925779863399526448120013810694217681884765625e-01, // 1.700000
+ 6.02775677450659741474225938873132690787315368652344e-01, // 1.800000
+ 6.04758935771455119478900996909942477941513061523438e-01, // 1.900000
+ 6.06641154768875257019544733338989317417144775390625e-01, // 2.000000
+ 6.17913083162764387168408575234934687614440917968750e-01, // 2.718282
+ 6.23234757420647156322957016527652740478515625000000e-01, // 3.141593
+ };
+
+ public static final double[] GNUR_WEIBULL_PDF_01_4 = { //
+ 7.97969827464829534292221069335937500000000000000000e+07, // 0.000000
+ 2.09043222444361890666186809539794921875000000000000e+03, // 0.000010
+ 3.46320428833006954683071398903848603367805480957031e-01, // 0.100000
+ 2.82305605668253523088395695594954304397106170654297e-01, // 0.123457
+ 1.76602319442542898819681340683018788695335388183594e-01, // 0.200000
+ 1.30926807720263271850313913091667927801609039306641e-01, // 0.271828
+ 1.18903693947193564439679391853132983669638633728027e-01, // 0.300000
+ 1.13663285983743478357865797079284675419330596923828e-01, // 0.314159
+ 8.97361927078755006181864928294089622795581817626953e-02, // 0.400000
+ 7.21048144026743276224777901006746105849742889404297e-02, // 0.500000
+ 6.02851905595647719060536928736837580800056457519531e-02, // 0.600000
+ 5.18057307044127585138326708147360477596521377563477e-02, // 0.700000
+ 4.54235195895719354175490423131122952327132225036621e-02, // 0.800000
+ 4.04448236551064599364480045551317743957042694091797e-02, // 0.900000
+ 3.64517761834422804323452282915241084992885589599609e-02, // 1.000000
+ 3.31775726553523511719312466539122397080063819885254e-02, // 1.100000
+ 3.04438254891349936726019365096362889744341373443604e-02, // 1.200000
+ 2.81267182882828474521641481942424434237182140350342e-02, // 1.300000
+ 2.61376080752830329545499665755414753220975399017334e-02, // 1.400000
+ 2.44113559017523976124586226887913653627038002014160e-02, // 1.500000
+ 2.28990161555940596738167869261815212666988372802734e-02, // 1.600000
+ 2.15630959198551200306503972115024225786328315734863e-02, // 1.700000
+ 2.03743883245797348380268232403977890498936176300049e-02, // 1.800000
+ 1.93098019737789824978868580274138366803526878356934e-02, // 1.900000
+ 1.83508390056730183448330251394509105011820793151855e-02, // 2.000000
+ 1.35235631786206692006579999087989563122391700744629e-02, // 2.718282
+ 1.17065775592864670939796667425980558618903160095215e-02, // 3.141593
+ };
+
+ public static final double[] SCIPY_WEIBULL_CDF_01_1 = { //
+ 9.51625819640404130295152640428568702191114425659180e-02, // 0.000000
+ 2.71106585889975382208660903415875509381294250488281e-01, // 0.000010
+ 5.48115306569588400797954363952158018946647644042969e-01, // 0.100000
+ 5.55694967119628291385424745385535061359405517578125e-01, // 0.123457
+ 5.73157387426872722002713089750614017248153686523438e-01, // 0.200000
+ 5.84332020844404609327682464936515316367149353027344e-01, // 0.271828
+ 5.87932517498272577682882911176420748233795166015625e-01, // 0.300000
+ 5.89617748244351203013025042309891432523727416992188e-01, // 0.314159
+ 5.98458157890379149890236476494465023279190063476562e-01, // 0.400000
+ 6.06641154768875257019544733338989317417144775390625e-01, // 0.500000
+ 6.13336400730758013466470401908736675977706909179688e-01, // 0.600000
+ 6.19001977866595609611977124586701393127441406250000e-01, // 0.700000
+ 6.23912243750147643694958787818904966115951538085938e-01, // 0.800000
+ 6.28244633588060930051710784027818590402603149414062e-01, // 0.900000
+ 6.32120558828557665975722557050175964832305908203125e-01, // 1.000000
+ 6.35626771185953010068203639093553647398948669433594e-01, // 1.100000
+ 6.38827420796338696362681730533950030803680419921875e-01, // 1.200000
+ 6.41771286235222282456902576086577028036117553710938e-01, // 1.300000
+ 6.44496325671848335758795656147412955760955810546875e-01, // 1.400000
+ 6.47032658735232191205000162881333380937576293945312e-01, // 1.500000
+ 6.49404586860663601832754920906154438853263854980469e-01, // 1.600000
+ 6.51632001805449334597142296843230724334716796875000e-01, // 1.700000
+ 6.53731392071210781757883978571044281125068664550781e-01, // 1.800000
+ 6.55716577591103022548679746250854805111885070800781e-01, // 1.900000
+ 6.57599256245357088879188722785329446196556091308594e-01, // 2.000000
+ 6.68845722847091206375580441090278327465057373046875e-01, // 2.718282
+ 6.74138343168612985678578297665808349847793579101562e-01, // 3.141593
+ };
+
+ public static final double[] SCIPY_WEIBULL_PDF_01_1 = { //
+ 9.04837418035960197448730468750000000000000000000000e+07, // 0.000000
+ 2.30496336008399066486163064837455749511718750000000e+03, // 0.000010
+ 3.58944770831502002472745971317635849118232727050781e-01, // 0.100000
+ 2.91956423650103102929165288514923304319381713867188e-01, // 0.123457
+ 1.81694078358287769425771784881362691521644592285156e-01, // 0.200000
+ 1.34239874155454602666637242691649589687585830688477e-01, // 0.271828
+ 1.21775301956540002445983361667458666488528251647949e-01, // 0.300000
+ 1.16346596858789258499555785419943276792764663696289e-01, // 0.314159
+ 9.15960646223762386952671477047260850667953491210938e-02, // 0.400000
+ 7.34033560226920733793321005578036420047283172607422e-02, // 0.500000
+ 6.12346392900829789018857240989746060222387313842773e-02, // 0.600000
+ 5.25211812394763555289500800427049398422241210937500e-02, // 0.700000
+ 4.59735675855645273268912376352091087028384208679199e-02, // 0.800000
+ 4.08732327117912602743032834951009135693311691284180e-02, // 0.900000
+ 3.67879441171442347902065250764280790463089942932129e-02, // 1.000000
+ 3.34420617455878435575478135888261022046208381652832e-02, // 1.100000
+ 3.06514941118683631460228866671968717128038406372070e-02, // 1.200000
+ 2.82885949087761413844877012024880968965590000152588e-02, // 1.300000
+ 2.62620643803951336892055223870556801557540893554688e-02, // 1.400000
+ 2.45048692989323843582916140348970657214522361755371e-02, // 1.500000
+ 2.29666813847786074886947460527153452858328819274902e-02, // 1.600000
+ 2.16089778205777807706944315668806666508316993713379e-02, // 1.700000
+ 2.04017709011452205714043373063759645447134971618652e-02, // 1.800000
+ 1.93213679270299865109450365707743912935256958007812e-02, // 1.900000
+ 1.83488015354457897898576845818752190098166465759277e-02, // 2.000000
+ 1.34637281783702208309838610489350685384124517440796e-02, // 2.718282
+ 1.16304997397552699334166703692972077988088130950928e-02, // 3.141593
+ };
+
+ public static final double[] GNUR_WEIBULL_CDF_01_1 = { //
+ 9.51625819640404130295152640428568702191114425659180e-02, // 0.000000
+ 2.71106585889975382208660903415875509381294250488281e-01, // 0.000010
+ 5.48115306569588400797954363952158018946647644042969e-01, // 0.100000
+ 5.55694967119628291385424745385535061359405517578125e-01, // 0.123457
+ 5.73157387426872722002713089750614017248153686523438e-01, // 0.200000
+ 5.84332020844417376892465654236730188131332397460938e-01, // 0.271828
+ 5.87932517498272577682882911176420748233795166015625e-01, // 0.300000
+ 5.89617748244353534481376755138626322150230407714844e-01, // 0.314159
+ 5.98458157890379149890236476494465023279190063476562e-01, // 0.400000
+ 6.06641154768875257019544733338989317417144775390625e-01, // 0.500000
+ 6.13336400730758013466470401908736675977706909179688e-01, // 0.600000
+ 6.19001977866595609611977124586701393127441406250000e-01, // 0.700000
+ 6.23912243750147643694958787818904966115951538085938e-01, // 0.800000
+ 6.28244633588060930051710784027818590402603149414062e-01, // 0.900000
+ 6.32120558828557665975722557050175964832305908203125e-01, // 1.000000
+ 6.35626771185953010068203639093553647398948669433594e-01, // 1.100000
+ 6.38827420796338696362681730533950030803680419921875e-01, // 1.200000
+ 6.41771286235222282456902576086577028036117553710938e-01, // 1.300000
+ 6.44496325671848335758795656147412955760955810546875e-01, // 1.400000
+ 6.47032658735232191205000162881333380937576293945312e-01, // 1.500000
+ 6.49404586860663601832754920906154438853263854980469e-01, // 1.600000
+ 6.51632001805449334597142296843230724334716796875000e-01, // 1.700000
+ 6.53731392071210781757883978571044281125068664550781e-01, // 1.800000
+ 6.55716577591103022548679746250854805111885070800781e-01, // 1.900000
+ 6.57599256245357088879188722785329446196556091308594e-01, // 2.000000
+ 6.68845722847103862918061167874839156866073608398438e-01, // 2.718282
+ 6.74138343168615428169232473010197281837463378906250e-01, // 3.141593
+ };
+
+ public static final double[] GNUR_WEIBULL_PDF_01_1 = { //
+ 9.04837418035960048437118530273437500000000000000000e+07, // 0.000000
+ 2.30496336008399021011427976191043853759765625000000e+03, // 0.000010
+ 3.58944770831502002472745971317635849118232727050781e-01, // 0.100000
+ 2.91956423650103102929165288514923304319381713867188e-01, // 0.123457
+ 1.81694078358287741670196169252449180930852890014648e-01, // 0.200000
+ 1.34239874155408001055178601745865307748317718505859e-01, // 0.271828
+ 1.21775301956539974690407746038545155897736549377441e-01, // 0.300000
+ 1.16346596858781695105200526541011640802025794982910e-01, // 0.314159
+ 9.15960646223762386952671477047260850667953491210938e-02, // 0.400000
+ 7.34033560226920733793321005578036420047283172607422e-02, // 0.500000
+ 6.12346392900829858407796280062029836699366569519043e-02, // 0.600000
+ 5.25211812394763624678439839499333174899220466613770e-02, // 0.700000
+ 4.59735675855645273268912376352091087028384208679199e-02, // 0.800000
+ 4.08732327117912672131971874023292912170290946960449e-02, // 0.900000
+ 3.67879441171442347902065250764280790463089942932129e-02, // 1.000000
+ 3.34420617455878435575478135888261022046208381652832e-02, // 1.100000
+ 3.06514941118683666154698386208110605366528034210205e-02, // 1.200000
+ 2.82885949087761448539346531561022857204079627990723e-02, // 1.300000
+ 2.62620643803951267503116184798273025080561637878418e-02, // 1.400000
+ 2.45048692989323808888446620812828768976032733917236e-02, // 1.500000
+ 2.29666813847786040192477940991011564619839191436768e-02, // 1.600000
+ 2.16089778205777807706944315668806666508316993713379e-02, // 1.700000
+ 2.04017709011452171019573853527617757208645343780518e-02, // 1.800000
+ 1.93213679270299865109450365707743912935256958007812e-02, // 1.900000
+ 1.83488015354457863204107326282610301859676837921143e-02, // 2.000000
+ 1.34637281783654468719779728758112469222396612167358e-02, // 2.718282
+ 1.16304997397544927772994327597189112566411495208740e-02, // 3.141593
+ };
+
+ public static final double[] P_QUANT = { //
+ 0.0001, 0.001, 0.01, 0.1, 0.25, 0.5, 0.75, 0.9, 0.99, 0.999, 0.9999 //
+ };
+
+ public static final double[] SCIPY_WEIBULL_QUANT_1_1 = { //
+ 1.00005000333358343134713963618054322068928740918636e-04, // 0.000100
+ 1.00050033358353349620395444929954464896582067012787e-03, // 0.001000
+ 1.00503358535014419156139453548348683398216962814331e-02, // 0.010000
+ 1.05360515657826309121603003404743503779172897338867e-01, // 0.100000
+ 2.87682072451780901367612841568188741803169250488281e-01, // 0.250000
+ 6.93147180559945286226763982995180413126945495605469e-01, // 0.500000
+ 1.38629436111989057245352796599036082625389099121094e+00, // 0.750000
+ 2.30258509299404590109361379290930926799774169921875e+00, // 0.900000
+ 4.60517018598809002583038818556815385818481445312500e+00, // 0.990000
+ 6.90775527898213592692400197847746312618255615234375e+00, // 0.999000
+ 9.21034037197629373849849798716604709625244140625000e+00, // 0.999900
+ };
+
+ public static final double[] GNUR_WEIBULL_QUANT_1_1 = { //
+ 1.00005000333358343134713963618054322068928740918636e-04, // 0.000100
+ 1.00050033358353349620395444929954464896582067012787e-03, // 0.001000
+ 1.00503358535014419156139453548348683398216962814331e-02, // 0.010000
+ 1.05360515657826309121603003404743503779172897338867e-01, // 0.100000
+ 2.87682072451780901367612841568188741803169250488281e-01, // 0.250000
+ 6.93147180559945286226763982995180413126945495605469e-01, // 0.500000
+ 1.38629436111989057245352796599036082625389099121094e+00, // 0.750000
+ 2.30258509299404590109361379290930926799774169921875e+00, // 0.900000
+ 4.60517018598809002583038818556815385818481445312500e+00, // 0.990000
+ 6.90775527898213592692400197847746312618255615234375e+00, // 0.999000
+ 9.21034037197629373849849798716604709625244140625000e+00, // 0.999900
+ };
+
+ public static final double[] SCIPY_WEIBULL_QUANT_2_1 = { //
+ 1.00002500135425789751231206992088118568062782287598e-02, // 0.000100
+ 3.16306865809696524660665772898937575519084930419922e-02, // 0.001000
+ 1.00251363349839001104513158679765183478593826293945e-01, // 0.010000
+ 3.24592845974501276185009146502125076949596405029297e-01, // 0.100000
+ 5.36360021302651590602295073040295392274856567382812e-01, // 0.250000
+ 8.32554611157697688206269504007650539278984069824219e-01, // 0.500000
+ 1.17741002251547466350700688053620979189872741699219e+00, // 0.750000
+ 1.51742712938514645593102159182308241724967956542969e+00, // 0.900000
+ 2.14596602628934673973049029882531613111495971679688e+00, // 0.990000
+ 2.62826088487846565300287693389691412448883056640625e+00, // 0.999000
+ 3.03485425877031111951964703621342778205871582031250e+00, // 0.999900
+ };
+
+ public static final double[] GNUR_WEIBULL_QUANT_2_1 = { //
+ 1.00002500135425789751231206992088118568062782287598e-02, // 0.000100
+ 3.16306865809696524660665772898937575519084930419922e-02, // 0.001000
+ 1.00251363349839001104513158679765183478593826293945e-01, // 0.010000
+ 3.24592845974501276185009146502125076949596405029297e-01, // 0.100000
+ 5.36360021302651590602295073040295392274856567382812e-01, // 0.250000
+ 8.32554611157697688206269504007650539278984069824219e-01, // 0.500000
+ 1.17741002251547466350700688053620979189872741699219e+00, // 0.750000
+ 1.51742712938514645593102159182308241724967956542969e+00, // 0.900000
+ 2.14596602628934673973049029882531613111495971679688e+00, // 0.990000
+ 2.62826088487846565300287693389691412448883056640625e+00, // 0.999000
+ 3.03485425877031111951964703621342778205871582031250e+00, // 0.999900
+ };
+
+ public static final double[] SCIPY_WEIBULL_QUANT_4_1 = { //
+ 1.00001250059899640665328490740648703649640083312988e-01, // 0.000100
+ 1.77850180154448117564314202354580629616975784301758e-01, // 0.001000
+ 3.16624956928286072077582957717822864651679992675781e-01, // 0.010000
+ 5.69730502934941429593607153947232291102409362792969e-01, // 0.100000
+ 7.32366043247945519567565497709438204765319824218750e-01, // 0.250000
+ 9.12444305784028575345701028709299862384796142578125e-01, // 0.500000
+ 1.08508526048208508996140153612941503524780273437500e+00, // 0.750000
+ 1.23183892185023369236773760349024087190628051757812e+00, // 0.900000
+ 1.46491161040157868988842437829589471220970153808594e+00, // 0.990000
+ 1.62119119319050875027699021302396431565284729003906e+00, // 0.999000
+ 1.74208330993965687660818275617202743887901306152344e+00, // 0.999900
+ };
+
+ public static final double[] GNUR_WEIBULL_QUANT_4_1 = { //
+ 1.00001250059899640665328490740648703649640083312988e-01, // 0.000100
+ 1.77850180154448117564314202354580629616975784301758e-01, // 0.001000
+ 3.16624956928286072077582957717822864651679992675781e-01, // 0.010000
+ 5.69730502934941429593607153947232291102409362792969e-01, // 0.100000
+ 7.32366043247945519567565497709438204765319824218750e-01, // 0.250000
+ 9.12444305784028575345701028709299862384796142578125e-01, // 0.500000
+ 1.08508526048208508996140153612941503524780273437500e+00, // 0.750000
+ 1.23183892185023369236773760349024087190628051757812e+00, // 0.900000
+ 1.46491161040157868988842437829589471220970153808594e+00, // 0.990000
+ 1.62119119319050875027699021302396431565284729003906e+00, // 0.999000
+ 1.74208330993965687660818275617202743887901306152344e+00, // 0.999900
+ };
+
+ public static final double[] SCIPY_WEIBULL_QUANT_4_10 = { //
+ 1.00001250059899637889770929177757352590560913085938e+00, // 0.000100
+ 1.77850180154448112013199079228797927498817443847656e+00, // 0.001000
+ 3.16624956928286049873122465214692056179046630859375e+00, // 0.010000
+ 5.69730502934941451798067646450363099575042724609375e+00, // 0.100000
+ 7.32366043247945519567565497709438204765319824218750e+00, // 0.250000
+ 9.12444305784028486527859058696776628494262695312500e+00, // 0.500000
+ 1.08508526048208508996140153612941503524780273437500e+01, // 0.750000
+ 1.23183892185023360354989563347771763801574707031250e+01, // 0.900000
+ 1.46491161040157873429734536330215632915496826171875e+01, // 0.990000
+ 1.62119119319050888350375316804274916648864746093750e+01, // 0.999000
+ 1.74208330993965674338141980115324258804321289062500e+01, // 0.999900
+ };
+
+ public static final double[] GNUR_WEIBULL_QUANT_4_10 = { //
+ 1.00001250059899637889770929177757352590560913085938e+00, // 0.000100
+ 1.77850180154448112013199079228797927498817443847656e+00, // 0.001000
+ 3.16624956928286049873122465214692056179046630859375e+00, // 0.010000
+ 5.69730502934941451798067646450363099575042724609375e+00, // 0.100000
+ 7.32366043247945519567565497709438204765319824218750e+00, // 0.250000
+ 9.12444305784028486527859058696776628494262695312500e+00, // 0.500000
+ 1.08508526048208508996140153612941503524780273437500e+01, // 0.750000
+ 1.23183892185023360354989563347771763801574707031250e+01, // 0.900000
+ 1.46491161040157873429734536330215632915496826171875e+01, // 0.990000
+ 1.62119119319050888350375316804274916648864746093750e+01, // 0.999000
+ 1.74208330993965674338141980115324258804321289062500e+01, // 0.999900
+ };
+
+ public static final double[] SCIPY_WEIBULL_QUANT_01_10 = { //
+ 1.00050014586584021700243769737484031845767568464672e-39, // 0.000100
+ 1.00501461589481204170765583646174510341434104691366e-29, // 0.001000
+ 1.05149145760085306110809830513112699455704405376921e-19, // 0.010000
+ 1.68569451981823333734044073758343712521323709552235e-09, // 0.100000
+ 3.88264771194455187157575093426231660487246699631214e-05, // 0.250000
+ 2.56008632895631083048471055008121766149997711181641e-01, // 0.500000
+ 2.62152840085126229041634360328316688537597656250000e+02, // 0.750000
+ 4.18944879802952418685890734195709228515625000000000e+04, // 0.900000
+ 4.28999556918221637606620788574218750000000000000000e+07, // 0.990000
+ 2.47382762074844741821289062500000000000000000000000e+09, // 0.999000
+ 4.39295546284313201904296875000000000000000000000000e+10, // 0.999900
+ };
+
+ public static final double[] GNUR_WEIBULL_QUANT_01_10 = { //
+ 1.00050014586584021700243769737484031845767568464672e-39, // 0.000100
+ 1.00501461589481204170765583646174510341434104691366e-29, // 0.001000
+ 1.05149145760085306110809830513112699455704405376921e-19, // 0.010000
+ 1.68569451981823333734044073758343712521323709552235e-09, // 0.100000
+ 3.88264771194455187157575093426231660487246699631214e-05, // 0.250000
+ 2.56008632895631083048471055008121766149997711181641e-01, // 0.500000
+ 2.62152840085126229041634360328316688537597656250000e+02, // 0.750000
+ 4.18944879802952418685890734195709228515625000000000e+04, // 0.900000
+ 4.28999556918221637606620788574218750000000000000000e+07, // 0.990000
+ 2.47382762074844741821289062500000000000000000000000e+09, // 0.999000
+ 4.39295546284313201904296875000000000000000000000000e+10, // 0.999900
+ };
+
+ public static final double[] SCIPY_WEIBULL_QUANT_01_20 = { //
+ 2.00100029173168043400487539474968063691535136929345e-39, // 0.000100
+ 2.01002923178962408341531167292349020682868209382732e-29, // 0.001000
+ 2.10298291520170612221619661026225398911408810753842e-19, // 0.010000
+ 3.37138903963646667468088147516687425042647419104469e-09, // 0.100000
+ 7.76529542388910374315150186852463320974493399262428e-05, // 0.250000
+ 5.12017265791262166096942110016243532299995422363281e-01, // 0.500000
+ 5.24305680170252458083268720656633377075195312500000e+02, // 0.750000
+ 8.37889759605904837371781468391418457031250000000000e+04, // 0.900000
+ 8.57999113836443275213241577148437500000000000000000e+07, // 0.990000
+ 4.94765524149689483642578125000000000000000000000000e+09, // 0.999000
+ 8.78591092568626403808593750000000000000000000000000e+10, // 0.999900
+ };
+
+ public static final double[] GNUR_WEIBULL_QUANT_01_20 = { //
+ 2.00100029173168043400487539474968063691535136929345e-39, // 0.000100
+ 2.01002923178962408341531167292349020682868209382732e-29, // 0.001000
+ 2.10298291520170612221619661026225398911408810753842e-19, // 0.010000
+ 3.37138903963646667468088147516687425042647419104469e-09, // 0.100000
+ 7.76529542388910374315150186852463320974493399262428e-05, // 0.250000
+ 5.12017265791262166096942110016243532299995422363281e-01, // 0.500000
+ 5.24305680170252458083268720656633377075195312500000e+02, // 0.750000
+ 8.37889759605904837371781468391418457031250000000000e+04, // 0.900000
+ 8.57999113836443275213241577148437500000000000000000e+07, // 0.990000
+ 4.94765524149689483642578125000000000000000000000000e+09, // 0.999000
+ 8.78591092568626403808593750000000000000000000000000e+10, // 0.999900
+ };
+
+ public static final double[] SCIPY_WEIBULL_QUANT_01_4 = { //
+ 4.00200058346336103114236248946247444158805547000059e-40, // 0.000100
+ 4.02005846357924816683062334584698041365736418765464e-30, // 0.001000
+ 4.20596583040341236480301474472674879422679762663480e-20, // 0.010000
+ 6.74277807927293355615691608859066721870512139958009e-10, // 0.100000
+ 1.55305908477782068086766459336089951648318674415350e-05, // 0.250000
+ 1.02403453158252430443830860440357355400919914245605e-01, // 0.500000
+ 1.04861136034050488774482801090925931930541992187500e+02, // 0.750000
+ 1.67577951921180974750313907861709594726562500000000e+04, // 0.900000
+ 1.71599822767288647592067718505859375000000000000000e+07, // 0.990000
+ 9.89531048299378991127014160156250000000000000000000e+08, // 0.999000
+ 1.75718218513725280761718750000000000000000000000000e+10, // 0.999900
+ };
+
+ public static final double[] GNUR_WEIBULL_QUANT_01_4 = { //
+ 4.00200058346336103114236248946247444158805547000059e-40, // 0.000100
+ 4.02005846357924816683062334584698041365736418765464e-30, // 0.001000
+ 4.20596583040341236480301474472674879422679762663480e-20, // 0.010000
+ 6.74277807927293355615691608859066721870512139958009e-10, // 0.100000
+ 1.55305908477782068086766459336089951648318674415350e-05, // 0.250000
+ 1.02403453158252430443830860440357355400919914245605e-01, // 0.500000
+ 1.04861136034050488774482801090925931930541992187500e+02, // 0.750000
+ 1.67577951921180974750313907861709594726562500000000e+04, // 0.900000
+ 1.71599822767288647592067718505859375000000000000000e+07, // 0.990000
+ 9.89531048299378991127014160156250000000000000000000e+08, // 0.999000
+ 1.75718218513725280761718750000000000000000000000000e+10, // 0.999900
+ };
+
+ public static final double[] SCIPY_WEIBULL_QUANT_01_1 = { //
+ 1.00050014586584025778559062236561861039701386750015e-40, // 0.000100
+ 1.00501461589481204170765583646174510341434104691366e-30, // 0.001000
+ 1.05149145760085309120075368618168719855669940665870e-20, // 0.010000
+ 1.68569451981823338903922902214766680467628034989502e-10, // 0.100000
+ 3.88264771194455170216916148340224879120796686038375e-06, // 0.250000
+ 2.56008632895631076109577151100893388502299785614014e-02, // 0.500000
+ 2.62152840085126221936207002727314829826354980468750e+01, // 0.750000
+ 4.18944879802952436875784769654273986816406250000000e+03, // 0.900000
+ 4.28999556918221618980169296264648437500000000000000e+06, // 0.990000
+ 2.47382762074844747781753540039062500000000000000000e+08, // 0.999000
+ 4.39295546284313201904296875000000000000000000000000e+09, // 0.999900
+ };
+
+ public static final double[] GNUR_WEIBULL_QUANT_01_1 = { //
+ 1.00050014586584025778559062236561861039701386750015e-40, // 0.000100
+ 1.00501461589481204170765583646174510341434104691366e-30, // 0.001000
+ 1.05149145760085309120075368618168719855669940665870e-20, // 0.010000
+ 1.68569451981823338903922902214766680467628034989502e-10, // 0.100000
+ 3.88264771194455170216916148340224879120796686038375e-06, // 0.250000
+ 2.56008632895631076109577151100893388502299785614014e-02, // 0.500000
+ 2.62152840085126221936207002727314829826354980468750e+01, // 0.750000
+ 4.18944879802952436875784769654273986816406250000000e+03, // 0.900000
+ 4.28999556918221618980169296264648437500000000000000e+06, // 0.990000
+ 2.47382762074844747781753540039062500000000000000000e+08, // 0.999000
+ 4.39295546284313201904296875000000000000000000000000e+09, // 0.999900
+ };
+
+ @Test
+ public void testPDF() {
+ checkPDF(new WeibullDistribution(1., 1.), P_CDFPDF, SCIPY_WEIBULL_PDF_1_1, 1e-13);
+ checkPDF(new WeibullDistribution(2., 1.), P_CDFPDF, SCIPY_WEIBULL_PDF_2_1, 1e-12);
+ checkPDF(new WeibullDistribution(4., 1.), P_CDFPDF, SCIPY_WEIBULL_PDF_4_1, 1e-11);
+ checkPDF(new WeibullDistribution(4., 10.), P_CDFPDF, SCIPY_WEIBULL_PDF_4_10, 1e-11);
+ checkPDF(new WeibullDistribution(.1, 1.), P_CDFPDF, SCIPY_WEIBULL_PDF_01_1, 1e-12);
+ checkPDF(new WeibullDistribution(.1, 4.), P_CDFPDF, SCIPY_WEIBULL_PDF_01_4, 1e-12);
+ checkPDF(new WeibullDistribution(.1, 10.), P_CDFPDF, SCIPY_WEIBULL_PDF_01_10, 1e-12);
+ checkPDF(new WeibullDistribution(.1, 20.), P_CDFPDF, SCIPY_WEIBULL_PDF_01_20, 1e-12);
+
+ checkPDF(new WeibullDistribution(1., 1.), P_CDFPDF, GNUR_WEIBULL_PDF_1_1, 1e-15);
+ checkPDF(new WeibullDistribution(2., 1.), P_CDFPDF, GNUR_WEIBULL_PDF_2_1, 1e-15);
+ checkPDF(new WeibullDistribution(4., 1.), P_CDFPDF, GNUR_WEIBULL_PDF_4_1, 1e-14);
+ checkPDF(new WeibullDistribution(4., 10.), P_CDFPDF, GNUR_WEIBULL_PDF_4_10, 1e-15);
+ checkPDF(new WeibullDistribution(.1, 1.), P_CDFPDF, GNUR_WEIBULL_PDF_01_1, 1e-15);
+ checkPDF(new WeibullDistribution(.1, 4.), P_CDFPDF, GNUR_WEIBULL_PDF_01_4, 1e-15);
+ checkPDF(new WeibullDistribution(.1, 10.), P_CDFPDF, GNUR_WEIBULL_PDF_01_10, 1e-15);
+ checkPDF(new WeibullDistribution(.1, 20.), P_CDFPDF, GNUR_WEIBULL_PDF_01_20, 1e-15);
+ }
+
+ @Test
+ public void testCDF() {
+ checkCDF(new WeibullDistribution(1., 1.), P_CDFPDF, SCIPY_WEIBULL_CDF_1_1, 1e-12);
+ checkCDF(new WeibullDistribution(2., 1.), P_CDFPDF, SCIPY_WEIBULL_CDF_2_1, 1e-12);
+ checkCDF(new WeibullDistribution(4., 1.), P_CDFPDF, SCIPY_WEIBULL_CDF_4_1, 1e-11);
+ checkCDF(new WeibullDistribution(4., 10.), P_CDFPDF, SCIPY_WEIBULL_CDF_4_10, 1e-11);
+ checkCDF(new WeibullDistribution(.1, 1.), P_CDFPDF, SCIPY_WEIBULL_CDF_01_1, 1e-13);
+ checkCDF(new WeibullDistribution(.1, 4.), P_CDFPDF, SCIPY_WEIBULL_CDF_01_4, 1e-13);
+ checkCDF(new WeibullDistribution(.1, 10.), P_CDFPDF, SCIPY_WEIBULL_CDF_01_10, 1e-13);
+ checkCDF(new WeibullDistribution(.1, 20.), P_CDFPDF, SCIPY_WEIBULL_CDF_01_20, 1e-13);
+
+ checkCDF(new WeibullDistribution(1., 1.), P_CDFPDF, GNUR_WEIBULL_CDF_1_1, 1e-14);
+ checkCDF(new WeibullDistribution(2., 1.), P_CDFPDF, GNUR_WEIBULL_CDF_2_1, 1e-14);
+ checkCDF(new WeibullDistribution(4., 1.), P_CDFPDF, GNUR_WEIBULL_CDF_4_1, 1e-13);
+ checkCDF(new WeibullDistribution(4., 10.), P_CDFPDF, GNUR_WEIBULL_CDF_4_10, 1e-13);
+ checkCDF(new WeibullDistribution(.1, 1.), P_CDFPDF, GNUR_WEIBULL_CDF_01_1, 1e-15);
+ checkCDF(new WeibullDistribution(.1, 4.), P_CDFPDF, GNUR_WEIBULL_CDF_01_4, 1e-15);
+ checkCDF(new WeibullDistribution(.1, 10.), P_CDFPDF, GNUR_WEIBULL_CDF_01_10, 1e-15);
+ checkCDF(new WeibullDistribution(.1, 20.), P_CDFPDF, GNUR_WEIBULL_CDF_01_20, 1e-15);
+ }
+
+ @Test
+ public void testQuantile() {
+ checkQuantile(new WeibullDistribution(1., 1.), P_QUANT, SCIPY_WEIBULL_QUANT_1_1, 1e-15);
+ checkQuantile(new WeibullDistribution(2., 1.), P_QUANT, SCIPY_WEIBULL_QUANT_2_1, 1e-15);
+ checkQuantile(new WeibullDistribution(4., 1.), P_QUANT, SCIPY_WEIBULL_QUANT_4_1, 1e-13);
+ checkQuantile(new WeibullDistribution(4., 10.), P_QUANT, SCIPY_WEIBULL_QUANT_4_10, 1e-13);
+ checkQuantile(new WeibullDistribution(.1, 1.), P_QUANT, SCIPY_WEIBULL_QUANT_01_1, 1e-14);
+ checkQuantile(new WeibullDistribution(.1, 4.), P_QUANT, SCIPY_WEIBULL_QUANT_01_4, 1e-13);
+ checkQuantile(new WeibullDistribution(.1, 10.), P_QUANT, SCIPY_WEIBULL_QUANT_01_10, 1e-13);
+ checkQuantile(new WeibullDistribution(.1, 20.), P_QUANT, SCIPY_WEIBULL_QUANT_01_20, 1e-13);
+
+ checkQuantile(new WeibullDistribution(1., 1.), P_QUANT, GNUR_WEIBULL_QUANT_1_1, 1e-15);
+ checkQuantile(new WeibullDistribution(2., 1.), P_QUANT, GNUR_WEIBULL_QUANT_2_1, 1e-15);
+ checkQuantile(new WeibullDistribution(4., 1.), P_QUANT, GNUR_WEIBULL_QUANT_4_1, 1e-13);
+ checkQuantile(new WeibullDistribution(4., 10.), P_QUANT, GNUR_WEIBULL_QUANT_4_10, 1e-13);
+ checkQuantile(new WeibullDistribution(.1, 1.), P_QUANT, GNUR_WEIBULL_QUANT_01_1, 1e-13);
+ checkQuantile(new WeibullDistribution(.1, 4.), P_QUANT, GNUR_WEIBULL_QUANT_01_4, 1e-13);
+ checkQuantile(new WeibullDistribution(.1, 10.), P_QUANT, GNUR_WEIBULL_QUANT_01_10, 1e-13);
+ checkQuantile(new WeibullDistribution(.1, 20.), P_QUANT, GNUR_WEIBULL_QUANT_01_20, 1e-13);
+ }
+}
diff --git a/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestDoubleObjHeaps.java b/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestDoubleObjectHeaps.java
index b37fc0b4..e75b8094 100644
--- a/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestDoubleObjHeaps.java
+++ b/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestDoubleObjectHeaps.java
@@ -36,11 +36,11 @@ import de.lmu.ifi.dbs.elki.JUnit4Test;
*
* @author Erich Schubert
*/
-public class TestDoubleObjHeaps implements JUnit4Test {
+public class TestDoubleObjectHeaps implements JUnit4Test {
@Test
public void testDoubleObjMinHeap() {
Random r = new Random();
- DoubleObjMinHeap<Double> heap = new DoubleObjMinHeap<Double>();
+ DoubleObjectMinHeap<Double> heap = new DoubleObjectMinHeap<>();
for(int i = 0; i < 1000; i++) {
double key = r.nextDouble();
heap.add(key, key);
@@ -66,7 +66,7 @@ public class TestDoubleObjHeaps implements JUnit4Test {
@Test
public void testDoubleObjMaxHeap() {
Random r = new Random();
- DoubleObjMaxHeap<Double> heap = new DoubleObjMaxHeap<Double>();
+ DoubleObjectMaxHeap<Double> heap = new DoubleObjectMaxHeap<>();
for(int i = 0; i < 1000; i++) {
double key = r.nextDouble();
heap.add(key, key);
diff --git a/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestHeap.java b/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestHeap.java
index 33ebdfae..66e06a9f 100644
--- a/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestHeap.java
+++ b/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestHeap.java
@@ -26,13 +26,10 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
-import java.util.Collections;
import java.util.Random;
import org.junit.Test;
-import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.Heap;
-
/**
* Test the in-memory heap class.
*
@@ -49,8 +46,8 @@ public class TestHeap {
Integer[] data = { 5, 3, 4, 2, 7, 1, 9, 8, 10, 6 };
Integer[] asc = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
Integer[] desc = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
- Heap<Integer> hasc = new Heap<Integer>(null);
- Heap<Integer> hdesc = new Heap<Integer>(Collections.reverseOrder());
+ ComparableMinHeap<Integer> hasc = new ComparableMinHeap<>();
+ ComparableMaxHeap<Integer> hdesc = new ComparableMaxHeap<>();
for(Integer i : data) {
for(int j = 0; j < dup; j++) {
hasc.add(i);
@@ -176,8 +173,8 @@ public class TestHeap {
public void testHeapRandomInt() {
int size = 10000;
Random r = new Random(123L);
- Heap<Integer> hasc = new Heap<Integer>();
- Heap<Integer> hdesc = new Heap<Integer>(Collections.reverseOrder());
+ ComparableMinHeap<Integer> hasc = new ComparableMinHeap<>();
+ ComparableMaxHeap<Integer> hdesc = new ComparableMaxHeap<>();
for(int i = 0; i < size; i++) {
int in = r.nextInt();
hasc.add(in);
diff --git a/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestHeapPerformance.java b/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestHeapPerformance.java
index 084a3761..f80fbec5 100644
--- a/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestHeapPerformance.java
+++ b/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestHeapPerformance.java
@@ -42,16 +42,18 @@ import org.junit.Test;
* @author Erich Schubert
*/
public class TestHeapPerformance {
- final private int queueSize = 100000;
+ final private int queueSize = 200000;
- final private int iterations = 20;
+ final private int preiterations = 20;
+
+ final private int iterations = 200;
final private long seed = 123456L;
@Test
public void testRuntime() throws Exception {
// prepare the data set
- final List<Integer> elements = new ArrayList<Integer>(queueSize);
+ final List<Integer> elements = new ArrayList<>(queueSize);
{
final Random random = new Random(seed);
for(int i = 0; i < queueSize; i++) {
@@ -62,39 +64,40 @@ public class TestHeapPerformance {
// Pretest, to trigger hotspot compiler, hopefully.
{
- for(int j = 0; j < iterations; j++) {
- Heap<Integer> pq = new Heap<Integer>();
+ for(int j = 0; j < preiterations; j++) {
+ ComparableMinHeap<Integer> pq = new ComparableMinHeap<>();
testHeap(elements, pq);
}
- for(int j = 0; j < iterations; j++) {
- PriorityQueue<Integer> pq = new PriorityQueue<Integer>(); // 11,
+ for(int j = 0; j < preiterations; j++) {
+ PriorityQueue<Integer> pq = new PriorityQueue<>();
testQueue(elements, pq);
}
}
- long hstart = System.nanoTime();
+ long pqstart = System.nanoTime();
{
for(int j = 0; j < iterations; j++) {
- Heap<Integer> pq = new Heap<Integer>();
- testHeap(elements, pq);
+ PriorityQueue<Integer> pq = new PriorityQueue<>();
+ testQueue(elements, pq);
}
}
- long htime = System.nanoTime() - hstart;
+ long pqtime = System.nanoTime() - pqstart;
- long pqstart = System.nanoTime();
+ long hstart = System.nanoTime();
{
for(int j = 0; j < iterations; j++) {
- PriorityQueue<Integer> pq = new PriorityQueue<Integer>(); // 11
- testQueue(elements, pq);
+ ComparableMinHeap<Integer> pq = new ComparableMinHeap<>();
+ testHeap(elements, pq);
}
}
- long pqtime = System.nanoTime() - pqstart;
+ long htime = System.nanoTime() - hstart;
+
System.err.println("Heap performance test: us: " + htime*1E-9 + " java: " + pqtime*1E-9);
assertTrue("Heap performance regression - run test individually, since the hotspot optimizations may make the difference! " + htime + " >>= " + pqtime, htime < 1.05 * pqtime);
// 1.05 allows some difference in measuring
}
- private void testHeap(final List<Integer> elements, Heap<Integer> pq) {
+ private void testHeap(final List<Integer> elements, ComparableMinHeap<Integer> pq) {
// Insert all
for(int i = 0; i < elements.size(); i++) {
pq.add(elements.get(i));
diff --git a/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestIntegerHeap.java b/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestIntegerHeap.java
new file mode 100644
index 00000000..93c83dff
--- /dev/null
+++ b/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestIntegerHeap.java
@@ -0,0 +1,232 @@
+package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2012
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Random;
+
+import org.junit.Test;
+
+/**
+ * Test the in-memory heap class.
+ *
+ * @author Erich Schubert
+ */
+public class TestIntegerHeap {
+ /**
+ * Puts 10 integers into both an ascending and a descending heap and verifies
+ * they come out in sequence.
+ */
+ @Test
+ public void testHeap() {
+ int dup = 2;
+ int[] data = { 5, 3, 4, 2, 7, 1, 9, 8, 10, 6 };
+ int[] asc = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+ int[] desc = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
+ IntegerMinHeap hasc = new IntegerMinHeap();
+ IntegerMaxHeap hdesc = new IntegerMaxHeap();
+ for(Integer i : data) {
+ for(int j = 0; j < dup; j++) {
+ hasc.add(i);
+ hdesc.add(i);
+ }
+ }
+ // Empty
+ for(int i = 0; i < asc.length; i++) {
+ for(int j = 0; j < dup; j++) {
+ final int gota = hasc.poll();
+ assertEquals("Objects sorted incorrectly at ascending position " + i, asc[i], gota);
+ final int gotd = hdesc.poll();
+ assertEquals("Objects sorted incorrectly at descending position " + i, desc[i], gotd);
+ }
+ }
+ // Refill
+ for(int i : data) {
+ for(int j = 0; j < dup; j++) {
+ hasc.add(i);
+ hdesc.add(i);
+ }
+ }
+ // Empty halfway
+ for(int i = 0; i < 5; i++) {
+ for(int j = 0; j < dup; j++) {
+ final int gota = hasc.poll();
+ assertEquals("Objects sorted incorrectly at ascending position " + i, asc[i], gota);
+ final int gotd = hdesc.poll();
+ assertEquals("Objects sorted incorrectly at descending position " + i, desc[i], gotd);
+ }
+ }
+ // Re-add
+ for(int i = 0; i < 5; i++) {
+ for(int j = 0; j < dup; j++) {
+ hasc.add(asc[i]);
+ hdesc.add(desc[i]);
+ }
+ }
+ // Empty again
+ for(int i = 0; i < asc.length; i++) {
+ for(int j = 0; j < dup; j++) {
+ final int gota = hasc.poll();
+ assertEquals("Objects sorted incorrectly at ascending position " + i, asc[i], gota);
+ final int gotd = hdesc.poll();
+ assertEquals("Objects sorted incorrectly at descending position " + i, desc[i], gotd);
+ }
+ }
+ // Sequential insert
+ for(int i : asc) {
+ for(int j = 0; j < dup; j++) {
+ hasc.add(i);
+ hdesc.add(i);
+ }
+ }
+ // Empty halfway
+ for(int i = 0; i < 5; i++) {
+ for(int j = 0; j < dup; j++) {
+ final int gota = hasc.poll();
+ assertEquals("Objects sorted incorrectly at ascending position " + i, asc[i], gota);
+ final int gotd = hdesc.poll();
+ assertEquals("Objects sorted incorrectly at descending position " + i, desc[i], gotd);
+ }
+ }
+ // Re-add
+ for(int i = 0; i < 5; i++) {
+ for(int j = 0; j < dup; j++) {
+ hasc.add(asc[i]);
+ hdesc.add(desc[i]);
+ }
+ }
+ // Empty again
+ for(int i = 0; i < asc.length; i++) {
+ for(int j = 0; j < dup; j++) {
+ final int gota = hasc.poll();
+ assertEquals("Objects sorted incorrectly at ascending position " + i, asc[i], gota);
+ final int gotd = hdesc.poll();
+ assertEquals("Objects sorted incorrectly at descending position " + i, desc[i], gotd);
+ }
+ }
+
+ // Bonus: Sequential insert lower part only
+ for(int i = 0; i < asc.length >> 1; i++) {
+ for(int j = 0; j < dup << 1; j++) {
+ hasc.add(asc[i]);
+ hdesc.add(desc[i]);
+ }
+ }
+ // Empty halfway
+ for(int i = 0; i < 3; i++) {
+ for(int j = 0; j < dup << 1; j++) {
+ final int gota = hasc.poll();
+ assertEquals("Objects sorted incorrectly at ascending position " + i, asc[i], gota);
+ final int gotd = hdesc.poll();
+ assertEquals("Objects sorted incorrectly at descending position " + i, desc[i], gotd);
+ }
+ }
+ // Add upper half
+ for(int i = asc.length >> 1; i < asc.length; i++) {
+ for(int j = 0; j < dup; j++) {
+ hasc.add(asc[i]);
+ hdesc.add(desc[i]);
+ }
+ }
+ //System.err.println(hasc.toString() + " " + hasc.validSize);
+ // Empty again
+ for(int i = 3; i < asc.length; i++) {
+ int f = (i < (asc.length >> 1)) ? 2 : 1;
+ for(int j = 0; j < dup * f; j++) {
+ final int gota = hasc.poll();
+ //System.err.println(hasc.toString() + " " + hasc.validSize);
+ assertEquals("Objects sorted incorrectly at ascending position " + i, asc[i], gota);
+ final int gotd = hdesc.poll();
+ assertEquals("Objects sorted incorrectly at descending position " + i, desc[i], gotd);
+ }
+ }
+ }
+
+ /**
+ * Puts 10 integers into both an ascending and a descending heap and verifies
+ * they come out in sequence.
+ */
+ @Test
+ public void testHeapRandomInt() {
+ int size = 10000;
+ Random r = new Random(123L);
+ ComparableMinHeap<Integer> hasc = new ComparableMinHeap<>();
+ ComparableMaxHeap<Integer> hdesc = new ComparableMaxHeap<>();
+ for(int i = 0; i < size; i++) {
+ int in = r.nextInt();
+ hasc.add(in);
+ hdesc.add(in);
+ }
+ int last = Integer.MIN_VALUE;
+ for(int i = 0; i < size; i++) {
+ final Integer gota = hasc.poll();
+ assertTrue("Objects sorted incorrectly at ascending position " + i, gota >= last);
+ last = gota;
+ }
+ last = Integer.MAX_VALUE;
+ for(int i = 0; i < size; i++) {
+ final Integer gotd = hdesc.poll();
+ assertTrue("Objects sorted incorrectly at descending position " + i, gotd <= last);
+ last = gotd;
+ }
+ // Rerun, but only halfway down
+ for(int i = 0; i < size; i++) {
+ int in = r.nextInt();
+ hasc.add(in);
+ hdesc.add(in);
+ }
+ last = Integer.MIN_VALUE;
+ for(int i = 0; i < size >>> 1; i++) {
+ final Integer gota = hasc.poll();
+ assertTrue("Objects sorted incorrectly at ascending position " + i, gota >= last);
+ last = gota;
+ }
+ last = Integer.MAX_VALUE;
+ for(int i = 0; i < size >>> 1; i++) {
+ final Integer gotd = hdesc.poll();
+ assertTrue("Objects sorted incorrectly at descending position " + i, gotd <= last);
+ last = gotd;
+ }
+ // Refill:
+ for(int i = size >>> 1; i < size; i++) {
+ int in = r.nextInt();
+ hasc.add(in);
+ hdesc.add(in);
+ }
+ last = Integer.MIN_VALUE;
+ for(int i = 0; i < size; i++) {
+ final Integer gota = hasc.poll();
+ assertTrue("Objects sorted incorrectly at ascending position " + i, gota >= last);
+ last = gota;
+ }
+ last = Integer.MAX_VALUE;
+ for(int i = 0; i < size; i++) {
+ final Integer gotd = hdesc.poll();
+ assertTrue("Objects sorted incorrectly at descending position " + i, gotd <= last);
+ last = gotd;
+ }
+ }
+} \ No newline at end of file
diff --git a/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestIntegerMinHeapPerformance.java b/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestIntegerMinHeapPerformance.java
new file mode 100644
index 00000000..9f4cf08e
--- /dev/null
+++ b/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestIntegerMinHeapPerformance.java
@@ -0,0 +1,124 @@
+package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2012
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.PriorityQueue;
+import java.util.Queue;
+import java.util.Random;
+
+import org.junit.Test;
+
+/**
+ * Unit test to ensure that our heap is not significantly worse than SUN javas
+ * regular PriorityQueue.
+ *
+ * @author Erich Schubert
+ */
+public class TestIntegerMinHeapPerformance {
+ final private int queueSize = 100000;
+
+ final private int iterations = 20;
+
+ final private long seed = 123456L;
+
+ @Test
+ public void testRuntime() throws Exception {
+ // prepare the data set
+ final List<Integer> elements = new ArrayList<>(queueSize);
+ {
+ final Random random = new Random(seed);
+ for(int i = 0; i < queueSize; i++) {
+ elements.add(i);
+ }
+ Collections.shuffle(elements, random);
+ }
+
+ // Pretest, to trigger hotspot compiler, hopefully.
+ {
+ for(int j = 0; j < iterations; j++) {
+ IntegerMinHeap pq = new IntegerMinHeap();
+ testHeap(elements, pq);
+ }
+ for(int j = 0; j < iterations; j++) {
+ PriorityQueue<Integer> pq = new PriorityQueue<>(); // 11,
+ testQueue(elements, pq);
+ }
+ }
+
+ long hstart = System.nanoTime();
+ {
+ for(int j = 0; j < iterations; j++) {
+ IntegerMinHeap pq = new IntegerMinHeap();
+ testHeap(elements, pq);
+ }
+ }
+ long htime = System.nanoTime() - hstart;
+
+ long pqstart = System.nanoTime();
+ {
+ for(int j = 0; j < iterations; j++) {
+ PriorityQueue<Integer> pq = new PriorityQueue<>(); // 11
+ testQueue(elements, pq);
+ }
+ }
+ long pqtime = System.nanoTime() - pqstart;
+ System.err.println("Heap performance test: us: " + htime*1E-9 + " java: " + pqtime*1E-9);
+ assertTrue("Heap performance regression - run test individually, since the hotspot optimizations may make the difference! " + htime + " >>= " + pqtime, htime < 1.05 * pqtime);
+ // 1.05 allows some difference in measuring
+ }
+
+ private void testHeap(final List<Integer> elements, IntegerMinHeap pq) {
+ // Insert all
+ for(int i = 0; i < elements.size(); i++) {
+ pq.add(elements.get(i));
+ }
+ // Poll first half.
+ for(int i = 0; i < elements.size() >> 1; i++) {
+ assertEquals(pq.poll(), i);
+ // assertEquals((int) pq.poll(), queueSize - 1 - i);
+ }
+ assertTrue("Heap not half-empty?", pq.size() == (elements.size() >> 1));
+ pq.clear();
+ }
+
+ private void testQueue(final List<Integer> elements, Queue<Integer> pq) {
+ // Insert all
+ for(int i = 0; i < elements.size(); i++) {
+ pq.add(elements.get(i));
+ }
+ // Poll first half.
+ for(int i = 0; i < elements.size() >> 1; i++) {
+ assertEquals((int) pq.poll(), i);
+ // assertEquals((int) pq.poll(), queueSize - 1 - i);
+ }
+ assertTrue("Heap not half-empty?", pq.size() == (elements.size() >> 1));
+ pq.clear();
+ }
+} \ No newline at end of file
diff --git a/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestTiedTopBoundedHeap.java b/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestTiedTopBoundedHeap.java
index 8059a873..f0c96231 100644
--- a/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestTiedTopBoundedHeap.java
+++ b/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestTiedTopBoundedHeap.java
@@ -46,8 +46,8 @@ public class TestTiedTopBoundedHeap {
Integer[] data = { 5, 3, 4, 2, 7, 1, 9, 8, 10, 6, 5 };
Integer[] asc = { 5, 5, 6, 7, 8, 9, 10 };
Integer[] desc = { 5, 5, 4, 3, 2, 1 };
- Heap<Integer> hasc = new TiedTopBoundedHeap<Integer>(asc.length - 1);
- Heap<Integer> hdesc = new TiedTopBoundedHeap<Integer>(desc.length - 1, Collections.reverseOrder());
+ Heap<Integer> hasc = new TiedTopBoundedHeap<>(asc.length - 1);
+ Heap<Integer> hdesc = new TiedTopBoundedHeap<>(desc.length - 1, Collections.reverseOrder());
for(Integer i : data) {
hasc.add(i);
hdesc.add(i);
@@ -70,11 +70,11 @@ public class TestTiedTopBoundedHeap {
*/
@Test
public void testTiedTopBoundedHeapTrival() {
- Heap<Integer> heap1 = new TiedTopBoundedHeap<Integer>(1);
- Heap<Integer> heap2 = new TiedTopBoundedHeap<Integer>(1);
- Heap<Integer> heap3 = new TiedTopBoundedHeap<Integer>(1);
- Heap<Integer> heap4 = new TiedTopBoundedHeap<Integer>(1);
- Heap<Integer> heap5 = new TiedTopBoundedHeap<Integer>(1);
+ Heap<Integer> heap1 = new TiedTopBoundedHeap<>(1);
+ Heap<Integer> heap2 = new TiedTopBoundedHeap<>(1);
+ Heap<Integer> heap3 = new TiedTopBoundedHeap<>(1);
+ Heap<Integer> heap4 = new TiedTopBoundedHeap<>(1);
+ Heap<Integer> heap5 = new TiedTopBoundedHeap<>(1);
heap2.add(2);
heap4.add(0);
for(int i = 0; i < 10; i++) {
diff --git a/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestTiedTopBoundedUpdatableHeap.java b/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestTiedTopBoundedUpdatableHeap.java
index e469bfca..a0c45901 100644
--- a/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestTiedTopBoundedUpdatableHeap.java
+++ b/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestTiedTopBoundedUpdatableHeap.java
@@ -42,14 +42,14 @@ public class TestTiedTopBoundedUpdatableHeap implements JUnit4Test {
final int bsize = 1000;
final int limit = 200;
final Random r = new Random(1);
- ArrayList<IntegerPriorityObject<Integer>> simulate = new ArrayList<IntegerPriorityObject<Integer>>(1000);
- TiedTopBoundedUpdatableHeap<IntegerPriorityObject<Integer>> heap = new TiedTopBoundedUpdatableHeap<IntegerPriorityObject<Integer>>(limit);
+ ArrayList<IntegerPriorityObject<Integer>> simulate = new ArrayList<>(1000);
+ TiedTopBoundedUpdatableHeap<IntegerPriorityObject<Integer>> heap = new TiedTopBoundedUpdatableHeap<>(limit);
for(int i = 0; i < iters; i++) {
int batchsize = r.nextInt(bsize);
for(int j = 0; j < batchsize; j++) {
int id = r.nextInt(maxid);
int score = r.nextInt(10000);
- IntegerPriorityObject<Integer> nobj = new IntegerPriorityObject<Integer>(score, id);
+ IntegerPriorityObject<Integer> nobj = new IntegerPriorityObject<>(score, id);
// Update heap
heap.add(nobj);
// Enabling the followig assertion *hides* certain problems!
diff --git a/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestTopBoundedHeap.java b/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestTopBoundedHeap.java
index 7586556c..2bc87013 100644
--- a/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestTopBoundedHeap.java
+++ b/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestTopBoundedHeap.java
@@ -46,8 +46,8 @@ public class TestTopBoundedHeap {
Integer[] data = { 5, 3, 4, 2, 7, 1, 9, 8, 10, 6 };
Integer[] asc = { 5, 6, 7, 8, 9, 10 };
Integer[] desc = { 6, 5, 4, 3, 2, 1 };
- Heap<Integer> hasc = new TopBoundedHeap<Integer>(asc.length);
- Heap<Integer> hdesc = new TopBoundedHeap<Integer>(desc.length, Collections.reverseOrder());
+ Heap<Integer> hasc = new TopBoundedHeap<>(asc.length);
+ Heap<Integer> hdesc = new TopBoundedHeap<>(desc.length, Collections.reverseOrder());
for(Integer i : data) {
hasc.add(i);
hdesc.add(i);
diff --git a/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestUpdatableHeap.java b/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestUpdatableHeap.java
index 7e0e8650..bfe7e1f4 100644
--- a/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestUpdatableHeap.java
+++ b/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestUpdatableHeap.java
@@ -40,15 +40,15 @@ public class TestUpdatableHeap implements JUnit4Test {
final int maxid = 5000;
final int bsize = 100;
final Random r = new Random(1);
- ArrayList<IntegerPriorityObject<Integer>> simulate = new ArrayList<IntegerPriorityObject<Integer>>(1000);
- UpdatableHeap<IntegerPriorityObject<Integer>> heap = new UpdatableHeap<IntegerPriorityObject<Integer>>();
+ ArrayList<IntegerPriorityObject<Integer>> simulate = new ArrayList<>(1000);
+ UpdatableHeap<IntegerPriorityObject<Integer>> heap = new UpdatableHeap<>();
for(int i = 0; i < iters; i++) {
int batchsize = r.nextInt(bsize);
for(int j = 0; j < batchsize; j++) {
int id = r.nextInt(maxid);
int score = r.nextInt(10000);
// Update heap
- heap.add(new IntegerPriorityObject<Integer>(score, id));
+ heap.add(new IntegerPriorityObject<>(score, id));
// Update simulation
boolean found = false;
for(IntegerPriorityObject<Integer> ent : simulate) {
@@ -62,7 +62,7 @@ public class TestUpdatableHeap implements JUnit4Test {
}
}
if(!found) {
- simulate.add(new IntegerPriorityObject<Integer>(score, id));
+ simulate.add(new IntegerPriorityObject<>(score, id));
}
}
// Keeping the simulation list reverse is a bit faster for removal
diff --git a/test/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/TestHashMapHierarchy.java b/test/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/TestHashMapHierarchy.java
new file mode 100644
index 00000000..3a97e72d
--- /dev/null
+++ b/test/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/TestHashMapHierarchy.java
@@ -0,0 +1,85 @@
+package de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy;
+
+/*
+ This file is part of ELKI:
+ Environment for Developing KDD-Applications Supported by Index-Structures
+
+ Copyright (C) 2013
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.HashSet;
+
+import org.junit.Test;
+
+import de.lmu.ifi.dbs.elki.JUnit4Test;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.hierarchy.Hierarchy.Iter;
+
+/**
+ * Test the main hierarchy implementation.
+ *
+ * @author Erich Schubert
+ */
+public class TestHashMapHierarchy implements JUnit4Test {
+ @Test
+ public void testEmpty() {
+ HashMapHierarchy<Object> hier = new HashMapHierarchy<>();
+ assertFalse("Iterator valid?", hier.iterAll().valid());
+ assertFalse("Iterator valid?", hier.iterParents(hier).valid());
+ assertFalse("Iterator valid?", hier.iterAncestors(hier).valid());
+ assertFalse("Iterator valid?", hier.iterChildren(hier).valid());
+ assertFalse("Iterator valid?", hier.iterDescendants(hier).valid());
+ }
+
+ @Test
+ public void testSimple() {
+ final String a = "a", b = "b", c = "c", d = "d";
+ HashMapHierarchy<Object> hier = new HashMapHierarchy<>();
+ // A diamond hierarchy.
+ hier.add(a, b);
+ hier.add(a, c);
+ hier.add(b, d);
+ hier.add(c, d);
+ validate(hier.iterAll(), new String[] { a, b, c, d });
+ validate(hier.iterChildren(a), new String[] { b, c });
+ validate(hier.iterDescendants(a), new String[] { b, c, d });
+ validate(hier.iterParents(d), new String[] { b, c });
+ validate(hier.iterAncestors(d), new String[] { a, b, c });
+ }
+
+ private <O> void validate(Iter<O> iter, O[] all) {
+ HashSet<O> seen = new HashSet<>(all.length);
+ for (; iter.valid(); iter.advance()) {
+ O cur = iter.get();
+ boolean found = false;
+ for (int i = 0; i < all.length; i++) {
+ if (all[i].equals(cur)) {
+ found = true;
+ seen.add(cur);
+ break;
+ }
+ }
+ assertTrue("Object not found in master solution: " + cur, found);
+ }
+ assertEquals("Not all objects were seen.", all.length, seen.size());
+ }
+}