summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErich Schubert <erich@debian.org>2012-06-02 17:47:03 +0200
committerAndrej Shadura <andrewsh@debian.org>2019-03-09 22:30:32 +0000
commit593eae6c91717eb9f4ff5088ba460dd4210509c0 (patch)
treed97e8cefb48773a382542e9e9d4a6796202a044a
parente580e42664ca92fbf8792bc39b8d59383db829fe (diff)
parentc36aa2a8fd31ca5e225ff30278e910070cd2c8c1 (diff)
Import Debian changes 0.5.0~beta2-1
elki (0.5.0~beta2-1) unstable; urgency=low * New upstream beta release. * Needs GNU Trove 3, in NEW. * Build with OpenJDK7, as OpenJDK6 complains. elki (0.5.0~beta1-1) unstable; urgency=low * New upstream beta release. * Needs GNU Trove 3, not yet in Debian (private package) * Build with OpenJDK7, as OpenJDK6 complains.
-rw-r--r--debian/changelog16
-rw-r--r--debian/control4
-rw-r--r--debian/patches/build.patch12
-rw-r--r--src/META-INF/MANIFEST.MF29
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm24
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.AbstractPrimitiveDistanceBasedAlgorithm3
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.Algorithm76
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.ClusteringAlgorithm21
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.OPTICSTypeAlgorithm4
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMeansInitialization4
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.outlier.OutlierAlgorithm38
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.neighborhood.NeighborSetPredicate$Factory3
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.data.ClassLabel$Factory2
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.data.NumberVector10
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.data.images.ComputeColorHistogram3
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.database.Database3
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.database.UpdatableDatabase1
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.datasource.DatabaseConnection11
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.datasource.filter.ObjectFilter21
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.datasource.parser.Parser10
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractIndexBasedDistanceFunction7
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction53
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.DoubleNorm10
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.FilteredLocalPCABasedDistanceFunction4
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.LocallyWeightedDistanceFunction1
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.NumberVectorDistanceFunction29
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction36
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction33
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDistanceFunction15
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDoubleDistanceFunction15
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.external.DistanceParser1
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.AbstractDimensionsSelectingDoubleDistanceFunction3
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.similarityfunction.NormalizedSimilarityFunction1
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.similarityfunction.PrimitiveSimilarityFunction4
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.similarityfunction.SimilarityFunction6
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.evaluation.Evaluator8
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.index.IndexFactory24
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.index.KNNIndex17
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.index.RKNNIndex6
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.index.RangeIndex10
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.index.preprocessed.LocalProjectionIndex$Factory4
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNPreprocessor2
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.index.preprocessed.localpca.FilteredLocalPCAIndex$Factory2
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.index.preprocessed.preference.PreferenceVectorIndex$Factory2
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.index.preprocessed.snn.SharedNearestNeighborIndex$Factory1
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.index.preprocessed.subspaceproj.SubspaceProjectionIndex$Factory2
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk.BulkSplit5
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert.InsertionStrategy5
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.overflow.OverflowTreatment2
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split.SplitStrategy5
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.math.linearalgebra.pca.CovarianceMatrixBuilder2
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.math.linearalgebra.pca.EigenPairFilter9
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.math.linearalgebra.pca.PCAFilteredRunner2
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions.WeightFunction13
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.math.spacefillingcurves.SpatialSorter4
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.result.ResultHandler6
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.utilities.referencepoints.ReferencePointsHeuristic6
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.utilities.scaling.ScalingFunction19
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.utilities.scaling.StaticScalingFunction5
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.utilities.scaling.outlier.OutlierScalingFunction14
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.visualization.projector.ProjectorFactory4
-rw-r--r--src/META-INF/elki/de.lmu.ifi.dbs.elki.visualization.visualizers.VisFactory46
-rw-r--r--src/META-INF/services/org.apache.batik.ext.awt.image.spi.RegistryEntry1
-rw-r--r--src/META-INF/services/org.apache.batik.util.ParsedURLProtocolHandler1
-rw-r--r--src/de/lmu/ifi/dbs/elki/KDDTask.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/APRIORI.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/AbstractAlgorithm.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/AbstractDistanceBasedAlgorithm.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/AbstractPrimitiveDistanceBasedAlgorithm.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/Algorithm.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/DependencyDerivator.java21
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/DummyAlgorithm.java12
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/KNNDistanceOrder.java9
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/KNNJoin.java313
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/MaterializeDistances.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/NullAlgorithm.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/AbstractProjectedClustering.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/AbstractProjectedDBSCAN.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/ClusteringAlgorithm.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/DBSCAN.java17
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/DeLiClu.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/EM.java129
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/KMeans.java307
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/OPTICS.java2
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/SLINK.java20
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/SNNClustering.java15
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/CASH.java21
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/COPAC.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/ERiC.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/FourC.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/HiCO.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/LMCLUS.java566
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/ORCLUS.java21
-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.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/kmeans/AbstractKMeans.java310
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/AbstractKMeansInitialization.java71
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/FirstKInitialMeans.java74
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeansInitialization.java49
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeansLloyd.java176
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeansMacQueen.java177
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeansPlusPlusInitialMeans.java213
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/RandomlyChosenInitialMeans.java78
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/RandomlyGeneratedInitialMeans.java87
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/package-info.java (renamed from src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis1d/package-info.java)7
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/package-info.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/CLIQUE.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/DiSH.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/HiSC.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/PROCLUS.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/PreDeCon.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/SUBCLU.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/clique/CLIQUESubspace.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/clique/CLIQUEUnit.java5
-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.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/ByLabelHierarchicalClustering.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/ByModelClustering.java163
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/TrivialAllInOne.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/TrivialAllNoise.java2
-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.java123
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/AbstractAggarwalYuOutlier.java9
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/AbstractDBOutlier.java64
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/AggarwalYuEvolutionary.java84
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/AggarwalYuNaive.java66
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/DBOutlierDetection.java69
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/DBOutlierScore.java57
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/EMOutlier.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/GaussianModel.java19
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/GaussianUniformMixture.java18
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/INFLO.java43
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/KNNOutlier.java22
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/KNNWeightOutlier.java71
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/LDOF.java74
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/LOCI.java123
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/LOF.java70
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/LoOP.java35
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/OPTICSOF.java29
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/OUTRES.java368
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/OnlineLOF.java47
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/OutlierAlgorithm.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/ReferenceBasedOutlierDetection.java195
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/SOD.java176
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/ExternalDoubleOutlierScore.java20
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/FeatureBagging.java45
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/RescaleMetaOutlierAlgorithm.java10
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/AbstractNeighborhoodOutlier.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuGLSBackwardSearchAlgorithm.java30
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuMeanMultipleAttributes.java13
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuMedianAlgorithm.java17
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuMedianMultipleAttributes.java15
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuMoranScatterplotOutlier.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuRandomWalkEC.java11
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuScatterplotOutlier.java18
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuZTestOutlier.java12
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/SLOM.java26
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/SOF.java20
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/TrimmedMeanApproach.java18
-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.java11
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/ExternalNeighborhood.java2
-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.java7
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/weighted/UnweightedNeighborhoodAdapter.java2
-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/trivial/ByLabelOutlier.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/TrivialAllOutlier.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/TrivialGeneratedOutlier.java212
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/TrivialNoOutlier.java8
-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/AveragePrecisionAtK.java235
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/statistics/DistanceStatisticsWithClasses.java13
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/statistics/EvaluateRankingQuality.java15
-rw-r--r--src/de/lmu/ifi/dbs/elki/algorithm/statistics/RankingQualityHistogram.java15
-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.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/ComputeSingleColorHistogram.java33
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/GeneratorXMLSpec.java92
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/KDDCLIApplication.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/cache/CacheDoubleDistanceInOnDiskMatrix.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/cache/CacheFloatDistanceInOnDiskMatrix.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/cache/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/greedyensemble/ComputeKNNOutlierScores.java468
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/greedyensemble/GreedyEnsembleExperiment.java439
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/greedyensemble/VisualizePairwiseGainMatrix.java307
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/greedyensemble/package-info.java32
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/internal/CheckELKIServices.java (renamed from src/de/lmu/ifi/dbs/elki/application/internal/CheckELKIProperties.java)96
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/internal/CheckParameterizables.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/internal/DocumentParameters.java13
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/internal/DocumentReferences.java176
-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.java2
-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.java2
-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.java19
-rw-r--r--src/de/lmu/ifi/dbs/elki/application/visualization/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/AbstractNumberVector.java9
-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.java214
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/ClassLabel.java19
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/Cluster.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/Clustering.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/DoubleVector.java130
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/ExternalID.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/FeatureVector.java18
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/FloatVector.java135
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/HierarchicalClassLabel.java13
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/HyperBoundingBox.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/IntegerVector.java175
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/Interval.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/LabelList.java16
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/ModifiableHyperBoundingBox.java31
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/NumberVector.java86
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/OneDimensionalDoubleVector.java88
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/ParameterizationFunction.java41
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/RationalNumber.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/SimpleClassLabel.java16
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/SparseFeatureVector.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/SparseFloatVector.java282
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/SparseNumberVector.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/Subspace.java9
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/VectorUtil.java203
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/images/AbstractComputeColorHistogram.java39
-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.java9
-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.java3
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/model/Bicluster.java7
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/model/BiclusterWithInverted.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/model/ClusterModel.java14
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/model/CorrelationAnalysisSolution.java13
-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/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/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/AbstractFeatureSelection.java64
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/projection/FeatureSelection.java104
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/projection/NumericalFeatureSelection.java104
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/projection/Projection.java59
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/projection/package-info.java (renamed from src/de/lmu/ifi/dbs/elki/properties/package-info.java)6
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/spatial/Polygon.java2
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/spatial/SpatialUtil.java214
-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.java21
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/GeneratorInterfaceDynamic.java18
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/GeneratorMain.java68
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/GeneratorSingleCluster.java97
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/GeneratorStatic.java56
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/distribution/NormalDistribution.java127
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/type/CombinedTypeInformation.java2
-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.java48
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/type/TypeInformation.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/type/TypeUtil.java25
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/type/VectorFieldTypeInformation.java96
-rw-r--r--src/de/lmu/ifi/dbs/elki/data/type/VectorTypeInformation.java31
-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.java34
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/Database.java37
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/DatabaseEventManager.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/HashmapDatabase.java21
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ProxyDatabase.java16
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/QueryUtil.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/StaticArrayDatabase.java31
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/UpdatableDatabase.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.java32
-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.java13
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/DoubleDataStore.java44
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/RangeIDMap.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/WritableDataStore.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/WritableDoubleDataStore.java59
-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/ArrayDoubleStore.java121
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayRecordStore.java6
-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/MapIntegerDBIDDoubleStore.java98
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDRecordStore.java191
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDStore.java104
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/datastore/memory/MemoryDataStoreFactory.java34
-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.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/ArrayDBIDs.java35
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/ArrayModifiableDBIDs.java37
-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.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/DBIDFactory.java25
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/DBIDIter.java79
-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/DBIDUtil.java63
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/DBIDs.java22
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/EmptyDBIDs.java60
-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.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/ModifiableDBIDs.java33
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/SetDBIDs.java5
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/StaticDBIDs.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/generic/DBIDIterAdapter.java82
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/generic/GenericArrayModifiableDBIDs.java64
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/generic/GenericHashSetModifiableDBIDs.java58
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/generic/GenericTreeSetModifiableDBIDs.java90
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/generic/MaskedDBIDs.java121
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/generic/MergedDBIDs.java89
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/generic/UnmodifiableDBIDs.java17
-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/IntegerArrayStaticDBIDs.java74
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBID.java72
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDPair.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDRange.java86
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/ReusingDBIDFactory.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/SimpleDBIDFactory.java54
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/TrivialDBIDFactory.java40
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveArrayDBIDs.java133
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveArrayModifiableDBIDs.java144
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveArrayStaticDBIDs.java (renamed from src/de/lmu/ifi/dbs/elki/visualization/visualizers/events/ContextChangedEvent.java)36
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveHashSetModifiableDBIDs.java193
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveIteratorAdapter.java66
-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.java39
-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.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/DatabaseQuery.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/DistanceResultPair.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/DoubleDistanceResultPair.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/GenericDistanceResultPair.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.java24
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/distance/SpatialPrimitiveDistanceQuery.java12
-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.java19
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/knn/KNNQuery.java32
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/knn/KNNResult.java83
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/knn/KNNUtil.java417
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/knn/LinearScanKNNQuery.java17
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/knn/LinearScanPrimitiveDistanceKNNQuery.java11
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/knn/LinearScanRawDoubleDistanceKNNQuery.java9
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/knn/PreprocessorKNNQuery.java41
-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.java18
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/range/LinearScanPrimitiveDistanceRangeQuery.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/range/LinearScanRangeQuery.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/range/LinearScanRawDoubleDistanceRangeQuery.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/range/RangeQuery.java25
-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.java7
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/rknn/LinearScanRKNNQuery.java13
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/rknn/PreprocessorRKNNQuery.java17
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/query/rknn/RKNNQuery.java15
-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.java2
-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.java114
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/relation/ProxyView.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/database/relation/Relation.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.java97
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/ArrayAdapterDatabaseConnection.java78
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/ConcatenateFilesDatabaseConnection.java178
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/DBIDRangeDatabaseConnection.java125
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/FileBasedDatabaseConnection.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/GeneratorXMLDatabaseConnection.java82
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/InputStreamDatabaseConnection.java51
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/LabelJoinDatabaseConnection.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/PresortedBlindJoinDatabaseConnection.java128
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/RandomDoubleVectorDatabaseConnection.java7
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/RandomDoubleVectorDatabaseConnection.java.rej14
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/bundle/BundleMeta.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/bundle/BundleStreamSource.java71
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/bundle/MultipleObjectsBundle.java46
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/bundle/StreamFromBundle.java73
-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.java11
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractFeatureSelectionFilter.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractRandomFeatureSelectionFilter.java19
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractStreamConversionFilter.java117
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractStreamFilter.java50
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/ByLabelFilter.java (renamed from src/de/lmu/ifi/dbs/elki/datasource/filter/FilterByLabelFilter.java)111
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/ClassLabelFilter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/DoubleVectorProjectionFilter.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/DoubleVectorRandomProjectionFilter.java5
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/ExternalIDFilter.java7
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/FixedDBIDsFilter.java57
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/NoMissingValuesFilter.java (renamed from src/de/lmu/ifi/dbs/elki/datasource/filter/FilterNoMissingValuesFilter.java)10
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/NoOpFilter.java22
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/ObjectFilter.java5
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/ShuffleObjectsFilter.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/SortByLabelFilter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/SparseFloatVectorProjectionFilter.java9
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/SparseFloatVectorRandomProjectionFilter.java9
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/SparseVectorFieldFilter.java75
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/SplitNumberVectorFilter.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/StreamFilter.java (renamed from src/de/lmu/ifi/dbs/elki/visualization/visualizers/events/ResizedEvent.java)28
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AbstractNormalization.java (renamed from src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractNormalization.java)5
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AttributeWiseErfNormalization.java (renamed from src/de/lmu/ifi/dbs/elki/datasource/filter/AttributeWiseErfNormalization.java)10
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AttributeWiseMinMaxNormalization.java (renamed from src/de/lmu/ifi/dbs/elki/datasource/filter/AttributeWiseMinMaxNormalization.java)20
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AttributeWiseVarianceNormalization.java (renamed from src/de/lmu/ifi/dbs/elki/datasource/filter/AttributeWiseVarianceNormalization.java)32
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/InverseDocumentFrequencyNormalization.java (renamed from src/de/lmu/ifi/dbs/elki/datasource/filter/InverseDocumentFrequencyNormalization.java)27
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/LengthNormalization.java115
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/NonNumericFeaturesException.java (renamed from src/de/lmu/ifi/dbs/elki/datasource/filter/NonNumericFeaturesException.java)4
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/Normalization.java (renamed from src/de/lmu/ifi/dbs/elki/datasource/filter/Normalization.java)5
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/RankTieNormalization.java113
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/TFIDFNormalization.java (renamed from src/de/lmu/ifi/dbs/elki/datasource/filter/TFIDFNormalization.java)12
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/package-info.java26
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/filter/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.java24
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/parser/AbstractStreamingParser.java51
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/parser/ArffParser.java93
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/parser/BitVectorLabelParser.java9
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/parser/DoubleVectorLabelParser.java72
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/parser/DoubleVectorLabelTransposingParser.java141
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/parser/FloatVectorLabelParser.java28
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/parser/NumberVectorLabelParser.java248
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/parser/ParameterizationFunctionLabelParser.java19
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/parser/Parser.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/parser/SimplePolygonParser.java49
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/parser/SparseBitVectorLabelParser.java7
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/parser/SparseFloatVectorLabelParser.java146
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/parser/StreamingParser.java (renamed from src/de/lmu/ifi/dbs/elki/datasource/parser/LinebasedParser.java)24
-rw-r--r--src/de/lmu/ifi/dbs/elki/datasource/parser/TermFrequencyParser.java118
-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/AbstractCosineDistanceFunction.java107
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractDBIDDistanceFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractDatabaseDistanceFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractIndexBasedDistanceFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractPrimitiveDistanceFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractVectorDoubleDistanceFunction.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractVectorDoubleDistanceNorm.java40
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/ArcCosineDistanceFunction.java42
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/CanberraDistanceFunction.java127
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/CosineDistanceFunction.java38
-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.java43
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/EuclideanDistanceFunction.java55
-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/JeffreyDivergenceDistanceFunction.java100
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/LPNormDistanceFunction.java65
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/LocallyWeightedDistanceFunction.java18
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/ManhattanDistanceFunction.java66
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/MaximumDistanceFunction.java49
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/MinKDistance.java18
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/MinimumDistanceFunction.java33
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/Norm.java44
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/NumberVectorDistanceFunction.java (renamed from src/de/lmu/ifi/dbs/elki/utilities/designpattern/Observable.java)29
-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.java2
-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.java19
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/SpatialPrimitiveDistanceFunction.java23
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/SpatialPrimitiveDoubleDistanceFunction.java13
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/SquaredEuclideanDistanceFunction.java42
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/WeightedDistanceFunction.java12
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/WeightedLPNormDistanceFunction.java38
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/WeightedSquaredEuclideanDistanceFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/AbstractSimilarityAdapter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/SimilarityAdapterArccos.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/SimilarityAdapterLinear.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/SimilarityAdapterLn.java2
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/colorhistogram/HistogramIntersectionDistanceFunction.java27
-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.java7
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/PCABasedCorrelationDistanceFunction.java25
-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.java2
-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.java (renamed from src/de/lmu/ifi/dbs/elki/datasource/parser/DistanceParser.java)10
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/DistanceParsingResult.java (renamed from src/de/lmu/ifi/dbs/elki/datasource/parser/DistanceParsingResult.java)4
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/FileBasedDoubleDistanceFunction.java16
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/FileBasedFloatDistanceFunction.java11
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/NumberDistanceParser.java (renamed from src/de/lmu/ifi/dbs/elki/datasource/parser/NumberDistanceParser.java)47
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/geo/LatLngDistanceFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/geo/LngLatDistanceFunction.java2
-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/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/AbstractDimensionsSelectingDoubleDistanceFunction.java20
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/DimensionSelectingDistanceFunction.java21
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/DimensionSelectingSubspaceDistanceFunction.java52
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/HiSCDistanceFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/LocalSubspaceDistanceFunction.java (renamed from src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/SubspaceDistanceFunction.java)14
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/SubspaceEuclideanDistanceFunction.java149
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/SubspaceLPNormDistanceFunction.java (renamed from src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/DimensionsSelectingEuclideanDistanceFunction.java)171
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/SubspaceManhattanDistanceFunction.java142
-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.java13
-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/distancevalue/AbstractDistance.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancevalue/BitDistance.java2
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancevalue/DoubleDistance.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancevalue/FloatDistance.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancevalue/IntegerDistance.java2
-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.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancevalue/PreferenceVectorBasedCorrelationDistance.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/distancevalue/SubspaceDistance.java2
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/similarityfunction/AbstractPrimitiveSimilarityFunction.java2
-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.java22
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/similarityfunction/IndexBasedSimilarityFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/similarityfunction/InvertedDistanceSimilarityFunction.java74
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/similarityfunction/SharedNearestNeighborSimilarityFunction.java16
-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.java2
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/distance/similarityfunction/kernel/PolynomialKernelFunction.java2
-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/Evaluator.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/clustering/BCubed.java103
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/clustering/ClusterContingencyTable.java321
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/clustering/EditDistance.java155
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/clustering/Entropy.java237
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/clustering/EvaluateClustering.java288
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/clustering/PairCounting.java225
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/clustering/SetMatchingPurity.java168
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/clustering/package-info.java26
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/clustering/pairsegments/ClusterPairSegmentAnalysis.java47
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/clustering/pairsegments/Segment.java149
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/clustering/pairsegments/Segments.java361
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/clustering/pairsegments/package-info.java26
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/histogram/ComputeOutlierHistogram.java27
-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.java104
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/index/IndexStatistics.java2
-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.java2
-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/paircounting/EvaluatePairCountingFMeasure.java180
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/paircounting/PairCountingFMeasure.java241
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/paircounting/generator/PairGeneratorMerge.java72
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/paircounting/generator/PairGeneratorNoise.java91
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/paircounting/generator/PairGeneratorSingleCluster.java136
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/paircounting/generator/PairSortedGenerator.java76
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/paircounting/package-info.java26
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/roc/ComputeROCCurve.java29
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/roc/ROC.java92
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/evaluation/similaritymatrix/package-info.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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/configurator/ClassParameterConfigurator.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/configurator/ConfiguratorPanel.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/configurator/EnumParameterConfigurator.java2
-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.java2
-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.java11
-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.java2
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/multistep/panels/EvaluationTabPanel.java2
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/multistep/panels/OutputTabPanel.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/multistep/panels/ParameterTabPanel.java7
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/multistep/panels/SavedSettingsTabPanel.java2
-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.java2
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/gui/util/ParameterTable.java2
-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.java2
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/AbstractRefiningIndex.java192
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/Index.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/IndexFactory.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/KNNIndex.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/RKNNIndex.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/RangeIndex.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/package-info.java34
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/AbstractPreprocessorIndex.java4
-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.java68
-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.java128
-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.java37
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/MaterializeKNNPreprocessor.java87
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/MetricalIndexApproximationMaterializeKNNPreprocessor.java13
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/PartitionApproximationMaterializeKNNPreprocessor.java14
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/RandomSampleKNNPreprocessor.java237
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/SpatialApproximationMaterializeKNNPreprocessor.java12
-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.java10
-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.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/RangeQueryFilteredPCAIndex.java2
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/DiSHPreferenceVectorIndex.java2
-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.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/snn/SharedNearestNeighborPreprocessor.java26
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/FourCSubspaceIndex.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/PreDeConSubspaceIndex.java2
-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/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.java89
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/BreadthFirstEnumeration.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/DirectoryEntry.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/DistanceEntry.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/Entry.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/IndexTree.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/IndexTreePath.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/LeafEntry.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/Node.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexFactory.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexHeader.java2
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTree.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTreeFactory.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTreeNode.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeDirectoryEntry.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeEntry.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeLeafEntry.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTree.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTreeUnified.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTreeUnifiedFactory.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/MkTreeHeader.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppDirectoryEntry.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppEntry.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppLeafEntry.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTree.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeFactory.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeIndex.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeNode.java2
-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.java2
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPEntry.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPLeafEntry.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTree.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTreeIndex.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTreeNode.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCopTreeFactory.java2
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxEntry.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxLeafEntry.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTree.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeFactory.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeIndex.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeNode.java2
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabEntry.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabLeafEntry.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTree.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTreeFactory.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTreeIndex.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTreeNode.java2
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeFactory.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeIndex.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeNode.java2
-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/MetricalIndexKNNQuery.java24
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MetricalIndexRangeQuery.java18
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MkTreeRKNNQuery.java2
-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/Assignments.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/MLBDistSplit.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/MRadSplit.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/MTreeSplit.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/package-info.java2
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/query/GenericDistanceSearchCandidate.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/query/GenericMTreeDistanceSearchCandidate.java2
-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.java34
-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.java7
-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.java2
-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.java300
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRStarTreeFactory.java93
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRStarTreeNode.java105
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/NonFlatRStarTree.java53
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/bulk/ZCurveBulkSplit.java184
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluDirectoryEntry.java6
-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.java7
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluTree.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluTreeFactory.java25
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluTreeIndex.java10
-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.java89
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/DoubleDistanceRStarTreeRangeQuery.java13
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/GenericRStarTreeKNNQuery.java85
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/GenericRStarTreeRangeQuery.java15
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/RStarTreeUtil.java2
-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.java25
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTreeIndex.java10
-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.java (renamed from src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/bulk/AbstractBulkSplit.java)37
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/BulkSplit.java (renamed from src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/bulk/BulkSplit.java)7
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/FileOrderBulkSplit.java67
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/MaxExtensionBulkSplit.java (renamed from src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/bulk/MaxExtensionBulkSplit.java)24
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/OneDimSortBulkSplit.java86
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/SortTileRecursiveBulkSplit.java115
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/SpatialSortBulkSplit.java107
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/package-info.java (renamed from src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/bulk/package-info.java)4
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/ApproximativeLeastOverlapInsertionStrategy.java168
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/CombinedInsertionStrategy.java127
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/InsertionStrategy.java (renamed from src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/InsertionStrategy.java)29
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastEnlargementInsertionStrategy.java89
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastEnlargementWithAreaInsertionStrategy.java102
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastOverlapInsertionStrategy.java120
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/package-info.java26
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/LimitedReinsertOverflowTreatment.java135
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/OverflowTreatment.java53
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/SplitOnlyOverflowTreatment.java73
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/package-info.java26
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/package-info.java26
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/AbstractPartialReinsert.java105
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/CloseReinsert.java88
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/FarReinsert.java88
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/ReinsertStrategy.java44
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/package-info.java26
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/AngTanLinearSplit.java193
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/GreeneSplit.java158
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/RTreeLinearSplit.java219
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/RTreeQuadraticSplit.java183
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/SplitStrategy.java (renamed from src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/SplitStrategy.java)22
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/TopologicalSplitter.java309
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/package-info.java26
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/ApproximateLeastOverlapInsertionStrategy.java150
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/Enlargement.java119
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/LeastOverlapInsertionStrategy.java87
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/NodeArrayAdapter.java58
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/SpatialComparator.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/TopologicalSplitter.java270
-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/VAFile.java518
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/vafile/VALPNormDistance.java169
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/vafile/VectorApproximation.java103
-rw-r--r--src/de/lmu/ifi/dbs/elki/index/vafile/package-info.java27
-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/Logging.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/logging/LoggingConfiguration.java17
-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/logging.properties (renamed from src/de/lmu/ifi/dbs/elki/logging/logging-cli.properties)0
-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.java2
-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/math/DoubleMinMax.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/MathUtil.java868
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/Mean.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/MeanVariance.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/MeanVarianceMinMax.java139
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/MinMax.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/PearsonCorrelation.java269
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/geometry/AlphaShape.java116
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/geometry/GrahamScanConvexHull2D.java (renamed from src/de/lmu/ifi/dbs/elki/math/ConvexHull2D.java)69
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/geometry/SweepHullDelaunay2D.java929
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/geometry/package-info.java26
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/histograms/AggregatingHistogram.java (renamed from src/de/lmu/ifi/dbs/elki/math/AggregatingHistogram.java)51
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/histograms/FlexiHistogram.java (renamed from src/de/lmu/ifi/dbs/elki/math/FlexiHistogram.java)103
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/histograms/ReplacingHistogram.java (renamed from src/de/lmu/ifi/dbs/elki/math/ReplacingHistogram.java)147
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/histograms/package-info.java26
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/AffineTransformation.java12
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/Centroid.java11
-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.java6
-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.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/LUDecomposition.java62
-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.java260
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/MatrixLike.java194
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/ProjectedCentroid.java7
-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.java56
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/SingularValueDecomposition.java75
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/SortedEigenPairs.java10
-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.java1512
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/Vector.java344
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/fitting/LevenbergMarquardtMethod.java2
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/CovarianceMatrixBuilder.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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/LimitEigenPairFilter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/NormalizingEigenPairFilter.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/PCAFilteredAutotuningRunner.java232
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/PCAFilteredResult.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/PCAFilteredRunner.java6
-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.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/PercentageEigenPairFilter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/ProgressiveEigenPairFilter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/RelativeEigenPairFilter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/SignificantEigenPairFilter.java2
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/WeightedCovarianceMatrixBuilder.java8
-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.java7
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/ErfcWeight.java6
-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.java2
-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/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/scales/LinearScale.java (renamed from src/de/lmu/ifi/dbs/elki/visualization/scales/LinearScale.java)4
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/scales/Scales.java (renamed from src/de/lmu/ifi/dbs/elki/visualization/scales/Scales.java)4
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/scales/package-info.java (renamed from src/de/lmu/ifi/dbs/elki/visualization/scales/package-info.java)4
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/AbstractSpatialSorter.java144
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/BinarySplitSpatialSorter.java112
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/HilbertSpatialSorter.java346
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/PeanoSpatialSorter.java149
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/SpatialSorter.java54
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/ZCurve.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/ZCurveSpatialSorter.java91
-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/EpanechnikovKernelDensityFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/GaussianKernelDensityFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/KernelDensityEstimator.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/KernelDensityFunction.java2
-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.java16
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/PolynomialRegression.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/QuickSelect.java231
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/StudentDistribution.java14
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/TriangularKernelDensityFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/UniformKernelDensityFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/ChiDistribution.java92
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/ChiSquaredDistribution.java72
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/ConstantDistribution.java61
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/Distribution.java (renamed from src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/distribution/Distribution.java)31
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/GammaDistribution.java (renamed from src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/distribution/GammaDistribution.java)253
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/NormalDistribution.java337
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/UniformDistribution.java (renamed from src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/distribution/UniformDistribution.java)36
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/distribution/package-info.java26
-rw-r--r--src/de/lmu/ifi/dbs/elki/math/statistics/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.java (renamed from src/de/lmu/ifi/dbs/elki/persistent/AbstractPage.java)26
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/AbstractPageFile.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/AbstractStoringPageFile.java14
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/DefaultPageHeader.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/ExternalizablePage.java (renamed from src/de/lmu/ifi/dbs/elki/database/ids/TreeSetModifiableDBIDs.java)17
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/FixedSizeByteBufferSerializer.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/LRUCache.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/MemoryPageFile.java12
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/OnDiskArray.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/OnDiskArrayPageFile.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/OnDiskUpperTriangleMatrix.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/Page.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/PageFile.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/PageFileStatistics.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/PageFileUtil.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/PageHeader.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/PersistentPageFile.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/persistent/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/properties/ELKI.properties646
-rw-r--r--src/de/lmu/ifi/dbs/elki/properties/IterateKnownImplementations.java152
-rw-r--r--src/de/lmu/ifi/dbs/elki/properties/Properties.java111
-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.java15
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/KNNDistanceOrderResult.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/OrderingFromDataStore.java7
-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.java7
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/ResultListener.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/ResultProcessor.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/ResultUtil.java82
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/ResultWriter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/SamplingResult.java77
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/ScalesResult.java85
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/SelectionResult.java4
-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.java2
-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.java5
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/textwriter/SingleStreamOutput.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/textwriter/StreamFactory.java2
-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.java117
-rw-r--r--src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriterStream.java2
-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.java2
-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.java2
-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/Base64.java100
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/BitsUtil.java1140
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/ClassGenericsUtil.java15
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/ConstantObject.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/DatabaseUtil.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/ELKIServiceLoader.java207
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/FileUtil.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/FormatUtil.java71
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/HandlerList.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/InspectionUtil.java337
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/InspectionUtilFrequentlyScanned.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/QueryStatistic.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/Util.java548
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/AnyMap.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/HashMapList.java2
-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.java780
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ArrayAdapter.java (renamed from src/de/lmu/ifi/dbs/elki/evaluation/paircounting/generator/PairSortedGeneratorInterface.java)34
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ArrayDBIDsAdapter.java53
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ArrayLikeUtil.java253
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/DoubleArrayAdapter.java81
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ExtendedArray.java96
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/FeatureVectorAdapter.java56
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/FloatArrayAdapter.java82
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/IdentityArrayAdapter.java55
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ListArrayAdapter.java55
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/NumberArrayAdapter.java99
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/NumberListArrayAdapter.java87
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/NumberVectorAdapter.java86
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/SingleSubsetArrayAdapter.java67
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/SubsetArrayAdapter.java65
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/TDoubleListAdapter.java81
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/package-info.java26
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoublePriorityObject.java127
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/Heap.java471
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/IntegerPriorityObject.java19
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/KNNHeap.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/KNNList.java304
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TiedTopBoundedHeap.java47
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TiedTopBoundedUpdatableHeap.java175
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TopBoundedHeap.java45
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TopBoundedUpdatableHeap.java122
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/UpdatableHeap.java251
-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/Hierarchical.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/Hierarchy.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/HierarchyHashmapList.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/HierarchyReferenceLists.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/ModifiableHierarchy.java2
-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/package-info.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/designpattern/Observer.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/designpattern/Observers.java18
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/designpattern/package-info.java2
-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.java48
-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/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.java2
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/iterator/EmptyIterator.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/iterator/IterableIterator.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/iterator/IterableIteratorAdapter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/iterator/IterableUtil.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/iterator/MergedIterator.java29
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/iterator/OneItemIterator.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/iterator/ReverseListIterator.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/iterator/TypeFilterIterator.java11
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/iterator/UnmodifiableIterator.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/iterator/UnmodifiableListIterator.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/iterator/package-info.java2
-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.java2
-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.java2
-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.java2
-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.java2
-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.java17
-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/ListGreaterEqualConstraint.java2
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/OneMustBeSetGlobalConstraint.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/OnlyOneIsAllowedToBeSetGlobalConstraint.java2
-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.java2
-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.java4
-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.java2
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/MergedParameterization.java6
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/TrackParameters.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/UnParameterization.java6
-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/ClassListParameter.java45
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ClassParameter.java53
-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.java2
-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/FileListParameter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/FileParameter.java2
-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.java2
-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.java2
-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.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/PatternParameter.java12
-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.java2
-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.java2
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/pairs/DoubleDoublePair.java2
-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.java7
-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.java2
-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.java8
-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.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/referencepoints/RandomSampleReferencePoints.java2
-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.java8
-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/HeDESNormalizationOutlierScaling.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MinusLogGammaScaling.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MinusLogStandardDeviationScaling.java7
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MixtureModelOutlierScalingFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MultiplicativeInverseScaling.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierGammaScaling.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierLinearScaling.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierMinusLogScaling.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierScalingFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierSqrtScaling.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/RankingPseudoOutlierScaling.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/SigmoidOutlierScalingFunction.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/SqrtStandardDeviationScaling.java7
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/StandardDeviationScaling.java7
-rw-r--r--src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/TopKOutlierScaling.java2
-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.java108
-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.java297
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/VisualizationTask.java14
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/VisualizerContext.java226
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/VisualizerParameterizer.java115
-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.java143
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/batikutil/DragableArea.java2
-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.java2
-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.java249
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/batikutil/ThumbnailTranscoder.java72
-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.java4
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/css/CSSClassManager.java2
-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.java48
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/gui/ResultWindow.java111
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/gui/SelectionTableWindow.java7
-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.java29
-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.java157
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/gui/overview/OverviewPlot.java264
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/gui/overview/PlotItem.java68
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/gui/overview/RectangleArranger.java11
-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/OPTICSColorFromClustering.java97
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSColorFromStylingPolicy.java56
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSCut.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSDistanceAdapter.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSNumberDistance.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSPlot.java78
-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.java239
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projections/AbstractProjection.java198
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projections/AbstractSimpleProjection.java6
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projections/AffineProjection.java132
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projections/CanvasSize.java139
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projections/FullProjection.java176
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projections/Projection.java144
-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.java70
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projections/ProjectionParallel.java196
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projections/Simple1D.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projections/Simple2D.java104
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projections/SimpleParallel.java286
-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.java28
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projector/HistogramProjector.java18
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projector/OPTICSProjector.java4
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projector/OPTICSProjectorFactory.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projector/ParallelPlotFactory.java64
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projector/ParallelPlotProjector.java100
-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.java27
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/projector/ScatterPlotProjector.java32
-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.java217
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/savedialog/SaveOptionsPanel.java13
-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.java67
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/ClusterStylingPolicy.java137
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/PropertiesBasedStyleLibrary.java48
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/SingleObjectsStylingPolicy.java34
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/StyleLibrary.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/StyleResult.java66
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/StylingPolicy.java (renamed from src/de/lmu/ifi/dbs/elki/visualization/visualizers/events/ContextChangeListener.java)30
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/classic.properties79
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/default.properties22
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/greyscale.properties (renamed from src/de/lmu/ifi/dbs/elki/visualization/style/grayscale.properties)14
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/lines/DashedLineStyleLibrary.java59
-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.java37
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/lines/package-info.java34
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/marker/CircleMarkers.java90
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/marker/MarkerLibrary.java19
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/marker/MinimalMarkers.java37
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/style/marker/PrettyMarkers.java54
-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.properties8
-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.properties28
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/svg/SVGButton.java165
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/svg/SVGCheckbox.java187
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/svg/SVGCloneVisible.java60
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/svg/SVGEffects.java147
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/svg/SVGHyperCube.java22
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/svg/SVGHyperSphere.java137
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/svg/SVGPath.java211
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/svg/SVGPlot.java179
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/svg/SVGScoreBar.java118
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/svg/SVGSimpleLinearAxis.java148
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/svg/SVGUtil.java92
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/svg/UpdateRunner.java42
-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.java152
-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.java9
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/AbstractVisualization.java49
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/StaticVisualization.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.java120
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/events/package-info.java26
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/histogram/AbstractHistogramVisualization.java (renamed from src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis1d/P1DVisualization.java)17
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/histogram/ColoredHistogramVisualizer.java (renamed from src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis1d/P1DHistogramVisualizer.java)143
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/histogram/package-info.java (renamed from src/de/lmu/ifi/dbs/elki/evaluation/paircounting/generator/package-info.java)7
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/AbstractOPTICSVisualization.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSClusterVisualization.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSPlotCutVisualization.java10
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSPlotSelectionVisualization.java7
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSPlotVisualizer.java28
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSSteepAreaVisualization.java13
-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.java708
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/pairsegments/SegmentsStylingPolicy.java287
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/pairsegments/package-info.java26
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/AbstractParallelVisualization.java163
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/LineVisualization.java218
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/ParallelAxisVisualization.java196
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/cluster/ClusterOutlineVisualization.java259
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/cluster/ClusterParallelMeanVisualization.java215
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/cluster/package-info.java26
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/index/RTreeParallelVisualization.java267
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/index/package-info.java26
-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/SelectionAxisRangeVisualization.java184
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/selection/SelectionLineVisualization.java167
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/selection/SelectionToolAxisRangeVisualization.java316
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/selection/SelectionToolLineVisualization.java331
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/selection/package-info.java26
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/AbstractScatterplotVisualization.java (renamed from src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/P2DVisualization.java)37
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/AbstractTooltipVisualization.java (renamed from src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/AbstractTooltipVisualization.java)45
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/AxisVisualization.java (renamed from src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/AxisVisualization.java)40
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/MarkerVisualization.java175
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/PolygonVisualization.java (renamed from src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/PolygonVisualization.java)27
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/ReferencePointsVisualization.java (renamed from src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/ReferencePointsVisualization.java)28
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/ToolBox2DVisualization.java (renamed from src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/ToolBox2DVisualization.java)41
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/TooltipScoreVisualization.java (renamed from src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/TooltipScoreVisualization.java)57
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/TooltipStringVisualization.java (renamed from src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/TooltipStringVisualization.java)38
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/ClusterHullVisualization.java276
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/ClusterMeanVisualization.java (renamed from src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/ClusterMeanVisualization.java)142
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/ClusterOrderVisualization.java (renamed from src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/ClusterOrderVisualization.java)31
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/EMClusterVisualization.java (renamed from src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/EMClusterVisualization.java)54
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/VoronoiVisualization.java298
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/package-info.java26
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/density/DensityEstimationOverlay.java236
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/density/package-info.java (renamed from src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/distribution/package-info.java)7
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/index/TreeMBRVisualization.java (renamed from src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/TreeMBRVisualization.java)39
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/index/TreeSphereVisualization.java (renamed from src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/TreeSphereVisualization.java)43
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/index/package-info.java26
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/outlier/BubbleVisualization.java (renamed from src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/BubbleVisualization.java)113
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/outlier/package-info.java26
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/package-info.java (renamed from src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/package-info.java)7
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/selection/MoveObjectsToolVisualization.java (renamed from src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/MoveObjectsToolVisualization.java)35
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/selection/SelectionConvexHullVisualization.java (renamed from src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/SelectionConvexHullVisualization.java)39
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/selection/SelectionCubeVisualization.java (renamed from src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/SelectionCubeVisualization.java)48
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/selection/SelectionDotVisualization.java (renamed from src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/SelectionDotVisualization.java)43
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/selection/SelectionToolCubeVisualization.java (renamed from src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/SelectionToolCubeVisualization.java)57
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/selection/SelectionToolDotVisualization.java (renamed from src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/SelectionToolDotVisualization.java)35
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/selection/package-info.java26
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/thumbs/ThumbnailThread.java14
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/thumbs/ThumbnailVisualization.java83
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/thumbs/Thumbnailer.java96
-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/vis2d/ClusterConvexHullVisualization.java207
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/ClusteringVisualization.java154
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/DotVisualization.java150
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/ClusterEvaluationVisFactory.java156
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/CurveVisFactory.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/HistogramVisFactory.java8
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/KeyVisFactory.java122
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/KeyVisualization.java198
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/LabelVisFactory.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/SettingsVisFactory.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/SimilarityMatrixVisualizer.java2
-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.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/workflow/EvaluationStep.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/workflow/InputStep.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/workflow/LoggingStep.java2
-rw-r--r--src/de/lmu/ifi/dbs/elki/workflow/OutputStep.java2
-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/distancefunction/MultiLPNorm.java126
-rw-r--r--src/tutorial/distancefunction/TutorialDistanceFunction.java50
-rw-r--r--src/tutorial/distancefunction/package-info.java26
-rw-r--r--src/tutorial/package-info.java (renamed from src/de/lmu/ifi/dbs/elki/database/ids/TreeSetDBIDs.java)17
-rw-r--r--test/de/lmu/ifi/dbs/elki/AllTests.java2
-rw-r--r--test/de/lmu/ifi/dbs/elki/JUnit4Test.java2
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/AbstractSimpleAlgorithmTest.java28
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/TestKNNJoin.java10
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestDBSCANResults.java2
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestDeLiCluResults.java17
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestEMResults.java5
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestOPTICSResults.java2
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestSLINKResults.java2
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestSNNClusteringResults.java2
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/TestCASHResults.java7
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/TestCOPACResults.java2
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/TestERiCResults.java4
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/TestFourCResults.java4
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/TestORCLUSResults.java4
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/TestKMeansResults.java (renamed from test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestKMeansResults.java)36
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/TestCLIQUEResults.java15
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/TestDiSHResults.java4
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/TestPROCLUSResults.java2
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/TestPreDeConResults.java2
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/TestSUBCLUResults.java8
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestABOD.java2
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestAggarwalYuEvolutionary.java2
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestAggarwalYuNaive.java2
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestDBOutlierDetection.java2
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestDBOutlierScore.java2
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestGaussianModel.java2
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestGaussianUniformMixture.java2
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestINFLO.java2
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestKNNOutlier.java2
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestKNNWeightOutlier.java2
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestLDOF.java4
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestLOCI.java6
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestLOF.java2
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestLoOP.java4
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestOPTICSOF.java2
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestOnlineLOF.java2
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestReferenceBasedOutlierDetection.java2
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestSOD.java5
-rw-r--r--test/de/lmu/ifi/dbs/elki/algorithm/outlier/meta/TestFeatureBagging.java4
-rw-r--r--test/de/lmu/ifi/dbs/elki/data/spatial/TestPolygon.java2
-rw-r--r--test/de/lmu/ifi/dbs/elki/distance/distancefunction/SpatialPrimitiveDistanceFunctionTest.java148
-rw-r--r--test/de/lmu/ifi/dbs/elki/evaluation/paircounting/TestClusterContingencyTable.java (renamed from test/de/lmu/ifi/dbs/elki/evaluation/TestPairCountingFMeasure.java)30
-rw-r--r--test/de/lmu/ifi/dbs/elki/evaluation/roc/TestComputeROC.java (renamed from test/de/lmu/ifi/dbs/elki/evaluation/TestComputeROC.java)5
-rw-r--r--test/de/lmu/ifi/dbs/elki/index/TestIndexStructures.java11
-rw-r--r--test/de/lmu/ifi/dbs/elki/index/preprocessed/TestMaterializedKNNAndRKNNPreprocessor.java11
-rw-r--r--test/de/lmu/ifi/dbs/elki/logging/TestOutputStreamLogger.java2
-rw-r--r--test/de/lmu/ifi/dbs/elki/math/TestAffineTransformation.java2
-rw-r--r--test/de/lmu/ifi/dbs/elki/math/TestKernelDensityFitting.java7
-rw-r--r--test/de/lmu/ifi/dbs/elki/math/TestLevenbergMarquardtGaussianFitting.java2
-rw-r--r--test/de/lmu/ifi/dbs/elki/math/TestMathUtil.java52
-rw-r--r--test/de/lmu/ifi/dbs/elki/math/TestMatrix.java2
-rw-r--r--test/de/lmu/ifi/dbs/elki/math/TestWeightFunctions.java2
-rw-r--r--test/de/lmu/ifi/dbs/elki/math/histograms/TestFlexiHistogram.java (renamed from test/de/lmu/ifi/dbs/elki/math/TestFlexiHistogram.java)14
-rw-r--r--test/de/lmu/ifi/dbs/elki/math/histograms/TestReplacingHistogram.java (renamed from test/de/lmu/ifi/dbs/elki/math/TestReplacingHistogram.java)10
-rw-r--r--test/de/lmu/ifi/dbs/elki/math/scales/TestLinearScale.java (renamed from test/de/lmu/ifi/dbs/elki/visualization/TestLinearScale.java)6
-rw-r--r--test/de/lmu/ifi/dbs/elki/persistent/TestByteArrayUtil.java2
-rw-r--r--test/de/lmu/ifi/dbs/elki/persistent/TestOnDiskArray.java2
-rw-r--r--test/de/lmu/ifi/dbs/elki/persistent/TestOnDiskUpperTriangleMatrix.java2
-rw-r--r--test/de/lmu/ifi/dbs/elki/utilities/TestBitsUtil.java186
-rw-r--r--test/de/lmu/ifi/dbs/elki/utilities/datastructures/TestHeap.java64
-rw-r--r--test/de/lmu/ifi/dbs/elki/utilities/datastructures/TestQuickSelect.java (renamed from test/de/lmu/ifi/dbs/elki/math/TestQuickSelect.java)12
-rw-r--r--test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestHeap.java235
-rw-r--r--test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestHeapPerformance.java113
-rw-r--r--test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestTiedTopBoundedHeap.java (renamed from test/de/lmu/ifi/dbs/elki/utilities/datastructures/TestTiedTopBoundedHeap.java)4
-rw-r--r--test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestTiedTopBoundedUpdatableHeap.java114
-rw-r--r--test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestTopBoundedHeap.java (renamed from test/de/lmu/ifi/dbs/elki/utilities/datastructures/TestTopBoundedHeap.java)4
-rw-r--r--test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestUpdatableHeap.java88
1540 files changed, 45969 insertions, 15450 deletions
diff --git a/debian/changelog b/debian/changelog
index 93e85cf2..a41e3cf0 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,19 @@
+elki (0.5.0~beta2-1) unstable; urgency=low
+
+ * New upstream beta release.
+ * Needs GNU Trove 3, in NEW.
+ * Build with OpenJDK7, as OpenJDK6 complains.
+
+ -- Erich Schubert <erich@debian.org> Sat, 02 Jun 2012 17:47:03 +0200
+
+elki (0.5.0~beta1-1) unstable; urgency=low
+
+ * New upstream beta release.
+ * Needs GNU Trove 3, not yet in Debian (private package)
+ * Build with OpenJDK7, as OpenJDK6 complains.
+
+ -- Erich Schubert <erich@debian.org> Thu, 03 May 2012 06:41:22 +0200
+
elki (0.4.1-1) unstable; urgency=low
* New upstream bug fix release (a couple of minor fixes)
diff --git a/debian/control b/debian/control
index a5887ef4..5f3d6147 100644
--- a/debian/control
+++ b/debian/control
@@ -2,13 +2,13 @@ Source: elki
Section: science
Priority: extra
Maintainer: Erich Schubert <erich@debian.org>
-Build-Depends: openjdk-7-jdk | sun-java6-jdk, fop, ant, debhelper (>= 8.0.0)
+Build-Depends: openjdk-7-jdk, fop, libtrove3-java, ant, debhelper (>= 8.0.0)
Standards-Version: 3.9.2
Homepage: http://elki.dbs.ifi.lmu.de/
Package: elki
Architecture: all
-Depends: openjdk-7-jre | java6-runtime, fop, java-wrappers, ${misc:Depends}
+Depends: openjdk-7-jre | java6-runtime, fop, libtrove3-java, java-wrappers, ${misc:Depends}
Suggests: openjdk7-jdk | java6-sdk
Description: Data mining algorithm development framework
ELKI: "Environment for Developing KDD-Applications Supported by
diff --git a/debian/patches/build.patch b/debian/patches/build.patch
index 9bc8c024..4b378aef 100644
--- a/debian/patches/build.patch
+++ b/debian/patches/build.patch
@@ -1,9 +1,8 @@
-# Debian build.xml file
-Index: elki-0.4.1/build.xml
+Index: elki-0.5.0~beta2/build.xml
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
-+++ elki-0.4.1/build.xml 2012-01-30 21:01:27.000000000 +0100
-@@ -0,0 +1,57 @@
++++ elki-0.5.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"/>
+ <property name="build" location="build"/>
@@ -11,7 +10,7 @@ Index: elki-0.4.1/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.4.1"/>
++ <property name="version" value="0.5.0~beta2"/>
+
+ <target name="init">
+ <!-- Create the build directory structure used by compile -->
@@ -27,6 +26,7 @@ Index: elki-0.4.1/build.xml
+ <pathelement path="/usr/share/java/batik.jar" />
+ <pathelement path="/usr/share/java/xml-commons-external.jar" />
+ <pathelement path="/usr/share/java/fop.jar" />
++ <pathelement path="/usr/share/java/trove-3.jar" />
+ </classpath>
+ <src path="${src}" />
+ </javac>
@@ -49,7 +49,7 @@ Index: elki-0.4.1/build.xml
+ <attribute name="Implementation-Title" value="${title}" />
+ <attribute name="Implementation-Version" value="${version}" />
+ <attribute name="Implementation-URL" value="${url}" />
-+ <attribute name="Class-Path" value="batik.jar fop.jar xml-commons-external.jar" />
++ <attribute name="Class-Path" value="batik.jar fop.jar trove-3.jar xml-commons-external.jar" />
+ </manifest>
+ </jar>
+ <!-- build source jar -->
diff --git a/src/META-INF/MANIFEST.MF b/src/META-INF/MANIFEST.MF
index 7ec310dc..1746b30f 100644
--- a/src/META-INF/MANIFEST.MF
+++ b/src/META-INF/MANIFEST.MF
@@ -167,27 +167,8 @@ Implementation-Version: 1.1
Implementation-Vendor: World Wide Web Consortium
Implementation-URL: http://www.w3.org/TR/SVG11/java.html
-Name: org/apache/avalon
-Comment: Apache Avalon from FOP PDF Transcoder package
-Implementation-Title: Apache Avalon
-Implementation-Vendor: Apache Software Foundation
-Implementation-URL: http://avalon.apache.org/
-
-Name: org/apache/fop
-Comment: FOP PDF Transcoder package for Apache Batik
-Implementation-Title: FOP PDF Transcoder package
-Implementation-Version: 1.0beta2
-Implementation-Vendor: Apache Software Foundation
-Implementation-URL: http://xmlgraphics.apache.org/fop/
-
-Name: org/apache/commons/io
-Comment: Apache Commons IO from FOP Transcoder package
-Implementation-Title: Apache Commons IO
-Implementation-Vendor: Apache Software Foundation
-Implementation-URL: http://commons.apache.org/io/
-
-Name: org/apache/commons/logging
-Comment: Apache Commons Logging from FOP Transcoder package
-Implementation-Title: Apache Commons Logging
-Implementation-Vendor: Apache Software Foundation
-Implementation-URL: http://commons.apache.org/logging/
+Name: gnu/trove
+Comment: GNU Trove
+Implementation-Title: Trove
+Implementation-Version: 3.0.1
+Implementation-URL: http://trove4j.sourceforge.net/
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.AbstractDistanceBasedAlgorithm
new file mode 100644
index 00000000..dd8d4482
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm
@@ -0,0 +1,24 @@
+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.DBSCAN
+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.correlation.HiCO
+de.lmu.ifi.dbs.elki.algorithm.clustering.subspace.HiSC
+de.lmu.ifi.dbs.elki.algorithm.outlier.ABOD
+de.lmu.ifi.dbs.elki.algorithm.outlier.DBOutlierDetection
+de.lmu.ifi.dbs.elki.algorithm.outlier.DBOutlierScore
+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.LDOF
+de.lmu.ifi.dbs.elki.algorithm.outlier.LOCI
+de.lmu.ifi.dbs.elki.algorithm.outlier.OPTICSOF
+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
+de.lmu.ifi.dbs.elki.algorithm.statistics.RankingQualityHistogram
+de.lmu.ifi.dbs.elki.algorithm.statistics.DistanceStatisticsWithClasses
+de.lmu.ifi.dbs.elki.algorithm.statistics.EvaluateRankingQuality
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.AbstractPrimitiveDistanceBasedAlgorithm b/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.AbstractPrimitiveDistanceBasedAlgorithm
new file mode 100644
index 00000000..375277a4
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.AbstractPrimitiveDistanceBasedAlgorithm
@@ -0,0 +1,3 @@
+de.lmu.ifi.dbs.elki.algorithm.DependencyDerivator
+de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMeansLloyd
+de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMeansMacQueen
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
new file mode 100644
index 00000000..466a746a
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.Algorithm
@@ -0,0 +1,76 @@
+de.lmu.ifi.dbs.elki.algorithm.NullAlgorithm
+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.kmeans.KMeansLloyd
+de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMeansMacQueen
+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
+de.lmu.ifi.dbs.elki.algorithm.clustering.correlation.ERiC
+de.lmu.ifi.dbs.elki.algorithm.clustering.correlation.FourC
+de.lmu.ifi.dbs.elki.algorithm.clustering.correlation.HiCO
+de.lmu.ifi.dbs.elki.algorithm.clustering.correlation.LMCLUS
+de.lmu.ifi.dbs.elki.algorithm.clustering.correlation.ORCLUS
+de.lmu.ifi.dbs.elki.algorithm.clustering.subspace.CLIQUE
+de.lmu.ifi.dbs.elki.algorithm.clustering.subspace.DiSH
+de.lmu.ifi.dbs.elki.algorithm.clustering.subspace.HiSC
+de.lmu.ifi.dbs.elki.algorithm.clustering.subspace.PreDeCon
+de.lmu.ifi.dbs.elki.algorithm.clustering.subspace.PROCLUS
+de.lmu.ifi.dbs.elki.algorithm.clustering.subspace.SUBCLU
+de.lmu.ifi.dbs.elki.algorithm.clustering.trivial.ByLabelClustering
+de.lmu.ifi.dbs.elki.algorithm.clustering.trivial.ByLabelHierarchicalClustering
+de.lmu.ifi.dbs.elki.algorithm.clustering.trivial.ByModelClustering
+de.lmu.ifi.dbs.elki.algorithm.clustering.trivial.TrivialAllInOne
+de.lmu.ifi.dbs.elki.algorithm.clustering.trivial.TrivialAllNoise
+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.DBOutlierDetection
+de.lmu.ifi.dbs.elki.algorithm.outlier.DBOutlierScore
+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.INFLO
+de.lmu.ifi.dbs.elki.algorithm.outlier.KNNOutlier
+de.lmu.ifi.dbs.elki.algorithm.outlier.KNNWeightOutlier
+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.OPTICSOF
+de.lmu.ifi.dbs.elki.algorithm.outlier.OUTRES
+de.lmu.ifi.dbs.elki.algorithm.outlier.ReferenceBasedOutlierDetection
+de.lmu.ifi.dbs.elki.algorithm.outlier.SOD
+de.lmu.ifi.dbs.elki.algorithm.outlier.OnlineLOF
+de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.CTLuGLSBackwardSearchAlgorithm
+de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.CTLuMeanMultipleAttributes
+de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.CTLuMedianAlgorithm
+de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.CTLuMedianMultipleAttributes
+de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.CTLuMoranScatterplotOutlier
+de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.CTLuRandomWalkEC
+de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.CTLuScatterplotOutlier
+de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.CTLuZTestOutlier
+de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.SLOM
+de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.SOF
+de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.TrimmedMeanApproach
+de.lmu.ifi.dbs.elki.algorithm.outlier.meta.ExternalDoubleOutlierScore
+de.lmu.ifi.dbs.elki.algorithm.outlier.meta.FeatureBagging
+de.lmu.ifi.dbs.elki.algorithm.outlier.meta.RescaleMetaOutlierAlgorithm
+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.statistics.AveragePrecisionAtK
+de.lmu.ifi.dbs.elki.algorithm.statistics.EvaluateRankingQuality
+de.lmu.ifi.dbs.elki.algorithm.statistics.RankingQualityHistogram
+de.lmu.ifi.dbs.elki.algorithm.statistics.DistanceStatisticsWithClasses
+# de.lmu.ifi.dbs.elki.algorithm.DummyAlgorithm
+de.lmu.ifi.dbs.elki.algorithm.APRIORI
+de.lmu.ifi.dbs.elki.algorithm.DependencyDerivator
+de.lmu.ifi.dbs.elki.algorithm.KNNDistanceOrder
+de.lmu.ifi.dbs.elki.algorithm.KNNJoin
+de.lmu.ifi.dbs.elki.algorithm.MaterializeDistances
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
new file mode 100644
index 00000000..f429b53e
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.ClusteringAlgorithm
@@ -0,0 +1,21 @@
+de.lmu.ifi.dbs.elki.algorithm.clustering.DBSCAN
+de.lmu.ifi.dbs.elki.algorithm.clustering.EM
+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.OPTICSXi
+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
+de.lmu.ifi.dbs.elki.algorithm.clustering.correlation.ERiC
+de.lmu.ifi.dbs.elki.algorithm.clustering.correlation.FourC
+de.lmu.ifi.dbs.elki.algorithm.clustering.correlation.ORCLUS
+de.lmu.ifi.dbs.elki.algorithm.clustering.subspace.CLIQUE
+de.lmu.ifi.dbs.elki.algorithm.clustering.subspace.DiSH
+de.lmu.ifi.dbs.elki.algorithm.clustering.subspace.PreDeCon
+de.lmu.ifi.dbs.elki.algorithm.clustering.subspace.PROCLUS
+de.lmu.ifi.dbs.elki.algorithm.clustering.subspace.SUBCLU
+de.lmu.ifi.dbs.elki.algorithm.clustering.trivial.ByLabelClustering
+de.lmu.ifi.dbs.elki.algorithm.clustering.trivial.ByLabelHierarchicalClustering
+de.lmu.ifi.dbs.elki.algorithm.clustering.trivial.ByModelClustering
+de.lmu.ifi.dbs.elki.algorithm.clustering.trivial.TrivialAllInOne
+de.lmu.ifi.dbs.elki.algorithm.clustering.trivial.TrivialAllNoise
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.OPTICSTypeAlgorithm b/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.OPTICSTypeAlgorithm
new file mode 100644
index 00000000..98ae4fdb
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.OPTICSTypeAlgorithm
@@ -0,0 +1,4 @@
+de.lmu.ifi.dbs.elki.algorithm.clustering.OPTICS
+de.lmu.ifi.dbs.elki.algorithm.clustering.DeLiClu
+de.lmu.ifi.dbs.elki.algorithm.clustering.correlation.HiCO
+de.lmu.ifi.dbs.elki.algorithm.clustering.subspace.HiSC
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
new file mode 100644
index 00000000..b5006bd4
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMeansInitialization
@@ -0,0 +1,4 @@
+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
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
new file mode 100644
index 00000000..14bb81fa
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.outlier.OutlierAlgorithm
@@ -0,0 +1,38 @@
+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.DBOutlierDetection
+de.lmu.ifi.dbs.elki.algorithm.outlier.DBOutlierScore
+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.INFLO
+de.lmu.ifi.dbs.elki.algorithm.outlier.KNNOutlier
+de.lmu.ifi.dbs.elki.algorithm.outlier.KNNWeightOutlier
+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.OPTICSOF
+de.lmu.ifi.dbs.elki.algorithm.outlier.OUTRES
+de.lmu.ifi.dbs.elki.algorithm.outlier.ReferenceBasedOutlierDetection
+de.lmu.ifi.dbs.elki.algorithm.outlier.SOD
+de.lmu.ifi.dbs.elki.algorithm.outlier.OnlineLOF
+de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.CTLuGLSBackwardSearchAlgorithm
+de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.CTLuMeanMultipleAttributes
+de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.CTLuMedianAlgorithm
+de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.CTLuMedianMultipleAttributes
+de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.CTLuMoranScatterplotOutlier
+de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.CTLuRandomWalkEC
+de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.CTLuScatterplotOutlier
+de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.CTLuZTestOutlier
+de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.SLOM
+de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.SOF
+de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.TrimmedMeanApproach
+de.lmu.ifi.dbs.elki.algorithm.outlier.meta.ExternalDoubleOutlierScore
+de.lmu.ifi.dbs.elki.algorithm.outlier.meta.FeatureBagging
+de.lmu.ifi.dbs.elki.algorithm.outlier.meta.RescaleMetaOutlierAlgorithm
+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
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.neighborhood.NeighborSetPredicate$Factory b/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.neighborhood.NeighborSetPredicate$Factory
new file mode 100644
index 00000000..a68f645b
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.neighborhood.NeighborSetPredicate$Factory
@@ -0,0 +1,3 @@
+de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.neighborhood.ExtendedNeighborhood$Factory
+de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.neighborhood.ExternalNeighborhood$Factory
+de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.neighborhood.PrecomputedKNearestNeighborNeighborhood$Factory
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.data.ClassLabel$Factory b/src/META-INF/elki/de.lmu.ifi.dbs.elki.data.ClassLabel$Factory
new file mode 100644
index 00000000..4282b1f1
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.data.ClassLabel$Factory
@@ -0,0 +1,2 @@
+de.lmu.ifi.dbs.elki.data.SimpleClassLabel$Factory
+de.lmu.ifi.dbs.elki.data.HierarchicalClassLabel$Factory
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.data.NumberVector b/src/META-INF/elki/de.lmu.ifi.dbs.elki.data.NumberVector
new file mode 100644
index 00000000..9ee14dab
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.data.NumberVector
@@ -0,0 +1,10 @@
+de.lmu.ifi.dbs.elki.data.DoubleVector
+de.lmu.ifi.dbs.elki.data.BitVector
+de.lmu.ifi.dbs.elki.data.FloatVector
+de.lmu.ifi.dbs.elki.data.IntegerVector
+de.lmu.ifi.dbs.elki.data.OneDimensionalDoubleVector
+de.lmu.ifi.dbs.elki.data.ParameterizationFunction
+de.lmu.ifi.dbs.elki.data.SparseFloatVector
+# de.lmu.ifi.dbs.elki.math.linearalgebra.Vector
+# de.lmu.ifi.dbs.elki.math.linearalgebra.Centroid
+# de.lmu.ifi.dbs.elki.math.linearalgebra.ProjectedCentroid \ No newline at end of file
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.data.images.ComputeColorHistogram b/src/META-INF/elki/de.lmu.ifi.dbs.elki.data.images.ComputeColorHistogram
new file mode 100644
index 00000000..94c65a07
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.data.images.ComputeColorHistogram
@@ -0,0 +1,3 @@
+de.lmu.ifi.dbs.elki.data.images.ComputeHSBColorHistogram
+de.lmu.ifi.dbs.elki.data.images.ComputeNaiveHSBColorHistogram
+de.lmu.ifi.dbs.elki.data.images.ComputeNaiveRGBColorHistogram
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.database.Database b/src/META-INF/elki/de.lmu.ifi.dbs.elki.database.Database
new file mode 100644
index 00000000..acb11415
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.database.Database
@@ -0,0 +1,3 @@
+de.lmu.ifi.dbs.elki.database.StaticArrayDatabase
+de.lmu.ifi.dbs.elki.database.HashmapDatabase
+# de.lmu.ifi.dbs.elki.database.ProxyDatabase
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.database.UpdatableDatabase b/src/META-INF/elki/de.lmu.ifi.dbs.elki.database.UpdatableDatabase
new file mode 100644
index 00000000..486453f7
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.database.UpdatableDatabase
@@ -0,0 +1 @@
+de.lmu.ifi.dbs.elki.database.HashmapDatabase
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.datasource.DatabaseConnection b/src/META-INF/elki/de.lmu.ifi.dbs.elki.datasource.DatabaseConnection
new file mode 100644
index 00000000..942dc71f
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.datasource.DatabaseConnection
@@ -0,0 +1,11 @@
+de.lmu.ifi.dbs.elki.datasource.FileBasedDatabaseConnection
+de.lmu.ifi.dbs.elki.datasource.ExternalIDJoinDatabaseConnection
+de.lmu.ifi.dbs.elki.datasource.LabelJoinDatabaseConnection
+de.lmu.ifi.dbs.elki.datasource.GeneratorXMLDatabaseConnection
+de.lmu.ifi.dbs.elki.datasource.RandomDoubleVectorDatabaseConnection
+de.lmu.ifi.dbs.elki.datasource.ConcatenateFilesDatabaseConnection
+de.lmu.ifi.dbs.elki.datasource.EmptyDatabaseConnection
+de.lmu.ifi.dbs.elki.datasource.DBIDRangeDatabaseConnection
+de.lmu.ifi.dbs.elki.datasource.PresortedBlindJoinDatabaseConnection
+# de.lmu.ifi.dbs.elki.datasource.InputStreamDatabaseConnection
+# de.lmu.ifi.dbs.elki.datasource.ArrayAdapterDatabaseConnection \ 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
new file mode 100644
index 00000000..3c159ed2
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.datasource.filter.ObjectFilter
@@ -0,0 +1,21 @@
+de.lmu.ifi.dbs.elki.datasource.filter.ByLabelFilter
+de.lmu.ifi.dbs.elki.datasource.filter.ClassLabelFilter
+de.lmu.ifi.dbs.elki.datasource.filter.DoubleVectorProjectionFilter
+de.lmu.ifi.dbs.elki.datasource.filter.DoubleVectorRandomProjectionFilter
+de.lmu.ifi.dbs.elki.datasource.filter.ExternalIDFilter
+de.lmu.ifi.dbs.elki.datasource.filter.FixedDBIDsFilter
+de.lmu.ifi.dbs.elki.datasource.filter.NoOpFilter
+de.lmu.ifi.dbs.elki.datasource.filter.NoMissingValuesFilter
+de.lmu.ifi.dbs.elki.datasource.filter.ShuffleObjectsFilter
+de.lmu.ifi.dbs.elki.datasource.filter.SortByLabelFilter
+de.lmu.ifi.dbs.elki.datasource.filter.SparseFloatVectorProjectionFilter
+de.lmu.ifi.dbs.elki.datasource.filter.SparseFloatVectorRandomProjectionFilter
+de.lmu.ifi.dbs.elki.datasource.filter.SparseVectorFieldFilter
+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.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
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
new file mode 100644
index 00000000..4002f056
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.datasource.parser.Parser
@@ -0,0 +1,10 @@
+de.lmu.ifi.dbs.elki.datasource.parser.NumberVectorLabelParser
+de.lmu.ifi.dbs.elki.datasource.parser.ArffParser
+de.lmu.ifi.dbs.elki.datasource.parser.DoubleVectorLabelParser
+de.lmu.ifi.dbs.elki.datasource.parser.FloatVectorLabelParser
+de.lmu.ifi.dbs.elki.datasource.parser.SparseBitVectorLabelParser
+de.lmu.ifi.dbs.elki.datasource.parser.SparseFloatVectorLabelParser
+de.lmu.ifi.dbs.elki.datasource.parser.TermFrequencyParser
+de.lmu.ifi.dbs.elki.datasource.parser.BitVectorLabelParser
+de.lmu.ifi.dbs.elki.datasource.parser.ParameterizationFunctionLabelParser
+de.lmu.ifi.dbs.elki.datasource.parser.SimplePolygonParser
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractIndexBasedDistanceFunction b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractIndexBasedDistanceFunction
new file mode 100644
index 00000000..3c32949a
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractIndexBasedDistanceFunction
@@ -0,0 +1,7 @@
+de.lmu.ifi.dbs.elki.distance.distancefunction.LocallyWeightedDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.SharedNearestNeighborJaccardDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.ERiCDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.PCABasedCorrelationDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.LocalSubspaceDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.DiSHDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.HiSCDistanceFunction
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
new file mode 100644
index 00000000..45c31e56
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction
@@ -0,0 +1,53 @@
+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.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.CanberraDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.JeffreyDivergenceDistanceFunction
+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.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.colorhistogram.HSBHistogramQuadraticDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.colorhistogram.HistogramIntersectionDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.colorhistogram.RGBHistogramQuadraticDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.PearsonCorrelationDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.SquaredPearsonCorrelationDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.ERiCDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.PCABasedCorrelationDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.WeightedPearsonCorrelationDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.WeightedSquaredPearsonCorrelationDistanceFunction
+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.subspace.DimensionSelectingDistanceFunction
+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.DiSHDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.HiSCDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.LocalSubspaceDistanceFunction
+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.similarityfunction.kernel.FooKernelFunction
+# de.lmu.ifi.dbs.elki.distance.similarityfunction.kernel.LinearKernelFunction
+# de.lmu.ifi.dbs.elki.distance.similarityfunction.kernel.PolynomialKernelFunction
+# tutorial.distancefunction.MultiLPNorm
+# tutorial.distancefunction.TutorialDistanceFunction
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
new file mode 100644
index 00000000..bb3847a9
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.DoubleNorm
@@ -0,0 +1,10 @@
+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.subspace.SubspaceEuclideanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.SubspaceLPNormDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.SubspaceManhattanDistanceFunction
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.FilteredLocalPCABasedDistanceFunction b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.FilteredLocalPCABasedDistanceFunction
new file mode 100644
index 00000000..df161a0a
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.FilteredLocalPCABasedDistanceFunction
@@ -0,0 +1,4 @@
+de.lmu.ifi.dbs.elki.distance.distancefunction.LocallyWeightedDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.ERiCDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.PCABasedCorrelationDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.LocalSubspaceDistanceFunction
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.LocallyWeightedDistanceFunction b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.LocallyWeightedDistanceFunction
new file mode 100644
index 00000000..6b852263
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.LocallyWeightedDistanceFunction
@@ -0,0 +1 @@
+de.lmu.ifi.dbs.elki.distance.distancefunction.LocallyWeightedDistanceFunction
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
new file mode 100644
index 00000000..ab889ff6
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.NumberVectorDistanceFunction
@@ -0,0 +1,29 @@
+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.ArcCosineDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.CosineDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.SquaredEuclideanDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.CanberraDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.JeffreyDivergenceDistanceFunction
+# 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.colorhistogram.HSBHistogramQuadraticDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.colorhistogram.HistogramIntersectionDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.colorhistogram.RGBHistogramQuadraticDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.PearsonCorrelationDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.SquaredPearsonCorrelationDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.WeightedPearsonCorrelationDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.WeightedSquaredPearsonCorrelationDistanceFunction
+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.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
+# tutorial.distancefunction.MultiLPNorm
+# tutorial.distancefunction.TutorialDistanceFunction \ No newline at end of file
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
new file mode 100644
index 00000000..bc770e74
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction
@@ -0,0 +1,36 @@
+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.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.CanberraDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.JeffreyDivergenceDistanceFunction
+# 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.colorhistogram.HSBHistogramQuadraticDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.colorhistogram.HistogramIntersectionDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.colorhistogram.RGBHistogramQuadraticDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.PearsonCorrelationDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.SquaredPearsonCorrelationDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.WeightedPearsonCorrelationDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.WeightedSquaredPearsonCorrelationDistanceFunction
+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.subspace.DimensionSelectingDistanceFunction
+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.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.similarityfunction.kernel.FooKernelFunction
+# de.lmu.ifi.dbs.elki.distance.similarityfunction.kernel.LinearKernelFunction
+# de.lmu.ifi.dbs.elki.distance.similarityfunction.kernel.PolynomialKernelFunction
+# tutorial.distancefunction.MultiLPNorm
+# tutorial.distancefunction.TutorialDistanceFunction
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
new file mode 100644
index 00000000..3bf5428e
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction
@@ -0,0 +1,33 @@
+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.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.CanberraDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.JeffreyDivergenceDistanceFunction
+# 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.colorhistogram.HSBHistogramQuadraticDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.colorhistogram.HistogramIntersectionDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.colorhistogram.RGBHistogramQuadraticDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.PearsonCorrelationDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.SquaredPearsonCorrelationDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.WeightedPearsonCorrelationDistanceFunction
+# de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.WeightedSquaredPearsonCorrelationDistanceFunction
+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.subspace.DimensionSelectingDistanceFunction
+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.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
+# tutorial.distancefunction.MultiLPNorm
+# tutorial.distancefunction.TutorialDistanceFunction
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
new file mode 100644
index 00000000..bc1c6777
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDistanceFunction
@@ -0,0 +1,15 @@
+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.ArcCosineDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.CosineDistanceFunction
+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.colorhistogram.HistogramIntersectionDistanceFunction
+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
+de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.SubspaceManhattanDistanceFunction \ No newline at end of file
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
new file mode 100644
index 00000000..a5e3364e
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDoubleDistanceFunction
@@ -0,0 +1,15 @@
+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.ArcCosineDistanceFunction
+de.lmu.ifi.dbs.elki.distance.distancefunction.CosineDistanceFunction
+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.colorhistogram.HistogramIntersectionDistanceFunction
+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
+de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.SubspaceManhattanDistanceFunction
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.external.DistanceParser b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.external.DistanceParser
new file mode 100644
index 00000000..199f56b9
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.external.DistanceParser
@@ -0,0 +1 @@
+de.lmu.ifi.dbs.elki.distance.distancefunction.external.NumberDistanceParser \ 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.AbstractDimensionsSelectingDoubleDistanceFunction
new file mode 100644
index 00000000..f0a38487
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.AbstractDimensionsSelectingDoubleDistanceFunction
@@ -0,0 +1,3 @@
+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
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.similarityfunction.NormalizedSimilarityFunction b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.similarityfunction.NormalizedSimilarityFunction
new file mode 100644
index 00000000..6d8add0c
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.similarityfunction.NormalizedSimilarityFunction
@@ -0,0 +1 @@
+de.lmu.ifi.dbs.elki.distance.similarityfunction.FractionalSharedNearestNeighborSimilarityFunction
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
new file mode 100644
index 00000000..33284aa0
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.similarityfunction.PrimitiveSimilarityFunction
@@ -0,0 +1,4 @@
+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
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
new file mode 100644
index 00000000..bc5ffaa6
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.distance.similarityfunction.SimilarityFunction
@@ -0,0 +1,6 @@
+de.lmu.ifi.dbs.elki.distance.similarityfunction.FractionalSharedNearestNeighborSimilarityFunction
+de.lmu.ifi.dbs.elki.distance.similarityfunction.SharedNearestNeighborSimilarityFunction
+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
+# de.lmu.ifi.dbs.elki.distance.similarityfunction.kernel.PolynomialKernelFunction
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
new file mode 100644
index 00000000..f2813425
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.evaluation.Evaluator
@@ -0,0 +1,8 @@
+de.lmu.ifi.dbs.elki.evaluation.clustering.EvaluateClustering
+de.lmu.ifi.dbs.elki.evaluation.clustering.pairsegments.ClusterPairSegmentAnalysis
+de.lmu.ifi.dbs.elki.evaluation.roc.ComputeROCCurve
+de.lmu.ifi.dbs.elki.evaluation.histogram.ComputeOutlierHistogram
+de.lmu.ifi.dbs.elki.evaluation.index.IndexPurity
+de.lmu.ifi.dbs.elki.evaluation.index.IndexStatistics
+de.lmu.ifi.dbs.elki.evaluation.outlier.JudgeOutlierScores
+de.lmu.ifi.dbs.elki.evaluation.similaritymatrix.ComputeSimilarityMatrixImage
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
new file mode 100644
index 00000000..6c0fff30
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.IndexFactory
@@ -0,0 +1,24 @@
+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.rdknn.RdKNNTreeFactory
+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.vafile.VAFile$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
+de.lmu.ifi.dbs.elki.index.preprocessed.knn.MetricalIndexApproximationMaterializeKNNPreprocessor$Factory
+de.lmu.ifi.dbs.elki.index.preprocessed.knn.PartitionApproximationMaterializeKNNPreprocessor$Factory
+de.lmu.ifi.dbs.elki.index.preprocessed.knn.SpatialApproximationMaterializeKNNPreprocessor$Factory
+de.lmu.ifi.dbs.elki.index.preprocessed.knn.RandomSampleKNNPreprocessor$Factory
+de.lmu.ifi.dbs.elki.index.preprocessed.localpca.KNNQueryFilteredPCAIndex$Factory
+de.lmu.ifi.dbs.elki.index.preprocessed.localpca.RangeQueryFilteredPCAIndex$Factory
+de.lmu.ifi.dbs.elki.index.preprocessed.preference.DiSHPreferenceVectorIndex$Factory
+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
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
new file mode 100644
index 00000000..cc1e2e56
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.KNNIndex
@@ -0,0 +1,17 @@
+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.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.MaterializeKNNAndRKNNPreprocessor
+de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNPreprocessor
+de.lmu.ifi.dbs.elki.index.preprocessed.knn.KNNJoinMaterializeKNNPreprocessor
+de.lmu.ifi.dbs.elki.index.preprocessed.knn.MetricalIndexApproximationMaterializeKNNPreprocessor
+de.lmu.ifi.dbs.elki.index.preprocessed.knn.PartitionApproximationMaterializeKNNPreprocessor
+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 \ No newline at end of file
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
new file mode 100644
index 00000000..04293f79
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.RKNNIndex
@@ -0,0 +1,6 @@
+de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNAndRKNNPreprocessor
+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.tree.spatial.rstarvariants.rdknn.RdKNNTree
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
new file mode 100644
index 00000000..d39d1bbb
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.RangeIndex
@@ -0,0 +1,10 @@
+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.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.VAFile \ No newline at end of file
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.preprocessed.LocalProjectionIndex$Factory b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.preprocessed.LocalProjectionIndex$Factory
new file mode 100644
index 00000000..296ec2ae
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.preprocessed.LocalProjectionIndex$Factory
@@ -0,0 +1,4 @@
+de.lmu.ifi.dbs.elki.index.preprocessed.localpca.KNNQueryFilteredPCAIndex$Factory
+de.lmu.ifi.dbs.elki.index.preprocessed.localpca.RangeQueryFilteredPCAIndex$Factory
+de.lmu.ifi.dbs.elki.index.preprocessed.subspaceproj.FourCSubspaceIndex$Factory
+de.lmu.ifi.dbs.elki.index.preprocessed.subspaceproj.PreDeConSubspaceIndex$Factory
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNPreprocessor b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNPreprocessor
new file mode 100644
index 00000000..293dd23a
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNPreprocessor
@@ -0,0 +1,2 @@
+de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNPreprocessor
+de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNAndRKNNPreprocessor
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.preprocessed.localpca.FilteredLocalPCAIndex$Factory b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.preprocessed.localpca.FilteredLocalPCAIndex$Factory
new file mode 100644
index 00000000..6d19b635
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.preprocessed.localpca.FilteredLocalPCAIndex$Factory
@@ -0,0 +1,2 @@
+de.lmu.ifi.dbs.elki.index.preprocessed.localpca.KNNQueryFilteredPCAIndex$Factory
+de.lmu.ifi.dbs.elki.index.preprocessed.localpca.RangeQueryFilteredPCAIndex$Factory
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.preprocessed.preference.PreferenceVectorIndex$Factory b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.preprocessed.preference.PreferenceVectorIndex$Factory
new file mode 100644
index 00000000..bbf473e6
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.preprocessed.preference.PreferenceVectorIndex$Factory
@@ -0,0 +1,2 @@
+de.lmu.ifi.dbs.elki.index.preprocessed.preference.DiSHPreferenceVectorIndex$Factory
+de.lmu.ifi.dbs.elki.index.preprocessed.preference.HiSCPreferenceVectorIndex$Factory
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.preprocessed.snn.SharedNearestNeighborIndex$Factory b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.preprocessed.snn.SharedNearestNeighborIndex$Factory
new file mode 100644
index 00000000..809e8f7e
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.preprocessed.snn.SharedNearestNeighborIndex$Factory
@@ -0,0 +1 @@
+de.lmu.ifi.dbs.elki.index.preprocessed.snn.SharedNearestNeighborPreprocessor$Factory
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.preprocessed.subspaceproj.SubspaceProjectionIndex$Factory b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.preprocessed.subspaceproj.SubspaceProjectionIndex$Factory
new file mode 100644
index 00000000..577610dc
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.preprocessed.subspaceproj.SubspaceProjectionIndex$Factory
@@ -0,0 +1,2 @@
+de.lmu.ifi.dbs.elki.index.preprocessed.subspaceproj.FourCSubspaceIndex$Factory
+de.lmu.ifi.dbs.elki.index.preprocessed.subspaceproj.PreDeConSubspaceIndex$Factory
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
new file mode 100644
index 00000000..c40d3887
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk.BulkSplit
@@ -0,0 +1,5 @@
+de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk.SortTileRecursiveBulkSplit
+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
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert.InsertionStrategy b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert.InsertionStrategy
new file mode 100644
index 00000000..3efef709
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert.InsertionStrategy
@@ -0,0 +1,5 @@
+de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert.ApproximativeLeastOverlapInsertionStrategy
+de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert.CombinedInsertionStrategy
+de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert.LeastEnlargementWithAreaInsertionStrategy
+de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert.LeastEnlargementInsertionStrategy
+de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert.LeastOverlapInsertionStrategy
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.overflow.OverflowTreatment b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.overflow.OverflowTreatment
new file mode 100644
index 00000000..9e5698ad
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.overflow.OverflowTreatment
@@ -0,0 +1,2 @@
+de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.overflow.LimitedReinsertOverflowTreatment
+de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.overflow.SplitOnlyOverflowTreatment
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split.SplitStrategy b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split.SplitStrategy
new file mode 100644
index 00000000..46523b64
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split.SplitStrategy
@@ -0,0 +1,5 @@
+de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split.TopologicalSplitter
+de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split.RTreeQuadraticSplit
+de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split.RTreeLinearSplit
+de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split.AngTanLinearSplit
+de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split.GreeneSplit
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.linearalgebra.pca.CovarianceMatrixBuilder b/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.linearalgebra.pca.CovarianceMatrixBuilder
new file mode 100644
index 00000000..95801f2c
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.linearalgebra.pca.CovarianceMatrixBuilder
@@ -0,0 +1,2 @@
+de.lmu.ifi.dbs.elki.math.linearalgebra.pca.StandardCovarianceMatrixBuilder
+de.lmu.ifi.dbs.elki.math.linearalgebra.pca.WeightedCovarianceMatrixBuilder
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.linearalgebra.pca.EigenPairFilter b/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.linearalgebra.pca.EigenPairFilter
new file mode 100644
index 00000000..67050b39
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.linearalgebra.pca.EigenPairFilter
@@ -0,0 +1,9 @@
+de.lmu.ifi.dbs.elki.math.linearalgebra.pca.FirstNEigenPairFilter
+# de.lmu.ifi.dbs.elki.math.linearalgebra.pca.NormalizingEigenPairFilter
+de.lmu.ifi.dbs.elki.math.linearalgebra.pca.LimitEigenPairFilter
+de.lmu.ifi.dbs.elki.math.linearalgebra.pca.PercentageEigenPairFilter
+de.lmu.ifi.dbs.elki.math.linearalgebra.pca.ProgressiveEigenPairFilter
+de.lmu.ifi.dbs.elki.math.linearalgebra.pca.WeakEigenPairFilter
+de.lmu.ifi.dbs.elki.math.linearalgebra.pca.RelativeEigenPairFilter
+de.lmu.ifi.dbs.elki.math.linearalgebra.pca.SignificantEigenPairFilter
+de.lmu.ifi.dbs.elki.math.linearalgebra.pca.CompositeEigenPairFilter
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.linearalgebra.pca.PCAFilteredRunner b/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.linearalgebra.pca.PCAFilteredRunner
new file mode 100644
index 00000000..7ae46e6e
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.linearalgebra.pca.PCAFilteredRunner
@@ -0,0 +1,2 @@
+de.lmu.ifi.dbs.elki.math.linearalgebra.pca.PCAFilteredRunner
+de.lmu.ifi.dbs.elki.math.linearalgebra.pca.PCAFilteredAutotuningRunner \ No newline at end of file
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions.WeightFunction b/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions.WeightFunction
new file mode 100644
index 00000000..683e3bb7
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions.WeightFunction
@@ -0,0 +1,13 @@
+de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions.ConstantWeight
+de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions.ErfcStddevWeight
+de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions.ErfcWeight
+de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions.ExponentialStddevWeight
+de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions.ExponentialWeight
+de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions.GaussStddevWeight
+de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions.GaussWeight
+de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions.InverseLinearWeight
+de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions.InverseProportionalStddevWeight
+de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions.InverseProportionalWeight
+de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions.LinearWeight
+de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions.QuadraticStddevWeight
+de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions.QuadraticWeight
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.spacefillingcurves.SpatialSorter b/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.spacefillingcurves.SpatialSorter
new file mode 100644
index 00000000..55923a7e
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.math.spacefillingcurves.SpatialSorter
@@ -0,0 +1,4 @@
+de.lmu.ifi.dbs.elki.math.spacefillingcurves.PeanoSpatialSorter
+de.lmu.ifi.dbs.elki.math.spacefillingcurves.ZCurveSpatialSorter
+de.lmu.ifi.dbs.elki.math.spacefillingcurves.HilbertSpatialSorter
+de.lmu.ifi.dbs.elki.math.spacefillingcurves.BinarySplitSpatialSorter \ 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
new file mode 100644
index 00000000..66d8fef1
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.result.ResultHandler
@@ -0,0 +1,6 @@
+de.lmu.ifi.dbs.elki.result.ResultWriter
+de.lmu.ifi.dbs.elki.visualization.gui.ResultVisualizer
+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
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.utilities.referencepoints.ReferencePointsHeuristic b/src/META-INF/elki/de.lmu.ifi.dbs.elki.utilities.referencepoints.ReferencePointsHeuristic
new file mode 100644
index 00000000..1c20e4fb
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.utilities.referencepoints.ReferencePointsHeuristic
@@ -0,0 +1,6 @@
+de.lmu.ifi.dbs.elki.utilities.referencepoints.GridBasedReferencePoints
+de.lmu.ifi.dbs.elki.utilities.referencepoints.AxisBasedReferencePoints
+de.lmu.ifi.dbs.elki.utilities.referencepoints.FullDatabaseReferencePoints
+de.lmu.ifi.dbs.elki.utilities.referencepoints.RandomGeneratedReferencePoints
+de.lmu.ifi.dbs.elki.utilities.referencepoints.RandomSampleReferencePoints
+de.lmu.ifi.dbs.elki.utilities.referencepoints.StarBasedReferencePoints
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
new file mode 100644
index 00000000..ccd91844
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.utilities.scaling.ScalingFunction
@@ -0,0 +1,19 @@
+de.lmu.ifi.dbs.elki.utilities.scaling.IdentityScaling
+de.lmu.ifi.dbs.elki.utilities.scaling.ClipScaling
+de.lmu.ifi.dbs.elki.utilities.scaling.GammaScaling
+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.MinusLogGammaScaling
+de.lmu.ifi.dbs.elki.utilities.scaling.outlier.MinusLogStandardDeviationScaling
+de.lmu.ifi.dbs.elki.utilities.scaling.outlier.MultiplicativeInverseScaling
+de.lmu.ifi.dbs.elki.utilities.scaling.outlier.OutlierGammaScaling
+de.lmu.ifi.dbs.elki.utilities.scaling.outlier.OutlierMinusLogScaling
+de.lmu.ifi.dbs.elki.utilities.scaling.outlier.OutlierSqrtScaling
+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.RankingPseudoOutlierScaling
+de.lmu.ifi.dbs.elki.utilities.scaling.outlier.SigmoidOutlierScalingFunction
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.utilities.scaling.StaticScalingFunction b/src/META-INF/elki/de.lmu.ifi.dbs.elki.utilities.scaling.StaticScalingFunction
new file mode 100644
index 00000000..13f418e7
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.utilities.scaling.StaticScalingFunction
@@ -0,0 +1,5 @@
+de.lmu.ifi.dbs.elki.utilities.scaling.IdentityScaling
+de.lmu.ifi.dbs.elki.utilities.scaling.ClipScaling
+de.lmu.ifi.dbs.elki.utilities.scaling.GammaScaling
+de.lmu.ifi.dbs.elki.utilities.scaling.LinearScaling
+de.lmu.ifi.dbs.elki.utilities.scaling.MinusLogScaling
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
new file mode 100644
index 00000000..49617959
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.utilities.scaling.outlier.OutlierScalingFunction
@@ -0,0 +1,14 @@
+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.MinusLogGammaScaling
+de.lmu.ifi.dbs.elki.utilities.scaling.outlier.MinusLogStandardDeviationScaling
+de.lmu.ifi.dbs.elki.utilities.scaling.outlier.MultiplicativeInverseScaling
+de.lmu.ifi.dbs.elki.utilities.scaling.outlier.OutlierGammaScaling
+de.lmu.ifi.dbs.elki.utilities.scaling.outlier.OutlierMinusLogScaling
+de.lmu.ifi.dbs.elki.utilities.scaling.outlier.OutlierSqrtScaling
+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
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.visualization.projector.ProjectorFactory b/src/META-INF/elki/de.lmu.ifi.dbs.elki.visualization.projector.ProjectorFactory
new file mode 100644
index 00000000..5fc4f399
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.visualization.projector.ProjectorFactory
@@ -0,0 +1,4 @@
+de.lmu.ifi.dbs.elki.visualization.projector.HistogramFactory
+de.lmu.ifi.dbs.elki.visualization.projector.ScatterPlotFactory
+de.lmu.ifi.dbs.elki.visualization.projector.ParallelPlotFactory
+de.lmu.ifi.dbs.elki.visualization.projector.OPTICSProjectorFactory \ No newline at end of file
diff --git a/src/META-INF/elki/de.lmu.ifi.dbs.elki.visualization.visualizers.VisFactory b/src/META-INF/elki/de.lmu.ifi.dbs.elki.visualization.visualizers.VisFactory
new file mode 100644
index 00000000..296024aa
--- /dev/null
+++ b/src/META-INF/elki/de.lmu.ifi.dbs.elki.visualization.visualizers.VisFactory
@@ -0,0 +1,46 @@
+de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.AxisVisualization$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.MarkerVisualization$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.PolygonVisualization$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.cluster.ClusterMeanVisualization$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.cluster.ClusterHullVisualization$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.cluster.EMClusterVisualization$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.cluster.VoronoiVisualization$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.cluster.ClusterOrderVisualization$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.index.TreeMBRVisualization$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.index.TreeSphereVisualization$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.outlier.BubbleVisualization$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.TooltipScoreVisualization$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.TooltipStringVisualization$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.ToolBox2DVisualization$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.ReferencePointsVisualization$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.density.DensityEstimationOverlay$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.selection.MoveObjectsToolVisualization$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.selection.SelectionDotVisualization$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.selection.SelectionConvexHullVisualization$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.selection.SelectionCubeVisualization$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.selection.SelectionToolCubeVisualization$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.selection.SelectionToolDotVisualization$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.histogram.ColoredHistogramVisualizer$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.parallel.LineVisualization$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.parallel.ParallelAxisVisualization$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.parallel.cluster.ClusterParallelMeanVisualization$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.parallel.cluster.ClusterOutlineVisualization$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.parallel.index.RTreeParallelVisualization$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.parallel.selection.SelectionAxisRangeVisualization$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.parallel.selection.SelectionLineVisualization$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.parallel.selection.SelectionToolAxisRangeVisualization$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.parallel.selection.SelectionToolLineVisualization$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.pairsegments.CircleSegmentsVisualizer$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.visunproj.HistogramVisFactory
+de.lmu.ifi.dbs.elki.visualization.visualizers.visunproj.ClusterEvaluationVisFactory
+de.lmu.ifi.dbs.elki.visualization.visualizers.visunproj.CurveVisFactory
+de.lmu.ifi.dbs.elki.visualization.visualizers.visunproj.LabelVisFactory
+de.lmu.ifi.dbs.elki.visualization.visualizers.visunproj.PixmapVisualizer$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.visunproj.SimilarityMatrixVisualizer$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.visunproj.KeyVisualization$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.visunproj.SettingsVisFactory
+de.lmu.ifi.dbs.elki.visualization.visualizers.optics.OPTICSClusterVisualization$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.optics.OPTICSPlotCutVisualization$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.optics.OPTICSPlotSelectionVisualization$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.optics.OPTICSPlotVisualizer$Factory
+de.lmu.ifi.dbs.elki.visualization.visualizers.optics.OPTICSSteepAreaVisualization$Factory
diff --git a/src/META-INF/services/org.apache.batik.ext.awt.image.spi.RegistryEntry b/src/META-INF/services/org.apache.batik.ext.awt.image.spi.RegistryEntry
new file mode 100644
index 00000000..f1252025
--- /dev/null
+++ b/src/META-INF/services/org.apache.batik.ext.awt.image.spi.RegistryEntry
@@ -0,0 +1 @@
+de.lmu.ifi.dbs.elki.visualization.batikutil.ThumbnailRegistryEntry \ No newline at end of file
diff --git a/src/META-INF/services/org.apache.batik.util.ParsedURLProtocolHandler b/src/META-INF/services/org.apache.batik.util.ParsedURLProtocolHandler
new file mode 100644
index 00000000..f1252025
--- /dev/null
+++ b/src/META-INF/services/org.apache.batik.util.ParsedURLProtocolHandler
@@ -0,0 +1 @@
+de.lmu.ifi.dbs.elki.visualization.batikutil.ThumbnailRegistryEntry \ 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 33c5b29d..cdad3198 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -106,10 +106,8 @@ public class KDDTask implements Parameterizable {
/**
* Method to run the specified algorithm using the specified database
* connection.
- *
- * @throws IllegalStateException on execution errors
*/
- public void run() throws IllegalStateException {
+ public void run() {
// Input step
Database db = inputStep.getDatabase();
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/APRIORI.java b/src/de/lmu/ifi/dbs/elki/algorithm/APRIORI.java
index 5cfb7073..fc346cd9 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) 2011
+ Copyright (C) 2012
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/AbstractAlgorithm.java b/src/de/lmu/ifi/dbs/elki/algorithm/AbstractAlgorithm.java
index 61a695eb..30e6e226 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -126,6 +126,9 @@ public abstract class AbstractAlgorithm<R extends Result> implements Algorithm {
if(e.getTargetException() instanceof RuntimeException) {
throw (RuntimeException) e.getTargetException();
}
+ if(e.getTargetException() instanceof AssertionError) {
+ throw (AssertionError) e.getTargetException();
+ }
throw new APIViolationException("Invoking the real 'run' method failed: " + e.getTargetException().toString(), e.getTargetException());
}
}
@@ -147,6 +150,9 @@ public abstract class AbstractAlgorithm<R extends Result> implements Algorithm {
if(e.getTargetException() instanceof RuntimeException) {
throw (RuntimeException) e.getTargetException();
}
+ if(e.getTargetException() instanceof AssertionError) {
+ throw (AssertionError) e.getTargetException();
+ }
throw new APIViolationException("Invoking the real 'run' method failed: " + e.getTargetException().toString(), e.getTargetException());
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/AbstractDistanceBasedAlgorithm.java b/src/de/lmu/ifi/dbs/elki/algorithm/AbstractDistanceBasedAlgorithm.java
index 394ea55b..70d4ba3a 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) 2011
+ Copyright (C) 2012
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/AbstractPrimitiveDistanceBasedAlgorithm.java b/src/de/lmu/ifi/dbs/elki/algorithm/AbstractPrimitiveDistanceBasedAlgorithm.java
index ad49563a..4fa12e11 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) 2011
+ Copyright (C) 2012
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/Algorithm.java b/src/de/lmu/ifi/dbs/elki/algorithm/Algorithm.java
index 40f24914..7c6f0dc5 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) 2011
+ Copyright (C) 2012
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 86fc3e51..0ecfb228 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) 2011
+ Copyright (C) 2012
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.algorithm;
*/
import java.text.NumberFormat;
-import java.util.List;
import java.util.Locale;
import de.lmu.ifi.dbs.elki.data.NumberVector;
@@ -34,9 +33,8 @@ 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.ModifiableDBIDs;
-import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
+import de.lmu.ifi.dbs.elki.database.query.knn.KNNResult;
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;
@@ -97,7 +95,7 @@ public class DependencyDerivator<V extends NumberVector<V, ?>, D extends Distanc
public static final OptionID OUTPUT_ACCURACY_ID = OptionID.getOrCreateOptionID("derivator.accuracy", "Threshold for output accuracy fraction digits.");
/**
- * Optional parameter to specify the treshold for the size of the random
+ * Optional parameter to specify the threshold for the size of the random
* sample to use, must be an integer greater than 0.
* <p/>
* Default value: the size of the complete dataset
@@ -159,17 +157,12 @@ public class DependencyDerivator<V extends NumberVector<V, ?>, D extends Distanc
DBIDs ids;
if(this.sampleSize > 0) {
if(randomsample) {
- ids = DBIDUtil.randomSample(relation.getDBIDs(), this.sampleSize, 1);
+ ids = DBIDUtil.randomSample(relation.getDBIDs(), this.sampleSize, 1l);
}
else {
DistanceQuery<V, D> distanceQuery = database.getDistanceQuery(relation, getDistanceFunction());
- List<DistanceResultPair<D>> queryResults = database.getKNNQuery(distanceQuery, this.sampleSize).getKNNForObject(centroidDV, this.sampleSize);
- ModifiableDBIDs tids = DBIDUtil.newHashSet(this.sampleSize);
- for(DistanceResultPair<D> qr : queryResults) {
- tids.add(qr.getDBID());
- }
- // Cast to non-modifiable
- ids = tids;
+ KNNResult<D> queryResults = database.getKNNQuery(distanceQuery, this.sampleSize).getKNNForObject(centroidDV, this.sampleSize);
+ ids = DBIDUtil.newHashSet(queryResults.asDBIDs());
}
}
else {
@@ -243,7 +236,7 @@ public class DependencyDerivator<V extends NumberVector<V, ?>, D extends Distanc
// +1 == + B.getColumnDimensionality()
Matrix gaussJordan = new Matrix(transposedWeakEigenvectors.getRowDimensionality(), transposedWeakEigenvectors.getColumnDimensionality() + 1);
gaussJordan.setMatrix(0, transposedWeakEigenvectors.getRowDimensionality() - 1, 0, transposedWeakEigenvectors.getColumnDimensionality() - 1, transposedWeakEigenvectors);
- gaussJordan.setColumnVector(transposedWeakEigenvectors.getColumnDimensionality(), B);
+ gaussJordan.setCol(transposedWeakEigenvectors.getColumnDimensionality(), B);
if(logger.isDebuggingFiner()) {
logger.debugFiner("Gauss-Jordan-Elimination of " + FormatUtil.format(gaussJordan, NF));
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/DummyAlgorithm.java b/src/de/lmu/ifi/dbs/elki/algorithm/DummyAlgorithm.java
index e403c623..168c69f1 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) 2011
+ Copyright (C) 2012
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.utilities.documentation.Description;
import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
/**
- * Dummy Algorithm, which just iterates over all points once, doing a 10NN query
+ * Dummy algorithm, which just iterates over all points once, doing a 10NN query
* each. Useful in testing e.g. index structures and as template for custom
- * algorithms. If you are looking for an algorithm that does <em>nothing</em>,
+ * algorithms. While this algorithm doesn't produce a result, it
+ * still performs rather expensive operations. If you are looking for an algorithm that does <em>nothing</em>,
* you must use {@link de.lmu.ifi.dbs.elki.algorithm.NullAlgorithm
- * NullAlgorithm} instead. While this algorithm doesn't produce a result, it
- * still performs rather expensive operations.
+ * NullAlgorithm} instead.
*
* @author Erich Schubert
* @param <O> Vector type
@@ -52,7 +52,7 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
* @apiviz.uses KNNQuery
*/
@Title("Dummy Algorithm")
-@Description("The algorithm executes a euclidena 10NN query on all data points, and can be used in unit testing")
+@Description("The algorithm executes an Euclidean 10NN query on all data points, and can be used in unit testing")
public class DummyAlgorithm<O extends NumberVector<?, ?>> extends AbstractAlgorithm<Result> {
/**
* The logger for this class.
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/KNNDistanceOrder.java b/src/de/lmu/ifi/dbs/elki/algorithm/KNNDistanceOrder.java
index 35065973..ac1820f9 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) 2011
+ Copyright (C) 2012
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.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.DBID;
-import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
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.KNNResult;
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;
@@ -117,9 +117,8 @@ public class KNNDistanceOrder<O, D extends Distance<D>> extends AbstractDistance
List<D> knnDistances = new ArrayList<D>(relation.size());
for(DBID id : relation.iterDBIDs()) {
if(random.nextDouble() < percentage) {
- final List<DistanceResultPair<D>> neighbors = knnQuery.getKNNForDBID(id, k);
- final int last = Math.min(k - 1, neighbors.size() - 1);
- knnDistances.add(neighbors.get(last).getDistance());
+ final KNNResult<D> neighbors = knnQuery.getKNNForDBID(id, k);
+ knnDistances.add(neighbors.getKNNDistance());
}
}
Collections.sort(knnDistances, Collections.reverseOrder());
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/KNNJoin.java b/src/de/lmu/ifi/dbs/elki/algorithm/KNNJoin.java
index 6dac350d..3cbfe143 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -37,20 +37,24 @@ 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.DBIDs;
-import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
+import de.lmu.ifi.dbs.elki.database.query.DoubleDistanceResultPair;
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.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.index.tree.LeafEntry;
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.SpatialNode;
+import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialPointLeafEntry;
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.KNNHeap;
import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.KNNList;
import de.lmu.ifi.dbs.elki.utilities.documentation.Description;
@@ -66,7 +70,13 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
* This algorithm only supports spatial databases based on a spatial index
* structure.
*
+ * Since this method compares the MBR of every single leaf with every other
+ * leaf, it is essentially quadratic in the number of leaves, which may not be
+ * appropriate for large trees.
+ *
* @author Elke Achtert
+ * @author Erich Schubert
+ *
* @param <V> the type of FeatureVector handled by this Algorithm
* @param <D> the type of Distance used by this Algorithm
* @param <N> the type of node used in the spatial index structure
@@ -110,7 +120,7 @@ public class KNNJoin<V extends NumberVector<V, ?>, D extends Distance<D>, N exte
* {@link SpatialPrimitiveDistanceFunction}.
*/
@SuppressWarnings("unchecked")
- public DataStore<KNNList<D>> run(Database database, Relation<V> relation) throws IllegalStateException {
+ public WritableDataStore<KNNList<D>> run(Database database, Relation<V> relation) throws IllegalStateException {
if(!(getDistanceFunction() instanceof SpatialPrimitiveDistanceFunction)) {
throw new IllegalStateException("Distance Function must be an instance of " + SpatialPrimitiveDistanceFunction.class.getName());
}
@@ -121,117 +131,222 @@ public class KNNJoin<V extends NumberVector<V, ?>, D extends Distance<D>, N exte
// FIXME: Ensure were looking at the right relation!
SpatialIndexTree<N, E> index = indexes.iterator().next();
SpatialPrimitiveDistanceFunction<V, D> distFunction = (SpatialPrimitiveDistanceFunction<V, D>) getDistanceFunction();
- DistanceQuery<V, D> distq = database.getDistanceQuery(relation, distFunction);
-
DBIDs ids = relation.getDBIDs();
- WritableDataStore<KNNHeap<D>> knnHeaps = DataStoreUtil.makeStorage(ids, DataStoreFactory.HINT_TEMP | DataStoreFactory.HINT_HOT, KNNHeap.class);
+ // Optimize for double?
+ final boolean doubleOptimize = (getDistanceFunction() instanceof SpatialPrimitiveDoubleDistanceFunction);
- try {
- // data pages of s
- List<E> ps_candidates = index.getLeaves();
- FiniteProgress progress = logger.isVerbose() ? new FiniteProgress(this.getClass().getName(), relation.size(), logger) : null;
- IndefiniteProgress pageprog = logger.isVerbose() ? new IndefiniteProgress("Number of processed data pages", logger) : null;
- if(logger.isDebugging()) {
- logger.debugFine("# ps = " + ps_candidates.size());
- }
- // data pages of r
- List<E> pr_candidates = new ArrayList<E>(ps_candidates);
- if(logger.isDebugging()) {
- logger.debugFine("# pr = " + pr_candidates.size());
- }
- int processed = 0;
- int processedPages = 0;
- boolean up = true;
- for(E pr_entry : pr_candidates) {
- N pr = index.getNode(pr_entry);
- D pr_knn_distance = distq.infiniteDistance();
- if(logger.isDebugging()) {
- logger.debugFine(" ------ PR = " + pr);
- }
- // create for each data object a knn list
- for(int j = 0; j < pr.getNumEntries(); j++) {
- knnHeaps.put(((LeafEntry) pr.getEntry(j)).getDBID(), new KNNHeap<D>(k, distq.infiniteDistance()));
- }
+ // data pages
+ List<E> ps_candidates = new ArrayList<E>(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);
- if(up) {
- for(E ps_entry : ps_candidates) {
- D distance = distFunction.minDist(pr_entry, ps_entry);
+ // Initialize with the page self-pairing
+ for(int i = 0; i < ps_candidates.size(); i++) {
+ E pr_entry = ps_candidates.get(i);
+ N pr = index.getNode(pr_entry);
+ heaps.add(initHeaps(distFunction, doubleOptimize, pr));
+ }
- if(distance.compareTo(pr_knn_distance) <= 0) {
- N ps = index.getNode(ps_entry);
- pr_knn_distance = processDataPages(distq, pr, ps, knnHeaps, pr_knn_distance);
- }
- }
- up = false;
+ // Build priority queue
+ final int sqsize = ps_candidates.size() * (ps_candidates.size() - 1) / 2;
+ if(logger.isDebuggingFine()) {
+ logger.debugFine("Number of leaves: " + ps_candidates.size() + " so " + sqsize + " MBR computations.");
+ }
+ FiniteProgress mprogress = logger.isVerbose() ? new FiniteProgress("Comparing leaf MBRs", sqsize, logger) : null;
+ for(int i = 0; i < ps_candidates.size(); i++) {
+ E pr_entry = ps_candidates.get(i);
+ List<KNNHeap<D>> pr_heaps = heaps.get(i);
+ D pr_knn_distance = computeStopDistance(pr_heaps);
+
+ for(int j = i + 1; j < ps_candidates.size(); j++) {
+ E ps_entry = ps_candidates.get(j);
+ List<KNNHeap<D>> ps_heaps = heaps.get(j);
+ D ps_knn_distance = computeStopDistance(ps_heaps);
+ D minDist = distFunction.minDist(pr_entry, ps_entry);
+ // Resolve immediately:
+ if(minDist.isNullDistance()) {
+ N pr = index.getNode(ps_candidates.get(i));
+ N ps = index.getNode(ps_candidates.get(j));
+ processDataPagesOptimize(distFunction, doubleOptimize, pr_heaps, ps_heaps, pr, ps);
+ }
+ else if(minDist.compareTo(pr_knn_distance) <= 0 || minDist.compareTo(ps_knn_distance) <= 0) {
+ pq.add(new Task(minDist, i, j));
}
+ if(mprogress != null) {
+ mprogress.incrementProcessed(logger);
+ }
+ }
+ }
+ if(mprogress != null) {
+ mprogress.ensureCompleted(logger);
+ }
+ // Process the queue
+ FiniteProgress qprogress = logger.isVerbose() ? new FiniteProgress("Processing queue", pq.size(), logger) : null;
+ IndefiniteProgress fprogress = logger.isVerbose() ? new IndefiniteProgress("Full comparisons", logger) : null;
+ while(!pq.isEmpty()) {
+ Task task = pq.poll();
+ List<KNNHeap<D>> pr_heaps = heaps.get(task.i);
+ List<KNNHeap<D>> ps_heaps = heaps.get(task.j);
+ D pr_knn_distance = computeStopDistance(pr_heaps);
+ D ps_knn_distance = computeStopDistance(ps_heaps);
+ boolean dor = task.mindist.compareTo(pr_knn_distance) <= 0;
+ boolean dos = task.mindist.compareTo(ps_knn_distance) <= 0;
+ if(dor || dos) {
+ N pr = index.getNode(ps_candidates.get(task.i));
+ N ps = index.getNode(ps_candidates.get(task.j));
+ if(dor && dos) {
+ processDataPagesOptimize(distFunction, doubleOptimize, pr_heaps, ps_heaps, pr, ps);
+ }
else {
- for(int s = ps_candidates.size() - 1; s >= 0; s--) {
- E ps_entry = ps_candidates.get(s);
- D distance = distFunction.minDist(pr_entry, ps_entry);
-
- if(distance.compareTo(pr_knn_distance) <= 0) {
- N ps = index.getNode(ps_entry);
- pr_knn_distance = processDataPages(distq, pr, ps, knnHeaps, pr_knn_distance);
- }
+ if(dor) {
+ processDataPagesOptimize(distFunction, doubleOptimize, pr_heaps, null, pr, ps);
+ }
+ else /* dos */{
+ processDataPagesOptimize(distFunction, doubleOptimize, ps_heaps, null, ps, pr);
}
- up = true;
}
+ if(fprogress != null) {
+ fprogress.incrementProcessed(logger);
+ }
+ }
+ if(qprogress != null) {
+ qprogress.incrementProcessed(logger);
+ }
+ }
+ if(qprogress != null) {
+ qprogress.ensureCompleted(logger);
+ }
+ if(fprogress != null) {
+ fprogress.setCompleted(logger);
+ }
- processed += pr.getNumEntries();
+ 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;
+ FiniteProgress pageprog = logger.isVerbose() ? new FiniteProgress("Number of processed data pages", ps_candidates.size(), logger) : null;
+ // int processed = 0;
+ for(int i = 0; i < ps_candidates.size(); i++) {
+ N pr = index.getNode(ps_candidates.get(i));
+ List<KNNHeap<D>> pr_heaps = heaps.get(i);
- if(progress != null && pageprog != null) {
- progress.setProcessed(processed, logger);
- pageprog.setProcessed(processedPages++, logger);
- }
+ // Finalize lists
+ for(int j = 0; j < pr.getNumEntries(); j++) {
+ knnLists.put(((LeafEntry) pr.getEntry(j)).getDBID(), pr_heaps.get(j).toKNNList());
}
+ // Forget heaps and pq
+ heaps.set(i, null);
+ // processed += pr.getNumEntries();
+
+ // if(progress != null) {
+ // progress.setProcessed(processed, logger);
+ // }
if(pageprog != null) {
- pageprog.setCompleted(logger);
- }
- WritableDataStore<KNNList<D>> knnLists = DataStoreUtil.makeStorage(ids, DataStoreFactory.HINT_STATIC, KNNList.class);
- for(DBID id : ids) {
- knnLists.put(id, knnHeaps.get(id).toKNNList());
+ pageprog.incrementProcessed(logger);
}
- return knnLists;
}
+ // if(progress != null) {
+ // progress.ensureCompleted(logger);
+ // }
+ if(pageprog != null) {
+ pageprog.ensureCompleted(logger);
+ }
+ return knnLists;
+ }
- catch(Exception e) {
- throw new IllegalStateException(e);
+ private List<KNNHeap<D>> initHeaps(SpatialPrimitiveDistanceFunction<V, D> distFunction, final boolean doubleOptimize, N pr) {
+ List<KNNHeap<D>> pr_heaps;
+ // Create for each data object a knn heap
+ pr_heaps = new ArrayList<KNNHeap<D>>(pr.getNumEntries());
+ for(int j = 0; j < pr.getNumEntries(); j++) {
+ pr_heaps.add(new KNNHeap<D>(k, distFunction.getDistanceFactory().infiniteDistance()));
}
+ // Self-join first, as this is expected to improve most and cannot be
+ // pruned.
+ processDataPagesOptimize(distFunction, doubleOptimize, pr_heaps, null, pr, pr);
+ return pr_heaps;
}
/**
* Processes the two data pages pr and ps and determines the k-nearest
* neighbors of pr in ps.
*
- * @param distQ the distance to use
+ * @param distFunction the distance to use
+ * @param doubleOptimize Flag whether to optimize for doubles.
* @param pr the first data page
* @param ps the second data page
- * @param knnLists the knn lists for each data object
- * @param pr_knn_distance the current knn distance of data page pr
- * @return the k-nearest neighbor distance of pr in ps
+ * @param pr_heaps the knn lists for each data object in pr
+ * @param ps_heaps the knn lists for each data object in ps (if ps != pr)
*/
- private D processDataPages(DistanceQuery<V, D> distQ, N pr, N ps, WritableDataStore<KNNHeap<D>> knnLists, D pr_knn_distance) {
- // TODO: optimize for double?
- boolean infinite = pr_knn_distance.isInfiniteDistance();
- for(int i = 0; i < pr.getNumEntries(); i++) {
- DBID r_id = ((LeafEntry) pr.getEntry(i)).getDBID();
- KNNHeap<D> knnList = knnLists.get(r_id);
-
+ private void processDataPagesOptimize(SpatialPrimitiveDistanceFunction<V, D> distFunction, final boolean doubleOptimize, List<KNNHeap<D>> pr_heaps, List<KNNHeap<D>> ps_heaps, N pr, N ps) {
+ if(doubleOptimize) {
+ List<?> khp = (List<?>) pr_heaps;
+ List<?> khs = (List<?>) ps_heaps;
+ processDataPagesDouble((SpatialPrimitiveDoubleDistanceFunction<? super V>) distFunction, pr, ps, (List<KNNHeap<DoubleDistance>>) khp, (List<KNNHeap<DoubleDistance>>) khs);
+ }
+ else {
for(int j = 0; j < ps.getNumEntries(); j++) {
- DBID s_id = ((LeafEntry) ps.getEntry(j)).getDBID();
-
- D distance = distQ.distance(r_id, s_id);
- if(knnList.add(distance, s_id)) {
- // set kNN distance of r
- if(infinite) {
- pr_knn_distance = knnList.getMaximumDistance();
+ final SpatialPointLeafEntry s_e = (SpatialPointLeafEntry) ps.getEntry(j);
+ DBID s_id = s_e.getDBID();
+ for(int i = 0; i < pr.getNumEntries(); i++) {
+ final SpatialPointLeafEntry r_e = (SpatialPointLeafEntry) pr.getEntry(i);
+ D distance = distFunction.minDist(s_e, r_e);
+ pr_heaps.get(i).add(distance, s_id);
+ if(pr != ps && ps_heaps != null) {
+ ps_heaps.get(j).add(distance, r_e.getDBID());
}
- pr_knn_distance = DistanceUtil.max(knnList.getMaximumDistance(), pr_knn_distance);
}
}
}
+ }
+
+ /**
+ * Processes the two data pages pr and ps and determines the k-nearest
+ * neighbors of pr in ps.
+ *
+ * @param df the distance function to use
+ * @param pr the first data page
+ * @param ps the second data page
+ * @param pr_heaps the knn lists for each data object
+ * @param ps_heaps the knn lists for each data object in ps
+ */
+ private void processDataPagesDouble(SpatialPrimitiveDoubleDistanceFunction<? super V> df, N pr, N ps, List<KNNHeap<DoubleDistance>> pr_heaps, List<KNNHeap<DoubleDistance>> ps_heaps) {
+ // Compare pairwise
+ for(int j = 0; j < ps.getNumEntries(); j++) {
+ final SpatialPointLeafEntry s_e = (SpatialPointLeafEntry) ps.getEntry(j);
+ DBID s_id = s_e.getDBID();
+ for(int i = 0; i < pr.getNumEntries(); i++) {
+ final SpatialPointLeafEntry r_e = (SpatialPointLeafEntry) pr.getEntry(i);
+ double distance = df.doubleMinDist(s_e, r_e);
+ pr_heaps.get(i).add(new DoubleDistanceResultPair(distance, s_id));
+ if(pr != ps && ps_heaps != null) {
+ ps_heaps.get(j).add(new DoubleDistanceResultPair(distance, r_e.getDBID()));
+ }
+ }
+ }
+ }
+
+ /**
+ * Compute the maximum stop distance
+ *
+ * @param heaps
+ * @return the k-nearest neighbor distance of pr in ps
+ */
+ private D computeStopDistance(List<KNNHeap<D>> heaps) {
+ // Update pruning distance
+ D pr_knn_distance = null;
+ for(KNNHeap<D> knnList : heaps) {
+ // set kNN distance of r
+ if(pr_knn_distance == null) {
+ pr_knn_distance = knnList.getKNNDistance();
+ }
+ else {
+ pr_knn_distance = DistanceUtil.max(knnList.getKNNDistance(), pr_knn_distance);
+ }
+ }
return pr_knn_distance;
}
@@ -246,6 +361,40 @@ public class KNNJoin<V extends NumberVector<V, ?>, D extends Distance<D>, N exte
}
/**
+ * Task in the processing queue
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ private class Task implements Comparable<Task> {
+ final D mindist;
+
+ final int i;
+
+ final int j;
+
+ /**
+ * Constructor.
+ *
+ * @param mindist
+ * @param i
+ * @param j
+ */
+ public Task(D mindist, int i, int j) {
+ super();
+ this.mindist = mindist;
+ this.i = i;
+ this.j = j;
+ }
+
+ @Override
+ public int compareTo(Task o) {
+ return mindist.compareTo(o.mindist);
+ }
+ }
+
+ /**
* Parameterization class.
*
* @author Erich Schubert
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/MaterializeDistances.java b/src/de/lmu/ifi/dbs/elki/algorithm/MaterializeDistances.java
index 345fda1a..89d2d3e0 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) 2011
+ Copyright (C) 2012
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/NullAlgorithm.java b/src/de/lmu/ifi/dbs/elki/algorithm/NullAlgorithm.java
index 6c13e68e..a879c6b2 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) 2011
+ Copyright (C) 2012
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 5712d814..ea441655 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) 2011
+ Copyright (C) 2012
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/AbstractProjectedDBSCAN.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/AbstractProjectedDBSCAN.java
index 95d88b93..108ba0ed 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -340,9 +340,9 @@ public abstract class AbstractProjectedDBSCAN<R extends Clustering<Model>, V ext
}
}
- if(processedIDs.size() == distFunc.getRelation().size() && noise.size() == 0) {
+ /* if(processedIDs.size() == relation.size() && noise.size() == 0) {
break;
- }
+ } */
}
if(currentCluster.size() >= minpts) {
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 e28dbff3..5ec59777 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) 2011
+ Copyright (C) 2012
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/DBSCAN.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/DBSCAN.java
index 2576c5f6..b59af555 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -33,7 +33,6 @@ import de.lmu.ifi.dbs.elki.data.model.ClusterModel;
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.QueryUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
@@ -132,7 +131,7 @@ public class DBSCAN<O, D extends Distance<D>> extends AbstractDistanceBasedAlgor
/**
* Performs the DBSCAN algorithm on the given database.
*/
- public Clustering<Model> run(Database database, Relation<O> relation) {
+ public Clustering<Model> run(Relation<O> relation) {
RangeQuery<O, D> rangeQuery = QueryUtil.getRangeQuery(relation, getDistanceFunction());
final int size = relation.size();
@@ -142,9 +141,9 @@ public class DBSCAN<O, D extends Distance<D>> extends AbstractDistanceBasedAlgor
noise = DBIDUtil.newHashSet();
processedIDs = DBIDUtil.newHashSet(size);
if(size >= minpts) {
- for(DBID id : rangeQuery.getRelation().iterDBIDs()) {
+ for(DBID id : relation.iterDBIDs()) {
if(!processedIDs.contains(id)) {
- expandCluster(database, rangeQuery, id, objprog, clusprog);
+ expandCluster(relation, rangeQuery, id, objprog, clusprog);
}
if(objprog != null && clusprog != null) {
objprog.setProcessed(processedIDs.size(), logger);
@@ -156,7 +155,7 @@ public class DBSCAN<O, D extends Distance<D>> extends AbstractDistanceBasedAlgor
}
}
else {
- for(DBID id : rangeQuery.getRelation().iterDBIDs()) {
+ for(DBID id : relation.iterDBIDs()) {
noise.add(id);
if(objprog != null && clusprog != null) {
objprog.setProcessed(noise.size(), logger);
@@ -189,12 +188,12 @@ public class DBSCAN<O, D extends Distance<D>> extends AbstractDistanceBasedAlgor
* <p/>
* Border-Objects become members of the first possible cluster.
*
- * @param database the database on which the algorithm is run
+ * @param relation Database relation to run on
* @param rangeQuery Range query to use
* @param startObjectID potential seed of a new potential cluster
* @param objprog the progress object for logging the current status
*/
- protected void expandCluster(Database database, RangeQuery<O, D> rangeQuery, DBID startObjectID, FiniteProgress objprog, IndefiniteProgress clusprog) {
+ protected void expandCluster(Relation<O> relation, RangeQuery<O, D> rangeQuery, DBID startObjectID, FiniteProgress objprog, IndefiniteProgress clusprog) {
List<DistanceResultPair<D>> seeds = rangeQuery.getRangeForDBID(startObjectID, epsilon);
// startObject is no core-object
@@ -245,7 +244,7 @@ public class DBSCAN<O, D extends Distance<D>> extends AbstractDistanceBasedAlgor
}
}
- if(processedIDs.size() == rangeQuery.getRelation().size() && noise.size() == 0) {
+ if(processedIDs.size() == relation.size() && noise.size() == 0) {
break;
}
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 ca401ddc..f1e6c945 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) 2011
+ Copyright (C) 2012
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/EM.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/EM.java
index c1285659..a70a3f6f 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,9 +25,10 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering;
import java.util.ArrayList;
import java.util.List;
-import java.util.Random;
import de.lmu.ifi.dbs.elki.algorithm.AbstractAlgorithm;
+import de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMeansInitialization;
+import de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.RandomlyGeneratedInitialMeans;
import de.lmu.ifi.dbs.elki.data.Cluster;
import de.lmu.ifi.dbs.elki.data.Clustering;
import de.lmu.ifi.dbs.elki.data.NumberVector;
@@ -42,6 +43,7 @@ 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.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.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;
@@ -58,8 +60,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterEqualCons
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.LongParameter;
-import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
/**
* Provides the EM algorithm (clustering by expectation maximization).
@@ -113,6 +114,11 @@ public class EM<V extends NumberVector<V, ?>> extends AbstractAlgorithm<Clusteri
*/
public static final OptionID DELTA_ID = OptionID.getOrCreateOptionID("em.delta", "The termination criterion for maximization of E(M): " + "E(M) - E(M') < em.delta");
+ /**
+ * Parameter to specify the initialization method
+ */
+ public static final OptionID INIT_ID = OptionID.getOrCreateOptionID("kmeans.initialization", "Method to choose the initial means.");
+
private static final double MIN_LOGLIKELIHOOD = -100000;
/**
@@ -121,32 +127,27 @@ public class EM<V extends NumberVector<V, ?>> extends AbstractAlgorithm<Clusteri
private double delta;
/**
- * Parameter to specify the random generator seed.
+ * Store the individual probabilities, for use by EMOutlierDetection etc.
*/
- public static final OptionID SEED_ID = OptionID.getOrCreateOptionID("em.seed", "The random number generator seed.");
+ private WritableDataStore<double[]> probClusterIGivenX;
/**
- * Holds the value of {@link #SEED_ID}.
+ * Class to choose the initial means
*/
- private Long seed;
-
- /**
- * Store the individual probabilities, for use by EMOutlierDetection etc.
- */
- private WritableDataStore<double[]> probClusterIGivenX;
+ private KMeansInitialization<V> initializer;
/**
* Constructor.
*
* @param k k parameter
* @param delta delta parameter
- * @param seed Seed parameter
+ * @param initializer Class to choose the initial means
*/
- public EM(int k, double delta, Long seed) {
+ public EM(int k, double delta, KMeansInitialization<V> initializer) {
super();
this.k = k;
this.delta = delta;
- this.seed = seed;
+ this.initializer = initializer;
}
/**
@@ -169,14 +170,14 @@ public class EM<V extends NumberVector<V, ?>> extends AbstractAlgorithm<Clusteri
if(logger.isVerbose()) {
logger.verbose("initializing " + k + " models");
}
- List<V> means = initialMeans(relation);
+ List<Vector> means = initializer.chooseInitialMeans(relation, k, EuclideanDistanceFunction.STATIC);
List<Matrix> covarianceMatrices = new ArrayList<Matrix>(k);
List<Double> normDistrFactor = new ArrayList<Double>(k);
List<Matrix> invCovMatr = new ArrayList<Matrix>(k);
List<Double> clusterWeights = new ArrayList<Double>(k);
probClusterIGivenX = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_SORTED, double[].class);
- int dimensionality = means.get(0).getDimensionality();
+ final int dimensionality = means.get(0).getDimensionality();
for(int i = 0; i < k; i++) {
Matrix m = Matrix.identity(dimensionality, dimensionality);
covarianceMatrices.add(m);
@@ -211,12 +212,12 @@ public class EM<V extends NumberVector<V, ?>> extends AbstractAlgorithm<Clusteri
em = emNew;
// recompute models
- List<V> meanSums = new ArrayList<V>(k);
+ List<Vector> meanSums = new ArrayList<Vector>(k);
double[] sumOfClusterProbabilities = new double[k];
for(int i = 0; i < k; i++) {
clusterWeights.set(i, 0.0);
- meanSums.add(means.get(i).nullVector());
+ meanSums.add(new Vector(dimensionality));
covarianceMatrices.set(i, Matrix.zeroMatrix(dimensionality));
}
@@ -226,24 +227,23 @@ public class EM<V extends NumberVector<V, ?>> extends AbstractAlgorithm<Clusteri
for(int i = 0; i < k; i++) {
sumOfClusterProbabilities[i] += clusterProbabilities[i];
- V summand = relation.get(id).multiplicate(clusterProbabilities[i]);
- V currentMeanSum = meanSums.get(i).plus(summand);
- meanSums.set(i, currentMeanSum);
+ Vector summand = relation.get(id).getColumnVector().timesEquals(clusterProbabilities[i]);
+ meanSums.get(i).plusEquals(summand);
}
}
final int n = relation.size();
for(int i = 0; i < k; i++) {
clusterWeights.set(i, sumOfClusterProbabilities[i] / n);
- V newMean = meanSums.get(i).multiplicate(1 / sumOfClusterProbabilities[i]);
+ Vector newMean = meanSums.get(i).timesEquals(1 / sumOfClusterProbabilities[i]);
means.set(i, newMean);
}
// covariance matrices
for(DBID id : relation.iterDBIDs()) {
double[] clusterProbabilities = probClusterIGivenX.get(id);
- V instance = relation.get(id);
+ Vector instance = relation.get(id).getColumnVector();
for(int i = 0; i < k; i++) {
- V difference = instance.minus(means.get(i));
- covarianceMatrices.get(i).plusEquals(difference.getColumnVector().times(difference.getRowVector()).times(clusterProbabilities[i]));
+ Vector difference = instance.minus(means.get(i));
+ covarianceMatrices.get(i).plusEquals(difference.timesTranspose(difference).timesEquals(clusterProbabilities[i]));
}
}
for(int i = 0; i < k; i++) {
@@ -281,13 +281,14 @@ public class EM<V extends NumberVector<V, ?>> extends AbstractAlgorithm<Clusteri
}
hardClusters.get(maxIndex).add(id);
}
+ final V factory = DatabaseUtil.assumeVectorField(relation).getFactory();
Clustering<EMModel<V>> result = new Clustering<EMModel<V>>("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>(means.get(i), covarianceMatrices.get(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);
}
return result;
@@ -308,24 +309,20 @@ public class EM<V extends NumberVector<V, ?>> extends AbstractAlgorithm<Clusteri
* @param clusterWeights the weights of the current clusters
* @return the expectation value of the current mixture of distributions
*/
- protected double assignProbabilitiesToInstances(Relation<V> database, List<Double> normDistrFactor, List<V> means, List<Matrix> invCovMatr, List<Double> clusterWeights, WritableDataStore<double[]> probClusterIGivenX) {
+ protected double assignProbabilitiesToInstances(Relation<V> database, List<Double> normDistrFactor, List<Vector> means, List<Matrix> invCovMatr, List<Double> clusterWeights, WritableDataStore<double[]> probClusterIGivenX) {
double emSum = 0.0;
for(DBID id : database.iterDBIDs()) {
- V x = database.get(id);
+ Vector x = database.get(id).getColumnVector();
List<Double> probabilities = new ArrayList<Double>(k);
for(int i = 0; i < k; i++) {
- V difference = x.minus(means.get(i));
- Matrix differenceRow = difference.getRowVector();
- Vector differenceCol = difference.getColumnVector();
- Matrix rowTimesCov = differenceRow.times(invCovMatr.get(i));
- Vector rowTimesCovTimesCol = rowTimesCov.times(differenceCol);
- double power = rowTimesCovTimesCol.get(0, 0) / 2.0;
+ Vector difference = x.minus(means.get(i));
+ double rowTimesCovTimesCol = difference.transposeTimesTimes(invCovMatr.get(i), difference);
+ double power = rowTimesCovTimesCol / 2.0;
double prob = normDistrFactor.get(i) * Math.exp(-power);
if(logger.isDebuggingFinest()) {
- logger.debugFinest(" difference vector= ( " + difference.toString() + " )\n" + " differenceRow:\n" + FormatUtil.format(differenceRow, " ") + "\n" + " differenceCol:\n" + FormatUtil.format(differenceCol, " ") + "\n" + " rowTimesCov:\n" + FormatUtil.format(rowTimesCov, " ") + "\n" + " rowTimesCovTimesCol:\n" + FormatUtil.format(rowTimesCovTimesCol, " ") + "\n" + " power= " + power + "\n" + " prob=" + prob + "\n" + " inv cov matrix: \n" + FormatUtil.format(invCovMatr.get(i), " "));
+ logger.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), " "));
}
-
probabilities.add(prob);
}
double priorProbability = 0.0;
@@ -356,48 +353,6 @@ public class EM<V extends NumberVector<V, ?>> extends AbstractAlgorithm<Clusteri
}
/**
- * Creates {@link #k k} random points distributed uniformly within the
- * attribute ranges of the given database.
- *
- * @param relation the database must contain enough points in order to
- * ascertain the range of attribute values. Less than two points would
- * make no sense. The content of the database is not touched otherwise.
- * @return a list of {@link #k k} random points distributed uniformly within
- * the attribute ranges of the given database
- */
- protected List<V> initialMeans(Relation<V> relation) {
- final Random random;
- if(this.seed != null) {
- random = new Random(this.seed);
- }
- else {
- random = new Random();
- }
- if(relation.size() > 0) {
- final int dim = DatabaseUtil.dimensionality(relation);
- Pair<V, V> minmax = DatabaseUtil.computeMinMax(relation);
- List<V> means = new ArrayList<V>(k);
- if(logger.isVerbose()) {
- logger.verbose("initializing random vectors");
- }
- for(int i = 0; i < k; i++) {
- double[] r = MathUtil.randomDoubleArray(dim, random);
- // Rescale
- for (int d = 0; d < dim; d++) {
- r[d] = minmax.first.doubleValue(d + 1) + (minmax.second.doubleValue(d + 1) - minmax.first.doubleValue(d + 1)) * r[d];
- }
- // Instantiate
- V randomVector = minmax.first.newInstance(r);
- means.add(randomVector);
- }
- return means;
- }
- else {
- return new ArrayList<V>(0);
- }
- }
-
- /**
* Get the probabilities for a given point.
*
* @param index Point ID
@@ -429,7 +384,7 @@ public class EM<V extends NumberVector<V, ?>> extends AbstractAlgorithm<Clusteri
protected double delta;
- protected Long seed;
+ protected KMeansInitialization<V> initializer;
@Override
protected void makeOptions(Parameterization config) {
@@ -439,20 +394,20 @@ public class EM<V extends NumberVector<V, ?>> extends AbstractAlgorithm<Clusteri
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);
+ }
+
DoubleParameter deltaP = new DoubleParameter(DELTA_ID, new GreaterEqualConstraint(0.0), 0.0);
if(config.grab(deltaP)) {
delta = deltaP.getValue();
}
-
- LongParameter seedP = new LongParameter(SEED_ID, true);
- if(config.grab(seedP)) {
- seed = seedP.getValue();
- }
}
@Override
protected EM<V> makeInstance() {
- return new EM<V>(k, delta, seed);
+ return new EM<V>(k, delta, initializer);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/KMeans.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/KMeans.java
deleted file mode 100644
index 38ea89c2..00000000
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/KMeans.java
+++ /dev/null
@@ -1,307 +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) 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 java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Random;
-
-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;
-import de.lmu.ifi.dbs.elki.data.model.MeanModel;
-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.ArrayModifiableDBIDs;
-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.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.distancevalue.Distance;
-import de.lmu.ifi.dbs.elki.logging.Logging;
-import de.lmu.ifi.dbs.elki.math.MathUtil;
-import de.lmu.ifi.dbs.elki.utilities.DatabaseUtil;
-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.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.LongParameter;
-import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
-
-/**
- * Provides the k-means algorithm.
- * <p>
- * Reference: J. MacQueen: Some Methods for Classification and Analysis of
- * Multivariate Observations. <br>
- * In 5th Berkeley Symp. Math. Statist. Prob., Vol. 1, 1967, pp 281-297.
- * </p>
- *
- * @author Arthur Zimek
- *
- * @apiviz.has MeanModel
- *
- * @param <D> a type of {@link Distance} as returned by the used distance
- * function
- * @param <V> a type of {@link NumberVector} as a suitable datatype for this
- * algorithm
- */
-@Title("K-Means")
-@Description("Finds a partitioning into k clusters.")
-@Reference(authors = "J. MacQueen", title = "Some Methods for Classification and Analysis of Multivariate Observations", booktitle = "5th Berkeley Symp. Math. Statist. Prob., Vol. 1, 1967, pp 281-297", url = "http://projecteuclid.org/euclid.bsmsp/1200512992")
-public class KMeans<V extends NumberVector<V, ?>, D extends Distance<D>> extends AbstractPrimitiveDistanceBasedAlgorithm<V, D, Clustering<MeanModel<V>>> implements ClusteringAlgorithm<Clustering<MeanModel<V>>> {
- /**
- * The logger for this class.
- */
- private static final Logging logger = Logging.getLogger(KMeans.class);
-
- /**
- * Parameter to specify the number of clusters to find, must be an integer
- * greater than 0.
- */
- public static final OptionID K_ID = OptionID.getOrCreateOptionID("kmeans.k", "The number of clusters to find.");
-
- /**
- * Parameter to specify the number of clusters to find, must be an integer
- * greater or equal to 0, where 0 means no limit.
- */
- public static final OptionID MAXITER_ID = OptionID.getOrCreateOptionID("kmeans.maxiter", "The maximum number of iterations to do. 0 means no limit.");
-
- /**
- * Parameter to specify the random generator seed.
- */
- public static final OptionID SEED_ID = OptionID.getOrCreateOptionID("kmeans.seed", "The random number generator seed.");
-
- /**
- * Holds the value of {@link #K_ID}.
- */
- private int k;
-
- /**
- * Holds the value of {@link #MAXITER_ID}.
- */
- private int maxiter;
-
- /**
- * Holds the value of {@link #SEED_ID}.
- */
- private Long seed;
-
- /**
- * Constructor.
- *
- * @param distanceFunction distance function
- * @param k k parameter
- * @param maxiter Maxiter parameter
- * @param seed Random generator seed
- */
- public KMeans(PrimitiveDistanceFunction<? super V, D> distanceFunction, int k, int maxiter, Long seed) {
- super(distanceFunction);
- this.k = k;
- this.maxiter = maxiter;
- this.seed = seed;
- }
-
- /**
- * Run k-means
- *
- * @param database Database
- * @param relation relation to use
- * @return result
- * @throws IllegalStateException
- */
- public Clustering<MeanModel<V>> run(Database database, Relation<V> relation) throws IllegalStateException {
- final Random random = (this.seed != null) ? new Random(this.seed) : new Random();
- if(relation.size() > 0) {
- final int dim = DatabaseUtil.dimensionality(relation);
- Pair<V, V> minmax = DatabaseUtil.computeMinMax(relation);
- List<V> means = new ArrayList<V>(k);
- List<V> oldMeans;
- if(logger.isVerbose()) {
- logger.verbose("initializing random vectors");
- }
- for(int i = 0; i < k; i++) {
- double[] r = MathUtil.randomDoubleArray(dim, random);
- // Rescale
- for (int d = 0; d < dim; d++) {
- r[d] = minmax.first.doubleValue(d + 1) + (minmax.second.doubleValue(d + 1) - minmax.first.doubleValue(d + 1)) * r[d];
- }
- // Instantiate
- V randomVector = minmax.first.newInstance(r);
- means.add(randomVector);
- }
- List<? extends ModifiableDBIDs> clusters;
- clusters = sort(means, relation);
- boolean changed = true;
- int iteration = 1;
- while(changed) {
- if(logger.isVerbose()) {
- logger.verbose("iteration " + iteration);
- }
- oldMeans = new ArrayList<V>(means);
- means = means(clusters, means, relation);
- clusters = sort(means, relation);
- changed = !means.equals(oldMeans);
- iteration++;
-
- if(maxiter > 0 && iteration > maxiter) {
- break;
- }
- }
- Clustering<MeanModel<V>> result = new Clustering<MeanModel<V>>("k-Means Clustering", "kmeans-clustering");
- for(int i = 0; i < clusters.size(); i++) {
- DBIDs ids = clusters.get(i);
- MeanModel<V> model = new MeanModel<V>(means.get(i));
- result.addCluster(new Cluster<MeanModel<V>>(ids, model));
- }
- return result;
- }
- else {
- return new Clustering<MeanModel<V>>("k-Means Clustering", "kmeans-clustering");
- }
- }
-
- /**
- * Returns the mean vectors of the given clusters in the given database.
- *
- * @param clusters the clusters to compute the means
- * @param means the recent means
- * @param database the database containing the vectors
- * @return the mean vectors of the given clusters in the given database
- */
- protected List<V> means(List<? extends ModifiableDBIDs> clusters, List<V> means, Relation<V> database) {
- List<V> newMeans = new ArrayList<V>(k);
- for(int i = 0; i < k; i++) {
- ModifiableDBIDs list = clusters.get(i);
- V mean = null;
- for(Iterator<DBID> clusterIter = list.iterator(); clusterIter.hasNext();) {
- if(mean == null) {
- mean = database.get(clusterIter.next());
- }
- else {
- mean = mean.plus(database.get(clusterIter.next()));
- }
- }
- if(list.size() > 0) {
- assert mean != null;
- mean = mean.multiplicate(1.0 / list.size());
- }
- else {
- mean = means.get(i);
- }
- newMeans.add(mean);
- }
- return newMeans;
- }
-
- /**
- * Returns a list of clusters. The k<sup>th</sup> cluster contains the ids of
- * those FeatureVectors, that are nearest to the k<sup>th</sup> mean.
- *
- * @param means a list of k means
- * @param database the database to cluster
- * @return list of k clusters
- */
- protected List<? extends ModifiableDBIDs> sort(List<V> means, Relation<V> database) {
- List<ArrayModifiableDBIDs> clusters = new ArrayList<ArrayModifiableDBIDs>(k);
- for(int i = 0; i < k; i++) {
- clusters.add(DBIDUtil.newArray());
- }
-
- for(DBID id : database.iterDBIDs()) {
- List<D> distances = new ArrayList<D>(k);
- V fv = database.get(id);
- int minIndex = 0;
- for(int d = 0; d < k; d++) {
- distances.add(getDistanceFunction().distance(fv, means.get(d)));
- if(distances.get(d).compareTo(distances.get(minIndex)) < 0) {
- minIndex = d;
- }
- }
- clusters.get(minIndex).add(id);
- }
- for(ArrayModifiableDBIDs cluster : clusters) {
- Collections.sort(cluster);
- }
- return clusters;
- }
-
- @Override
- public TypeInformation[] getInputTypeRestriction() {
- return TypeUtil.array(TypeUtil.NUMBER_VECTOR_FIELD);
- }
-
- @Override
- protected Logging getLogger() {
- return logger;
- }
-
- /**
- * Parameterization class.
- *
- * @author Erich Schubert
- *
- * @apiviz.exclude
- */
- public static class Parameterizer<V extends NumberVector<V, ?>, D extends Distance<D>> extends AbstractPrimitiveDistanceBasedAlgorithm.Parameterizer<V, D> {
- protected int k;
-
- protected int maxiter;
-
- protected Long seed;
-
- @Override
- protected void makeOptions(Parameterization config) {
- super.makeOptions(config);
- IntParameter kP = new IntParameter(K_ID, new GreaterConstraint(0));
- if(config.grab(kP)) {
- k = kP.getValue();
- }
-
- IntParameter maxiterP = new IntParameter(MAXITER_ID, new GreaterEqualConstraint(0), 0);
- if(config.grab(maxiterP)) {
- maxiter = maxiterP.getValue();
- }
-
- LongParameter seedP = new LongParameter(SEED_ID, true);
- if(config.grab(seedP)) {
- seed = seedP.getValue();
- }
- }
-
- @Override
- protected KMeans<V, D> makeInstance() {
- return new KMeans<V, D>(distanceFunction, k, maxiter, seed);
- }
- }
-} \ No newline at end of file
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 24985e24..2244b07b 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) 2011
+ Copyright (C) 2012
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/OPTICSTypeAlgorithm.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/OPTICSTypeAlgorithm.java
index c233963d..d6c5872a 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) 2011
+ Copyright (C) 2012
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 f7bd10c7..41e48b89 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) 2011
+ Copyright (C) 2012
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/SLINK.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/SLINK.java
index e1329888..45b12c43 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/SLINK.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/SLINK.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -133,18 +133,18 @@ public class SLINK<O, D extends Distance<D>> extends AbstractDistanceBasedAlgori
public Result run(Database database, Relation<O> relation) {
DistanceQuery<O, D> distQuery = database.getDistanceQuery(relation, getDistanceFunction());
Class<D> distCls = (Class<D>) getDistanceFunction().getDistanceFactory().getClass();
- WritableRecordStore store = DataStoreUtil.makeRecordStorage(distQuery.getRelation().getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_STATIC, DBID.class, distCls);
+ WritableRecordStore store = DataStoreUtil.makeRecordStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_STATIC, DBID.class, distCls);
pi = store.getStorage(0, DBID.class);
lambda = store.getStorage(1, distCls);
// Temporary storage for m.
- WritableDataStore<D> m = DataStoreUtil.makeStorage(distQuery.getRelation().getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP, distCls);
+ WritableDataStore<D> m = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP, distCls);
- FiniteProgress progress = logger.isVerbose() ? new FiniteProgress("Clustering", distQuery.getRelation().size(), logger) : null;
+ FiniteProgress progress = logger.isVerbose() ? new FiniteProgress("Clustering", relation.size(), logger) : null;
// has to be an array for monotonicity reasons!
- ModifiableDBIDs processedIDs = DBIDUtil.newArray(distQuery.getRelation().size());
+ ModifiableDBIDs processedIDs = DBIDUtil.newArray(relation.size());
// apply the algorithm
- for(DBID id : distQuery.getRelation().iterDBIDs()) {
+ for(DBID id : relation.iterDBIDs()) {
step1(id);
step2(id, processedIDs, distQuery, m);
step3(id, processedIDs, m);
@@ -168,8 +168,8 @@ public class SLINK<O, D extends Distance<D>> extends AbstractDistanceBasedAlgori
BasicResult result = null;
// Build clusters identified by their target object
- int minc = minclusters != null ? minclusters : distQuery.getRelation().size();
- result = extractClusters(distQuery.getRelation().getDBIDs(), pi, lambda, minc);
+ int minc = minclusters != null ? minclusters : relation.size();
+ result = extractClusters(relation.getDBIDs(), pi, lambda, minc);
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));
@@ -288,7 +288,7 @@ public class SLINK<O, D extends Distance<D>> extends AbstractDistanceBasedAlgori
D stopdist = null;
// sort by lambda
ArrayModifiableDBIDs order = DBIDUtil.newArray(ids);
- Collections.sort(order, new CompareByLambda<D>(lambda));
+ order.sort(new CompareByLambda<D>(lambda));
int index = ids.size() - minclusters - 1;
while(index >= 0) {
if(lambda.get(order.get(index)).equals(lambda.get(order.get(index + 1)))) {
@@ -458,7 +458,7 @@ public class SLINK<O, D extends Distance<D>> extends AbstractDistanceBasedAlgori
// extract a hierarchical clustering
ArrayModifiableDBIDs order = DBIDUtil.newArray(ids);
// sort by lambda
- Collections.sort(order, new CompareByLambda<D>(lambda));
+ order.sort(new CompareByLambda<D>(lambda));
D curdist = null;
D stopdist = null;
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 3bde2932..7c3a13c9 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) 2011
+ Copyright (C) 2012
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.algorithm.clustering;
import java.util.ArrayList;
import java.util.Iterator;
-import java.util.LinkedList;
import java.util.List;
import de.lmu.ifi.dbs.elki.algorithm.AbstractAlgorithm;
@@ -36,6 +35,7 @@ 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.ArrayModifiableDBIDs;
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;
@@ -200,8 +200,8 @@ public class SNNClustering<O> extends AbstractAlgorithm<Clustering<Model>> imple
* @return the shared nearest neighbors of the specified query object in the
* given database
*/
- protected List<DBID> findSNNNeighbors(SimilarityQuery<O, IntegerDistance> snnInstance, DBID queryObject) {
- List<DBID> neighbors = new LinkedList<DBID>();
+ protected ArrayModifiableDBIDs findSNNNeighbors(SimilarityQuery<O, IntegerDistance> snnInstance, DBID queryObject) {
+ ArrayModifiableDBIDs neighbors = DBIDUtil.newArray();
for(DBID id : snnInstance.getRelation().iterDBIDs()) {
if(snnInstance.similarity(queryObject, id).compareTo(epsilon) >= 0) {
neighbors.add(id);
@@ -222,7 +222,7 @@ public class SNNClustering<O> extends AbstractAlgorithm<Clustering<Model>> imple
* clustering
*/
protected void expandCluster(SimilarityQuery<O, IntegerDistance> snnInstance, DBID startObjectID, FiniteProgress objprog, IndefiniteProgress clusprog) {
- List<DBID> seeds = findSNNNeighbors(snnInstance, startObjectID);
+ ArrayModifiableDBIDs seeds = findSNNNeighbors(snnInstance, startObjectID);
// startObject is no core-object
if(seeds.size() < minpts) {
@@ -247,11 +247,10 @@ public class SNNClustering<O> extends AbstractAlgorithm<Clustering<Model>> imple
noise.remove(seed);
}
}
- seeds.remove(0);
while(seeds.size() > 0) {
- DBID o = seeds.remove(0);
- List<DBID> neighborhood = findSNNNeighbors(snnInstance, o);
+ DBID o = seeds.remove(seeds.size() - 1);
+ ArrayModifiableDBIDs neighborhood = findSNNNeighbors(snnInstance, o);
if(neighborhood.size() >= minpts) {
for(DBID p : neighborhood) {
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 4a0b391c..b877415e 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -55,7 +55,7 @@ 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.datasource.filter.NonNumericFeaturesException;
+import de.lmu.ifi.dbs.elki.datasource.filter.normalization.NonNumericFeaturesException;
import de.lmu.ifi.dbs.elki.distance.distancefunction.WeightedDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.logging.Logging;
@@ -84,7 +84,12 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
/**
* Provides the CASH algorithm, an subspace clustering algorithm based on the
- * hough transform.
+ * Hough transform.
+ *
+ * <b>Note:</b> CASH requires explicitly setting the input parser other than default to
+ * {@link de.lmu.ifi.dbs.elki.datasource.parser.ParameterizationFunctionLabelParser}:
+ * (in the MiniGui, set option: dbc.parser ParameterizationFunctionLabelParser).
+ *
* <p>
* Reference: E. Achtert, C. Böhm, J. David, P. Kröger, A. Zimek: Robust
* clustering in arbitrarily oriented subspaces. <br>
@@ -99,7 +104,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
*/
// todo elke hierarchy (later)
@Title("CASH: Robust clustering in arbitrarily oriented subspaces")
-@Description("Subspace clustering algorithm based on the hough transform.")
+@Description("Subspace clustering algorithm based on the Hough transform.")
@Reference(authors = "E. Achtert, C. Böhm, J. David, P. Kröger, A. Zimek", title = "Robust clustering in arbitraily oriented subspaces", booktitle = "Proc. 8th SIAM Int. Conf. on Data Mining (SDM'08), Atlanta, GA, 2008", url = "http://www.siam.org/proceedings/datamining/2008/dm08_69_AchtertBoehmDavidKroegerZimek.pdf")
public class CASH extends AbstractAlgorithm<Clustering<Model>> implements ClusteringAlgorithm<Clustering<Model>> {
/**
@@ -349,7 +354,7 @@ public class CASH extends AbstractAlgorithm<Clustering<Model>> implements Cluste
res.addCluster(c);
noiseIDs.removeDBIDs(interval.getIDs());
clusterIDs.addDBIDs(interval.getIDs());
- processedIDs.addAll(interval.getIDs());
+ processedIDs.addDBIDs(interval.getIDs());
}
// Rebuild heap
@@ -372,13 +377,13 @@ public class CASH extends AbstractAlgorithm<Clustering<Model>> implements Cluste
if(dim == noiseDim) {
Cluster<Model> c = new Cluster<Model>(noiseIDs, true, ClusterModel.CLUSTER);
res.addCluster(c);
- processedIDs.addAll(noiseIDs);
+ 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);
- processedIDs.addAll(noiseIDs);
+ processedIDs.addDBIDs(noiseIDs);
}
}
@@ -521,7 +526,7 @@ public class CASH extends AbstractAlgorithm<Clustering<Model>> implements Cluste
private ParameterizationFunction project(Matrix basis, ParameterizationFunction f) {
// Matrix m = new Matrix(new
// double[][]{f.getPointCoordinates()}).times(basis);
- Matrix m = f.getRowVector().times(basis);
+ Matrix m = f.getColumnVector().transposeTimes(basis);
ParameterizationFunction f_t = new ParameterizationFunction(m.getColumnPackedCopy());
return f_t;
}
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 8fc30b3d..575bf117 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) 2011
+ Copyright (C) 2012
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/ERiC.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/ERiC.java
index 75633853..af4f677f 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -244,7 +244,7 @@ public class ERiC<V extends NumberVector<V, ?>> extends AbstractAlgorithm<Cluste
}
else {
ModifiableDBIDs merged = DBIDUtil.newHashSet(noise.getIDs());
- merged.addAll(clus.getIDs().asCollection());
+ merged.addDBIDs(clus.getIDs());
noise.setIDs(merged);
}
}
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 93d0cc99..98761962 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) 2011
+ Copyright (C) 2012
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/HiCO.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/HiCO.java
index 92723428..1065682c 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
@@ -3,7 +3,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) 2011
+Copyright (C) 2012
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/LMCLUS.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/LMCLUS.java
new file mode 100644
index 00000000..41ee1f69
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/LMCLUS.java
@@ -0,0 +1,566 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.Iterator;
+import java.util.List;
+import java.util.Random;
+
+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.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.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.ModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+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.math.MeanVariance;
+import de.lmu.ifi.dbs.elki.math.histograms.FlexiHistogram;
+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.DatabaseUtil;
+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.UnableToComplyException;
+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.pairs.DoubleObjPair;
+
+/**
+ * Linear manifold clustering in high dimensional spaces by stochastic search.
+ *
+ * Reference:
+ * <p>
+ * Robert Haralick, Rave Harpaz<br />
+ * Linear manifold clustering in high dimensional spaces by stochastic search<br/>
+ * In: Pattern Recognition volume 40, Issue 10
+ * </p>
+ *
+ * Implementation note: the LMCLUS algorithm seems to lack good stopping
+ * criterions. We can't entirely reproduce the good results from the original
+ * publication, in particular not on noisy data. But the questionable parts are
+ * as in the original publication, associated thesis and published source code.
+ * The minimum cluster size however can serve as a hidden stopping criterion.
+ *
+ * @author Ernst Waas
+ * @author Erich Schubert
+ */
+@Reference(authors = "Robert Haralick, Rave Harpaz", title = "Linear manifold clustering in high dimensional spaces by stochastic search", booktitle = "Pattern Recognition volume 40, Issue 10", url = "http://dx.doi.org/10.1016/j.patcog.2007.01.020")
+public class LMCLUS extends AbstractAlgorithm<Clustering<Model>> {
+ /**
+ * The logger for this class.
+ */
+ private static final Logging logger = Logging.getLogger(LMCLUS.class);
+
+ /**
+ * Epsilon
+ */
+ private final static double NOT_FROM_ONE_CLUSTER_PROBABILITY = 0.2;
+
+ /**
+ * Histogram resolution
+ */
+ private final static int BINS = 50;
+
+ /**
+ * The current threshold value calculated by the findSeperation Method.
+ */
+ private final double sensitivityThreshold;
+
+ /**
+ * Maximum cluster dimensionality
+ */
+ private final int maxLMDim;
+
+ /**
+ * Minimum cluster size
+ */
+ private final int minsize;
+
+ /**
+ * Number of sampling rounds to find a good split
+ */
+ private final int samplingLevel;
+
+ /**
+ * Constructor.
+ *
+ * @param maxdim Maximum dimensionality
+ * @param minsize Minimum cluster size
+ * @param samplingLevel Sampling level
+ * @param sensitivityThreshold Threshold
+ */
+ public LMCLUS(int maxdim, int minsize, int samplingLevel, double sensitivityThreshold) {
+ super();
+ this.maxLMDim = maxdim;
+ this.minsize = minsize;
+ this.samplingLevel = samplingLevel;
+ this.sensitivityThreshold = sensitivityThreshold;
+ }
+
+ /**
+ * The main LMCLUS (Linear manifold clustering algorithm) is processed in this
+ * method.
+ *
+ * <PRE>
+ * The algorithm samples random linear manifolds and tries to find clusters in it.
+ * It calculates a distance histogram searches for a threshold and partitions the
+ * points in two groups the ones in the cluster and everything else.
+ * Then the best fitting linear manifold is searched and registered as a cluster.
+ * The process is started over until all points are clustered.
+ * The last cluster should contain all the outliers. (or the whole data if no clusters have been found.)
+ * For details see {@link LMCLUS}.
+ * </PRE>
+ *
+ * @param database The database to operate on
+ * @param relation Relation
+ * @return Clustering result
+ * @throws de.lmu.ifi.dbs.elki.utilities.UnableToComplyException
+ */
+ public Clustering<Model> run(Database database, Relation<NumberVector<?, ?>> relation) throws UnableToComplyException {
+ Clustering<Model> ret = new Clustering<Model>("LMCLUS Clustering", "lmclus-clustering");
+ FiniteProgress progress = logger.isVerbose() ? new FiniteProgress("Clustered objects", relation.size(), logger) : null;
+ IndefiniteProgress cprogress = logger.isVerbose() ? new IndefiniteProgress("Clusters found", logger) : null;
+ ModifiableDBIDs unclustered = DBIDUtil.newHashSet(relation.getDBIDs());
+
+ final int maxdim = Math.min(maxLMDim, DatabaseUtil.dimensionality(relation));
+ int cnum = 0;
+ while(unclustered.size() > minsize) {
+ DBIDs current = unclustered;
+ int lmDim = 1;
+ for(int k = 1; k <= maxdim; k++) {
+ // Implementation note: this while loop is from the original publication
+ // and the published LMCLUS source code. It doesn't make sense to me -
+ // it is lacking a stop criterion other than "cluster is too small" and
+ // "cluster is inseparable"! Additionally, there is good criterion for
+ // stopping at the appropriate dimensionality either.
+ while(true) {
+ Separation separation = findSeparation(relation, current, k);
+ // logger.verbose("k: " + k + " goodness: " + separation.goodness +
+ // " threshold: " + separation.threshold);
+ if(separation.goodness <= sensitivityThreshold) {
+ break;
+ }
+ ModifiableDBIDs subset = DBIDUtil.newArray(current.size());
+ for(DBID id : current) {
+ if(deviation(relation.get(id).getColumnVector().minusEquals(separation.originV), separation.basis) < separation.threshold) {
+ subset.add(id);
+ }
+ }
+ // logger.verbose("size:"+subset.size());
+ if(subset.size() < minsize) {
+ break;
+ }
+ current = subset;
+ lmDim = k;
+ // System.out.println("Partition: " + subset.size());
+ }
+ }
+ // No more clusters found
+ if(current.size() < minsize || current == unclustered) {
+ break;
+ }
+ // New cluster found
+ // TODO: annotate cluster with dimensionality
+ final Cluster<Model> cluster = new Cluster<Model>(current);
+ cluster.setName("Cluster_" + lmDim + "d_" + cnum);
+ cnum++;
+ ret.addCluster(cluster);
+ // Remove from main working set.
+ unclustered.removeDBIDs(current);
+ if(progress != null) {
+ progress.setProcessed(relation.size() - unclustered.size(), logger);
+ }
+ if(cprogress != null) {
+ cprogress.setProcessed(cnum, logger);
+ }
+ }
+ // Remaining objects are noise
+ if(unclustered.size() > 0) {
+ ret.addCluster(new Cluster<Model>(unclustered, true));
+ }
+ if(progress != null) {
+ progress.setProcessed(relation.size(), logger);
+ progress.ensureCompleted(logger);
+ }
+ if(cprogress != null) {
+ cprogress.setCompleted(logger);
+ }
+ return ret;
+ }
+
+ /**
+ * Deviation from a manifold described by beta.
+ *
+ * @param delta Delta from origin vector
+ * @param beta Manifold
+ * @return Deviation score
+ */
+ private double deviation(Vector delta, Matrix beta) {
+ double a = delta.euclideanLength();
+ double b = beta.transposeTimes(delta).euclideanLength();
+ return Math.sqrt((a * a) - (b * b));
+ }
+
+ /**
+ * This method samples a number of linear manifolds an tries to determine
+ * which the one with the best cluster is.
+ *
+ * <PRE>
+ * A number of sample points according to the dimension of the linear manifold are taken.
+ * The basis (B) and the origin(o) of the manifold are calculated.
+ * A distance histogram using the distance function ||x-o|| -||B^t*(x-o)|| is generated.
+ * The best threshold is searched using the elevate threshold function.
+ * The overall goodness of the threshold is determined.
+ * The process is redone until a specific number of samples is taken.
+ * </PRE>
+ *
+ * @param relation The vector relation
+ * @param currentids Current DBIDs
+ * @param dimension the dimension of the linear manifold to sample.
+ * @return the overall goodness of the separation. The values origin basis and
+ * threshold are returned indirectly over class variables.
+ */
+ private Separation findSeparation(Relation<NumberVector<?, ?>> relation, DBIDs currentids, int dimension) {
+ Separation separation = new Separation();
+ // determine the number of samples needed, to secure that with a specific
+ // probability
+ // in at least on sample every sampled point is from the same cluster.
+ int samples = (int) Math.min(Math.log(NOT_FROM_ONE_CLUSTER_PROBABILITY) / (Math.log(1 - Math.pow((1.0d / samplingLevel), dimension))), (double) currentids.size());
+ // System.out.println("Number of samples: " + samples);
+ Random r = new Random();
+ int remaining_retries = 100;
+ for(int i = 1; i <= samples; i++) {
+ DBIDs sample = DBIDUtil.randomSample(currentids, dimension + 1, r.nextLong());
+ final Iterator<DBID> iter = sample.iterator();
+ // Use first as origin
+ DBID origin = iter.next();
+ Vector originV = relation.get(origin).getColumnVector();
+ // Build orthogonal basis from remainder
+ Matrix basis;
+ {
+ List<Vector> vectors = new ArrayList<Vector>(sample.size() - 1);
+ while(iter.hasNext()) {
+ Vector vec = relation.get(iter.next()).getColumnVector();
+ vectors.add(vec.minusEquals(originV));
+ }
+ // generate orthogonal basis
+ basis = generateOrthonormalBasis(vectors);
+ if(basis == null) {
+ // new sample has to be taken.
+ i--;
+ remaining_retries--;
+ if(remaining_retries < 0) {
+ throw new AbortException("Too many retries in sampling, and always a linear dependant data set.");
+ }
+ continue;
+ }
+ }
+ // Generate and fill a histogram.
+ FlexiHistogram<Double, Double> histogram = FlexiHistogram.DoubleSumHistogram(BINS);
+ double w = 1.0 / currentids.size();
+ for(DBID point : currentids) {
+ // Skip sampled points
+ if(sample.contains(point)) {
+ continue;
+ }
+ Vector vec = relation.get(point).getColumnVector().minusEquals(originV);
+ final double distance = deviation(vec, basis);
+ histogram.aggregate(distance, w);
+ }
+ double[] th = findAndEvaluateThreshold(histogram); // evaluate threshold
+ if(th[1] > separation.goodness) {
+ separation.goodness = th[1];
+ separation.threshold = th[0];
+ separation.originV = originV;
+ separation.basis = basis;
+ }
+ }
+ return separation;
+ }
+
+ /**
+ * This Method generates an orthonormal basis from a set of Vectors. It uses
+ * the established Gram-Schmidt algorithm for orthonormalisation:
+ *
+ * <PRE>
+ * u_1 = v_1
+ * u_k = v_k -proj_u1(v_k)...proj_u(k-1)(v_k);
+ *
+ * Where proj_u(v) = <v,u>/<u,u> *u
+ * </PRE>
+ *
+ * @param vectors The set of vectors to generate the orthonormal basis from
+ * @return the orthonormal basis generated by this method.
+ * @throws RuntimeException if the given vectors are not linear independent.
+ */
+ private Matrix generateOrthonormalBasis(List<Vector> vectors) {
+ Vector first = vectors.get(0);
+ first = first.times(1.0 / first.euclideanLength());
+ Matrix ret = new Matrix(first.getDimensionality(), vectors.size());
+ ret.setCol(0, first);
+ for(int i = 1; i < vectors.size(); i++) {
+ // System.out.println("Matrix:" + ret);
+ Vector v_i = vectors.get(i);
+ Vector u_i = v_i.copy();
+ // System.out.println("Vector " + i + ":" + partialSol);
+ for(int j = 0; j < i; j++) {
+ Vector v_j = ret.getCol(j);
+ double f = v_i.transposeTimes(v_j) / v_j.transposeTimes(v_j);
+ if(Double.isNaN(f)) {
+ if(logger.isDebuggingFine()) {
+ logger.debugFine("Zero vector encountered? " + v_j);
+ }
+ return null;
+ }
+ u_i.minusTimesEquals(v_j, f);
+ }
+ // check if the vectors weren't independent
+ final double len_u_i = u_i.euclideanLength();
+ if(len_u_i == 0.0) {
+ if(logger.isDebuggingFine()) {
+ logger.debugFine("Points not independent - no orthonormalization.");
+ }
+ return null;
+ }
+ // System.out.println("Vector " + i + ":" + partialSol);
+ u_i.timesEquals(1 / len_u_i);
+ ret.setCol(i, u_i);
+ }
+ return ret;
+ }
+
+ /**
+ * Evaluate the histogram to find a suitable threshold
+ *
+ * @param histogram Histogram to evaluate
+ * @return Position and goodness
+ */
+ private double[] findAndEvaluateThreshold(FlexiHistogram<Double, Double> histogram) {
+ int n = histogram.getNumBins();
+ double[] p1 = new double[n];
+ double[] p2 = new double[n];
+ double[] mu1 = new double[n];
+ double[] mu2 = new double[n];
+ double[] sigma1 = new double[n];
+ double[] sigma2 = new double[n];
+ double[] jt = new double[n];
+ // Forward pass
+ {
+ MeanVariance mv = new MeanVariance();
+ Iterator<DoubleObjPair<Double>> forward = histogram.iterator();
+ for(int i = 0; forward.hasNext(); i++) {
+ DoubleObjPair<Double> pair = forward.next();
+ p1[i] = pair.second + ((i > 0) ? p1[i - 1] : 0);
+ mv.put(i, pair.second);
+ mu1[i] = mv.getMean();
+ sigma1[i] = mv.getNaiveStddev();
+ }
+ }
+ // Backwards pass
+ {
+ MeanVariance mv = new MeanVariance();
+ Iterator<DoubleObjPair<Double>> backwards = histogram.reverseIterator();
+ for(int j = n - 1; backwards.hasNext(); j--) {
+ DoubleObjPair<Double> pair = backwards.next();
+ p2[j] = pair.second + ((j + 1 < n) ? p2[j + 1] : 0);
+ mv.put(j, pair.second);
+ mu2[j] = mv.getMean();
+ sigma2[j] = mv.getNaiveStddev();
+ }
+ }
+
+ for(int i = 0; i < n; i++) {
+ jt[i] = 1.0 + 2 * (p1[i] * (Math.log(sigma1[i]) - Math.log(p1[i])) + p2[i] * (Math.log(sigma2[i]) - Math.log(p2[i])));
+ }
+
+ int bestpos = -1;
+ double bestgoodness = Double.NEGATIVE_INFINITY;
+
+ double devPrev = jt[1] - jt[0];
+ for(int i = 1; i < jt.length - 1; i++) {
+ double devCur = jt[i + 1] - jt[i];
+ // System.out.println(p1[i]);
+ // System.out.println(jt[i + 1]);
+ // System.out.println(jt[i]);
+ // System.out.println(devCur);
+ // Local minimum found - calculate depth
+ if(devCur >= 0 && devPrev <= 0) {
+ double lowestMaxima = Double.POSITIVE_INFINITY;
+ for(int j = i - 1; j > 0; j--) {
+ if(jt[j - 1] < jt[j]) {
+ lowestMaxima = Math.min(lowestMaxima, jt[j]);
+ break;
+ }
+ }
+ for(int j = i + 1; j < n - 2; j++) {
+ if(jt[j + 1] < jt[j]) {
+ lowestMaxima = Math.min(lowestMaxima, jt[j]);
+ break;
+ }
+ }
+ double localDepth = lowestMaxima - jt[i];
+
+ final double mud = mu1[i] - mu2[i];
+ double discriminability = mud * mud / (sigma1[i] * sigma1[i] + sigma2[i] * sigma2[i]);
+ if(Double.isNaN(discriminability)) {
+ discriminability = -1;
+ }
+ double goodness = localDepth * discriminability;
+ if(goodness > bestgoodness) {
+ bestgoodness = goodness;
+ bestpos = i;
+ }
+ }
+ devPrev = devCur;
+ }
+ return new double[] { histogram.getBinMax(bestpos), bestgoodness };
+ }
+
+ @Override
+ protected Logging getLogger() {
+ return logger;
+ }
+
+ @Override
+ public TypeInformation[] getInputTypeRestriction() {
+ return TypeUtil.array(TypeUtil.NUMBER_VECTOR_FIELD);
+ }
+
+ /**
+ * Class to represent a linear manifold separation
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ private static class Separation {
+ /**
+ * Goodness of separation
+ */
+ double goodness = Double.NEGATIVE_INFINITY;
+
+ /**
+ * Threshold
+ */
+ double threshold = Double.NEGATIVE_INFINITY;
+
+ /**
+ * Basis of manifold
+ */
+ Matrix basis = null;
+
+ /**
+ * Origin vector
+ */
+ Vector originV = null;
+ }
+
+ /**
+ * Parameterization class
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ /**
+ * Parameter with the maximum dimension to search for
+ */
+ public static final OptionID MAXDIM_ID = OptionID.getOrCreateOptionID("lmclus.maxdim", "Maximum linear manifold dimension to search.");
+
+ /**
+ * Parameter for the minimum cluster size
+ */
+ public static final OptionID MINSIZE_ID = OptionID.getOrCreateOptionID("lmclus.minsize", "Minimum cluster size to allow.");
+
+ /**
+ * Sampling intensity level
+ */
+ public static final OptionID SAMPLINGL_ID = OptionID.getOrCreateOptionID("lmclus.sampling-level", "A number used to determine how many samples are taken in each search.");
+
+ /**
+ * Global significance threshold
+ */
+ public static final OptionID THRESHOLD_ID = OptionID.getOrCreateOptionID("lmclus.threshold", "Threshold to determine if a cluster was found.");
+
+ /**
+ * Maximum dimensionality to search for
+ */
+ private int maxdim = Integer.MAX_VALUE;
+
+ /**
+ * Minimum cluster size.
+ */
+ private int minsize;
+
+ /**
+ * Sampling level
+ */
+ private int samplingLevel;
+
+ /**
+ * Threshold
+ */
+ private double threshold;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ IntParameter maxLMDimP = new IntParameter(MAXDIM_ID, new GreaterEqualConstraint(1), true);
+ if(config.grab(maxLMDimP)) {
+ maxdim = maxLMDimP.getValue();
+ }
+ IntParameter minsizeP = new IntParameter(MINSIZE_ID, new GreaterEqualConstraint(1));
+ if(config.grab(minsizeP)) {
+ minsize = minsizeP.getValue();
+ }
+ IntParameter samplingLevelP = new IntParameter(SAMPLINGL_ID, 100);
+ if(config.grab(samplingLevelP)) {
+ samplingLevel = samplingLevelP.getValue();
+ }
+ DoubleParameter sensivityThresholdP = new DoubleParameter(THRESHOLD_ID);
+ if(config.grab(sensivityThresholdP)) {
+ threshold = sensivityThresholdP.getValue();
+ }
+ }
+
+ @Override
+ protected LMCLUS makeInstance() {
+ return new LMCLUS(maxdim, minsize, samplingLevel, threshold);
+ }
+ }
+} \ No newline at end of file
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 924e1786..eb5608fc 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) 2011
+ Copyright (C) 2012
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.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.progress.IndefiniteProgress;
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.math.linearalgebra.pca.PCAResult;
import de.lmu.ifi.dbs.elki.math.linearalgebra.pca.PCARunner;
import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
@@ -420,14 +421,14 @@ public class ORCLUS<V extends NumberVector<V, ?>> extends AbstractProjectedClust
/**
* Returns the union of the two specified clusters.
*
- * @param database the database holding the objects
+ * @param relation the database holding the objects
* @param distFunc the distance function
* @param c1 the first cluster
* @param c2 the second cluster
* @param dim the dimensionality of the union cluster
* @return the union of the two specified clusters
*/
- private ORCLUSCluster union(Relation<V> database, DistanceQuery<V, DoubleDistance> distFunc, ORCLUSCluster c1, ORCLUSCluster c2, int dim) {
+ private ORCLUSCluster union(Relation<V> relation, DistanceQuery<V, DoubleDistance> distFunc, ORCLUSCluster c1, ORCLUSCluster c2, int dim) {
ORCLUSCluster c = new ORCLUSCluster();
c.objectIDs = DBIDUtil.newHashSet(c1.objectIDs);
@@ -436,11 +437,13 @@ public class ORCLUS<V extends NumberVector<V, ?>> extends AbstractProjectedClust
c.objectIDs = DBIDUtil.newArray(c.objectIDs);
if(c.objectIDs.size() > 0) {
- c.centroid = DatabaseUtil.centroid(database, c.objectIDs);
- c.basis = findBasis(database, distFunc, c, dim);
+ c.centroid = DatabaseUtil.centroid(relation, c.objectIDs);
+ c.basis = findBasis(relation, distFunc, c, dim);
}
else {
- c.centroid = c1.centroid.plus(c2.centroid).multiplicate(0.5);
+ V factory = DatabaseUtil.assumeVectorField(relation).getFactory();
+ Vector cent = c1.centroid.getColumnVector().plusEquals(c2.centroid.getColumnVector()).timesEquals(0.5);
+ c.centroid = factory.newNumberVector(cent.getArrayRef());
double[][] doubles = new double[c1.basis.getRowDimensionality()][dim];
for(int i = 0; i < dim; i++) {
doubles[i][i] = 1;
@@ -460,9 +463,9 @@ public class ORCLUS<V extends NumberVector<V, ?>> extends AbstractProjectedClust
* @return the projection of double vector o in the subspace of cluster c
*/
private V projection(ORCLUSCluster c, V o, V factory) {
- Matrix o_proj = o.getRowVector().times(c.basis);
+ Matrix o_proj = o.getColumnVector().transposeTimes(c.basis);
double[] values = o_proj.getColumnPackedCopy();
- return factory.newInstance(values);
+ return factory.newNumberVector(values);
}
@Override
@@ -523,7 +526,7 @@ public class ORCLUS<V extends NumberVector<V, ?>> extends AbstractProjectedClust
for(int d = 1; d <= o.getDimensionality(); d++) {
values[d - 1] = o.doubleValue(d);
}
- this.centroid = factory.newInstance(values);
+ this.centroid = factory.newNumberVector(values);
}
}
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 6c5db740..46112498 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) 2011
+ Copyright (C) 2012
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 62ff658f..86e045cb 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) 2011
+ Copyright (C) 2012
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 8cd156e8..8b6d104c 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) 2011
+Copyright (C) 2012
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 82a1f1e1..665de632 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) 2011
+Copyright (C) 2012
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/AbstractKMeans.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/AbstractKMeans.java
new file mode 100644
index 00000000..d3c73b53
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/AbstractKMeans.java
@@ -0,0 +1,310 @@
+package de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import de.lmu.ifi.dbs.elki.algorithm.AbstractPrimitiveDistanceBasedAlgorithm;
+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.data.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.database.ids.DBID;
+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.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You 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 k-means implementations.
+ *
+ * @author Erich Schubert
+ *
+ * @param <V> Vector type
+ * @param <D> Distance type
+ */
+public abstract class AbstractKMeans<V extends NumberVector<V, ?>, D extends Distance<D>> extends AbstractPrimitiveDistanceBasedAlgorithm<NumberVector<?, ?>, D, Clustering<MeanModel<V>>> {
+ /**
+ * Parameter to specify the number of clusters to find, must be an integer
+ * greater than 0.
+ */
+ public static final OptionID K_ID = OptionID.getOrCreateOptionID("kmeans.k", "The number of clusters to find.");
+
+ /**
+ * Parameter to specify the number of clusters to find, must be an integer
+ * greater or equal to 0, where 0 means no limit.
+ */
+ public static final OptionID MAXITER_ID = OptionID.getOrCreateOptionID("kmeans.maxiter", "The maximum number of iterations to do. 0 means no limit.");
+
+ /**
+ * Parameter to specify the random generator seed.
+ */
+ public static final OptionID SEED_ID = OptionID.getOrCreateOptionID("kmeans.seed", "The random number generator seed.");
+
+ /**
+ * Parameter to specify the initialization method
+ */
+ public static final OptionID INIT_ID = OptionID.getOrCreateOptionID("kmeans.initialization", "Method to choose the initial means.");
+
+ /**
+ * Holds the value of {@link #K_ID}.
+ */
+ protected int k;
+
+ /**
+ * Holds the value of {@link #MAXITER_ID}.
+ */
+ protected int maxiter;
+
+ /**
+ * Method to choose initial means.
+ */
+ protected KMeansInitialization<V> initializer;
+
+ /**
+ * Constructor.
+ *
+ * @param distanceFunction distance function
+ * @param k k parameter
+ * @param maxiter Maxiter parameter
+ */
+ public AbstractKMeans(PrimitiveDistanceFunction<NumberVector<?, ?>, D> distanceFunction, int k, int maxiter, KMeansInitialization<V> initializer) {
+ super(distanceFunction);
+ this.k = k;
+ this.maxiter = maxiter;
+ this.initializer = initializer;
+ }
+
+ /**
+ * Returns a list of clusters. The k<sup>th</sup> cluster contains the ids of
+ * those FeatureVectors, that are nearest to the k<sup>th</sup> mean.
+ *
+ * @param relation the database to cluster
+ * @param means a list of k means
+ * @param clusters cluster assignment
+ * @return true when the object was reassigned
+ */
+ protected boolean assignToNearestCluster(Relation<V> relation, List<Vector> means, List<? extends ModifiableDBIDs> clusters) {
+ boolean changed = false;
+
+ if(getDistanceFunction() instanceof PrimitiveDoubleDistanceFunction) {
+ @SuppressWarnings("unchecked")
+ final PrimitiveDoubleDistanceFunction<? super NumberVector<?, ?>> df = (PrimitiveDoubleDistanceFunction<? super NumberVector<?, ?>>) getDistanceFunction();
+ for(DBID id : relation.iterDBIDs()) {
+ double mindist = Double.POSITIVE_INFINITY;
+ V fv = relation.get(id);
+ int minIndex = 0;
+ for(int i = 0; i < k; i++) {
+ double dist = df.doubleDistance(fv, means.get(i));
+ if(dist < mindist) {
+ minIndex = i;
+ mindist = dist;
+ }
+ }
+ if(clusters.get(minIndex).add(id)) {
+ 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(id)) {
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ else {
+ final PrimitiveDistanceFunction<? super NumberVector<?, ?>, D> df = getDistanceFunction();
+ for(DBID id : relation.iterDBIDs()) {
+ D mindist = df.getDistanceFactory().infiniteDistance();
+ V fv = relation.get(id);
+ int minIndex = 0;
+ for(int i = 0; i < k; i++) {
+ D dist = df.distance(fv, means.get(i));
+ if(dist.compareTo(mindist) < 0) {
+ minIndex = i;
+ mindist = dist;
+ }
+ }
+ if(clusters.get(minIndex).add(id)) {
+ 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(id)) {
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ return changed;
+ }
+
+ @Override
+ public TypeInformation[] getInputTypeRestriction() {
+ return TypeUtil.array(TypeUtil.NUMBER_VECTOR_FIELD);
+ }
+
+ /**
+ * Returns the mean vectors of the given clusters in the given database.
+ *
+ * @param clusters the clusters to compute the means
+ * @param means the recent means
+ * @param database the database containing the vectors
+ * @return the mean vectors of the given clusters in the given database
+ */
+ protected List<Vector> means(List<? extends ModifiableDBIDs> clusters, List<Vector> means, Relation<V> database) {
+ List<Vector> newMeans = new ArrayList<Vector>(k);
+ for(int i = 0; i < k; i++) {
+ ModifiableDBIDs list = clusters.get(i);
+ Vector mean = null;
+ for(Iterator<DBID> clusterIter = list.iterator(); clusterIter.hasNext();) {
+ if(mean == null) {
+ mean = database.get(clusterIter.next()).getColumnVector();
+ }
+ else {
+ mean.plusEquals(database.get(clusterIter.next()).getColumnVector());
+ }
+ }
+ if(list.size() > 0) {
+ assert mean != null;
+ mean.timesEquals(1.0 / list.size());
+ }
+ else {
+ mean = means.get(i);
+ }
+ newMeans.add(mean);
+ }
+ return newMeans;
+ }
+
+ /**
+ * Compute an incremental update for the mean
+ *
+ * @param mean Mean to update
+ * @param vec Object vector
+ * @param newsize (New) size of cluster
+ * @param op Cluster size change / Weight change
+ */
+ protected void incrementalUpdateMean(Vector mean, V vec, int newsize, double op) {
+ if(newsize == 0) {
+ return; // Keep old mean
+ }
+ Vector delta = vec.getColumnVector();
+ // Compute difference from mean
+ delta.minusEquals(mean);
+ delta.timesEquals(op / newsize);
+ mean.plusEquals(delta);
+ }
+
+ /**
+ * Perform a MacQueen style iteration.
+ *
+ * @param relation Relation
+ * @param means Means
+ * @param clusters Clusters
+ * @return true when the means have changed
+ */
+ protected boolean macQueenIterate(Relation<V> relation, List<Vector> means, List<ModifiableDBIDs> clusters) {
+ boolean changed = false;
+
+ if(getDistanceFunction() instanceof PrimitiveDoubleDistanceFunction) {
+ // Raw distance function
+ @SuppressWarnings("unchecked")
+ final PrimitiveDoubleDistanceFunction<? super NumberVector<?, ?>> df = (PrimitiveDoubleDistanceFunction<? super NumberVector<?, ?>>) getDistanceFunction();
+
+ // Incremental update
+ for(DBID id : relation.iterDBIDs()) {
+ double mindist = Double.POSITIVE_INFINITY;
+ V fv = relation.get(id);
+ int minIndex = 0;
+ for(int i = 0; i < k; i++) {
+ double dist = df.doubleDistance(fv, means.get(i));
+ if(dist < mindist) {
+ minIndex = i;
+ mindist = dist;
+ }
+ }
+ // Update the cluster mean incrementally:
+ for(int i = 0; i < k; i++) {
+ ModifiableDBIDs ci = clusters.get(i);
+ if(i == minIndex) {
+ if(ci.add(id)) {
+ incrementalUpdateMean(means.get(i), relation.get(id), ci.size(), +1);
+ changed = true;
+ }
+ }
+ else if(ci.remove(id)) {
+ incrementalUpdateMean(means.get(i), relation.get(id), ci.size() + 1, -1);
+ changed = true;
+ }
+ }
+ }
+ }
+ else {
+ // Raw distance function
+ final PrimitiveDistanceFunction<? super NumberVector<?, ?>, D> df = getDistanceFunction();
+
+ // Incremental update
+ for(DBID id : relation.iterDBIDs()) {
+ D mindist = df.getDistanceFactory().infiniteDistance();
+ V fv = relation.get(id);
+ int minIndex = 0;
+ for(int i = 0; i < k; i++) {
+ D dist = df.distance(fv, means.get(i));
+ if(dist.compareTo(mindist) < 0) {
+ minIndex = i;
+ mindist = dist;
+ }
+ }
+ // Update the cluster mean incrementally:
+ for(int i = 0; i < k; i++) {
+ ModifiableDBIDs ci = clusters.get(i);
+ if(i == minIndex) {
+ if(ci.add(id)) {
+ incrementalUpdateMean(means.get(i), relation.get(id), ci.size(), +1);
+ changed = true;
+ }
+ }
+ else if(ci.remove(id)) {
+ incrementalUpdateMean(means.get(i), relation.get(id), ci.size() + 1, -1);
+ changed = true;
+ }
+ }
+ }
+ }
+ return changed;
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..b5f088fb
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/AbstractKMeansInitialization.java
@@ -0,0 +1,71 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.LongParameter;
+
+/**
+ * Abstract base class for common k-means initializations.
+ *
+ * @author Erich Schubert
+ *
+ * @param <V> Vector type
+ */
+public abstract class AbstractKMeansInitialization<V extends NumberVector<V, ?>> implements KMeansInitialization<V> {
+ /**
+ * Holds the value of {@link KMeansLloyd#SEED_ID}.
+ */
+ protected Long seed;
+
+ /**
+ * Constructor.
+ *
+ * @param seed Random seed.
+ */
+ public AbstractKMeansInitialization(Long seed) {
+ this.seed = seed;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public abstract static class Parameterizer<V extends NumberVector<V, ?>> extends AbstractParameterizer {
+ protected Long seed;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ LongParameter seedP = new LongParameter(AbstractKMeans.SEED_ID, true);
+ if(config.grab(seedP)) {
+ seed = seedP.getValue();
+ }
+ }
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..78ccd426
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/FirstKInitialMeans.java
@@ -0,0 +1,74 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.Iterator;
+import java.util.List;
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.database.ids.DBID;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Initialize K-means by using the first k objects as initial means.
+ *
+ * @author Erich Schubert
+ *
+ * @param <V> Vector type
+ */
+public class FirstKInitialMeans<V extends NumberVector<V, ?>> extends AbstractKMeansInitialization<V> {
+ /**
+ * Constructor.
+ */
+ public FirstKInitialMeans() {
+ super(null);
+ }
+
+ @Override
+ public List<Vector> chooseInitialMeans(Relation<V> relation, int k, PrimitiveDistanceFunction<? super V, ?> distanceFunction) {
+ Iterator<DBID> iter = relation.iterDBIDs();
+ List<Vector> means = new ArrayList<Vector>(k);
+ for(int i = 0; i < k && iter.hasNext(); i++) {
+ means.add(relation.get(iter.next()).getColumnVector());
+ }
+ return means;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer<V extends NumberVector<V, ?>> extends AbstractParameterizer {
+ @Override
+ protected FirstKInitialMeans<V> makeInstance() {
+ return new FirstKInitialMeans<V>();
+ }
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..f4c0d9c7
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeansInitialization.java
@@ -0,0 +1,49 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
+
+/**
+ * Interface for initializing K-Means
+ *
+ * @author Erich Schubert
+ *
+ * @param <V> Vector type
+ */
+public interface KMeansInitialization<V extends NumberVector<V, ?>> {
+ /**
+ * Choose initial means
+ *
+ * @param relation Relation
+ * @param k Parameter k
+ * @param distanceFunction Distance function
+ * @return List of chosen means for k-means
+ */
+ public abstract List<Vector> chooseInitialMeans(Relation<V> relation, int k, PrimitiveDistanceFunction<? super V, ?> distanceFunction);
+} \ No newline at end of file
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
new file mode 100644
index 00000000..fda1d6c0
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeansLloyd.java
@@ -0,0 +1,176 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.algorithm.AbstractPrimitiveDistanceBasedAlgorithm;
+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.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.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.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.math.linearalgebra.Vector;
+import de.lmu.ifi.dbs.elki.utilities.DatabaseUtil;
+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.
+ *
+ * <p>
+ * Reference:<br />
+ * S. Lloyd<br/>
+ * Least squares quantization in PCM<br/>
+ * IEEE Transactions on Information Theory 28 (2)<br/>
+ * previously published as Bell Telephone Laboratories Paper
+ * </p>
+ *
+ * @author Arthur Zimek
+ *
+ * @apiviz.has MeanModel
+ *
+ * @param <V> vector datatype
+ * @param <D> distance value type
+ */
+@Title("K-Means")
+@Description("Finds a partitioning into k clusters.")
+@Reference(authors = "S. Lloyd", title = "Least squares quantization in PCM", booktitle = "IEEE Transactions on Information Theory 28 (2): 129–137.", url = "http://dx.doi.org/10.1109/TIT.1982.1056489")
+public class KMeansLloyd<V extends NumberVector<V, ?>, D extends Distance<D>> extends AbstractKMeans<V, D> implements ClusteringAlgorithm<Clustering<MeanModel<V>>> {
+ /**
+ * The logger for this class.
+ */
+ private static final Logging logger = Logging.getLogger(KMeansLloyd.class);
+
+ /**
+ * Constructor.
+ *
+ * @param distanceFunction distance function
+ * @param k k parameter
+ * @param maxiter Maxiter parameter
+ */
+ public KMeansLloyd(PrimitiveDistanceFunction<NumberVector<?, ?>, D> distanceFunction, int k, int maxiter, KMeansInitialization<V> initializer) {
+ super(distanceFunction, k, maxiter, initializer);
+ }
+
+ /**
+ * Run k-means
+ *
+ * @param database Database
+ * @param relation relation to use
+ * @return result
+ * @throws IllegalStateException
+ */
+ public Clustering<MeanModel<V>> run(Database database, Relation<V> relation) throws IllegalStateException {
+ if(relation.size() <= 0) {
+ return new Clustering<MeanModel<V>>("k-Means Clustering", "kmeans-clustering");
+ }
+ // Choose initial means
+ List<Vector> means = initializer.chooseInitialMeans(relation, k, getDistanceFunction());
+ // Setup cluster assignment store
+ List<ModifiableDBIDs> clusters = new ArrayList<ModifiableDBIDs>();
+ for(int i = 0; i < k; i++) {
+ clusters.add(DBIDUtil.newHashSet(relation.size() / k));
+ }
+
+ for(int iteration = 0; maxiter <= 0 || iteration < maxiter; iteration++) {
+ if(logger.isVerbose()) {
+ logger.verbose("K-Means iteration " + (iteration + 1));
+ }
+ boolean changed = assignToNearestCluster(relation, means, clusters);
+ // Stop if no cluster assignment changed.
+ if(!changed) {
+ break;
+ }
+ // Recompute means.
+ means = means(clusters, means, relation);
+ }
+ // Wrap result
+ final V factory = DatabaseUtil.assumeVectorField(relation).getFactory();
+ Clustering<MeanModel<V>> result = new Clustering<MeanModel<V>>("k-Means Clustering", "kmeans-clustering");
+ for(int i = 0; i < clusters.size(); i++) {
+ MeanModel<V> model = new MeanModel<V>(factory.newNumberVector(means.get(i).getArrayRef()));
+ result.addCluster(new Cluster<MeanModel<V>>(clusters.get(i), model));
+ }
+ return result;
+ }
+
+ @Override
+ protected Logging getLogger() {
+ return logger;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer<V extends NumberVector<V, ?>, D extends Distance<D>> extends AbstractPrimitiveDistanceBasedAlgorithm.Parameterizer<NumberVector<?, ?>, D> {
+ protected int k;
+
+ protected int maxiter;
+
+ protected KMeansInitialization<V> initializer;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ IntParameter kP = new IntParameter(K_ID, 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, new GreaterEqualConstraint(0), 0);
+ if(config.grab(maxiterP)) {
+ maxiter = maxiterP.getValue();
+ }
+ }
+
+ @Override
+ protected AbstractKMeans<V, D> makeInstance() {
+ return new KMeansLloyd<V, D>(distanceFunction, k, maxiter, initializer);
+ }
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..56492dd0
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeansMacQueen.java
@@ -0,0 +1,177 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.algorithm.AbstractPrimitiveDistanceBasedAlgorithm;
+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.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.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.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.logging.Logging;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
+import de.lmu.ifi.dbs.elki.utilities.DatabaseUtil;
+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.
+ *
+ * <p>
+ * Reference:<br />
+ * J. MacQueen: Some Methods for Classification and Analysis of Multivariate
+ * Observations. <br />
+ * In 5th Berkeley Symp. Math. Statist. Prob., Vol. 1, 1967, pp 281-297.
+ * </p>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has MeanModel
+ *
+ * @param <V> vector type to use
+ * @param <D> distance function value type
+ */
+@Title("K-Means")
+@Description("Finds a partitioning into k clusters.")
+@Reference(authors = "J. MacQueen", title = "Some Methods for Classification and Analysis of Multivariate Observations", booktitle = "5th Berkeley Symp. Math. Statist. Prob., Vol. 1, 1967, pp 281-297", url = "http://projecteuclid.org/euclid.bsmsp/1200512992")
+public class KMeansMacQueen<V extends NumberVector<V, ?>, D extends Distance<D>> extends AbstractKMeans<V, D> implements ClusteringAlgorithm<Clustering<MeanModel<V>>> {
+ /**
+ * The logger for this class.
+ */
+ private static final Logging logger = Logging.getLogger(KMeansMacQueen.class);
+
+ /**
+ * Constructor.
+ *
+ * @param distanceFunction distance function
+ * @param k k parameter
+ * @param maxiter Maxiter parameter
+ */
+ public KMeansMacQueen(PrimitiveDistanceFunction<NumberVector<?, ?>, D> distanceFunction, int k, int maxiter, KMeansInitialization<V> initializer) {
+ super(distanceFunction, k, maxiter, initializer);
+ }
+
+ /**
+ * Run k-means
+ *
+ * @param database Database
+ * @param relation relation to use
+ * @return result
+ * @throws IllegalStateException
+ */
+ public Clustering<MeanModel<V>> run(Database database, Relation<V> relation) throws IllegalStateException {
+ if(relation.size() <= 0) {
+ return new Clustering<MeanModel<V>>("k-Means Clustering", "kmeans-clustering");
+ }
+ // Choose initial means
+ List<Vector> means = initializer.chooseInitialMeans(relation, k, getDistanceFunction());
+ // Initialize cluster and assign objects
+ List<ModifiableDBIDs> clusters = new ArrayList<ModifiableDBIDs>();
+ for(int i = 0; i < k; i++) {
+ clusters.add(DBIDUtil.newHashSet(relation.size() / k));
+ }
+ assignToNearestCluster(relation, means, clusters);
+ // Initial recomputation of the means.
+ means = means(clusters, means, relation);
+
+ // Refine result
+ for(int iteration = 0; maxiter <= 0 || iteration < maxiter; iteration++) {
+ if(logger.isVerbose()) {
+ logger.verbose("K-Means iteration " + (iteration + 1));
+ }
+ boolean changed = macQueenIterate(relation, means, clusters);
+ if(!changed) {
+ break;
+ }
+ }
+ final V factory = DatabaseUtil.assumeVectorField(relation).getFactory();
+ Clustering<MeanModel<V>> result = new Clustering<MeanModel<V>>("k-Means Clustering", "kmeans-clustering");
+ for(int i = 0; i < clusters.size(); i++) {
+ DBIDs ids = clusters.get(i);
+ MeanModel<V> model = new MeanModel<V>(factory.newNumberVector(means.get(i).getArrayRef()));
+ result.addCluster(new Cluster<MeanModel<V>>(ids, model));
+ }
+ return result;
+ }
+
+ @Override
+ protected Logging getLogger() {
+ return logger;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer<V extends NumberVector<V, ?>, D extends Distance<D>> extends AbstractPrimitiveDistanceBasedAlgorithm.Parameterizer<NumberVector<?, ?>, D> {
+ protected int k;
+
+ protected int maxiter;
+
+ protected KMeansInitialization<V> initializer;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ IntParameter kP = new IntParameter(K_ID, 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, new GreaterEqualConstraint(0), 0);
+ if(config.grab(maxiterP)) {
+ maxiter = maxiterP.getValue();
+ }
+ }
+
+ @Override
+ protected AbstractKMeans<V, D> makeInstance() {
+ return new KMeansMacQueen<V, D>(distanceFunction, k, maxiter, initializer);
+ }
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..c7a2fa1d
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMeansPlusPlusInitialMeans.java
@@ -0,0 +1,213 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.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.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.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;
+import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
+
+/**
+ * K-Means++ initialization for k-means.
+ *
+ * Reference:
+ * <p>
+ * D. Arthur, S. Vassilvitskii<br />
+ * k-means++: the advantages of careful seeding<br />
+ * In: Proc. of the Eighteenth Annual ACM-SIAM Symposium on Discrete Algorithms,
+ * SODA 2007
+ * </p>
+ *
+ * @author Erich Schubert
+ *
+ * @param <V> Vector type
+ * @param <D> Distance type
+ */
+@Reference(authors = "D. Arthur, S. Vassilvitskii", title = "k-means++: the advantages of careful seeding", booktitle = "Proc. of the Eighteenth Annual ACM-SIAM Symposium on Discrete Algorithms, SODA 2007", url = "http://dx.doi.org/10.1145/1283383.1283494")
+public class KMeansPlusPlusInitialMeans<V extends NumberVector<V, ?>, D extends NumberDistance<D, ?>> extends AbstractKMeansInitialization<V> {
+ /**
+ * Constructor.
+ *
+ * @param seed Random seed.
+ */
+ public KMeansPlusPlusInitialMeans(Long seed) {
+ super(seed);
+ }
+
+ @Override
+ public List<Vector> chooseInitialMeans(Relation<V> relation, int k, PrimitiveDistanceFunction<? super V, ?> 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);
+
+ // Chose first mean
+ List<Vector> means = new ArrayList<Vector>(k);
+
+ Random random = (seed != null) ? new Random(seed) : new Random();
+ DBID first = DBIDUtil.randomSample(relation.getDBIDs(), 1, random.nextLong()).iterator().next();
+ means.add(relation.get(first).getColumnVector());
+
+ ModifiableDBIDs chosen = DBIDUtil.newHashSet(k);
+ chosen.add(first);
+ ArrayDBIDs ids = DBIDUtil.ensureArray(relation.getDBIDs());
+ // Initialize weights
+ double[] weights = new double[ids.size()];
+ double weightsum = initialWeights(weights, ids, first, distQ);
+ while(means.size() < k) {
+ if(weightsum > Double.MAX_VALUE) {
+ LoggingUtil.warning("Could not choose a reasonable mean for k-means++ - too many data points, too large squared distances?");
+ }
+ if(weightsum < Double.MIN_NORMAL) {
+ LoggingUtil.warning("Could not choose a reasonable mean for k-means++ - to few data points?");
+ }
+ double r = random.nextDouble() * weightsum;
+ int pos = 0;
+ while(r > 0 && pos < weights.length) {
+ r -= weights[pos];
+ pos++;
+ }
+ // Add new mean:
+ DBID newmean = ids.get(pos);
+ means.add(relation.get(newmean).getColumnVector());
+ chosen.add(newmean);
+ // Update weights:
+ weights[pos] = 0.0;
+ // Choose optimized version for double distances, if applicable.
+ if (distF instanceof PrimitiveDoubleDistanceFunction) {
+ @SuppressWarnings("unchecked")
+ PrimitiveDoubleDistanceFunction<V> ddist = (PrimitiveDoubleDistanceFunction<V>) distF;
+ weightsum = updateWeights(weights, ids, newmean, ddist, relation);
+ } else {
+ weightsum = updateWeights(weights, ids, newmean, distQ);
+ }
+ }
+
+ return means;
+ }
+
+ /**
+ * Initialize the weight list.
+ *
+ * @param weights Weight list
+ * @param ids IDs
+ * @param latest Added ID
+ * @param distQ Distance query
+ * @return Weight sum
+ */
+ protected double initialWeights(double[] weights, ArrayDBIDs ids, DBID latest, DistanceQuery<V, D> distQ) {
+ double weightsum = 0.0;
+ DBIDIter it = ids.iter();
+ for(int i = 0; i < weights.length; i++, it.advance()) {
+ DBID id = it.getDBID();
+ if(latest.equals(id)) {
+ weights[i] = 0.0;
+ }
+ else {
+ double d = distQ.distance(latest, id).doubleValue();
+ weights[i] = d * d;
+ }
+ weightsum += weights[i];
+ }
+ return weightsum;
+ }
+
+ /**
+ * Update the weight list.
+ *
+ * @param weights Weight list
+ * @param ids IDs
+ * @param latest Added ID
+ * @param distQ Distance query
+ * @return Weight sum
+ */
+ protected double updateWeights(double[] weights, ArrayDBIDs ids, DBID latest, DistanceQuery<V, D> distQ) {
+ double weightsum = 0.0;
+ DBIDIter it = ids.iter();
+ for(int i = 0; i < weights.length; i++, it.advance()) {
+ DBID id = it.getDBID();
+ if(weights[i] > 0.0) {
+ double d = distQ.distance(latest, id).doubleValue();
+ weights[i] = Math.min(weights[i], d * d);
+ weightsum += weights[i];
+ }
+ }
+ return weightsum;
+ }
+
+ /**
+ * Update the weight list.
+ *
+ * @param weights Weight list
+ * @param ids IDs
+ * @param latest Added ID
+ * @param distF Distance function
+ * @return Weight sum
+ */
+ protected double updateWeights(double[] weights, ArrayDBIDs ids, DBID latest, PrimitiveDoubleDistanceFunction<V> distF, Relation<V> rel) {
+ final V lv = rel.get(latest);
+ double weightsum = 0.0;
+ DBIDIter it = ids.iter();
+ for(int i = 0; i < weights.length; i++, it.advance()) {
+ DBID id = it.getDBID();
+ if(weights[i] > 0.0) {
+ double d = distF.doubleDistance(lv, rel.get(id));
+ weights[i] = Math.min(weights[i], d * d);
+ weightsum += weights[i];
+ }
+ }
+ return weightsum;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer<V extends NumberVector<V, ?>, D extends NumberDistance<D, ?>> extends AbstractKMeansInitialization.Parameterizer<V> {
+ @Override
+ protected KMeansPlusPlusInitialMeans<V, D> makeInstance() {
+ return new KMeansPlusPlusInitialMeans<V, D>(seed);
+ }
+ }
+} \ 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
new file mode 100644
index 00000000..30e59453
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/RandomlyChosenInitialMeans.java
@@ -0,0 +1,78 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.NumberVector;
+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.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
+
+/**
+ * Initialize K-means by randomly choosing k exsiting elements as cluster
+ * centers.
+ *
+ * @author Erich Schubert
+ *
+ * @param <V> Vector type
+ */
+public class RandomlyChosenInitialMeans<V extends NumberVector<V, ?>> extends AbstractKMeansInitialization<V> {
+ /**
+ * Constructor.
+ *
+ * @param seed Random seed.
+ */
+ public RandomlyChosenInitialMeans(Long seed) {
+ super(seed);
+ }
+
+ @Override
+ public List<Vector> chooseInitialMeans(Relation<V> relation, int k, PrimitiveDistanceFunction<? super V, ?> distanceFunction) {
+ DBIDs ids = DBIDUtil.randomSample(relation.getDBIDs(), k, seed);
+ List<Vector> means = new ArrayList<Vector>(k);
+ for(DBID id : ids) {
+ means.add(relation.get(id).getColumnVector());
+ }
+ return means;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer<V extends NumberVector<V, ?>> extends AbstractKMeansInitialization.Parameterizer<V> {
+
+ @Override
+ protected RandomlyChosenInitialMeans<V> makeInstance() {
+ return new RandomlyChosenInitialMeans<V>(seed);
+ }
+ }
+} \ 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
new file mode 100644
index 00000000..e8a466dd
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/RandomlyGeneratedInitialMeans.java
@@ -0,0 +1,87 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.relation.Relation;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction;
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
+import de.lmu.ifi.dbs.elki.utilities.DatabaseUtil;
+import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
+
+/**
+ * Initialize k-means by generating random vectors (within the data sets value
+ * range).
+ *
+ * @author Erich Schubert
+ *
+ * @param <V> Vector type
+ */
+public class RandomlyGeneratedInitialMeans<V extends NumberVector<V, ?>> extends AbstractKMeansInitialization<V> {
+ /**
+ * Constructor.
+ *
+ * @param seed Random seed.
+ */
+ public RandomlyGeneratedInitialMeans(Long seed) {
+ super(seed);
+ }
+
+ @Override
+ public List<Vector> chooseInitialMeans(Relation<V> relation, int k, PrimitiveDistanceFunction<? super V, ?> distanceFunction) {
+ final int dim = DatabaseUtil.dimensionality(relation);
+ Pair<V, V> minmax = DatabaseUtil.computeMinMax(relation);
+ List<Vector> means = new ArrayList<Vector>(k);
+ final Random random = (this.seed != null) ? new Random(this.seed) : new Random();
+ for(int i = 0; i < k; i++) {
+ double[] r = MathUtil.randomDoubleArray(dim, random);
+ // Rescale
+ for(int d = 0; d < dim; d++) {
+ r[d] = minmax.first.doubleValue(d + 1) + (minmax.second.doubleValue(d + 1) - minmax.first.doubleValue(d + 1)) * r[d];
+ }
+ means.add(new Vector(r));
+ }
+ return means;
+ }
+
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer<V extends NumberVector<V, ?>> extends AbstractKMeansInitialization.Parameterizer<V> {
+
+ @Override
+ protected RandomlyGeneratedInitialMeans<V> makeInstance() {
+ return new RandomlyGeneratedInitialMeans<V>(seed);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis1d/package-info.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/package-info.java
index 36dae86c..2ce625b0 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis1d/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/package-info.java
@@ -1,12 +1,11 @@
/**
- * <p>Visualizers based on 1D projections.</p>
- *
+ * <p>K-means clustering and variations.</p>
*/
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2011
+Copyright (C) 2012
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.visualization.visualizers.vis1d; \ No newline at end of file
+package de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans; \ 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 660a7a4f..eed031df 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
@@ -1,5 +1,5 @@
/**
- * <p>Clustering algorithms</p>
+ * <p>Clustering algorithms.</p>
*
* Clustering algorithms are supposed to implement the {@link de.lmu.ifi.dbs.elki.algorithm.Algorithm}-Interface.
* The more specialized interface {@link de.lmu.ifi.dbs.elki.algorithm.clustering.ClusteringAlgorithm}
@@ -15,7 +15,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2011
+Copyright (C) 2012
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 dfc4e1cd..e3b274a6 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) 2011
+ Copyright (C) 2012
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/DiSH.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/DiSH.java
index 987c7eda..c4c1687b 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) 2011
+ Copyright (C) 2012
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/HiSC.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/HiSC.java
index 36473cc0..40ab60a8 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) 2011
+Copyright (C) 2012
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/PROCLUS.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/PROCLUS.java
index 92c2248c..3f16e907 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) 2011
+ Copyright (C) 2012
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/PreDeCon.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/PreDeCon.java
index 22e9c150..4ca5a564 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) 2011
+ Copyright (C) 2012
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/SUBCLU.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/SUBCLU.java
index c0edb2ea..963c0922 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) 2011
+ Copyright (C) 2012
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.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.distance.distancefunction.subspace.AbstractDimensionsSelectingDoubleDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.DimensionsSelectingEuclideanDistanceFunction;
+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;
import de.lmu.ifi.dbs.elki.logging.progress.StepProgress;
@@ -94,7 +94,7 @@ public class SUBCLU<V extends NumberVector<V, ?>> extends AbstractAlgorithm<Clus
/**
* The distance function to determine the distance between database objects.
* <p>
- * Default value: {@link DimensionsSelectingEuclideanDistanceFunction}
+ * Default value: {@link SubspaceEuclideanDistanceFunction}
* </p>
* <p>
* Key: {@code -subclu.distancefunction}
@@ -477,7 +477,7 @@ public class SUBCLU<V extends NumberVector<V, ?>> extends AbstractAlgorithm<Clus
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- ObjectParameter<AbstractDimensionsSelectingDoubleDistanceFunction<V>> param = new ObjectParameter<AbstractDimensionsSelectingDoubleDistanceFunction<V>>(DISTANCE_FUNCTION_ID, AbstractDimensionsSelectingDoubleDistanceFunction.class, DimensionsSelectingEuclideanDistanceFunction.class);
+ ObjectParameter<AbstractDimensionsSelectingDoubleDistanceFunction<V>> param = new ObjectParameter<AbstractDimensionsSelectingDoubleDistanceFunction<V>>(DISTANCE_FUNCTION_ID, AbstractDimensionsSelectingDoubleDistanceFunction.class, SubspaceEuclideanDistanceFunction.class);
if(config.grab(param)) {
distance = param.instantiateClass(config);
}
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 1874c9e8..eff71a35 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) 2011
+ Copyright (C) 2012
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/CLIQUEUnit.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/clique/CLIQUEUnit.java
index 4b6fa9ad..db687567 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) 2011
+ Copyright (C) 2012
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.data.NumberVector;
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.HashSetModifiableDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
/**
@@ -265,7 +266,7 @@ public class CLIQUEUnit<V extends NumberVector<V, ?>> {
resultIntervals.add(this.intervals.last());
resultIntervals.add(other.intervals.last());
- ModifiableDBIDs resultIDs = DBIDUtil.newHashSet(this.ids);
+ HashSetModifiableDBIDs resultIDs = DBIDUtil.newHashSet(this.ids);
resultIDs.retainAll(other.ids);
if(resultIDs.size() / all >= tau) {
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 444cb0e6..7a686190 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) 2011
+Copyright (C) 2012
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 168ceadb..2a1eb930 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) 2011
+Copyright (C) 2012
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 02350db3..43c6a218 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -85,9 +85,7 @@ public class ByLabelClustering extends AbstractAlgorithm<Clustering<Model>> impl
public static final OptionID MULTIPLE_ID = OptionID.getOrCreateOptionID("bylabelclustering.multiple", "Flag to indicate that only subspaces with large coverage " + "(i.e. the fraction of the database that is covered by the dense units) " + "are selected, the rest will be pruned.");
/**
- * Flag to indicate that multiple cluster assignment is possible. If an
- * assignment to multiple clusters is desired, the labels indicating the
- * clusters need to be separated by blanks.
+ * Pattern to recognize noise clusters by.
*/
public static final OptionID NOISE_ID = OptionID.getOrCreateOptionID("bylabelclustering.noise", "Pattern to recognize noise classes by their label.");
@@ -144,7 +142,7 @@ public class ByLabelClustering extends AbstractAlgorithm<Clustering<Model>> impl
ModifiableDBIDs noiseids = DBIDUtil.newArray();
Clustering<Model> result = new Clustering<Model>("By Label Clustering", "bylabel-clustering");
for(Entry<String, ModifiableDBIDs> entry : labelMap.entrySet()) {
- ModifiableDBIDs ids = labelMap.get(entry.getKey());
+ ModifiableDBIDs ids = entry.getValue();
if(ids.size() <= 1) {
noiseids.addDBIDs(ids);
continue;
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 5b8041d7..228cc7e7 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) 2011
+ Copyright (C) 2012
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/ByModelClustering.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/ByModelClustering.java
new file mode 100644
index 00000000..cd45cda2
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/ByModelClustering.java
@@ -0,0 +1,163 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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;
+import java.util.Map.Entry;
+import java.util.regex.Pattern;
+
+import de.lmu.ifi.dbs.elki.algorithm.AbstractAlgorithm;
+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.Model;
+import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.GeneratorInterface;
+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.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.relation.Relation;
+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;
+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;
+
+/**
+ * Pseudo clustering using annotated models.
+ *
+ * This "algorithm" puts elements into the same cluster when they agree in their
+ * model. I.e. it just uses a predefined clustering, and is mostly useful for
+ * testing and evaluation (e.g. comparing the result of a real algorithm to the
+ * reference result / golden standard used by the generator).
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.uses Model
+ */
+@Title("Clustering by model")
+@Description("Cluster points by a (pre-assigned!) model. For comparing results with a reference clustering.")
+public class ByModelClustering extends AbstractAlgorithm<Clustering<Model>> implements ClusteringAlgorithm<Clustering<Model>> {
+ /**
+ * The logger for this class.
+ */
+ private static final Logging logger = Logging.getLogger(ByModelClustering.class);
+
+ /**
+ * Pattern to recognize noise clusters with
+ */
+ public static final OptionID NOISE_ID = OptionID.getOrCreateOptionID("bymodel.noise", "Pattern to recognize noise models by their label.");
+
+ /**
+ * Holds the value of {@link #NOISE_ID}.
+ */
+ private Pattern noisepattern = null;
+
+ /**
+ * Constructor.
+ *
+ * @param noisepattern Noise pattern
+ */
+ public ByModelClustering(Pattern noisepattern) {
+ super();
+ this.noisepattern = noisepattern;
+ }
+
+ /**
+ * Constructor without parameters
+ */
+ public ByModelClustering() {
+ this(null);
+ }
+
+ /**
+ * Run the actual clustering algorithm.
+ *
+ * @param relation The data input we use
+ */
+ public Clustering<Model> run(Relation<Model> relation) {
+ // Build model mapping
+ HashMap<Model, ModifiableDBIDs> modelMap = new HashMap<Model, ModifiableDBIDs>();
+ for(DBID id : relation.iterDBIDs()) {
+ Model model = relation.get(id);
+ ModifiableDBIDs modelids = modelMap.get(model);
+ if(modelids == null) {
+ modelids = DBIDUtil.newHashSet();
+ modelMap.put(model, modelids);
+ }
+ modelids.add(id);
+ }
+
+ Clustering<Model> result = new Clustering<Model>("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);
+ if(noisepattern != null && noisepattern.matcher(name).find()) {
+ c.setNoise(true);
+ }
+ result.addCluster(c);
+ }
+ return result;
+ }
+
+ @Override
+ public TypeInformation[] getInputTypeRestriction() {
+ return TypeUtil.array(TypeUtil.MODEL);
+ }
+
+ @Override
+ protected Logging getLogger() {
+ return logger;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ protected Pattern noisepat;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ PatternParameter noisepatP = new PatternParameter(NOISE_ID, true);
+ if(config.grab(noisepatP)) {
+ noisepat = noisepatP.getValue();
+ }
+ }
+
+ @Override
+ protected ByModelClustering makeInstance() {
+ return new ByModelClustering(noisepat);
+ }
+ }
+} \ No newline at end of file
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 a316ce57..2e7d006d 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) 2011
+ Copyright (C) 2012
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/TrivialAllNoise.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/TrivialAllNoise.java
index b85f5445..c497632c 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) 2011
+ Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/trivial/package-info.java
index 5629855c..5870a736 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) 2011
+Copyright (C) 2012
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 50365996..f0b31d32 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,9 +26,6 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.PriorityQueue;
import de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm;
import de.lmu.ifi.dbs.elki.data.NumberVector;
@@ -38,7 +35,7 @@ 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.WritableDataStore;
+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.DBIDUtil;
@@ -46,6 +43,8 @@ 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.DistanceResultPair;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
+import de.lmu.ifi.dbs.elki.database.query.knn.KNNResult;
+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.DoubleDistance;
@@ -55,10 +54,11 @@ import de.lmu.ifi.dbs.elki.distance.similarityfunction.kernel.PolynomialKernelFu
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
import de.lmu.ifi.dbs.elki.math.MeanVariance;
-import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
+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.documentation.Description;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
@@ -68,7 +68,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterEqualCons
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.FCPair;
+import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleObjPair;
/**
* Angle-Based Outlier Detection
@@ -177,10 +177,10 @@ public class ABOD<V extends NumberVector<V, ?>> extends AbstractDistanceBasedAlg
public OutlierResult getRanking(Relation<V> relation, int k) {
// Fix a static set of IDs
staticids = DBIDUtil.newArray(relation.getDBIDs());
- Collections.sort(staticids);
+ staticids.sort();
KernelMatrix kernelMatrix = new KernelMatrix(primitiveKernelFunction, relation, staticids);
- PriorityQueue<FCPair<Double, DBID>> pq = new PriorityQueue<FCPair<Double, DBID>>(relation.size(), Collections.reverseOrder());
+ Heap<DoubleObjPair<DBID>> pq = new Heap<DoubleObjPair<DBID>>(relation.size(), Collections.reverseOrder());
// preprocess kNN neighborhoods
assert (k == this.k);
@@ -190,7 +190,7 @@ public class ABOD<V extends NumberVector<V, ?>> extends AbstractDistanceBasedAlg
MeanVariance s = new MeanVariance();
// System.out.println("Processing: " +objKey);
- List<DistanceResultPair<DoubleDistance>> neighbors = knnQuery.getKNNForDBID(objKey, k);
+ KNNResult<DoubleDistance> neighbors = knnQuery.getKNNForDBID(objKey, k);
Iterator<DistanceResultPair<DoubleDistance>> iter = neighbors.iterator();
while(iter.hasNext()) {
DBID key1 = iter.next().getDBID();
@@ -214,14 +214,14 @@ public class ABOD<V extends NumberVector<V, ?>> extends AbstractDistanceBasedAlg
}
// Sample variance probably would be correct, however the numerical
// instabilities can actually break ABOD here.
- pq.add(new FCPair<Double, DBID>(s.getNaiveVariance(), objKey));
+ pq.add(new DoubleObjPair<DBID>(s.getNaiveVariance(), objKey));
}
DoubleMinMax minmaxabod = new DoubleMinMax();
- WritableDataStore<Double> abodvalues = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, Double.class);
- for(FCPair<Double, DBID> pair : pq) {
- abodvalues.put(pair.getSecond(), pair.getFirst());
- minmaxabod.put(pair.getFirst());
+ WritableDoubleDataStore abodvalues = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC);
+ for(DoubleObjPair<DBID> pair : pq) {
+ abodvalues.putDouble(pair.getSecond(), pair.first);
+ minmaxabod.put(pair.first);
}
// Build result representation.
Relation<Double> scoreResult = new MaterializedRelation<Double>("Angle-based Outlier Degree", "abod-outlier", TypeUtil.DOUBLE, abodvalues, relation.getDBIDs());
@@ -240,16 +240,16 @@ public class ABOD<V extends NumberVector<V, ?>> extends AbstractDistanceBasedAlg
public OutlierResult getFastRanking(Relation<V> relation, int k, int sampleSize) {
// Fix a static set of IDs
staticids = DBIDUtil.newArray(relation.getDBIDs());
- Collections.sort(staticids);
+ staticids.sort();
KernelMatrix kernelMatrix = new KernelMatrix(primitiveKernelFunction, relation, staticids);
- PriorityQueue<FCPair<Double, DBID>> pq = new PriorityQueue<FCPair<Double, DBID>>(relation.size(), Collections.reverseOrder());
+ Heap<DoubleObjPair<DBID>> pq = new Heap<DoubleObjPair<DBID>>(relation.size(), Collections.reverseOrder());
// get Candidate Ranking
for(DBID aKey : relation.iterDBIDs()) {
HashMap<DBID, Double> dists = new HashMap<DBID, Double>(relation.size());
// determine kNearestNeighbors and pairwise distances
- PriorityQueue<FCPair<Double, DBID>> nn;
+ Heap<DoubleObjPair<DBID>> nn;
if(!useRNDSample) {
nn = calcDistsandNN(relation, kernelMatrix, sampleSize, aKey, dists);
}
@@ -269,15 +269,15 @@ public class ABOD<V extends NumberVector<V, ?>> extends AbstractDistanceBasedAlg
}
// getFilter
double var = getAbofFilter(kernelMatrix, aKey, dists, counter[1], counter[0], neighbors);
- pq.add(new FCPair<Double, DBID>(var, aKey));
+ pq.add(new DoubleObjPair<DBID>(var, aKey));
// System.out.println("prog "+(prog++));
}
// refine Candidates
- PriorityQueue<FCPair<Double, DBID>> resqueue = new PriorityQueue<FCPair<Double, DBID>>(k);
+ Heap<DoubleObjPair<DBID>> resqueue = new Heap<DoubleObjPair<DBID>>(k);
// System.out.println(pq.size() + " objects ordered into candidate list.");
// int v = 0;
while(!pq.isEmpty()) {
- if(resqueue.size() == k && pq.peek().getFirst() > resqueue.peek().getFirst()) {
+ if(resqueue.size() == k && pq.peek().first > resqueue.peek().first) {
break;
}
// double approx = pq.peek().getFirst();
@@ -313,22 +313,22 @@ public class ABOD<V extends NumberVector<V, ?>> extends AbstractDistanceBasedAlg
double var = s.getSampleVariance();
// System.out.println(aKey+ " : " + approx +" " + var);
if(resqueue.size() < k) {
- resqueue.add(new FCPair<Double, DBID>(var, aKey));
+ resqueue.add(new DoubleObjPair<DBID>(var, aKey));
}
else {
- if(resqueue.peek().getFirst() > var) {
+ if(resqueue.peek().first > var) {
resqueue.remove();
- resqueue.add(new FCPair<Double, DBID>(var, aKey));
+ resqueue.add(new DoubleObjPair<DBID>(var, aKey));
}
}
}
// System.out.println(v + " Punkte von " + data.size() + " verfeinert !!");
DoubleMinMax minmaxabod = new DoubleMinMax();
- WritableDataStore<Double> abodvalues = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, Double.class);
- for(FCPair<Double, DBID> pair : pq) {
- abodvalues.put(pair.getSecond(), pair.getFirst());
- minmaxabod.put(pair.getFirst());
+ WritableDoubleDataStore abodvalues = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC);
+ for(DoubleObjPair<DBID> pair : pq) {
+ abodvalues.putDouble(pair.getSecond(), pair.first);
+ minmaxabod.put(pair.first);
}
// Build result representation.
Relation<Double> scoreResult = new MaterializedRelation<Double>("Angle-based Outlier Detection", "abod-outlier", TypeUtil.DOUBLE, abodvalues, relation.getDBIDs());
@@ -336,31 +336,6 @@ public class ABOD<V extends NumberVector<V, ?>> extends AbstractDistanceBasedAlg
return new OutlierResult(scoreMeta, scoreResult);
}
- // TODO: remove?
- @SuppressWarnings("unused")
- private double[] calcNormalization(Integer xKey, HashMap<Integer, Double> dists) {
- double[] result = new double[2];
- for(Integer yKey : dists.keySet()) {
- if(yKey.equals(xKey)) {
- continue;
- }
- for(Integer zKey : dists.keySet()) {
- if(zKey <= yKey) {
- continue;
- }
- if(zKey.equals(xKey)) {
- continue;
- }
- if(dists.get(yKey) != 0 && dists.get(zKey) != 0) {
- double sqr = Math.sqrt(dists.get(yKey) * dists.get(zKey));
- result[0] += 1 / sqr;
- result[1] += 1 / (dists.get(yKey) * dists.get(zKey) * sqr);
- }
- }
- }
- return result;
- }
-
private double[] calcFastNormalization(DBID x, HashMap<DBID, Double> dists) {
double[] result = new double[2];
@@ -439,7 +414,7 @@ public class ABOD<V extends NumberVector<V, ?>> extends AbstractDistanceBasedAlg
private int mapDBID(DBID aKey) {
// TODO: this is not the most efficient...
- int off = Collections.binarySearch(staticids, aKey);
+ int off = staticids.binarySearch(aKey);
if(off < 0) {
throw new AbortException("Did not find id " + aKey.toString() + " in staticids. " + staticids.contains(aKey));
}
@@ -457,33 +432,33 @@ public class ABOD<V extends NumberVector<V, ?>> extends AbstractDistanceBasedAlg
return (kernelMatrix.getDistance(ai, ai) + kernelMatrix.getDistance(bi, ci) - kernelMatrix.getDistance(ai, ci) - kernelMatrix.getDistance(ai, bi));
}
- private PriorityQueue<FCPair<Double, DBID>> calcDistsandNN(Relation<V> data, KernelMatrix kernelMatrix, int sampleSize, DBID aKey, HashMap<DBID, Double> dists) {
- PriorityQueue<FCPair<Double, DBID>> nn = new PriorityQueue<FCPair<Double, DBID>>(sampleSize);
+ private Heap<DoubleObjPair<DBID>> calcDistsandNN(Relation<V> data, KernelMatrix kernelMatrix, int sampleSize, DBID aKey, HashMap<DBID, Double> dists) {
+ Heap<DoubleObjPair<DBID>> nn = new Heap<DoubleObjPair<DBID>>(sampleSize);
for(DBID bKey : data.iterDBIDs()) {
double val = calcCos(kernelMatrix, aKey, bKey);
dists.put(bKey, val);
if(nn.size() < sampleSize) {
- nn.add(new FCPair<Double, DBID>(val, bKey));
+ nn.add(new DoubleObjPair<DBID>(val, bKey));
}
else {
- if(val < nn.peek().getFirst()) {
+ if(val < nn.peek().first) {
nn.remove();
- nn.add(new FCPair<Double, DBID>(val, bKey));
+ nn.add(new DoubleObjPair<DBID>(val, bKey));
}
}
}
return nn;
}
- private PriorityQueue<FCPair<Double, DBID>> calcDistsandRNDSample(Relation<V> data, KernelMatrix kernelMatrix, int sampleSize, DBID aKey, HashMap<DBID, Double> dists) {
- PriorityQueue<FCPair<Double, DBID>> nn = new PriorityQueue<FCPair<Double, DBID>>(sampleSize);
+ private Heap<DoubleObjPair<DBID>> calcDistsandRNDSample(Relation<V> data, KernelMatrix kernelMatrix, int sampleSize, DBID aKey, HashMap<DBID, Double> dists) {
+ Heap<DoubleObjPair<DBID>> nn = new Heap<DoubleObjPair<DBID>>(sampleSize);
int step = (int) ((double) data.size() / (double) sampleSize);
int counter = 0;
for(DBID bKey : data.iterDBIDs()) {
double val = calcCos(kernelMatrix, aKey, bKey);
dists.put(bKey, val);
if(counter % step == 0) {
- nn.add(new FCPair<Double, DBID>(val, bKey));
+ nn.add(new DoubleObjPair<DBID>(val, bKey));
}
counter++;
}
@@ -499,13 +474,13 @@ public class ABOD<V extends NumberVector<V, ?>> extends AbstractDistanceBasedAlg
public void getExplanations(Relation<V> data) {
KernelMatrix kernelMatrix = new KernelMatrix(primitiveKernelFunction, data, staticids);
// PQ for Outlier Ranking
- PriorityQueue<FCPair<Double, DBID>> pq = new PriorityQueue<FCPair<Double, DBID>>(data.size(), Collections.reverseOrder());
- HashMap<DBID, LinkedList<DBID>> explaintab = new HashMap<DBID, LinkedList<DBID>>();
+ Heap<DoubleObjPair<DBID>> pq = new Heap<DoubleObjPair<DBID>>(data.size(), Collections.reverseOrder());
+ HashMap<DBID, DBIDs> explaintab = new HashMap<DBID, DBIDs>();
// test all objects
for(DBID objKey : data.iterDBIDs()) {
MeanVariance s = new MeanVariance();
// Queue for the best explanation
- PriorityQueue<FCPair<Double, DBID>> explain = new PriorityQueue<FCPair<Double, DBID>>();
+ Heap<DoubleObjPair<DBID>> explain = new Heap<DoubleObjPair<DBID>>();
// determine Object
// for each pair of other objects
Iterator<DBID> iter = data.iterDBIDs();
@@ -529,13 +504,13 @@ public class ABOD<V extends NumberVector<V, ?>> extends AbstractDistanceBasedAlg
s2.put(tmp, 1 / sqr);
}
}
- explain.add(new FCPair<Double, DBID>(s2.getSampleVariance(), key1));
+ explain.add(new DoubleObjPair<DBID>(s2.getSampleVariance(), key1));
s.put(s2);
}
// build variance of the observed vectors
- pq.add(new FCPair<Double, DBID>(s.getSampleVariance(), objKey));
+ pq.add(new DoubleObjPair<DBID>(s.getSampleVariance(), objKey));
//
- LinkedList<DBID> expList = new LinkedList<DBID>();
+ ModifiableDBIDs expList = DBIDUtil.newArray();
expList.add(explain.remove().getSecond());
while(!explain.isEmpty()) {
DBID nextKey = explain.remove().getSecond();
@@ -564,26 +539,26 @@ public class ABOD<V extends NumberVector<V, ?>> extends AbstractDistanceBasedAlg
if(count > 10) {
break;
}
- double factor = pq.peek().getFirst();
+ double factor = pq.peek().first;
DBID key = pq.remove().getSecond();
System.out.print(data.get(key) + " ");
System.out.println(count + " Factor=" + factor + " " + key);
- LinkedList<DBID> expList = explaintab.get(key);
+ DBIDs expList = explaintab.get(key);
generateExplanation(data, key, expList);
count++;
}
System.out.println("--------------------------------------------");
}
- private void generateExplanation(Relation<V> data, DBID key, LinkedList<DBID> expList) {
- V vect1 = data.get(key);
+ private void generateExplanation(Relation<V> data, DBID key, DBIDs expList) {
+ Vector vect1 = data.get(key).getColumnVector();
Iterator<DBID> iter = expList.iterator();
while(iter.hasNext()) {
System.out.println("Outlier: " + vect1);
- V exp = data.get(iter.next());
+ Vector exp = data.get(iter.next()).getColumnVector();
System.out.println("Most common neighbor: " + exp);
// determine difference Vector
- V vals = exp.minus(vect1);
+ Vector vals = exp.minus(vect1);
System.out.println(vals);
// System.out.println(new FeatureVector(
// "Diff-"+vect1.getPrimaryKey(),vals ));
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 3be73ca6..994ce8e2 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) 2011
+ Copyright (C) 2012
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.algorithm.AbstractAlgorithm;
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.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.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
@@ -54,8 +54,7 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.IntIntPair;
*
* <p>
* Reference: <br />
- * Outlier detection for high dimensional data Outlier detection for high
- * dimensional data <br />
+ * Outlier detection for high dimensional data<br />
* C.C. Aggarwal, P. S. Yu<br />
* International Conference on Management of Data Proceedings of the 2001 ACM
* SIGMOD international conference on Management of data 2001, Santa Barbara,
@@ -147,7 +146,7 @@ public abstract class AbstractAggarwalYuOutlier<V extends NumberVector<?, ?>> ex
if(r == phi - 1) {
end = size;
}
- ArrayDBIDs currange = DBIDUtil.newArray(phi + 1);
+ ArrayModifiableDBIDs currange = DBIDUtil.newArray(phi + 1);
for(int i = start; i < end; i++) {
currange.add(axis.get(i).second);
}
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 23496389..1d77af3a 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/AbstractDBOutlier.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/AbstractDBOutlier.java
@@ -1,37 +1,37 @@
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) 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/>.
-*/
+
+/*
+ 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.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.DataStore;
-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.distancevalue.Distance;
-import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
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;
@@ -79,10 +79,8 @@ public abstract class AbstractDBOutlier<O, D extends Distance<D>> extends Abstra
*
*/
public OutlierResult run(Database database, Relation<O> relation) throws IllegalStateException {
- DistanceQuery<O, D> distFunc = database.getDistanceQuery(relation, getDistanceFunction());
-
// Run the actual score process
- DataStore<Double> dbodscore = computeOutlierScores(database, distFunc, d);
+ DataStore<Double> 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());
@@ -92,8 +90,13 @@ public abstract class AbstractDBOutlier<O, D extends Distance<D>> extends Abstra
/**
* computes an outlier score for each object of the database.
+ *
+ * @param database Database
+ * @param relation Relation
+ * @param d distance
+ * @return computed scores
*/
- protected abstract DataStore<Double> computeOutlierScores(Database database, DistanceQuery<O, D> distFunc, D d);
+ protected abstract DataStore<Double> computeOutlierScores(Database database, Relation<O> relation, D d);
@Override
public TypeInformation[] getInputTypeRestriction() {
@@ -108,8 +111,11 @@ public abstract class AbstractDBOutlier<O, D extends Distance<D>> extends Abstra
* @apiviz.exclude
*/
public static abstract class Parameterizer<O, D extends Distance<D>> extends AbstractDistanceBasedAlgorithm.Parameterizer<O, D> {
+ /**
+ * Query radius
+ */
protected D d = null;
-
+
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
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 aba5576e..5d357744 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/AggarwalYuEvolutionary.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/AggarwalYuEvolutionary.java
@@ -1,26 +1,27 @@
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) 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/>.
-*/
+
+/*
+ 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.Arrays;
@@ -35,13 +36,13 @@ 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.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+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.database.relation.MaterializedRelation;
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;
@@ -65,8 +66,7 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
* detect outliers for high dimensional data.
* <p>
* Reference: <br />
- * Outlier detection for high dimensional data Outlier detection for high
- * dimensional data <br />
+ * Outlier detection for high dimensional data<br />
* C.C. Aggarwal, P. S. Yu <br />
* Proceedings of the 2001 ACM SIGMOD international conference on Management of
* data 2001, Santa Barbara, California, United States
@@ -147,23 +147,23 @@ public class AggarwalYuEvolutionary<V extends NumberVector<?, ?>> extends Abstra
Collection<Individuum> individuums = (new EvolutionarySearch(relation, ranges, m, seed)).run();
- WritableDataStore<Double> outlierScore = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_STATIC, Double.class);
+ WritableDoubleDataStore outlierScore = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_STATIC);
for(Individuum ind : individuums) {
DBIDs ids = computeSubspaceForGene(ind.getGene(), ranges);
double sparsityC = sparsity(ids.size(), dbsize, k);
for(DBID id : ids) {
- Double prev = outlierScore.get(id);
- if(prev == null || sparsityC < prev) {
- outlierScore.put(id, sparsityC);
+ double prev = outlierScore.doubleValue(id);
+ if(Double.isNaN(prev) || sparsityC < prev) {
+ outlierScore.putDouble(id, sparsityC);
}
}
}
DoubleMinMax minmax = new DoubleMinMax();
for(DBID id : relation.iterDBIDs()) {
- Double val = outlierScore.get(id);
- if(val == null) {
- outlierScore.put(id, 0.0);
+ double val = outlierScore.doubleValue(id);
+ if(Double.isNaN(val)) {
+ outlierScore.putDouble(id, 0.0);
val = 0.0;
}
minmax.put(val);
@@ -224,9 +224,10 @@ public class AggarwalYuEvolutionary<V extends NumberVector<?, ?>> extends Abstra
this.m = m;
this.dbsize = database.size();
this.dim = DatabaseUtil.dimensionality(database);
- if (seed != null) {
+ if(seed != null) {
this.random = new Random(seed);
- } else {
+ }
+ else {
this.random = new Random();
}
}
@@ -274,7 +275,6 @@ public class AggarwalYuEvolutionary<V extends NumberVector<?, ?>> extends Abstra
/**
* check the termination criterion
- *
*/
private boolean checkConvergence(Collection<Individuum> pop) {
if(pop.size() == 0) {
@@ -683,15 +683,15 @@ public class AggarwalYuEvolutionary<V extends NumberVector<?, ?>> extends Abstra
}
/**
- * Parameterization class.
- *
- * @author Erich Schubert
- *
- * @apiviz.exclude
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
*/
public static class Parameterizer<V extends NumberVector<?, ?>> extends AbstractAggarwalYuOutlier.Parameterizer {
protected int m = 0;
-
+
protected Long seed = null;
@Override
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 af80c264..190211c3 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/AggarwalYuNaive.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/AggarwalYuNaive.java
@@ -1,26 +1,27 @@
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) 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/>.
-*/
+
+/*
+ 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.Vector;
@@ -29,13 +30,13 @@ import de.lmu.ifi.dbs.elki.data.NumberVector;
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.WritableDataStore;
+import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+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.database.relation.MaterializedRelation;
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;
@@ -55,8 +56,7 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.IntIntPair;
*
* <p>
* Reference: <br />
- * Outlier detection for high dimensional data Outlier detection for high
- * dimensional data <br />
+ * Outlier detection for high dimensional data<br />
* C.C. Aggarwal, P. S. Yu<br />
* International Conference on Management of Data Proceedings of the 2001 ACM
* SIGMOD international conference on Management of data 2001, Santa Barbara,
@@ -140,7 +140,7 @@ public class AggarwalYuNaive<V extends NumberVector<?, ?>> extends AbstractAggar
}
}
- WritableDataStore<Double> sparsity = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_STATIC, Double.class);
+ WritableDoubleDataStore sparsity = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_STATIC);
// calculate the sparsity coefficient
for(Vector<IntIntPair> sub : Rk) {
DBIDs ids = computeSubspace(sub, ranges);
@@ -148,18 +148,18 @@ public class AggarwalYuNaive<V extends NumberVector<?, ?>> extends AbstractAggar
if(sparsityC < 0) {
for(DBID id : ids) {
- Double prev = sparsity.get(id);
- if(prev == null || sparsityC < prev) {
- sparsity.put(id, sparsityC);
+ double prev = sparsity.doubleValue(id);
+ if(Double.isNaN(prev) || sparsityC < prev) {
+ sparsity.putDouble(id, sparsityC);
}
}
}
}
DoubleMinMax minmax = new DoubleMinMax();
for(DBID id : relation.iterDBIDs()) {
- Double val = sparsity.get(id);
- if(val == null) {
- sparsity.put(id, 0.0);
+ double val = sparsity.doubleValue(id);
+ if(Double.isNaN(val)) {
+ sparsity.putDouble(id, 0.0);
val = 0.0;
}
minmax.put(val);
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 0d5f115b..f4b0ba35 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/DBOutlierDetection.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/DBOutlierDetection.java
@@ -1,40 +1,41 @@
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) 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/>.
-*/
+
+/*
+ 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 java.util.Iterator;
-import java.util.List;
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;
-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.DBID;
import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery;
-import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
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.KNNResult;
+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;
@@ -99,11 +100,14 @@ public class DBOutlierDetection<O, D extends Distance<D>> extends AbstractDBOutl
}
@Override
- protected DataStore<Double> computeOutlierScores(Database database, DistanceQuery<O, D> distFunc, D neighborhoodSize) {
+ protected DataStore<Double> computeOutlierScores(Database database, Relation<O> relation, D neighborhoodSize) {
+ DistanceQuery<O, D> distFunc = database.getDistanceQuery(relation, getDistanceFunction());
+ KNNQuery<O, D> knnQuery = database.getKNNQuery(distFunc, DatabaseQuery.HINT_OPTIMIZED_ONLY);
+
// maximum number of objects in the D-neighborhood of an outlier
int m = (int) ((distFunc.getRelation().size()) * (1 - p));
- WritableDataStore<Double> scores = DataStoreUtil.makeStorage(distFunc.getRelation().getDBIDs(), DataStoreFactory.HINT_STATIC, Double.class);
+ WritableDoubleDataStore scores = DataStoreUtil.makeDoubleStorage(distFunc.getRelation().getDBIDs(), DataStoreFactory.HINT_STATIC);
if(logger.isVerbose()) {
logger.verbose("computing outlier flag");
}
@@ -112,21 +116,20 @@ public class DBOutlierDetection<O, D extends Distance<D>> extends AbstractDBOutl
int counter = 0;
// if index exists, kNN query. if the distance to the mth nearest neighbor
// is more than d -> object is outlier
- KNNQuery<O, D> knnQuery = database.getKNNQuery(distFunc, m, DatabaseQuery.HINT_OPTIMIZED_ONLY);
if(knnQuery != null) {
for(DBID id : distFunc.getRelation().iterDBIDs()) {
counter++;
- final List<DistanceResultPair<D>> knns = knnQuery.getKNNForDBID(id, m);
+ final KNNResult<D> knns = knnQuery.getKNNForDBID(id, m);
if(logger.isDebugging()) {
logger.debugFine("distance to mth nearest neighbour" + knns.toString());
}
if(knns.get(Math.min(m, knns.size()) - 1).getDistance().compareTo(neighborhoodSize) <= 0) {
// flag as outlier
- scores.put(id, 1.0);
+ scores.putDouble(id, 1.0);
}
else {
// flag as no outlier
- scores.put(id, 0.0);
+ scores.putDouble(id, 0.0);
}
}
if(progressOFlags != null) {
@@ -150,11 +153,11 @@ public class DBOutlierDetection<O, D extends Distance<D>> extends AbstractDBOutl
if(count < m) {
// flag as outlier
- scores.put(id, 1.0);
+ scores.putDouble(id, 1.0);
}
else {
// flag as no outlier
- scores.put(id, 0.0);
+ scores.putDouble(id, 0.0);
}
}
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 c72675f8..ec83a2a2 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/DBOutlierScore.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/DBOutlierScore.java
@@ -1,35 +1,37 @@
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) 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/>.
-*/
+
+/*
+ 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.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;
-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.DBID;
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.Distance;
import de.lmu.ifi.dbs.elki.logging.Logging;
@@ -71,17 +73,18 @@ public class DBOutlierScore<O, D extends Distance<D>> extends AbstractDBOutlier<
}
@Override
- protected DataStore<Double> computeOutlierScores(Database database, DistanceQuery<O, D> distFunc, D d) {
- WritableDataStore<Double> scores = DataStoreUtil.makeStorage(distFunc.getRelation().getDBIDs(), DataStoreFactory.HINT_STATIC, Double.class);
+ protected DataStore<Double> computeOutlierScores(Database database, Relation<O> relation, D d) {
+ DistanceQuery<O, D> distFunc = database.getDistanceQuery(relation, getDistanceFunction());
RangeQuery<O, D> rangeQuery = database.getRangeQuery(distFunc);
final double size = distFunc.getRelation().size();
+
+ WritableDoubleDataStore scores = DataStoreUtil.makeDoubleStorage(distFunc.getRelation().getDBIDs(), DataStoreFactory.HINT_STATIC);
// TODO: use bulk when implemented.
for(DBID id : distFunc.getRelation().iterDBIDs()) {
// compute percentage of neighbors in the given neighborhood with size d
double n = (rangeQuery.getRangeForDBID(id, d).size()) / size;
- scores.put(id, 1.0 - n);
+ scores.putDouble(id, 1.0 - n);
}
- scores.toString();
return scores;
}
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 b1464bbb..92d92036 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/EMOutlier.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/EMOutlier.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) 2011
+Copyright (C) 2012
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.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.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
+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.database.relation.MaterializedRelation;
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;
@@ -89,14 +89,14 @@ public class EMOutlier<V extends NumberVector<V, ?>> extends AbstractAlgorithm<O
Clustering<EMModel<V>> emresult = emClustering.run(database, relation);
double globmax = 0.0;
- WritableDataStore<Double> emo_score = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_TEMP | DataStoreFactory.HINT_HOT, Double.class);
+ WritableDoubleDataStore emo_score = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_TEMP | DataStoreFactory.HINT_HOT);
for(DBID id : relation.iterDBIDs()) {
double maxProb = Double.POSITIVE_INFINITY;
double[] probs = emClustering.getProbClusterIGivenX(id);
for(double prob : probs) {
maxProb = Math.min(1 - prob, maxProb);
}
- emo_score.put(id, maxProb);
+ emo_score.putDouble(id, maxProb);
globmax = Math.max(maxProb, globmax);
}
Relation<Double> scoreres = new MaterializedRelation<Double>("EM outlier scores", "em-outlier", TypeUtil.DOUBLE, emo_score, relation.getDBIDs());
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 13f047e7..ae47c100 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) 2011
+Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,8 +28,9 @@ 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.WritableDataStore;
+import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
+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;
@@ -37,7 +38,6 @@ import de.lmu.ifi.dbs.elki.math.MathUtil;
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.database.relation.MaterializedRelation;
import de.lmu.ifi.dbs.elki.result.outlier.BasicOutlierScoreMeta;
import de.lmu.ifi.dbs.elki.result.outlier.InvertedOutlierScoreMeta;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
@@ -95,11 +95,11 @@ public class GaussianModel<V extends NumberVector<V, ?>> extends AbstractAlgorit
public OutlierResult run(Relation<V> relation) throws IllegalStateException {
DoubleMinMax mm = new DoubleMinMax();
// resulting scores
- WritableDataStore<Double> oscores = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_TEMP | DataStoreFactory.HINT_HOT, Double.class);
+ WritableDoubleDataStore oscores = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_TEMP | DataStoreFactory.HINT_HOT);
// Compute mean and covariance Matrix
CovarianceMatrix temp = CovarianceMatrix.make(relation);
- V mean = temp.getMeanVector(relation);
+ Vector mean = temp.getMeanVector(relation).getColumnVector();
// debugFine(mean.toString());
Matrix covarianceMatrix = temp.destroyToNaiveMatrix();
// debugFine(covarianceMatrix.toString());
@@ -110,21 +110,20 @@ public class GaussianModel<V extends NumberVector<V, ?>> extends AbstractAlgorit
// for each object compute Mahalanobis distance
for(DBID id : relation.iterDBIDs()) {
- V x = relation.get(id);
- Vector x_minus_mean = x.minus(mean).getColumnVector();
+ Vector x = relation.get(id).getColumnVector().minusEquals(mean);
// Gaussian PDF
- final double mDist = x_minus_mean.transposeTimes(covarianceTransposed).times(x_minus_mean).get(0, 0);
+ final double mDist = x.transposeTimesTimes(covarianceTransposed, x);
final double prob = fakt * Math.exp(-mDist / 2.0);
mm.put(prob);
- oscores.put(id, prob);
+ oscores.putDouble(id, prob);
}
final OutlierScoreMeta meta;
if(invert) {
double max = mm.getMax() != 0 ? mm.getMax() : 1.;
for(DBID id : relation.iterDBIDs()) {
- oscores.put(id, (max - oscores.get(id)) / max);
+ oscores.putDouble(id, (max - oscores.doubleValue(id)) / max);
}
meta = new BasicOutlierScoreMeta(0.0, 1.0);
}
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 520c3673..aa352582 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) 2011
+Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -30,19 +30,19 @@ 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.WritableDataStore;
+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.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.generic.MaskedDBIDs;
+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.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.database.relation.MaterializedRelation;
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;
@@ -137,7 +137,7 @@ public class GaussianUniformMixture<V extends NumberVector<V, ?>> extends Abstra
// Positive masked collection
DBIDs anomalousObjs = new MaskedDBIDs(objids, bits, false);
// resulting scores
- WritableDataStore<Double> oscores = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_TEMP | DataStoreFactory.HINT_HOT, Double.class);
+ WritableDoubleDataStore oscores = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_TEMP | DataStoreFactory.HINT_HOT);
// compute loglikelihood
double logLike = relation.size() * logml + loglikelihoodNormal(normalObjs, relation);
// logger.debugFine("normalsize " + normalObjs.size() + " anormalsize " +
@@ -159,7 +159,7 @@ public class GaussianUniformMixture<V extends NumberVector<V, ?>> extends Abstra
// if the loglike increases more than a threshold, object stays in
// anomalous set and is flagged as outlier
final double loglikeGain = currentLogLike - logLike;
- oscores.put(curid, loglikeGain);
+ oscores.putDouble(curid, loglikeGain);
minmax.put(loglikeGain);
if(loglikeGain > c) {
@@ -206,7 +206,7 @@ public class GaussianUniformMixture<V extends NumberVector<V, ?>> extends Abstra
return 0;
}
double prob = 0;
- V mean = DatabaseUtil.centroid(database, objids);
+ Vector mean = DatabaseUtil.centroid(database, objids).getColumnVector();
Matrix covarianceMatrix = DatabaseUtil.covarianceMatrix(database, objids);
// test singulaere matrix
@@ -216,10 +216,8 @@ public class GaussianUniformMixture<V extends NumberVector<V, ?>> extends Abstra
double fakt = 1.0 / Math.sqrt(Math.pow(MathUtil.TWOPI, DatabaseUtil.dimensionality(database)) * covarianceDet);
// for each object compute probability and sum
for(DBID id : objids) {
- V x = database.get(id);
-
- Vector x_minus_mean = x.minus(mean).getColumnVector();
- double mDist = x_minus_mean.transposeTimes(covInv).times(x_minus_mean).get(0, 0);
+ Vector x = database.get(id).getColumnVector().minusEquals(mean);
+ double mDist = x.transposeTimesTimes(covInv, x);
prob += Math.log(fakt * Math.exp(-mDist / 2.0));
}
return prob;
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/INFLO.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/INFLO.java
index ee4a77ba..083a72a6 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/INFLO.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/INFLO.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) 2011
+Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -22,8 +22,6 @@ You should 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.data.type.TypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
@@ -31,19 +29,20 @@ 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.datastore.WritableDoubleDataStore;
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.DatabaseQuery;
-import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
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.KNNResult;
+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.logging.Logging;
import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
-import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
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;
@@ -133,9 +132,9 @@ public class INFLO<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBa
// RNNS
WritableDataStore<ModifiableDBIDs> rnns = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_TEMP | DataStoreFactory.HINT_HOT, ModifiableDBIDs.class);
// density
- WritableDataStore<Double> density = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_TEMP | DataStoreFactory.HINT_HOT, Double.class);
+ WritableDoubleDataStore density = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_TEMP | DataStoreFactory.HINT_HOT);
// init knns and rnns
- for(DBID id : distFunc.getRelation().iterDBIDs()) {
+ for(DBID id : relation.iterDBIDs()) {
knns.put(id, DBIDUtil.newArray());
rnns.put(id, DBIDUtil.newArray());
}
@@ -149,13 +148,11 @@ public class INFLO<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBa
ModifiableDBIDs s;
if(!processedIDs.contains(id)) {
// TODO: use exactly k neighbors?
- List<DistanceResultPair<D>> list = knnQuery.getKNNForDBID(id, k);
- for(DistanceResultPair<D> d : list) {
- knns.get(id).add(d.getDBID());
- }
+ KNNResult<D> list = knnQuery.getKNNForDBID(id, k);
+ knns.get(id).addDBIDs(list.asDBIDs());
processedIDs.add(id);
s = knns.get(id);
- density.put(id, 1 / list.get(k - 1).getDistance().doubleValue());
+ density.putDouble(id, 1 / list.get(k - 1).getDistance().doubleValue());
}
else {
@@ -164,11 +161,9 @@ public class INFLO<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBa
for(DBID q : s) {
if(!processedIDs.contains(q)) {
// TODO: use exactly k neighbors?
- List<DistanceResultPair<D>> listQ = knnQuery.getKNNForDBID(q, k);
- for(DistanceResultPair<D> dq : listQ) {
- knns.get(q).add(dq.getDBID());
- }
- density.put(q, 1 / listQ.get(k - 1).getDistance().doubleValue());
+ KNNResult<D> listQ = knnQuery.getKNNForDBID(q, k);
+ knns.get(q).addDBIDs(listQ.asDBIDs());
+ density.putDouble(q, 1 / listQ.getKNNDistance().doubleValue());
processedIDs.add(q);
}
@@ -186,28 +181,28 @@ public class INFLO<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBa
// Calculate INFLO for any Object
// IF Object is pruned INFLO=1.0
DoubleMinMax inflominmax = new DoubleMinMax();
- WritableDataStore<Double> inflos = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, Double.class);
- for(DBID id : distFunc.getRelation().iterDBIDs()) {
+ WritableDoubleDataStore inflos = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC);
+ for(DBID id : relation.iterDBIDs()) {
if(!pruned.contains(id)) {
ModifiableDBIDs knn = knns.get(id);
ModifiableDBIDs rnn = rnns.get(id);
- double denP = density.get(id);
- knn.addAll(rnn);
+ double denP = density.doubleValue(id);
+ knn.addDBIDs(rnn);
double den = 0;
for(DBID q : knn) {
- double denQ = density.get(q);
+ double denQ = density.doubleValue(q);
den = den + denQ;
}
den = den / rnn.size();
den = den / denP;
- inflos.put(id, den);
+ inflos.putDouble(id, den);
// update minimum and maximum
inflominmax.put(den);
}
if(pruned.contains(id)) {
- inflos.put(id, 1.0);
+ inflos.putDouble(id, 1.0);
inflominmax.put(1.0);
}
}
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 fa89f954..ee748f99 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/KNNOutlier.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/KNNOutlier.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) 2011
+Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -22,26 +22,24 @@ You should 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.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.WritableDataStore;
+import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
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.KNNResult;
+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.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.database.relation.MaterializedRelation;
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;
@@ -115,15 +113,13 @@ public class KNNOutlier<O, D extends NumberDistance<D, ?>> extends AbstractDista
FiniteProgress progressKNNDistance = logger.isVerbose() ? new FiniteProgress("kNN distance for objects", relation.size(), logger) : null;
DoubleMinMax minmax = new DoubleMinMax();
- WritableDataStore<Double> knno_score = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, Double.class);
+ WritableDoubleDataStore knno_score = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC);
// compute distance to the k nearest neighbor.
- for(DBID id : distanceQuery.getRelation().iterDBIDs()) {
+ for(DBID id : relation.iterDBIDs()) {
// distance to the kth nearest neighbor
- final List<DistanceResultPair<D>> knns = knnQuery.getKNNForDBID(id, k);
- final int last = Math.min(k - 1, knns.size() - 1);
-
- double dkn = knns.get(last).getDistance().doubleValue();
- knno_score.put(id, dkn);
+ final KNNResult<D> knns = knnQuery.getKNNForDBID(id, k);
+ double dkn = knns.getKNNDistance().doubleValue();
+ knno_score.putDouble(id, dkn);
minmax.put(dkn);
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 02e0789b..e9657e12 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/KNNWeightOutlier.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/KNNWeightOutlier.java
@@ -1,28 +1,27 @@
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) 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 java.util.List;
+
+/*
+ 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.algorithm.AbstractDistanceBasedAlgorithm;
import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
@@ -30,18 +29,19 @@ 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.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
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.KNNResult;
+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.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.database.relation.MaterializedRelation;
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;
@@ -118,20 +118,17 @@ public class KNNWeightOutlier<O, D extends NumberDistance<D, ?>> extends Abstrac
// compute distance to the k nearest neighbor. n objects with the highest
// distance are flagged as outliers
- WritableDataStore<Double> knnw_score = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, Double.class);
- for(DBID id : distanceQuery.getRelation().iterDBIDs()) {
+ WritableDoubleDataStore knnw_score = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC);
+ for(DBID id : relation.iterDBIDs()) {
// compute sum of the distances to the k nearest neighbors
- List<DistanceResultPair<D>> knn = knnQuery.getKNNForDBID(id, k);
- D skn = knn.get(0).getDistance();
- final int last = Math.min(k + 1, knn.size());
- for(int i = 1; i < last; i++) {
- skn = skn.plus(knn.get(i).getDistance());
+ final KNNResult<D> knn = knnQuery.getKNNForDBID(id, k);
+ double skn = 0;
+ for(DistanceResultPair<D> r : knn) {
+ skn += r.getDistance().doubleValue();
}
-
- double doubleSkn = skn.getValue().doubleValue();
- knnw_score.put(id, doubleSkn);
- minmax.put(doubleSkn);
+ knnw_score.putDouble(id, skn);
+ minmax.put(skn);
if(progressKNNWeight != null) {
progressKNNWeight.incrementProcessed(logger);
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/LDOF.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/LDOF.java
index 04ffe8cf..d9256428 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/LDOF.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/LDOF.java
@@ -1,28 +1,27 @@
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) 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 java.util.List;
+
+/*
+ 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.algorithm.AbstractDistanceBasedAlgorithm;
import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
@@ -30,18 +29,19 @@ 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.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
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.KNNResult;
+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.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.database.relation.MaterializedRelation;
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;
@@ -117,7 +117,7 @@ public class LDOF<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBas
// track the maximum value for normalization
DoubleMinMax ldofminmax = new DoubleMinMax();
// compute the ldof values
- WritableDataStore<Double> ldofs = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP, Double.class);
+ WritableDoubleDataStore ldofs = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP);
// compute LOF_SCORE of each db object
if(logger.isVerbose()) {
@@ -125,17 +125,17 @@ public class LDOF<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBas
}
FiniteProgress progressLDOFs = logger.isVerbose() ? new FiniteProgress("LDOF_SCORE for objects", relation.size(), logger) : null;
- for(DBID id : distFunc.getRelation().iterDBIDs()) {
- List<DistanceResultPair<D>> neighbors = knnQuery.getKNNForDBID(id, k);
+ for(DBID id : relation.iterDBIDs()) {
+ KNNResult<D> neighbors = knnQuery.getKNNForDBID(id, k);
int nsize = neighbors.size() - 1;
// skip the point itself
double dxp = 0;
double Dxp = 0;
for(DistanceResultPair<D> neighbor1 : neighbors) {
- if(neighbor1.getDBID() != id) {
+ if(!neighbor1.getDBID().equals(id)) {
dxp += neighbor1.getDistance().doubleValue();
for(DistanceResultPair<D> neighbor2 : neighbors) {
- if(neighbor1.getDBID() != neighbor2.getDBID() && neighbor2.getDBID() != id) {
+ if(!neighbor1.getDBID().equals(neighbor2.getDBID()) && !neighbor2.getDBID().equals(id)) {
Dxp += distFunc.distance(neighbor1.getDBID(), neighbor2.getDBID()).doubleValue();
}
}
@@ -147,7 +147,7 @@ public class LDOF<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBas
if(ldof.isNaN() || ldof.isInfinite()) {
ldof = 1.0;
}
- ldofs.put(id, ldof);
+ ldofs.putDouble(id, ldof);
// update maximum
ldofminmax.put(ldof);
@@ -176,11 +176,11 @@ public class LDOF<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBas
}
/**
- * 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> {
protected int k = 0;
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/LOCI.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/LOCI.java
index 57c04be3..cfd8623c 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/LOCI.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/LOCI.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) 2011
+ Copyright (C) 2012
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.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.datastore.WritableRecordStore;
+import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
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.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.database.relation.MaterializedRelation;
+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.result.outlier.OutlierScoreMeta;
import de.lmu.ifi.dbs.elki.result.outlier.QuotientOutlierScoreMeta;
@@ -185,80 +187,66 @@ public class LOCI<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBas
}
// LOCI main step
FiniteProgress progressLOCI = logger.isVerbose() ? new FiniteProgress("LOCI scores", relation.size(), logger) : null;
- WritableRecordStore store = DataStoreUtil.makeRecordStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, Double.class, Double.class);
- WritableDataStore<Double> mdef_norm = store.getStorage(0, Double.class);
- WritableDataStore<Double> mdef_radius = store.getStorage(1, Double.class);
+ WritableDoubleDataStore mdef_norm = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC);
+ WritableDoubleDataStore mdef_radius = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC);
+ DoubleMinMax minmax = new DoubleMinMax();
+
for(DBID id : relation.iterDBIDs()) {
+ final List<DoubleIntPair> cdist = interestingDistances.get(id);
+ final double maxdist = cdist.get(cdist.size() - 1).first;
+ final int maxneig = cdist.get(cdist.size() - 1).second;
+
double maxmdefnorm = 0.0;
double maxnormr = 0;
- List<DoubleIntPair> cdist = interestingDistances.get(id);
- double maxdist = cdist.get(cdist.size() - 1).first;
- int maxneig = cdist.get(cdist.size() - 1).second;
if(maxneig >= nmin) {
D range = distFunc.getDistanceFactory().fromDouble(maxdist);
// Compute the largest neighborhood we will need.
List<DistanceResultPair<D>> maxneighbors = rangeQuery.getRangeForDBID(id, range);
+ // Ensure the set is sorted. Should be a no-op with most indexes.
+ Collections.sort(maxneighbors);
+ // For any critical distance, compute the normalized MDEF score.
for(DoubleIntPair c : cdist) {
- double alpha_r = alpha * c.first;
- // compute n(p_i, \alpha * r) from list
- int n_alphar = 0;
- for(DoubleIntPair c2 : cdist) {
- if(c2.first <= alpha_r) {
- n_alphar = c2.second;
- }
- else {
- break;
- }
- }
- // compute \hat{n}(p_i, r, \alpha)
- double nhat_r_alpha = 0.0;
- double sigma_nhat_r_alpha = 0.0;
- // Build the sublist from maxneighbors to match the radius c.first
- List<DistanceResultPair<D>> rneighbors = null;
- for(int i = nmin; i < maxneighbors.size(); i++) {
- DistanceResultPair<D> ne = maxneighbors.get(i);
- if(ne.getDistance().doubleValue() > c.first) {
- rneighbors = maxneighbors.subList(1, i);
- break;
- }
- }
- if(rneighbors == null) {
+ // Only start when minimum size is fulfilled
+ if (c.second < nmin) {
continue;
}
- for(DistanceResultPair<D> rn : rneighbors) {
- List<DoubleIntPair> rncdist = interestingDistances.get(rn.getDBID());
- int rn_alphar = 0;
- for(DoubleIntPair c2 : rncdist) {
- if(c2.first <= alpha_r) {
- rn_alphar = c2.second;
- }
- else {
- break;
- }
+ final double r = c.first;
+ final double alpha_r = alpha * r;
+ // compute n(p_i, \alpha * r) from list (note: alpha_r is different from c!)
+ final int n_alphar = elementsAtRadius(cdist, alpha_r);
+ // compute \hat{n}(p_i, r, \alpha) and the corresponding \simga_{MDEF}
+ MeanVariance mv_n_r_alpha = new MeanVariance();
+ for(DistanceResultPair<D> ne : maxneighbors) {
+ // Stop at radius r
+ if(ne.getDistance().doubleValue() > r) {
+ break;
}
- nhat_r_alpha = nhat_r_alpha + rn_alphar;
- sigma_nhat_r_alpha = sigma_nhat_r_alpha + (rn_alphar * rn_alphar);
+ int rn_alphar = elementsAtRadius(interestingDistances.get(ne.getDBID()), alpha_r);
+ mv_n_r_alpha.put(rn_alphar);
}
- // finalize average and deviation
- nhat_r_alpha = nhat_r_alpha / rneighbors.size();
- sigma_nhat_r_alpha = Math.sqrt(sigma_nhat_r_alpha / rneighbors.size() - nhat_r_alpha * nhat_r_alpha);
- double mdef = 1.0 - (n_alphar / nhat_r_alpha);
- double sigmamdef = sigma_nhat_r_alpha / nhat_r_alpha;
- double mdefnorm = mdef / sigmamdef;
+ // We only use the average and standard deviation
+ final double nhat_r_alpha = mv_n_r_alpha.getMean();
+ final double sigma_nhat_r_alpha = mv_n_r_alpha.getNaiveStddev();
+
+ // Redundant divisions removed.
+ final double mdef = (nhat_r_alpha - n_alphar); // / nhat_r_alpha;
+ final double sigmamdef = sigma_nhat_r_alpha; // / nhat_r_alpha;
+ final double mdefnorm = mdef / sigmamdef;
if(mdefnorm > maxmdefnorm) {
maxmdefnorm = mdefnorm;
- maxnormr = c.first;
+ maxnormr = r;
}
}
}
else {
- // FIXME: when nmin was never fulfilled - what is the proper value then?
+ // FIXME: when nmin was not fulfilled - what is the proper value then?
maxmdefnorm = 1.0;
maxnormr = maxdist;
}
- mdef_norm.put(id, maxmdefnorm);
- mdef_radius.put(id, maxnormr);
+ mdef_norm.putDouble(id, maxmdefnorm);
+ mdef_radius.putDouble(id, maxnormr);
+ minmax.put(maxmdefnorm);
if(progressLOCI != null) {
progressLOCI.incrementProcessed(logger);
}
@@ -267,13 +255,34 @@ public class LOCI<O, D extends NumberDistance<D, ?>> extends AbstractDistanceBas
progressLOCI.ensureCompleted(logger);
}
Relation<Double> scoreResult = new MaterializedRelation<Double>("LOCI normalized MDEF", "loci-mdef-outlier", TypeUtil.DOUBLE, mdef_norm, relation.getDBIDs());
- // TODO: actually provide min and max?
- OutlierScoreMeta scoreMeta = new QuotientOutlierScoreMeta(Double.NaN, Double.NaN, 0.0, Double.POSITIVE_INFINITY, 0.0);
+ OutlierScoreMeta scoreMeta = new QuotientOutlierScoreMeta(minmax.getMin(), minmax.getMax(), 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()));
return result;
}
+ /**
+ * Get the number of objects for a given radius, from the list of critical
+ * distances, storing (radius, count) pairs.
+ *
+ * @param criticalDistances
+ * @param radius
+ * @return Number of elements at the given radius
+ */
+ protected int elementsAtRadius(List<DoubleIntPair> criticalDistances, final double radius) {
+ int n_r = 0;
+ for(DoubleIntPair c2 : criticalDistances) {
+ if(c2.first > radius) {
+ break;
+ }
+ if(c2.second != Integer.MIN_VALUE) {
+ // Update
+ n_r = c2.second;
+ }
+ }
+ return n_r;
+ }
+
@Override
public TypeInformation[] getInputTypeRestriction() {
return TypeUtil.array(getDistanceFunction().getInputTypeRestriction());
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/LOF.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/LOF.java
index 5f5f3568..85e1aef2 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/LOF.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/LOF.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) 2011
+ Copyright (C) 2012
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.algorithm.outlier;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.List;
-
import de.lmu.ifi.dbs.elki.algorithm.AbstractAlgorithm;
import de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm;
import de.lmu.ifi.dbs.elki.data.type.CombinedTypeInformation;
@@ -34,13 +32,14 @@ import de.lmu.ifi.dbs.elki.database.QueryUtil;
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.WritableDataStore;
+import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
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.DistanceResultPair;
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.KNNResult;
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.MaterializedRelation;
@@ -170,8 +169,21 @@ public class LOF<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<Ou
}
/**
+ * 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 {@code #doRunInTime(Database)}.
+ * calling {@link #doRunInTime}.
*
* @param relation Data to process
*/
@@ -180,7 +192,7 @@ public class LOF<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<Ou
Pair<KNNQuery<O, D>, KNNQuery<O, D>> pair = getKNNQueries(relation, stepprog);
KNNQuery<O, D> kNNRefer = pair.getFirst();
KNNQuery<O, D> kNNReach = pair.getSecond();
- return doRunInTime(kNNRefer, kNNReach, stepprog).getResult();
+ return doRunInTime(relation.getDBIDs(), kNNRefer, kNNReach, stepprog).getResult();
}
/**
@@ -231,7 +243,7 @@ public class LOF<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<Ou
* function
* @param kNNReach the kNN query w.r.t. reachability distance function
*/
- protected LOFResult<O, D> doRunInTime(KNNQuery<O, D> kNNRefer, KNNQuery<O, D> kNNReach, StepProgress stepprog) throws IllegalStateException {
+ protected LOFResult<O, D> doRunInTime(DBIDs ids, KNNQuery<O, D> kNNRefer, KNNQuery<O, D> kNNReach, StepProgress stepprog) throws IllegalStateException {
// Assert we got something
if(kNNRefer == null) {
throw new AbortException("No kNN queries supported by database for reference neighborhood distance function.");
@@ -244,14 +256,14 @@ public class LOF<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<Ou
if(stepprog != null) {
stepprog.beginStep(2, "Computing LRDs.", logger);
}
- WritableDataStore<Double> lrds = computeLRDs(kNNReach.getRelation().getDBIDs(), kNNReach);
+ WritableDoubleDataStore lrds = computeLRDs(ids, kNNReach);
// compute LOF_SCORE of each db object
if(stepprog != null) {
stepprog.beginStep(3, "Computing LOFs.", logger);
}
- Pair<WritableDataStore<Double>, DoubleMinMax> lofsAndMax = computeLOFs(kNNRefer.getRelation().getDBIDs(), lrds, kNNRefer);
- WritableDataStore<Double> lofs = lofsAndMax.getFirst();
+ Pair<WritableDoubleDataStore, DoubleMinMax> lofsAndMax = computeLOFs(ids, lrds, kNNRefer);
+ WritableDoubleDataStore lofs = lofsAndMax.getFirst();
// track the maximum value for normalization.
DoubleMinMax lofminmax = lofsAndMax.getSecond();
@@ -260,7 +272,7 @@ 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, kNNRefer.getRelation().getDBIDs());
+ Relation<Double> scoreResult = new MaterializedRelation<Double>("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);
@@ -275,22 +287,22 @@ public class LOF<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<Ou
* reachability distance
* @return the LRDs of the objects
*/
- protected WritableDataStore<Double> computeLRDs(DBIDs ids, KNNQuery<O, D> knnReach) {
- WritableDataStore<Double> lrds = DataStoreUtil.makeStorage(ids, DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP, Double.class);
+ protected WritableDoubleDataStore computeLRDs(DBIDs ids, KNNQuery<O, D> knnReach) {
+ WritableDoubleDataStore lrds = DataStoreUtil.makeDoubleStorage(ids, DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP);
FiniteProgress lrdsProgress = logger.isVerbose() ? new FiniteProgress("LRD", ids.size(), logger) : null;
for(DBID id : ids) {
double sum = 0;
- List<DistanceResultPair<D>> neighbors = knnReach.getKNNForDBID(id, k);
+ KNNResult<D> neighbors = knnReach.getKNNForDBID(id, k);
int nsize = neighbors.size() - (objectIsInKNN ? 0 : 1);
for(DistanceResultPair<D> neighbor : neighbors) {
if(objectIsInKNN || !neighbor.getDBID().equals(id)) {
- List<DistanceResultPair<D>> neighborsNeighbors = knnReach.getKNNForDBID(neighbor.getDBID(), k);
- sum += Math.max(neighbor.getDistance().doubleValue(), neighborsNeighbors.get(neighborsNeighbors.size() - 1).getDistance().doubleValue());
+ KNNResult<D> neighborsNeighbors = knnReach.getKNNForDBID(neighbor.getDBID(), k);
+ sum += Math.max(neighbor.getDistance().doubleValue(), neighborsNeighbors.getKNNDistance().doubleValue());
}
}
// Avoid division by 0
- Double lrd = (sum > 0) ? nsize / sum : 0.0;
- lrds.put(id, lrd);
+ double lrd = (sum > 0) ? nsize / sum : 0.0;
+ lrds.putDouble(id, lrd);
if(lrdsProgress != null) {
lrdsProgress.incrementProcessed(logger);
}
@@ -310,17 +322,17 @@ public class LOF<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<Ou
* reference distance
* @return the LOFs of the objects and the maximum LOF
*/
- protected Pair<WritableDataStore<Double>, DoubleMinMax> computeLOFs(DBIDs ids, DataStore<Double> lrds, KNNQuery<O, D> knnRefer) {
- WritableDataStore<Double> lofs = DataStoreUtil.makeStorage(ids, DataStoreFactory.HINT_STATIC, Double.class);
+ protected Pair<WritableDoubleDataStore, DoubleMinMax> computeLOFs(DBIDs ids, DataStore<Double> lrds, KNNQuery<O, D> knnRefer) {
+ WritableDoubleDataStore lofs = DataStoreUtil.makeDoubleStorage(ids, DataStoreFactory.HINT_STATIC);
// track the maximum value for normalization.
DoubleMinMax lofminmax = new DoubleMinMax();
FiniteProgress progressLOFs = logger.isVerbose() ? new FiniteProgress("LOF_SCORE for objects", ids.size(), logger) : null;
for(DBID id : ids) {
double lrdp = lrds.get(id);
- final Double lof;
+ final double lof;
if(lrdp > 0) {
- List<DistanceResultPair<D>> neighbors = knnRefer.getKNNForDBID(id, k);
+ final KNNResult<D> neighbors = knnRefer.getKNNForDBID(id, k);
int nsize = neighbors.size() - (objectIsInKNN ? 0 : 1);
// skip the point itself
// neighbors.remove(0);
@@ -335,7 +347,7 @@ public class LOF<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<Ou
else {
lof = 1.0;
}
- lofs.put(id, lof);
+ lofs.putDouble(id, lof);
// update minimum and maximum
lofminmax.put(lof);
@@ -346,7 +358,7 @@ public class LOF<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<Ou
if(progressLOFs != null) {
progressLOFs.ensureCompleted(logger);
}
- return new Pair<WritableDataStore<Double>, DoubleMinMax>(lofs, lofminmax);
+ return new Pair<WritableDoubleDataStore, DoubleMinMax>(lofs, lofminmax);
}
@Override
@@ -399,12 +411,12 @@ public class LOF<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<Ou
/**
* The LRD values of the objects.
*/
- private final WritableDataStore<Double> lrds;
+ private final WritableDoubleDataStore lrds;
/**
* The LOF values of the objects.
*/
- private final WritableDataStore<Double> lofs;
+ private final WritableDoubleDataStore lofs;
/**
* Encapsulates information generated during a run of the {@link LOF}
@@ -416,7 +428,7 @@ public class LOF<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<Ou
* @param lrds the LRD values of the objects
* @param lofs the LOF values of the objects
*/
- public LOFResult(OutlierResult result, KNNQuery<O, D> kNNRefer, KNNQuery<O, D> kNNReach, WritableDataStore<Double> lrds, WritableDataStore<Double> lofs) {
+ public LOFResult(OutlierResult result, KNNQuery<O, D> kNNRefer, KNNQuery<O, D> kNNReach, WritableDoubleDataStore lrds, WritableDoubleDataStore lofs) {
this.result = result;
this.kNNRefer = kNNRefer;
this.kNNReach = kNNReach;
@@ -441,14 +453,14 @@ public class LOF<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<Ou
/**
* @return the LRD values of the objects
*/
- public WritableDataStore<Double> getLrds() {
+ public WritableDoubleDataStore getLrds() {
return lrds;
}
/**
* @return the LOF values of the objects
*/
- public WritableDataStore<Double> getLofs() {
+ public WritableDoubleDataStore getLofs() {
return lofs;
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/LoOP.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/LoOP.java
index dfb32bb9..f1c273f6 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/LoOP.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/LoOP.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) 2011
+ Copyright (C) 2012
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.algorithm.outlier;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.List;
-
import de.lmu.ifi.dbs.elki.algorithm.AbstractAlgorithm;
import de.lmu.ifi.dbs.elki.data.type.CombinedTypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
@@ -33,12 +31,13 @@ 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.WritableDataStore;
+import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery;
import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
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.KNNResult;
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;
@@ -48,8 +47,8 @@ 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.MathUtil;
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.result.outlier.OutlierScoreMeta;
import de.lmu.ifi.dbs.elki.result.outlier.ProbabilisticOutlierScore;
@@ -226,19 +225,19 @@ public class LoOP<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<O
}
// Probabilistic distances
- WritableDataStore<Double> pdists = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP, Double.class);
+ WritableDoubleDataStore pdists = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP);
{// computing PRDs
if(stepprog != null) {
stepprog.beginStep(3, "Computing pdists", logger);
}
FiniteProgress prdsProgress = logger.isVerbose() ? new FiniteProgress("pdists", relation.size(), logger) : null;
for(DBID id : relation.iterDBIDs()) {
- List<DistanceResultPair<D>> neighbors = knnReach.getKNNForDBID(id, kreach);
+ final KNNResult<D> neighbors = knnReach.getKNNForDBID(id, kreach);
double sqsum = 0.0;
// use first kref neighbors as reference set
int ks = 0;
for(DistanceResultPair<D> neighbor : neighbors) {
- if(objectIsInKNN || neighbor.getDBID() != id) {
+ if(objectIsInKNN || !neighbor.getDBID().equals(id)) {
double d = neighbor.getDistance().doubleValue();
sqsum += d * d;
ks++;
@@ -247,15 +246,15 @@ public class LoOP<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<O
}
}
}
- Double pdist = lambda * Math.sqrt(sqsum / ks);
- pdists.put(id, pdist);
+ double pdist = lambda * Math.sqrt(sqsum / ks);
+ pdists.putDouble(id, pdist);
if(prdsProgress != null) {
prdsProgress.incrementProcessed(logger);
}
}
}
// Compute PLOF values.
- WritableDataStore<Double> plofs = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP, Double.class);
+ WritableDoubleDataStore plofs = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP);
MeanVariance mvplof = new MeanVariance();
{// compute LOOP_SCORE of each db object
if(stepprog != null) {
@@ -264,24 +263,24 @@ public class LoOP<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<O
FiniteProgress progressPLOFs = logger.isVerbose() ? new FiniteProgress("PLOFs for objects", relation.size(), logger) : null;
for(DBID id : relation.iterDBIDs()) {
- List<DistanceResultPair<D>> neighbors = knnComp.getKNNForDBID(id, kcomp);
+ final KNNResult<D> neighbors = knnComp.getKNNForDBID(id, kcomp);
MeanVariance mv = new MeanVariance();
// use first kref neighbors as comparison set.
int ks = 0;
for(DistanceResultPair<D> neighbor1 : neighbors) {
- if(objectIsInKNN || neighbor1.getDBID() != id) {
- mv.put(pdists.get(neighbor1.getDBID()));
+ if(objectIsInKNN || !neighbor1.getDBID().equals(id)) {
+ mv.put(pdists.doubleValue(neighbor1.getDBID()));
ks++;
if(ks >= kcomp) {
break;
}
}
}
- double plof = Math.max(pdists.get(id) / mv.getMean(), 1.0);
+ double plof = Math.max(pdists.doubleValue(id) / mv.getMean(), 1.0);
if(Double.isNaN(plof) || Double.isInfinite(plof)) {
plof = 1.0;
}
- plofs.put(id, plof);
+ plofs.putDouble(id, plof);
mvplof.put((plof - 1.0) * (plof - 1.0));
if(progressPLOFs != null) {
@@ -296,7 +295,7 @@ public class LoOP<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<O
}
// Compute final LoOP values.
- WritableDataStore<Double> loops = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, Double.class);
+ WritableDoubleDataStore loops = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC);
{// compute LOOP_SCORE of each db object
if(stepprog != null) {
stepprog.beginStep(5, "Computing LoOP scores", logger);
@@ -304,7 +303,7 @@ public class LoOP<O, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<O
FiniteProgress progressLOOPs = logger.isVerbose() ? new FiniteProgress("LoOP for objects", relation.size(), logger) : null;
for(DBID id : relation.iterDBIDs()) {
- loops.put(id, MathUtil.erf((plofs.get(id) - 1) / (nplof * sqrt2)));
+ loops.putDouble(id, NormalDistribution.erf((plofs.doubleValue(id) - 1) / (nplof * sqrt2)));
if(progressLOOPs != null) {
progressLOOPs.incrementProcessed(logger);
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 369db4d3..2f120c44 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) 2011
+Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -33,11 +33,13 @@ 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.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
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.KNNResult;
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;
@@ -111,30 +113,31 @@ public class OPTICSOF<O, D extends NumberDistance<D, ?>> extends AbstractDistanc
RangeQuery<O, D> rangeQuery = database.getRangeQuery(distQuery);
DBIDs ids = relation.getDBIDs();
- WritableDataStore<List<DistanceResultPair<D>>> nMinPts = DataStoreUtil.makeStorage(ids, DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP, List.class);
- WritableDataStore<Double> coreDistance = DataStoreUtil.makeStorage(ids, DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP, Double.class);
+ // FIXME: implicit preprocessor.
+ WritableDataStore<KNNResult<D>> nMinPts = DataStoreUtil.makeStorage(ids, DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP, KNNResult.class);
+ WritableDoubleDataStore coreDistance = DataStoreUtil.makeDoubleStorage(ids, DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP);
WritableDataStore<Integer> minPtsNeighborhoodSize = DataStoreUtil.makeStorage(ids, DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP, Integer.class);
// Pass 1
// N_minpts(id) and core-distance(id)
for(DBID id : relation.iterDBIDs()) {
- List<DistanceResultPair<D>> minptsNeighbours = knnQuery.getKNNForDBID(id, minpts);
- D d = minptsNeighbours.get(minptsNeighbours.size() - 1).getDistance();
+ KNNResult<D> minptsNeighbours = knnQuery.getKNNForDBID(id, minpts);
+ D d = minptsNeighbours.getKNNDistance();
nMinPts.put(id, minptsNeighbours);
- coreDistance.put(id, d.doubleValue());
+ coreDistance.putDouble(id, d.doubleValue());
minPtsNeighborhoodSize.put(id, rangeQuery.getRangeForDBID(id, d).size());
}
// Pass 2
WritableDataStore<List<Double>> reachDistance = DataStoreUtil.makeStorage(ids, DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP, List.class);
- WritableDataStore<Double> lrds = DataStoreUtil.makeStorage(ids, DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP, Double.class);
+ WritableDoubleDataStore lrds = DataStoreUtil.makeDoubleStorage(ids, DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP);
for(DBID id : relation.iterDBIDs()) {
List<Double> core = new ArrayList<Double>();
double lrd = 0;
for(DistanceResultPair<D> neighPair : nMinPts.get(id)) {
DBID idN = neighPair.getDBID();
- double coreDist = coreDistance.get(idN);
+ double coreDist = coreDistance.doubleValue(idN);
double dist = distQuery.distance(id, idN).doubleValue();
Double rd = Math.max(coreDist, dist);
lrd = rd + lrd;
@@ -142,22 +145,22 @@ public class OPTICSOF<O, D extends NumberDistance<D, ?>> extends AbstractDistanc
}
lrd = (minPtsNeighborhoodSize.get(id) / lrd);
reachDistance.put(id, core);
- lrds.put(id, lrd);
+ lrds.putDouble(id, lrd);
}
// Pass 3
DoubleMinMax ofminmax = new DoubleMinMax();
- WritableDataStore<Double> ofs = DataStoreUtil.makeStorage(ids, DataStoreFactory.HINT_STATIC, Double.class);
+ WritableDoubleDataStore ofs = DataStoreUtil.makeDoubleStorage(ids, DataStoreFactory.HINT_STATIC);
for(DBID id : relation.iterDBIDs()) {
double of = 0;
for(DistanceResultPair<D> pair : nMinPts.get(id)) {
DBID idN = pair.getDBID();
- double lrd = lrds.get(id);
- double lrdN = lrds.get(idN);
+ double lrd = lrds.doubleValue(id);
+ double lrdN = lrds.doubleValue(idN);
of = of + lrdN / lrd;
}
of = of / minPtsNeighborhoodSize.get(id);
- ofs.put(id, of);
+ ofs.putDouble(id, of);
// update minimum and maximum
ofminmax.put(of);
}
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/OUTRES.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/OUTRES.java
new file mode 100644
index 00000000..912f878a
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/OUTRES.java
@@ -0,0 +1,368 @@
+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/>.
+ */
+
+import java.util.Arrays;
+import java.util.BitSet;
+import java.util.List;
+
+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.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.DBID;
+import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
+import de.lmu.ifi.dbs.elki.database.query.DoubleDistanceResultPair;
+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.subspace.SubspaceEuclideanDistanceFunction;
+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.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.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.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleParameter;
+
+/**
+ * Adaptive outlierness for subspace outlier ranking (OUTRES).
+ *
+ * Note: this algorithm seems to have a O(n^3) complexity without appropriate
+ * index structures to accelerate range queries: each object in each tested
+ * subspace will need to know the mean and standard deviation of the density of
+ * the neighbors, which in turn needs another range query.
+ *
+ * Reference:
+ * <p>
+ * E. Müller, M. Schiffer, T. Seidl<br />
+ * Adaptive outlierness for subspace outlier ranking<br />
+ * in: Proc. 19th ACM International Conference on Information and knowledge
+ * management
+ * </p>
+ *
+ * @author Pleintinger Viktoria
+ * @author Erich Schubert
+ */
+@Reference(authors = "E. Müller, M. Schiffer, T. Seidl", title = "Adaptive outlierness for subspace outlier ranking", booktitle = "Proc. 19th ACM International Conference on Information and knowledge management")
+public class OUTRES<V extends NumberVector<V, ?>> extends AbstractAlgorithm<OutlierResult> implements OutlierAlgorithm {
+ /**
+ * The logger for this class.
+ */
+ private static final Logging logger = Logging.getLogger(OUTRES.class);
+
+ /**
+ * The epsilon (in 2d) parameter
+ */
+ private final double eps;
+
+ /**
+ * Constant for Kolmogorov-Smirnov at alpha=0.01 (table value)
+ */
+ private static final double K_S_CRITICAL001 = 1.63;
+
+ /**
+ * Constructor.
+ *
+ * @param eps Epsilon
+ */
+ public OUTRES(double eps) {
+ super();
+ this.eps = eps;
+ }
+
+ /**
+ * Main loop for OUTRES
+ *
+ * @param relation Relation to process
+ * @return Outlier detection result
+ */
+ public OutlierResult run(Relation<V> relation) {
+ WritableDoubleDataStore ranks = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC);
+ DoubleMinMax minmax = new DoubleMinMax();
+
+ KernelDensityEstimator kernel = new KernelDensityEstimator(relation);
+ BitSet subspace = new BitSet(kernel.dim);
+
+ FiniteProgress progress = logger.isVerbose() ? new FiniteProgress("OutRank scores", relation.size(), logger) : null;
+
+ for(DBID object : relation.iterDBIDs()) {
+ subspace.clear();
+ double score = outresScore(0, subspace, object, kernel);
+ ranks.putDouble(object, score);
+ minmax.put(score);
+ if(progress != null) {
+ progress.incrementProcessed(logger);
+ }
+ }
+ if(progress != null) {
+ progress.ensureCompleted(logger);
+ }
+
+ 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()));
+ return outresResult;
+ }
+
+ /**
+ * Main loop of OUTRES. Run for each object
+ *
+ * @param s start dimension
+ * @param subspace Current subspace
+ * @param id Current object ID
+ * @param kernel Kernel
+ * @return Score
+ */
+ public double outresScore(final int s, BitSet subspace, DBID id, KernelDensityEstimator kernel) {
+ double score = 1.0; // Initial score is 1.0
+
+ for(int i = s; i < kernel.dim; i++) {
+ if(subspace.get(i)) { // TODO: needed? Or should we always start with i=0?
+ continue;
+ }
+ subspace.set(i);
+ final SubspaceEuclideanDistanceFunction df = new SubspaceEuclideanDistanceFunction(subspace);
+ final DoubleDistance range = new DoubleDistance(kernel.adjustedEps(kernel.dim));
+ RangeQuery<V, DoubleDistance> rq = QueryUtil.getRangeQuery(kernel.relation, df, range);
+
+ List<DistanceResultPair<DoubleDistance>> neigh = rq.getRangeForDBID(id, range);
+ if(neigh.size() > 2) {
+ // Relevance test
+ if(relevantSubspace(subspace, neigh, kernel)) {
+ final double density = kernel.subspaceDensity(subspace, neigh);
+ final double deviation;
+ // Compute mean and standard deviation for densities of neighbors.
+ MeanVariance meanv = new MeanVariance();
+ for(DistanceResultPair<DoubleDistance> pair : neigh) {
+ List<DistanceResultPair<DoubleDistance>> n2 = rq.getRangeForDBID(pair.getDBID(), range);
+ meanv.put(kernel.subspaceDensity(subspace, n2));
+ }
+ deviation = (meanv.getMean() - density) / (2. * meanv.getSampleStddev());
+ // High deviation:
+ if(deviation >= 1) {
+ score *= (density / deviation);
+ }
+ // Recursion
+ score *= outresScore(i + 1, subspace, id, kernel);
+ }
+ }
+ subspace.clear(i);
+ }
+ return score;
+ }
+
+ /**
+ *
+ * @param test: subspace that will be tested about scattering
+ * @return if the subspace is scattered return will be 0, else 1
+ */
+ protected boolean relevantSubspace(BitSet subspace, List<DistanceResultPair<DoubleDistance>> neigh, KernelDensityEstimator kernel) {
+ Relation<V> relation = kernel.relation;
+ final double crit = K_S_CRITICAL001 / Math.sqrt(neigh.size());
+
+ for(int dim = subspace.nextSetBit(0); dim > 0; dim = subspace.nextSetBit(dim + 1)) {
+ // TODO: can we save this copy somehow?
+ double[] data = new double[neigh.size()];
+ {
+ int count = 0;
+ for(DistanceResultPair<DoubleDistance> object : neigh) {
+ V vector = relation.get(object.getDBID());
+ data[count] = vector.doubleValue(dim + 1);
+ count++;
+ }
+ assert (count == neigh.size());
+ }
+ Arrays.sort(data);
+
+ final double norm = data[data.length - 1] - data[0];
+ final double min = data[0];
+
+ // Kolmogorow-Smirnow-Test against uniform distribution:
+ for(int j = 1; j < data.length - 2; j++) {
+ double delta = (j / (data.length - 1)) - ((data[j] - min) / norm);
+ if(Math.abs(delta) > crit) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Kernel density estimation and utility class.
+ *
+ * @author Erich Schubert
+ */
+ protected class KernelDensityEstimator {
+ /**
+ * Actual kernel in use
+ */
+ final KernelDensityFunction kernel = EpanechnikovKernelDensityFunction.KERNEL;
+
+ /**
+ * Relation to retrieve data from
+ */
+ final Relation<V> relation;
+
+ /**
+ * Epsilon values for different subspace dimensionalities
+ */
+ final double[] epsilons;
+
+ /**
+ * Optimal bandwidth for a dimensionality of 2
+ */
+ final double hopttwo;
+
+ /**
+ * Dimensionality of data set
+ */
+ final int dim;
+
+ /**
+ * Constructor.
+ *
+ * @param relation Relation to apply to
+ */
+ public KernelDensityEstimator(Relation<V> relation) {
+ super();
+ this.relation = relation;
+ dim = DatabaseUtil.dimensionality(relation);
+ hopttwo = optimalBandwidth(2);
+ epsilons = new double[dim + 1];
+ Arrays.fill(epsilons, Double.NEGATIVE_INFINITY);
+ epsilons[2] = OUTRES.this.eps;
+ }
+
+ /**
+ * Compute density in the given subspace.
+ *
+ * @param subspace Subspace
+ * @param neighbours Neighbor distance list
+ * @return Density
+ */
+ protected double subspaceDensity(BitSet subspace, List<DistanceResultPair<DoubleDistance>> neighbours) {
+ final double bandwidth = optimalBandwidth(subspace.cardinality());
+
+ // TODO: optimize by moving instanceof outside?
+ double density = 0;
+ for(DistanceResultPair<DoubleDistance> pair : neighbours) {
+ if(pair instanceof DoubleDistanceResultPair) {
+ density += kernel.density(((DoubleDistanceResultPair) pair).getDoubleDistance() / bandwidth);
+ }
+ else {
+ density += kernel.density(pair.getDistance().doubleValue() / bandwidth);
+ }
+ }
+
+ return density / relation.size();
+ }
+
+ /**
+ * Compute optimal kernel bandwidth
+ *
+ * @param dim Dimensionality of subspace
+ * @return optimal bandwidth
+ */
+ protected double optimalBandwidth(int dim) {
+ // Pi in the publication is redundant and cancels out!
+ double hopt = 8 * Math.exp(GammaDistribution.logGamma(dim / 2.0 + 1)) * (dim + 4) * Math.pow(2, dim);
+ return hopt * Math.pow(relation.size(), (-1 / (dim + 4)));
+ }
+
+ /**
+ * Rescale the query radius based on the given dimensionality.
+ *
+ * @param dim Dimensionality
+ * @return Query radius
+ */
+ protected double adjustedEps(int dim) {
+ // Cached
+ double e = epsilons[dim];
+ if(e < 0) {
+ e = epsilons[2] * optimalBandwidth(dim) / hopttwo;
+ epsilons[dim] = e;
+ }
+ return e;
+ }
+ }
+
+ @Override
+ protected Logging getLogger() {
+ return logger;
+ }
+
+ @Override
+ public TypeInformation[] getInputTypeRestriction() {
+ return TypeUtil.array(TypeUtil.NUMBER_VECTOR_FIELD);
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Viktoria Pleintinger
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer<O extends NumberVector<O, ?>> extends AbstractParameterizer {
+ /**
+ * Option ID for Epsilon parameter
+ */
+ public static final OptionID D_ID = OptionID.getOrCreateOptionID("outres.epsilon", "Range value for OUTRES in 2 dimensions.");
+
+ /**
+ * Query radius
+ */
+ protected double eps;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ final DoubleParameter param = new DoubleParameter(D_ID);
+ if(config.grab(param)) {
+ eps = param.getValue();
+ }
+ }
+
+ @Override
+ protected OUTRES<O> makeInstance() {
+ return new OUTRES<O>(eps);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/OnlineLOF.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/OnlineLOF.java
index a5115fdf..ad17398c 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/OnlineLOF.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/OnlineLOF.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) 2011
+Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,7 +26,7 @@ import java.util.List;
import de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm;
import de.lmu.ifi.dbs.elki.database.QueryUtil;
-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.ArrayDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
@@ -37,6 +37,7 @@ import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery;
import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
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.KNNResult;
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;
@@ -101,14 +102,14 @@ public class OnlineLOF<O, D extends NumberDistance<D, ?>> extends LOF<O, D> {
RKNNQuery<O, D> rkNNRefer = queries.getSecond().getFirst();
RKNNQuery<O, D> rkNNReach = queries.getSecond().getSecond();
- LOFResult<O, D> lofResult = super.doRunInTime(kNNRefer, kNNReach, stepprog);
+ LOFResult<O, D> lofResult = super.doRunInTime(relation.getDBIDs(), kNNRefer, kNNReach, stepprog);
lofResult.setRkNNRefer(rkNNRefer);
lofResult.setRkNNReach(rkNNReach);
// add listener
KNNListener l = new LOFKNNListener(lofResult);
- ((MaterializeKNNPreprocessor<O, D>)((PreprocessorKNNQuery<O, D>) lofResult.getKNNRefer()).getPreprocessor()).addKNNListener(l);
- ((MaterializeKNNPreprocessor<O, D>)((PreprocessorKNNQuery<O, D>) lofResult.getKNNReach()).getPreprocessor()).addKNNListener(l);
+ ((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);
return lofResult.getResult();
}
@@ -194,8 +195,8 @@ public class OnlineLOF<O, D extends NumberDistance<D, ?>> extends LOF<O, D> {
@Override
public void kNNsChanged(KNNChangeEvent e) {
- AbstractMaterializeKNNPreprocessor<O, D> p1 = ((PreprocessorKNNQuery<O, D>) lofResult.getKNNRefer()).getPreprocessor();
- AbstractMaterializeKNNPreprocessor<O, D> p2 = ((PreprocessorKNNQuery<O, D>) lofResult.getKNNReach()).getPreprocessor();
+ 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)) {
@@ -266,13 +267,13 @@ public class OnlineLOF<O, D extends NumberDistance<D, ?>> extends LOF<O, D> {
ArrayDBIDs lrd_ids = DBIDUtil.ensureArray(DBIDUtil.union(insertions, updates2));
List<List<DistanceResultPair<D>>> reachDistRKNNs = lofResult.getRkNNReach().getRKNNForBulkDBIDs(lrd_ids, k);
ArrayDBIDs affected_lrd_id_candidates = mergeIDs(reachDistRKNNs, lrd_ids);
- ArrayDBIDs affected_lrd_ids = DBIDUtil.newArray(affected_lrd_id_candidates.size());
- WritableDataStore<Double> new_lrds = computeLRDs(affected_lrd_id_candidates, lofResult.getKNNReach());
+ ArrayModifiableDBIDs affected_lrd_ids = DBIDUtil.newArray(affected_lrd_id_candidates.size());
+ WritableDoubleDataStore new_lrds = computeLRDs(affected_lrd_id_candidates, lofResult.getKNNReach());
for(DBID id : affected_lrd_id_candidates) {
- Double new_lrd = new_lrds.get(id);
- Double old_lrd = lofResult.getLrds().get(id);
- if(old_lrd == null || !old_lrd.equals(new_lrd)) {
- lofResult.getLrds().put(id, new_lrd);
+ double new_lrd = new_lrds.doubleValue(id);
+ double old_lrd = lofResult.getLrds().doubleValue(id);
+ if(Double.isNaN(old_lrd) || old_lrd != new_lrd) {
+ lofResult.getLrds().putDouble(id, new_lrd);
affected_lrd_ids.add(id);
}
}
@@ -325,13 +326,13 @@ public class OnlineLOF<O, D extends NumberDistance<D, ?>> extends LOF<O, D> {
ArrayDBIDs lrd_ids = DBIDUtil.ensureArray(updates2);
List<List<DistanceResultPair<D>>> reachDistRKNNs = lofResult.getRkNNReach().getRKNNForBulkDBIDs(lrd_ids, k);
ArrayDBIDs affected_lrd_id_candidates = mergeIDs(reachDistRKNNs, lrd_ids);
- ArrayDBIDs affected_lrd_ids = DBIDUtil.newArray(affected_lrd_id_candidates.size());
- WritableDataStore<Double> new_lrds = computeLRDs(affected_lrd_id_candidates, lofResult.getKNNReach());
+ ArrayModifiableDBIDs affected_lrd_ids = DBIDUtil.newArray(affected_lrd_id_candidates.size());
+ WritableDoubleDataStore new_lrds = computeLRDs(affected_lrd_id_candidates, lofResult.getKNNReach());
for(DBID id : affected_lrd_id_candidates) {
- Double new_lrd = new_lrds.get(id);
- Double old_lrd = lofResult.getLrds().get(id);
- if(!old_lrd.equals(new_lrd)) {
- lofResult.getLrds().put(id, new_lrd);
+ double new_lrd = new_lrds.doubleValue(id);
+ double old_lrd = lofResult.getLrds().doubleValue(id);
+ if(old_lrd != new_lrd) {
+ lofResult.getLrds().putDouble(id, new_lrd);
affected_lrd_ids.add(id);
}
}
@@ -364,7 +365,7 @@ public class OnlineLOF<O, D extends NumberDistance<D, ?>> extends LOF<O, D> {
* ids
*/
private ArrayModifiableDBIDs mergeIDs(List<List<DistanceResultPair<D>>> queryResults, DBIDs... ids) {
- ModifiableDBIDs result = DBIDUtil.newTreeSet();
+ ModifiableDBIDs result = DBIDUtil.newHashSet();
for(DBIDs dbids : ids) {
result.addDBIDs(dbids);
}
@@ -383,10 +384,10 @@ public class OnlineLOF<O, D extends NumberDistance<D, ?>> extends LOF<O, D> {
* @param lofResult the result of the former LOF run
*/
private void recomputeLOFs(DBIDs ids, LOFResult<O, D> lofResult) {
- Pair<WritableDataStore<Double>, DoubleMinMax> lofsAndMax = computeLOFs(ids, lofResult.getLrds(), lofResult.getKNNRefer());
- WritableDataStore<Double> new_lofs = lofsAndMax.getFirst();
+ Pair<WritableDoubleDataStore, DoubleMinMax> lofsAndMax = computeLOFs(ids, lofResult.getLrds(), lofResult.getKNNRefer());
+ WritableDoubleDataStore new_lofs = lofsAndMax.getFirst();
for(DBID id : ids) {
- lofResult.getLofs().put(id, new_lofs.get(id));
+ lofResult.getLofs().putDouble(id, new_lofs.doubleValue(id));
}
// track the maximum value for normalization.
DoubleMinMax new_lofminmax = lofsAndMax.getSecond();
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 fb0a89d5..2b122183 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) 2011
+ Copyright (C) 2012
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/ReferenceBasedOutlierDetection.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/ReferenceBasedOutlierDetection.java
index e7895bad..befd03ed 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/ReferenceBasedOutlierDetection.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/ReferenceBasedOutlierDetection.java
@@ -1,26 +1,27 @@
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) 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/>.
-*/
+
+/*
+ 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 java.util.ArrayList;
import java.util.Collection;
@@ -35,17 +36,18 @@ 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.WritableDataStore;
+import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
import de.lmu.ifi.dbs.elki.database.query.GenericDistanceResultPair;
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.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.logging.Logging;
-import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
+import de.lmu.ifi.dbs.elki.math.Mean;
import de.lmu.ifi.dbs.elki.result.ReferencePointsResult;
import de.lmu.ifi.dbs.elki.result.outlier.BasicOutlierScoreMeta;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
@@ -53,6 +55,7 @@ import de.lmu.ifi.dbs.elki.result.outlier.OutlierScoreMeta;
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.parameterization.Parameterization;
@@ -144,45 +147,51 @@ public class ReferenceBasedOutlierDetection<V extends NumberVector<?, ?>, D exte
DBIDs ids = relation.getDBIDs();
// storage of distance/score values.
- WritableDataStore<Double> rbod_score = DataStoreUtil.makeStorage(ids, DataStoreFactory.HINT_STATIC, Double.class);
- // compute density for one reference point, to initialize the first density
- // value for each object
+ WritableDoubleDataStore rbod_score = DataStoreUtil.makeDoubleStorage(ids, DataStoreFactory.HINT_STATIC | DataStoreFactory.HINT_HOT);
- double density = 0;
- V firstRef = refPoints.iterator().next();
- // compute distance vector for the first reference point
- List<DistanceResultPair<D>> firstReferenceDists = computeDistanceVector(firstRef, relation, distFunc);
- // order ascending
- Collections.sort(firstReferenceDists);
- for(int l = 0; l < firstReferenceDists.size(); l++) {
- density = computeDensity(firstReferenceDists, l);
- rbod_score.put(firstReferenceDists.get(l).getDBID(), density);
- }
- // compute density values for all remaining reference points
- for(V refPoint : refPoints) {
- List<DistanceResultPair<D>> referenceDists = computeDistanceVector(refPoint, relation, distFunc);
- // order ascending
- Collections.sort(referenceDists);
- // compute density value for each object
- for(int l = 0; l < referenceDists.size(); l++) {
- density = computeDensity(referenceDists, l);
- if(density < rbod_score.get(referenceDists.get(l).getDBID())) {
- rbod_score.put(referenceDists.get(l).getDBID(), density);
+ // Compute density estimation:
+ {
+ // compute density for one reference point, to initialize the first
+ // density
+ // value for each object, then update
+ final Iterator<V> iter = refPoints.iterator();
+ if(!iter.hasNext()) {
+ throw new AbortException("Cannot compute ROS without reference points!");
+ }
+ V firstRef = iter.next();
+ // compute distance vector for the first reference point
+ List<DistanceResultPair<D>> firstReferenceDists = computeDistanceVector(firstRef, relation, distFunc);
+ for(int l = 0; l < firstReferenceDists.size(); l++) {
+ double density = computeDensity(firstReferenceDists, l);
+ // Initial value
+ rbod_score.putDouble(firstReferenceDists.get(l).getDBID(), density);
+ }
+ // compute density values for all remaining reference points
+ while(iter.hasNext()) {
+ V refPoint = iter.next();
+ List<DistanceResultPair<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);
+ // Update minimum
+ if(density < rbod_score.doubleValue(referenceDists.get(l).getDBID())) {
+ rbod_score.putDouble(referenceDists.get(l).getDBID(), density);
+ }
}
}
}
// compute maximum density
double maxDensity = 0.0;
for(DBID id : relation.iterDBIDs()) {
- double dens = rbod_score.get(id);
+ double dens = rbod_score.doubleValue(id);
if(dens > maxDensity) {
maxDensity = dens;
}
}
- // compute REFOD_SCORE
+ // compute ROS
for(DBID id : relation.iterDBIDs()) {
- double score = 1 - (rbod_score.get(id) / maxDensity);
- rbod_score.put(id, score);
+ double score = 1 - (rbod_score.doubleValue(id) / maxDensity);
+ rbod_score.putDouble(id, score);
}
// adds reference points to the result. header information for the
@@ -207,13 +216,13 @@ public class ReferenceBasedOutlierDetection<V extends NumberVector<?, ?>, D exte
* database object and the object id
*/
protected List<DistanceResultPair<D>> computeDistanceVector(V refPoint, Relation<V> database, DistanceQuery<V, D> distFunc) {
+ // TODO: optimize for double distances?
List<DistanceResultPair<D>> referenceDists = new ArrayList<DistanceResultPair<D>>(database.size());
- int counter = 0;
- for(Iterator<DBID> iter = database.iterDBIDs(); iter.hasNext(); counter++) {
- DBID id = iter.next();
- DistanceResultPair<D> referenceDist = new GenericDistanceResultPair<D>(distFunc.distance(id, refPoint), id);
- referenceDists.add(counter, referenceDist);
+ for(DBID id : database.iterDBIDs()) {
+ final D distance = distFunc.distance(id, refPoint);
+ referenceDists.add(new GenericDistanceResultPair<D>(distance, id));
}
+ Collections.sort(referenceDists);
return referenceDists;
}
@@ -230,51 +239,53 @@ public class ReferenceBasedOutlierDetection<V extends NumberVector<?, ?>, D exte
* @return density for one object and reference point
*/
protected double computeDensity(List<DistanceResultPair<D>> referenceDists, int index) {
- double density = 0.0;
- DistanceResultPair<D> x = referenceDists.get(index);
- double xDist = x.getDistance().doubleValue();
+ final DistanceResultPair<D> x = referenceDists.get(index);
+ final double xDist = x.getDistance().doubleValue();
- int j = 0;
- int n = index - 1;
- int m = index + 1;
- while(j < k) {
- double mdist = 0;
- double ndist = 0;
- if(n >= 0) {
- ndist = referenceDists.get(n).getDistance().doubleValue();
- if(m < referenceDists.size()) {
- mdist = referenceDists.get(m).getDistance().doubleValue();
- if(Math.abs(ndist - xDist) < Math.abs(mdist - xDist)) {
- density += Math.abs(ndist - xDist);
- n--;
- j++;
- }
- else {
- density += Math.abs(mdist - xDist);
- m++;
- j++;
- }
+ int lef = index - 1;
+ int rig = index + 1;
+ Mean mean = new Mean();
+ double lef_d = (lef >= 0) ? referenceDists.get(lef).getDistance().doubleValue() : Double.NEGATIVE_INFINITY;
+ double rig_d = (rig < referenceDists.size()) ? referenceDists.get(rig).getDistance().doubleValue() : Double.NEGATIVE_INFINITY;
+ while(mean.getCount() < k) {
+ if(lef >= 0 && rig < referenceDists.size()) {
+ // Prefer n or m?
+ if(Math.abs(lef_d - xDist) < Math.abs(rig_d - xDist)) {
+ mean.put(Math.abs(lef_d - xDist));
+ // Update n
+ lef--;
+ lef_d = (lef >= 0) ? referenceDists.get(lef).getDistance().doubleValue() : Double.NEGATIVE_INFINITY;
}
else {
- density += Math.abs(ndist - xDist);
- n--;
- j++;
+ mean.put(Math.abs(rig_d - xDist));
+ // Update right
+ rig++;
+ rig_d = (rig < referenceDists.size()) ? referenceDists.get(rig).getDistance().doubleValue() : Double.NEGATIVE_INFINITY;
}
}
- else if(m < referenceDists.size()) {
- mdist = referenceDists.get(m).getDistance().doubleValue();
- density += Math.abs(mdist - xDist);
- m++;
- j++;
- }
else {
- throw new IndexOutOfBoundsException();
+ if(lef >= 0) {
+ // Choose left, since right is not available.
+ mean.put(Math.abs(lef_d - xDist));
+ // update left
+ lef--;
+ lef_d = (lef >= 0) ? referenceDists.get(lef).getDistance().doubleValue() : Double.NEGATIVE_INFINITY;
+ }
+ else if(rig < referenceDists.size()) {
+ // Choose right, since left is not available
+ mean.put(Math.abs(rig_d - xDist));
+ // Update right
+ rig++;
+ rig_d = (rig < referenceDists.size()) ? referenceDists.get(rig).getDistance().doubleValue() : Double.NEGATIVE_INFINITY;
+ }
+ else {
+ // Not enough objects in database?
+ throw new IndexOutOfBoundsException();
+ }
}
}
- double densityDegree = 1.0 / ((1.0 / k) * density);
-
- return densityDegree;
+ return 1.0 / mean.getMean();
}
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/SOD.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/SOD.java
index 5e7184a3..a09bbcfd 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/outlier/SOD.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/SOD.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -35,16 +35,17 @@ 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.ArrayModifiableDBIDs;
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.query.DoubleDistanceResultPair;
import de.lmu.ifi.dbs.elki.database.query.similarity.SimilarityQuery;
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.subspace.DimensionsSelectingEuclideanDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.IntegerDistance;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.SubspaceEuclideanDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
import de.lmu.ifi.dbs.elki.distance.similarityfunction.SharedNearestNeighborSimilarityFunction;
+import de.lmu.ifi.dbs.elki.distance.similarityfunction.SimilarityFunction;
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;
@@ -54,10 +55,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.result.textwriter.TextWriteable;
import de.lmu.ifi.dbs.elki.result.textwriter.TextWriterStream;
-import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
import de.lmu.ifi.dbs.elki.utilities.DatabaseUtil;
-import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.KNNHeap;
-import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.KNNList;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.Heap;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.TiedTopBoundedHeap;
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;
@@ -69,6 +69,8 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstrain
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.pairs.DoubleObjPair;
/**
* @author Arthur Zimek
@@ -82,7 +84,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
@Title("SOD: Subspace outlier degree")
@Description("Outlier Detection in Axis-Parallel Subspaces of High Dimensional Data")
@Reference(authors = "H.-P. Kriegel, P. Kröger, E. Schubert, A. Zimek", title = "Outlier Detection in Axis-Parallel Subspaces of High Dimensional Data", booktitle = "Proceedings of the 13th Pacific-Asia Conference on Knowledge Discovery and Data Mining (PAKDD), Bangkok, Thailand, 2009", url = "http://dx.doi.org/10.1007/978-3-642-01307-2")
-public class SOD<V extends NumberVector<V, ?>> extends AbstractAlgorithm<OutlierResult> implements OutlierAlgorithm {
+public class SOD<V extends NumberVector<V, ?>, D extends NumberDistance<D, ?>> extends AbstractAlgorithm<OutlierResult> implements OutlierAlgorithm {
/**
* The logger for this class.
*/
@@ -93,7 +95,7 @@ public class SOD<V extends NumberVector<V, ?>> extends AbstractAlgorithm<Outlier
* considered for learning the subspace properties., must be an integer
* greater than 0.
*/
- public static final OptionID KNN_ID = OptionID.getOrCreateOptionID("sod.knn", "The number of shared nearest neighbors to be considered for learning the subspace properties.");
+ public static final OptionID KNN_ID = OptionID.getOrCreateOptionID("sod.knn", "The number of most snn-similar objects to use as reference set for learning the subspace properties.");
/**
* Parameter to indicate the multiplier for the discriminance value for
@@ -102,6 +104,11 @@ public class SOD<V extends NumberVector<V, ?>> extends AbstractAlgorithm<Outlier
public static final OptionID ALPHA_ID = OptionID.getOrCreateOptionID("sod.alpha", "The multiplier for the discriminance value for discerning small from large variances.");
/**
+ * Parameter for the similarity function.
+ */
+ public static final OptionID SIM_ID = OptionID.getOrCreateOptionID("sod.similarity", "The similarity function used for the neighborhood set.");
+
+ /**
* Holds the value of {@link #KNN_ID}.
*/
private int knn;
@@ -112,9 +119,9 @@ public class SOD<V extends NumberVector<V, ?>> extends AbstractAlgorithm<Outlier
private double alpha;
/**
- * The similarity function.
+ * The similarity function {@link #SIM_ID}.
*/
- private SharedNearestNeighborSimilarityFunction<V> similarityFunction;
+ private SimilarityFunction<V, D> similarityFunction;
/**
* Constructor with parameters.
@@ -123,7 +130,7 @@ public class SOD<V extends NumberVector<V, ?>> extends AbstractAlgorithm<Outlier
* @param alpha Alpha parameter
* @param similarityFunction Shared nearest neighbor similarity function
*/
- public SOD(int knn, double alpha, SharedNearestNeighborSimilarityFunction<V> similarityFunction) {
+ public SOD(int knn, double alpha, SimilarityFunction<V, D> similarityFunction) {
super();
this.knn = knn;
this.alpha = alpha;
@@ -136,7 +143,7 @@ public class SOD<V extends NumberVector<V, ?>> extends AbstractAlgorithm<Outlier
* @param relation Data relation to process
*/
public OutlierResult run(Relation<V> relation) throws IllegalStateException {
- SimilarityQuery<V, IntegerDistance> snnInstance = similarityFunction.instantiate(relation);
+ SimilarityQuery<V, D> snnInstance = similarityFunction.instantiate(relation);
FiniteProgress progress = logger.isVerbose() ? new FiniteProgress("Assigning Subspace Outlier Degree", relation.size(), logger) : null;
WritableDataStore<SODModel<?>> sod_models = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, SODModel.class);
DoubleMinMax minmax = new DoubleMinMax();
@@ -145,7 +152,7 @@ public class SOD<V extends NumberVector<V, ?>> extends AbstractAlgorithm<Outlier
if(progress != null) {
progress.incrementProcessed(logger);
}
- DBIDs knnList = getKNN(relation, snnInstance, queryObject).asDBIDs();
+ DBIDs knnList = getNearestNeighbors(relation, snnInstance, queryObject);
SODModel<V> model = new SODModel<V>(relation, knnList, alpha, relation.get(queryObject));
sod_models.put(queryObject, model);
minmax.put(model.getSod());
@@ -168,23 +175,30 @@ public class SOD<V extends NumberVector<V, ?>> extends AbstractAlgorithm<Outlier
* <p/>
* The query object is excluded from the knn list.
*
- * @param database the database holding the objects
- * @param snnInstance similarity function
+ * @param relation the database holding the objects
+ * @param simQ similarity function
* @param queryObject the query object for which the kNNs should be determined
* @return the k nearest neighbors in terms of the shared nearest neighbor
* distance without the query object
*/
- private KNNList<DoubleDistance> getKNN(Relation<V> database, SimilarityQuery<V, IntegerDistance> snnInstance, DBID queryObject) {
+ private DBIDs getNearestNeighbors(Relation<V> relation, SimilarityQuery<V, D> simQ, DBID queryObject) {
// similarityFunction.getPreprocessor().getParameters();
- KNNHeap<DoubleDistance> kNearestNeighbors = new KNNHeap<DoubleDistance>(knn, new DoubleDistance(Double.POSITIVE_INFINITY));
- for(Iterator<DBID> iter = database.iterDBIDs(); iter.hasNext();) {
- DBID id = iter.next();
+ Heap<DoubleObjPair<DBID>> nearestNeighbors = new TiedTopBoundedHeap<DoubleObjPair<DBID>>(knn);
+ for(DBID id : relation.iterDBIDs()) {
if(!id.equals(queryObject)) {
- double distance = 1.0 / snnInstance.similarity(queryObject, id).doubleValue();
- kNearestNeighbors.add(new DoubleDistanceResultPair(distance, id));
+ double sim = simQ.similarity(queryObject, id).doubleValue();
+ if(sim > 0) {
+ nearestNeighbors.add(new DoubleObjPair<DBID>(sim, id));
+ }
}
}
- return kNearestNeighbors.toKNNList();
+ // Collect DBIDs
+ ArrayModifiableDBIDs dbids = DBIDUtil.newArray(nearestNeighbors.size());
+ while(nearestNeighbors.size() > 0) {
+ final DoubleObjPair<DBID> next = nearestNeighbors.poll();
+ dbids.add(next.second);
+ }
+ return dbids;
}
@Override
@@ -201,13 +215,13 @@ public class SOD<V extends NumberVector<V, ?>> extends AbstractAlgorithm<Outlier
*
*
* @author Arthur Zimek
- * @param <O> the type of DatabaseObjects handled by this Result
+ * @param <V> the type of DatabaseObjects handled by this Result
*/
// TODO: arthur comment
- public static class SODModel<O extends NumberVector<O, ?>> implements TextWriteable, Comparable<SODModel<?>> {
+ public static class SODModel<V extends NumberVector<V, ?>> implements TextWriteable, Comparable<SODModel<?>> {
private double[] centerValues;
- private O center;
+ private V center;
private double[] variances;
@@ -220,61 +234,71 @@ public class SOD<V extends NumberVector<V, ?>> extends AbstractAlgorithm<Outlier
/**
* Initialize SOD Model
*
- * @param database Database
+ * @param relation Database
* @param neighborhood Neighborhood
* @param alpha Alpha value
* @param queryObject Query object
*/
- public SODModel(Relation<O> database, DBIDs neighborhood, double alpha, O queryObject) {
- // TODO: store database link?
- centerValues = new double[DatabaseUtil.dimensionality(database)];
- variances = new double[centerValues.length];
- for(DBID id : neighborhood) {
- O databaseObject = database.get(id);
- for(int d = 0; d < centerValues.length; d++) {
- centerValues[d] += databaseObject.doubleValue(d + 1);
+ public SODModel(Relation<V> relation, DBIDs neighborhood, double alpha, V queryObject) {
+ if(neighborhood.size() > 0) {
+ // TODO: store database link?
+ centerValues = new double[DatabaseUtil.dimensionality(relation)];
+ variances = new double[centerValues.length];
+ for(DBID id : neighborhood) {
+ V databaseObject = relation.get(id);
+ for(int d = 0; d < centerValues.length; d++) {
+ centerValues[d] += databaseObject.doubleValue(d + 1);
+ }
}
- }
- for(int d = 0; d < centerValues.length; d++) {
- centerValues[d] /= neighborhood.size();
- }
- for(DBID id : neighborhood) {
- O databaseObject = database.get(id);
for(int d = 0; d < centerValues.length; d++) {
- // distance
- double distance = centerValues[d] - databaseObject.doubleValue(d + 1);
- // variance
- variances[d] += distance * distance;
+ centerValues[d] /= neighborhood.size();
}
- }
- expectationOfVariance = 0;
- for(int d = 0; d < variances.length; d++) {
- variances[d] /= neighborhood.size();
- expectationOfVariance += variances[d];
- }
- expectationOfVariance /= variances.length;
- weightVector = new BitSet(variances.length);
- for(int d = 0; d < variances.length; d++) {
- if(variances[d] < alpha * expectationOfVariance) {
- weightVector.set(d, true);
+ for(DBID id : neighborhood) {
+ V databaseObject = relation.get(id);
+ for(int d = 0; d < centerValues.length; d++) {
+ // distance
+ double distance = centerValues[d] - databaseObject.doubleValue(d + 1);
+ // variance
+ variances[d] += distance * distance;
+ }
}
+ expectationOfVariance = 0;
+ for(int d = 0; d < variances.length; d++) {
+ variances[d] /= neighborhood.size();
+ expectationOfVariance += variances[d];
+ }
+ expectationOfVariance /= variances.length;
+ weightVector = new BitSet(variances.length);
+ for(int d = 0; d < variances.length; d++) {
+ if(variances[d] < alpha * expectationOfVariance) {
+ weightVector.set(d, true);
+ }
+ }
+ center = DatabaseUtil.assumeVectorField(relation).getFactory().newNumberVector(centerValues);
+ sod = subspaceOutlierDegree(queryObject, center, weightVector);
+ }
+ else {
+ center = queryObject;
+ sod = 0.0;
}
- center = DatabaseUtil.assumeVectorField(database).getFactory().newInstance(centerValues);
- sod = subspaceOutlierDegree(queryObject, center, weightVector);
}
/**
- *
+ * Compute SOD score
*
* @param queryObject
* @param center
* @param weightVector
* @return sod value
*/
- private double subspaceOutlierDegree(O queryObject, O center, BitSet weightVector) {
- final DimensionsSelectingEuclideanDistanceFunction df = new DimensionsSelectingEuclideanDistanceFunction(weightVector);
+ private double subspaceOutlierDegree(V queryObject, V center, BitSet weightVector) {
+ final SubspaceEuclideanDistanceFunction df = new SubspaceEuclideanDistanceFunction(weightVector);
+ final int card = weightVector.cardinality();
+ if(card == 0) {
+ return 0;
+ }
double distance = df.distance(queryObject, center).doubleValue();
- distance /= weightVector.cardinality();
+ distance /= card;
return distance;
}
@@ -316,7 +340,7 @@ public class SOD<V extends NumberVector<V, ?>> extends AbstractAlgorithm<Outlier
* Model result this is a proxy for.
*/
Relation<SODModel<?>> models;
-
+
/**
* The IDs we are defined for
*/
@@ -326,7 +350,7 @@ public class SOD<V extends NumberVector<V, ?>> extends AbstractAlgorithm<Outlier
* Constructor.
*
* @param models Models result
- * @param dbids IDs we are defined for
+ * @param dbids IDs we are defined for
*/
public SODProxyScoreResult(Relation<SODModel<?>> models, DBIDs dbids) {
super();
@@ -353,7 +377,7 @@ public class SOD<V extends NumberVector<V, ?>> extends AbstractAlgorithm<Outlier
public DBIDs getDBIDs() {
return dbids;
}
-
+
@Override
public IterableIterator<DBID> iterDBIDs() {
return IterableUtil.fromIterator(dbids.iterator());
@@ -402,7 +426,7 @@ public class SOD<V extends NumberVector<V, ?>> extends AbstractAlgorithm<Outlier
*
* @apiviz.exclude
*/
- public static class Parameterizer<V extends NumberVector<V, ?>> extends AbstractParameterizer {
+ public static class Parameterizer<V extends NumberVector<V, ?>, D extends NumberDistance<D, ?>> extends AbstractParameterizer {
/**
* Holds the value of {@link #KNN_ID}.
*/
@@ -414,14 +438,19 @@ public class SOD<V extends NumberVector<V, ?>> extends AbstractAlgorithm<Outlier
private double alpha = 1.1;
/**
- * The similarity function.
+ * The similarity function - {@link #SIM_ID}.
*/
- private SharedNearestNeighborSimilarityFunction<V> similarityFunction;
+ private SimilarityFunction<V, D> similarityFunction;
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- final IntParameter knnP = new IntParameter(KNN_ID, new GreaterConstraint(0), 1);
+ final ObjectParameter<SimilarityFunction<V, D>> simP = new ObjectParameter<SimilarityFunction<V, D>>(SIM_ID, SimilarityFunction.class, SharedNearestNeighborSimilarityFunction.class);
+ if(config.grab(simP)) {
+ similarityFunction = simP.instantiateClass(config);
+ }
+
+ final IntParameter knnP = new IntParameter(KNN_ID, new GreaterConstraint(0));
if(config.grab(knnP)) {
knn = knnP.getValue();
}
@@ -430,14 +459,11 @@ public class SOD<V extends NumberVector<V, ?>> extends AbstractAlgorithm<Outlier
if(config.grab(alphaP)) {
alpha = alphaP.getValue();
}
-
- Class<SharedNearestNeighborSimilarityFunction<V>> cls = ClassGenericsUtil.uglyCastIntoSubclass(SharedNearestNeighborSimilarityFunction.class);
- similarityFunction = config.tryInstantiate(cls);
}
@Override
- protected SOD<V> makeInstance() {
- return new SOD<V>(knn, alpha, similarityFunction);
+ protected SOD<V, D> makeInstance() {
+ return new SOD<V, D>(knn, alpha, similarityFunction);
}
}
} \ No newline at end of file
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 5a4503fd..22447454 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -39,14 +39,14 @@ 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.datastore.WritableDoubleDataStore;
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.relation.MaterializedRelation;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.datasource.parser.AbstractParser;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
-import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
import de.lmu.ifi.dbs.elki.result.outlier.BasicOutlierScoreMeta;
import de.lmu.ifi.dbs.elki.result.outlier.InvertedOutlierScoreMeta;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
@@ -140,7 +140,7 @@ public class ExternalDoubleOutlierScore extends AbstractAlgorithm<OutlierResult>
* @return Result
*/
public OutlierResult run(Database database, Relation<?> relation) {
- WritableDataStore<Double> scores = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, Double.class);
+ WritableDoubleDataStore scores = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC);
Pattern colSep = Pattern.compile(AbstractParser.WHITESPACE_PATTERN);
DoubleMinMax minmax = new DoubleMinMax();
@@ -156,7 +156,7 @@ public class ExternalDoubleOutlierScore extends AbstractAlgorithm<OutlierResult>
else if(line.length() > 0) {
String[] cols = colSep.split(line);
Integer id = null;
- Double score = null;
+ double score = Double.NaN;
for(String str : cols) {
Matcher mi = idpattern.matcher(str);
Matcher ms = scorepattern.matcher(str);
@@ -172,17 +172,17 @@ public class ExternalDoubleOutlierScore extends AbstractAlgorithm<OutlierResult>
id = Integer.parseInt(str.substring(mi.end()));
}
if(msf) {
- if(score != null) {
+ if(!Double.isNaN(score)) {
throw new AbortException("Score pattern matched twice: previous value " + score + " second value: " + str);
}
score = Double.parseDouble(str.substring(ms.end()));
}
}
- if(id != null && score != null) {
- scores.put(DBIDUtil.importInteger(id), score);
+ if(id != null && !Double.isNaN(score)) {
+ scores.putDouble(DBIDUtil.importInteger(id), score);
minmax.put(score);
}
- else if(id == null && score == null) {
+ else if(id == null && Double.isNaN(score)) {
logger.warning("Line did not match either ID nor score nor comment: " + line);
}
else {
@@ -213,7 +213,7 @@ public class ExternalDoubleOutlierScore extends AbstractAlgorithm<OutlierResult>
for(DBID id : relation.iterDBIDs()) {
double val = scoresult.get(id); // scores.get(id);
val = scaling.getScaled(val);
- scores.put(id, val);
+ scores.putDouble(id, val);
mm.put(val);
}
meta = new BasicOutlierScoreMeta(mm.getMin(), mm.getMax());
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 d3e738a1..c8da9501 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) 2011
+ Copyright (C) 2012
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.algorithm.outlier.meta;
import java.util.ArrayList;
import java.util.BitSet;
-import java.util.HashMap;
import java.util.Random;
import de.lmu.ifi.dbs.elki.algorithm.AbstractAlgorithm;
@@ -36,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.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.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
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.subspace.DimensionsSelectingEuclideanDistanceFunction;
+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;
import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress;
@@ -60,6 +59,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameteriz
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;
+import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
/**
* A simple ensemble method called "Feature bagging" for outlier detection.
@@ -144,8 +144,8 @@ public class FeatureBagging extends AbstractAlgorithm<OutlierResult> implements
FiniteProgress prog = logger.isVerbose() ? new FiniteProgress("LOF iterations", num, logger) : null;
for(int i = 0; i < num; i++) {
BitSet dimset = randomSubspace(dbdim, mindim, maxdim);
- DimensionsSelectingEuclideanDistanceFunction df = new DimensionsSelectingEuclideanDistanceFunction(dimset);
- LOF<NumberVector<?, ?>, DoubleDistance> lof = new LOF<NumberVector<?, ?>, DoubleDistance>(k, df, df);
+ SubspaceEuclideanDistanceFunction df = new SubspaceEuclideanDistanceFunction(dimset);
+ LOF<NumberVector<?, ?>, DoubleDistance> lof = new LOF<NumberVector<?, ?>, DoubleDistance>(k, df);
// run LOF and collect the result
OutlierResult result = lof.run(relation);
@@ -159,28 +159,34 @@ public class FeatureBagging extends AbstractAlgorithm<OutlierResult> implements
}
}
- WritableDataStore<Double> scores = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, Double.class);
+ WritableDoubleDataStore scores = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC);
DoubleMinMax minmax = new DoubleMinMax();
if(breadth) {
FiniteProgress cprog = logger.isVerbose() ? new FiniteProgress("Combining results", relation.size(), logger) : null;
- HashMap<IterableIterator<DBID>, Relation<Double>> IDVectorOntoScoreVector = new HashMap<IterableIterator<DBID>, Relation<Double>>();
+ Pair<IterableIterator<DBID>, Relation<Double>>[] IDVectorOntoScoreVector = Pair.newPairArray(results.size());
// Mapping score-sorted DBID-Iterators onto their corresponding scores.
// We need to initialize them now be able to iterate them "in parallel".
- for(OutlierResult r : results) {
- IDVectorOntoScoreVector.put(r.getOrdering().iter(relation.getDBIDs()), r.getScores());
+ {
+ int i = 0;
+ for(OutlierResult r : results) {
+ IDVectorOntoScoreVector[i] = new Pair<IterableIterator<DBID>, Relation<Double>>(r.getOrdering().iter(relation.getDBIDs()), r.getScores());
+ i++;
+ }
}
// Iterating over the *lines* of the AS_t(i)-matrix.
for(int i = 0; i < relation.size(); i++) {
// Iterating over the elements of a line (breadth-first).
- for(IterableIterator<DBID> iter : IDVectorOntoScoreVector.keySet()) {
- if(iter.hasNext()) { // Always true if every algorithm returns a
- // complete result (one score for every DBID).
+ for(Pair<IterableIterator<DBID>, Relation<Double>> pair : IDVectorOntoScoreVector) {
+ IterableIterator<DBID> iter = pair.first;
+ // Always true if every algorithm returns a complete result (one score
+ // for every DBID).
+ if(iter.hasNext()) {
DBID tmpID = iter.next();
- double score = IDVectorOntoScoreVector.get(iter).get(tmpID);
- if(scores.get(tmpID) == null) {
- scores.put(tmpID, score);
+ double score = pair.second.get(tmpID);
+ if(Double.isNaN(scores.doubleValue(tmpID))) {
+ scores.putDouble(tmpID, score);
minmax.put(score);
}
}
@@ -202,9 +208,12 @@ public class FeatureBagging extends AbstractAlgorithm<OutlierResult> implements
for(DBID id : relation.iterDBIDs()) {
double sum = 0.0;
for(OutlierResult r : results) {
- sum += r.getScores().get(id);
+ final Double s = r.getScores().get(id);
+ if (s != null && !Double.isNaN(s)) {
+ sum += s;
+ }
}
- scores.put(id, sum);
+ scores.putDouble(id, sum);
minmax.put(sum);
if(cprog != null) {
cprog.incrementProcessed(logger);
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 18f62549..9634cd59 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -33,12 +33,12 @@ 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.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
+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.database.relation.MaterializedRelation;
import de.lmu.ifi.dbs.elki.result.Result;
import de.lmu.ifi.dbs.elki.result.ResultUtil;
import de.lmu.ifi.dbs.elki.result.outlier.BasicOutlierScoreMeta;
@@ -102,13 +102,13 @@ public class RescaleMetaOutlierAlgorithm extends AbstractAlgorithm<OutlierResult
((OutlierScalingFunction) scaling).prepare(or);
}
- WritableDataStore<Double> scaledscores = DataStoreUtil.makeStorage(scores.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_STATIC, Double.class);
+ WritableDoubleDataStore scaledscores = DataStoreUtil.makeDoubleStorage(scores.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_STATIC);
DoubleMinMax minmax = new DoubleMinMax();
for(DBID id : scores.iterDBIDs()) {
double val = scores.get(id);
val = scaling.getScaled(val);
- scaledscores.put(id, val);
+ scaledscores.putDouble(id, val);
minmax.put(val);
}
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 6565e144..d7e78281 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
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2011
+Copyright (C) 2012
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 372383f8..ea5d3ec4 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
@@ -9,7 +9,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2011
+Copyright (C) 2012
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 79fae09d..1caf7582 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) 2011
+ Copyright (C) 2012
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/AbstractNeighborhoodOutlier.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/AbstractNeighborhoodOutlier.java
index 4e1e0fa1..f0c05e1e 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) 2011
+ Copyright (C) 2012
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/CTLuGLSBackwardSearchAlgorithm.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/CTLuGLSBackwardSearchAlgorithm.java
index e8a7415b..b4070e0c 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,9 +23,6 @@ package de.lmu.ifi.dbs.elki.algorithm.outlier.spatial;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-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.NumberVector;
@@ -34,13 +31,14 @@ import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
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.WritableDataStore;
-import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs;
+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.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
+import de.lmu.ifi.dbs.elki.database.query.knn.KNNResult;
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;
@@ -48,8 +46,8 @@ 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.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.statistics.distribution.NormalDistribution;
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;
@@ -123,7 +121,7 @@ public class CTLuGLSBackwardSearchAlgorithm<V extends NumberVector<?, ?>, D exte
* @return Algorithm result
*/
public OutlierResult run(Relation<V> relationx, Relation<? extends NumberVector<?, ?>> relationy) {
- WritableDataStore<Double> scores = DataStoreUtil.makeStorage(relationx.getDBIDs(), DataStoreFactory.HINT_STATIC, Double.class);
+ WritableDoubleDataStore scores = DataStoreUtil.makeDoubleStorage(relationx.getDBIDs(), DataStoreFactory.HINT_STATIC);
DoubleMinMax mm = new DoubleMinMax(0.0, 0.0);
// Outlier detection loop
@@ -131,14 +129,14 @@ public class CTLuGLSBackwardSearchAlgorithm<V extends NumberVector<?, ?>, D exte
ModifiableDBIDs idview = DBIDUtil.newHashSet(relationx.getDBIDs());
ProxyView<V> proxy = new ProxyView<V>(relationx.getDatabase(), idview, relationx);
- double phialpha = MathUtil.standardNormalProbit(1.0 - alpha / 2);
+ double phialpha = NormalDistribution.standardNormalProbit(1.0 - alpha / 2);
// Detect outliers while significant.
while(true) {
Pair<DBID, Double> candidate = singleIteration(proxy, relationy);
if(candidate.second < phialpha) {
break;
}
- scores.put(candidate.first, candidate.second);
+ scores.putDouble(candidate.first, candidate.second);
if (!Double.isNaN(candidate.second)) {
mm.put(candidate.second);
}
@@ -147,7 +145,7 @@ public class CTLuGLSBackwardSearchAlgorithm<V extends NumberVector<?, ?>, D exte
// Remaining objects are inliers
for(DBID id : idview) {
- scores.put(id, 0.0);
+ scores.putDouble(id, 0.0);
}
}
@@ -170,9 +168,9 @@ public class CTLuGLSBackwardSearchAlgorithm<V extends NumberVector<?, ?>, D exte
KNNQuery<V, D> knnQuery = QueryUtil.getKNNQuery(relationx, getDistanceFunction(), k + 1);
// We need stable indexed DBIDs
- ArrayDBIDs ids = DBIDUtil.newArray(relationx.getDBIDs());
+ ArrayModifiableDBIDs ids = DBIDUtil.newArray(relationx.getDBIDs());
// Sort, so we can do a binary search below.
- Collections.sort(ids);
+ ids.sort();
// init F,X,Z
Matrix X = new Matrix(ids.size(), 6);
@@ -203,7 +201,7 @@ public class CTLuGLSBackwardSearchAlgorithm<V extends NumberVector<?, ?>, D exte
// Fill the neighborhood matrix F:
{
- List<DistanceResultPair<D>> neighbors = knnQuery.getKNNForDBID(id, k + 1);
+ KNNResult<D> neighbors = knnQuery.getKNNForDBID(id, k + 1);
ModifiableDBIDs neighborhood = DBIDUtil.newArray(neighbors.size());
for(DistanceResultPair<D> dpair : neighbors) {
if(id.equals(dpair.getDBID())) {
@@ -216,7 +214,7 @@ public class CTLuGLSBackwardSearchAlgorithm<V extends NumberVector<?, ?>, D exte
final int nweight = -1 / neighborhood.size();
// We need to find the index positions of the neighbors, unfortunately.
for(DBID nid : neighborhood) {
- int pos = Collections.binarySearch(ids, nid);
+ int pos = ids.binarySearch(nid);
assert (pos >= 0);
F.set(pos, i, nweight);
}
@@ -239,7 +237,7 @@ public class CTLuGLSBackwardSearchAlgorithm<V extends NumberVector<?, ?>, D exte
double worstscore = Double.NEGATIVE_INFINITY;
for(int i = 0; i < ids.size(); i++) {
DBID id = ids.get(i);
- double err = E.getRowVector(i).euclideanLength();
+ double err = E.getRow(i).euclideanLength();
// double err = Math.abs(E.get(i, 0));
if(err > worstscore) {
worstscore = err;
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 516c2ade..68e58ffa 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) 2011
+ Copyright (C) 2012
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.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.WritableDataStore;
+import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
@@ -60,7 +61,7 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
* <p>
* Implementation note: attribute standardization is not used; this is
* equivalent to using the
- * {@link de.lmu.ifi.dbs.elki.datasource.filter.AttributeWiseVarianceNormalization
+ * {@link de.lmu.ifi.dbs.elki.datasource.filter.normalization.AttributeWiseVarianceNormalization
* AttributeWiseVarianceNormalization} filter.
* </p>
*
@@ -115,14 +116,12 @@ public class CTLuMeanMultipleAttributes<N, O extends NumberVector<?, ?>> extends
Matrix cmati = covmaker.destroyToSampleMatrix().inverse();
DoubleMinMax minmax = new DoubleMinMax();
- WritableDataStore<Double> scores = DataStoreUtil.makeStorage(attributes.getDBIDs(), DataStoreFactory.HINT_STATIC, Double.class);
+ WritableDoubleDataStore scores = DataStoreUtil.makeDoubleStorage(attributes.getDBIDs(), DataStoreFactory.HINT_STATIC);
for(DBID id : attributes.iterDBIDs()) {
Vector temp = deltas.get(id).minus(mean);
- final Vector res = temp.transposeTimes(cmati).times(temp);
- assert (res.getDimensionality() == 1);
- double score = res.get(0);
+ final double score = temp.transposeTimesTimes(cmati, temp);
minmax.put(score);
- scores.put(id, score);
+ scores.putDouble(id, score);
}
Relation<Double> scoreResult = new MaterializedRelation<Double>("mean multiple attributes spatial outlier", "mean-multipleattributes-outlier", TypeUtil.DOUBLE, scores, attributes.getDBIDs());
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 7f397790..9b4534fe 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
@@ -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) 2011
+Copyright (C) 2012
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.type.TypeUtil;
import de.lmu.ifi.dbs.elki.data.type.VectorFieldTypeInformation;
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.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
@@ -37,10 +37,10 @@ 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.MeanVariance;
-import de.lmu.ifi.dbs.elki.math.statistics.QuickSelect;
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.datastructures.QuickSelect;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
@@ -91,7 +91,7 @@ public class CTLuMedianAlgorithm<N> extends AbstractNeighborhoodOutlier<N> {
*/
public OutlierResult run(Relation<N> nrel, Relation<? extends NumberVector<?, ?>> relation) {
final NeighborSetPredicate npred = getNeighborSetPredicateFactory().instantiate(nrel);
- WritableDataStore<Double> scores = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, Double.class);
+ WritableDoubleDataStore scores = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC);
MeanVariance mv = new MeanVariance();
for(DBID id : relation.iterDBIDs()) {
@@ -110,15 +110,14 @@ public class CTLuMedianAlgorithm<N> extends AbstractNeighborhoodOutlier<N> {
}
if(c > 0) {
- // Note: only use up to c-1, since we may have used a too big array
- median = QuickSelect.median(fi, 0, c - 1);
+ median = QuickSelect.median(fi, 0, c);
}
else {
median = relation.get(id).doubleValue(1);
}
}
double h = relation.get(id).doubleValue(1) - median;
- scores.put(id, h);
+ scores.putDouble(id, h);
mv.put(h);
}
@@ -127,9 +126,9 @@ public class CTLuMedianAlgorithm<N> extends AbstractNeighborhoodOutlier<N> {
final double stddev = mv.getNaiveStddev();
DoubleMinMax minmax = new DoubleMinMax();
for(DBID id : relation.iterDBIDs()) {
- double score = Math.abs((scores.get(id) - mean) / stddev);
+ double score = Math.abs((scores.doubleValue(id) - mean) / stddev);
minmax.put(score);
- scores.put(id, score);
+ scores.putDouble(id, score);
}
Relation<Double> scoreResult = new MaterializedRelation<Double>("MO", "Median-outlier", TypeUtil.DOUBLE, scores, relation.getDBIDs());
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 649511eb..cbf61c38 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) 2011
+ Copyright (C) 2012
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.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.WritableDataStore;
+import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
@@ -39,11 +40,11 @@ import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
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.math.statistics.QuickSelect;
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.DatabaseUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.QuickSelect;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
/**
@@ -61,7 +62,7 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
* <p>
* Implementation note: attribute standardization is not used; this is
* equivalent to using the
- * {@link de.lmu.ifi.dbs.elki.datasource.filter.AttributeWiseVarianceNormalization
+ * {@link de.lmu.ifi.dbs.elki.datasource.filter.normalization.AttributeWiseVarianceNormalization
* AttributeWiseVarianceNormalization} filter.
* </p>
*
@@ -141,14 +142,12 @@ public class CTLuMedianMultipleAttributes<N, O extends NumberVector<?, ?>> exten
Matrix cmati = covmaker.destroyToSampleMatrix().inverse();
DoubleMinMax minmax = new DoubleMinMax();
- WritableDataStore<Double> scores = DataStoreUtil.makeStorage(attributes.getDBIDs(), DataStoreFactory.HINT_STATIC, Double.class);
+ WritableDoubleDataStore scores = DataStoreUtil.makeDoubleStorage(attributes.getDBIDs(), DataStoreFactory.HINT_STATIC);
for(DBID id : attributes.iterDBIDs()) {
Vector temp = deltas.get(id).minus(mean);
- final Vector res = temp.transposeTimes(cmati).times(temp);
- assert (res.getDimensionality() == 1);
- double score = res.get(0);
+ final double score = temp.transposeTimesTimes(cmati, temp);
minmax.put(score);
- scores.put(id, score);
+ scores.putDouble(id, score);
}
Relation<Double> scoreResult = new MaterializedRelation<Double>("Median multiple attributes outlier", "median-outlier", TypeUtil.DOUBLE, scores, attributes.getDBIDs());
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 6780fcc9..9f19757d 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) 2011
+ Copyright (C) 2012
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.data.type.TypeUtil;
import de.lmu.ifi.dbs.elki.data.type.VectorFieldTypeInformation;
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.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
@@ -103,7 +103,7 @@ public class CTLuMoranScatterplotOutlier<N> extends AbstractNeighborhoodOutlier<
}
DoubleMinMax minmax = new DoubleMinMax();
- WritableDataStore<Double> scores = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, Double.class);
+ WritableDoubleDataStore scores = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC);
// calculate normalized attribute values
// calculate neighborhood average of normalized attribute values.
@@ -132,7 +132,7 @@ public class CTLuMoranScatterplotOutlier<N> extends AbstractNeighborhoodOutlier<
// Note: in the original moran scatterplot, any object with a score < 0 would be an outlier.
final double score = Math.max(-globalZ * localZ, 0);
minmax.put(score);
- scores.put(id, score);
+ scores.putDouble(id, score);
}
Relation<Double> scoreResult = new MaterializedRelation<Double>("MoranOutlier", "Moran Scatterplot Outlier", TypeUtil.DOUBLE, scores, relation.getDBIDs());
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 0fe65fee..a6425d43 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
@@ -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) 2011
+Copyright (C) 2012
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.data.type.VectorFieldTypeInformation;
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.datastore.WritableDoubleDataStore;
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.DBIDUtil;
@@ -196,13 +197,13 @@ public class CTLuRandomWalkEC<N, D extends NumberDistance<D, ?>> extends Abstrac
for(int i = 0; i < ids.size(); i++) {
DBID id = ids.get(i);
// Note: matrix times ith unit vector = ith column
- Vector sim = E.getColumnVector(i);
+ Vector sim = E.getCol(i);
similarityVectors.put(id, sim);
}
E = null;
// compute the relevance scores between specified Object and its neighbors
DoubleMinMax minmax = new DoubleMinMax();
- WritableDataStore<Double> scores = DataStoreUtil.makeStorage(spatial.getDBIDs(), DataStoreFactory.HINT_STATIC, Double.class);
+ WritableDoubleDataStore scores = DataStoreUtil.makeDoubleStorage(spatial.getDBIDs(), DataStoreFactory.HINT_STATIC);
for(int i = 0; i < ids.size(); i++) {
DBID id = ids.get(i);
double gmean = 1.0;
@@ -211,13 +212,13 @@ public class CTLuRandomWalkEC<N, D extends NumberDistance<D, ?>> extends Abstrac
if(id.equals(n)) {
continue;
}
- double sim = MathUtil.cosineSimilarity(similarityVectors.get(id), similarityVectors.get(n));
+ double sim = MathUtil.angle(similarityVectors.get(id), similarityVectors.get(n));
gmean *= sim;
cnt++;
}
final double score = Math.pow(gmean, 1.0 / cnt);
minmax.put(score);
- scores.put(id, score);
+ scores.putDouble(id, score);
}
Relation<Double> scoreResult = new MaterializedRelation<Double>("randomwalkec", "RandomWalkEC", TypeUtil.DOUBLE, scores, relation.getDBIDs());
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 d18e4130..8e4ab32c 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) 2011
+ Copyright (C) 2012
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.data.type.TypeUtil;
import de.lmu.ifi.dbs.elki.data.type.VectorFieldTypeInformation;
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.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
@@ -97,7 +97,7 @@ public class CTLuScatterplotOutlier<N> extends AbstractNeighborhoodOutlier<N> {
*/
public OutlierResult run(Relation<N> nrel, Relation<? extends NumberVector<?, ?>> relation) {
final NeighborSetPredicate npred = getNeighborSetPredicateFactory().instantiate(nrel);
- WritableDataStore<Double> means = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_TEMP, Double.class);
+ WritableDoubleDataStore means = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_TEMP);
// Calculate average of neighborhood for each object and perform a linear
// regression using the covariance matrix
@@ -122,7 +122,7 @@ public class CTLuScatterplotOutlier<N> extends AbstractNeighborhoodOutlier<N> {
m = local;
}
// Store the mean for the score calculation
- means.put(id, m);
+ means.putDouble(id, m);
covm.put(new double[] { local, m });
}
// Finalize covariance matrix, compute linear regression
@@ -137,13 +137,13 @@ public class CTLuScatterplotOutlier<N> extends AbstractNeighborhoodOutlier<N> {
}
// calculate mean and variance for error
- WritableDataStore<Double> scores = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, Double.class);
+ WritableDoubleDataStore scores = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC);
MeanVariance mv = new MeanVariance();
for(DBID id : relation.iterDBIDs()) {
// Compute the error from the linear regression
double y_i = relation.get(id).doubleValue(1);
- double e = means.get(id) - (slope * y_i + inter);
- scores.put(id, e);
+ double e = means.doubleValue(id) - (slope * y_i + inter);
+ scores.putDouble(id, e);
mv.put(e);
}
@@ -153,9 +153,9 @@ public class CTLuScatterplotOutlier<N> extends AbstractNeighborhoodOutlier<N> {
final double mean = mv.getMean();
final double variance = mv.getNaiveStddev();
for(DBID id : relation.iterDBIDs()) {
- double score = Math.abs((scores.get(id) - mean) / variance);
+ double score = Math.abs((scores.doubleValue(id) - mean) / variance);
minmax.put(score);
- scores.put(id, score);
+ scores.putDouble(id, score);
}
}
// build representation
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 304203db..573e1526 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) 2011
+ Copyright (C) 2012
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.data.type.VectorFieldTypeInformation;
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.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
@@ -99,7 +99,7 @@ public class CTLuZTestOutlier<N> extends AbstractNeighborhoodOutlier<N> {
*/
public OutlierResult run(Database database, Relation<N> nrel, Relation<? extends NumberVector<?, ?>> relation) {
final NeighborSetPredicate npred = getNeighborSetPredicateFactory().instantiate(nrel);
- WritableDataStore<Double> scores = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, Double.class);
+ WritableDoubleDataStore scores = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC);
MeanVariance zmv = new MeanVariance();
for(DBID id : relation.iterDBIDs()) {
@@ -121,16 +121,16 @@ public class CTLuZTestOutlier<N> extends AbstractNeighborhoodOutlier<N> {
else {
localdiff = 0.0;
}
- scores.put(id, localdiff);
+ scores.putDouble(id, localdiff);
zmv.put(localdiff);
}
// Normalize scores using mean and variance
DoubleMinMax minmax = new DoubleMinMax();
for(DBID id : relation.iterDBIDs()) {
- double score = Math.abs(scores.get(id) - zmv.getMean()) / zmv.getSampleStddev();
+ double score = Math.abs(scores.doubleValue(id) - zmv.getMean()) / zmv.getSampleStddev();
minmax.put(score);
- scores.put(id, score);
+ scores.putDouble(id, score);
}
// Wrap result
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 af8762e0..e69d46d4 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) 2011
+ Copyright (C) 2012
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.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.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
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.MaterializedRelation;
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.math.DoubleMinMax;
-import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
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;
@@ -96,7 +96,7 @@ public class SLOM<N, O, D extends NumberDistance<D, ?>> extends AbstractDistance
final NeighborSetPredicate npred = getNeighborSetPredicateFactory().instantiate(spatial);
DistanceQuery<O, D> distFunc = getNonSpatialDistanceFunction().instantiate(relation);
- WritableDataStore<Double> modifiedDistance = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP, Double.class);
+ WritableDoubleDataStore modifiedDistance = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP);
// calculate D-Tilde
for(DBID id : relation.iterDBIDs()) {
double sum = 0;
@@ -114,18 +114,18 @@ public class SLOM<N, O, D extends NumberDistance<D, ?>> extends AbstractDistance
maxDist = Math.max(maxDist, dist);
}
if(cnt > 1) {
- modifiedDistance.put(id, ((sum - maxDist) / (cnt - 1)));
+ modifiedDistance.putDouble(id, ((sum - maxDist) / (cnt - 1)));
}
else {
// Use regular distance when the d-tilde trick is undefined.
// Note: this can be 0 when there were no neighbors.
- modifiedDistance.put(id, maxDist);
+ modifiedDistance.putDouble(id, maxDist);
}
}
// Second step - compute actual SLOM values
DoubleMinMax slomminmax = new DoubleMinMax();
- WritableDataStore<Double> sloms = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, Double.class);
+ WritableDoubleDataStore sloms = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC);
for(DBID id : relation.iterDBIDs()) {
double sum = 0;
@@ -136,18 +136,18 @@ public class SLOM<N, O, D extends NumberDistance<D, ?>> extends AbstractDistance
if(neighbor.equals(id)) {
continue;
}
- sum += modifiedDistance.get(neighbor);
+ sum += modifiedDistance.doubleValue(neighbor);
cnt++;
}
double slom;
if(cnt > 0) {
// With and without the object itself:
- double avgPlus = (sum + modifiedDistance.get(id)) / (cnt + 1);
+ double avgPlus = (sum + modifiedDistance.doubleValue(id)) / (cnt + 1);
double avg = sum / cnt;
double beta = 0;
for(DBID neighbor : neighbors) {
- final double dist = modifiedDistance.get(neighbor).doubleValue();
+ final double dist = modifiedDistance.doubleValue(neighbor);
if(dist > avgPlus) {
beta += 1;
}
@@ -157,7 +157,7 @@ public class SLOM<N, O, D extends NumberDistance<D, ?>> extends AbstractDistance
}
// Include object itself
if(!neighbors.contains(id)) {
- final double dist = modifiedDistance.get(id).doubleValue();
+ final double dist = modifiedDistance.doubleValue(id);
if(dist > avgPlus) {
beta += 1;
}
@@ -176,13 +176,13 @@ public class SLOM<N, O, D extends NumberDistance<D, ?>> extends AbstractDistance
}
beta = beta / (1 + avg);
- slom = beta * modifiedDistance.get(id);
+ slom = beta * modifiedDistance.doubleValue(id);
}
else {
// No neighbors to compare to - no score.
slom = 0.0;
}
- sloms.put(id, slom);
+ sloms.putDouble(id, slom);
slomminmax.put(slom);
}
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 e3ede8bb..abc3c481 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) 2011
+Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,16 +28,16 @@ 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.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
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.MaterializedRelation;
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.math.DoubleMinMax;
-import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
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;
@@ -103,8 +103,8 @@ public class SOF<N, O, D extends NumberDistance<D, ?>> extends AbstractDistanceB
final NeighborSetPredicate npred = getNeighborSetPredicateFactory().instantiate(spatial);
DistanceQuery<O, D> distFunc = getNonSpatialDistanceFunction().instantiate(relation);
- WritableDataStore<Double> lrds = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_TEMP | DataStoreFactory.HINT_HOT, Double.class);
- WritableDataStore<Double> lofs = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, Double.class);
+ WritableDoubleDataStore lrds = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_TEMP | DataStoreFactory.HINT_HOT);
+ WritableDoubleDataStore lofs = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC);
DoubleMinMax lofminmax = new DoubleMinMax();
// Compute densities
@@ -118,7 +118,7 @@ public class SOF<N, O, D extends NumberDistance<D, ?>> extends AbstractDistanceB
if (Double.isNaN(lrd)) {
lrd = 0;
}
- lrds.put(id, lrd);
+ lrds.putDouble(id, lrd);
}
// Compute density quotients
@@ -126,14 +126,14 @@ public class SOF<N, O, D extends NumberDistance<D, ?>> extends AbstractDistanceB
DBIDs neighbors = npred.getNeighborDBIDs(id);
double avg = 0;
for(DBID n : neighbors) {
- avg += lrds.get(n);
+ avg += lrds.doubleValue(n);
}
- final double lrd = (avg / neighbors.size()) / lrds.get(id);
+ final double lrd = (avg / neighbors.size()) / lrds.doubleValue(id);
if (!Double.isNaN(lrd)) {
- lofs.put(id, lrd);
+ lofs.putDouble(id, lrd);
lofminmax.put(lrd);
} else {
- lofs.put(id, 0.0);
+ lofs.putDouble(id, 0.0);
}
}
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 d99ecc99..75700bca 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) 2011
+Copyright (C) 2012
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.data.type.VectorFieldTypeInformation;
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.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
@@ -41,11 +41,11 @@ 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.Mean;
-import de.lmu.ifi.dbs.elki.math.statistics.QuickSelect;
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.DatabaseUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.QuickSelect;
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;
@@ -112,8 +112,8 @@ public class TrimmedMeanApproach<N> extends AbstractNeighborhoodOutlier<N> {
assert (DatabaseUtil.dimensionality(relation) == 1) : "TrimmedMean can only process one-dimensional data sets.";
final NeighborSetPredicate npred = getNeighborSetPredicateFactory().instantiate(nrel);
- WritableDataStore<Double> errors = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_TEMP, Double.class);
- WritableDataStore<Double> scores = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, Double.class);
+ WritableDoubleDataStore errors = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_TEMP);
+ WritableDoubleDataStore scores = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC);
FiniteProgress progress = logger.isVerbose() ? new FiniteProgress("Computing trimmed means", relation.size(), logger) : null;
for(DBID id : relation.iterDBIDs()) {
@@ -142,7 +142,7 @@ public class TrimmedMeanApproach<N> extends AbstractNeighborhoodOutlier<N> {
tm = relation.get(id).doubleValue(1);
}
// Error: deviation from trimmed mean
- errors.put(id, relation.get(id).doubleValue(1) - tm);
+ errors.putDouble(id, relation.get(id).doubleValue(1) - tm);
if(progress != null) {
progress.incrementProcessed(logger);
@@ -162,7 +162,7 @@ public class TrimmedMeanApproach<N> extends AbstractNeighborhoodOutlier<N> {
{
int i = 0;
for(DBID id : relation.iterDBIDs()) {
- ei[i] = errors.get(id);
+ ei[i] = errors.doubleValue(id);
i++;
}
}
@@ -181,8 +181,8 @@ public class TrimmedMeanApproach<N> extends AbstractNeighborhoodOutlier<N> {
// calculate score
DoubleMinMax minmax = new DoubleMinMax();
for(DBID id : relation.iterDBIDs()) {
- double score = Math.abs(errors.get(id)) * 0.6745 / median_dev_from_median;
- scores.put(id, score);
+ double score = Math.abs(errors.doubleValue(id)) * 0.6745 / median_dev_from_median;
+ scores.putDouble(id, score);
minmax.put(score);
}
//
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 df28de24..5898b053 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) 2011
+ Copyright (C) 2012
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 640c30fe..9ee92d35 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) 2011
+ Copyright (C) 2012
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.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.HashSetModifiableDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.logging.Logging;
@@ -132,15 +133,15 @@ public class ExtendedNeighborhood extends AbstractPrecomputedNeighborhood {
// Expand multiple steps
FiniteProgress progress = logger.isVerbose() ? new FiniteProgress("Expanding neighborhoods", database.size(), logger) : null;
for(final DBID id : database.iterDBIDs()) {
- ModifiableDBIDs res = DBIDUtil.newHashSet(id);
+ HashSetModifiableDBIDs res = DBIDUtil.newHashSet(id);
DBIDs todo = id;
for(int i = 0; i < steps; i++) {
ModifiableDBIDs ntodo = DBIDUtil.newHashSet();
for(final DBID oid : todo) {
DBIDs add = innerinst.getNeighborDBIDs(oid);
if(add != null) {
- for (DBID nid: add) {
- if (res.contains(add)) {
+ for(DBID nid : add) {
+ if(res.contains(nid)) {
continue;
}
ntodo.add(nid);
@@ -148,7 +149,7 @@ public class ExtendedNeighborhood extends AbstractPrecomputedNeighborhood {
}
}
}
- if (ntodo.size() == 0) {
+ if(ntodo.size() == 0) {
continue;
}
todo = ntodo;
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 789a63e7..f2586e2e 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) 2011
+ Copyright (C) 2012
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/NeighborSetPredicate.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/NeighborSetPredicate.java
index 6683b3fd..3a6d0e28 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) 2011
+ Copyright (C) 2012
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 fa878778..f5ea7e15 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) 2011
+Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -22,8 +22,6 @@ You should 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.type.TypeInformation;
import de.lmu.ifi.dbs.elki.database.QueryUtil;
import de.lmu.ifi.dbs.elki.database.datastore.DataStore;
@@ -36,6 +34,7 @@ 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.DistanceResultPair;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
+import de.lmu.ifi.dbs.elki.database.query.knn.KNNResult;
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;
@@ -121,7 +120,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(DBID id : relation.iterDBIDs()) {
- List<DistanceResultPair<D>> neighbors = knnQuery.getKNNForDBID(id, k);
+ KNNResult<D> neighbors = knnQuery.getKNNForDBID(id, k);
ArrayModifiableDBIDs neighbours = DBIDUtil.newArray(neighbors.size());
for(DistanceResultPair<D> dpair : neighbors) {
neighbours.add(dpair.getDBID());
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 eb490642..47ca5ad2 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) 2011
+Copyright (C) 2012
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 b2f70e16..52fc2c46 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) 2011
+ Copyright (C) 2012
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/UnweightedNeighborhoodAdapter.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/weighted/UnweightedNeighborhoodAdapter.java
index 0927c026..4378aa2e 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) 2011
+ Copyright (C) 2012
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/WeightedNeighborSetPredicate.java b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/spatial/neighborhood/weighted/WeightedNeighborSetPredicate.java
index d0cdfa9c..b147935a 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) 2011
+ Copyright (C) 2012
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 ff82dbee..39165cfd 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) 2011
+Copyright (C) 2012
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 df50e592..13bf3f25 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) 2011
+Copyright (C) 2012
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 62f083fb..86730404 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) 2011
+ Copyright (C) 2012
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.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.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
@@ -111,7 +111,7 @@ public class ByLabelOutlier extends AbstractAlgorithm<OutlierResult> implements
* @return Result
*/
public OutlierResult run(Relation<?> relation) {
- WritableDataStore<Double> scores = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT, Double.class);
+ WritableDoubleDataStore scores = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT);
for(DBID id : relation.iterDBIDs()) {
String label = relation.get(id).toString();
final double score;
@@ -120,7 +120,7 @@ public class ByLabelOutlier extends AbstractAlgorithm<OutlierResult> implements
} else {
score = 0.0;
}
- scores.put(id, score);
+ scores.putDouble(id, score);
}
Relation<Double> scoreres = new MaterializedRelation<Double>("By label outlier scores", "label-outlier", TypeUtil.DOUBLE, scores, relation.getDBIDs());
OutlierScoreMeta meta = new ProbabilisticOutlierScore();
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 ff93e0ed..509e35e9 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) 2011
+ Copyright (C) 2012
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.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.WritableDataStore;
+import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
@@ -69,9 +69,9 @@ public class TrivialAllOutlier extends AbstractAlgorithm<OutlierResult> implemen
* @return Result
*/
public OutlierResult run(Relation<?> relation) {
- WritableDataStore<Double> scores = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT, Double.class);
+ WritableDoubleDataStore scores = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT);
for(DBID id : relation.iterDBIDs()) {
- scores.put(id, 1.0);
+ scores.putDouble(id, 1.0);
}
Relation<Double> scoreres = new MaterializedRelation<Double>("Trivial all-outlier score", "all-outlier", TypeUtil.DOUBLE, scores, relation.getDBIDs());
OutlierScoreMeta meta = new ProbabilisticOutlierScore();
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
new file mode 100644
index 00000000..db40ff30
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/outlier/trivial/TrivialGeneratedOutlier.java
@@ -0,0 +1,212 @@
+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 java.util.HashSet;
+
+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.model.Model;
+import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.GeneratorSingleCluster;
+import de.lmu.ifi.dbs.elki.data.type.NoSupportedDataTypeException;
+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.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.DBID;
+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.linearalgebra.Vector;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.ChiSquaredDistribution;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.Distribution;
+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.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;
+
+/**
+ * Extract outlier score from the model the objects were generated by.
+ *
+ * This algorithm can only be applied to data that was freshly generated, to the
+ * generator model information is still available.
+ *
+ * @author Erich Schubert
+ */
+public class TrivialGeneratedOutlier extends AbstractAlgorithm<OutlierResult> implements OutlierAlgorithm {
+ /**
+ * Class logger
+ */
+ private static final Logging logger = Logging.getLogger(TrivialGeneratedOutlier.class);
+
+ /**
+ * Expected share of outliers
+ */
+ public static final OptionID EXPECT_ID = OptionID.getOrCreateOptionID("modeloutlier.expect", "Expected amount of outliers, for making the scores more intuitive.");
+
+ /**
+ * Expected share of outliers.
+ */
+ double expect = 0.01;
+
+ /**
+ * Constructor.
+ *
+ * @param expect Expected share of outliers
+ */
+ public TrivialGeneratedOutlier(double expect) {
+ super();
+ this.expect = expect;
+ }
+
+ /**
+ * Constructor.
+ */
+ public TrivialGeneratedOutlier() {
+ this(0.01);
+ }
+
+ @Override
+ public TypeInformation[] getInputTypeRestriction() {
+ return TypeUtil.array(TypeUtil.NUMBER_VECTOR_FIELD, new SimpleTypeInformation<Model>(Model.class), TypeUtil.GUESSED_LABEL);
+ }
+
+ @Override
+ public OutlierResult run(Database database) throws IllegalStateException {
+ Relation<NumberVector<?, ?>> vecs = database.getRelation(TypeUtil.NUMBER_VECTOR_FIELD);
+ Relation<Model> models = database.getRelation(new SimpleTypeInformation<Model>(Model.class));
+ // Prefer a true class label
+ try {
+ Relation<?> relation = database.getRelation(TypeUtil.CLASSLABEL);
+ return run(models, vecs, relation);
+ }
+ catch(NoSupportedDataTypeException e) {
+ // Otherwise, try any labellike.
+ return run(models, vecs, database.getRelation(TypeUtil.GUESSED_LABEL));
+ }
+ }
+
+ /**
+ * Run the algorithm
+ *
+ * @param models Model relation
+ * @param vecs Vector relation
+ * @param labels Label relation
+ * @return Outlier result
+ */
+ 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(DBID id : models.iterDBIDs()) {
+ Model model = models.get(id);
+ if(model instanceof GeneratorSingleCluster) {
+ generators.add((GeneratorSingleCluster) model);
+ }
+ }
+ if(generators.size() == 0) {
+ logger.warning("No generator models found for dataset - all points will be considered outliers.");
+ }
+
+ for(DBID id : models.iterDBIDs()) {
+ double score = 0.0;
+ // Convert to a math vector
+ Vector v = vecs.get(id).getColumnVector();
+ for(GeneratorSingleCluster gen : generators) {
+ Vector tv = v;
+ // Transform backwards
+ 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++) {
+ Distribution dist = gen.getDistribution(i);
+ if(dist instanceof NormalDistribution) {
+ NormalDistribution d = (NormalDistribution) dist;
+ double delta = (tv.get(i) - d.getMean()) / d.getStddev();
+ lensq += delta * delta;
+ norm += 1;
+ }
+ }
+ if(norm > 0) {
+ // The squared distances are ChiSquared distributed
+ score = Math.max(score, 1 - ChiSquaredDistribution.cdf(lensq, norm));
+ }
+ }
+ // score inversion.
+ score = expect / (expect + score);
+ // adjust to 0 to 1 range:
+ score = (score - minscore) / (1 - minscore);
+ scores.putDouble(id, score);
+ }
+ Relation<Double> scoreres = new MaterializedRelation<Double>("Model outlier scores", "model-outlier", TypeUtil.DOUBLE, scores, models.getDBIDs());
+ OutlierScoreMeta meta = new ProbabilisticOutlierScore(0., 1.);
+ return new OutlierResult(meta, scoreres);
+ }
+
+ @Override
+ protected Logging getLogger() {
+ return logger;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ /**
+ * 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)) {
+ expect = expectP.getValue();
+ }
+ }
+
+ @Override
+ protected TrivialGeneratedOutlier makeInstance() {
+ 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 f3ae7e72..cff2ad2c 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) 2011
+ Copyright (C) 2012
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.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.WritableDataStore;
+import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
@@ -69,9 +69,9 @@ public class TrivialNoOutlier extends AbstractAlgorithm<OutlierResult> implement
* @return Result
*/
public OutlierResult run(Relation<?> relation) throws IllegalStateException {
- WritableDataStore<Double> scores = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT, Double.class);
+ WritableDoubleDataStore scores = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT);
for(DBID id : relation.iterDBIDs()) {
- scores.put(id, 0.0);
+ scores.putDouble(id, 0.0);
}
Relation<Double> scoreres = new MaterializedRelation<Double>("Trivial no-outlier score", "no-outlier", TypeUtil.DOUBLE, scores, relation.getDBIDs());
OutlierScoreMeta meta = new ProbabilisticOutlierScore();
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 fbae60dc..d49d3565 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) 2011
+Copyright (C) 2012
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 0dfbc8c1..c18579f0 100644
--- a/src/de/lmu/ifi/dbs/elki/algorithm/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/package-info.java
@@ -10,7 +10,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2011
+Copyright (C) 2012
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
new file mode 100644
index 00000000..1c74621b
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/algorithm/statistics/AveragePrecisionAtK.java
@@ -0,0 +1,235 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.Collection;
+import java.util.Iterator;
+
+import de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm;
+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;
+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.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.query.DistanceResultPair;
+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.KNNResult;
+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.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.GreaterEqualConstraint;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.IntervalConstraint;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.IntervalConstraint.IntervalBoundary;
+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.LongParameter;
+
+/**
+ * Evaluate a distance functions performance by computing the average precision
+ * at k, when ranking the objects by distance.
+ *
+ * @author Erich Schubert
+ * @param <V> Vector type
+ * @param <D> Distance type
+ */
+public class AveragePrecisionAtK<V extends Object, D extends NumberDistance<D, ?>> extends AbstractDistanceBasedAlgorithm<V, D, CollectionResult<DoubleVector>> {
+ /**
+ * The logger for this class.
+ */
+ private static final Logging logger = Logging.getLogger(AveragePrecisionAtK.class);
+
+ /**
+ * 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;
+
+ /**
+ * Constructor.
+ *
+ * @param distanceFunction Distance function
+ * @param sampling Sampling rate
+ * @param seed Random sampling seed (may be null)
+ */
+ public AveragePrecisionAtK(DistanceFunction<? super V, D> distanceFunction, int k, double sampling, Long seed) {
+ super(distanceFunction);
+ this.k = k;
+ this.sampling = sampling;
+ this.seed = seed;
+ }
+
+ @Override
+ public HistogramResult<DoubleVector> run(Database database) throws IllegalStateException {
+ final Relation<V> relation = database.getRelation(getInputTypeRestriction()[0]);
+ final Relation<Object> lrelation = database.getRelation(getInputTypeRestriction()[1]);
+ final DistanceQuery<V, D> distQuery = database.getDistanceQuery(relation, getDistanceFunction());
+ final KNNQuery<V, D> knnQuery = database.getKNNQuery(distQuery, k);
+
+ MeanVariance[] mvs = MeanVariance.newArray(k);
+
+ final DBIDs ids;
+ if (sampling < 1.0) {
+ int size = Math.max(1, (int) (sampling * relation.size()));
+ ids = DBIDUtil.randomSample(relation.getDBIDs(), size, seed);
+ } else {
+ ids = relation.getDBIDs();
+ }
+
+ if(logger.isVerbose()) {
+ logger.verbose("Processing points...");
+ }
+ FiniteProgress objloop = logger.isVerbose() ? new FiniteProgress("Computing nearest neighbors", ids.size(), logger) : null;
+ // sort neighbors
+ for(DBID id : ids) {
+ KNNResult<D> knn = knnQuery.getKNNForDBID(id, k);
+ Object label = lrelation.get(id);
+
+ int positive = 0;
+ Iterator<DistanceResultPair<D>> ri = knn.iterator();
+ for(int i = 0; i < k && ri.hasNext(); i++) {
+ DBID nid = ri.next().getDBID();
+ Object olabel = lrelation.get(nid);
+ if(label == null) {
+ if(olabel == null) {
+ positive += 1;
+ }
+ }
+ else {
+ if(label.equals(olabel)) {
+ positive += 1;
+ }
+ }
+ final double precision = positive / (double) (i + 1);
+ mvs[i].put(precision);
+ }
+ if(objloop != null) {
+ objloop.incrementProcessed(logger);
+ }
+ }
+ if(objloop != null) {
+ objloop.ensureCompleted(logger);
+ }
+ // Collections.sort(results);
+
+ // Transform Histogram into a Double Vector array.
+ Collection<DoubleVector> res = new ArrayList<DoubleVector>(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);
+ }
+
+ @Override
+ public TypeInformation[] getInputTypeRestriction() {
+ return TypeUtil.array(getDistanceFunction().getInputTypeRestriction(), TypeUtil.GUESSED_LABEL);
+ }
+
+ @Override
+ protected Logging getLogger() {
+ return logger;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer<V extends NumberVector<V, ?>, D extends NumberDistance<D, ?>> extends AbstractDistanceBasedAlgorithm.Parameterizer<V, D> {
+ /**
+ * Parameter k to compute the average precision at.
+ */
+ private static final OptionID K_ID = OptionID.getOrCreateOptionID("avep.k", "K to compute the average precision at.");
+
+ /**
+ * Parameter to enable sampling
+ */
+ public static final OptionID SAMPLING_ID = OptionID.getOrCreateOptionID("avep.sampling", "Relative amount of object to sample.");
+
+ /**
+ * Parameter to control the sampling random seed
+ */
+ public static final OptionID SEED_ID = OptionID.getOrCreateOptionID("avep.sampling-seed", "Random seed for deterministic sampling.");
+
+ /**
+ * Neighborhood size
+ */
+ protected int k = 20;
+
+ /**
+ * Relative amount of data to sample
+ */
+ protected double sampling = 1.0;
+
+ /**
+ * Random sampling seed.
+ */
+ protected Long seed = null;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ final IntParameter kP = new IntParameter(K_ID, new GreaterEqualConstraint(2));
+ if(config.grab(kP)) {
+ k = kP.getValue();
+ }
+ final DoubleParameter samplingP = new DoubleParameter(SAMPLING_ID, new IntervalConstraint(0.0, IntervalBoundary.OPEN, 1.0, IntervalBoundary.CLOSE), true);
+ if (config.grab(samplingP)) {
+ sampling = samplingP.getValue();
+ }
+ final LongParameter seedP = new LongParameter(SEED_ID, true);
+ if (config.grab(seedP)) {
+ seed = seedP.getValue();
+ }
+ }
+
+ @Override
+ protected AveragePrecisionAtK<V, D> makeInstance() {
+ return new AveragePrecisionAtK<V, D>(distanceFunction, k, sampling, seed);
+ }
+ }
+} \ 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 33201b67..78bbf5f4 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -49,10 +49,10 @@ 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.logging.progress.StepProgress;
-import de.lmu.ifi.dbs.elki.math.AggregatingHistogram;
import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
-import de.lmu.ifi.dbs.elki.math.FlexiHistogram;
import de.lmu.ifi.dbs.elki.math.MeanVariance;
+import de.lmu.ifi.dbs.elki.math.histograms.AggregatingHistogram;
+import de.lmu.ifi.dbs.elki.math.histograms.FlexiHistogram;
import de.lmu.ifi.dbs.elki.result.CollectionResult;
import de.lmu.ifi.dbs.elki.result.HistogramResult;
import de.lmu.ifi.dbs.elki.utilities.documentation.Description;
@@ -65,6 +65,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameteriz
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.Parameter;
+import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleObjPair;
import de.lmu.ifi.dbs.elki.utilities.pairs.FCPair;
import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
@@ -249,7 +250,7 @@ public class DistanceStatisticsWithClasses<O, D extends NumberDistance<D, ?>> ex
// count the number of samples we have in the data
long inum = 0;
long onum = 0;
- for(Pair<Double, Pair<Long, Long>> ppair : histogram) {
+ for(DoubleObjPair<Pair<Long, Long>> ppair : histogram) {
inum += ppair.getSecond().getFirst();
onum += ppair.getSecond().getSecond();
}
@@ -258,12 +259,12 @@ public class DistanceStatisticsWithClasses<O, D extends NumberDistance<D, ?>> ex
assert (bnum == relation.size() * (relation.size() - 1));
Collection<DoubleVector> binstat = new ArrayList<DoubleVector>(numbin);
- for(Pair<Double, Pair<Long, Long>> ppair : histogram) {
+ for(DoubleObjPair<Pair<Long, Long>> ppair : histogram) {
final double icof = (inum == 0) ? 0 : ((double) ppair.getSecond().getFirst()) / inum / histogram.getBinsize();
final double icaf = ((double) ppair.getSecond().getFirst()) / bnum / histogram.getBinsize();
final double ocof = (onum == 0) ? 0 : ((double) ppair.getSecond().getSecond()) / onum / histogram.getBinsize();
final double ocaf = ((double) ppair.getSecond().getSecond()) / bnum / histogram.getBinsize();
- DoubleVector row = new DoubleVector(new double[] { ppair.getFirst(), icof, icaf, ocof, ocaf });
+ DoubleVector row = new DoubleVector(new double[] { ppair.first, icof, icaf, ocof, ocaf });
binstat.add(row);
}
HistogramResult<DoubleVector> result = new HistogramResult<DoubleVector>("Distance Histogram", "distance-histogram", binstat);
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 58fb5b89..c1eb118d 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,7 +27,6 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
-import java.util.List;
import de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm;
import de.lmu.ifi.dbs.elki.algorithm.clustering.trivial.ByLabelClustering;
@@ -40,18 +39,18 @@ 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.DBID;
-import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
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.KNNResult;
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.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.AggregatingHistogram;
import de.lmu.ifi.dbs.elki.math.MathUtil;
import de.lmu.ifi.dbs.elki.math.MeanVariance;
+import de.lmu.ifi.dbs.elki.math.histograms.AggregatingHistogram;
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;
@@ -63,8 +62,8 @@ 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.pairs.DoubleObjPair;
import de.lmu.ifi.dbs.elki.utilities.pairs.FCPair;
-import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
/**
* Evaluate a distance function with respect to kNN queries. For each point, the
@@ -159,7 +158,7 @@ public class EvaluateRankingQuality<V extends NumberVector<V, ?>, D extends Numb
for(int ind = 0; ind < cmem.size(); ind++) {
DBID i1 = cmem.get(ind).getSecond();
- List<DistanceResultPair<D>> knn = knnQuery.getKNNForDBID(i1, relation.size());
+ KNNResult<D> knn = knnQuery.getKNNForDBID(i1, relation.size());
double result = ROC.computeROCAUCDistanceResult(relation.size(), clus, knn);
hist.aggregate(((double) ind) / clus.size(), result);
@@ -176,8 +175,8 @@ public class EvaluateRankingQuality<V extends NumberVector<V, ?>, D extends Numb
// Transform Histogram into a Double Vector array.
Collection<DoubleVector> res = new ArrayList<DoubleVector>(relation.size());
- for(Pair<Double, MeanVariance> pair : hist) {
- DoubleVector row = new DoubleVector(new double[] { pair.getFirst(), pair.getSecond().getCount(), pair.getSecond().getMean(), pair.getSecond().getSampleVariance() });
+ for(DoubleObjPair<MeanVariance> pair : hist) {
+ DoubleVector row = new DoubleVector(new double[] { pair.first, pair.getSecond().getCount(), pair.getSecond().getMean(), pair.getSecond().getSampleVariance() });
res.add(row);
}
return new HistogramResult<DoubleVector>("Ranking Quality Histogram", "ranking-histogram", res);
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 07e6795a..6d64dc55 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) 2011
+ Copyright (C) 2012
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.algorithm.statistics;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.List;
import de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm;
import de.lmu.ifi.dbs.elki.algorithm.clustering.trivial.ByLabelClustering;
@@ -36,17 +35,17 @@ 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.DBID;
-import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
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.KNNResult;
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.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.AggregatingHistogram;
import de.lmu.ifi.dbs.elki.math.MeanVariance;
+import de.lmu.ifi.dbs.elki.math.histograms.AggregatingHistogram;
import de.lmu.ifi.dbs.elki.result.CollectionResult;
import de.lmu.ifi.dbs.elki.result.HistogramResult;
import de.lmu.ifi.dbs.elki.utilities.documentation.Description;
@@ -55,7 +54,7 @@ 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.pairs.Pair;
+import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleObjPair;
/**
* Evaluate a distance function with respect to kNN queries. For each point, the
@@ -121,7 +120,7 @@ public class RankingQualityHistogram<O, D extends NumberDistance<D, ?>> extends
// sort neighbors
for(Cluster<?> clus : split) {
for(DBID i1 : clus.getIDs()) {
- List<DistanceResultPair<D>> knn = knnQuery.getKNNForDBID(i1, relation.size());
+ KNNResult<D> knn = knnQuery.getKNNForDBID(i1, relation.size());
double result = ROC.computeROCAUCDistanceResult(relation.size(), clus, knn);
mv.put(result);
@@ -138,8 +137,8 @@ public class RankingQualityHistogram<O, D extends NumberDistance<D, ?>> extends
// Transform Histogram into a Double Vector array.
Collection<DoubleVector> res = new ArrayList<DoubleVector>(relation.size());
- for(Pair<Double, Double> pair : hist) {
- DoubleVector row = new DoubleVector(new double[] { pair.getFirst(), pair.getSecond() });
+ for(DoubleObjPair<Double> pair : hist) {
+ DoubleVector row = new DoubleVector(new double[] { pair.first, pair.getSecond() });
res.add(row);
}
HistogramResult<DoubleVector> result = new HistogramResult<DoubleVector>("Ranking Quality Histogram", "ranking-histogram", res);
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 3928f01a..e706d586 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) 2011
+Copyright (C) 2012
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 c2f19ef5..2775c928 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -75,7 +75,7 @@ public abstract class AbstractApplication implements Parameterizable {
/**
* Information for citation and version.
*/
- public static final String INFORMATION = "ELKI Version 0.4 (2011, August)" + NEWLINE + NEWLINE + "published in:" + NEWLINE + "E. Achtert, A. Hettab, H.-P. Kriegel, E. Schubert, A. Zimek:" + NEWLINE + "Spatial Outlier Detection: Data, Algorithms, Visualizations." + NEWLINE + "In Proceedings of the 12th International Symposium on" + NEWLINE + "Spatial and Temporal Databases (SSTD), Minneapolis, MN, 2011." + NEWLINE;
+ public static final String INFORMATION = "ELKI Version 0.5.0~beta1 (2012, April)" + NEWLINE + NEWLINE + "published in:" + NEWLINE + "E. Achtert, S. Goldhofer, H.-P. Kriegel, E. Schubert, A. Zimek:" + NEWLINE + "Evaluation of Clusterings – Metrics and Visual Support." + NEWLINE + "In Proceedings of the 28th"+NEWLINE+"International Conference on Data Engineering (ICDE), Washington, DC, 2012." + NEWLINE;
/**
* Parameter that specifies the name of the output file.
diff --git a/src/de/lmu/ifi/dbs/elki/application/ComputeSingleColorHistogram.java b/src/de/lmu/ifi/dbs/elki/application/ComputeSingleColorHistogram.java
index 63fc5d63..e6fe5231 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -58,8 +58,15 @@ public class ComputeSingleColorHistogram extends AbstractApplication {
* Key: {@code -colorhist.in}
* </p>
*/
+ public static final OptionID INPUT_ID = OptionID.getOrCreateOptionID("colorhist.in", "Input image file for color histogram.");
- public static final OptionID INPUT_ID = OptionID.getOrCreateOptionID("colorhist.in", "Input image for color histograms.");
+ /**
+ * Parameter that specifies the name of the mask input file.
+ * <p>
+ * Key: {@code -colorhist.mask}
+ * </p>
+ */
+ public static final OptionID MASK_ID = OptionID.getOrCreateOptionID("colorhist.mask", "Input mask image file.");
/**
* Class that will compute the actual histogram
@@ -72,23 +79,30 @@ public class ComputeSingleColorHistogram extends AbstractApplication {
private File inputFile;
/**
+ * Mask file.
+ */
+ private File maskFile;
+
+ /**
* Constructor.
*
* @param verbose Verbose flag
* @param histogrammaker Class to compute histograms with
* @param inputFile Input file
+ * @param maskFile Mask file
*/
- public ComputeSingleColorHistogram(boolean verbose, ComputeColorHistogram histogrammaker, File inputFile) {
+ public ComputeSingleColorHistogram(boolean verbose, ComputeColorHistogram histogrammaker, File inputFile, File maskFile) {
super(verbose);
this.histogrammaker = histogrammaker;
this.inputFile = inputFile;
+ this.maskFile = maskFile;
}
@Override
public void run() throws UnableToComplyException {
double[] hist;
try {
- hist = histogrammaker.computeColorHistogram(inputFile);
+ hist = histogrammaker.computeColorHistogram(inputFile, maskFile);
}
catch(IOException e) {
throw new UnableToComplyException(e);
@@ -114,6 +128,11 @@ public class ComputeSingleColorHistogram extends AbstractApplication {
*/
private File inputFile;
+ /**
+ * Mask file.
+ */
+ private File maskFile;
+
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
@@ -125,11 +144,15 @@ public class ComputeSingleColorHistogram extends AbstractApplication {
if(config.grab(inputP)) {
inputFile = inputP.getValue();
}
+ final FileParameter maskP = new FileParameter(MASK_ID, FileParameter.FileType.INPUT_FILE, true);
+ if(config.grab(maskP)) {
+ maskFile = maskP.getValue();
+ }
}
@Override
protected ComputeSingleColorHistogram makeInstance() {
- return new ComputeSingleColorHistogram(verbose, histogrammaker, inputFile);
+ return new ComputeSingleColorHistogram(verbose, histogrammaker, inputFile, maskFile);
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/application/GeneratorXMLSpec.java b/src/de/lmu/ifi/dbs/elki/application/GeneratorXMLSpec.java
index 373960a5..ccee6d39 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,22 +23,30 @@ package de.lmu.ifi.dbs.elki.application;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import gnu.trove.iterator.TIntIterator;
+import gnu.trove.list.TIntList;
+import gnu.trove.list.array.TIntArrayList;
+
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
-import java.util.List;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
-import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.GeneratorInterface;
-import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.GeneratorInterfaceDynamic;
+import de.lmu.ifi.dbs.elki.data.model.Model;
import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.GeneratorSingleCluster;
-import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.distribution.Distribution;
+import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
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.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;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
@@ -124,27 +132,52 @@ public class GeneratorXMLSpec extends AbstractApplication {
* @throws IOException thrown on write errors
*/
public void writeClusters(OutputStreamWriter outStream, MultipleObjectsBundle data) throws IOException {
- List<GeneratorInterface> clusters = generator.gen.getGenerators();
+ int modelcol = -1;
+ { // Find model column
+ for(int i = 0; i < data.metaLength(); i++) {
+ if(TypeUtil.MODEL.isAssignableFromType(data.meta(i))) {
+ modelcol = i;
+ break;
+ }
+ }
+ }
+ 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>();
+ { // Build a map from model to the actual objects
+ for(int i = 0; i < data.dataLength(); i++) {
+ Model model = (Model) data.data(i, modelcol);
+ TIntList modelids = modelMap.get(model);
+ if(modelids == null) {
+ models.add(model);
+ modelids = new TIntArrayList();
+ modelMap.put(model, modelids);
+ }
+ modelids.add(i);
+ }
+ }
// compute global discard values
int totalsize = 0;
int totaldisc = 0;
- assert (clusters.size() > 0);
- for(GeneratorInterface curclus : clusters) {
- totalsize = totalsize + curclus.getSize();
- if(curclus instanceof GeneratorSingleCluster) {
- totaldisc = totaldisc + ((GeneratorSingleCluster) curclus).getDiscarded();
+ for(Entry<Model, TIntList> ent : modelMap.entrySet()) {
+ totalsize = totalsize + ent.getValue().size();
+ if(ent.getKey() instanceof GeneratorSingleCluster) {
+ totaldisc = totaldisc + ((GeneratorSingleCluster) ent.getKey()).getDiscarded();
}
}
double globdens = (double) (totalsize + totaldisc) / totalsize;
outStream.write("########################################################" + LINE_SEPARATOR);
- outStream.write("## Number of clusters: " + clusters.size() + LINE_SEPARATOR);
- for(GeneratorInterface curclus : clusters) {
+ outStream.write("## Number of clusters: " + models.size() + LINE_SEPARATOR);
+ for(Model model : models) {
+ TIntList ids = modelMap.get(model);
outStream.write("########################################################" + LINE_SEPARATOR);
- outStream.write("## Cluster: " + curclus.getName() + LINE_SEPARATOR);
- outStream.write("########################################################" + LINE_SEPARATOR);
- outStream.write("## Size: " + curclus.getSize() + LINE_SEPARATOR);
- if(curclus instanceof GeneratorSingleCluster) {
- GeneratorSingleCluster cursclus = (GeneratorSingleCluster) curclus;
+ outStream.write("## Size: " + ids.size() + LINE_SEPARATOR);
+ if(model instanceof GeneratorSingleCluster) {
+ GeneratorSingleCluster cursclus = (GeneratorSingleCluster) model;
+ outStream.write("########################################################" + LINE_SEPARATOR);
+ outStream.write("## Cluster: " + cursclus.getName() + LINE_SEPARATOR);
Vector cmin = cursclus.getClipmin();
Vector cmax = cursclus.getClipmax();
if(cmin != null && cmax != null) {
@@ -152,27 +185,30 @@ public class GeneratorXMLSpec extends AbstractApplication {
}
outStream.write("## Density correction factor: " + cursclus.getDensityCorrection() + LINE_SEPARATOR);
outStream.write("## Generators:" + LINE_SEPARATOR);
- for(Distribution gen : cursclus.getAxes()) {
+ for(int i = 0; i < cursclus.getDim(); i++) {
+ Distribution gen = cursclus.getDistribution(i);
outStream.write("## " + gen.toString() + LINE_SEPARATOR);
}
- if(cursclus.getTrans() != null && cursclus.getTrans().getTransformation() != null) {
+ if(cursclus.getTransformation() != null && cursclus.getTransformation().getTransformation() != null) {
outStream.write("## Affine transformation matrix:" + LINE_SEPARATOR);
- outStream.write(FormatUtil.format(cursclus.getTrans().getTransformation(), "## ") + LINE_SEPARATOR);
+ outStream.write(FormatUtil.format(cursclus.getTransformation().getTransformation(), "## ") + LINE_SEPARATOR);
}
- }
- if(curclus instanceof GeneratorInterfaceDynamic) {
- GeneratorSingleCluster cursclus = (GeneratorSingleCluster) curclus;
outStream.write("## Discards: " + cursclus.getDiscarded() + " Retries left: " + cursclus.getRetries() + LINE_SEPARATOR);
double corf = /* cursclus.overweight */(double) (cursclus.getSize() + cursclus.getDiscarded()) / cursclus.getSize() / globdens;
outStream.write("## Density correction factor estimation: " + corf + LINE_SEPARATOR);
}
outStream.write("########################################################" + LINE_SEPARATOR);
- for(Vector p : curclus.getPoints()) {
- for(int i = 0; i < p.getRowDimensionality(); i++) {
- outStream.write(p.get(i) + " ");
+ for(TIntIterator iter = ids.iterator(); iter.hasNext();) {
+ int num = iter.next();
+ for(int c = 0; c < data.metaLength(); c++) {
+ if(c != modelcol) {
+ if (c > 0) {
+ outStream.write(" ");
+ }
+ outStream.write(data.data(num, c).toString());
+ }
}
- outStream.write(curclus.getName());
outStream.write(LINE_SEPARATOR);
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/application/KDDCLIApplication.java b/src/de/lmu/ifi/dbs/elki/application/KDDCLIApplication.java
index 59f75a7b..9184df58 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) 2011
+ Copyright (C) 2012
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/cache/CacheDoubleDistanceInOnDiskMatrix.java b/src/de/lmu/ifi/dbs/elki/application/cache/CacheDoubleDistanceInOnDiskMatrix.java
index 62080b51..c2e575be 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -119,7 +119,7 @@ public class CacheDoubleDistanceInOnDiskMatrix<O, D extends NumberDistance<D, ?>
DistanceQuery<O, D> distanceQuery = database.getDistanceQuery(relation, distance);
int matrixsize = 0;
- for(DBID id : distanceQuery.getRelation().iterDBIDs()) {
+ for(DBID id : relation.iterDBIDs()) {
matrixsize = Math.max(matrixsize, id.getIntegerID() + 1);
if(id.getIntegerID() < 0) {
throw new AbortException("OnDiskMatrixCache does not allow negative DBIDs.");
@@ -134,8 +134,8 @@ public class CacheDoubleDistanceInOnDiskMatrix<O, D extends NumberDistance<D, ?>
throw new AbortException("Error creating output matrix.", e);
}
- for(DBID id1 : distanceQuery.getRelation().iterDBIDs()) {
- for(DBID id2 : distanceQuery.getRelation().iterDBIDs()) {
+ for(DBID id1 : relation.iterDBIDs()) {
+ for(DBID id2 : relation.iterDBIDs()) {
if(id2.getIntegerID() >= id1.getIntegerID()) {
double d = distanceQuery.distance(id1, id2).doubleValue();
if(debugExtraCheckSymmetry) {
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 7c99779d..237aedb9 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -124,7 +124,7 @@ public class CacheFloatDistanceInOnDiskMatrix<O, D extends NumberDistance<D, ?>>
DistanceQuery<O, D> distanceQuery = database.getDistanceQuery(relation, distance);
int matrixsize = 0;
- for(DBID id : distanceQuery.getRelation().iterDBIDs()) {
+ for(DBID id : relation.iterDBIDs()) {
matrixsize = Math.max(matrixsize, id.getIntegerID() + 1);
if(id.getIntegerID() < 0) {
throw new AbortException("OnDiskMatrixCache does not allow negative DBIDs.");
@@ -139,8 +139,8 @@ public class CacheFloatDistanceInOnDiskMatrix<O, D extends NumberDistance<D, ?>>
throw new AbortException("Error creating output matrix.", e);
}
- for(DBID id1 : distanceQuery.getRelation().iterDBIDs()) {
- for(DBID id2 : distanceQuery.getRelation().iterDBIDs()) {
+ for(DBID id1 : relation.iterDBIDs()) {
+ for(DBID id2 : relation.iterDBIDs()) {
if(id2.getIntegerID() >= id1.getIntegerID()) {
float d = distanceQuery.distance(id1, id2).floatValue();
if(debugExtraCheckSymmetry) {
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 17013c55..5ed7ec1c 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) 2011
+Copyright (C) 2012
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
new file mode 100644
index 00000000..f6506fcc
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/application/greedyensemble/ComputeKNNOutlierScores.java
@@ -0,0 +1,468 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.FileNotFoundException;
+import java.io.PrintStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+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.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.database.Database;
+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.DBIDs;
+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.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.result.outlier.OutlierResult;
+import de.lmu.ifi.dbs.elki.utilities.Base64;
+import de.lmu.ifi.dbs.elki.utilities.FormatUtil;
+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.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;
+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.workflow.InputStep;
+
+/**
+ * Application that runs a series of kNN-based algorithms on a data set, for
+ * building an ensemble in a second step. The output file consists of a label
+ * and one score value for each object.
+ *
+ * Reference:
+ * <p>
+ * E. Schubert, R. Wojdanowski, A. Zimek, H.-P. Kriegel<br />
+ * On Evaluation of Outlier Rankings and Outlier Scores<br/>
+ * In Proceedings of the 12th SIAM International Conference on Data Mining
+ * (SDM), Anaheim, CA, 2012.
+ * </p>
+ *
+ * @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 {
+ /**
+ * Our logger class.
+ */
+ private static final Logging logger = Logging.getLogger(ComputeKNNOutlierScores.class);
+
+ /**
+ * Input step
+ */
+ final InputStep inputstep;
+
+ /**
+ * Distance function to use
+ */
+ final DistanceFunction<? super O, D> distf;
+
+ /**
+ * Starting value of k.
+ */
+ final int startk;
+
+ /**
+ * k step size
+ */
+ final int stepk;
+
+ /**
+ * Maximum value of k
+ */
+ final int maxk;
+
+ /**
+ * Output file
+ */
+ File outfile;
+
+ /**
+ * By label outlier detection - reference
+ */
+ ByLabelOutlier bylabel;
+
+ /**
+ * Include ABOD in the experiments.
+ */
+ boolean runabod = false;
+
+ /**
+ * Constructor.
+ *
+ * @param verbose Verbose flag
+ * @param inputstep Input step
+ * @param distf Distance function
+ * @param startk Starting value of k
+ * @param stepk K step size
+ * @param maxk Maximum k value
+ * @param bylabel By label outlier (reference)
+ * @param outfile Output file
+ */
+ public ComputeKNNOutlierScores(boolean verbose, InputStep inputstep, DistanceFunction<? super O, D> distf, int startk, int stepk, int maxk, ByLabelOutlier bylabel, File outfile) {
+ super(verbose);
+ this.distf = distf;
+ this.startk = startk;
+ this.stepk = stepk;
+ this.maxk = maxk;
+ this.inputstep = inputstep;
+ this.bylabel = bylabel;
+ this.outfile = outfile;
+ }
+
+ @Override
+ public void run() {
+ final Database database = inputstep.getDatabase();
+ final Relation<O> relation = database.getRelation(distf.getInputTypeRestriction());
+ logger.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)) {
+ logger.warning("Not using preprocessor knn query -- KNN queries using class: " + knnq.getClass());
+ }
+
+ final DBIDs ids = relation.getDBIDs();
+
+ final PrintStream fout;
+ try {
+ fout = new PrintStream(outfile);
+ }
+ catch(FileNotFoundException e) {
+ throw new AbortException("Cannot create output file.", e);
+ }
+ // Control: print the DBIDs in case we are seeing an odd iteration
+ {
+ try {
+ MessageDigest md = MessageDigest.getInstance("MD5");
+ for(DBID id : ids) {
+ md.update(" ".getBytes());
+ md.update(id.toString().getBytes());
+ }
+ fout.append("# DBID-series MD5:");
+ fout.append(Base64.encodeBase64(md.digest()));
+ fout.append(FormatUtil.NEWLINE);
+ }
+ catch(NoSuchAlgorithmException e) {
+ throw new AbortException("MD5 not found.");
+ }
+ }
+
+ // Label outlier result (reference)
+ {
+ OutlierResult bylabelresult = bylabel.run(database);
+ writeResult(fout, ids, bylabelresult, new IdentityScaling(), "bylabel");
+ }
+ // No/all outliers "results"
+ {
+ OutlierResult noresult = (new TrivialNoOutlier()).run(database);
+ writeResult(fout, ids, noresult, new IdentityScaling(), "no-outliers");
+ OutlierResult allresult = (new TrivialAllOutlier()).run(database);
+ writeResult(fout, ids, allresult, new IdentityScaling(), "all-outliers");
+ }
+
+ // KNN
+ logger.verbose("Running KNN");
+ runForEachK(new AlgRunner() {
+ @Override
+ public void run(int k, String kstr) {
+ KNNOutlier<O, D> knn = new KNNOutlier<O, D>(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);
+ }
+ });
+ // KNN Weight
+ logger.verbose("Running KNNweight");
+ runForEachK(new AlgRunner() {
+ @Override
+ public void run(int k, String kstr) {
+ KNNWeightOutlier<O, D> knnw = new KNNWeightOutlier<O, D>(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);
+ }
+ });
+ // Run LOF
+ logger.verbose("Running LOF");
+ 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);
+ writeResult(fout, ids, lofresult, scaling, "LOF-" + kstr);
+ detachResult(database, lofresult);
+ }
+ });
+ // LoOP
+ logger.verbose("Running LoOP");
+ 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);
+ OutlierResult loopresult = loop.run(database, relation);
+ writeResult(fout, ids, loopresult, new IdentityScaling(), "LOOP-" + kstr);
+ detachResult(database, loopresult);
+ }
+ });
+ // LDOF
+ logger.verbose("Running LDOF");
+ runForEachK(new AlgRunner() {
+ @Override
+ public void run(int k, String kstr) {
+ LDOF<O, D> ldof = new LDOF<O, D>(distf, k);
+ 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);
+ }
+ });
+ // ABOD
+ if(runabod && relation.size() < 10000) {
+ try {
+ final PolynomialKernelFunction poly = new PolynomialKernelFunction(PolynomialKernelFunction.DEFAULT_DEGREE);
+ @SuppressWarnings("unchecked")
+ final DistanceFunction<DoubleVector, DoubleDistance> df = DistanceFunction.class.cast(distf);
+ logger.verbose("Running ABOD");
+ runForEachK(new AlgRunner() {
+ @Override
+ public void run(int k, String kstr) {
+ ABOD<DoubleVector> abod = new ABOD<DoubleVector>(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);
+ }
+ });
+ }
+ catch(ClassCastException e) {
+ // ABOD might just be not appropriate.
+ logger.warning("Running ABOD failed - probably not appropriate to this data type / distance?", e);
+ }
+ }
+ }
+
+ /**
+ * 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 label Identification label
+ */
+ void writeResult(PrintStream out, DBIDs ids, OutlierResult result, ScalingFunction scaling, String label) {
+ out.append(label);
+ Relation<Double> scores = result.getScores();
+ for(DBID id : ids) {
+ final double value = scaling.getScaled(scores.get(id));
+ out.append(" ").append(FormatUtil.format(value, FormatUtil.NF8));
+ }
+ out.append(FormatUtil.NEWLINE);
+ }
+
+ /**
+ * Iterate over the k range.
+ *
+ * @param runner Runner to run
+ */
+ 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) {
+ String kstr = String.format("%0" + digits + "d", k);
+ runner.run(k, kstr);
+ }
+ }
+
+ /**
+ * Run an algorithm for a given k.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ private interface AlgRunner {
+ public void run(int k, String kstr);
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer<O, D extends NumberDistance<D, ?>> extends AbstractApplication.Parameterizer {
+ /**
+ * Option ID for k step size.
+ */
+ public static final OptionID STEPK_ID = OptionID.getOrCreateOptionID("stepk", "Step size for k.");
+
+ /**
+ * Option ID for k start size.
+ */
+ public static final OptionID STARTK_ID = OptionID.getOrCreateOptionID("startk", "Minimum value for k.");
+
+ /**
+ * Option ID for k step size.
+ */
+ public static final OptionID MAXK_ID = OptionID.getOrCreateOptionID("maxk", "Maximum value for k.");
+
+ /**
+ * k step size
+ */
+ int stepk;
+
+ /**
+ * starting value of k
+ */
+ int startk;
+
+ /**
+ * Maximum value of k
+ */
+ int maxk;
+
+ /**
+ * Data source
+ */
+ InputStep inputstep;
+
+ /**
+ * Distance function to use
+ */
+ DistanceFunction<? super O, D> distf;
+
+ /**
+ * By label outlier -- reference
+ */
+ ByLabelOutlier bylabel;
+
+ /**
+ * Output destination file
+ */
+ File outfile;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ // Data input
+ inputstep = config.tryInstantiate(InputStep.class);
+ // Distance function
+ ObjectParameter<DistanceFunction<? super O, D>> distP = AbstractAlgorithm.makeParameterDistanceFunction(EuclideanDistanceFunction.class, DistanceFunction.class);
+ if(config.grab(distP)) {
+ distf = distP.instantiateClass(config);
+ }
+ // k parameters
+ IntParameter stepkP = new IntParameter(STEPK_ID, new GreaterConstraint(0));
+ if(config.grab(stepkP)) {
+ stepk = stepkP.getValue();
+ }
+ IntParameter startkP = new IntParameter(STARTK_ID, true);
+ if(config.grab(startkP)) {
+ startk = startkP.getValue();
+ }
+ else {
+ startk = stepk;
+ }
+ IntParameter maxkP = new IntParameter(MAXK_ID, new GreaterConstraint(0));
+ 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.");
+ }
+
+ @Override
+ protected AbstractApplication makeInstance() {
+ return new ComputeKNNOutlierScores<O, D>(verbose, inputstep, distf, startk, stepk, maxk, bylabel, outfile);
+ }
+ }
+
+ /**
+ * Main method.
+ *
+ * @param args Command line parameters.
+ */
+ public static void main(String[] args) {
+ ComputeKNNOutlierScores.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
new file mode 100644
index 00000000..cfd768c1
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/application/greedyensemble/GreedyEnsembleExperiment.java
@@ -0,0 +1,439 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.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.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.HashSetModifiableDBIDs;
+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.PrimitiveDoubleDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.WeightedPearsonCorrelationDistanceFunction;
+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.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.documentation.Reference;
+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.pairs.DoubleObjPair;
+import de.lmu.ifi.dbs.elki.workflow.InputStep;
+
+/**
+ * Class to load an outlier detection summary file, as produced by
+ * {@link ComputeKNNOutlierScores}, and compute a naive ensemble for it. Based
+ * on this initial estimation, and optimized ensemble is built using a greedy
+ * strategy. Starting with the best candidate only as initial ensemble, the most
+ * diverse candidate is investigated at each step. If it improves towards the
+ * (estimated) target vector, it is added, otherwise it is discarded.
+ *
+ * This approach is naive, and it may be surprising that it can improve results.
+ * The reason is probably that diversity will result in a comparable ensemble,
+ * while the reduced ensemble size is actually responsible for the improvements,
+ * by being more decisive and less noisy due to dropping "unhelpful" members.
+ *
+ * This still leaves quite a bit of room for improvement. If you build upon this
+ * basic approach, please acknowledge our proof of concept work.
+ *
+ * Reference:
+ * <p>
+ * E. Schubert, R. Wojdanowski, A. Zimek, H.-P. Kriegel<br />
+ * On Evaluation of Outlier Rankings and Outlier Scores<br/>
+ * In Proceedings of the 12th SIAM International Conference on Data Mining
+ * (SDM), Anaheim, CA, 2012.
+ * </p>
+ *
+ * @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 GreedyEnsembleExperiment extends AbstractApplication {
+ /**
+ * Get static logger
+ */
+ private static final Logging logger = Logging.getLogger(GreedyEnsembleExperiment.class);
+
+ /**
+ * The data input part.
+ */
+ private InputStep inputstep;
+
+ /**
+ * Variant, where the truth vector is also updated.
+ */
+ boolean refine_truth = false;
+
+ /**
+ * Constructor.
+ *
+ * @param verbose Verbosity
+ * @param inputstep Input step
+ */
+ public GreedyEnsembleExperiment(boolean verbose, InputStep inputstep) {
+ super(verbose);
+ this.inputstep = inputstep;
+ }
+
+ @Override
+ public void run() {
+ // Note: the database contains the *result vectors*, not the original data
+ // points.
+ final Database database = inputstep.getDatabase();
+ final Relation<NumberVector<?, ?>> relation = database.getRelation(TypeUtil.NUMBER_VECTOR_FIELD);
+ final Relation<String> labels = DatabaseUtil.guessLabelRepresentation(database);
+ final DBID firstid = labels.iterDBIDs().next();
+ final String firstlabel = labels.get(firstid);
+ if(!firstlabel.matches("bylabel")) {
+ throw new AbortException("No 'by label' reference outlier found, which is needed for weighting!");
+ }
+
+ // Dimensionality and reference vector
+ final int dim = DatabaseUtil.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 + 1) > 0) {
+ positive.add(d);
+ }
+ }
+
+ final int estimated_outliers = (int) (0.005 * dim);
+ int union_outliers = 0;
+ final int[] outliers_seen = new int[dim];
+ // Find the top-k for each ensemble member
+ {
+ for(DBID id : relation.iterDBIDs()) {
+ // Skip "by label", obviously
+ if(firstid.equals(id)) {
+ continue;
+ }
+ final NumberVector<?, ?> vec = relation.get(id);
+ TiedTopBoundedHeap<DoubleIntPair> heap = new TiedTopBoundedHeap<DoubleIntPair>(estimated_outliers, Collections.reverseOrder());
+ for(int i = 0; i < dim; i++) {
+ heap.add(new DoubleIntPair(vec.doubleValue(i + 1), i));
+ }
+ if(heap.size() >= 2 * estimated_outliers) {
+ logger.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;
+ }
+ else {
+ outliers_seen[pair.second] += 1;
+ }
+ }
+ }
+ }
+ logger.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];
+ updateEstimations(outliers_seen, union_outliers, estimated_weights, estimated_truth);
+ NumberVector<?, ?> estimated_truth_vec = refvec.newNumberVector(estimated_truth);
+
+ PrimitiveDoubleDistanceFunction<NumberVector<?, ?>> wdist = getDistanceFunction(estimated_weights);
+ PrimitiveDoubleDistanceFunction<NumberVector<?, ?>> tdist = wdist;
+
+ // Build the naive ensemble:
+ final double[] naiveensemble = new double[dim];
+ {
+ for(DBID id : relation.iterDBIDs()) {
+ if(firstid.equals(id)) {
+ continue;
+ }
+ final NumberVector<?, ?> vec = relation.get(id);
+ for(int d = 0; d < dim; d++) {
+ naiveensemble[d] += vec.doubleValue(d + 1);
+ }
+ }
+ for(int d = 0; d < dim; d++) {
+ naiveensemble[d] /= (relation.size() - 1);
+ }
+ }
+ NumberVector<?, ?> naivevec = refvec.newNumberVector(naiveensemble);
+
+ // Compute single AUC scores and estimations.
+ // Remember the method most similar to the estimation
+ double bestauc = 0.0;
+ String bestaucstr = "";
+ double bestcost = Double.POSITIVE_INFINITY;
+ String bestcoststr = "";
+ DBID bestid = null;
+ double bestest = Double.POSITIVE_INFINITY;
+ {
+ // Compute individual scores
+ for(DBID id : relation.iterDBIDs()) {
+ if(firstid.equals(id)) {
+ continue;
+ }
+ // fout.append(labels.get(id));
+ final NumberVector<?, ?> vec = relation.get(id);
+ double auc = computeROCAUC(vec, positive, dim);
+ double estimated = wdist.doubleDistance(vec, estimated_truth_vec);
+ double cost = tdist.doubleDistance(vec, refvec);
+ logger.verbose("ROC AUC: " + auc + " estimated " + estimated + " cost " + cost + " " + labels.get(id));
+ if(auc > bestauc) {
+ bestauc = auc;
+ bestaucstr = labels.get(id);
+ }
+ if(cost < bestcost) {
+ bestcost = cost;
+ bestcoststr = labels.get(id);
+ }
+ if(estimated < bestest) {
+ bestest = estimated;
+ bestid = id;
+ }
+ }
+ }
+
+ // Initialize ensemble with "best" method
+ logger.verbose("Distance function: " + wdist);
+ logger.verbose("Initial estimation of outliers: " + union_outliers);
+ logger.verbose("Initializing ensemble with: " + labels.get(bestid));
+ ModifiableDBIDs ensemble = DBIDUtil.newArray(bestid);
+ ModifiableDBIDs enscands = DBIDUtil.newHashSet(relation.getDBIDs());
+ 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 + 1);
+ }
+ }
+ // Greedily grow the ensemble
+ final double[] testensemble = new double[dim];
+ while(enscands.size() > 0) {
+ NumberVector<?, ?> greedyvec = refvec.newNumberVector(greedyensemble);
+
+ // Weighting factors for combining:
+ double s1 = ensemble.size() / (ensemble.size() + 1.);
+ double s2 = 1. / (ensemble.size() + 1.);
+
+ final int heapsize = enscands.size();
+ TopBoundedHeap<DoubleObjPair<DBID>> heap = new TopBoundedHeap<DoubleObjPair<DBID>>(heapsize, Collections.reverseOrder());
+ for(DBID id : enscands) {
+ final NumberVector<?, ?> vec = relation.get(id);
+ double diversity = wdist.doubleDistance(vec, greedyvec);
+ heap.add(new DoubleObjPair<DBID>(diversity, id));
+ }
+ while(heap.size() > 0) {
+ DBID bestadd = heap.poll().second;
+ 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 + 1) * s2;
+ }
+ NumberVector<?, ?> testvec = refvec.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) {
+ System.arraycopy(testensemble, 0, greedyensemble, 0, dim);
+ ensemble.add(bestadd);
+ // logger.verbose("Growing ensemble with: " + labels.get(bestadd));
+ break; // Recompute heap
+ }
+ else {
+ // logger.verbose("Discarding: " + labels.get(bestadd));
+ if(refine_truth) {
+ boolean refresh = false;
+ // 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 + 1), 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;
+ }
+ }
+ if(refresh) {
+ updateEstimations(outliers_seen, union_outliers, estimated_weights, estimated_truth);
+ estimated_truth_vec = refvec.newNumberVector(estimated_truth);
+ }
+ }
+ }
+ }
+ }
+ // Build the improved ensemble:
+ StringBuffer greedylbl = new StringBuffer();
+ {
+ for(DBID id : ensemble) {
+ if(greedylbl.length() > 0) {
+ greedylbl.append(" ");
+ }
+ greedylbl.append(labels.get(id));
+ }
+ }
+ NumberVector<?, ?> greedyvec = refvec.newNumberVector(greedyensemble);
+ logger.verbose("Estimated outliers remaining: " + union_outliers);
+ logger.verbose("Greedy ensemble: " + greedylbl.toString());
+
+ logger.verbose("Best single ROC AUC: " + bestauc + " (" + bestaucstr + ")");
+ logger.verbose("Best single cost: " + bestcost + " (" + bestcoststr + ")");
+ // Evaluate the naive ensemble and the "shrunk" ensemble
+ double naiveauc, naivecost;
+ {
+ naiveauc = computeROCAUC(naivevec, positive, dim);
+ naivecost = tdist.doubleDistance(naivevec, refvec);
+ logger.verbose("Naive ensemble AUC: " + naiveauc + " cost: " + naivecost);
+ logger.verbose("Naive ensemble Gain: " + gain(naiveauc, bestauc, 1) + " cost gain: " + gain(naivecost, bestcost, 0));
+ }
+ double greedyauc, greedycost;
+ {
+ greedyauc = computeROCAUC(greedyvec, positive, dim);
+ greedycost = tdist.doubleDistance(greedyvec, refvec);
+ logger.verbose("Greedy ensemble AUC: " + greedyauc + " cost: " + greedycost);
+ logger.verbose("Greedy ensemble Gain to best: " + gain(greedyauc, bestauc, 1) + " cost gain: " + gain(greedycost, bestcost, 0));
+ logger.verbose("Greedy ensemble Gain to naive: " + gain(greedyauc, naiveauc, 1) + " cost gain: " + gain(greedycost, naivecost, 0));
+ }
+ {
+ MeanVariance meanauc = new MeanVariance();
+ MeanVariance meancost = new MeanVariance();
+ HashSetModifiableDBIDs candidates = DBIDUtil.newHashSet(relation.getDBIDs());
+ candidates.remove(firstid);
+ for(int i = 0; i < 5000; i++) {
+ // Build the improved ensemble:
+ final double[] randomensemble = new double[dim];
+ {
+ DBIDs random = DBIDUtil.randomSample(candidates, ensemble.size(), (long)i);
+ for(DBID id : random) {
+ assert (!firstid.equals(id));
+ // logger.verbose("Using: "+labels.get(id));
+ final NumberVector<?, ?> vec = relation.get(id);
+ for(int d = 0; d < dim; d++) {
+ randomensemble[d] += vec.doubleValue(d + 1);
+ }
+ }
+ for(int d = 0; d < dim; d++) {
+ randomensemble[d] /= ensemble.size();
+ }
+ }
+ NumberVector<?, ?> randomvec = refvec.newNumberVector(randomensemble);
+ double auc = computeROCAUC(randomvec, positive, dim);
+ meanauc.put(auc);
+ double cost = tdist.doubleDistance(randomvec, refvec);
+ meancost.put(cost);
+ }
+ logger.verbose("Random ensemble AUC: " + meanauc.getMean() + " + stddev: " + meanauc.getSampleStddev() + " = " + (meanauc.getMean() + meanauc.getSampleStddev()));
+ logger.verbose("Random ensemble Gain: " + gain(meanauc.getMean(), bestauc, 1));
+ logger.verbose("Greedy improvement: " + (greedyauc - meanauc.getMean()) / meanauc.getSampleStddev() + " standard deviations.");
+ logger.verbose("Random ensemble Cost: " + meancost.getMean() + " + stddev: " + meancost.getSampleStddev() + " = " + (meancost.getMean() + meanauc.getSampleStddev()));
+ logger.verbose("Random ensemble Gain: " + gain(meancost.getMean(), bestcost, 0));
+ logger.verbose("Greedy improvement: " + (meancost.getMean() - greedycost) / meancost.getSampleStddev() + " standard deviations.");
+ logger.verbose("Naive ensemble Gain to random: " + gain(naiveauc, meanauc.getMean(), 1) + " cost gain: " + gain(naivecost, meancost.getMean(), 0));
+ logger.verbose("Random ensemble Gain to naive: " + gain(meanauc.getMean(), naiveauc, 1) + " cost gain: " + gain(meancost.getMean(), naivecost, 0));
+ logger.verbose("Greedy ensemble Gain to random: " + gain(greedyauc, meanauc.getMean(), 1) + " cost gain: " + gain(greedycost, meancost.getMean(), 0));
+ }
+ }
+
+ 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;
+ }
+ else {
+ estimated_weights[i] = 0.5 / (outliers_seen.length - union_outliers);
+ estimated_truth[i] = 0.0;
+ }
+ }
+ }
+
+ private PrimitiveDoubleDistanceFunction<NumberVector<?, ?>> getDistanceFunction(double[] estimated_weights) {
+ // return new WeightedSquaredEuclideanDistanceFunction(estimated_weights);
+ // return new WeightedLPNormDistanceFunction(1.0, estimated_weights);
+ return new WeightedPearsonCorrelationDistanceFunction(estimated_weights);
+ }
+
+ 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 + 1), d);
+ }
+ Arrays.sort(scores, Collections.reverseOrder(DoubleIntPair.BYFIRST_COMPARATOR));
+ return ROC.computeAUC(ROC.materializeROC(dim, positive, Arrays.asList(scores).iterator()));
+ }
+
+ double gain(double score, double ref, double optimal) {
+ return 1 - ((optimal - score) / (optimal - ref));
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractApplication.Parameterizer {
+ /**
+ * Data source
+ */
+ InputStep inputstep;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ // Data input
+ inputstep = config.tryInstantiate(InputStep.class);
+ }
+
+ @Override
+ protected AbstractApplication makeInstance() {
+ return new GreedyEnsembleExperiment(verbose, inputstep);
+ }
+ }
+
+ /**
+ * Main method.
+ *
+ * @param args Command line parameters.
+ */
+ public static void main(String[] args) {
+ GreedyEnsembleExperiment.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
new file mode 100644
index 00000000..2c728878
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/application/greedyensemble/VisualizePairwiseGainMatrix.java
@@ -0,0 +1,307 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.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;
+
+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.ids.ArrayModifiableDBIDs;
+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.relation.Relation;
+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.math.DoubleMinMax;
+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.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.scaling.LinearScaling;
+import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
+import de.lmu.ifi.dbs.elki.visualization.VisualizerContext;
+import de.lmu.ifi.dbs.elki.visualization.VisualizerParameterizer;
+import de.lmu.ifi.dbs.elki.visualization.gui.SimpleSVGViewer;
+import de.lmu.ifi.dbs.elki.visualization.svg.SVGPlot;
+import de.lmu.ifi.dbs.elki.visualization.visualizers.Visualization;
+import de.lmu.ifi.dbs.elki.visualization.visualizers.visunproj.SimilarityMatrixVisualizer;
+import de.lmu.ifi.dbs.elki.workflow.InputStep;
+
+/**
+ * Class to load an outlier detection summary file, as produced by
+ * {@link ComputeKNNOutlierScores}, and compute a matrix with the pairwise
+ * gains. It will have one column / row obtained for each combination.
+ *
+ * The gain is always computed in relation to the better of the two input
+ * methods. Green colors indicate the result has improved, red indicate it
+ * became worse.
+ *
+ * Reference:
+ * <p>
+ * E. Schubert, R. Wojdanowski, A. Zimek, H.-P. Kriegel<br />
+ * On Evaluation of Outlier Rankings and Outlier Scores<br/>
+ * In Proceedings of the 12th SIAM International Conference on Data Mining
+ * (SDM), Anaheim, CA, 2012.
+ * </p>
+ *
+ * @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 VisualizePairwiseGainMatrix extends AbstractApplication {
+ /**
+ * Get static logger
+ */
+ private static final Logging logger = Logging.getLogger(VisualizePairwiseGainMatrix.class);
+
+ /**
+ * The data input part.
+ */
+ private InputStep inputstep;
+
+ /**
+ * Parameterizer for visualizers
+ */
+ private VisualizerParameterizer vispar;
+
+ /**
+ * Constructor.
+ *
+ * @param verbose Verbosity
+ * @param inputstep Input step
+ * @param vispar Visualizer parameterizer
+ */
+ public VisualizePairwiseGainMatrix(boolean verbose, InputStep inputstep, VisualizerParameterizer vispar) {
+ super(verbose);
+ this.inputstep = inputstep;
+ this.vispar = vispar;
+ }
+
+ @Override
+ public void run() {
+ final Database database = inputstep.getDatabase();
+ final Relation<NumberVector<?, ?>> relation = database.getRelation(TypeUtil.NUMBER_VECTOR_FIELD);
+ final Relation<String> labels = DatabaseUtil.guessLabelRepresentation(database);
+ final DBID firstid = labels.iterDBIDs().next();
+ final String firstlabel = labels.get(firstid);
+ if(!firstlabel.matches("bylabel")) {
+ throw new AbortException("No 'by label' reference outlier found, which is needed for weighting!");
+ }
+
+ // Dimensionality and reference vector
+ final int dim = DatabaseUtil.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 + 1) > 0) {
+ pos.add(d);
+ }
+ }
+ }
+
+ ArrayModifiableDBIDs ids = DBIDUtil.newArray(relation.getDBIDs());
+ ids.remove(firstid);
+ final int size = ids.size();
+
+ double[][] data = new double[size][size];
+ DoubleMinMax minmax = new DoubleMinMax();
+
+ for(int a = 0; a < size; a++) {
+ final NumberVector<?, ?> veca = relation.get(ids.get(a));
+ // Direct AUC score:
+ {
+ for(int d = 0; d < dim; d++) {
+ combined[d].first = veca.doubleValue(d + 1);
+ combined[d].second = d;
+ }
+ Arrays.sort(combined, Collections.reverseOrder(DoubleIntPair.BYFIRST_COMPARATOR));
+ double auc = ROC.computeAUC(ROC.materializeROC(dim, pos, Arrays.asList(combined).iterator()));
+ data[a][a] = auc;
+ // minmax.put(auc);
+ // logger.verbose(auc + " " + labels.get(ids.get(a)));
+ }
+ // Compare to others, exploiting symmetry
+ for(int b = a + 1; b < size; b++) {
+ final NumberVector<?, ?> vecb = relation.get(ids.get(b));
+ for(int d = 0; d < dim; d++) {
+ combined[d].first = veca.doubleValue(d + 1) + vecb.doubleValue(d + 1);
+ combined[d].second = d;
+ }
+ Arrays.sort(combined, Collections.reverseOrder(DoubleIntPair.BYFIRST_COMPARATOR));
+ double auc = ROC.computeAUC(ROC.materializeROC(dim, pos, Arrays.asList(combined).iterator()));
+ // logger.verbose(auc + " " + labels.get(ids.get(a)) + " " +
+ // labels.get(ids.get(b)));
+ data[a][b] = auc;
+ data[b][a] = auc;
+ // minmax.put(auc);
+ }
+ }
+ 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);
+ // logger.verbose(data[a][b] + " " + labels.get(ids.get(a)) + " " +
+ // labels.get(ids.get(b)));
+ minmax.put(data[a][b]);
+ }
+ }
+ for(int a = 0; a < size; a++) {
+ data[a][a] = 0;
+ }
+
+ logger.verbose(minmax.toString());
+
+ boolean hasneg = (minmax.getMin() < -1E-3);
+ LinearScaling scale;
+ if(!hasneg) {
+ scale = new LinearScaling(minmax);
+ }
+ else {
+ scale = LinearScaling.fromMinMax(0.0, Math.max(minmax.getMax(), -minmax.getMin()));
+ }
+
+ BufferedImage img = new BufferedImage(size, size, BufferedImage.TYPE_INT_RGB);
+ for(int x = 0; x < size; x++) {
+ for(int y = x; y < size; y++) {
+ double val = data[x][y];
+ val = 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);
+ }
+ }
+ }
+ img.setRGB(x, y, col);
+ img.setRGB(y, x, col);
+ }
+ }
+ SimilarityMatrix smat = new ComputeSimilarityMatrixImage.SimilarityMatrix(img, relation, ids);
+ database.getHierarchy().add(database, smat);
+
+ VisualizerContext context = vispar.newContext(database);
+
+ // Attach visualizers to results
+ SimilarityMatrixVisualizer.Factory factory = new SimilarityMatrixVisualizer.Factory();
+ factory.processNewResult(database, database);
+
+ List<VisualizationTask> tasks = ResultUtil.filterResults(database, VisualizationTask.class);
+ for(VisualizationTask task : tasks) {
+ if(task.getFactory() == factory) {
+ showVisualization(context, factory, task);
+ }
+ }
+ }
+
+ /**
+ * Show a single visualization.
+ *
+ * @param context
+ *
+ * @param factory
+ * @param task
+ */
+ private void showVisualization(VisualizerContext context, SimilarityMatrixVisualizer.Factory factory, VisualizationTask task) {
+ SVGPlot plot = new SVGPlot();
+ Visualization vis = factory.makeVisualization(task.clone(plot, context, null, 1.0, 1.0));
+ plot.getRoot().appendChild(vis.getLayer());
+ plot.getRoot().setAttribute(SVGConstants.SVG_WIDTH_ATTRIBUTE, "20cm");
+ plot.getRoot().setAttribute(SVGConstants.SVG_HEIGHT_ATTRIBUTE, "20cm");
+ plot.getRoot().setAttribute(SVGConstants.SVG_VIEW_BOX_ATTRIBUTE, "0 0 1 1");
+ plot.updateStyleElement();
+
+ (new SimpleSVGViewer()).setPlot(plot);
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractApplication.Parameterizer {
+ /**
+ * Data source
+ */
+ InputStep inputstep;
+
+ /**
+ * Parameterizer for visualizers
+ */
+ private VisualizerParameterizer vispar;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ // Data input
+ inputstep = config.tryInstantiate(InputStep.class);
+ // Visualization options
+ vispar = config.tryInstantiate(VisualizerParameterizer.class);
+ }
+
+ @Override
+ protected AbstractApplication makeInstance() {
+ return new VisualizePairwiseGainMatrix(verbose, inputstep, vispar);
+ }
+ }
+
+ /**
+ * Main method.
+ *
+ * @param args Command line parameters.
+ */
+ public static void main(String[] args) {
+ VisualizePairwiseGainMatrix.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
new file mode 100644
index 00000000..29b34e96
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/application/greedyensemble/package-info.java
@@ -0,0 +1,32 @@
+/**
+ * <p>Greedy ensembles for outlier detection.</p>
+ *
+ * <p>This package contains code that was used for the greedy ensemble experiment in
+ * <blockquote> E. Schubert, R. Wojdanowski, A. Zimek, H.-P. Kriegel<br />
+ * On Evaluation of Outlier Rankings and Outlier Scores<br/>
+ * In Proceedings of the 12th SIAM International Conference on Data Mining (SDM), Anaheim, CA, 2012.</blockquote>
+ * </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.application.greedyensemble; \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/application/internal/CheckELKIProperties.java b/src/de/lmu/ifi/dbs/elki/application/internal/CheckELKIServices.java
index fa260564..21ed047b 100644
--- a/src/de/lmu/ifi/dbs/elki/application/internal/CheckELKIProperties.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,36 +23,44 @@ package de.lmu.ifi.dbs.elki.application.internal;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URISyntaxException;
+import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
-import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import de.lmu.ifi.dbs.elki.logging.Logging;
-import de.lmu.ifi.dbs.elki.properties.Properties;
+import de.lmu.ifi.dbs.elki.utilities.ELKIServiceLoader;
import de.lmu.ifi.dbs.elki.utilities.FormatUtil;
import de.lmu.ifi.dbs.elki.utilities.InspectionUtil;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
/**
- * Helper application to test the ELKI properties file for "missing" implementations.
+ * Helper application to test the ELKI properties file for "missing"
+ * implementations.
*
* @author Erich Schubert
*
- * @apiviz.uses Properties
+ * @apiviz.uses ELKIServiceLoader
*/
-public class CheckELKIProperties {
+public class CheckELKIServices {
/**
* The logger for this class.
*/
- private static final Logging logger = Logging.getLogger(CheckELKIProperties.class);
-
+ private static final Logging logger = Logging.getLogger(CheckELKIServices.class);
+
/**
* Pattern to strip comments, while keeping commented class names.
*/
- private Pattern strip = Pattern.compile("^[\\s#]*(.*?)[\\s,]*$");
+ private Pattern strip = Pattern.compile("^[\\s#]*(.*?)[\\s]*$");
/**
* Package to skip matches in - unreleased code.
@@ -65,25 +73,36 @@ public class CheckELKIProperties {
* @param argv Command line arguments
*/
public static void main(String[] argv) {
- new CheckELKIProperties().checkProperties();
+ new CheckELKIServices().checkServices();
}
-
+
/**
* Retrieve all properties and check them.
*/
- public void checkProperties() {
- Set<String> props = Properties.ELKI_PROPERTIES.getPropertyNames();
- for(String prop : props) {
- checkProperty(prop);
+ public void checkServices() {
+ URL u = getClass().getClassLoader().getResource(ELKIServiceLoader.PREFIX);
+ try {
+ for(String prop : new File(u.toURI()).list()) {
+ if (".svn".equals(prop)) {
+ continue;
+ }
+ if (logger.isVerbose()) {
+ logger.verbose("Checking property: "+prop);
+ }
+ checkService(prop);
+ }
+ }
+ catch(URISyntaxException e) {
+ throw new AbortException("Cannot check all properties, as some are not in a file: URL.");
}
}
/**
- * Check a single property
+ * Check a single service class
*
- * @param prop Property = Class name.
+ * @param prop Class name.
*/
- private void checkProperty(String prop) {
+ private void checkService(String prop) {
Class<?> cls;
try {
cls = Class.forName(prop);
@@ -108,23 +127,34 @@ public class CheckELKIProperties {
names.add(c2.getName());
}
- String[] known = Properties.ELKI_PROPERTIES.getProperty(cls.getName());
- for(String k : known) {
- Matcher m = strip.matcher(k);
- if(m.matches()) {
- String stripped = m.group(1);
- if(stripped.length() > 0) {
- if(names.contains(stripped)) {
- names.remove(stripped);
- }
- else {
- logger.warning("Name " + stripped + " found for property " + prop + " but no class discovered (or referenced twice?).");
+ try {
+ InputStream is = getClass().getClassLoader().getResource(ELKIServiceLoader.PREFIX + cls.getName()).openStream();
+ BufferedReader r = new BufferedReader(new InputStreamReader(is, "utf-8"));
+ for(String line;;) {
+ line = r.readLine();
+ // End of stream:
+ if(line == null) {
+ break;
+ }
+ Matcher m = strip.matcher(line);
+ if(m.matches()) {
+ String stripped = m.group(1);
+ if(stripped.length() > 0) {
+ if(names.contains(stripped)) {
+ names.remove(stripped);
+ }
+ else {
+ logger.warning("Name " + stripped + " found for property " + prop + " but no class discovered (or referenced twice?).");
+ }
}
}
+ else {
+ logger.warning("Line: " + line + " didn't match regexp.");
+ }
}
- else {
- logger.warning("Line: " + k + " didn't match regexp.");
- }
+ }
+ catch(IOException e) {
+ logger.exception(e);
}
if(names.size() > 0) {
StringBuffer message = new StringBuffer();
@@ -134,7 +164,7 @@ public class CheckELKIProperties {
// TODO: sort by package, then classname
Collections.sort(sorted);
for(String remaining : sorted) {
- message.append("# " + remaining + ",\\" + FormatUtil.NEWLINE);
+ message.append("# " + remaining + FormatUtil.NEWLINE);
}
logger.warning(message.toString());
}
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 017f2d12..b94ee47a 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) 2011
+ Copyright (C) 2012
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/DocumentParameters.java b/src/de/lmu/ifi/dbs/elki/application/internal/DocumentParameters.java
index 05af4b4d..c77e9dbb 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -33,6 +33,7 @@ import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
+import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -50,11 +51,10 @@ import org.w3c.dom.Document;
import org.w3c.dom.Element;
import de.lmu.ifi.dbs.elki.logging.Logging;
-import de.lmu.ifi.dbs.elki.properties.Properties;
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.iterator.IterableIterator;
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;
@@ -635,8 +635,8 @@ public class DocumentParameters {
private static void appendKnownImplementationsIfNonempty(Document htmldoc, ClassParameter<?> opt, Element elemdd) {
if(opt.getRestrictionClass() != Object.class) {
- IterableIterator<Class<?>> iter = opt.getKnownImplementations();
- if(iter.hasNext()) {
+ List<Class<?>> iter = opt.getKnownImplementations();
+ if(!iter.isEmpty()) {
Element p = htmldoc.createElement(HTMLUtil.HTML_P_TAG);
p.appendChild(htmldoc.createTextNode(HEADER_KNOWN_IMPLEMENTATIONS));
elemdd.appendChild(p);
@@ -652,7 +652,8 @@ public class DocumentParameters {
elemdd.appendChild(ul);
}
// Report when not in properties file.
- if(Properties.ELKI_PROPERTIES.getProperty(opt.getRestrictionClass().getName()).length == 0) {
+ Iterator<Class<?>> clss = new ELKIServiceLoader(opt.getRestrictionClass());
+ if (!clss.hasNext()) {
logger.warning(opt.getRestrictionClass().getName() + " not in properties. No autocompletion available in release GUI.");
}
}
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 949a7874..2e002243 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,12 +25,12 @@ package de.lmu.ifi.dbs.elki.application.internal;
import java.io.BufferedOutputStream;
import java.io.File;
-import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
+import java.io.PrintStream;
+import java.lang.reflect.Method;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -44,9 +44,9 @@ import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
+import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
import de.lmu.ifi.dbs.elki.utilities.InspectionUtil;
-import de.lmu.ifi.dbs.elki.utilities.documentation.DocumentationUtil;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
import de.lmu.ifi.dbs.elki.utilities.xml.HTMLUtil;
@@ -64,46 +64,56 @@ public class DocumentReferences {
private static final String MODIFICATION_WARNING = "WARNING: THIS DOCUMENT IS AUTOMATICALLY GENERATED. MODIFICATIONS MAY GET LOST.";
/**
+ * Logger
+ */
+ private static final Logging logger = Logging.getLogger(DocumentReferences.class);
+
+ /**
* @param args Command line arguments
*/
public static void main(String[] args) {
- if(args.length != 1) {
- LoggingUtil.warning("I need exactly one file name to operate!");
+ if(args.length < 1 || args.length > 2) {
+ LoggingUtil.warning("I need exactly one or two file names to operate!");
System.exit(1);
}
- if(!args[0].endsWith(".html")) {
- LoggingUtil.warning("File name doesn't end with .html!");
+ if(!args[0].endsWith(".html") || (args.length > 1 && !args[1].endsWith(".wiki"))) {
+ LoggingUtil.warning("File name doesn't end in expected extension!");
System.exit(1);
}
- File references = new File(args[0]);
- {
- FileOutputStream reffo;
- try {
- reffo = new FileOutputStream(references);
- }
- catch(FileNotFoundException e) {
- LoggingUtil.exception("Can't create output stream!", e);
- throw new RuntimeException(e);
- }
+ List<Pair<Reference, List<Class<?>>>> refs = sortedReferences();
+ try {
+ File references = new File(args[0]);
+ FileOutputStream reffo = new FileOutputStream(references);
+ Document refdoc = documentReferences(refs);
OutputStream refstream = new BufferedOutputStream(reffo);
- Document refdoc = documentParameters();
+ HTMLUtil.writeXHTML(refdoc, refstream);
+ refstream.flush();
+ refstream.close();
+ reffo.close();
+ }
+ catch(IOException e) {
+ LoggingUtil.exception("IO Exception writing HTML output.", e);
+ throw new RuntimeException(e);
+ }
+ if(args.length > 1) {
try {
- HTMLUtil.writeXHTML(refdoc, refstream);
- refstream.flush();
- refstream.close();
- reffo.close();
+ File refwiki = new File(args[1]);
+ FileOutputStream reffow = new FileOutputStream(refwiki);
+ PrintStream refstreamW = new PrintStream(reffow);
+ documentReferencesWiki(refs, refstreamW);
+ refstreamW.flush();
+ refstreamW.close();
+ reffow.close();
}
catch(IOException e) {
- LoggingUtil.exception("IO Exception writing output.", e);
+ LoggingUtil.exception("IO Exception writing Wiki output.", e);
throw new RuntimeException(e);
}
}
}
- private static Document documentParameters() {
- List<Pair<Reference, List<Class<?>>>> refs = sortedReferences();
-
+ private static Document documentReferences(List<Pair<Reference, List<Class<?>>>> refs) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder;
try {
@@ -165,7 +175,7 @@ public class DocumentReferences {
{
boolean first = true;
for(Class<?> cls : pair.second) {
- if (!first) {
+ if(!first) {
classdt.appendChild(htmldoc.createTextNode(", "));
}
Element classan = htmldoc.createElement(HTMLUtil.HTML_A_TAG);
@@ -177,7 +187,7 @@ public class DocumentReferences {
classa.setAttribute(HTMLUtil.HTML_HREF_ATTRIBUTE, linkForClassName(cls.getName()));
classa.setTextContent(cls.getName());
classdt.appendChild(classa);
-
+
first = false;
}
}
@@ -222,25 +232,98 @@ public class DocumentReferences {
return htmldoc;
}
- private static List<Pair<Reference, List<Class<?>>>> sortedReferences() {
- ArrayList<Class<?>> classes = findAllClassesWithReferences();
- Collections.sort(classes, new InspectionUtil.ClassSorter());
+ private static void documentReferencesWiki(List<Pair<Reference, List<Class<?>>>> refs, PrintStream refstreamW) {
+ for(Pair<Reference, List<Class<?>>> pair : refs) {
+ // JavaDoc links for relevant classes.
+ {
+ boolean first = true;
+ for(Class<?> cls : pair.second) {
+ if(!first) {
+ refstreamW.println(",[[br]]");
+ }
+ refstreamW.print("[[javadoc(");
+ refstreamW.print(cls.getName());
+ refstreamW.print(",");
+ refstreamW.print(cls.getName());
+ refstreamW.print(")]]");
+
+ first = false;
+ }
+ }
+ refstreamW.println("");
- List<Pair<Reference, List<Class<?>>>> refs = new ArrayList<Pair<Reference, List<Class<?>>>>(classes.size());
- Map<Reference, List<Class<?>>> map = new HashMap<Reference, List<Class<?>>>(classes.size());
- for(Class<?> cls : classes) {
- Reference ref = DocumentationUtil.getReference(cls);
- List<Class<?>> list = map.get(ref);
- if(list == null) {
- list = new ArrayList<Class<?>>(5);
- map.put(ref, list);
- refs.add(new Pair<Reference, List<Class<?>>>(ref, list));
+ String indent = " ";
+ {
+ Reference ref = pair.first;
+ // Prefix
+ if(ref.prefix().length() > 0) {
+ refstreamW.println(indent + ref.prefix() + " [[br]]");
+ }
+ // Authors
+ refstreamW.println(indent + "By: " + ref.authors() + " [[br]]");
+ // Title
+ refstreamW.println(indent + "'''" + ref.title() + "'''" + " [[br]]");
+ // Booktitle
+ refstreamW.println(indent + "In: " + ref.booktitle() + " [[br]]");
+ // URL
+ if(ref.url().length() > 0) {
+ refstreamW.println(indent + "Online: [" + ref.url() + "][[br]]");
+ }
}
- list.add(cls);
+ refstreamW.println("");
+ refstreamW.println("");
+ }
+ }
+
+ 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<?>>>();
+
+ for(final Class<?> cls : InspectionUtil.findAllImplementations(Object.class, true)) {
+ inspectClass(cls, refs, map);
}
return refs;
}
+ private static void inspectClass(final Class<?> cls, List<Pair<Reference, List<Class<?>>>> refs, Map<Reference, List<Class<?>>> map) {
+ try {
+ if(cls.isAnnotationPresent(Reference.class)) {
+ Reference ref = cls.getAnnotation(Reference.class);
+ List<Class<?>> list = map.get(ref);
+ if(list == null) {
+ list = new ArrayList<Class<?>>(5);
+ map.put(ref, list);
+ refs.add(new Pair<Reference, List<Class<?>>>(ref, list));
+ }
+ list.add(cls);
+ }
+ // Inner classes
+ for(Class<?> c2 : cls.getDeclaredClasses()) {
+ inspectClass(c2, refs, map);
+ }
+ for(Method m : cls.getDeclaredMethods()) {
+ if(m.isAnnotationPresent(Reference.class)) {
+ Reference ref = m.getAnnotation(Reference.class);
+ List<Class<?>> list = map.get(ref);
+ if(list == null) {
+ list = new ArrayList<Class<?>>(5);
+ map.put(ref, list);
+ refs.add(new Pair<Reference, List<Class<?>>>(ref, list));
+ }
+ list.add(cls);
+ }
+ }
+ }
+ catch(NoClassDefFoundError e) {
+ if(!cls.getCanonicalName().startsWith("experimentalcode.")) {
+ logger.warning("Exception in finding references for class " + cls.getCanonicalName() + " - missing referenced class?");
+ }
+ }
+ catch(Error e) {
+ logger.warning("Exception in finding references for class " + cls.getCanonicalName() + ": " + e, e);
+ }
+ }
+
private static String linkForClassName(String name) {
String link = name.replace(".", "/") + ".html";
return link;
@@ -253,10 +336,17 @@ public class DocumentReferences {
*/
public static ArrayList<Class<?>> findAllClassesWithReferences() {
ArrayList<Class<?>> references = new ArrayList<Class<?>>();
- for(final Class<?> cls : InspectionUtil.findAllImplementations(Object.class, false)) {
+ for(final Class<?> cls : InspectionUtil.findAllImplementations(Object.class, true)) {
if(cls.isAnnotationPresent(Reference.class)) {
references.add(cls);
}
+ else {
+ for(Method m : cls.getDeclaredMethods()) {
+ if(m.isAnnotationPresent(Reference.class)) {
+ references.add(cls);
+ }
+ }
+ }
}
return references;
}
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 dd7746e8..56326655 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) 2011
+Copyright (C) 2012
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 9ef3f688..c077e9d3 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) 2011
+ Copyright (C) 2012
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/JSONResultHandler.java b/src/de/lmu/ifi/dbs/elki/application/jsmap/JSONResultHandler.java
index 96a24dcb..7fc26496 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) 2011
+ Copyright (C) 2012
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 873420fd..5b210795 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) 2011
+ Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/application/jsmap/package-info.java
index f359198a..e89e272c 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) 2011
+Copyright (C) 2012
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 b81ac8f5..35b3b3d9 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) 2011
+Copyright (C) 2012
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
index 0cb950af..0419f791 100644
--- a/src/de/lmu/ifi/dbs/elki/application/visualization/KNNExplorer.java
+++ b/src/de/lmu/ifi/dbs/elki/application/visualization/KNNExplorer.java
@@ -4,7 +4,7 @@ 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,8 +29,6 @@ import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
-import java.util.List;
-import java.util.ListIterator;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
@@ -62,12 +60,14 @@ import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
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.KNNResult;
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.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;
@@ -79,7 +79,6 @@ 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.scales.LinearScale;
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;
@@ -393,7 +392,7 @@ public class KNNExplorer<O extends NumberVector<?, ?>, D extends NumberDistance<
try {
StyleLibrary style = new PropertiesBasedStyleLibrary();
- SVGSimpleLinearAxis.drawAxis(plot, viewport, this.s, 0.0, StyleLibrary.SCALE, 0.0, 0.0, true, false, style);
+ SVGSimpleLinearAxis.drawAxis(plot, viewport, this.s, 0.0, StyleLibrary.SCALE, 0.0, 0.0, SVGSimpleLinearAxis.LabelStyle.LEFTHAND, style);
}
catch(CSSNamingConflict e) {
LoggingUtil.exception(e);
@@ -436,21 +435,21 @@ public class KNNExplorer<O extends NumberVector<?, ?>, D extends NumberDistance<
for(Object o : sel) {
DBID idx = (DBID) o;
- List<DistanceResultPair<D>> knn = knnQuery.getKNNForDBID(idx, k);
+ KNNResult<D> knn = knnQuery.getKNNForDBID(idx, k);
- double maxdist = knn.get(knn.size() - 1).getDistance().doubleValue();
+ double maxdist = knn.getKNNDistance().doubleValue();
// avoid division by zero.
if(maxdist == 0) {
maxdist = 1;
}
- for(ListIterator<DistanceResultPair<D>> iter = knn.listIterator(knn.size()); iter.hasPrevious();) {
- DistanceResultPair<D> pair = iter.previous();
+ for (int i = knn.size() - 1; i >= 0; i--) {
+ DistanceResultPair<D> pair = knn.get(i);
Element line = plotSeries(pair.getDBID(), MAXRESOLUTION);
double dist = pair.getDistance().doubleValue() / maxdist;
Color color = getColor(dist);
String colstr = "#" + Integer.toHexString(color.getRGB()).substring(2);
- String width = (pair.getDBID() == idx) ? "0.5%" : "0.2%";
+ String width = (pair.getDBID().equals(idx)) ? "0.5%" : "0.2%";
SVGUtil.setStyle(line, "stroke: " + colstr + "; stroke-width: " + width + "; fill: none");
newe.appendChild(line);
// put into cache
diff --git a/src/de/lmu/ifi/dbs/elki/application/visualization/package-info.java b/src/de/lmu/ifi/dbs/elki/application/visualization/package-info.java
index 70870cfd..717a80f9 100644
--- a/src/de/lmu/ifi/dbs/elki/application/visualization/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/application/visualization/package-info.java
@@ -6,7 +6,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2011
+Copyright (C) 2012
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/AbstractNumberVector.java b/src/de/lmu/ifi/dbs/elki/data/AbstractNumberVector.java
index 32d43d44..eb783ab5 100644
--- a/src/de/lmu/ifi/dbs/elki/data/AbstractNumberVector.java
+++ b/src/de/lmu/ifi/dbs/elki/data/AbstractNumberVector.java
@@ -1,10 +1,12 @@
package de.lmu.ifi.dbs.elki.data;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayLikeUtil;
+
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -101,4 +103,9 @@ public abstract class AbstractNumberVector<V extends AbstractNumberVector<? exte
public short shortValue(int dimension) {
return (short) longValue(dimension);
}
+
+ @Override
+ public V newNumberVector(double[] values) {
+ return newNumberVector(values, ArrayLikeUtil.doubleArrayAdapter());
+ }
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/data/Arithmetic.java b/src/de/lmu/ifi/dbs/elki/data/Arithmetic.java
index 3a2959ca..75c3cad8 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) 2011
+ Copyright (C) 2012
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 3c77a4d5..7272e235 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) 2011
+ Copyright (C) 2012
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 b51ed4e3..4756fef4 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,12 +26,13 @@ package de.lmu.ifi.dbs.elki.data;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.BitSet;
-import java.util.List;
-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;
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;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
/**
* Provides a BitVector wrapping a BitSet.
@@ -40,6 +41,11 @@ import de.lmu.ifi.dbs.elki.persistent.ByteBufferSerializer;
*/
public class BitVector extends AbstractNumberVector<BitVector, Bit> implements ByteBufferSerializer<BitVector> {
/**
+ * Static instance.
+ */
+ public static final BitVector STATIC = new BitVector(new BitSet(0), 0);
+
+ /**
* Storing the bits.
*/
private BitSet bits;
@@ -80,21 +86,6 @@ public class BitVector extends AbstractNumberVector<BitVector, Bit> implements B
}
/**
- * Provides a new BitVector corresponding to the bits in the given list.
- *
- * @param bits an array of bits specifying the bits in this bit vector
- */
- public BitVector(List<Bit> bits) {
- this.bits = new BitSet(bits.size());
- int i = 0;
- for(Bit bit : bits) {
- this.bits.set(i, bit.bitValue());
- i++;
- }
- this.dimensionality = bits.size();
- }
-
- /**
* The dimensionality of the binary vector space of which this BitVector is an
* element.
*
@@ -177,110 +168,6 @@ public class BitVector extends AbstractNumberVector<BitVector, Bit> implements B
}
/**
- * Returns a Matrix representing in one row and
- * <code>getDimensionality()</code> columns the values of this BitVector as
- * double values.
- *
- * @return a Matrix representing in one row and
- * <code>getDimensionality()</code> columns the values of this
- * BitVector as double values
- *
- * @see de.lmu.ifi.dbs.elki.data.NumberVector#getRowVector()
- */
- @Override
- public Matrix getRowVector() {
- double[] values = new double[dimensionality];
- for(int i = 0; i < dimensionality; i++) {
- values[i] = bits.get(i) ? 1 : 0;
- }
- return new Matrix(new double[][] { values });
- }
-
- /**
- * Returns a bit vector equal to this bit vector, if k is not 0, a bit vector
- * with all components equal to zero otherwise.
- *
- * @param k used as multiplier 1 if k &ne; 0, otherwise the resulting bit
- * vector will have all values equal to zero
- * @return a bit vector equal to this bit vector, if k is not 0, a bit vector
- * with all components equal to zero otherwise
- */
- @Override
- public BitVector multiplicate(double k) {
- if(k == 0) {
- return nullVector();
- }
- else {
- return new BitVector(bits, dimensionality);
- }
- }
-
- /**
- * Returns the inverse of the bit vector.
- *
- * The result is the same as obtained by flipping all bits in the underlying
- * BitSet.
- *
- * @return the inverse of the bit vector
- * @see BitSet#flip(int,int)
- */
- @Override
- public BitVector negativeVector() {
- BitSet newBits = (BitSet) bits.clone();
- newBits.flip(0, dimensionality);
- return new BitVector(newBits, dimensionality);
- }
-
- /**
- * Returns a bit vector of equal dimensionality but containing 0 only.
- *
- * @return a bit vector of equal dimensionality but containing 0 only
- */
- @Override
- public BitVector nullVector() {
- return new BitVector(new BitSet(), dimensionality);
- }
-
- /**
- * Returns a bit vector corresponding to an XOR operation on this and the
- * specified bit vector.
- *
- * @param fv the bit vector to add
- * @return a new bit vector corresponding to an XOR operation on this and the
- * specified bit vector
- */
- @Override
- public BitVector plus(BitVector fv) {
- if(this.getDimensionality() != fv.getDimensionality()) {
- throw new IllegalArgumentException("Incompatible dimensionality: " + this.getDimensionality() + " - " + fv.getDimensionality() + ".");
- }
-
- BitVector bv = new BitVector((BitSet) fv.bits.clone(), this.dimensionality);
- bv.bits.xor(this.bits);
- return bv;
- }
-
- /**
- * Returns a bit vector corresponding to an NXOR operation on this and the
- * specified bit vector.
- *
- * @param fv the bit vector to add
- * @return a new bit vector corresponding to an NXOR operation on this and the
- * specified bit vector
- */
- @Override
- public BitVector minus(BitVector fv) {
- if(this.getDimensionality() != fv.getDimensionality()) {
- throw new IllegalArgumentException("Incompatible dimensionality: " + this.getDimensionality() + " - " + fv.getDimensionality() + ".");
- }
-
- BitVector bv = new BitVector((BitSet) fv.bits.clone(), this.dimensionality);
- bv.bits.flip(0, dimensionality);
- bv.bits.xor(this.bits);
- return bv;
- }
-
- /**
* Returns whether this BitVector contains all bits that are set to true in
* the specified BitSet.
*
@@ -347,74 +234,29 @@ public class BitVector extends AbstractNumberVector<BitVector, Bit> implements B
}
}
- /**
- * Provides the scalar product (inner product) of this BitVector and the given
- * BitVector.
- *
- * As multiplication of Bits, the logical AND operation is used. The result is
- * 0 if the number of bits after the AND operation is a multiple of 2,
- * otherwise the result is 1.
- *
- * @param fv the BitVector to compute the scalar product for
- * @return the scalar product (inner product) of this and the given BitVector
- */
- @Override
- public Bit scalarProduct(BitVector fv) {
- if(this.getDimensionality() != fv.getDimensionality()) {
- throw new IllegalArgumentException("Incompatible dimensionality: " + this.getDimensionality() + " - " + fv.getDimensionality() + ".");
- }
- BitSet bs = (BitSet) this.bits.clone();
- bs.and(fv.bits);
-
- return new Bit(bs.cardinality() % 2 == 1);
- }
-
@Override
- public BitVector newInstance(double[] values) {
- int dim = values.length;
+ public <A> BitVector newFeatureVector(A array, ArrayAdapter<Bit, A> adapter) {
+ int dim = adapter.size(array);
BitSet bits = new BitSet(dim);
for(int i = 0; i < dim; i++) {
- if(values[i] >= 0.5) {
- bits.set(i);
- }
+ bits.set(i, adapter.get(array, i).bitValue());
+ i++;
}
return new BitVector(bits, dim);
}
@Override
- public BitVector newInstance(Vector values) {
- int dim = values.getDimensionality();
+ public <A> BitVector newNumberVector(A array, NumberArrayAdapter<?, A> adapter) {
+ int dim = adapter.size(array);
BitSet bits = new BitSet(dim);
for(int i = 0; i < dim; i++) {
- if(values.get(i) >= 0.5) {
+ if(adapter.getDouble(array, i) >= 0.5) {
bits.set(i);
}
}
return new BitVector(bits, dim);
}
- /**
- * Creates and returns a new BitVector based on the passed values.
- *
- * @return a new instance of this BitVector with the specified values
- *
- */
- @Override
- public BitVector newInstance(Bit[] values) {
- return new BitVector(values);
- }
-
- /**
- * Creates and returns a new BitVector based on the passed values.
- *
- * @return a new instance of this BitVector with the specified values
- *
- */
- @Override
- public BitVector newInstance(List<Bit> values) {
- return new BitVector(values);
- }
-
@Override
public BitVector fromByteBuffer(ByteBuffer buffer) throws IOException {
short dimensionality = buffer.getShort();
@@ -425,9 +267,9 @@ public class BitVector extends AbstractNumberVector<BitVector, Bit> implements B
// read values
BitSet values = new BitSet(dimensionality);
byte b = 0;
- for(int i = 0; i < dimensionality; i ++) {
+ for(int i = 0; i < dimensionality; i++) {
// read the next byte when needed.
- if ((i & 7) == 0) {
+ if((i & 7) == 0) {
b = buffer.get();
}
final byte bit = (byte) (1 << (i & 7));
@@ -441,7 +283,7 @@ public class BitVector extends AbstractNumberVector<BitVector, Bit> implements B
@Override
public void toByteBuffer(ByteBuffer buffer, BitVector vec) throws IOException {
final int len = getByteSize(vec);
- assert(vec.getDimensionality() <= Short.MAX_VALUE);
+ assert (vec.getDimensionality() <= Short.MAX_VALUE);
final short dim = (short) vec.getDimensionality();
if(buffer.remaining() < len) {
throw new IOException("Not enough space for the bit vector!");
@@ -460,15 +302,29 @@ public class BitVector extends AbstractNumberVector<BitVector, Bit> implements B
b &= ~mask;
}
// Write when appropriate
- if ((i & 7) == 7 || i == dim - 1) {
+ if((i & 7) == 7 || i == dim - 1) {
buffer.put(b);
b = 0;
}
}
}
-
+
@Override
public int getByteSize(BitVector vec) {
return ByteArrayUtil.SIZE_SHORT + (vec.getDimensionality() + 7) / 8;
}
+
+ /**
+ * Parameterization class
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected BitVector makeInstance() {
+ return STATIC;
+ }
+ }
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/data/ClassLabel.java b/src/de/lmu/ifi/dbs/elki/data/ClassLabel.java
index 3ec5874c..8a3b0b30 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) 2011
+ Copyright (C) 2012
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.data;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import java.util.HashMap;
+
import de.lmu.ifi.dbs.elki.utilities.InspectionUtilFrequentlyScanned;
/**
@@ -76,16 +78,27 @@ public abstract class ClassLabel implements Comparable<ClassLabel> {
public int hashCode() {
return toString().hashCode();
}
-
+
/**
* Class label factory
*
* @author Erich Schubert
- *
+ *
* @apiviz.has ClassLabel - - «creates»
* @apiviz.stereotype factory
*/
public static abstract class Factory<L extends ClassLabel> implements InspectionUtilFrequentlyScanned {
+ /**
+ * Set for reusing the same objects.
+ */
+ protected HashMap<String, L> existing = new HashMap<String, L>();
+
+ /**
+ * Convert a string into a class label
+ *
+ * @param lbl String to convert
+ * @return Class label instance.
+ */
public abstract L makeFromString(String lbl);
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/data/Cluster.java b/src/de/lmu/ifi/dbs/elki/data/Cluster.java
index 7bc3fc30..6863e995 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) 2011
+ Copyright (C) 2012
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/Clustering.java b/src/de/lmu/ifi/dbs/elki/data/Clustering.java
index 13203175..eaac4418 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) 2011
+ Copyright (C) 2012
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/DoubleVector.java b/src/de/lmu/ifi/dbs/elki/data/DoubleVector.java
index 76405d60..a8f8db6d 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,15 +23,20 @@ package de.lmu.ifi.dbs.elki.data;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import gnu.trove.list.TDoubleList;
+
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Iterator;
import java.util.List;
-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;
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.ArrayLikeUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
/**
* A DoubleVector is to store real values approximately as double values.
@@ -42,6 +47,11 @@ import de.lmu.ifi.dbs.elki.persistent.ByteBufferSerializer;
*/
public class DoubleVector extends AbstractNumberVector<DoubleVector, Double> implements ByteBufferSerializer<DoubleVector> {
/**
+ * Static factory instance
+ */
+ public static final DoubleVector STATIC = new DoubleVector(new double[0], true);
+
+ /**
* Keeps the values of the real vector
*/
private double[] values;
@@ -101,7 +111,7 @@ public class DoubleVector extends AbstractNumberVector<DoubleVector, Double> imp
* @param columnMatrix a matrix of one column
*/
public DoubleVector(Vector columnMatrix) {
- values = new double[columnMatrix.getRowDimensionality()];
+ values = new double[columnMatrix.getDimensionality()];
for(int i = 0; i < values.length; i++) {
values[i] = columnMatrix.get(i);
}
@@ -188,74 +198,6 @@ public class DoubleVector extends AbstractNumberVector<DoubleVector, Double> imp
}
@Override
- public Matrix getRowVector() {
- return new Matrix(new double[][] { values.clone() });
- }
-
- @Override
- public DoubleVector plus(DoubleVector fv) {
- if(fv.getDimensionality() != this.getDimensionality()) {
- throw new IllegalArgumentException("Incompatible dimensionality: " + this.getDimensionality() + " - " + fv.getDimensionality() + ".");
- }
- double[] values = new double[this.values.length];
- for(int i = 0; i < values.length; i++) {
- values[i] = this.values[i] + fv.values[i];
- }
- return new DoubleVector(values, true);
- }
-
- @Override
- public DoubleVector minus(DoubleVector fv) {
- if(fv.getDimensionality() != this.getDimensionality()) {
- throw new IllegalArgumentException("Incompatible dimensionality: " + this.getDimensionality() + " - " + fv.getDimensionality() + ".");
- }
- double[] values = new double[this.values.length];
- for(int i = 0; i < values.length; i++) {
- values[i] = this.values[i] - fv.values[i];
- }
- return new DoubleVector(values, true);
- }
-
- @Override
- public DoubleVector nullVector() {
- return new DoubleVector(new double[this.values.length], true);
- }
-
- @Override
- public DoubleVector negativeVector() {
- return multiplicate(-1);
- }
-
- @Override
- public DoubleVector multiplicate(double k) {
- double[] values = new double[this.values.length];
- for(int i = 0; i < values.length; i++) {
- values[i] = this.values[i] * k;
- }
- return new DoubleVector(values, true);
- }
-
- /**
- * Provides the scalar product (inner product) of this and the given
- * DoubleVector.
- *
- * @param d the DoubleVector to compute the scalar product for
- * @return the scalar product (inner product) of this and the given
- * DoubleVector
- */
- @Override
- public Double scalarProduct(DoubleVector d) {
- if(this.getDimensionality() != d.getDimensionality()) {
- throw new IllegalArgumentException("Incompatible dimensionality: " + this.getDimensionality() + " - " + d.getDimensionality() + ".");
- }
- double result = 0.0;
- for(int i = 0; i < this.getDimensionality(); i++) {
- result += this.values[i] * d.values[i];
- }
- return result;
- }
-
- @Override
public String toString() {
StringBuffer featureLine = new StringBuffer();
for(int i = 0; i < values.length; i++) {
@@ -268,23 +210,31 @@ public class DoubleVector extends AbstractNumberVector<DoubleVector, Double> imp
}
@Override
- public DoubleVector newInstance(Vector values) {
- return new DoubleVector(values);
- }
-
- @Override
- public DoubleVector newInstance(Double[] values) {
+ public DoubleVector newNumberVector(double[] values) {
return new DoubleVector(values);
}
@Override
- public DoubleVector newInstance(double[] values) {
- return new DoubleVector(values);
+ public <A> DoubleVector newFeatureVector(A array, ArrayAdapter<Double, A> adapter) {
+ int dim = adapter.size(array);
+ double[] values = new double[dim];
+ for(int i = 0; i < dim; i++) {
+ values[i] = adapter.get(array, i);
+ }
+ return new DoubleVector(values, true);
}
@Override
- public DoubleVector newInstance(List<Double> values) {
- return new DoubleVector(values);
+ public <A> DoubleVector newNumberVector(A array, NumberArrayAdapter<?, A> adapter) {
+ if(adapter == ArrayLikeUtil.TDOUBLELISTADAPTER) {
+ return new DoubleVector(((TDoubleList) array).toArray(), true);
+ }
+ final int dim = adapter.size(array);
+ double[] values = new double[dim];
+ for(int i = 0; i < dim; i++) {
+ values[i] = adapter.getDouble(array, i);
+ }
+ return new DoubleVector(values, true);
}
@Override
@@ -294,9 +244,9 @@ public class DoubleVector extends AbstractNumberVector<DoubleVector, Double> imp
if(buffer.remaining() < len) {
throw new IOException("Not enough data for a double vector!");
}
- double[] values = new double[dimensionality];
+ final double[] values = new double[dimensionality];
buffer.asDoubleBuffer().get(values);
- return new DoubleVector(values, false);
+ return new DoubleVector(values, true);
}
@Override
@@ -314,4 +264,18 @@ public class DoubleVector extends AbstractNumberVector<DoubleVector, Double> imp
public int getByteSize(DoubleVector vec) {
return ByteArrayUtil.SIZE_SHORT + ByteArrayUtil.SIZE_DOUBLE * vec.getDimensionality();
}
+
+ /**
+ * Parameterization class
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected DoubleVector makeInstance() {
+ return STATIC;
+ }
+ }
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/data/ExternalID.java b/src/de/lmu/ifi/dbs/elki/data/ExternalID.java
index 228b97d0..1fc9873c 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) 2011
+ Copyright (C) 2012
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 c4a0fa1d..12999159 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) 2011
+ Copyright (C) 2012
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.data;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.List;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayAdapter;
/**
* Generic FeatureVector class that can contain any type of data (i.e. numerical
@@ -65,16 +65,10 @@ public interface FeatureVector<V extends FeatureVector<? extends V, D>, D> {
/**
* Returns a new FeatureVector of V for the given values.
*
- * @param values the values of the featureVector
+ * @param array the values of the featureVector
+ * @param adapter adapter class
+ * @param <A> Array type
* @return a new FeatureVector of V for the given values
*/
- V newInstance(D[] values);
-
- /**
- * Returns a new FeatureVector of V for the given values.
- *
- * @param values the values of the featureVector
- * @return a new FeatureVector of V for the given values
- */
- V newInstance(List<D> values);
+ <A> V newFeatureVector(A array, ArrayAdapter<D, A> adapter);
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/data/FloatVector.java b/src/de/lmu/ifi/dbs/elki/data/FloatVector.java
index 6943eb8a..e34e97d9 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,11 +28,13 @@ import java.nio.ByteBuffer;
import java.util.Iterator;
import java.util.List;
-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;
import de.lmu.ifi.dbs.elki.persistent.ByteBufferSerializer;
-import de.lmu.ifi.dbs.elki.utilities.Util;
+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.NumberArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
/**
* A FloatVector is to store real values approximately as float values.
@@ -41,6 +43,11 @@ import de.lmu.ifi.dbs.elki.utilities.Util;
*/
public class FloatVector extends AbstractNumberVector<FloatVector, Float> implements ByteBufferSerializer<FloatVector> {
/**
+ * Static factory instance
+ */
+ public static final FloatVector STATIC = new FloatVector(new float[0], true);
+
+ /**
* Keeps the values of the float vector
*/
private float[] values;
@@ -100,9 +107,9 @@ public class FloatVector extends AbstractNumberVector<FloatVector, Float> implem
* @param columnMatrix a matrix of one column
*/
public FloatVector(Vector columnMatrix) {
- values = new float[columnMatrix.getRowDimensionality()];
+ values = new float[columnMatrix.getDimensionality()];
for(int i = 0; i < values.length; i++) {
- values[i] = (float) columnMatrix.get(i, 0);
+ values[i] = (float) columnMatrix.get(i);
}
}
@@ -143,75 +150,7 @@ public class FloatVector extends AbstractNumberVector<FloatVector, Float> implem
@Override
public Vector getColumnVector() {
- return new Vector(Util.convertToDoubles(values));
- }
-
- @Override
- public Matrix getRowVector() {
- return new Matrix(new double[][] { Util.convertToDoubles(values) });
- }
-
- @Override
- public FloatVector plus(FloatVector fv) {
- if(fv.getDimensionality() != this.getDimensionality()) {
- throw new IllegalArgumentException("Incompatible dimensionality: " + this.getDimensionality() + " - " + fv.getDimensionality() + ".");
- }
- float[] values = new float[this.values.length];
- for(int i = 0; i < values.length; i++) {
- values[i] = this.values[i] + fv.getValue(i + 1);
- }
- return new FloatVector(values, true);
- }
-
- @Override
- public FloatVector minus(FloatVector fv) {
- if(fv.getDimensionality() != this.getDimensionality()) {
- throw new IllegalArgumentException("Incompatible dimensionality: " + this.getDimensionality() + " - " + fv.getDimensionality() + ".");
- }
- float[] values = new float[this.values.length];
- for(int i = 0; i < values.length; i++) {
- values[i] = this.values[i] - fv.getValue(i + 1);
- }
- return new FloatVector(values, true);
- }
-
- /**
- * Provides the scalar product (inner product) of this and the given
- * FloatVector.
- *
- * @param f the FloatVector to compute the scalar product for
- * @return the scalar product (inner product) of this and the given
- * FloatVector
- */
- @Override
- public Float scalarProduct(FloatVector f) {
- if(this.getDimensionality() != f.getDimensionality()) {
- throw new IllegalArgumentException("Incompatible dimensionality: " + this.getDimensionality() + " - " + f.getDimensionality() + ".");
- }
- float result = 0.0f;
- for(int i = 0; i < this.getDimensionality(); i++) {
- result += this.values[i] * f.values[i];
- }
- return result;
- }
-
- @Override
- public FloatVector nullVector() {
- return new FloatVector(new float[this.values.length], true);
- }
-
- @Override
- public FloatVector negativeVector() {
- return multiplicate(-1);
- }
-
- @Override
- public FloatVector multiplicate(double k) {
- float[] values = new float[this.values.length];
- for(int i = 0; i < values.length; i++) {
- values[i] = (float) (this.values[i] * k);
- }
- return new FloatVector(values, true);
+ return new Vector(ArrayLikeUtil.toPrimitiveDoubleArray(values, ArrayLikeUtil.FLOATARRAYADAPTER));
}
@Override
@@ -226,30 +165,24 @@ public class FloatVector extends AbstractNumberVector<FloatVector, Float> implem
return featureLine.toString();
}
- /**
- * @return a new FloatVector with the specified values
- */
- @Override
- public FloatVector newInstance(Vector values) {
- return new FloatVector(values);
- }
-
- /**
- * @return a new FloatVector with the specified values
- */
- @Override
- public FloatVector newInstance(double[] values) {
- return new FloatVector(Util.convertToFloat(values));
- }
-
@Override
- public FloatVector newInstance(Float[] values) {
- return new FloatVector(values);
+ public <A> FloatVector newFeatureVector(A array, ArrayAdapter<Float, A> adapter) {
+ int dim = adapter.size(array);
+ float[] values = new float[dim];
+ for(int i = 0; i < dim; i++) {
+ values[i] = adapter.get(array, i);
+ }
+ return new FloatVector(values, true);
}
@Override
- public FloatVector newInstance(List<Float> values) {
- return new FloatVector(values);
+ public <A> FloatVector newNumberVector(A array, NumberArrayAdapter<?, A> adapter) {
+ int dim = adapter.size(array);
+ float[] values = new float[dim];
+ for(int i = 0; i < dim; i++) {
+ values[i] = adapter.getFloat(array, i);
+ }
+ return new FloatVector(values, true);
}
@Override
@@ -281,4 +214,18 @@ public class FloatVector extends AbstractNumberVector<FloatVector, Float> implem
public int getByteSize(FloatVector vec) {
return ByteArrayUtil.SIZE_SHORT + ByteArrayUtil.SIZE_FLOAT * vec.getDimensionality();
}
+
+ /**
+ * Parameterization class
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected FloatVector makeInstance() {
+ return STATIC;
+ }
+ }
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/data/HierarchicalClassLabel.java b/src/de/lmu/ifi/dbs/elki/data/HierarchicalClassLabel.java
index 499a40be..5e958fd7 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -77,7 +77,7 @@ public class HierarchicalClassLabel extends ClassLabel {
this.separatorPattern = regex;
this.separatorString = separator;
String[] levelwiseStrings = separatorPattern.split(name);
- this.levelwiseNames = new Comparable[levelwiseStrings.length];
+ this.levelwiseNames = new Comparable<?>[levelwiseStrings.length];
for(int i = 0; i < levelwiseStrings.length; i++) {
try {
levelwiseNames[i] = new Integer(levelwiseStrings[i]);
@@ -188,14 +188,19 @@ public class HierarchicalClassLabel extends ClassLabel {
* Factory class
*
* @author Erich Schubert
- *
+ *
* @apiviz.has HierarchicalClassLabel - - «creates»
* @apiviz.stereotype factory
*/
public static class Factory extends ClassLabel.Factory<HierarchicalClassLabel> {
@Override
public HierarchicalClassLabel makeFromString(String lbl) {
- return new HierarchicalClassLabel(lbl);
+ HierarchicalClassLabel l = existing.get(lbl);
+ if(l == null) {
+ l = new HierarchicalClassLabel(lbl);
+ existing.put(lbl, l);
+ }
+ return l;
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/data/HyperBoundingBox.java b/src/de/lmu/ifi/dbs/elki/data/HyperBoundingBox.java
index 3c4d50d6..feb5cace 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) 2011
+ Copyright (C) 2012
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/IntegerVector.java b/src/de/lmu/ifi/dbs/elki/data/IntegerVector.java
index af6d7299..ae0d8cce 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,13 +25,13 @@ package de.lmu.ifi.dbs.elki.data;
import java.io.IOException;
import java.nio.ByteBuffer;
-import java.util.Iterator;
-import java.util.List;
-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;
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;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
/**
* An IntegerVector is to store integer values.
@@ -40,6 +40,11 @@ import de.lmu.ifi.dbs.elki.persistent.ByteBufferSerializer;
*/
public class IntegerVector extends AbstractNumberVector<IntegerVector, Integer> implements ByteBufferSerializer<IntegerVector> {
/**
+ * Static instance (object factory)
+ */
+ public static final IntegerVector STATIC = new IntegerVector(new int[0], true);
+
+ /**
* Keeps the values of the real vector
*/
private int[] values;
@@ -58,20 +63,6 @@ public class IntegerVector extends AbstractNumberVector<IntegerVector, Integer>
}
/**
- * Provides a feature vector consisting of int values according to the
- * given Integer values.
- *
- * @param values the values to be set as values of the integer vector
- */
- public IntegerVector(List<Integer> values) {
- int i = 0;
- this.values = new int[values.size()];
- for(Iterator<Integer> iter = values.iterator(); iter.hasNext(); i++) {
- this.values[i] = (iter.next());
- }
- }
-
- /**
* Provides an IntegerVector consisting of the given integer values.
*
* @param values the values to be set as values of the IntegerVector
@@ -81,39 +72,6 @@ public class IntegerVector extends AbstractNumberVector<IntegerVector, Integer>
System.arraycopy(values, 0, this.values, 0, values.length);
}
- /**
- * Provides an IntegerVector consisting of the given integer values.
- *
- * @param values the values to be set as values of the IntegerVector
- */
- public IntegerVector(Integer[] values) {
- this.values = new int[values.length];
- for(int i = 0; i < values.length; i++) {
- this.values[i] = values[i];
- }
- }
-
- /**
- * Provides an IntegerVector consisting of the given double values.
- *
- * @param values the values to be set as values of the IntegerVector
- */
- public IntegerVector(double[] values) {
- this.values = new int[values.length];
- for(int i = 0; i < this.values.length; i++) {
- this.values[i] = (int) values[i];
- }
- }
-
- /**
- * Provides an IntegerVector consisting of the given double vectors values.
- *
- * @param values the values to be set as values of the IntegerVector
- */
- public IntegerVector(Vector values) {
- this(values.getArrayRef());
- }
-
@Override
public int getDimensionality() {
return values.length;
@@ -197,78 +155,6 @@ public class IntegerVector extends AbstractNumberVector<IntegerVector, Integer>
}
@Override
- public Matrix getRowVector() {
- double[] data = new double[values.length];
- for(int i = 0; i < values.length; i++) {
- data[i] = values[i];
- }
- return new Matrix(new double[][] { data });
- }
-
- @Override
- public IntegerVector plus(IntegerVector fv) {
- if(fv.getDimensionality() != this.getDimensionality()) {
- throw new IllegalArgumentException("Incompatible dimensionality: " + this.getDimensionality() + " - " + fv.getDimensionality() + ".");
- }
- int[] values = new int[this.values.length];
- for(int i = 0; i < values.length; i++) {
- values[i] = this.values[i] + fv.values[i];
- }
- return new IntegerVector(values, true);
- }
-
- @Override
- public IntegerVector minus(IntegerVector fv) {
- if(fv.getDimensionality() != this.getDimensionality()) {
- throw new IllegalArgumentException("Incompatible dimensionality: " + this.getDimensionality() + " - " + fv.getDimensionality() + ".");
- }
- int[] values = new int[this.values.length];
- for(int i = 0; i < values.length; i++) {
- values[i] = this.values[i] - fv.values[i];
- }
- return new IntegerVector(values, true);
- }
-
- @Override
- public IntegerVector nullVector() {
- return new IntegerVector(new int[this.values.length], true);
- }
-
- @Override
- public IntegerVector negativeVector() {
- return multiplicate(-1);
- }
-
- @Override
- public IntegerVector multiplicate(double k) {
- int[] values = new int[this.values.length];
- for(int i = 0; i < values.length; i++) {
- values[i] = (int) (this.values[i] * k);
- }
- return new IntegerVector(values, true);
- }
-
- /**
- * Provides the scalar product (inner product) of this and the given
- * IntegerVector.
- *
- * @param d the IntegerVector to compute the scalar product for
- * @return the scalar product (inner product) of this and the given
- * IntegerVector
- */
- @Override
- public Integer scalarProduct(IntegerVector d) {
- if(this.getDimensionality() != d.getDimensionality()) {
- throw new IllegalArgumentException("Incompatible dimensionality: " + this.getDimensionality() + " - " + d.getDimensionality() + ".");
- }
- double result = 0.0;
- for(int i = 0; i < this.getDimensionality(); i++) {
- result += this.values[i] * d.values[i];
- }
- return (int) result;
- }
-
- @Override
public String toString() {
StringBuffer featureLine = new StringBuffer();
for(int i = 0; i < values.length; i++) {
@@ -281,23 +167,23 @@ public class IntegerVector extends AbstractNumberVector<IntegerVector, Integer>
}
@Override
- public IntegerVector newInstance(Vector values) {
- return new IntegerVector(values);
- }
-
- @Override
- public IntegerVector newInstance(Integer[] values) {
- return new IntegerVector(values);
- }
-
- @Override
- public IntegerVector newInstance(double[] values) {
- return new IntegerVector(values);
+ public <A> IntegerVector newFeatureVector(A array, ArrayAdapter<Integer, A> adapter) {
+ int dim = adapter.size(array);
+ int[] values = new int[dim];
+ for(int i = 0; i < dim; i++) {
+ values[i] = adapter.get(array, i);
+ }
+ return new IntegerVector(values, true);
}
@Override
- public IntegerVector newInstance(List<Integer> values) {
- return new IntegerVector(values);
+ public <A> IntegerVector newNumberVector(A array, NumberArrayAdapter<?, A> adapter) {
+ int dim = adapter.size(array);
+ int[] values = new int[dim];
+ for(int i = 0; i < dim; i++) {
+ values[i] = adapter.getInteger(array, i);
+ }
+ return new IntegerVector(values, true);
}
@Override
@@ -327,4 +213,19 @@ public class IntegerVector extends AbstractNumberVector<IntegerVector, Integer>
public int getByteSize(IntegerVector vec) {
return ByteArrayUtil.SIZE_SHORT + ByteArrayUtil.SIZE_DOUBLE * vec.getDimensionality();
}
+
+
+ /**
+ * Parameterization class
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected IntegerVector makeInstance() {
+ return STATIC;
+ }
+ }
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/data/Interval.java b/src/de/lmu/ifi/dbs/elki/data/Interval.java
index 87e1f1b9..1b16fb88 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) 2011
+ Copyright (C) 2012
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 9dc73c0f..b1182112 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) 2011
+ Copyright (C) 2012
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.data;
*/
import java.util.ArrayList;
+import java.util.Collection;
import de.lmu.ifi.dbs.elki.utilities.FormatUtil;
@@ -50,7 +51,16 @@ public class LabelList extends ArrayList<String> {
/**
* Constructor.
*
- * @param initialCapacity
+ * @param c existing collection
+ */
+ public LabelList(Collection<? extends String> c) {
+ super(c);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param initialCapacity initial size
*/
public LabelList(int initialCapacity) {
super(initialCapacity);
@@ -60,4 +70,4 @@ public class LabelList extends ArrayList<String> {
public String toString() {
return FormatUtil.format(this, " ");
}
-}
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/data/ModifiableHyperBoundingBox.java b/src/de/lmu/ifi/dbs/elki/data/ModifiableHyperBoundingBox.java
index 3bb7610c..b11411bd 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,12 +25,12 @@ package de.lmu.ifi.dbs.elki.data;
import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil;
+import de.lmu.ifi.dbs.elki.logging.LoggingConfiguration;
/**
* MBR class allowing modifications (as opposed to {@link HyperBoundingBox}).
*
* @author Marisa Thoma
- *
*/
public class ModifiableHyperBoundingBox extends HyperBoundingBox {
/**
@@ -115,4 +115,29 @@ public class ModifiableHyperBoundingBox extends HyperBoundingBox {
public double[] getMaxRef() {
return max;
}
-}
+
+ /**
+ * Extend the bounding box by some other spatial object
+ *
+ * @param obj Spatial object to extend with
+ * @return true when the MBR changed.
+ */
+ public boolean extend(SpatialComparable obj) {
+ final int dim = min.length;
+ assert (!LoggingConfiguration.DEBUG || (obj.getDimensionality() == dim));
+ boolean extended = false;
+ for(int i = 0; i < dim; i++) {
+ final double omin = obj.getMin(i + 1);
+ final double omax = obj.getMax(i + 1);
+ if(omin < min[i]) {
+ min[i] = omin;
+ extended = true;
+ }
+ if(omax > max[i]) {
+ max[i] = omax;
+ extended = true;
+ }
+ }
+ return extended;
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/data/NumberVector.java b/src/de/lmu/ifi/dbs/elki/data/NumberVector.java
index 409ea9b7..1964277c 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,8 +24,9 @@ package de.lmu.ifi.dbs.elki.data;
*/
import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
-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.NumberArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable;
/**
* Interface NumberVector defines the methods that should be implemented by any
@@ -40,7 +41,7 @@ import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
* @apiviz.has Matrix
* @apiviz.has Vector
*/
-public interface NumberVector<V extends NumberVector<? extends V, N>, N extends Number> extends FeatureVector<V, N>, SpatialComparable {
+public interface NumberVector<V extends NumberVector<? extends V, N>, N extends Number> extends FeatureVector<V, N>, SpatialComparable, Parameterizable {
/**
* Returns the value in the specified dimension as double.
*
@@ -130,85 +131,20 @@ public interface NumberVector<V extends NumberVector<? extends V, N>, N extends
Vector getColumnVector();
/**
- * Returns a Matrix representing in one row and
- * <code>getDimensionality()</code> columns the values of this NumberVector of
- * V.
- *
- * @return a Matrix representing in one row and
- * <code>getDimensionality()</code> columns the values of this
- * NumberVector of V
- */
- Matrix getRowVector();
-
- /**
- * Provides a null vector of the same Vector Space as this NumberVector of V
- * (that is, of the same dimensionality).
- *
- * @return a null vector of the same Vector Space as this NumberVector of V
- * (that is, of the same dimensionality)
- */
- V nullVector();
-
- /**
- * Returns the additive inverse to this NumberVector of V.
- *
- * @return the additive inverse to this NumberVector of V
- */
- V negativeVector();
-
- /**
- * Returns a new NumberVector of V that is the sum of this NumberVector of V
- * and the given NumberVector of V.
- *
- * @param fv a NumberVector of V to be added to this NumberVector of V
- * @return a new NumberVector of V that is the sum of this NumberVector of V
- * and the given NumberVector of V
- */
- V plus(V fv);
-
- /**
- * Returns a new NumberVector of V that is the sum of this NumberVector of V
- * and the negativeVector() of given NumberVector of V.
- *
- * @param fv a NumberVector of V to be subtracted to this NumberVector of V
- * @return a new NumberVector of V that is the sum of this NumberVector of V
- * and the negative of given NumberVector of V
- */
- V minus(V fv);
-
- /**
- * Provides the scalar product (inner product) of this NumberVector of V and
- * the given NumberVector of V.
- *
- * @param fv the NumberVector of V to compute the scalar product for
- * @return the scalar product (inner product) of this and the given
- * NumberVector of V
- */
- N scalarProduct(V fv);
-
- /**
- * Returns a new NumberVector of V that is the result of a scalar
- * multiplication with the given scalar.
- *
- * @param k a scalar to multiply this NumberVector of V with
- * @return a new NumberVector of V that is the result of a scalar
- * multiplication with the given scalar
- */
- V multiplicate(double k);
-
- /**
* Returns a new NumberVector of N for the given values.
*
* @param values the values of the NumberVector
* @return a new NumberVector of N for the given values
*/
- V newInstance(double[] values);
+ V newNumberVector(double[] values);
/**
- * Returns a new NumberVector of N for the given values.
+ * Instantiate from any number-array like object.
*
- * @param values the values of the NumberVector
- * @return a new NumberVector of N for the given values
+ * @param <A> Array type
+ * @param array Array
+ * @param adapter Adapter
+ * @return a new NumberVector of N for the given values.
*/
- V newInstance(Vector values);
+ <A> V newNumberVector(A array, NumberArrayAdapter<?, A> adapter);
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/data/OneDimensionalDoubleVector.java b/src/de/lmu/ifi/dbs/elki/data/OneDimensionalDoubleVector.java
index d686e6b2..382ff9ae 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,20 +23,25 @@ package de.lmu.ifi.dbs.elki.data;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.List;
-
-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.ArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
/**
* Specialized class implementing a one-dimensional double vector without using
- * an array. Saves a little bit of memory, albeit we cannot avoid boxing as long as
- * we want to implement the interface.
+ * an array. Saves a little bit of memory, albeit we cannot avoid boxing as long
+ * as we want to implement the interface.
*
* @author Erich Schubert
*/
public class OneDimensionalDoubleVector extends AbstractNumberVector<OneDimensionalDoubleVector, Double> {
/**
+ * Static factory instance
+ */
+ public static final OneDimensionalDoubleVector STATIC = new OneDimensionalDoubleVector(Double.NaN);
+
+ /**
* The actual data value
*/
double val;
@@ -79,63 +84,28 @@ public class OneDimensionalDoubleVector extends AbstractNumberVector<OneDimensio
}
@Override
- public Matrix getRowVector() {
- return new Matrix(new double[][] { { val } });
+ public <A> OneDimensionalDoubleVector newFeatureVector(A array, ArrayAdapter<Double, A> adapter) {
+ assert (adapter.size(array) == 1) : "Incorrect dimensionality for 1-dimensional vector.";
+ return new OneDimensionalDoubleVector(adapter.get(array, 0));
}
@Override
- public OneDimensionalDoubleVector nullVector() {
- return new OneDimensionalDoubleVector(0.0);
+ public <A> OneDimensionalDoubleVector newNumberVector(A array, NumberArrayAdapter<?, A> adapter) {
+ assert (adapter.size(array) == 1) : "Incorrect dimensionality for 1-dimensional vector.";
+ return new OneDimensionalDoubleVector(adapter.getDouble(array, 0));
}
- @Override
- public OneDimensionalDoubleVector negativeVector() {
- return new OneDimensionalDoubleVector(-this.val);
- }
-
- @Override
- public OneDimensionalDoubleVector plus(OneDimensionalDoubleVector fv) {
- return new OneDimensionalDoubleVector(this.val + fv.val);
- }
-
- @Override
- public OneDimensionalDoubleVector minus(OneDimensionalDoubleVector fv) {
- return new OneDimensionalDoubleVector(this.val - fv.val);
- }
-
- @Override
- public Double scalarProduct(OneDimensionalDoubleVector fv) {
- return this.val * fv.val;
- }
-
- @Override
- public OneDimensionalDoubleVector multiplicate(double k) {
- return new OneDimensionalDoubleVector(this.val * k);
- }
-
- @Override
- public OneDimensionalDoubleVector newInstance(double[] values) {
- assert (values.length == 1) : "Incorrect dimensionality for 1-dimensional vector.";
- return new OneDimensionalDoubleVector(values[0]);
- }
-
- @Override
- public OneDimensionalDoubleVector newInstance(Vector values) {
- assert (values.getDimensionality() == 1) : "Incorrect dimensionality for 1-dimensional vector.";
- return new OneDimensionalDoubleVector(values.get(0));
- }
-
- @Override
- public OneDimensionalDoubleVector newInstance(Double[] values) {
- assert (values != null) : "newInstace(null) is not allowed.";
- assert (values.length == 1) : "Incorrect dimensionality for 1-dimensional vector.";
- return new OneDimensionalDoubleVector(values[0]);
- }
-
- @Override
- public OneDimensionalDoubleVector newInstance(List<Double> values) {
- assert (values != null) : "newInstace(null) is not allowed.";
- assert (values.size() == 1) : "Incorrect dimensionality for 1-dimensional vector.";
- return new OneDimensionalDoubleVector(values.get(0));
+ /**
+ * Parameterization class
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected OneDimensionalDoubleVector makeInstance() {
+ return STATIC;
+ }
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/data/ParameterizationFunction.java b/src/de/lmu/ifi/dbs/elki/data/ParameterizationFunction.java
index b74c902d..29e46c96 100644
--- a/src/de/lmu/ifi/dbs/elki/data/ParameterizationFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/data/ParameterizationFunction.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -30,6 +30,9 @@ import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
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.FormatUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
/**
* A parameterization function describes all lines in a d-dimensional feature
@@ -61,6 +64,11 @@ public class ParameterizationFunction extends DoubleVector implements TextWritea
}
/**
+ * Static factory
+ */
+ public static final ParameterizationFunction STATIC = new ParameterizationFunction(new double[] { 0.0 });
+
+ /**
* A small number to handle numbers near 0 as 0.
*/
public static final double DELTA = 1E-10;
@@ -549,22 +557,41 @@ public class ParameterizationFunction extends DoubleVector implements TextWritea
}
@Override
- public DoubleVector newInstance(double[] values) {
+ public ParameterizationFunction newNumberVector(double[] values) {
return new ParameterizationFunction(values);
}
@Override
- public DoubleVector newInstance(Vector values) {
+ public <A> ParameterizationFunction newFeatureVector(A array, ArrayAdapter<Double, A> adapter) {
+ final int dim = adapter.size(array);
+ double[] values = new double[dim];
+ for(int i = 0; i < dim; i++) {
+ values[i] = adapter.get(array, i);
+ }
return new ParameterizationFunction(values);
}
@Override
- public DoubleVector newInstance(Double[] values) {
+ public <A> ParameterizationFunction newNumberVector(A array, NumberArrayAdapter<?, A> adapter) {
+ final int dim = adapter.size(array);
+ double[] values = new double[dim];
+ for(int i = 0; i < dim; i++) {
+ values[i] = adapter.getDouble(array, i);
+ }
return new ParameterizationFunction(values);
}
- @Override
- public DoubleVector newInstance(List<Double> values) {
- return new ParameterizationFunction(values);
+ /**
+ * Parameterization class
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected ParameterizationFunction makeInstance() {
+ return STATIC;
+ }
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/data/RationalNumber.java b/src/de/lmu/ifi/dbs/elki/data/RationalNumber.java
index ac26b926..5b2e08fa 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) 2011
+ Copyright (C) 2012
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 b71dd9bb..ad88295e 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) 2011
+ Copyright (C) 2012
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.data;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
/**
* A simple class label casting a String as it is as label.
*
@@ -36,10 +35,10 @@ public class SimpleClassLabel extends ClassLabel {
* Holds the String designating the label.
*/
private String label;
-
+
/**
* Constructor.
- *
+ *
* @param label Label
*/
public SimpleClassLabel(String label) {
@@ -107,14 +106,19 @@ public class SimpleClassLabel extends ClassLabel {
* Factory class
*
* @author Erich Schubert
- *
+ *
* @apiviz.has SimpleClassLabel - - «creates»
* @apiviz.stereotype factory
*/
public static class Factory extends ClassLabel.Factory<SimpleClassLabel> {
@Override
public SimpleClassLabel makeFromString(String lbl) {
- return new SimpleClassLabel(lbl);
+ SimpleClassLabel l = existing.get(lbl);
+ if(l == null) {
+ l = new SimpleClassLabel(lbl);
+ existing.put(lbl, l);
+ }
+ return l;
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/data/SparseFeatureVector.java b/src/de/lmu/ifi/dbs/elki/data/SparseFeatureVector.java
index aad17813..4359d841 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) 2011
+ Copyright (C) 2012
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 b9066d40..1ce8c5f7 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,16 +23,19 @@ package de.lmu.ifi.dbs.elki.data;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import gnu.trove.impl.unmodifiable.TUnmodifiableIntFloatMap;
+import gnu.trove.iterator.TIntFloatIterator;
+import gnu.trove.map.TIntFloatMap;
+import gnu.trove.map.hash.TIntFloatHashMap;
+
import java.util.Arrays;
import java.util.BitSet;
-import java.util.List;
-import java.util.Map;
import de.lmu.ifi.dbs.elki.datasource.parser.SparseFloatVectorLabelParser;
-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.ClassGenericsUtil;
-import de.lmu.ifi.dbs.elki.utilities.Util;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
/**
* <p>
@@ -47,6 +50,11 @@ import de.lmu.ifi.dbs.elki.utilities.Util;
// TODO: implement ByteArraySerializer<SparseFloatVector>
public class SparseFloatVector extends AbstractNumberVector<SparseFloatVector, Float> implements SparseNumberVector<SparseFloatVector, Float> {
/**
+ * Static instance
+ */
+ public static final SparseFloatVector STATIC = new SparseFloatVector(new int[0], new float[0], -1);
+
+ /**
* Indexes of values
*/
private int[] indexes;
@@ -85,7 +93,7 @@ public class SparseFloatVector extends AbstractNumberVector<SparseFloatVector, F
* to cover the given values (i.e., the maximum index of any value not
* zero is bigger than the given dimensionality)
*/
- public SparseFloatVector(Map<Integer, Float> values, int dimensionality) throws IllegalArgumentException {
+ public SparseFloatVector(TIntFloatMap values, int dimensionality) throws IllegalArgumentException {
if(values.size() > dimensionality) {
throw new IllegalArgumentException("values.size() > dimensionality!");
}
@@ -94,10 +102,10 @@ public class SparseFloatVector extends AbstractNumberVector<SparseFloatVector, F
this.values = new float[values.size()];
// Import and sort the indexes
{
- int i = 0;
- for(Integer index : values.keySet()) {
- this.indexes[i] = index;
- i++;
+ TIntFloatIterator iter = values.iterator();
+ for (int i = 0; iter.hasNext(); i++) {
+ iter.advance();
+ this.indexes[i] = iter.key();
}
Arrays.sort(this.indexes);
}
@@ -160,6 +168,7 @@ public class SparseFloatVector extends AbstractNumberVector<SparseFloatVector, F
if(value != 0.0f) {
this.indexes[pos] = i + 1;
this.values[pos] = value;
+ pos++;
}
}
}
@@ -226,172 +235,6 @@ public class SparseFloatVector extends AbstractNumberVector<SparseFloatVector, F
return new Vector(values);
}
- @Override
- public Matrix getRowVector() {
- double[] values = getValues(); // already a copy
- return new Matrix(new double[][] { values });
- }
-
- @Override
- public SparseFloatVector plus(SparseFloatVector fv) {
- if(fv.getDimensionality() != this.getDimensionality()) {
- throw new IllegalArgumentException("Incompatible dimensionality: " + this.getDimensionality() + " - " + fv.getDimensionality() + ".");
- }
- // Compute size of result vector
- int destsize = 0;
- {
- int po = 0;
- int pt = 0;
- while(po < fv.indexes.length && pt < this.indexes.length) {
- final int delta = fv.indexes[po] - this.indexes[pt];
- if(delta == 0) {
- final float fdelta = this.values[pt] - fv.values[po];
- if(fdelta != 0.0f) {
- destsize++;
- }
- po++;
- pt++;
- }
- else if(delta < 0) {
- // next index in this bigger than in fv
- po++;
- destsize++;
- }
- else {
- // next index in fv bigger than in this
- pt++;
- destsize++;
- }
- }
- }
- int[] newindexes = new int[destsize];
- float[] newvalues = new float[destsize];
- // Compute difference
- {
- int outp = 0;
- int po = 0;
- int pt = 0;
- while(po < fv.indexes.length && pt < this.indexes.length) {
- final int delta = fv.indexes[po] - this.indexes[pt];
- if(delta == 0) {
- final float fdelta = this.values[pt] + fv.values[po];
- if(fdelta != 0.0f) {
- newindexes[outp] = fv.indexes[po];
- newvalues[outp] = fdelta;
- outp++;
- }
- po++;
- pt++;
- }
- else if(delta < 0) {
- // next index in this bigger than in fv
- newindexes[outp] = fv.indexes[po];
- newvalues[outp] = fv.values[po];
- outp++;
- po++;
- }
- else {
- // next index in fv bigger than in this
- newindexes[outp] = this.indexes[pt];
- newvalues[outp] = this.values[pt];
- outp++;
- pt++;
- }
- }
- }
- return new SparseFloatVector(newindexes, newvalues, this.dimensionality);
- }
-
- @Override
- public SparseFloatVector minus(SparseFloatVector fv) {
- if(fv.getDimensionality() != this.getDimensionality()) {
- throw new IllegalArgumentException("Incompatible dimensionality: " + this.getDimensionality() + " - " + fv.getDimensionality() + ".");
- }
- // Compute size of result vector
- int destsize = 0;
- {
- int po = 0;
- int pt = 0;
- while(po < fv.indexes.length && pt < this.indexes.length) {
- final int delta = fv.indexes[po] - this.indexes[pt];
- if(delta == 0) {
- final float fdelta = this.values[pt] - fv.values[po];
- if(fdelta != 0.0f) {
- destsize++;
- }
- po++;
- pt++;
- }
- else if(delta < 0) {
- // next index in this bigger than in fv
- po++;
- destsize++;
- }
- else {
- // next index in fv bigger than in this
- pt++;
- destsize++;
- }
- }
- }
- int[] newindexes = new int[destsize];
- float[] newvalues = new float[destsize];
- // Compute difference
- {
- int outp = 0;
- int po = 0;
- int pt = 0;
- while(po < fv.indexes.length && pt < this.indexes.length) {
- final int delta = fv.indexes[po] - this.indexes[pt];
- if(delta == 0) {
- final float fdelta = this.values[pt] - fv.values[po];
- if(fdelta != 0.0f) {
- newindexes[outp] = fv.indexes[po];
- newvalues[outp] = fdelta;
- outp++;
- }
- po++;
- pt++;
- }
- else if(delta < 0) {
- // next index in this bigger than in fv
- newindexes[outp] = fv.indexes[po];
- newvalues[outp] = -fv.values[po];
- outp++;
- po++;
- }
- else {
- // next index in fv bigger than in this
- newindexes[outp] = this.indexes[pt];
- newvalues[outp] = this.values[pt];
- outp++;
- pt++;
- }
- }
- }
- return new SparseFloatVector(newindexes, newvalues, this.dimensionality);
- }
-
- @Override
- public SparseFloatVector nullVector() {
- return new SparseFloatVector(new int[] {}, new float[] {}, dimensionality);
- }
-
- @Override
- public SparseFloatVector negativeVector() {
- return multiplicate(-1);
- }
-
- @Override
- public SparseFloatVector multiplicate(double k) {
- int[] newindexes = indexes.clone();
- float[] newvalues = new float[this.values.length];
- for(int i = 0; i < this.indexes.length; i++) {
- newvalues[i] = (float) (this.values[i] * k);
- }
- return new SparseFloatVector(newindexes, newvalues, this.dimensionality);
- }
-
/**
* <p>
* Provides a String representation of this SparseFloatVector as suitable for
@@ -440,60 +283,26 @@ public class SparseFloatVector extends AbstractNumberVector<SparseFloatVector, F
return values;
}
- /**
- * Provides the scalar product (inner product) of this and the given
- * SparseFloatVector.
- *
- * @param fv the SparseFloatVector to compute the scalar product for
- * @return the scalar product (inner product) of this and the given
- * SparseFloatVector
- */
@Override
- public Float scalarProduct(SparseFloatVector fv) {
- if(this.getDimensionality() != fv.getDimensionality()) {
- throw new IllegalArgumentException("Incompatible dimensionality: " + this.getDimensionality() + " - " + fv.getDimensionality() + ".");
- }
- float result = 0.0f;
- int po = 0;
- int pt = 0;
- while(po < fv.indexes.length && pt < this.indexes.length) {
- final int delta = fv.indexes[po] - this.indexes[pt];
- if(delta == 0) {
- result += fv.values[po] * this.values[pt];
- po++;
- pt++;
- }
- else if(delta < 0) {
- // next index in this bigger than in fv
- po++;
- }
- else {
- // next index in fv bigger than in this
- pt++;
- }
+ public <A> SparseFloatVector newFeatureVector(A array, ArrayAdapter<Float, A> adapter) {
+ int dim = adapter.size(array);
+ float[] values = new float[dim];
+ for(int i = 0; i < dim; i++) {
+ values[i] = adapter.get(array, i);
}
- return result;
+ // TODO: inefficient
+ return new SparseFloatVector(values);
}
@Override
- public SparseFloatVector newInstance(Vector values) {
- return newInstance(values.getArrayRef());
- }
-
- @Override
- public SparseFloatVector newInstance(double[] values) {
- // FIXME: inefficient
- return new SparseFloatVector(Util.convertToFloat(values));
- }
-
- @Override
- public SparseFloatVector newInstance(List<Float> values) {
- return new SparseFloatVector(Util.unboxToFloat(ClassGenericsUtil.toArray(values, Float.class)));
- }
-
- @Override
- public SparseFloatVector newInstance(Float[] values) {
- return new SparseFloatVector(Util.unboxToFloat(values));
+ public <A> SparseFloatVector newNumberVector(A array, NumberArrayAdapter<?, A> adapter) {
+ int dim = adapter.size(array);
+ float[] values = new float[dim];
+ for(int i = 0; i < dim; i++) {
+ values[i] = adapter.getFloat(array, i);
+ }
+ // TODO: inefficient
+ return new SparseFloatVector(values);
}
@Override
@@ -504,4 +313,23 @@ public class SparseFloatVector extends AbstractNumberVector<SparseFloatVector, F
}
return b;
}
-} \ No newline at end of file
+
+ /**
+ * Parameterization class
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected SparseFloatVector makeInstance() {
+ return STATIC;
+ }
+ }
+
+ /**
+ * Empty map.
+ */
+ public static final TIntFloatMap EMPTYMAP = new TUnmodifiableIntFloatMap(new TIntFloatHashMap());
+}
diff --git a/src/de/lmu/ifi/dbs/elki/data/SparseNumberVector.java b/src/de/lmu/ifi/dbs/elki/data/SparseNumberVector.java
index 03038344..d337d08b 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) 2011
+ Copyright (C) 2012
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 c0174fb2..cd9074a8 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -62,9 +62,8 @@ public class Subspace<V extends FeatureVector<V, ?>> {
* @param dimensions the dimensions building this subspace
*/
public Subspace(BitSet dimensions) {
- for(int d = dimensions.nextSetBit(0); d >= 0; d = dimensions.nextSetBit(d + 1)) {
- this.dimensions.set(d);
- }
+ this.dimensions.clear();
+ this.dimensions.or(dimensions);
dimensionality = dimensions.cardinality();
}
@@ -74,7 +73,7 @@ public class Subspace<V extends FeatureVector<V, ?>> {
* @return the dimensions of this subspace
*/
public final BitSet getDimensions() {
- return dimensions;
+ return (BitSet) dimensions.clone();
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/data/VectorUtil.java b/src/de/lmu/ifi/dbs/elki/data/VectorUtil.java
index 159fd9a8..1607b482 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,10 +23,13 @@ package de.lmu.ifi.dbs.elki.data;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import java.util.BitSet;
import java.util.Random;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
import de.lmu.ifi.dbs.elki.math.MathUtil;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
/**
* Utility functions for use with vectors.
@@ -35,17 +38,17 @@ import de.lmu.ifi.dbs.elki.math.MathUtil;
*
* @author Erich Schubert
*
- * @apiviz.uses de.lmu.ifi.dbs.elki.data.NumberVector
+ * @apiviz.uses NumberVector
*/
public final class VectorUtil {
/**
- * Return the range across all dimensions. Useful in particular for time series.
+ * Return the range across all dimensions. Useful in particular for time
+ * series.
*
* @param vec Vector to process.
- * @param <V> Vector type
* @return [min, max]
*/
- public static <V extends NumberVector<?, ?>> DoubleMinMax getRangeDouble(V vec) {
+ public static DoubleMinMax getRangeDouble(NumberVector<?, ?> vec) {
DoubleMinMax minmax = new DoubleMinMax();
for(int i = 0; i < vec.getDimensionality(); i++) {
@@ -64,7 +67,7 @@ public final class VectorUtil {
* @return new instance
*/
public static <V extends NumberVector<V, ?>> V randomVector(V template, Random r) {
- return template.newInstance(MathUtil.randomDoubleArray(template.getDimensionality(), r));
+ return template.newNumberVector(MathUtil.randomDoubleArray(template.getDimensionality(), r));
}
/**
@@ -77,4 +80,192 @@ public final class VectorUtil {
public static <V extends NumberVector<V, ?>> V randomVector(V template) {
return randomVector(template, new Random());
}
+
+ /**
+ * Compute the angle for sparse vectors.
+ *
+ * @param v1 First vector
+ * @param v2 Second vector
+ * @return angle
+ */
+ public static double angleSparse(SparseNumberVector<?, ?> v1, SparseNumberVector<?, ?> v2) {
+ BitSet b1 = v1.getNotNullMask();
+ BitSet b2 = v2.getNotNullMask();
+ BitSet both = (BitSet) b1.clone();
+ both.and(b2);
+
+ // Length of first vector
+ double l1 = 0.0;
+ for(int i = b1.nextSetBit(0); i >= 0; i = b1.nextSetBit(i + 1)) {
+ final double val = v1.doubleValue(i);
+ l1 += val * val;
+ }
+ l1 = Math.sqrt(l1);
+
+ // Length of second vector
+ double l2 = 0.0;
+ for(int i = b2.nextSetBit(0); i >= 0; i = b2.nextSetBit(i + 1)) {
+ final double val = v2.doubleValue(i);
+ l2 += val * val;
+ }
+ l2 = Math.sqrt(l2);
+
+ // Cross product
+ double cross = 0.0;
+ for(int i = both.nextSetBit(0); i >= 0; i = both.nextSetBit(i + 1)) {
+ cross += v1.doubleValue(i) * v2.doubleValue(i);
+ }
+ return cross / (l1 * l2);
+ }
+
+ /**
+ * Compute the angle between two vectors.
+ *
+ * @param v1 first vector
+ * @param v2 second vector
+ * @param o Origin
+ * @return Angle
+ */
+ public static double angle(NumberVector<?, ?> v1, NumberVector<?, ?> v2, Vector o) {
+ // Essentially, we want to compute this:
+ // v1' = v1 - o, v2' = v2 - o
+ // v1'.transposeTimes(v2') / (v1'.euclideanLength()*v2'.euclideanLength());
+ // We can just compute all three in parallel.
+ double[] oe = o.getArrayRef();
+ final int dim = v1.getDimensionality();
+ double s = 0, e1 = 0, e2 = 0;
+ for(int k = 0; k < dim; k++) {
+ final double r1 = v1.doubleValue(k + 1) - oe[k];
+ final double r2 = v2.doubleValue(k + 1) - oe[k];
+ s += r1 * r2;
+ e1 += r1 * r1;
+ e2 += r2 * r2;
+ }
+ return Math.sqrt((s / e1) * (s / e2));
+ }
+
+ /**
+ * Compute the angle between two vectors.
+ *
+ * @param v1 first vector
+ * @param v2 second vector
+ * @param o Origin
+ * @return Angle
+ */
+ public static double angle(NumberVector<?, ?> v1, NumberVector<?, ?> v2, NumberVector<?, ?> o) {
+ // Essentially, we want to compute this:
+ // v1' = v1 - o, v2' = v2 - o
+ // v1'.transposeTimes(v2') / (v1'.euclideanLength()*v2'.euclideanLength());
+ // 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++) {
+ final double r1 = v1.doubleValue(k + 1) - o.doubleValue(k + 1);
+ final double r2 = v2.doubleValue(k + 1) - o.doubleValue(k + 1);
+ s += r1 * r2;
+ e1 += r1 * r1;
+ e2 += r2 * r2;
+ }
+ return Math.sqrt((s / e1) * (s / e2));
+ }
+
+ /**
+ * Compute the absolute cosine of the angle between two vectors.
+ *
+ * To convert it to radians, use <code>Math.acos(angle)</code>!
+ *
+ * @param v1 first vector
+ * @param v2 second vector
+ * @return Angle
+ */
+ public static double cosAngle(NumberVector<?, ?> v1, NumberVector<?, ?> v2) {
+ if(v1 instanceof SparseNumberVector<?, ?> && v2 instanceof SparseNumberVector<?, ?>) {
+ return angleSparse((SparseNumberVector<?, ?>) v1, (SparseNumberVector<?, ?>) v2);
+ }
+ // Essentially, we want to compute this:
+ // v1.transposeTimes(v2) / (v1.euclideanLength() * v2.euclideanLength());
+ // We can just compute all three in parallel.
+ final int d1 = v1.getDimensionality();
+ 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++) {
+ final double r1 = v1.doubleValue(k + 1);
+ final double r2 = v2.doubleValue(k + 1);
+ s += r1 * r2;
+ e1 += r1 * r1;
+ e2 += r2 * r2;
+ }
+ for(int k = dim; k < d1; k++) {
+ final double r1 = v1.doubleValue(k + 1);
+ e1 += r1 * r1;
+ }
+ for(int k = dim; k < d2; k++) {
+ final double r2 = v2.doubleValue(k + 1);
+ e2 += r2 * r2;
+ }
+ return Math.min(Math.sqrt((s / e1) * (s / e2)), 1);
+ }
+
+ // TODO: add more precise but slower O(n^2) angle computation according to:
+ // Computing the Angle between Vectors, P. Schatte
+ // Journal of Computing, Volume 63, Number 1 (1999)
+
+ /**
+ * Compute the minimum angle between two rectangles.
+ *
+ * @param v1 first rectangle
+ * @param v2 second rectangle
+ * @return Angle
+ */
+ public static double minCosAngle(SpatialComparable v1, SpatialComparable v2) {
+ if(v1 instanceof NumberVector<?, ?> && v2 instanceof NumberVector<?, ?>) {
+ return cosAngle((NumberVector<?, ?>) v1, (NumberVector<?, ?>) v2);
+ }
+ // Essentially, we want to compute this:
+ // absmax(v1.transposeTimes(v2))/(min(v1.euclideanLength())*min(v2.euclideanLength()));
+ // 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++) {
+ final double min1 = v1.getMin(k + 1), max1 = v1.getMax(k + 1);
+ final double min2 = v2.getMin(k + 1), max2 = v2.getMax(k + 1);
+ 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) {
+ e1 += max1 * max1;
+ }
+ else if(min1 > 0) {
+ e1 += min1 * min1;
+ } // else: 0
+ if(max2 < 0) {
+ e2 += max2 * max2;
+ }
+ 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);
+ }
+
+ /**
+ * Provides the scalar product (inner product) of this and the given
+ * DoubleVector.
+ *
+ * @param d1 the first vector to compute the scalar product for
+ * @param d2 the second vector to compute the scalar product for
+ * @return the scalar product (inner product) of this and the given
+ * DoubleVector
+ */
+ public static double scalarProduct(NumberVector<?, ?> d1, NumberVector<?, ?> d2) {
+ final int dim = d1.getDimensionality();
+ double result = 0.0;
+ for(int i = 1; i <= dim; i++) {
+ result += d1.doubleValue(i) * d2.doubleValue(i);
+ }
+ return result;
+ }
} \ No newline at end of file
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 70d635d1..cb6ca494 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,30 +27,57 @@ import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
+
/**
* Abstract class for color histogram computation.
- *
+ *
* @author Erich Schubert
*
* @apiviz.uses ImageUtil
*/
public abstract class AbstractComputeColorHistogram implements ComputeColorHistogram {
@Override
- public double[] computeColorHistogram(File file) throws IOException {
+ public double[] computeColorHistogram(File file, File mask) throws IOException {
BufferedImage image = ImageUtil.loadImage(file);
int height = image.getHeight();
int width = image.getWidth();
+
+ BufferedImage maski = null;
+ if(mask != null) {
+ maski = ImageUtil.loadImage(mask);
+ if(maski.getHeight() != height || maski.getWidth() != width) {
+ throw new AbortException("Input image and mask do not agree on the image size!");
+ }
+ }
+
double[] bins = new double[getNumBins()];
+ long valid = 0;
for(int x = 0; x < width; x++) {
for(int y = 0; y < height; y++) {
+ if(maski != null) {
+ int col = maski.getRGB(x, y);
+ // More transparent than covering
+ if((col >>> 24) < 127) {
+ continue;
+ }
+ // More black than white: (R+G+B) > 1.5 * 255
+ if(((col >>> 16) & 0xFF) + ((col >>> 8) & 0xFF) + (col & 0xFF) < 382) {
+ continue;
+ }
+ }
int bin = getBinForColor(image.getRGB(x, y));
- assert(bin < bins.length);
+ assert (bin < bins.length);
bins[bin] += 1;
+ valid += 1;
}
}
- for (int i = 0; i < bins.length; i++) {
- bins[i] /= height * width;
+ if (valid == 0) {
+ throw new AbortException("Mask apparently was all-black.");
+ }
+ for(int i = 0; i < bins.length; i++) {
+ bins[i] /= valid;
}
return bins;
}
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 459a8698..e45d27bd 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) 2011
+ Copyright (C) 2012
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 2c82c5bd..a13a4086 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -39,9 +39,14 @@ public interface ComputeColorHistogram extends Parameterizable {
/**
* Compute a color histogram given a file name.
*
+ * The mask file (which may be null) is expected to use >50% transparent or
+ * black to mask pixels, Non-transparent white to keep pixels. Alpha values
+ * are not used.
+ *
* @param file File name
+ * @param mask Mask file (optional)
* @return Color histogram
* @throws IOException on file read errors.
*/
- public double[] computeColorHistogram(File file) throws IOException;
+ public double[] computeColorHistogram(File file, File mask) throws IOException;
} \ No newline at end of file
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 bec59540..e5d91aa4 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) 2011
+ Copyright (C) 2012
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 ab912cff..4fb887e7 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) 2011
+ Copyright (C) 2012
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 2032bd62..3e6e8c64 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) 2011
+ Copyright (C) 2012
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 37079f96..10722c36 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) 2011
+ Copyright (C) 2012
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 f78b52b9..c851a21a 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) 2011
+Copyright (C) 2012
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 f7f69e07..56d7cd3f 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,7 +29,6 @@ import de.lmu.ifi.dbs.elki.result.textwriter.TextWriterStream;
* Abstract base class for Cluster Models.
*
* @author Erich Schubert
- *
*/
public abstract class BaseModel implements Model {
/**
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 f06b321f..371c4d02 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) 2011
+ Copyright (C) 2012
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.data.model;
*/
import java.util.Arrays;
-import java.util.Collections;
import java.util.Iterator;
import de.lmu.ifi.dbs.elki.data.FeatureVector;
@@ -86,7 +85,7 @@ public class Bicluster<V extends FeatureVector<?, ?>> implements TextWriteable,
@Deprecated
public Bicluster(int[] rowIDs, int[] colIDs, Relation<V> database) {
ArrayModifiableDBIDs ids = DBIDUtil.newArray(rowIDs.length);
- for (int rowid : rowIDs) {
+ for(int rowid : rowIDs) {
ids.add(DBIDUtil.importInteger(rowid));
}
this.rowIDs = ids;
@@ -101,7 +100,7 @@ public class Bicluster<V extends FeatureVector<?, ?>> implements TextWriteable,
if(!(this.rowIDs instanceof ModifiableDBIDs)) {
this.rowIDs = DBIDUtil.newArray(this.rowIDs);
}
- Collections.sort(this.rowIDs);
+ ((ArrayModifiableDBIDs) this.rowIDs).sort();
Arrays.sort(this.colIDs);
}
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 1eb53b42..10f3bed2 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) 2011
+ Copyright (C) 2012
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.data.model;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.Collections;
-
import de.lmu.ifi.dbs.elki.data.FeatureVector;
import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs;
import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs;
@@ -95,7 +93,7 @@ public class BiclusterWithInverted<V extends FeatureVector<V, ?>> extends Biclus
public void sortIDs() {
super.sortIDs();
if(this.invertedRows != null) {
- Collections.sort(this.invertedRows);
+ this.invertedRows.sort();
}
}
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 f40b4b73..260c9a66 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,22 +23,22 @@ package de.lmu.ifi.dbs.elki.data.model;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
/**
- * Generic cluster model. Does not supply additional meta information except that it is a cluster.
- * Since there is no meta information, you should use the static {@link #CLUSTER} object.
+ * Generic cluster model. Does not supply additional meta information except
+ * that it is a cluster. Since there is no meta information, you should use the
+ * static {@link #CLUSTER} object.
*
* @author Erich Schubert
- *
+ *
* @apiviz.landmark
*/
public final class ClusterModel extends BaseModel {
/**
- * Static cluster model that can be shared for all clusters (since the object doesn't include meta information.
+ * Static cluster model that can be shared for all clusters (since the object
+ * doesn't include meta information.
*/
public final static ClusterModel CLUSTER = new ClusterModel();
- /** {@inheritDoc} */
@Override
public String toString() {
return "ClusterModel";
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 2f8c2d15..e6cb893f 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -34,8 +34,8 @@ import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
import de.lmu.ifi.dbs.elki.math.linearalgebra.LinearEquationSystem;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Matrix;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
-import de.lmu.ifi.dbs.elki.datasource.filter.NonNumericFeaturesException;
-import de.lmu.ifi.dbs.elki.datasource.filter.Normalization;
+import de.lmu.ifi.dbs.elki.datasource.filter.normalization.NonNumericFeaturesException;
+import de.lmu.ifi.dbs.elki.datasource.filter.normalization.Normalization;
import de.lmu.ifi.dbs.elki.result.Result;
import de.lmu.ifi.dbs.elki.result.textwriter.TextWriteable;
import de.lmu.ifi.dbs.elki.result.textwriter.TextWriterStream;
@@ -226,10 +226,9 @@ public class CorrelationAnalysisSolution<V extends NumberVector<V, ?>> implement
Vector centered = p.getColumnVector().minus(centroid);
Matrix sum = new Matrix(p.getDimensionality(), strongEigenvectors.getColumnDimensionality());
for(int i = 0; i < strongEigenvectors.getColumnDimensionality(); i++) {
- Vector v_i = strongEigenvectors.getColumnVector(i);
- Vector proj = v_i.times(centered.scalarProduct(v_i));
-
- sum.setColumnVector(i, proj);
+ Vector v_i = strongEigenvectors.getCol(i);
+ v_i.timesEquals(centered.transposeTimes(v_i));
+ sum.setCol(i, v_i);
}
return sum;
}
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 0aa56478..fa4d33fa 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) 2011
+ Copyright (C) 2012
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 e0b39795..e4bcba52 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) 2011
+Copyright (C) 2012
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 07857aa7..104ade9a 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) 2011
+ Copyright (C) 2012
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 62c5c2a5..3ba6a981 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) 2011
+ Copyright (C) 2012
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 3716ffa7..366c7717 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) 2011
+ Copyright (C) 2012
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 b9747f75..761837be 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) 2011
+ Copyright (C) 2012
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 d07fc926..4ffac679 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) 2011
+ Copyright (C) 2012
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 eecf5e7a..16a9619b 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) 2011
+ Copyright (C) 2012
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 ccaff24f..f4db1424 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) 2011
+ Copyright (C) 2012
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 f150e98e..c8f514ec 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) 2011
+Copyright (C) 2012
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 6cb2c08b..51c7c716 100644
--- a/src/de/lmu/ifi/dbs/elki/data/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/data/package-info.java
@@ -9,7 +9,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2011
+Copyright (C) 2012
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/AbstractFeatureSelection.java b/src/de/lmu/ifi/dbs/elki/data/projection/AbstractFeatureSelection.java
new file mode 100644
index 00000000..fcd5fd84
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/data/projection/AbstractFeatureSelection.java
@@ -0,0 +1,64 @@
+package de.lmu.ifi.dbs.elki.data.projection;
+
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.TypeInformation;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.SubsetArrayAdapter;
+
+/**
+ * Abstract feature selection projection
+ *
+ * @author Erich Schubert
+ *
+ * @param <V> Vector type
+ * @param <F> Feature type
+ */
+public abstract class AbstractFeatureSelection<V extends FeatureVector<V, F>, F> implements Projection<V, V> {
+ /**
+ * Array adapter
+ */
+ protected SubsetArrayAdapter<F, V> adapter;
+
+ /**
+ * Constructor.
+ *
+ * @param adapter Data adapter
+ */
+ public AbstractFeatureSelection(SubsetArrayAdapter<F, V> adapter) {
+ super();
+ this.adapter = adapter;
+ }
+
+ @Override
+ public V project(V data) {
+ return data.newFeatureVector(data, adapter);
+ }
+
+ @Override
+ abstract public SimpleTypeInformation<V> getOutputDataTypeInformation();
+
+ @Override
+ abstract public TypeInformation getInputDataTypeInformation();
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/data/projection/FeatureSelection.java b/src/de/lmu/ifi/dbs/elki/data/projection/FeatureSelection.java
new file mode 100644
index 00000000..fca75e3f
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/data/projection/FeatureSelection.java
@@ -0,0 +1,104 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.FeatureVector;
+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.VectorTypeInformation;
+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;
+
+/**
+ * Projection class for number vectors.
+ *
+ * @author Erich Schubert
+ *
+ * @param <V> Vector type
+ * @param <F> Feature type
+ */
+public class FeatureSelection<V extends FeatureVector<V, F>, F> extends AbstractFeatureSelection<V, F> {
+ /**
+ * Minimum dimensionality required for projection
+ */
+ private int mindim;
+
+ /**
+ * Object factory
+ */
+ private V factory;
+
+ /**
+ * Output dimensionality
+ */
+ private int dimensionality;
+
+ /**
+ * Constructor.
+ *
+ * @param dims Dimensions
+ * @param factory Object factory
+ */
+ public FeatureSelection(int[] dims, V factory) {
+ super(new SubsetArrayAdapter<F, V>(getAdapter(factory), dims));
+ this.factory = factory;
+ this.dimensionality = dims.length;
+
+ int mindim = 0;
+ for(int dim : dims) {
+ mindim = Math.max(mindim, dim + 1);
+ }
+ this.mindim = mindim;
+ }
+
+ /**
+ * Choose the best adapter for this.
+ *
+ * @param factory Object factory, for type inference
+ * @return Adapter
+ */
+ @SuppressWarnings("unchecked")
+ private static <V extends FeatureVector<V, F>, F> ArrayAdapter<F, ? super V> getAdapter(V factory) {
+ if(factory instanceof NumberVector) {
+ ArrayAdapter<?, ?> ret = ArrayLikeUtil.numberVectorAdapter((NumberVector<?, ?>) factory);
+ return (ArrayAdapter<F, ? super V>) ret;
+ }
+ return ArrayLikeUtil.featureVectorAdapter(factory);
+ }
+
+ @Override
+ public SimpleTypeInformation<V> getOutputDataTypeInformation() {
+ @SuppressWarnings("unchecked")
+ final Class<V> cls = (Class<V>) factory.getClass();
+ return new VectorTypeInformation<V>(cls, dimensionality, dimensionality);
+ }
+
+ @Override
+ public TypeInformation getInputDataTypeInformation() {
+ @SuppressWarnings("unchecked")
+ final Class<V> cls = (Class<V>) factory.getClass();
+ return new VectorTypeInformation<V>(cls, mindim, Integer.MAX_VALUE);
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/data/projection/NumericalFeatureSelection.java b/src/de/lmu/ifi/dbs/elki/data/projection/NumericalFeatureSelection.java
new file mode 100644
index 00000000..7dfd580f
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/data/projection/NumericalFeatureSelection.java
@@ -0,0 +1,104 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.VectorTypeInformation;
+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.datastructures.arraylike.SubsetArrayAdapter;
+
+/**
+ * Projection class for number vectors.
+ *
+ * @author Erich Schubert
+ *
+ * @param <V> Vector type
+ * @param <N> Number type
+ */
+public class NumericalFeatureSelection<V extends NumberVector<V, N>, N extends Number> extends AbstractFeatureSelection<V, N> {
+ /**
+ * Minimum dimensionality required for projection
+ */
+ private int mindim;
+
+ /**
+ * Object factory
+ */
+ private V factory;
+
+ /**
+ * Output dimensionality
+ */
+ private int dimensionality;
+
+ /**
+ * Constructor.
+ *
+ * @param dims Dimensions
+ * @param factory Object factory
+ */
+ public NumericalFeatureSelection(int[] dims, V factory) {
+ super(new SubsetArrayAdapter<N, V>(getAdapter(factory), dims));
+ this.factory = factory;
+ this.dimensionality = dims.length;
+
+ int mindim = 0;
+ for(int dim : dims) {
+ mindim = Math.max(mindim, dim + 1);
+ }
+ this.mindim = mindim;
+ }
+
+ /**
+ * Choose the best adapter for this.
+ *
+ * @param factory Object factory, for type inference
+ * @return Adapter
+ */
+ private static <V extends NumberVector<V, N>, N extends Number> NumberArrayAdapter<N, ? super V> getAdapter(V factory) {
+ return ArrayLikeUtil.numberVectorAdapter(factory);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public V project(V data) {
+ return factory.newNumberVector(data, (NumberArrayAdapter<N, ? super V>) adapter);
+ }
+
+ @Override
+ public SimpleTypeInformation<V> getOutputDataTypeInformation() {
+ @SuppressWarnings("unchecked")
+ final Class<V> cls = (Class<V>) factory.getClass();
+ return new VectorTypeInformation<V>(cls, dimensionality, dimensionality);
+ }
+
+ @Override
+ public TypeInformation getInputDataTypeInformation() {
+ @SuppressWarnings("unchecked")
+ final Class<V> cls = (Class<V>) factory.getClass();
+ return new VectorTypeInformation<V>(cls, mindim, Integer.MAX_VALUE);
+ }
+} \ 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
new file mode 100644
index 00000000..c9cd98d2
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/data/projection/Projection.java
@@ -0,0 +1,59 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Projection interface.
+ *
+ * @author Erich Schubert
+ *
+ * @param <IN> Input data type
+ * @param <OUT> Output data type
+ */
+public interface Projection<IN, OUT> {
+ /**
+ * Project a single instance.
+ *
+ * @param data Data to project
+ * @return Projected data
+ */
+ public OUT project(IN data);
+
+ /**
+ * Output type restriction
+ *
+ * @return Output type
+ */
+ public SimpleTypeInformation<OUT> getOutputDataTypeInformation();
+
+ /**
+ * Input type information.
+ *
+ * @return Type restriction
+ */
+ public TypeInformation getInputDataTypeInformation();
+}
diff --git a/src/de/lmu/ifi/dbs/elki/properties/package-info.java b/src/de/lmu/ifi/dbs/elki/data/projection/package-info.java
index f085e800..d39c51ba 100644
--- a/src/de/lmu/ifi/dbs/elki/properties/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/data/projection/package-info.java
@@ -1,11 +1,11 @@
/**
- * <p>Property handling and main ELKI properties file.</p>
+ * <p>Data projections.</p>
*/
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2011
+Copyright (C) 2012
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.properties; \ No newline at end of file
+package de.lmu.ifi.dbs.elki.data.projection; \ No newline at end of file
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 aa16c12e..f485c052 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) 2011
+ Copyright (C) 2012
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/PolygonsObject.java b/src/de/lmu/ifi/dbs/elki/data/spatial/PolygonsObject.java
index d5d11c8d..17bed0e1 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) 2011
+ Copyright (C) 2012
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 dc82a05b..eb9edf4e 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) 2011
+ Copyright (C) 2012
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/SpatialUtil.java b/src/de/lmu/ifi/dbs/elki/data/spatial/SpatialUtil.java
index f3bd030f..731c021a 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,6 +24,9 @@ package de.lmu.ifi.dbs.elki.data.spatial;
*/
import de.lmu.ifi.dbs.elki.data.HyperBoundingBox;
+import de.lmu.ifi.dbs.elki.data.ModifiableHyperBoundingBox;
+import de.lmu.ifi.dbs.elki.logging.LoggingConfiguration;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayAdapter;
/**
* Utility class with spatial functions.
@@ -76,7 +79,7 @@ public final class SpatialUtil {
public static boolean intersects(SpatialComparable box1, SpatialComparable box2) {
final int dim = box1.getDimensionality();
if(dim != box2.getDimensionality()) {
- throw new IllegalArgumentException("The spatial objects do not have the same dimensionality!");
+ throw new IllegalArgumentException("The spatial objects do not have the same dimensionality: " + box1.getDimensionality() + " " + box2.getDimensionality());
}
boolean intersect = true;
for(int i = 1; i <= dim; i++) {
@@ -146,19 +149,138 @@ public final class SpatialUtil {
double vol = 1;
final int dim = box.getDimensionality();
for(int i = 1; i <= dim; i++) {
- vol *= box.getMax(i) - box.getMin(i);
+ double delta = box.getMax(i) - box.getMin(i);
+ if(delta == 0.0) {
+ return 0.0;
+ }
+ vol *= delta;
+ }
+ return vol;
+ }
+
+ /**
+ * Compute the volume (area) of the union of two MBRs
+ *
+ * @param r1 First object
+ * @param r2 Second object
+ * @return Volume of union
+ */
+ public static double volumeUnion(SpatialComparable r1, SpatialComparable r2) {
+ final int dim1 = r1.getDimensionality();
+ final int dim2 = r2.getDimensionality();
+ assert (!LoggingConfiguration.DEBUG || dim1 == dim2) : "Computing union with different dimensionality: " + dim1 + " vs. " + dim2;
+ double volume = 1.0;
+ for(int i = 1; i <= dim1; i++) {
+ final double min = Math.min(r1.getMin(i), r2.getMin(i));
+ final double max = Math.max(r1.getMax(i), r2.getMax(i));
+ volume *= (max - min);
+ }
+ return volume;
+ }
+
+ /**
+ * Computes the volume of this SpatialComparable
+ *
+ * @param scale Scaling factor
+ * @return the volume of this SpatialComparable
+ */
+ public static double volumeScaled(SpatialComparable box, double scale) {
+ double vol = 1;
+ final int dim = box.getDimensionality();
+ for(int i = 1; i <= dim; i++) {
+ double delta = box.getMax(i) - box.getMin(i);
+ if(delta == 0.0) {
+ return 0.0;
+ }
+ vol *= delta * scale;
}
return vol;
}
/**
+ * Compute the volume (area) of the union of two MBRs
+ *
+ * @param r1 First object
+ * @param r2 Second object
+ * @param scale Scaling factor
+ * @return Volume of union
+ */
+ public static double volumeUnionScaled(SpatialComparable r1, SpatialComparable r2, double scale) {
+ final int dim1 = r1.getDimensionality();
+ final int dim2 = r2.getDimensionality();
+ assert (!LoggingConfiguration.DEBUG || dim1 == dim2) : "Computing union with different dimensionality: " + dim1 + " vs. " + dim2;
+ double volume = 1.0;
+ for(int i = 1; i <= dim1; i++) {
+ final double min = Math.min(r1.getMin(i), r2.getMin(i));
+ final double max = Math.max(r1.getMax(i), r2.getMax(i));
+ volume *= (max - min) * scale;
+ }
+ return volume;
+ }
+
+ /**
+ * Compute the enlargement obtained by adding an object to an existing object.
+ *
+ * @param exist Existing rectangle
+ * @param addit Additional rectangle
+ * @return Enlargement factor
+ */
+ public static double enlargement(SpatialComparable exist, SpatialComparable addit) {
+ final int dim1 = exist.getDimensionality();
+ final int dim2 = addit.getDimensionality();
+ assert (!LoggingConfiguration.DEBUG || dim1 == dim2) : "Computing union with different dimensionality: " + dim1 + " vs. " + dim2;
+ double v1 = 1.0;
+ double v2 = 1.0;
+ for(int i = 1; i <= dim1; i++) {
+ final double emin = exist.getMin(i);
+ final double emax = exist.getMax(i);
+ final double amin = addit.getMin(i);
+ final double amax = addit.getMax(i);
+
+ final double min = Math.min(emin, amin);
+ final double max = Math.max(emax, amax);
+ v1 *= (max - min);
+ v2 *= (emax - emin);
+ }
+ return v2 - v1;
+ }
+
+ /**
+ * Compute the enlargement obtained by adding an object to an existing object.
+ *
+ * @param exist Existing rectangle
+ * @param addit Additional rectangle
+ * @param scale Scaling helper
+ * @return Enlargement factor
+ */
+ public static double enlargementScaled(SpatialComparable exist, SpatialComparable addit, double scale) {
+ final int dim1 = exist.getDimensionality();
+ final int dim2 = addit.getDimensionality();
+ assert (!LoggingConfiguration.DEBUG || dim1 == dim2) : "Computing union with different dimensionality: " + dim1 + " vs. " + dim2;
+ double v1 = 1.0;
+ double v2 = 1.0;
+ for(int i = 1; i <= dim1; i++) {
+ final double emin = exist.getMin(i);
+ final double emax = exist.getMax(i);
+ final double amin = addit.getMin(i);
+ final double amax = addit.getMax(i);
+
+ final double min = Math.min(emin, amin);
+ final double max = Math.max(emax, amax);
+ v1 *= (max - min) * scale;
+ v2 *= (emax - emin) * scale;
+ }
+ return v2 - v1;
+ }
+
+ /**
* Computes the perimeter of this SpatialComparable.
*
* @return the perimeter of this SpatialComparable
*/
public static double perimeter(SpatialComparable box) {
- double perimeter = 0;
final int dim = box.getDimensionality();
+ double perimeter = 0;
for(int i = 1; i <= dim; i++) {
perimeter += box.getMax(i) - box.getMin(i);
}
@@ -166,15 +288,13 @@ public final class SpatialUtil {
}
/**
- * Computes the volume of the overlapping box between two SpatialComparables
- * and return the relation between the volume of the overlapping box and the
- * volume of both SpatialComparable.
+ * Computes the volume of the overlapping box between two SpatialComparables.
*
* @param box1 the first SpatialComparable
* @param box2 the second SpatialComparable
- * @return the overlap volume in relation to the singular volumes.
+ * @return the overlap volume.
*/
- public static double relativeOverlap(SpatialComparable box1, SpatialComparable box2) {
+ public static double overlap(SpatialComparable box1, SpatialComparable box2) {
final int dim = box1.getDimensionality();
if(dim != box2.getDimensionality()) {
throw new IllegalArgumentException("This HyperBoundingBox and the given HyperBoundingBox need same dimensionality");
@@ -201,7 +321,49 @@ public final class SpatialUtil {
overlap *= omax - omin;
}
- return overlap / (volume(box1) + volume(box2));
+ return overlap;
+ }
+
+ /**
+ * Computes the volume of the overlapping box between two SpatialComparables
+ * and return the relation between the volume of the overlapping box and the
+ * volume of both SpatialComparable.
+ *
+ * @param box1 the first SpatialComparable
+ * @param box2 the second SpatialComparable
+ * @return the overlap volume in relation to the singular volumes.
+ */
+ public static double relativeOverlap(SpatialComparable box1, SpatialComparable box2) {
+ final int dim = box1.getDimensionality();
+ if(dim != box2.getDimensionality()) {
+ throw new IllegalArgumentException("This HyperBoundingBox and the given HyperBoundingBox need same dimensionality");
+ }
+
+ // the overlap volume
+ double overlap = 1.0;
+ double vol1 = 1.0;
+ double vol2 = 1.0;
+
+ for(int i = 1; i <= dim; i++) {
+ final double box1min = box1.getMin(i);
+ final double box1max = box1.getMax(i);
+ final double box2min = box2.getMin(i);
+ final double box2max = box2.getMax(i);
+
+ final double omax = Math.min(box1max, box2max);
+ final double omin = Math.max(box1min, box2min);
+
+ // if omax <= omin in any dimension, the overlap box has a volume of zero
+ if(omax <= omin) {
+ return 0.0;
+ }
+
+ overlap *= omax - omin;
+ vol1 *= box1max - box1min;
+ vol2 *= box2max - box2min;
+ }
+
+ return overlap / (vol1 + vol2);
}
/**
@@ -212,7 +374,7 @@ public final class SpatialUtil {
* @return the union HyperBoundingBox of this HyperBoundingBox and the given
* HyperBoundingBox
*/
- public static HyperBoundingBox union(SpatialComparable box1, SpatialComparable box2) {
+ public static ModifiableHyperBoundingBox union(SpatialComparable box1, SpatialComparable box2) {
final int dim = box1.getDimensionality();
if(dim != box2.getDimensionality()) {
throw new IllegalArgumentException("This HyperBoundingBox and the given HyperBoundingBox need same dimensionality");
@@ -225,7 +387,7 @@ public final class SpatialUtil {
min[i - 1] = Math.min(box1.getMin(i), box2.getMin(i));
max[i - 1] = Math.max(box1.getMax(i), box2.getMax(i));
}
- return new HyperBoundingBox(min, max);
+ return new ModifiableHyperBoundingBox(min, max);
}
/**
@@ -251,6 +413,34 @@ public final class SpatialUtil {
}
/**
+ * Compute the union of a number of objects as a flat MBR (low-level, for
+ * index structures)
+ *
+ * @param data Object
+ * @param getter Array adapter
+ * @return Flat MBR
+ */
+ public static <E extends SpatialComparable, A> double[] unionFlatMBR(A data, ArrayAdapter<E, ? super A> getter) {
+ final int num = getter.size(data);
+ assert (num > 0) : "Cannot compute MBR of empty set.";
+ final E first = getter.get(data, 0);
+ final int dim = first.getDimensionality();
+ double[] mbr = new double[2 * dim];
+ for(int d = 0; d < dim; d++) {
+ mbr[d] = first.getMin(d + 1);
+ mbr[dim + d] = first.getMax(d + 1);
+ }
+ for(int i = 1; i < num; i++) {
+ E next = getter.get(data, i);
+ for(int d = 0; d < dim; d++) {
+ mbr[d] = Math.min(mbr[d], next.getMin(d + 1));
+ mbr[dim + d] = Math.max(mbr[dim + d], next.getMax(d + 1));
+ }
+ }
+ return mbr;
+ }
+
+ /**
* Returns the centroid of this SpatialComparable.
*
* @param obj Spatial object to process
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 7474c14f..e418bcaf 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) 2011
+Copyright (C) 2012
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 3c5853ed..363c6c3b 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) 2011
+ Copyright (C) 2012
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.data.synthetic.bymodel;
import java.util.List;
+import de.lmu.ifi.dbs.elki.data.model.Model;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
import de.lmu.ifi.dbs.elki.utilities.exceptions.UnableToComplyException;
@@ -66,19 +67,15 @@ public interface GeneratorInterface {
public abstract double getDensity(Vector p);
/**
- * Get points.
- *
- * NOTE: The list may be modified by the caller, it is not immutable.
- * The class should not return a copy, but should allow modification.
- * However when removing points, the called is expected to call setDiscarded.
- *
- * @return points
- */
- public List<Vector> getPoints();
-
- /**
* Get cluster name
* @return cluster name
*/
public String getName();
+
+ /**
+ * Make a cluster model for this cluster.
+ *
+ * @return Cluster model
+ */
+ public Model makeModel();
} \ No newline at end of file
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 240cda31..cd3f18b7 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) 2011
+ Copyright (C) 2012
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.data.synthetic.bymodel;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
/**
* Interface for a dynamic cluster generator.
*
@@ -41,15 +40,14 @@ public interface GeneratorInterfaceDynamic extends GeneratorInterface {
public int getDiscarded();
/**
- * Indicate that points were discarded.
- *
- * @param discarded number of points that were discarded.
- */
- public void addDiscarded(int discarded);
-
- /**
* Retrieve remaining number of retries.
+ *
* @return remaining number of retries
*/
public int getRetries();
-}
+
+ /**
+ * Increment the number of elements discarded.
+ */
+ public void incrementDiscarded();
+} \ No newline at end of file
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 eef7b13d..6870fcaa 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -31,6 +31,7 @@ import java.util.List;
import de.lmu.ifi.dbs.elki.data.ClassLabel;
import de.lmu.ifi.dbs.elki.data.DoubleVector;
import de.lmu.ifi.dbs.elki.data.SimpleClassLabel;
+import de.lmu.ifi.dbs.elki.data.model.Model;
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;
@@ -91,26 +92,41 @@ public class GeneratorMain {
* @throws UnableToComplyException when model not satisfiable or no clusters
* specified.
*/
- public void generate() throws UnableToComplyException {
+ public MultipleObjectsBundle generate() throws UnableToComplyException {
// we actually need some clusters.
if(generators.size() < 1) {
throw new UnableToComplyException("No clusters specified.");
}
// Assert that cluster dimensions agree.
final int dim = generators.get(0).getDim();
- for(GeneratorInterface c : generators) {
- if(c.getDim() != dim) {
- throw new UnableToComplyException("Cluster dimensions do not agree.");
+ {
+ for(GeneratorInterface c : generators) {
+ if(c.getDim() != dim) {
+ throw new UnableToComplyException("Cluster dimensions do not agree.");
+ }
}
}
+ // Vector factory. TODO: make configurable
+ final DoubleVector factory = new DoubleVector(new double[dim]);
+ // Prepare result bundle
+ MultipleObjectsBundle bundle = new MultipleObjectsBundle();
+ VectorFieldTypeInformation<DoubleVector> type = new VectorFieldTypeInformation<DoubleVector>(DoubleVector.class, dim, factory);
+ bundle.appendColumn(type, new ArrayList<Object>());
+ bundle.appendColumn(TypeUtil.CLASSLABEL, new ArrayList<Object>());
+ bundle.appendColumn(TypeUtil.MODEL, new ArrayList<Model>());
+
// generate clusters
for(GeneratorInterface curclus : generators) {
- while(curclus.getPoints().size() < curclus.getSize()) {
+ ClassLabel l = new SimpleClassLabel(curclus.getName());
+ Model model = curclus.makeModel();
+ int kept = 0;
+ while(kept < curclus.getSize()) {
// generate the "missing" number of points
- List<Vector> newp = curclus.generate(curclus.getSize() - curclus.getPoints().size());
+ List<Vector> newp = curclus.generate(curclus.getSize() - kept);
if(curclus instanceof GeneratorInterfaceDynamic) {
GeneratorInterfaceDynamic cursclus = (GeneratorInterfaceDynamic) curclus;
for(Vector p : newp) {
+ boolean keep = true;
if(testAgainstModel) {
double max = 0.0;
double is = 0.0;
@@ -125,20 +141,23 @@ public class GeneratorMain {
}
// Only keep the point if the largest density was the cluster it
// was generated for
- if(is >= max) {
- cursclus.getPoints().add(p);
- }
- else {
- cursclus.addDiscarded(1);
+ if(is < max) {
+ keep = false;
}
}
+ if(keep) {
+ DoubleVector dv = new DoubleVector(p);
+ bundle.appendSimple(dv, l, model);
+ ++kept;
+ }
else {
- cursclus.getPoints().add(p);
+ cursclus.incrementDiscarded();
}
}
}
}
}
+ return bundle;
}
/**
@@ -167,27 +186,4 @@ public class GeneratorMain {
public List<GeneratorInterface> getGenerators() {
return Collections.unmodifiableList(generators);
}
-
- /**
- * Get the objects bundle
- *
- * @return Bundle
- */
- public MultipleObjectsBundle getBundle() {
- final int dim = generators.get(0).getDim();
- final DoubleVector factory = new DoubleVector(new double[dim]);
- MultipleObjectsBundle bundle = new MultipleObjectsBundle();
- VectorFieldTypeInformation<DoubleVector> type = new VectorFieldTypeInformation<DoubleVector>(DoubleVector.class, dim, factory);
- bundle.appendColumn(type, new ArrayList<Object>());
- bundle.appendColumn(TypeUtil.CLASSLABEL, new ArrayList<Object>());
-
- for(GeneratorInterface generator : generators) {
- ClassLabel l = new SimpleClassLabel(generator.getName());
- for(Vector v : generator.getPoints()) {
- DoubleVector dv = new DoubleVector(v);
- bundle.appendSimple(dv, l);
- }
- }
- return bundle;
- }
} \ No newline at end of file
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 3d54d937..f9818916 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) 2011
+ Copyright (C) 2012
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.data.synthetic.bymodel;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.LinkedList;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Random;
-import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.distribution.Distribution;
+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.Distribution;
import de.lmu.ifi.dbs.elki.utilities.exceptions.UnableToComplyException;
/**
@@ -41,11 +43,11 @@ import de.lmu.ifi.dbs.elki.utilities.exceptions.UnableToComplyException;
* @apiviz.composedOf Distribution
* @apiviz.composedOf AffineTransformation
*/
-public class GeneratorSingleCluster implements GeneratorInterfaceDynamic {
+public class GeneratorSingleCluster implements GeneratorInterfaceDynamic, Model {
/**
* The distribution generators for each axis
*/
- private LinkedList<Distribution> axes = new LinkedList<Distribution>();
+ private List<Distribution> axes = new ArrayList<Distribution>();
/**
* The transformation matrix
@@ -91,11 +93,6 @@ public class GeneratorSingleCluster implements GeneratorInterfaceDynamic {
private int discarded = 0;
/**
- * The generated cluster points.
- */
- public LinkedList<Vector> points = new LinkedList<Vector>();
-
- /**
* Random generator (used for initializing random generators)
*/
private Random random;
@@ -121,7 +118,8 @@ public class GeneratorSingleCluster implements GeneratorInterfaceDynamic {
* so far!
*
* @param gen Distribution generator
- * @throws UnableToComplyException thrown when no new generators may be added anymore
+ * @throws UnableToComplyException thrown when no new generators may be added
+ * anymore
*/
public void addGenerator(Distribution gen) throws UnableToComplyException {
if(trans != null) {
@@ -168,23 +166,23 @@ public class GeneratorSingleCluster implements GeneratorInterfaceDynamic {
*/
public void setClipping(Vector min, Vector max) throws UnableToComplyException {
// if only one dimension was given, expand to all dimensions.
- if(min.getRowDimensionality() == 1 && max.getRowDimensionality() == 1) {
+ if(min.getDimensionality() == 1 && max.getDimensionality() == 1) {
if(min.get(0) >= max.get(0)) {
throw new UnableToComplyException("Clipping range empty.");
}
clipmin = new Vector(dim);
clipmax = new Vector(dim);
for(int i = 0; i < dim; i++) {
- clipmin.set(i, 0, min.get(0));
- clipmax.set(i, 0, max.get(0));
+ clipmin.set(i, min.get(0));
+ clipmax.set(i, max.get(0));
}
return;
}
- if(dim != min.getRowDimensionality()) {
- throw new UnableToComplyException("Clipping vector dimensionalities do not match: " + dim + " vs. " + min.getRowDimensionality());
+ if(dim != min.getDimensionality()) {
+ throw new UnableToComplyException("Clipping vector dimensionalities do not match: " + dim + " vs. " + min.getDimensionality());
}
- if(dim != max.getRowDimensionality()) {
- throw new UnableToComplyException("Clipping vector dimensionalities do not match: " + dim + " vs. " + max.getRowDimensionality());
+ if(dim != max.getDimensionality()) {
+ throw new UnableToComplyException("Clipping vector dimensionalities do not match: " + dim + " vs. " + max.getDimensionality());
}
for(int i = 0; i < dim; i++) {
if(min.get(i) >= max.get(i)) {
@@ -215,7 +213,7 @@ public class GeneratorSingleCluster implements GeneratorInterfaceDynamic {
if(clipmin == null || clipmax == null) {
return false;
}
- for(int i = 0; i < p.getRowDimensionality(); i++) {
+ for(int i = 0; i < p.getDimensionality(); i++) {
if(p.get(i) < clipmin.get(i)) {
return true;
}
@@ -232,13 +230,13 @@ public class GeneratorSingleCluster implements GeneratorInterfaceDynamic {
* @see de.lmu.ifi.dbs.elki.data.synthetic.bymodel.GeneratorInterface#generate(int)
*/
@Override
- public LinkedList<Vector> generate(int count) throws UnableToComplyException {
- LinkedList<Vector> result = new LinkedList<Vector>();
+ public List<Vector> generate(int count) throws UnableToComplyException {
+ ArrayList<Vector> result = new ArrayList<Vector>(count);
while(result.size() < count) {
double[] d = new double[dim];
int i = 0;
for(Distribution axis : axes) {
- d[i] = axis.generate();
+ d[i] = axis.nextRandom();
i++;
}
Vector p = new Vector(d);
@@ -272,27 +270,18 @@ public class GeneratorSingleCluster implements GeneratorInterfaceDynamic {
double density = 1.0;
int i = 0;
for(Distribution axis : axes) {
- density = density * axis.explain(o.get(i));
+ density = density * axis.pdf(o.get(i));
i++;
}
return density * densitycorrection;
}
/**
- * Get axis generators. Used for printing model information
- *
- * @return list of distributions
- */
- public LinkedList<Distribution> getAxes() {
- return axes;
- }
-
- /**
* Get transformation
*
* @return transformation matrix, may be null.
*/
- public AffineTransformation getTrans() {
+ public AffineTransformation getTransformation() {
return trans;
}
@@ -321,23 +310,6 @@ public class GeneratorSingleCluster implements GeneratorInterfaceDynamic {
}
/**
- * Return the list of points (no copy)
- */
- @Override
- public LinkedList<Vector> getPoints() {
- return points;
- }
-
- /**
- * Set the list of points in the cluster
- *
- * @param points New list of points in this cluster.
- */
- public void setPoints(LinkedList<Vector> points) {
- this.points = points;
- }
-
- /**
* Return the size
*
* @return size of this cluster.
@@ -369,12 +341,10 @@ public class GeneratorSingleCluster implements GeneratorInterfaceDynamic {
/**
* Increase number of discarded points
- *
- * @param discarded number of points discarded.
*/
@Override
- public void addDiscarded(int discarded) {
- this.discarded += discarded;
+ public void incrementDiscarded() {
+ ++this.discarded;
}
/**
@@ -413,4 +383,23 @@ public class GeneratorSingleCluster implements GeneratorInterfaceDynamic {
public Random getNewRandomGenerator() {
return new Random(random.nextLong());
}
+
+ /**
+ * Make a cluster model for this cluster.
+ *
+ * @return Model
+ */
+ public Model makeModel() {
+ return this;
+ }
+
+ /**
+ * Get distribution along (generator) axis i.
+ *
+ * @param i Generator axis i
+ * @return Distribution
+ */
+ 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 6c44eaca..7075bcb4 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) 2011
+ Copyright (C) 2012
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.data.synthetic.bymodel;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.ArrayList;
-import java.util.LinkedList;
+import java.util.Collections;
import java.util.List;
+import de.lmu.ifi.dbs.elki.data.model.ClusterModel;
+import de.lmu.ifi.dbs.elki.data.model.Model;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
-import de.lmu.ifi.dbs.elki.utilities.exceptions.UnableToComplyException;
/**
* Class for static clusters, that is an implementation of GeneratorInterface
@@ -45,7 +45,7 @@ public class GeneratorStatic implements GeneratorInterface {
/**
* Cluster points
*/
- public LinkedList<Vector> points;
+ public List<Vector> points;
/**
* Construct generator using given name and points
@@ -53,7 +53,7 @@ public class GeneratorStatic implements GeneratorInterface {
* @param name Cluster name
* @param points Cluster points
*/
- public GeneratorStatic(String name, LinkedList<Vector> points) {
+ public GeneratorStatic(String name, List<Vector> points) {
super();
this.name = name;
this.points = points;
@@ -67,12 +67,9 @@ public class GeneratorStatic implements GeneratorInterface {
*/
@Override
public List<Vector> generate(int count) {
- return new ArrayList<Vector>(points);
+ return Collections.unmodifiableList(points);
}
- /**
- * Get density at a given coordinate.
- */
@Override
public double getDensity(Vector p) {
for(Vector my : points) {
@@ -83,54 +80,23 @@ public class GeneratorStatic implements GeneratorInterface {
return 0.0;
}
- /**
- * Get cluster dimensionality
- */
@Override
public int getDim() {
- return points.getFirst().getDimensionality();
+ return points.get(0).getDimensionality();
}
- /**
- * Get number of discarded points
- *
- * @return number of discarded points
- */
- public int getDiscarded() {
- return 0;
- }
-
- /**
- * Get cluster name
- */
@Override
public String getName() {
return name;
}
- /**
- * Get cluster points
- */
- @Override
- public List<Vector> getPoints() {
- return points;
- }
-
- /**
- * Get cluster size
- */
@Override
public int getSize() {
return points.size();
}
- /**
- * Notify cluster of discarded points. Not supported for static generators.
- *
- * @param discarded parameter not supported.
- * @throws UnableToComplyException always thrown, since the static generator doesn't supprot discards.
- */
- public void setDiscarded(int discarded) throws UnableToComplyException {
- throw new UnableToComplyException("Points in static clusters may never be discarded.");
+ @Override
+ public Model makeModel() {
+ return ClusterModel.CLUSTER;
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/distribution/NormalDistribution.java b/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/distribution/NormalDistribution.java
deleted file mode 100644
index 24f06f32..00000000
--- a/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/distribution/NormalDistribution.java
+++ /dev/null
@@ -1,127 +0,0 @@
-package de.lmu.ifi.dbs.elki.data.synthetic.bymodel.distribution;
-
-/*
- 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 java.util.Random;
-
-import de.lmu.ifi.dbs.elki.math.MathUtil;
-
-/**
- * Simple generator for a Gaussian = Normal Distribution
- *
- * @author Erich Schubert
- */
-public final class NormalDistribution implements Distribution {
- /**
- * Mean value for the generator
- */
- private double mean;
-
- /**
- * Standard deviation
- */
- private double stddev;
-
- /**
- * The random generator.
- */
- private Random random;
-
- /**
- * Constructor for Gaussian generator
- *
- * @param mean Mean
- * @param stddev Standard Deviation
- * @param random Random generator
- */
- public NormalDistribution(double mean, double stddev, Random random) {
- this.mean = mean;
- this.stddev = stddev;
- this.random = random;
- }
-
- /**
- * Standardized Gaussian PDF
- *
- * @param x query value
- * @return probability density
- */
- // TODO: make a math.distributions package with various PDF, CDF, Error
- // functions etc.?
- private static double phi(double x) {
- return Math.exp(-x * x / 2) / MathUtil.SQRTTWOPI;
- }
-
- /**
- * Gaussian distribution PDF
- *
- * @param x query value
- * @param mu mean
- * @param sigma standard distribution
- * @return probability density
- */
- public static double phi(double x, double mu, double sigma) {
- return phi((x - mu) / sigma) / sigma;
- }
-
- /**
- * Return the PDF of the generators distribution
- */
- @Override
- public double explain(double val) {
- return phi(val, mean, stddev);
- }
-
- /**
- * Generate a random value with the generators parameters
- */
- @Override
- public double generate() {
- return mean + random.nextGaussian() * stddev;
- }
-
- /**
- * Simple toString explaining the distribution parameters.
- *
- * Used in producing a model description.
- */
- @Override
- public String toString() {
- return "Normal Distribution (mean="+mean+", stddev="+stddev+")";
- }
-
- /**
- * @return the mean
- */
- public double getMean() {
- return mean;
- }
-
- /**
- * @return the standard deviation
- */
- public double getStddev() {
- return stddev;
- }
-}
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 dd0d3e44..51dcd8e8 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) 2011
+Copyright (C) 2012
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 4151409d..c311cf0b 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) 2011
+Copyright (C) 2012
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 3d37c680..89fc760a 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) 2011
+ Copyright (C) 2012
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/CombinedTypeInformation.java b/src/de/lmu/ifi/dbs/elki/data/type/CombinedTypeInformation.java
index 02a549f6..15712262 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) 2011
+ Copyright (C) 2012
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/NoSupportedDataTypeException.java b/src/de/lmu/ifi/dbs/elki/data/type/NoSupportedDataTypeException.java
index 3bfef34f..9865e96f 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) 2011
+ Copyright (C) 2012
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 c169906e..7fb66462 100644
--- a/src/de/lmu/ifi/dbs/elki/data/type/SimpleTypeInformation.java
+++ b/src/de/lmu/ifi/dbs/elki/data/type/SimpleTypeInformation.java
@@ -1,10 +1,12 @@
package de.lmu.ifi.dbs.elki.data.type;
+import de.lmu.ifi.dbs.elki.persistent.ByteBufferSerializer;
+
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,7 +25,6 @@ package de.lmu.ifi.dbs.elki.data.type;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
/**
* Class wrapping a particular data type.
*
@@ -36,13 +37,18 @@ public class SimpleTypeInformation<T> implements TypeInformation {
* The restriction class we represent.
*/
private Class<? super T> cls;
-
+
/**
* Type label
*/
private String label = null;
/**
+ * Type serializer
+ */
+ private ByteBufferSerializer<? super T> serializer = null;
+
+ /**
* Constructor.
*
* @param cls restriction class
@@ -65,6 +71,33 @@ public class SimpleTypeInformation<T> implements TypeInformation {
}
/**
+ * Constructor.
+ *
+ * @param cls restriction class
+ * @param serializer Serializer
+ */
+ public SimpleTypeInformation(Class<? super T> cls, ByteBufferSerializer<? super T> serializer) {
+ super();
+ this.cls = cls;
+ this.serializer = serializer;
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param cls restriction class
+ * @param label type label
+ * @param serializer Serializer
+ */
+ public SimpleTypeInformation(Class<? super T> cls, String label, ByteBufferSerializer<? super T> serializer) {
+ super();
+ this.cls = cls;
+ this.label = label;
+ this.serializer = serializer;
+ }
+
+
+ /**
* Get the raw restriction class.
*
* @return Restriction class
@@ -111,4 +144,13 @@ public class SimpleTypeInformation<T> implements TypeInformation {
public String getLabel() {
return label;
}
+
+ /**
+ * Get the serializer for this type.
+ *
+ * @return Type serializer
+ */
+ public ByteBufferSerializer<? super T> getSerializer() {
+ return serializer;
+ }
} \ No newline at end of file
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 b871f2a7..d39afcad 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) 2011
+ Copyright (C) 2012
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/TypeUtil.java b/src/de/lmu/ifi/dbs/elki/data/type/TypeUtil.java
index 7abad242..91257906 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -30,10 +30,13 @@ import de.lmu.ifi.dbs.elki.data.ExternalID;
import de.lmu.ifi.dbs.elki.data.LabelList;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.data.SparseFloatVector;
+import de.lmu.ifi.dbs.elki.data.model.Model;
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.math.linearalgebra.Matrix;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
+import de.lmu.ifi.dbs.elki.persistent.ByteArrayUtil;
/**
* Utility package containing various common types
@@ -52,12 +55,12 @@ public final class TypeUtil {
/**
* Database IDs
*/
- public static final SimpleTypeInformation<DBID> DBID = new SimpleTypeInformation<DBID>(DBID.class);
+ public static final SimpleTypeInformation<DBID> DBID = new SimpleTypeInformation<DBID>(DBID.class, DBIDFactory.FACTORY.getDBIDSerializer());
/**
* A string
*/
- public static final SimpleTypeInformation<String> STRING = new SimpleTypeInformation<String>(String.class);
+ public static final SimpleTypeInformation<String> STRING = new SimpleTypeInformation<String>(String.class, ByteArrayUtil.STRING_SERIALIZER);
/**
* A class label
@@ -77,6 +80,11 @@ public final class TypeUtil {
public static final TypeInformation GUESSED_LABEL = new AlternativeTypeInformation(LABELLIST, CLASSLABEL, STRING);
/**
+ * Number vectors of <em>variable</em> length.
+ */
+ public static final SimpleTypeInformation<? super NumberVector<?, ?>> NUMBER_VECTOR_VARIABLE_LENGTH = new SimpleTypeInformation<NumberVector<?, ?>>(NumberVector.class);
+
+ /**
* Input type for algorithms that require number vector fields.
*/
public static final VectorFieldTypeInformation<NumberVector<?, ?>> NUMBER_VECTOR_FIELD = new VectorFieldTypeInformation<NumberVector<?, ?>>(NumberVector.class);
@@ -86,7 +94,7 @@ public final class TypeUtil {
*
* 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>(DoubleVector.class, DoubleVector.STATIC);
/**
* Input type for algorithms that require number vector fields.
@@ -111,12 +119,12 @@ public final class TypeUtil {
/**
* Double type, outlier scores etc.
*/
- public static final SimpleTypeInformation<Double> DOUBLE = new SimpleTypeInformation<Double>(Double.class);
+ public static final SimpleTypeInformation<Double> DOUBLE = new SimpleTypeInformation<Double>(Double.class, ByteArrayUtil.DOUBLE_SERIALIZER);
/**
* Integer type.
*/
- public static final SimpleTypeInformation<Integer> INTEGER = new SimpleTypeInformation<Integer>(Integer.class);
+ public static final SimpleTypeInformation<Integer> INTEGER = new SimpleTypeInformation<Integer>(Integer.class, ByteArrayUtil.INT_SERIALIZER);
/**
* Vector type.
@@ -129,6 +137,11 @@ public final class TypeUtil {
public static final SimpleTypeInformation<Matrix> MATRIX = new SimpleTypeInformation<Matrix>(Matrix.class);
/**
+ * Cluster model type.
+ */
+ public static final SimpleTypeInformation<Model> MODEL = new SimpleTypeInformation<Model>(Model.class);
+
+ /**
* Make a type array easily.
*
* @param ts Types
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 99bed220..69e0c969 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) 2011
+ Copyright (C) 2012
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.data.type;
*/
import de.lmu.ifi.dbs.elki.data.FeatureVector;
+import de.lmu.ifi.dbs.elki.persistent.ByteBufferSerializer;
/**
* Type information to specify that a type has a fixed dimensionality.
@@ -44,27 +45,86 @@ public class VectorFieldTypeInformation<V extends FeatureVector<?, ?>> extends V
private String[] labels = null;
/**
- * Constructor for a request without fixed dimensionality.
+ * Constructor with given dimensionality and factory, so usually an instance.
+ *
+ * @param cls Restriction java class
+ * @param serializer Serializer
+ * @param dim Dimensionality
+ * @param labels Labels
+ * @param factory Factory class
+ */
+ public VectorFieldTypeInformation(Class<? super V> cls, ByteBufferSerializer<? super V> serializer, int dim, String[] labels, V factory) {
+ super(cls, serializer, dim, dim);
+ this.labels = labels;
+ this.factory = factory;
+ assert (labels == null || labels.length == dim) : "Created vector field with incomplete labels.";
+ }
+
+ /**
+ * Constructor for a request with minimum and maximum dimensionality.
*
* @param cls Vector restriction class.
+ * @param serializer Serializer
+ * @param mindim Minimum dimensionality request
+ * @param maxdim Maximum dimensionality request
*/
- public VectorFieldTypeInformation(Class<? super V> cls) {
- super(cls);
+ public VectorFieldTypeInformation(Class<? super V> cls, ByteBufferSerializer<? super V> serializer, int mindim, int maxdim) {
+ super(cls, serializer, mindim, maxdim);
this.factory = null;
}
/**
+ * Constructor with given dimensionality and factory, so usually an instance.
+ *
+ * @param cls Restriction java class
+ * @param serializer Serializer
+ * @param dim Dimensionality
+ * @param factory Factory class
+ */
+ public VectorFieldTypeInformation(Class<? super V> cls, ByteBufferSerializer<? super V> serializer, int dim, V factory) {
+ super(cls, serializer, dim, dim);
+ this.factory = factory;
+ }
+
+ /**
* Constructor for a request with fixed dimensionality.
*
* @param cls Vector restriction class.
+ * @param serializer Serializer
* @param dim Dimensionality request
*/
- public VectorFieldTypeInformation(Class<? super V> cls, int dim) {
- super(cls, dim, dim);
+ public VectorFieldTypeInformation(Class<? super V> cls, ByteBufferSerializer<? super V> serializer, int dim) {
+ super(cls, serializer, dim, dim);
+ this.factory = null;
+ }
+
+ /**
+ * Constructor for a request without fixed dimensionality.
+ *
+ * @param cls Vector restriction class.
+ * @param serializer Serializer
+ */
+ public VectorFieldTypeInformation(Class<? super V> cls, ByteBufferSerializer<? super V> serializer) {
+ super(cls, serializer);
this.factory = null;
}
/**
+ * Constructor with given dimensionality and factory, so usually an instance.
+ *
+ * @param cls Restriction java class
+ * @param dim Dimensionality
+ * @param labels Labels
+ * @param factory Factory class
+ */
+ public VectorFieldTypeInformation(Class<? super V> cls, int dim, String[] labels, V factory) {
+ super(cls, dim, dim);
+ this.labels = labels;
+ this.factory = factory;
+ assert (labels == null || labels.length == dim) : "Created vector field with incomplete labels.";
+ }
+
+ /**
* Constructor for a request with minimum and maximum dimensionality.
*
* @param cls Vector restriction class.
@@ -89,18 +149,24 @@ public class VectorFieldTypeInformation<V extends FeatureVector<?, ?>> extends V
}
/**
- * Constructor with given dimensionality and factory, so usually an instance.
+ * Constructor for a request with fixed dimensionality.
*
- * @param cls Restriction java class
- * @param dim Dimensionality
- * @param labels Labels
- * @param factory Factory class
+ * @param cls Vector restriction class.
+ * @param dim Dimensionality request
*/
- public VectorFieldTypeInformation(Class<? super V> cls, int dim, String[] labels, V factory) {
+ public VectorFieldTypeInformation(Class<? super V> cls, int dim) {
super(cls, dim, dim);
- this.labels = labels;
- this.factory = factory;
- assert (labels == null || labels.length == dim) : "Created vector field with incomplete labels.";
+ this.factory = null;
+ }
+
+ /**
+ * Constructor for a request without fixed dimensionality.
+ *
+ * @param cls Vector restriction class.
+ */
+ public VectorFieldTypeInformation(Class<? super V> cls) {
+ super(cls);
+ this.factory = null;
}
@Override
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 a529ce7b..012cff48 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) 2011
+ Copyright (C) 2012
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.data.type;
*/
import de.lmu.ifi.dbs.elki.data.FeatureVector;
+import de.lmu.ifi.dbs.elki.persistent.ByteBufferSerializer;
/**
* Construct a type information for vector spaces with fixed dimensionality.
@@ -47,11 +48,12 @@ public class VectorTypeInformation<V extends FeatureVector<?, ?>> extends Simple
* Constructor.
*
* @param cls base class
+ * @param serializer Serializer
* @param mindim Minimum dimensionality
* @param maxdim Maximum dimensionality
*/
- public VectorTypeInformation(Class<? super V> cls, int mindim, int maxdim) {
- super(cls);
+ public VectorTypeInformation(Class<? super V> cls, ByteBufferSerializer<? super V> serializer, int mindim, int maxdim) {
+ super(cls, serializer);
assert (this.mindim <= this.maxdim);
this.mindim = mindim;
this.maxdim = maxdim;
@@ -60,10 +62,31 @@ public class VectorTypeInformation<V extends FeatureVector<?, ?>> extends Simple
/**
* Constructor without size constraints.
*
+ * @param cls base class
+ * @param serializer Serializer
+ */
+ public VectorTypeInformation(Class<? super V> cls, ByteBufferSerializer<? super V> serializer) {
+ this(cls, serializer, -1, Integer.MAX_VALUE);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param cls base class
+ * @param mindim Minimum dimensionality
+ * @param maxdim Maximum dimensionality
+ */
+ public VectorTypeInformation(Class<? super V> cls, int mindim, int maxdim) {
+ this(cls, null, mindim, maxdim);
+ }
+
+ /**
+ * Constructor without size constraints.
+ *
* @param cls
*/
public VectorTypeInformation(Class<? super V> cls) {
- this(cls, -1, Integer.MAX_VALUE);
+ this(cls, null, -1, Integer.MAX_VALUE);
}
@Override
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 92a3e931..858efc7a 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) 2011
+Copyright (C) 2012
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 f20efcec..f9582039 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) 2011
+ Copyright (C) 2012
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.database;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import java.util.ListIterator;
import de.lmu.ifi.dbs.elki.data.type.NoSupportedDataTypeException;
import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
@@ -106,7 +107,7 @@ public abstract class AbstractDatabase extends AbstractHierarchicalResult implem
}
@Override
- public Collection<Index> getIndexes() {
+ public List<Index> getIndexes() {
return Collections.unmodifiableList(this.indexes);
}
@@ -151,6 +152,14 @@ public abstract class AbstractDatabase extends AbstractHierarchicalResult implem
return (Relation<O>) relation;
}
}
+ if (getLogger().isDebugging()) {
+ StringBuffer buf = new StringBuffer();
+ buf.append("No matching relation for type ").append(restriction.toString()).append(":\n");
+ for(Relation<?> relation : relations) {
+ buf.append(relation.getDataTypeInformation().toString()).append(",");
+ }
+ getLogger().debug(buf);
+ }
throw new NoSupportedDataTypeException(restriction);
}
@@ -175,8 +184,13 @@ public abstract class AbstractDatabase extends AbstractHierarchicalResult implem
if(distanceQuery == null) {
throw new AbortException("kNN query requested for 'null' distance!");
}
- for(Index idx : getIndexes()) {
+ ListIterator<Index> iter = indexes.listIterator(indexes.size());
+ while(iter.hasPrevious()) {
+ Index idx = iter.previous();
if(idx instanceof KNNIndex) {
+ if(getLogger().isDebuggingFinest()) {
+ getLogger().debugFinest("Considering index for kNN Query: " + idx);
+ }
@SuppressWarnings("unchecked")
final KNNIndex<O> knnIndex = (KNNIndex<O>) idx;
KNNQuery<O, D> q = knnIndex.getKNNQuery(distanceQuery, hints);
@@ -200,8 +214,13 @@ public abstract class AbstractDatabase extends AbstractHierarchicalResult implem
if(distanceQuery == null) {
throw new AbortException("Range query requested for 'null' distance!");
}
- for(Index idx : getIndexes()) {
+ ListIterator<Index> iter = indexes.listIterator(indexes.size());
+ while(iter.hasPrevious()) {
+ Index idx = iter.previous();
if(idx instanceof RangeIndex) {
+ if(getLogger().isDebuggingFinest()) {
+ getLogger().debugFinest("Considering index for range query: " + idx);
+ }
@SuppressWarnings("unchecked")
final RangeIndex<O> rangeIndex = (RangeIndex<O>) idx;
RangeQuery<O, D> q = rangeIndex.getRangeQuery(distanceQuery, hints);
@@ -225,8 +244,13 @@ public abstract class AbstractDatabase extends AbstractHierarchicalResult implem
if(distanceQuery == null) {
throw new AbortException("RKNN query requested for 'null' distance!");
}
- for(Index idx : getIndexes()) {
+ ListIterator<Index> iter = indexes.listIterator(indexes.size());
+ while(iter.hasPrevious()) {
+ Index idx = iter.previous();
if(idx instanceof RKNNIndex) {
+ if(getLogger().isDebuggingFinest()) {
+ getLogger().debugFinest("Considering index for RkNN Query: " + idx);
+ }
@SuppressWarnings("unchecked")
final RKNNIndex<O> rknnIndex = (RKNNIndex<O>) idx;
RKNNQuery<O, D> q = rknnIndex.getRKNNQuery(distanceQuery, hints);
diff --git a/src/de/lmu/ifi/dbs/elki/database/Database.java b/src/de/lmu/ifi/dbs/elki/database/Database.java
index 1b216fd0..a931d5c8 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -30,7 +30,6 @@ import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreEvent;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreListener;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.database.ids.StaticDBIDs;
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;
@@ -43,6 +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;
/**
* Database specifies the requirements for any database implementation. Note
@@ -60,7 +60,7 @@ import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
* @apiviz.has Index oneway - - manages
* @apiviz.uses DataStoreListener oneway - - invokes
*/
-public interface Database extends HierarchicalResult {
+public interface Database extends HierarchicalResult, InspectionUtilFrequentlyScanned {
/**
* Initialize the database, for example by loading the input data. (Since this
* should NOT be done on construction time!)
@@ -68,14 +68,6 @@ public interface Database extends HierarchicalResult {
public void initialize();
/**
- * Returns the number of objects contained in this Database.
- *
- * @return the number of objects in this Database
- */
- @Deprecated
- int size();
-
- /**
* Get all relations of a database.
*
* @return All relations in the database
@@ -93,18 +85,6 @@ public interface Database extends HierarchicalResult {
<O> Relation<O> getRelation(TypeInformation restriction, Object... hints) throws NoSupportedDataTypeException;
/**
- * Get all matching object representations.
- *
- * @param <O> Object type
- * @param restriction Type restriction
- * @param hints Optimizer hints
- * @return Object representation
- */
- // TODO: add
- // <O> Collection<DataQuery<O>> getObjectQueries(TypeInformation restriction,
- // Object... hints);
-
- /**
* Get the distance query for a particular distance function.
*
* @param <O> Object type
@@ -210,17 +190,6 @@ public interface Database extends HierarchicalResult {
// MultipleObjectsBundle getBundles(DBIDs id) throws ObjectNotFoundException;
/**
- * Returns a list comprising all IDs currently in use.
- *
- * The list returned shall not be linked to any actual list possibly hold in
- * the database implementation.
- *
- * @return a list comprising all IDs currently in use
- */
- @Deprecated
- StaticDBIDs getDBIDs();
-
- /**
* Add a new index to the database.
*
* @param index Index to add
diff --git a/src/de/lmu/ifi/dbs/elki/database/DatabaseEventManager.java b/src/de/lmu/ifi/dbs/elki/database/DatabaseEventManager.java
index 333ac1eb..633be46f 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) 2011
+Copyright (C) 2012
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/HashmapDatabase.java b/src/de/lmu/ifi/dbs/elki/database/HashmapDatabase.java
index a4c31379..e94bcfb1 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -33,8 +33,7 @@ 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.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
-import de.lmu.ifi.dbs.elki.database.ids.StaticDBIDs;
-import de.lmu.ifi.dbs.elki.database.ids.TreeSetModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.HashSetModifiableDBIDs;
import de.lmu.ifi.dbs.elki.database.relation.DBIDView;
import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
@@ -75,7 +74,7 @@ public class HashmapDatabase extends AbstractDatabase implements UpdatableDataba
/**
* IDs of this database
*/
- private TreeSetModifiableDBIDs ids;
+ private HashSetModifiableDBIDs ids;
/**
* The DBID representation we use
@@ -96,7 +95,7 @@ public class HashmapDatabase extends AbstractDatabase implements UpdatableDataba
public HashmapDatabase(DatabaseConnection databaseConnection, Collection<IndexFactory<?, ?>> indexFactories) {
super();
this.databaseConnection = databaseConnection;
- this.ids = DBIDUtil.newTreeSet();
+ this.ids = DBIDUtil.newHashSet();
this.idrep = new DBIDView(this, this.ids);
this.relations.add(idrep);
this.addChildResult(idrep);
@@ -284,18 +283,6 @@ public class HashmapDatabase extends AbstractDatabase implements UpdatableDataba
restoreID(id);
}
- @Deprecated
- @Override
- public final int size() {
- return ids.size();
- }
-
- @Deprecated
- @Override
- public StaticDBIDs getDBIDs() {
- return DBIDUtil.makeUnmodifiable(ids);
- }
-
/**
* Makes the given id reusable for new insertion operations.
*
diff --git a/src/de/lmu/ifi/dbs/elki/database/ProxyDatabase.java b/src/de/lmu/ifi/dbs/elki/database/ProxyDatabase.java
index 4fc2455c..0f411cb4 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,9 +25,7 @@ package de.lmu.ifi.dbs.elki.database;
import java.util.Arrays;
-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.StaticDBIDs;
import de.lmu.ifi.dbs.elki.database.relation.DBIDView;
import de.lmu.ifi.dbs.elki.database.relation.ProxyView;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
@@ -120,18 +118,6 @@ public class ProxyDatabase extends AbstractDatabase {
this.relations.add(relation);
}
- @Deprecated
- @Override
- public int size() {
- return ids.size();
- }
-
- @Deprecated
- @Override
- public StaticDBIDs getDBIDs() {
- return DBIDUtil.makeUnmodifiable(ids);
- }
-
@Override
protected Logging getLogger() {
return logger;
diff --git a/src/de/lmu/ifi/dbs/elki/database/QueryUtil.java b/src/de/lmu/ifi/dbs/elki/database/QueryUtil.java
index 9e335f51..f65b3cba 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) 2011
+ Copyright (C) 2012
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/StaticArrayDatabase.java b/src/de/lmu/ifi/dbs/elki/database/StaticArrayDatabase.java
index 9d96a55f..79143ad8 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) 2011
+ Copyright (C) 2012
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.database;
import java.util.BitSet;
import java.util.Collection;
-import java.util.Collections;
import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
@@ -33,7 +32,6 @@ 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.DBIDUtil;
-import de.lmu.ifi.dbs.elki.database.ids.StaticDBIDs;
import de.lmu.ifi.dbs.elki.database.relation.DBIDView;
import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
@@ -65,7 +63,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
* @apiviz.uses DatabaseConnection
*/
@Description("Database using an in-memory hashtable and at least providing linear scans.")
-public class StaticArrayDatabase extends AbstractDatabase implements Database, Parameterizable {
+public class StaticArrayDatabase extends AbstractDatabase implements Parameterizable {
/**
* Our logger
*/
@@ -185,21 +183,14 @@ public class StaticArrayDatabase extends AbstractDatabase implements Database, P
@Override
public void addIndex(Index index) {
+ if(logger.isDebuggingFiner()) {
+ logger.debugFine("Adding index: " + index);
+ }
this.indexes.add(index);
// TODO: actually add index to the representation used?
this.addChildResult(index);
}
- @Override
- public Collection<Index> getIndexes() {
- return Collections.unmodifiableList(this.indexes);
- }
-
- @Override
- public void removeIndex(Index index) {
- this.indexes.remove(index);
- this.getHierarchy().remove(this, index);
- }
/**
* Find an DBID column.
@@ -263,18 +254,6 @@ public class StaticArrayDatabase extends AbstractDatabase implements Database, P
return relation;
}
- @Deprecated
- @Override
- public final int size() {
- return ids.size();
- }
-
- @Deprecated
- @Override
- public StaticDBIDs getDBIDs() {
- return DBIDUtil.makeUnmodifiable(ids);
- }
-
@Override
protected Logging getLogger() {
return logger;
diff --git a/src/de/lmu/ifi/dbs/elki/database/UpdatableDatabase.java b/src/de/lmu/ifi/dbs/elki/database/UpdatableDatabase.java
index b74ebc1d..56a988f8 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) 2011
+ Copyright (C) 2012
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 1b0a714c..8d7f73ce 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) 2011
+ Copyright (C) 2012
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 a6849360..5c0a6836 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) 2011
+Copyright (C) 2012
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 d83c9a1c..65a1265d 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -42,34 +42,35 @@ public interface DataStoreFactory {
* Static storage factory
*/
public static DataStoreFactory FACTORY = new MemoryDataStoreFactory();
-
+
/**
* Storage will be used only temporary.
*/
public final static int HINT_TEMP = 0x01;
-
+
/**
* "Hot" data, that will be used a lot, preferring memory storage.
*/
public final static int HINT_HOT = 0x02;
-
+
/**
* "static" data, that will not change often
*/
public final static int HINT_STATIC = 0x04;
-
+
/**
* Data that might require sorted access (so hashmaps are suboptimal)
*/
public final static int HINT_SORTED = 0x08;
-
+
/**
* Data that is the main database. Includes HOT, STATIC, SORTED
*/
public final static int HINT_DB = 0x1E;
-
+
/**
- * Make a new storage, to associate the given ids with an object of class dataclass.
+ * Make a new storage, to associate the given ids with an object of class
+ * dataclass.
*
* @param <T> stored data type
* @param ids DBIDs to store data for
@@ -78,9 +79,20 @@ public interface DataStoreFactory {
* @return new data store
*/
public <T> WritableDataStore<T> makeStorage(DBIDs ids, int hints, Class<? super T> dataclass);
-
+
+ /**
+ * Make a new storage, to associate the given ids with an object of class
+ * dataclass.
+ *
+ * @param ids DBIDs to store data for
+ * @param hints Hints for the storage manager
+ * @return new data store
+ */
+ public WritableDoubleDataStore makeDoubleStorage(DBIDs ids, int hints);
+
/**
- * Make a new record storage, to associate the given ids with an object of class dataclass.
+ * Make a new record storage, to associate the given ids with an object of
+ * class dataclass.
*
* @param ids DBIDs to store data for
* @param hints Hints for the storage manager
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 21b876ce..ead75709 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) 2011
+ Copyright (C) 2012
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 02d5db77..609fe67d 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) 2011
+ Copyright (C) 2012
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 6e7af03d..f299c1e8 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -48,6 +48,17 @@ public final class DataStoreUtil {
}
/**
+ * Make a new storage, to associate the given ids with an object of class dataclass.
+ *
+ * @param ids DBIDs to store data for
+ * @param hints Hints for the storage manager
+ * @return new data store
+ */
+ public static WritableDoubleDataStore makeDoubleStorage(DBIDs ids, int hints) {
+ return DataStoreFactory.FACTORY.makeDoubleStorage(ids, hints);
+ }
+
+ /**
* Make a new record storage, to associate the given ids with an object of class dataclass.
*
* @param ids DBIDs to store data for
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/DoubleDataStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/DoubleDataStore.java
new file mode 100644
index 00000000..ee315a0c
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/DoubleDataStore.java
@@ -0,0 +1,44 @@
+package de.lmu.ifi.dbs.elki.database.datastore;
+
+import de.lmu.ifi.dbs.elki.database.ids.DBID;
+
+/*
+ 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/>.
+ */
+
+/**
+ * Double-valued data store (avoids boxing/unboxing).
+ *
+ * @author Erich Schubert
+ */
+public interface DoubleDataStore extends DataStore<Double> {
+ @Deprecated
+ public Double get(DBID id);
+
+ /**
+ * Retrieves an object from the storage.
+ *
+ * @param id Database ID.
+ * @return Double value
+ */
+ public double doubleValue(DBID id);
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/RangeIDMap.java b/src/de/lmu/ifi/dbs/elki/database/datastore/RangeIDMap.java
index 85a0f4c4..7fc0ed7f 100644
--- a/src/de/lmu/ifi/dbs/elki/database/datastore/RangeIDMap.java
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/RangeIDMap.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) 2011
+ Copyright (C) 2012
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 31bbbc3b..508dae8e 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) 2011
+ Copyright (C) 2012
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 a06c4b3f..7f1fbf52 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) 2011
+ Copyright (C) 2012
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
new file mode 100644
index 00000000..313e4adc
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDoubleDataStore.java
@@ -0,0 +1,59 @@
+package de.lmu.ifi.dbs.elki.database.datastore;
+
+import de.lmu.ifi.dbs.elki.database.ids.DBID;
+
+/*
+ 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/>.
+ */
+
+/**
+ * Data store specialized for doubles. Avoids boxing/unboxing.
+ *
+ * @author Erich Schubert
+ */
+public interface WritableDoubleDataStore extends DoubleDataStore, WritableDataStore<Double> {
+ @Override
+ @Deprecated
+ public Double put(DBID id, Double value);
+
+ /**
+ * Associates the specified value with the specified id in this storage. If
+ * the storage previously contained a value for the id, the previous value is
+ * replaced by the specified value.
+ *
+ * @param id Database ID.
+ * @param value Value to store.
+ * @return previous value
+ */
+ public double putDouble(DBID id, double value);
+
+ /**
+ * Associates the specified value with the specified id in this storage. If
+ * the storage previously contained a value for the id, the previous value is
+ * replaced by the specified value.
+ *
+ * @param id Database ID.
+ * @param value Value to store.
+ * @return previous value
+ */
+ public double put(DBID id, double value);
+} \ No newline at end of file
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 749acb0a..775d201b 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) 2011
+ Copyright (C) 2012
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
new file mode 100644
index 00000000..433547a5
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayDoubleStore.java
@@ -0,0 +1,121 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.DataStoreIDMap;
+import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
+import de.lmu.ifi.dbs.elki.database.ids.DBID;
+
+/**
+ * A class to answer representation queries using the stored Array.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.composedOf de.lmu.ifi.dbs.elki.database.datastore.DataStoreIDMap
+ */
+public class ArrayDoubleStore implements WritableDoubleDataStore {
+ /**
+ * Data array
+ */
+ private double[] data;
+
+ /**
+ * DBID to index map
+ */
+ private DataStoreIDMap idmap;
+
+ /**
+ * Constructor.
+ *
+ * @param size Size
+ * @param idmap ID map
+ */
+ public ArrayDoubleStore(int size, DataStoreIDMap idmap) {
+ super();
+ this.data = new double[size];
+ this.idmap = idmap;
+ }
+
+ @Override
+ @Deprecated
+ public Double get(DBID id) {
+ try {
+ return data[idmap.map(id)];
+ }
+ catch(ArrayIndexOutOfBoundsException e) {
+ return null;
+ }
+ }
+
+ @Override
+ @Deprecated
+ public Double put(DBID id, Double value) {
+ final int off = idmap.map(id);
+ double ret = data[off];
+ data[off] = value;
+ return ret;
+ }
+
+ @Override
+ public double doubleValue(DBID id) {
+ return data[idmap.map(id)];
+ }
+
+ @Override
+ public double putDouble(DBID id, double value) {
+ final int off = idmap.map(id);
+ final double ret = data[off];
+ data[off] = value;
+ return ret;
+ }
+
+ @Override
+ public double put(DBID id, double value) {
+ final int off = idmap.map(id);
+ final double ret = data[off];
+ data[off] = value;
+ return ret;
+ }
+
+ @Override
+ public void destroy() {
+ data = null;
+ idmap = null;
+ }
+
+ @Override
+ public void delete(DBID id) {
+ throw new UnsupportedOperationException("Can't delete from a static array storage.");
+ }
+
+ @Override
+ public String getLongName() {
+ return "raw";
+ }
+
+ @Override
+ public String getShortName() {
+ return "raw";
+ }
+} \ No newline at end of file
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 507fe15b..7be68c97 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -33,8 +33,8 @@ import de.lmu.ifi.dbs.elki.database.ids.DBID;
*
* @author Erich Schubert
*
- * @apiviz.composedOf de.lmu.ifi.dbs.elki.database.datastore.DataStoreIDMap
- * @apiviz.has de.lmu.ifi.dbs.elki.database.datastore.memory.ArrayRecordStore.StorageAccessor oneway - - projectsTo
+ * @apiviz.composedOf DataStoreIDMap
+ * @apiviz.has ArrayRecordStore.StorageAccessor oneway - - projectsTo
*/
public class ArrayRecordStore implements WritableRecordStore {
/**
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 96cadddf..a41a444d 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) 2011
+ Copyright (C) 2012
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
new file mode 100644
index 00000000..ae06dc00
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDDoubleStore.java
@@ -0,0 +1,98 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.TIntDoubleMap;
+import gnu.trove.map.hash.TIntDoubleHashMap;
+import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore;
+import de.lmu.ifi.dbs.elki.database.ids.DBID;
+
+/**
+ * Writable data store for double values.
+ *
+ * @author Erich Schubert
+ */
+public class MapIntegerDBIDDoubleStore implements WritableDoubleDataStore {
+ /**
+ * Data storage
+ */
+ private TIntDoubleMap map;
+
+ /**
+ * Constructor.
+ *
+ * @param size Expected size
+ */
+ public MapIntegerDBIDDoubleStore(int size) {
+ super();
+ map = new TIntDoubleHashMap(size, 0.5f, Integer.MIN_VALUE, Double.NaN);
+ }
+
+ @Override
+ @Deprecated
+ public Double get(DBID id) {
+ return map.get(id.getIntegerID());
+ }
+
+ @Override
+ public double doubleValue(DBID id) {
+ return map.get(id.getIntegerID());
+ }
+
+ @Override
+ public String getLongName() {
+ return "raw";
+ }
+
+ @Override
+ public String getShortName() {
+ return "raw";
+ }
+
+ @Override
+ @Deprecated
+ public Double put(DBID id, Double value) {
+ return map.put(id.getIntegerID(), value);
+ }
+
+ @Override
+ public void destroy() {
+ map.clear();
+ map = null;
+ }
+
+ @Override
+ public void delete(DBID id) {
+ map.remove(id.getIntegerID());
+ }
+
+ @Override
+ public double putDouble(DBID id, double value) {
+ return map.put(id.getIntegerID(), value);
+ }
+
+ @Override
+ public double put(DBID id, double value) {
+ return map.put(id.getIntegerID(), value);
+ }
+}
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
new file mode 100644
index 00000000..8272fb2e
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDRecordStore.java
@@ -0,0 +1,191 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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 de.lmu.ifi.dbs.elki.database.datastore.WritableDataStore;
+import de.lmu.ifi.dbs.elki.database.datastore.WritableRecordStore;
+import de.lmu.ifi.dbs.elki.database.ids.DBID;
+
+/**
+ * A class to answer representation queries using a map and an index within the
+ * record.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has MapIntegerDBIDRecordStore.StorageAccessor oneway - - projectsTo
+ */
+public class MapIntegerDBIDRecordStore implements WritableRecordStore {
+ /**
+ * Record length
+ */
+ private final int rlen;
+
+ /**
+ * Storage Map
+ */
+ private final TIntObjectMap<Object[]> data;
+
+ /**
+ * Constructor with existing data.
+ *
+ * @param rlen Number of columns (record length)
+ * @param data Existing data map
+ */
+ public MapIntegerDBIDRecordStore(int rlen, TIntObjectMap<Object[]> data) {
+ super();
+ this.rlen = rlen;
+ this.data = data;
+ }
+
+ /**
+ * Constructor without existing data.
+ *
+ * @param rlen Number of columns (record length)
+ */
+ public MapIntegerDBIDRecordStore(int rlen) {
+ this(rlen, new TIntObjectHashMap<Object[]>());
+ }
+
+ /**
+ * Constructor without existing data.
+ *
+ * @param size Expected size
+ * @param rlen Number of columns (record length)
+ */
+ public MapIntegerDBIDRecordStore(int size, int rlen) {
+ this(rlen, new TIntObjectHashMap<Object[]>(size));
+ }
+
+ @Override
+ public <T> WritableDataStore<T> getStorage(int col, Class<? super T> datatype) {
+ // TODO: add type checking?
+ return new StorageAccessor<T>(col);
+ }
+
+ /**
+ * Actual getter
+ *
+ * @param id Database ID
+ * @param index column index
+ * @return current value
+ */
+ @SuppressWarnings("unchecked")
+ protected <T> T get(DBID id, int index) {
+ Object[] d = data.get(id.getIntegerID());
+ if(d == null) {
+ return null;
+ }
+ try {
+ return (T) d[index];
+ }
+ catch(ClassCastException e) {
+ return null;
+ }
+ catch(ArrayIndexOutOfBoundsException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Actual setter
+ *
+ * @param id Database ID
+ * @param index column index
+ * @param value new value
+ * @return previous value
+ */
+ @SuppressWarnings("unchecked")
+ protected <T> T set(DBID id, int index, T value) {
+ Object[] d = data.get(id.getIntegerID());
+ if(d == null) {
+ d = new Object[rlen];
+ data.put(id.getIntegerID(), d);
+ }
+ T ret = (T) d[index];
+ d[index] = value;
+ return ret;
+ }
+
+ /**
+ * Access a single record in the given data.
+ *
+ * @author Erich Schubert
+ *
+ * @param <T> Object data type to access
+ */
+ protected class StorageAccessor<T> implements WritableDataStore<T> {
+ /**
+ * Representation index.
+ */
+ private final int index;
+
+ /**
+ * Constructor.
+ *
+ * @param index In-record index
+ */
+ protected StorageAccessor(int index) {
+ super();
+ this.index = index;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public T get(DBID id) {
+ return (T) MapIntegerDBIDRecordStore.this.get(id, index);
+ }
+
+ @Override
+ public T put(DBID id, T value) {
+ return MapIntegerDBIDRecordStore.this.set(id, index, value);
+ }
+
+ @Override
+ public void destroy() {
+ throw new UnsupportedOperationException("Record storage accessors cannot be destroyed.");
+ }
+
+ @Override
+ public void delete(DBID id) {
+ throw new UnsupportedOperationException("Record storage values cannot be deleted.");
+ }
+
+ @Override
+ public String getLongName() {
+ return "raw";
+ }
+
+ @Override
+ public String getShortName() {
+ return "raw";
+ }
+ }
+
+ @Override
+ public boolean remove(DBID id) {
+ return data.remove(id.getIntegerID()) != null;
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..4deb929d
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDStore.java
@@ -0,0 +1,104 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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 de.lmu.ifi.dbs.elki.database.datastore.WritableDataStore;
+import de.lmu.ifi.dbs.elki.database.ids.DBID;
+
+/**
+ * A class to answer representation queries using a map. Basically, it is just a
+ * wrapper around a regular map.
+ *
+ * @author Erich Schubert
+ *
+ * @param <T> Representation object type
+ */
+public class MapIntegerDBIDStore<T> implements WritableDataStore<T> {
+ /**
+ * Storage Map
+ */
+ private TIntObjectMap<T> data;
+
+ /**
+ * Constructor.
+ *
+ * @param data Existing map
+ */
+ public MapIntegerDBIDStore(TIntObjectMap<T> data) {
+ super();
+ this.data = data;
+ }
+
+ /**
+ * Constructor.
+ */
+ public MapIntegerDBIDStore() {
+ super();
+ this.data = new TIntObjectHashMap<T>();
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param size Expected size
+ */
+ public MapIntegerDBIDStore(int size) {
+ this.data = new TIntObjectHashMap<T>(size);
+ }
+
+ @Override
+ public T get(DBID id) {
+ return data.get(id.getIntegerID());
+ }
+
+ @Override
+ public T put(DBID id, T value) {
+ if(value == null) {
+ return data.remove(id.getIntegerID());
+ }
+ return data.put(id.getIntegerID(), value);
+ }
+
+ @Override
+ public void destroy() {
+ data = null;
+ }
+
+ @Override
+ public void delete(DBID id) {
+ data.remove(id.getIntegerID());
+ }
+
+ @Override
+ public String getLongName() {
+ return "raw";
+ }
+
+ @Override
+ public String getShortName() {
+ return "raw";
+ }
+} \ No newline at end of file
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 31efc613..5a98966f 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -36,7 +36,7 @@ import de.lmu.ifi.dbs.elki.database.ids.DBID;
*
* @author Erich Schubert
*
- * @apiviz.has de.lmu.ifi.dbs.elki.database.datastore.memory.MapRecordStore.StorageAccessor oneway - - projectsTo
+ * @apiviz.has MapRecordStore.StorageAccessor oneway - - projectsTo
*/
public class MapRecordStore implements WritableRecordStore {
/**
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 e8a806ec..27cd9f63 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) 2011
+ Copyright (C) 2012
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/MemoryDataStoreFactory.java b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MemoryDataStoreFactory.java
index 2c64ee55..3e3ce017 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,14 +26,17 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory;
import de.lmu.ifi.dbs.elki.database.datastore.RangeIDMap;
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.datastore.WritableRecordStore;
import de.lmu.ifi.dbs.elki.database.ids.DBIDRange;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
/**
- * Simple factory class that will store all data in memory using object arrays or hashmaps.
+ * Simple factory class that will store all data in memory using object arrays
+ * or hashmaps.
*
- * Hints are currently not used by this implementation, since everything is in-memory.
+ * Hints are currently not used by this implementation, since everything is
+ * in-memory.
*
* @author Erich Schubert
*
@@ -46,23 +49,36 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
public class MemoryDataStoreFactory implements DataStoreFactory {
@Override
public <T> WritableDataStore<T> makeStorage(DBIDs ids, int hints, Class<? super T> dataclass) {
- if (ids instanceof DBIDRange) {
+ if(ids instanceof DBIDRange) {
DBIDRange range = (DBIDRange) ids;
Object[] data = new Object[range.size()];
return new ArrayStore<T>(data, new RangeIDMap(range));
- } else {
- return new MapStore<T>();
+ }
+ else {
+ return new MapIntegerDBIDStore<T>(ids.size());
+ }
+ }
+
+ @Override
+ public WritableDoubleDataStore makeDoubleStorage(DBIDs ids, int hints) {
+ if(ids instanceof DBIDRange) {
+ DBIDRange range = (DBIDRange) ids;
+ return new ArrayDoubleStore(range.size(), new RangeIDMap(range));
+ }
+ else {
+ return new MapIntegerDBIDDoubleStore(ids.size());
}
}
@Override
public WritableRecordStore makeRecordStorage(DBIDs ids, int hints, Class<?>... dataclasses) {
- if (ids instanceof DBIDRange) {
+ if(ids instanceof DBIDRange) {
DBIDRange range = (DBIDRange) ids;
Object[][] data = new Object[range.size()][dataclasses.length];
return new ArrayRecordStore(data, new RangeIDMap(range));
- } else {
- return new MapRecordStore(dataclasses.length);
+ }
+ else {
+ return new MapIntegerDBIDRecordStore(ids.size(), dataclasses.length);
}
}
} \ No newline at end of file
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 c0f41618..6200bb46 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) 2011
+Copyright (C) 2012
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 02ef6f6c..dccd8d4e 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
@@ -14,7 +14,7 @@
* <h2>How to use:</h2>
* <pre>{@code
* // Storage for the outlier score of each ID.
- * final WritableDataStore<Double> scores = DataStoreFactory.FACTORY.makeStorage(ids, DataStoreFactory.HINT_STATIC, Double.class);
+ * final WritableDoubleDataStore scores = DataStoreFactory.FACTORY.makeDoubleStorage(ids, DataStoreFactory.HINT_STATIC);
* }</pre>
*
* @apiviz.exclude datastore.memory
@@ -23,7 +23,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2011
+Copyright (C) 2012
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 015d881a..13d6ea58 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,20 +23,43 @@ package de.lmu.ifi.dbs.elki.database.ids;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.List;
-
/**
* Interface for array based DBIDs.
*
* @author Erich Schubert
*/
-public interface ArrayDBIDs extends DBIDs, List<DBID> {
+public interface ArrayDBIDs extends DBIDs {
/**
* Get the i'th entry (starting at 0)
*
* @param i Index
* @return DBID of i'th entry.
*/
- // In List<DBID> which confuses the java compiler
- /* public DBID get(int i); */
+ public DBID get(int i);
+
+ /**
+ * Iterable
+ *
+ * @return Iterator
+ */
+ public DBIDIter iter();
+
+ /**
+ * Size of the DBID "collection".
+ *
+ * @return size
+ */
+ public int size();
+
+ /**
+ * Search for the position of the given key, assuming that the data set is
+ * sorted.
+ *
+ * For keys not found, <code>-(1+insertion position)</code> is returned, as
+ * for Java {@link java.util.Collections#binarySearch}
+ *
+ * @param key Key to search for
+ * @return Offset of key
+ */
+ public int binarySearch(DBID key);
}
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 1320ba4e..e9a6c8e0 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/ArrayModifiableDBIDs.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/ArrayModifiableDBIDs.java
@@ -1,10 +1,12 @@
package de.lmu.ifi.dbs.elki.database.ids;
+import java.util.Comparator;
+
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,13 +25,38 @@ package de.lmu.ifi.dbs.elki.database.ids;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.List;
-
/**
* Array-oriented implementation of a modifiable DBID collection.
*
* @author Erich Schubert
*/
-public interface ArrayModifiableDBIDs extends ModifiableDBIDs, ArrayDBIDs, List<DBID> {
- // Empty interface
+public interface ArrayModifiableDBIDs extends ModifiableDBIDs, ArrayDBIDs {
+ /**
+ * Sort the DBID set.
+ */
+ void sort();
+
+ /**
+ * Sort the DBID set.
+ *
+ * @param comparator Comparator to use
+ */
+ void sort(Comparator<? super DBID> comparator);
+
+ /**
+ * Remove the i'th entry (starting at 0)
+ *
+ * @param i Index
+ * @return value removed
+ */
+ public DBID remove(int i);
+
+ /**
+ * Replace the i'th entry (starting at 0)
+ *
+ * @param i Index
+ * @param newval New value
+ * @return previous value
+ */
+ public DBID set(int i, DBID newval);
} \ No newline at end of file
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 2cf0f030..a14eac0c 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) 2011
+ Copyright (C) 2012
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 41e67c4e..1391b75b 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) 2011
+ Copyright (C) 2012
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.database.ids;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
-
/**
* Database ID object.
*
@@ -39,7 +37,7 @@ package de.lmu.ifi.dbs.elki.database.ids;
*
* @apiviz.landmark
*/
-public interface DBID extends Comparable<DBID>, ArrayStaticDBIDs {
+public interface DBID extends Comparable<DBID>, ArrayDBIDs {
/**
* Return the integer value of the object ID, if possible.
*
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 cc5be115..f35f390b 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -111,13 +111,6 @@ public interface DBIDFactory {
public HashSetModifiableDBIDs newHashSet();
/**
- * Make a new (modifiable) tree set of DBIDs.
- *
- * @return New tree set
- */
- public TreeSetModifiableDBIDs newTreeSet();
-
- /**
* Make a new (modifiable) array of DBIDs.
*
* @param size Size hint
@@ -134,14 +127,6 @@ public interface DBIDFactory {
public HashSetModifiableDBIDs newHashSet(int size);
/**
- * Make a new (modifiable) tree set of DBIDs.
- *
- * @param size Size hint
- * @return New tree set
- */
- public TreeSetModifiableDBIDs newTreeSet(int size);
-
- /**
* Make a new (modifiable) array of DBIDs.
*
* @param existing existing DBIDs to use
@@ -158,14 +143,6 @@ public interface DBIDFactory {
public HashSetModifiableDBIDs newHashSet(DBIDs existing);
/**
- * Make a new (modifiable) tree set of DBIDs.
- *
- * @param existing existing DBIDs to use
- * @return New tree set
- */
- public TreeSetModifiableDBIDs newTreeSet(DBIDs existing);
-
- /**
* 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
new file mode 100644
index 00000000..a41284f4
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDIter.java
@@ -0,0 +1,79 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+/**
+ * Iterator for DBIDs.
+ *
+ * Important note: this iterator has a <em>significantly</em> different syntax
+ * and semantics than the Java iterators. It is much more aligned with C than
+ * with Java, but at the same time, the syntax is much more compatible with for
+ * loops.
+ *
+ * Usage example: <blockquote><code>{@code
+ * for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
+ * iter.getDBID();
+ * }
+ * }</code></blockquote>
+ *
+ * We list some fundamental differences.
+ * <ul>
+ * <li>{@link DBIDIter#valid() iter.valid()} refers to the current element,
+ * {@code Iterator.next()} to the next.</li>
+ * <li>{@link DBIDIter#advance() iter.advance()} does not return an element. Use
+ * {@code get...} to access it.</li>
+ * <li>{@code DBIDIter.get...} do not advance the iterator.</li>
+ * </ul>
+ *
+ * @author Erich Schubert
+ */
+public interface DBIDIter {
+ /**
+ * Returns true if the iterator currently points to a valid object.
+ *
+ * @return a <code>boolean</code> value
+ */
+ public boolean valid();
+
+ /**
+ * Moves the iterator forward to the next entry.
+ *
+ * @throws java.util.NoSuchElementException if the iterator is already
+ * exhausted
+ */
+ public void advance();
+
+ /**
+ * Return the integer value of the object ID, if possible.
+ *
+ * @return integer id
+ */
+ public int getIntegerID();
+
+ /**
+ * Get the current DBID.
+ *
+ * @return current DBID
+ */
+ public DBID getDBID();
+} \ No newline at end of file
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 fdaff560..8f03e279 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) 2011
+ Copyright (C) 2012
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 4143c570..48a1f0ba 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDRange.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDRange.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) 2011
+ Copyright (C) 2012
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 3a62c222..cd2bd4e0 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -133,15 +133,6 @@ public final class DBIDUtil {
}
/**
- * Make a new (modifiable) tree set of DBIDs.
- *
- * @return New tree set
- */
- public static TreeSetModifiableDBIDs newTreeSet() {
- return DBIDFactory.FACTORY.newTreeSet();
- }
-
- /**
* Make a new (modifiable) array of DBIDs.
*
* @param size Size hint
@@ -162,16 +153,6 @@ public final class DBIDUtil {
}
/**
- * Make a new (modifiable) tree set of DBIDs.
- *
- * @param size Size hint
- * @return New tree set
- */
- public static TreeSetModifiableDBIDs newTreeSet(int size) {
- return DBIDFactory.FACTORY.newTreeSet(size);
- }
-
- /**
* Make a new (modifiable) array of DBIDs.
*
* @param existing Existing DBIDs
@@ -192,16 +173,6 @@ public final class DBIDUtil {
}
/**
- * Make a new (modifiable) tree set of DBIDs.
- *
- * @param existing Existing DBIDs
- * @return New tree set
- */
- public static TreeSetModifiableDBIDs newTreeSet(DBIDs existing) {
- return DBIDFactory.FACTORY.newTreeSet(existing);
- }
-
- /**
* Compute the set intersection of two sets.
*
* @param first First set
@@ -285,11 +256,8 @@ public final class DBIDUtil {
* @return Array DBIDs.
*/
public static SetDBIDs ensureSet(DBIDs ids) {
- if(ids instanceof HashSetDBIDs) {
- return (HashSetDBIDs) ids;
- }
- else if(ids instanceof TreeSetDBIDs) {
- return (TreeSetDBIDs) ids;
+ if(ids instanceof SetDBIDs) {
+ return (SetDBIDs) ids;
}
else {
return newHashSet(ids);
@@ -313,9 +281,6 @@ public final class DBIDUtil {
if(ids instanceof HashSetDBIDs) {
return newHashSet(ids);
}
- if(ids instanceof TreeSetDBIDs) {
- return newTreeSet(ids);
- }
return newArray(ids);
}
}
@@ -340,11 +305,29 @@ public final class DBIDUtil {
* @param seed Random generator seed
* @return new DBIDs
*/
- public static ModifiableDBIDs randomSample(DBIDs source, int k, long seed) {
+ public static ModifiableDBIDs randomSample(DBIDs source, int k, int seed) {
+ return randomSample(source, k, (long) seed);
+ }
+
+ /**
+ * Produce a random sample of the given DBIDs
+ *
+ * @param source Original DBIDs
+ * @param k k Parameter
+ * @param seed Random generator seed
+ * @return new DBIDs
+ */
+ public static ModifiableDBIDs randomSample(DBIDs source, int k, Long seed) {
if(k <= 0 || k > source.size()) {
throw new IllegalArgumentException("Illegal value for size of random sample: " + k);
}
- Random random = new Random(seed);
+ final Random random;
+ if(seed != null) {
+ random = new Random(seed);
+ }
+ else {
+ random = new Random();
+ }
// TODO: better balancing for different sizes
// Two methods: constructive vs. destructive
if(k < source.size() / 2) {
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 c1a52d6a..ef83ba69 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) 2011
+ Copyright (C) 2012
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.database.ids;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.Collection;
import java.util.Iterator;
/**
@@ -36,13 +35,6 @@ import java.util.Iterator;
*/
public interface DBIDs extends Iterable<DBID> {
/**
- * Retrieve collection access to the IDs
- *
- * @return a collection of IDs
- */
- public Collection<DBID> asCollection();
-
- /**
* Retrieve Iterator access to the IDs.
*
* @return an iterator for the IDs
@@ -51,20 +43,26 @@ public interface DBIDs extends Iterable<DBID> {
public Iterator<DBID> iterator();
/**
+ * Get a DBIDIterator (a more efficient API).
+ *
+ * @return iterator
+ */
+ public DBIDIter iter();
+
+ /**
* Retrieve the collection / data size.
*
* @return collection size
*/
public int size();
-
+
/**
* Test whether an ID is contained.
- * Signature compatible with {@link Collection}.
*
* @param o object to test
* @return true when contained
*/
- public boolean contains(Object o);
+ public boolean contains(DBID o);
/**
* Test for an empty DBID collection.
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 bee2faab..5a7d6991 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,10 +23,8 @@ package de.lmu.ifi.dbs.elki.database.ids;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.AbstractList;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.Iterator;
+import java.util.NoSuchElementException;
import de.lmu.ifi.dbs.elki.utilities.iterator.EmptyIterator;
@@ -35,14 +33,21 @@ import de.lmu.ifi.dbs.elki.utilities.iterator.EmptyIterator;
*
* @author Erich Schubert
*/
-class EmptyDBIDs extends AbstractList<DBID> implements ArrayStaticDBIDs {
- @Override
- public Collection<DBID> asCollection() {
- return new ArrayList<DBID>(0);
+public class EmptyDBIDs implements ArrayStaticDBIDs, SetDBIDs {
+ /**
+ * Empty DBID iterator
+ */
+ public static final EmptyDBIDIterator EMPTY_ITERATOR = new EmptyDBIDIterator();
+
+ /**
+ * Constructor.
+ */
+ protected EmptyDBIDs() {
+ super();
}
@Override
- public boolean contains(Object o) {
+ public boolean contains(DBID o) {
return false;
}
@@ -65,4 +70,41 @@ class EmptyDBIDs extends AbstractList<DBID> implements ArrayStaticDBIDs {
public DBID get(int i) {
throw new ArrayIndexOutOfBoundsException();
}
+
+ @Override
+ public DBIDIter iter() {
+ return EMPTY_ITERATOR;
+ }
+
+ @Override
+ public int binarySearch(DBID key) {
+ return -1; // Not found
+ }
+
+ /**
+ * Iterator for empty DBIDs
+ *
+ * @author Erich Schubert
+ */
+ protected static class EmptyDBIDIterator implements DBIDIter {
+ @Override
+ public boolean valid() {
+ return false;
+ }
+
+ @Override
+ public void advance() {
+ assert (false) : "Misplaced call to advance()";
+ }
+
+ @Override
+ public int getIntegerID() {
+ throw new NoSuchElementException();
+ }
+
+ @Override
+ public DBID getDBID() {
+ throw new NoSuchElementException();
+ }
+ }
} \ No newline at end of file
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 f449180f..5ff0bc97 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) 2011
+ Copyright (C) 2012
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 03805590..f7c8b551 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,14 +23,12 @@ package de.lmu.ifi.dbs.elki.database.ids;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.Set;
-
/**
* Set-oriented implementation of a modifiable DBID collection.
*
* @author Erich Schubert
*/
-public interface HashSetModifiableDBIDs extends Set<DBID>, HashSetDBIDs, ModifiableDBIDs {
+public interface HashSetModifiableDBIDs extends HashSetDBIDs, ModifiableDBIDs {
/**
* Retain all elements that also are in the second set.
*
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 57d8c578..97646902 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,14 +23,16 @@ package de.lmu.ifi.dbs.elki.database.ids;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.Collection;
-
/**
* Interface for a generic modifiable DBID collection.
*
+ * Note: we had this use the Java Collections API for a long time, however this
+ * prevented certain optimizations. So it now only mimics the Collections API
+ * <em>deliberately</em>.
+ *
* @author Erich Schubert
*/
-public interface ModifiableDBIDs extends DBIDs, Collection<DBID> {
+public interface ModifiableDBIDs extends DBIDs {
/**
* Add DBIDs to collection.
*
@@ -38,7 +40,7 @@ public interface ModifiableDBIDs extends DBIDs, Collection<DBID> {
* @return {@code true} when modified
*/
boolean addDBIDs(DBIDs ids);
-
+
/**
* Remove DBIDs from collection.
*
@@ -46,4 +48,23 @@ public interface ModifiableDBIDs extends DBIDs, Collection<DBID> {
* @return {@code true} when modified
*/
boolean removeDBIDs(DBIDs ids);
-}
+
+ /**
+ * Add a single DBID to the collection.
+ *
+ * @param id ID to add
+ */
+ boolean add(DBID id);
+
+ /**
+ * Remove a single DBID from the collection.
+ *
+ * @param id ID to remove
+ */
+ boolean remove(DBID id);
+
+ /**
+ * Clear this collection.
+ */
+ void clear();
+} \ No newline at end of file
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 6509a57f..7fd28326 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) 2011
+ Copyright (C) 2012
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.database.ids;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.Set;
/**
* Interface for DBIDs that support fast "set" operations, in particular
@@ -31,6 +30,6 @@ import java.util.Set;
*
* @author Erich Schubert
*/
-public interface SetDBIDs extends DBIDs, Set<DBID> {
+public interface SetDBIDs extends DBIDs {
// empty marker interface
} \ No newline at end of file
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 08676215..ce616da3 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) 2011
+ Copyright (C) 2012
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/DBIDIterAdapter.java b/src/de/lmu/ifi/dbs/elki/database/ids/generic/DBIDIterAdapter.java
new file mode 100644
index 00000000..c517ea9f
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/generic/DBIDIterAdapter.java
@@ -0,0 +1,82 @@
+package de.lmu.ifi.dbs.elki.database.ids.generic;
+
+import java.util.Iterator;
+
+import de.lmu.ifi.dbs.elki.database.ids.DBID;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
+
+/*
+ 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/>.
+ */
+
+/**
+ * Iterator for classic collections.
+ *
+ * @author Erich Schubert
+ */
+public class DBIDIterAdapter implements DBIDIter {
+ /**
+ * Current DBID
+ */
+ DBID cur = null;
+
+ /**
+ * The real iterator
+ */
+ Iterator<DBID> iter;
+
+ /**
+ * Constructor.
+ *
+ * @param iter Iterator
+ */
+ public DBIDIterAdapter(Iterator<DBID> iter) {
+ super();
+ this.iter = iter;
+ advance();
+ }
+
+ @Override
+ public boolean valid() {
+ return cur != null;
+ }
+
+ @Override
+ public void advance() {
+ if(iter.hasNext()) {
+ cur = iter.next();
+ }
+ else {
+ cur = null;
+ }
+ }
+
+ @Override
+ public int getIntegerID() {
+ return cur.getIntegerID();
+ }
+
+ @Override
+ public DBID getDBID() {
+ return cur;
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/generic/GenericArrayModifiableDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/generic/GenericArrayModifiableDBIDs.java
index 0316f82d..f271180d 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/generic/GenericArrayModifiableDBIDs.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/generic/GenericArrayModifiableDBIDs.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,26 +24,27 @@ package de.lmu.ifi.dbs.elki.database.ids.generic;
*/
import java.util.ArrayList;
-import java.util.Collection;
+import java.util.Collections;
+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.DBIDs;
-
/**
* Array-oriented implementation of a modifiable DBID collection.
*
- * This should only be instantiated by a {@link de.lmu.ifi.dbs.elki.database.ids.DBIDFactory}!
+ * This should only be instantiated by a
+ * {@link de.lmu.ifi.dbs.elki.database.ids.DBIDFactory}!
*
* Use {@link de.lmu.ifi.dbs.elki.database.ids.DBIDUtil#newArray}!
*
* @author Erich Schubert
*
- * @apiviz.uses de.lmu.ifi.dbs.elki.database.ids.DBID
+ * @apiviz.uses DBID
*/
-// TODO: implement this optimized for integers?
-public class GenericArrayModifiableDBIDs extends ArrayList<DBID> implements ArrayModifiableDBIDs {
+public class GenericArrayModifiableDBIDs extends ArrayList<DBID> implements ArrayModifiableDBIDs {
/**
* Serial version
*/
@@ -71,21 +72,56 @@ public class GenericArrayModifiableDBIDs extends ArrayList<DBID> implements Arra
* @param c Existing DBIDs.
*/
public GenericArrayModifiableDBIDs(DBIDs c) {
- super(c.asCollection());
+ super(c.size());
+ addDBIDs(c);
}
@Override
- public Collection<DBID> asCollection() {
- return this;
+ public boolean addDBIDs(DBIDs ids) {
+ super.ensureCapacity(size() + ids.size());
+ boolean changed = false;
+ for(DBID id : ids) {
+ changed |= add(id);
+ }
+ return changed;
}
@Override
- public boolean addDBIDs(DBIDs ids) {
- return super.addAll(ids.asCollection());
+ public boolean removeDBIDs(DBIDs ids) {
+ boolean changed = false;
+ for(DBID id : ids) {
+ changed |= super.remove(id);
+ }
+ return changed;
}
@Override
- public boolean removeDBIDs(DBIDs ids) {
- return super.removeAll(ids.asCollection());
+ public boolean remove(DBID id) {
+ return super.remove(id);
+ }
+
+ @Override
+ public void sort() {
+ Collections.sort(this);
+ }
+
+ @Override
+ public void sort(Comparator<? super DBID> comparator) {
+ Collections.sort(this, comparator);
+ }
+
+ @Override
+ public DBIDIter iter() {
+ return new DBIDIterAdapter(iterator());
+ }
+
+ @Override
+ public int binarySearch(DBID key) {
+ return Collections.binarySearch(this, key);
+ }
+
+ @Override
+ public boolean contains(DBID o) {
+ return super.contains(o);
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/generic/GenericHashSetModifiableDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/generic/GenericHashSetModifiableDBIDs.java
index 6d251cd8..31a8602c 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/generic/GenericHashSetModifiableDBIDs.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/generic/GenericHashSetModifiableDBIDs.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,25 +23,26 @@ package de.lmu.ifi.dbs.elki.database.ids.generic;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.Collection;
import java.util.HashSet;
+import java.util.Iterator;
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.ids.HashSetModifiableDBIDs;
/**
* Set-oriented implementation of a modifiable DBID collection.
*
- * This should only be instantiated by a {@link de.lmu.ifi.dbs.elki.database.ids.DBIDFactory}!
+ * This should only be instantiated by a
+ * {@link de.lmu.ifi.dbs.elki.database.ids.DBIDFactory}!
*
* Use {@link de.lmu.ifi.dbs.elki.database.ids.DBIDUtil#newHashSet}!
*
* @author Erich Schubert
*
- * @apiviz.uses de.lmu.ifi.dbs.elki.database.ids.DBID
+ * @apiviz.uses DBID
*/
-// TODO: implement this optimized for integers?
public class GenericHashSetModifiableDBIDs extends HashSet<DBID> implements HashSetModifiableDBIDs {
/**
* Serial version
@@ -70,26 +71,55 @@ public class GenericHashSetModifiableDBIDs extends HashSet<DBID> implements Hash
* @param c Existing DBIDs.
*/
public GenericHashSetModifiableDBIDs(DBIDs c) {
- super(c.asCollection());
+ super(c.size());
+ for(DBID id : c) {
+ add(id);
+ }
}
@Override
- public Collection<DBID> asCollection() {
- return this;
+ public boolean addDBIDs(DBIDs ids) {
+ boolean changed = false;
+ for(DBID id : ids) {
+ changed |= add(id);
+ }
+ return changed;
}
@Override
- public boolean addDBIDs(DBIDs ids) {
- return super.addAll(ids.asCollection());
+ public boolean removeDBIDs(DBIDs ids) {
+ boolean changed = false;
+ for(DBID id : ids) {
+ changed |= super.remove(id);
+ }
+ return changed;
}
@Override
- public boolean removeDBIDs(DBIDs ids) {
- return super.removeAll(ids.asCollection());
+ public boolean remove(DBID id) {
+ return super.remove(id);
}
@Override
public boolean retainAll(DBIDs ids) {
- return super.retainAll(ids.asCollection());
+ boolean modified = false;
+ Iterator<DBID> it = iterator();
+ while(it.hasNext()) {
+ if(!ids.contains(it.next())) {
+ it.remove();
+ modified = true;
+ }
+ }
+ return modified;
+ }
+
+ @Override
+ public DBIDIter iter() {
+ return new DBIDIterAdapter(iterator());
+ }
+
+ @Override
+ public boolean contains(DBID o) {
+ return super.contains(o);
}
-}
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/generic/GenericTreeSetModifiableDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/generic/GenericTreeSetModifiableDBIDs.java
deleted file mode 100644
index afd56730..00000000
--- a/src/de/lmu/ifi/dbs/elki/database/ids/generic/GenericTreeSetModifiableDBIDs.java
+++ /dev/null
@@ -1,90 +0,0 @@
-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) 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 java.util.Collection;
-import java.util.TreeSet;
-
-import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
-import de.lmu.ifi.dbs.elki.database.ids.TreeSetModifiableDBIDs;
-
-/**
- * Set-oriented implementation of a modifiable DBID collection.
- *
- * This should only be instantiated by a {@link de.lmu.ifi.dbs.elki.database.ids.DBIDFactory}!
- *
- * Use {@link de.lmu.ifi.dbs.elki.database.ids.DBIDUtil#newTreeSet}!
- *
- * @author Erich Schubert
- *
- * @apiviz.uses de.lmu.ifi.dbs.elki.database.ids.DBID
- */
-// TODO: implement this optimized for integers?
-public class GenericTreeSetModifiableDBIDs extends TreeSet<DBID> implements TreeSetModifiableDBIDs {
- /**
- * Serial version
- */
- private static final long serialVersionUID = 1L;
-
- /**
- * Constructor with size hint.
- *
- * @param initialCapacity Size hint
- */
- public GenericTreeSetModifiableDBIDs(int initialCapacity) {
- super();
- }
-
- /**
- * Constructor without extra hints
- */
- public GenericTreeSetModifiableDBIDs() {
- super();
- }
-
- /**
- * Constructor from existing DBIDs.
- *
- * @param c Existing DBIDs.
- */
- public GenericTreeSetModifiableDBIDs(DBIDs c) {
- super(c.asCollection());
- }
-
- @Override
- public Collection<DBID> asCollection() {
- return this;
- }
-
- @Override
- public boolean addDBIDs(DBIDs ids) {
- return super.addAll(ids.asCollection());
- }
-
- @Override
- public boolean removeDBIDs(DBIDs ids) {
- return super.removeAll(ids.asCollection());
- }
-}
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 77d5c063..67c84290 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) 2011
+ Copyright (C) 2012
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.database.ids.generic;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.AbstractCollection;
import java.util.BitSet;
-import java.util.Collection;
import java.util.Iterator;
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.DBIDs;
/**
@@ -39,7 +38,7 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
*
* @apiviz.uses de.lmu.ifi.dbs.elki.database.ids.DBIDs
*/
-public class MaskedDBIDs extends AbstractCollection<DBID> implements DBIDs, Collection<DBID> {
+public class MaskedDBIDs implements DBIDs {
/**
* Data storage
*/
@@ -80,8 +79,13 @@ public class MaskedDBIDs extends AbstractCollection<DBID> implements DBIDs, Coll
}
@Override
- public Collection<DBID> asCollection() {
- return this;
+ public DBIDIter iter() {
+ if(inverse) {
+ return new InvDBIDItr();
+ }
+ else {
+ return new DBIDItr();
+ }
}
@Override
@@ -94,6 +98,22 @@ public class MaskedDBIDs extends AbstractCollection<DBID> implements DBIDs, Coll
}
}
+ @Override
+ public boolean contains(DBID o) {
+ // TODO: optimize.
+ for(DBID id : this) {
+ if(id.equals(o)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return size() == 0;
+ }
+
/**
* Iterator over set bits
*
@@ -133,6 +153,47 @@ public class MaskedDBIDs extends AbstractCollection<DBID> implements DBIDs, Coll
}
/**
+ * Iterator over set bits
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ protected class DBIDItr implements DBIDIter {
+ /**
+ * Next position.
+ */
+ private int pos;
+
+ /**
+ * Constructor
+ */
+ protected DBIDItr() {
+ this.pos = bits.nextSetBit(0);
+ }
+
+ @Override
+ public boolean valid() {
+ return pos >= 0;
+ }
+
+ @Override
+ public void advance() {
+ pos = bits.nextSetBit(pos + 1);
+ }
+
+ @Override
+ public int getIntegerID() {
+ return data.get(pos).getIntegerID();
+ }
+
+ @Override
+ public DBID getDBID() {
+ return data.get(pos);
+ }
+ }
+
+ /**
* Iterator over unset elements.
*
* @author Erich Schubert
@@ -170,18 +231,44 @@ public class MaskedDBIDs extends AbstractCollection<DBID> implements DBIDs, Coll
}
}
- @Override
- public boolean add(DBID e) {
- throw new UnsupportedOperationException();
- }
+ /**
+ * Iterator over set bits
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ protected class InvDBIDItr implements DBIDIter {
+ /**
+ * Next position.
+ */
+ private int pos;
- @Override
- public boolean remove(Object o) {
- throw new UnsupportedOperationException();
- }
+ /**
+ * Constructor
+ */
+ protected InvDBIDItr() {
+ this.pos = bits.nextClearBit(0);
+ }
- @Override
- public void clear() {
- throw new UnsupportedOperationException();
+ @Override
+ public boolean valid() {
+ return pos >= 0;
+ }
+
+ @Override
+ public void advance() {
+ pos = bits.nextClearBit(pos + 1);
+ }
+
+ @Override
+ public int getIntegerID() {
+ return data.get(pos).getIntegerID();
+ }
+
+ @Override
+ public DBID getDBID() {
+ return data.get(pos);
+ }
}
}
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 ce28ac38..97743867 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) 2011
+ Copyright (C) 2012
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.database.ids.generic;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.Collection;
import java.util.Iterator;
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.utilities.exceptions.AbortException;
/**
* Merge the IDs of multiple layers into one.
@@ -38,12 +38,12 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
* @apiviz.uses de.lmu.ifi.dbs.elki.database.ids.DBIDs
*/
// TODO: include ID mapping?
-public class MergedDBIDs implements DBIDs, Collection<DBID> {
+public class MergedDBIDs implements DBIDs {
/**
* Childs to merge
*/
DBIDs childs[];
-
+
/**
* Constructor.
*
@@ -55,14 +55,13 @@ public class MergedDBIDs implements DBIDs, Collection<DBID> {
}
@Override
- public Collection<DBID> asCollection() {
- return this;
+ public Iterator<DBID> iterator() {
+ throw new AbortException("Merged iterators not completely implemented yet!");
}
@Override
- public Iterator<DBID> iterator() {
- // TODO Auto-generated method stub
- return null;
+ public DBIDIter iter() {
+ throw new AbortException("Merged iterators not completely implemented yet!");
}
@Override
@@ -80,32 +79,7 @@ public class MergedDBIDs implements DBIDs, Collection<DBID> {
}
@Override
- public Object[] toArray() {
- return toArray(new Object[size()]);
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public <T> T[] toArray(T[] a) {
- final int si = size();
- T[] r = a;
- if(a.length < si) {
- r = (T[]) java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), si);
- }
- int i = 0;
- for (Iterator<DBID> iter = iterator(); iter.hasNext(); i++) {
- DBID id = iter.next();
- r[i] = (T) id;
- }
- // zero-terminate array
- if(r.length > si) {
- r[si] = null;
- }
- return r;
- }
-
- @Override
- public boolean contains(Object o) {
+ public boolean contains(DBID o) {
for(DBIDs child : childs) {
if(child.contains(o)) {
return true;
@@ -113,45 +87,4 @@ public class MergedDBIDs implements DBIDs, Collection<DBID> {
}
return false;
}
-
- @Override
- public boolean containsAll(Collection<?> c) {
- Iterator<?> e = c.iterator();
- while(e.hasNext()) {
- if(!contains(e.next())) {
- return false;
- }
- }
- return true;
- }
-
- @Override
- public void clear() {
- throw new UnsupportedOperationException(MergedDBIDs.class.getName() + " are unmodifiable!");
- }
-
- @Override
- public boolean add(DBID e) {
- throw new UnsupportedOperationException(MergedDBIDs.class.getName() + " are unmodifiable!");
- }
-
- @Override
- public boolean addAll(Collection<? extends DBID> c) {
- throw new UnsupportedOperationException(MergedDBIDs.class.getName() + " are unmodifiable!");
- }
-
- @Override
- public boolean remove(Object o) {
- throw new UnsupportedOperationException(MergedDBIDs.class.getName() + " are unmodifiable!");
- }
-
- @Override
- public boolean removeAll(Collection<?> c) {
- throw new UnsupportedOperationException(MergedDBIDs.class.getName() + " are unmodifiable!");
- }
-
- @Override
- public boolean retainAll(Collection<?> c) {
- throw new UnsupportedOperationException(MergedDBIDs.class.getName() + " are unmodifiable!");
- }
-}
+} \ No newline at end of file
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 908dabd3..bd68e2fb 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,11 +23,10 @@ package de.lmu.ifi.dbs.elki.database.ids.generic;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.Collection;
-import java.util.Collections;
import java.util.Iterator;
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.ids.StaticDBIDs;
import de.lmu.ifi.dbs.elki.utilities.iterator.UnmodifiableIterator;
@@ -56,12 +55,7 @@ public class UnmodifiableDBIDs implements StaticDBIDs {
}
@Override
- public Collection<DBID> asCollection() {
- return Collections.unmodifiableCollection(inner.asCollection());
- }
-
- @Override
- public boolean contains(Object o) {
+ public boolean contains(DBID o) {
return inner.contains(o);
}
@@ -74,6 +68,11 @@ public class UnmodifiableDBIDs implements StaticDBIDs {
public Iterator<DBID> iterator() {
return new UnmodifiableIterator<DBID>(inner.iterator());
}
+
+ @Override
+ public DBIDIter iter() {
+ return inner.iter();
+ }
@Override
public int size() {
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 cdf4c487..890b9c0a 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) 2011
+Copyright (C) 2012
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/IntegerArrayStaticDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerArrayStaticDBIDs.java
index b617b4c4..ef4aee94 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,22 +24,22 @@ package de.lmu.ifi.dbs.elki.database.ids.integer;
*/
import java.util.AbstractList;
-import java.util.Collection;
+import java.util.Arrays;
import java.util.Iterator;
-import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.ArrayStaticDBIDs;
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;
/**
* Static (no modifications allowed) set of Database Object IDs.
*
* @author Erich Schubert
*
- * @apiviz.composedOf IntegerDBID
+ * @apiviz.has IntegerDBID
*/
-public class IntegerArrayStaticDBIDs extends AbstractList<DBID> implements ArrayDBIDs {
+public class IntegerArrayStaticDBIDs extends AbstractList<DBID> implements ArrayStaticDBIDs {
/**
* The actual storage.
*/
@@ -59,7 +59,12 @@ public class IntegerArrayStaticDBIDs extends AbstractList<DBID> implements Array
public Iterator<DBID> iterator() {
return new Itr();
}
-
+
+ @Override
+ public DBIDIter iter() {
+ return new DBIDItr();
+ }
+
/**
* Iterator class.
*
@@ -77,7 +82,7 @@ public class IntegerArrayStaticDBIDs extends AbstractList<DBID> implements Array
@Override
public DBID next() {
- DBID ret = DBIDFactory.FACTORY.importInteger(ids[off]);
+ DBID ret = new IntegerDBID(ids[off]);
off++;
return ret;
}
@@ -88,22 +93,49 @@ public class IntegerArrayStaticDBIDs extends AbstractList<DBID> implements Array
}
}
+ /**
+ * DBID iterator in ELKI/C style.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ protected class DBIDItr implements DBIDIter {
+ int pos = 0;
+
+ @Override
+ public boolean valid() {
+ return pos < ids.length;
+ }
+
+ @Override
+ public void advance() {
+ pos++;
+ }
+
+ @Override
+ public int getIntegerID() {
+ return ids[pos];
+ }
+
+ @Override
+ public DBID getDBID() {
+ return new IntegerDBID(ids[pos]);
+ }
+
+ }
+
@Override
public int size() {
return ids.length;
}
-
- /*
- * "Contains" operations
- */
+
@Override
- public boolean contains(Object o) {
- if(o instanceof DBID) {
- int oid = ((DBID) o).getIntegerID();
- for(int i = 0; i < ids.length; i++) {
- if(ids[i] == oid) {
- return true;
- }
+ public boolean contains(DBID o) {
+ final int oid = o.getIntegerID();
+ for(int i = 0; i < ids.length; i++) {
+ if(ids[i] == oid) {
+ return true;
}
}
return false;
@@ -132,7 +164,7 @@ public class IntegerArrayStaticDBIDs extends AbstractList<DBID> implements Array
}
@Override
- public Collection<DBID> asCollection() {
- return this;
+ public int binarySearch(DBID key) {
+ return Arrays.binarySearch(ids, key.getIntegerID());
}
} \ 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 2842ca75..f9e83294 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) 2011
+ Copyright (C) 2012
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.database.ids.integer;
*/
import java.nio.ByteBuffer;
-import java.util.AbstractList;
-import java.util.Collection;
import java.util.Iterator;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.persistent.ByteArrayUtil;
import de.lmu.ifi.dbs.elki.persistent.ByteBufferSerializer;
import de.lmu.ifi.dbs.elki.persistent.FixedSizeByteBufferSerializer;
@@ -50,7 +49,7 @@ import de.lmu.ifi.dbs.elki.persistent.FixedSizeByteBufferSerializer;
* @apiviz.composedOf DynamicSerializer
* @apiviz.composedOf StaticSerializer
*/
-class IntegerDBID extends AbstractList<DBID> implements DBID {
+class IntegerDBID implements DBID {
/**
* The actual object ID.
*/
@@ -113,13 +112,16 @@ class IntegerDBID extends AbstractList<DBID> implements DBID {
}
@Override
- public Collection<DBID> asCollection() {
- return this;
+ public DBIDIter iter() {
+ return new DBIDItr();
}
@Override
- public boolean contains(Object o) {
- return this.equals(o);
+ public DBID get(int i) {
+ if(i != 0) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ return this;
}
@Override
@@ -128,10 +130,20 @@ class IntegerDBID extends AbstractList<DBID> implements DBID {
}
@Override
+ public boolean contains(DBID o) {
+ return o.getIntegerID() == id;
+ }
+
+ @Override
public int size() {
return 1;
}
+ @Override
+ public int binarySearch(DBID key) {
+ return equals(key) ? 0 : -1;
+ }
+
/**
* Pseudo iterator for DBIDs interface.
*
@@ -163,21 +175,45 @@ class IntegerDBID extends AbstractList<DBID> implements DBID {
}
}
- @Override
- public boolean isEmpty() {
- return false;
- }
+ /**
+ * Pseudo iterator for DBIDs interface.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ protected class DBIDItr implements DBIDIter {
+ /**
+ * Whether we've already returned our object.
+ */
+ boolean first = true;
- @Override
- public DBID get(int i) {
- if(i == 0) {
- return this;
+ @Override
+ public void advance() {
+ first = false;
}
- else {
- throw new ArrayIndexOutOfBoundsException();
+
+ @Override
+ public int getIntegerID() {
+ return id;
+ }
+
+ @Override
+ public DBID getDBID() {
+ return IntegerDBID.this;
+ }
+
+ @Override
+ public boolean valid() {
+ return first;
}
}
+ @Override
+ public boolean isEmpty() {
+ return false;
+ }
+
/**
* Dynamic sized serializer, using varint.
*
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 742bab57..e716f5b5 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) 2011
+ Copyright (C) 2012
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.DBIDPair;
*
* @author Erich Schubert
*
- * @apiviz.composedOf IntegerDBID
+ * @apiviz.has IntegerDBID
*/
public class IntegerDBIDPair implements DBIDPair {
/**
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 1142f1a6..debe39a4 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,32 +24,31 @@ package de.lmu.ifi.dbs.elki.database.ids.integer;
*/
import java.util.AbstractList;
-import java.util.Collection;
import java.util.Iterator;
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.DBIDRange;
-
/**
* Representing a DBID range allocation
*
* @author Erich Schubert
*
- * @apiviz.composedOf IntegerDBID
+ * @apiviz.has IntegerDBID
*/
class IntegerDBIDRange extends AbstractList<DBID> implements DBIDRange {
/**
* Start value
*/
protected final int start;
-
+
/**
* Length value
*/
protected final int len;
-
+
/**
* Constructor.
*
@@ -72,6 +71,11 @@ class IntegerDBIDRange extends AbstractList<DBID> implements DBIDRange {
return new Itr();
}
+ @Override
+ public DBIDIter iter() {
+ return new DBIDItr();
+ }
+
/**
* Iterator class.
*
@@ -89,7 +93,7 @@ class IntegerDBIDRange extends AbstractList<DBID> implements DBIDRange {
@Override
public DBID next() {
- DBID ret = DBIDFactory.FACTORY.importInteger(pos + start);
+ DBID ret = new IntegerDBID(pos + start);
pos++;
return ret;
}
@@ -100,22 +104,48 @@ class IntegerDBIDRange extends AbstractList<DBID> implements DBIDRange {
}
}
- /*
- * "Contains" operations
+ /**
+ * Iterator in ELKI/C++ style.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
*/
+ protected class DBIDItr implements DBIDIter {
+ int pos = 0;
+
+ @Override
+ public boolean valid() {
+ return pos < len;
+ }
+
+ @Override
+ public void advance() {
+ pos++;
+ }
+
+ @Override
+ public int getIntegerID() {
+ return start + pos;
+ }
+
+ @Override
+ public DBID getDBID() {
+ return new IntegerDBID(start + pos);
+ }
+
+ }
+
@Override
- public boolean contains(Object o) {
- if(o instanceof DBID) {
- int oid = ((DBID) o).getIntegerID();
- if(oid < start) {
- return false;
- }
- if(oid >= start + len) {
- return false;
- }
- return true;
+ public boolean contains(DBID o) {
+ int oid = o.getIntegerID();
+ if(oid < start) {
+ return false;
}
- return false;
+ if(oid >= start + len) {
+ return false;
+ }
+ return true;
}
@SuppressWarnings("unchecked")
@@ -137,11 +167,11 @@ class IntegerDBIDRange extends AbstractList<DBID> implements DBIDRange {
@Override
public DBID get(int i) {
- if (i > len || i < 0) {
+ if(i > len || i < 0) {
throw new ArrayIndexOutOfBoundsException();
}
return DBIDFactory.FACTORY.importInteger(start + i);
- }
+ }
/**
* For storage array offsets.
@@ -155,7 +185,15 @@ class IntegerDBIDRange extends AbstractList<DBID> implements DBIDRange {
}
@Override
- public Collection<DBID> asCollection() {
- return this;
+ public int binarySearch(DBID key) {
+ int keyid = key.getIntegerID();
+ if(keyid < start) {
+ return -1;
+ }
+ final int off = keyid - start;
+ if(off < len) {
+ return off;
+ }
+ return -(len + 1);
}
} \ No newline at end of file
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 8e4600db..01e42fe9 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) 2011
+ Copyright (C) 2012
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/SimpleDBIDFactory.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/SimpleDBIDFactory.java
index 3348701e..59fa34b5 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,21 +27,17 @@ 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.DBIDs;
import de.lmu.ifi.dbs.elki.database.ids.HashSetModifiableDBIDs;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDRange;
-import de.lmu.ifi.dbs.elki.database.ids.TreeSetModifiableDBIDs;
-import de.lmu.ifi.dbs.elki.database.ids.generic.GenericArrayModifiableDBIDs;
-import de.lmu.ifi.dbs.elki.database.ids.generic.GenericHashSetModifiableDBIDs;
-import de.lmu.ifi.dbs.elki.database.ids.generic.GenericTreeSetModifiableDBIDs;
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;
/**
- * Simple DBID management, that never reuses IDs.
- * Statically allocated DBID ranges are given positive values,
- * Dynamically allocated DBIDs are given negative values.
+ * Simple DBID management, that never reuses IDs. Statically allocated DBID
+ * ranges are given positive values, Dynamically allocated DBIDs are given
+ * negative values.
*
* @author Erich Schubert
*
@@ -50,21 +46,20 @@ import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
* @apiviz.uses IntegerDBID oneway - - «create»
* @apiviz.uses IntegerDBIDPair oneway - - «create»
* @apiviz.uses IntegerDBIDRange oneway - - «create»
- * @apiviz.uses GenericArrayModifiableDBIDs oneway - - «create»
- * @apiviz.uses GenericHashSetModifiableDBIDs oneway - - «create»
- * @apiviz.uses GenericTreeSetModifiableDBIDs oneway - - «create»
+ * @apiviz.uses TroveArrayModifiableDBIDs oneway - - «create»
+ * @apiviz.uses TroveHashSetModifiableDBIDs oneway - - «create»
*/
public class SimpleDBIDFactory implements DBIDFactory {
/**
* Keep track of the smallest dynamic DBID offset not used
*/
int dynamicids = 0;
-
+
/**
* The starting point for static DBID range allocations.
*/
int rangestart = 0;
-
+
/**
* Constructor
*/
@@ -74,7 +69,7 @@ public class SimpleDBIDFactory implements DBIDFactory {
@Override
public synchronized DBID generateSingleDBID() {
- if (dynamicids == Integer.MIN_VALUE) {
+ if(dynamicids == Integer.MIN_VALUE) {
throw new AbortException("DBID range allocation error - too many objects allocated!");
}
dynamicids--;
@@ -88,7 +83,7 @@ public class SimpleDBIDFactory implements DBIDFactory {
@Override
public synchronized DBIDRange generateStaticDBIDRange(int size) {
- if (rangestart >= Integer.MAX_VALUE - size) {
+ if(rangestart >= Integer.MAX_VALUE - size) {
throw new AbortException("DBID range allocation error - too many objects allocated!");
}
DBIDRange alloc = new IntegerDBIDRange(rangestart, size);
@@ -108,47 +103,32 @@ public class SimpleDBIDFactory implements DBIDFactory {
@Override
public ArrayModifiableDBIDs newArray() {
- return new GenericArrayModifiableDBIDs();
+ return new TroveArrayModifiableDBIDs();
}
@Override
public HashSetModifiableDBIDs newHashSet() {
- return new GenericHashSetModifiableDBIDs();
- }
-
- @Override
- public TreeSetModifiableDBIDs newTreeSet() {
- return new GenericTreeSetModifiableDBIDs();
+ return new TroveHashSetModifiableDBIDs();
}
@Override
public ArrayModifiableDBIDs newArray(int size) {
- return new GenericArrayModifiableDBIDs(size);
+ return new TroveArrayModifiableDBIDs(size);
}
@Override
public HashSetModifiableDBIDs newHashSet(int size) {
- return new GenericHashSetModifiableDBIDs(size);
- }
-
- @Override
- public TreeSetModifiableDBIDs newTreeSet(int size) {
- return new GenericTreeSetModifiableDBIDs(size);
+ return new TroveHashSetModifiableDBIDs(size);
}
@Override
public ArrayModifiableDBIDs newArray(DBIDs existing) {
- return new GenericArrayModifiableDBIDs(existing);
+ return new TroveArrayModifiableDBIDs(existing);
}
@Override
public HashSetModifiableDBIDs newHashSet(DBIDs existing) {
- return new GenericHashSetModifiableDBIDs(existing);
- }
-
- @Override
- public TreeSetModifiableDBIDs newTreeSet(DBIDs existing) {
- return new GenericTreeSetModifiableDBIDs(existing);
+ return new TroveHashSetModifiableDBIDs(existing);
}
@Override
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 ee49e2f1..b38286fe 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,13 +29,9 @@ 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.DBIDs;
import de.lmu.ifi.dbs.elki.database.ids.HashSetModifiableDBIDs;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDRange;
-import de.lmu.ifi.dbs.elki.database.ids.TreeSetModifiableDBIDs;
-import de.lmu.ifi.dbs.elki.database.ids.generic.GenericArrayModifiableDBIDs;
-import de.lmu.ifi.dbs.elki.database.ids.generic.GenericHashSetModifiableDBIDs;
-import de.lmu.ifi.dbs.elki.database.ids.generic.GenericTreeSetModifiableDBIDs;
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;
@@ -52,9 +48,8 @@ import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
* @apiviz.uses IntegerDBID oneway - - «create»
* @apiviz.uses IntegerDBIDPair oneway - - «create»
* @apiviz.uses IntegerDBIDRange oneway - - «create»
- * @apiviz.uses GenericArrayModifiableDBIDs oneway - - «create»
- * @apiviz.uses GenericHashSetModifiableDBIDs oneway - - «create»
- * @apiviz.uses GenericTreeSetModifiableDBIDs oneway - - «create»
+ * @apiviz.uses TroveArrayModifiableDBIDs oneway - - «create»
+ * @apiviz.uses TroveHashSetModifiableDBIDs oneway - - «create»
*/
public class TrivialDBIDFactory implements DBIDFactory {
/**
@@ -106,47 +101,32 @@ public class TrivialDBIDFactory implements DBIDFactory {
@Override
public ArrayModifiableDBIDs newArray() {
- return new GenericArrayModifiableDBIDs();
+ return new TroveArrayModifiableDBIDs();
}
@Override
public HashSetModifiableDBIDs newHashSet() {
- return new GenericHashSetModifiableDBIDs();
- }
-
- @Override
- public TreeSetModifiableDBIDs newTreeSet() {
- return new GenericTreeSetModifiableDBIDs();
+ return new TroveHashSetModifiableDBIDs();
}
@Override
public ArrayModifiableDBIDs newArray(int size) {
- return new GenericArrayModifiableDBIDs(size);
+ return new TroveArrayModifiableDBIDs(size);
}
@Override
public HashSetModifiableDBIDs newHashSet(int size) {
- return new GenericHashSetModifiableDBIDs(size);
- }
-
- @Override
- public TreeSetModifiableDBIDs newTreeSet(int size) {
- return new GenericTreeSetModifiableDBIDs(size);
+ return new TroveHashSetModifiableDBIDs(size);
}
@Override
public ArrayModifiableDBIDs newArray(DBIDs existing) {
- return new GenericArrayModifiableDBIDs(existing);
+ return new TroveArrayModifiableDBIDs(existing);
}
@Override
public HashSetModifiableDBIDs newHashSet(DBIDs existing) {
- return new GenericHashSetModifiableDBIDs(existing);
- }
-
- @Override
- public TreeSetModifiableDBIDs newTreeSet(DBIDs existing) {
- return new GenericTreeSetModifiableDBIDs(existing);
+ return new TroveHashSetModifiableDBIDs(existing);
}
@Override
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
new file mode 100644
index 00000000..a060c6b8
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveArrayDBIDs.java
@@ -0,0 +1,133 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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 java.util.Iterator;
+
+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;
+
+/**
+ * Abstract base class for GNU Trove array based lists.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has IntegerDBID
+ * @apiviz.has TroveIteratorAdapter
+ */
+public abstract class TroveArrayDBIDs implements ArrayDBIDs {
+ /**
+ * Get the array store
+ *
+ * @return the store
+ */
+ abstract protected TIntList getStore();
+
+ @Override
+ public Iterator<DBID> iterator() {
+ return new TroveIteratorAdapter(getStore().iterator());
+ }
+
+ @Override
+ public DBIDIter iter() {
+ return new DBIDItr(getStore());
+ }
+
+ @Override
+ public DBID get(int index) {
+ return new IntegerDBID(getStore().get(index));
+ }
+
+ @Override
+ public int size() {
+ return getStore().size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return getStore().isEmpty();
+ }
+
+ @Override
+ public boolean contains(DBID o) {
+ return getStore().contains(o.getIntegerID());
+ }
+
+ @Override
+ public int binarySearch(DBID key) {
+ return getStore().binarySearch(key.getIntegerID());
+ }
+
+ /**
+ * Iterate over a Trove IntList, ELKI/C-style
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ protected static class DBIDItr implements DBIDIter {
+ /**
+ * Current position
+ */
+ int pos = 0;
+
+ /**
+ * The actual store we use
+ */
+ TIntList store;
+
+ /**
+ * Constructor.
+ *
+ * @param store The actual trove store
+ */
+ public DBIDItr(TIntList store) {
+ super();
+ this.store = store;
+ }
+
+ @Override
+ public boolean valid() {
+ return pos < store.size();
+ }
+
+ @Override
+ public void advance() {
+ pos++;
+ }
+
+ @Override
+ public int getIntegerID() {
+ return store.get(pos);
+ }
+
+ @Override
+ public DBID getDBID() {
+ return new IntegerDBID(store.get(pos));
+ }
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..abcbba14
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveArrayModifiableDBIDs.java
@@ -0,0 +1,144 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.TIntArrayList;
+
+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.DBIDs;
+
+/**
+ * Class using a GNU Trove int array list as storage.
+ *
+ * @author Erich Schubert
+ */
+class TroveArrayModifiableDBIDs extends TroveArrayDBIDs implements ArrayModifiableDBIDs {
+ /**
+ * The actual trove array list
+ */
+ private TIntArrayList store;
+
+ /**
+ * Constructor.
+ *
+ * @param size Initial size
+ */
+ protected TroveArrayModifiableDBIDs(int size) {
+ super();
+ this.store = new TIntArrayList(size);
+ }
+
+ /**
+ * Constructor.
+ */
+ protected TroveArrayModifiableDBIDs() {
+ super();
+ this.store = new TIntArrayList();
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param existing Existing ids
+ */
+ protected TroveArrayModifiableDBIDs(DBIDs existing) {
+ this(existing.size());
+ this.addDBIDs(existing);
+ }
+
+ @Override
+ protected TIntArrayList getStore() {
+ return store;
+ }
+
+ @Override
+ public boolean addDBIDs(DBIDs ids) {
+ boolean success = false;
+ for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
+ success |= store.add(iter.getIntegerID());
+ }
+ return success;
+ }
+
+ @Override
+ public boolean removeDBIDs(DBIDs ids) {
+ boolean success = false;
+ for(DBID id : ids) {
+ success |= store.remove(id.getIntegerID());
+ }
+ return success;
+ }
+
+ @Override
+ public boolean add(DBID e) {
+ return store.add(e.getIntegerID());
+ }
+
+ @Override
+ public boolean remove(DBID o) {
+ return store.remove(o.getIntegerID());
+ }
+
+ @Override
+ public DBID set(int index, DBID element) {
+ int prev = store.set(index, element.getIntegerID());
+ return new IntegerDBID(prev);
+ }
+
+ @Override
+ public DBID remove(int index) {
+ return new IntegerDBID(store.removeAt(index));
+ }
+
+ @Override
+ public void clear() {
+ store.clear();
+ }
+
+ @Override
+ public void sort() {
+ store.sort();
+ }
+
+ @Override
+ public void sort(Comparator<? super DBID> comparator) {
+ // FIXME: optimize, avoid the extra copy.
+ // Clone data
+ DBID[] data = new DBID[store.size()];
+ for(int i = 0; i < store.size(); i++) {
+ data[i] = new IntegerDBID(store.get(i));
+ }
+ // Sort
+ Arrays.sort(data, comparator);
+ // Copy back
+ for(int i = 0; i < store.size(); i++) {
+ store.set(i, data[i].getIntegerID());
+ }
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/events/ContextChangedEvent.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveArrayStaticDBIDs.java
index 6d3aa24a..53ab34d4 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/events/ContextChangedEvent.java
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveArrayStaticDBIDs.java
@@ -1,10 +1,9 @@
-package de.lmu.ifi.dbs.elki.visualization.visualizers.events;
-
+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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,29 +22,32 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.events;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.EventObject;
-
-import de.lmu.ifi.dbs.elki.visualization.VisualizerContext;
+import gnu.trove.list.TIntList;
+import de.lmu.ifi.dbs.elki.database.ids.ArrayStaticDBIDs;
/**
- * Event produced when the visualizer context has changed.
+ * Class accessing a trove int array.
*
* @author Erich Schubert
- *
- * @apiviz.stereotype event
*/
-public abstract class ContextChangedEvent extends EventObject {
+class TroveArrayStaticDBIDs extends TroveArrayDBIDs implements ArrayStaticDBIDs {
/**
- * Serial version
+ * Actual trove store
*/
- private static final long serialVersionUID = 1L;
+ private final TIntList store;
/**
- * Visualization context changed.
+ * Constructor.
*
- * @param source context that has changed
+ * @param store Actual trove store.
*/
- public ContextChangedEvent(VisualizerContext source) {
- super(source);
+ protected TroveArrayStaticDBIDs(TIntList store) {
+ super();
+ this.store = store;
+ }
+
+ @Override
+ protected TIntList getStore() {
+ return store;
}
-} \ No newline at end of file
+}
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
new file mode 100644
index 00000000..11fe669c
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveHashSetModifiableDBIDs.java
@@ -0,0 +1,193 @@
+package de.lmu.ifi.dbs.elki.database.ids.integer;
+
+import java.util.Iterator;
+
+import gnu.trove.impl.hash.THashPrimitiveIterator;
+import gnu.trove.impl.hash.TIntHash;
+import gnu.trove.set.hash.TIntHashSet;
+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.ids.HashSetModifiableDBIDs;
+
+/*
+ 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/>.
+ */
+
+/**
+ * Implementation using GNU Trove Int Hash Sets.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has IntegerDBID
+ * @apiviz.has TroveIteratorAdapter
+ */
+class TroveHashSetModifiableDBIDs implements HashSetModifiableDBIDs {
+ /**
+ * The actual store.
+ */
+ TIntHashSet store;
+
+ /**
+ * Constructor.
+ *
+ * @param size Initial size
+ */
+ protected TroveHashSetModifiableDBIDs(int size) {
+ super();
+ this.store = new TIntHashSet(size);
+ }
+
+ /**
+ * Constructor.
+ */
+ protected TroveHashSetModifiableDBIDs() {
+ super();
+ this.store = new TIntHashSet();
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param existing Existing IDs
+ */
+ protected TroveHashSetModifiableDBIDs(DBIDs existing) {
+ this(existing.size());
+ this.addDBIDs(existing);
+ }
+
+ @Override
+ public DBIDIter iter() {
+ return new DBIDItr(store);
+ }
+
+ @Override
+ public boolean addDBIDs(DBIDs ids) {
+ boolean success = false;
+ for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
+ success |= store.add(iter.getIntegerID());
+ }
+ return success;
+ }
+
+ @Override
+ public boolean removeDBIDs(DBIDs ids) {
+ boolean success = false;
+ for(DBID id : ids) {
+ success |= store.remove(id.getIntegerID());
+ }
+ return success;
+ }
+
+ @Override
+ public boolean add(DBID e) {
+ return store.add(e.getIntegerID());
+ }
+
+ @Override
+ public boolean remove(DBID o) {
+ return store.remove(o.getIntegerID());
+ }
+
+ @Override
+ public boolean retainAll(DBIDs set) {
+ boolean modified = false;
+ Iterator<DBID> it = iterator();
+ while(it.hasNext()) {
+ if(!set.contains(it.next())) {
+ it.remove();
+ modified = true;
+ }
+ }
+ return modified;
+ }
+
+ @Override
+ public Iterator<DBID> iterator() {
+ return new TroveIteratorAdapter(store.iterator());
+ }
+
+ @Override
+ public int size() {
+ return store.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return store.isEmpty();
+ }
+
+ @Override
+ public void clear() {
+ store.clear();
+ }
+
+ @Override
+ public boolean contains(DBID o) {
+ return store.contains(o.getIntegerID());
+ }
+
+ /**
+ * Iterator over trove hashs.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ protected static class DBIDItr extends THashPrimitiveIterator implements DBIDIter {
+ /**
+ * The has we access
+ */
+ private TIntHash hash;
+
+ /**
+ * Constructor.
+ *
+ * @param hash Trove hash
+ */
+ public DBIDItr(TIntHash hash) {
+ super(hash);
+ this.hash = hash;
+ this._index = nextIndex(); // Find first element
+ }
+
+ @Override
+ public boolean valid() {
+ return _index >= 0;
+ }
+
+ @Override
+ public void advance() {
+ this._index = nextIndex();
+ }
+
+ @Override
+ public int getIntegerID() {
+ return hash._set[_index];
+ }
+
+ @Override
+ public DBID getDBID() {
+ return new IntegerDBID(hash._set[_index]);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveIteratorAdapter.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveIteratorAdapter.java
new file mode 100644
index 00000000..2f596f47
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveIteratorAdapter.java
@@ -0,0 +1,66 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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 java.util.Iterator;
+
+import de.lmu.ifi.dbs.elki.database.ids.DBID;
+
+/**
+ * Adapter for using GNU Trove iterators.
+ *
+ * @author Erich Schubert
+ */
+class TroveIteratorAdapter implements Iterator<DBID> {
+ /**
+ * The actual iterator.
+ */
+ private TIntIterator iterator;
+
+ /**
+ * Constructor.
+ *
+ * @param iterator Trove iterator
+ */
+ protected TroveIteratorAdapter(TIntIterator iterator) {
+ this.iterator = iterator;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return iterator.hasNext();
+ }
+
+ @Override
+ public DBID next() {
+ return new IntegerDBID(iterator.next());
+ }
+
+ @Override
+ public void remove() {
+ iterator.remove();
+ }
+} \ No newline at end of file
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 d7ab7304..2508c930 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) 2011
+Copyright (C) 2012
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 ce8d1f39..2c7de1c5 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
@@ -17,19 +17,16 @@
* <th></th>
* <th style="border-bottom: 2px">{@link de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs ArrayDBIDs}</th>
* <th style="border-bottom: 2px">{@link de.lmu.ifi.dbs.elki.database.ids.HashSetDBIDs HashSetDBIDs}</th>
- * <th style="border-bottom: 2px">{@link de.lmu.ifi.dbs.elki.database.ids.TreeSetDBIDs TreeSetDBIDs}</th>
* </tr>
* <tr>
* <th style="border-right: 2px">{@link de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs ModifiableDBIDs}</th>
* <td>{@link de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs ArrayModifiableDBIDs}</td>
* <td>{@link de.lmu.ifi.dbs.elki.database.ids.HashSetModifiableDBIDs HashSetModifiableDBIDs}</td>
- * <td>{@link de.lmu.ifi.dbs.elki.database.ids.TreeSetModifiableDBIDs TreeSetModifiableDBIDs}</td>
* </tr>
* <tr>
* <th style="border-right: 2px">{@link de.lmu.ifi.dbs.elki.database.ids.StaticDBIDs StaticDBIDs}</th>
* <td>{@link de.lmu.ifi.dbs.elki.database.ids.ArrayStaticDBIDs ArrayStaticDBIDs}</td>
* <td>n/a</td>
- * <td>n/a</td>
* </tr>
* </table>
*
@@ -47,8 +44,6 @@
* ArrayModifiableDBIDs array = DBIDUtil.newArraySet(123);
* // new DBID hash set with minimum initial capacity
* ModifiableDBIDs hash = DBIDUtil.newHashSet();
- * // initialize a tree set with the IDs of the database.
- * ModifiableDBIDs tree = DBIDUtil.newTreeSet(database.getIDs());
*
* // add all DBIDs from the hash
* tree.addDBIDs(hash)
@@ -78,25 +73,25 @@
* @apiviz.exclude java.*
*/
/*
-This file is part of ELKI:
-Environment for Developing KDD-Applications Supported by Index-Structures
+ 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
+ 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 free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
+ You 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; \ No newline at end of file
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 e6c6077c..c39600f7 100644
--- a/src/de/lmu/ifi/dbs/elki/database/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/database/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2011
+Copyright (C) 2012
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 bb913602..d9accf4f 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -49,9 +49,9 @@ public abstract class AbstractDataBasedQuery<O> implements DatabaseQuery {
}
/**
- * Give access to the underlying data query.
+ * Get the queries relation.
*
- * @return data query instance
+ * @return Relation
*/
public Relation<? extends O> getRelation() {
return relation;
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 5d56a012..28c89ee3 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) 2011
+ Copyright (C) 2012
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/DistanceResultPair.java b/src/de/lmu/ifi/dbs/elki/database/query/DistanceResultPair.java
index ccdef3ef..e7403628 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/DistanceResultPair.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/DistanceResultPair.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) 2011
+ Copyright (C) 2012
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 44f735ec..9b9367fb 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) 2011
+ Copyright (C) 2012
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/DoubleDistanceResultPair.java b/src/de/lmu/ifi/dbs/elki/database/query/DoubleDistanceResultPair.java
index cbe2cb23..e0be7c40 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/DoubleDistanceResultPair.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/DoubleDistanceResultPair.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) 2011
+ Copyright (C) 2012
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/GenericDistanceResultPair.java b/src/de/lmu/ifi/dbs/elki/database/query/GenericDistanceResultPair.java
index 19f17c48..4b838560 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/GenericDistanceResultPair.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/GenericDistanceResultPair.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) 2011
+ Copyright (C) 2012
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 80f2c5b5..4cace1cf 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) 2011
+ Copyright (C) 2012
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 fff15c93..92c116e3 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) 2011
+ Copyright (C) 2012
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 e29ccc5e..10dde0ad 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) 2011
+ Copyright (C) 2012
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 cf650b0f..2bb45623 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) 2011
+ Copyright (C) 2012
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 63be8fe5..1986b246 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) 2011
+ Copyright (C) 2012
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 6c056a0b..5015dee1 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) 2011
+ Copyright (C) 2012
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 7013c693..4988c925 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) 2011
+ Copyright (C) 2012
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 c37c5b18..59f6534b 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -60,28 +60,6 @@ public interface SpatialDistanceQuery<V extends SpatialComparable, D extends Dis
D minDist(SpatialComparable mbr, DBID id);
/**
- * Computes the distance between the two given MBRs according to this distance
- * function.
- *
- * @param mbr1 the first MBR object
- * @param mbr2 the second MBR object
- * @return the distance between the two given MBRs according to this distance
- * function
- */
- D mbrDist(SpatialComparable mbr1, SpatialComparable mbr2);
-
- /**
- * Computes the distance between the centroids of the two given MBRs according
- * to this distance function.
- *
- * @param mbr1 the first MBR object
- * @param mbr2 the second MBR object
- * @return the distance between the centroids of the two given MBRs according
- * to this distance function
- */
- D centerDistance(SpatialComparable mbr1, SpatialComparable mbr2);
-
- /**
* Get the inner distance function.
*
* @return Distance function
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 ddafc622..550c2c5c 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -54,16 +54,6 @@ public class SpatialPrimitiveDistanceQuery<V extends SpatialComparable, D extend
}
@Override
- public D centerDistance(SpatialComparable mbr1, SpatialComparable mbr2) {
- return distanceFunction.centerDistance(mbr1, mbr2);
- }
-
- @Override
- public D mbrDist(SpatialComparable mbr1, SpatialComparable mbr2) {
- return distanceFunction.minDist(mbr1, mbr2);
- }
-
- @Override
public D minDist(SpatialComparable mbr, V v) {
return distanceFunction.minDist(mbr, v);
}
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 71b54314..2257eb98 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
@@ -6,7 +6,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2011
+Copyright (C) 2012
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 296a3950..731148e8 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,11 +23,8 @@ package de.lmu.ifi.dbs.elki.database.query.knn;
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.database.query.AbstractDataBasedQuery;
-import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
@@ -53,18 +50,8 @@ public abstract class AbstractDistanceKNNQuery<O, D extends Distance<D>> extends
}
@Override
- abstract public List<DistanceResultPair<D>> getKNNForDBID(DBID id, int k);
-
- @Override
- abstract public List<DistanceResultPair<D>> getKNNForObject(O obj, int k);
+ abstract public KNNResult<D> getKNNForDBID(DBID id, int k);
@Override
- public DistanceQuery<O, D> getDistanceQuery() {
- return distanceQuery;
- }
-
- @Override
- public D getDistanceFactory() {
- return distanceQuery.getDistanceFactory();
- }
+ abstract public KNNResult<D> getKNNForObject(O obj, int k);
} \ No newline at end of file
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 81b4ded8..80d91180 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,9 +29,6 @@ import java.util.Map;
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.query.DatabaseQuery;
-import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
-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.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.KNNHeap;
@@ -41,7 +38,7 @@ import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.KNNHeap;
* @author Erich Schubert
*
* @apiviz.landmark
- * @apiviz.uses DistanceResultPair oneway - - «create»
+ * @apiviz.has KNNResult oneway - - «create»
*
* @param <O> Object type
* @param <D> Distance type
@@ -54,7 +51,7 @@ public interface KNNQuery<O, D extends Distance<D>> extends DatabaseQuery {
* @param k Number of neighbors requested
* @return neighbors
*/
- public List<DistanceResultPair<D>> getKNNForDBID(DBID id, int k);
+ public KNNResult<D> getKNNForDBID(DBID id, int k);
/**
* Bulk query method
@@ -63,7 +60,7 @@ public interface KNNQuery<O, D extends Distance<D>> extends DatabaseQuery {
* @param k Number of neighbors requested
* @return neighbors
*/
- public List<List<DistanceResultPair<D>>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k);
+ public List<KNNResult<D>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k);
/**
* Bulk query method configured by a map.
@@ -82,24 +79,5 @@ public interface KNNQuery<O, D extends Distance<D>> extends DatabaseQuery {
* @param k Number of neighbors requested
* @return neighbors
*/
- // TODO: return KNNList<D> instead?
- public List<DistanceResultPair<D>> getKNNForObject(O obj, int k);
-
- /**
- * Get the distance query for this function.
- */
- // TODO: remove?
- public DistanceQuery<O, D> getDistanceQuery();
-
- /**
- * Get the distance data type of the function.
- */
- public D getDistanceFactory();
-
- /**
- * Access the underlying data query.
- *
- * @return data query in use
- */
- public abstract Relation<? extends O> getRelation();
+ public KNNResult<D> getKNNForObject(O obj, int k);
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/knn/KNNResult.java b/src/de/lmu/ifi/dbs/elki/database/query/knn/KNNResult.java
new file mode 100644
index 00000000..d45fd8d7
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/database/query/knn/KNNResult.java
@@ -0,0 +1,83 @@
+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 java.util.Collection;
+import java.util.List;
+
+import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs;
+import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+
+/**
+ * Interface for kNN results - List<> like.
+ *
+ * @author Erich Schubert
+ *
+ * @param <D> Distance type
+ *
+ * @apiviz.composedOf DistanceResultPair
+ */
+public interface KNNResult<D extends Distance<D>> extends Collection<DistanceResultPair<D>> {
+ /**
+ * Size
+ */
+ @Override
+ public int size();
+
+ /**
+ * Get the K parameter (note: this may be less than the size of the list!)
+ *
+ * @return K
+ */
+ public int getK();
+
+ /**
+ * Direct object access.
+ *
+ * @param index
+ */
+ public DistanceResultPair<D> get(int index);
+
+ /**
+ * Get the distance to the k nearest neighbor, or maxdist otherwise.
+ *
+ * @return Maximum distance
+ */
+ public D getKNNDistance();
+
+ /**
+ * View as ArrayDBIDs
+ *
+ * @return Static DBIDs
+ */
+ public ArrayDBIDs asDBIDs();
+
+ /**
+ * View as list of distances
+ *
+ * @return List of distances view
+ */
+ public List<D> asDistanceList();
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/database/query/knn/KNNUtil.java b/src/de/lmu/ifi/dbs/elki/database/query/knn/KNNUtil.java
new file mode 100644
index 00000000..1179edb5
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/database/query/knn/KNNUtil.java
@@ -0,0 +1,417 @@
+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 java.util.AbstractCollection;
+import java.util.AbstractList;
+import java.util.Iterator;
+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.DBIDIter;
+import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+
+/**
+ * Helper classes for kNN results.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.uses KNNResult
+ */
+public final class KNNUtil {
+ /**
+ * 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>> extends AbstractCollection<DistanceResultPair<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.
+ {
+ DistanceResultPair<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 DistanceResultPair<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 ArrayDBIDs asDBIDs() {
+ return KNNUtil.asDBIDs(this);
+ }
+
+ @Override
+ public List<D> asDistanceList() {
+ return KNNUtil.asDistanceList(this);
+ }
+
+ @Override
+ public Iterator<DistanceResultPair<D>> iterator() {
+ return new Itr();
+ }
+
+ @Override
+ public int size() {
+ return size;
+ }
+
+ /**
+ * Iterator for the sublist.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ private class Itr implements Iterator<DistanceResultPair<D>> {
+ /**
+ * Current position
+ */
+ private int pos = -1;
+
+ @Override
+ public boolean hasNext() {
+ return pos + 1 < size;
+ }
+
+ @Override
+ public DistanceResultPair<D> next() {
+ pos++;
+ return inner.get(pos);
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException("kNN results are unmodifiable.");
+ }
+ }
+ }
+
+ /**
+ * Proxy iterator for accessing DBIDs.
+ *
+ * @author Erich Schubert
+ */
+ protected static class DBIDIterator implements Iterator<DBID> {
+ /**
+ * The real iterator.
+ */
+ Iterator<? extends DistanceResultPair<?>> itr;
+
+ /**
+ * Constructor.
+ */
+ protected DBIDIterator(Iterator<? extends DistanceResultPair<?>> itr) {
+ super();
+ this.itr = itr;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return itr.hasNext();
+ }
+
+ @Override
+ public DBID next() {
+ return itr.next().getDBID();
+ }
+
+ @Override
+ public void remove() {
+ itr.remove();
+ }
+ }
+
+ /**
+ * Proxy iterator for accessing DBIDs.
+ *
+ * @author Erich Schubert
+ */
+ protected static class DBIDItr implements DBIDIter {
+ /**
+ * Current result
+ */
+ DistanceResultPair<?> cur;
+
+ /**
+ * The real iterator.
+ */
+ Iterator<? extends DistanceResultPair<?>> itr;
+
+ /**
+ * Constructor.
+ */
+ protected DBIDItr(Iterator<? extends DistanceResultPair<?>> itr) {
+ super();
+ this.itr = itr;
+ advance();
+ }
+
+ @Override
+ public boolean valid() {
+ return cur != null;
+ }
+
+ @Override
+ public void advance() {
+ if(itr.hasNext()) {
+ cur = itr.next();
+ }
+ else {
+ cur = null;
+ }
+ }
+
+ @Override
+ public int getIntegerID() {
+ return cur.getDBID().getIntegerID();
+ }
+
+ @Override
+ public DBID getDBID() {
+ return cur.getDBID();
+ }
+ }
+
+ /**
+ * A view on the DBIDs of the result
+ *
+ * @author Erich Schubert
+ */
+ protected static class DBIDView implements ArrayDBIDs {
+ /**
+ * The true list.
+ */
+ final KNNResult<?> parent;
+
+ /**
+ * Constructor.
+ *
+ * @param parent Owner
+ */
+ public DBIDView(KNNResult<?> parent) {
+ super();
+ this.parent = parent;
+ }
+
+ @Override
+ public DBID get(int i) {
+ return parent.get(i).getDBID();
+ }
+
+ @Override
+ public Iterator<DBID> iterator() {
+ return new DBIDIterator(parent.iterator());
+ }
+
+ @Override
+ public DBIDIter iter() {
+ return new DBIDItr(parent.iterator());
+ }
+
+ @Override
+ public int size() {
+ return parent.size();
+ }
+
+ @Override
+ public boolean contains(DBID o) {
+ for(DBID id : this) {
+ if(id.equals(o)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return parent.size() == 0;
+ }
+
+ /**
+ * A binary search does not make sense here, as the (read-only) result is sorted by
+ * distance, not DBID. Thus unsupported.
+ */
+ @Override
+ @Deprecated
+ public int binarySearch(DBID key) {
+ throw new UnsupportedOperationException("Since the result is usually not sorted, a binary Search does not make sense!");
+ }
+ }
+
+ /**
+ * Proxy iterator for accessing DBIDs.
+ *
+ * @author Erich Schubert
+ */
+ protected static class DistanceItr<D extends Distance<D>> implements Iterator<D> {
+ /**
+ * The real iterator.
+ */
+ Iterator<? extends DistanceResultPair<D>> itr;
+
+ /**
+ * Constructor.
+ */
+ protected DistanceItr(Iterator<? extends DistanceResultPair<D>> itr) {
+ super();
+ this.itr = itr;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return itr.hasNext();
+ }
+
+ @Override
+ public D next() {
+ return itr.next().getDistance();
+ }
+
+ @Override
+ public void remove() {
+ itr.remove();
+ }
+ }
+
+ /**
+ * A view on the Distances of the result
+ *
+ * @author Erich Schubert
+ */
+ 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.iterator());
+ }
+
+ @Override
+ public int size() {
+ return parent.size();
+ }
+ }
+
+ /**
+ * View as ArrayDBIDs
+ *
+ * @param list Result to proxy
+ * @return Static DBIDs
+ */
+ public static ArrayDBIDs asDBIDs(KNNResult<?> list) {
+ return new DBIDView(list);
+ }
+
+ /**
+ * View as list of distances
+ *
+ * @param list Result to proxy
+ * @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
+ * @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);
+ }
+} \ 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 b52c6dec..d6492f43 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -32,7 +32,6 @@ 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.DBIDUtil;
-import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
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;
@@ -76,7 +75,7 @@ public class LinearScanKNNQuery<O, D extends Distance<D>> extends AbstractDistan
}
@Override
- public List<DistanceResultPair<D>> getKNNForDBID(DBID id, int k) {
+ public KNNResult<D> getKNNForDBID(DBID id, int k) {
KNNHeap<D> heap = new KNNHeap<D>(k);
if(PrimitiveDistanceQuery.class.isInstance(distanceQuery)) {
O obj = relation.get(id);
@@ -89,11 +88,11 @@ public class LinearScanKNNQuery<O, D extends Distance<D>> extends AbstractDistan
heap.add(distanceQuery.distance(id, candidateID), candidateID);
}
}
- return heap.toSortedArrayList();
+ return heap.toKNNList();
}
@Override
- public List<List<DistanceResultPair<D>>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) {
+ public List<KNNResult<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++) {
@@ -101,9 +100,9 @@ public class LinearScanKNNQuery<O, D extends Distance<D>> extends AbstractDistan
}
linearScanBatchKNN(ids, heaps);
// Serialize heaps
- List<List<DistanceResultPair<D>>> result = new ArrayList<List<DistanceResultPair<D>>>(size);
+ List<KNNResult<D>> result = new ArrayList<KNNResult<D>>(size);
for(KNNHeap<D> heap : heaps) {
- result.add(heap.toSortedArrayList());
+ result.add(heap.toKNNList());
}
return result;
}
@@ -121,12 +120,12 @@ public class LinearScanKNNQuery<O, D extends Distance<D>> extends AbstractDistan
}
@Override
- public List<DistanceResultPair<D>> getKNNForObject(O obj, int k) {
+ public KNNResult<D> getKNNForObject(O obj, int k) {
KNNHeap<D> heap = new KNNHeap<D>(k);
for(DBID candidateID : relation.iterDBIDs()) {
O candidate = relation.get(candidateID);
heap.add(distanceQuery.distance(obj, candidate), candidateID);
}
- return heap.toSortedArrayList();
+ 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 8af7e549..07632a34 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -30,7 +30,6 @@ import java.util.Map.Entry;
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.query.DistanceResultPair;
import de.lmu.ifi.dbs.elki.database.query.distance.PrimitiveDistanceQuery;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.KNNHeap;
@@ -75,12 +74,12 @@ public class LinearScanPrimitiveDistanceKNNQuery<O, D extends Distance<D>> exten
}
@Override
- public List<DistanceResultPair<D>> getKNNForDBID(DBID id, int k) {
+ public KNNResult<D> getKNNForDBID(DBID id, int k) {
return getKNNForObject(relation.get(id), k);
}
@Override
- public List<List<DistanceResultPair<D>>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) {
+ public List<KNNResult<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);
@@ -90,9 +89,9 @@ public class LinearScanPrimitiveDistanceKNNQuery<O, D extends Distance<D>> exten
}
linearScanBatchKNN(objs, heaps);
- List<List<DistanceResultPair<D>>> result = new ArrayList<List<DistanceResultPair<D>>>(heaps.size());
+ List<KNNResult<D>> result = new ArrayList<KNNResult<D>>(heaps.size());
for(KNNHeap<D> heap : heaps) {
- result.add(heap.toSortedArrayList());
+ result.add(heap.toKNNList());
}
return result;
}
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
index 63652e5b..3f7dc04f 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/knn/LinearScanRawDoubleDistanceKNNQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/knn/LinearScanRawDoubleDistanceKNNQuery.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,7 +27,6 @@ import java.util.Arrays;
import java.util.List;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
import de.lmu.ifi.dbs.elki.database.query.DoubleDistanceResultPair;
import de.lmu.ifi.dbs.elki.database.query.distance.PrimitiveDistanceQuery;
import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction;
@@ -57,12 +56,12 @@ public class LinearScanRawDoubleDistanceKNNQuery<O> extends LinearScanPrimitiveD
}
@Override
- public List<DistanceResultPair<DoubleDistance>> getKNNForDBID(DBID id, int k) {
+ public KNNResult<DoubleDistance> getKNNForDBID(DBID id, int k) {
return getKNNForObject(relation.get(id), k);
}
@Override
- public List<DistanceResultPair<DoubleDistance>> getKNNForObject(O obj, int k) {
+ public KNNResult<DoubleDistance> getKNNForObject(O obj, int k) {
@SuppressWarnings("unchecked")
final PrimitiveDoubleDistanceFunction<O> rawdist = (PrimitiveDoubleDistanceFunction<O>) distanceQuery.getDistanceFunction();
// Optimization for double distances.
@@ -78,7 +77,7 @@ public class LinearScanRawDoubleDistanceKNNQuery<O> extends LinearScanPrimitiveD
}
}
}
- return heap.toSortedArrayList();
+ return heap.toKNNList();
}
@Override
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 d82fc20e..93321609 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -32,11 +32,9 @@ 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.query.AbstractDataBasedQuery;
import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
-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.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.index.preprocessed.knn.AbstractMaterializeKNNPreprocessor;
-import de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNPreprocessor;
import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.KNNHeap;
import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
@@ -46,11 +44,11 @@ import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
*
* @author Erich Schubert
*/
-public class PreprocessorKNNQuery<O, D extends Distance<D>> extends AbstractDataBasedQuery<O> implements KNNQuery<O, D> {
+public class PreprocessorKNNQuery<O, D extends Distance<D>, T extends KNNResult<D>> extends AbstractDataBasedQuery<O> implements KNNQuery<O, D> {
/**
* The last preprocessor result
*/
- final private MaterializeKNNPreprocessor<O, D> preprocessor;
+ final private AbstractMaterializeKNNPreprocessor<O, D, T> preprocessor;
/**
* Warn only once.
@@ -63,7 +61,7 @@ public class PreprocessorKNNQuery<O, D extends Distance<D>> extends AbstractData
* @param database Database to query
* @param preprocessor Preprocessor instance to use
*/
- public PreprocessorKNNQuery(Relation<O> database, MaterializeKNNPreprocessor<O, D> preprocessor) {
+ public PreprocessorKNNQuery(Relation<O> database, AbstractMaterializeKNNPreprocessor<O, D, T> preprocessor) {
super(database);
this.preprocessor = preprocessor;
}
@@ -74,17 +72,17 @@ public class PreprocessorKNNQuery<O, D extends Distance<D>> extends AbstractData
* @param database Database to query
* @param preprocessor Preprocessor to use
*/
- public PreprocessorKNNQuery(Relation<O> database, MaterializeKNNPreprocessor.Factory<O, D> preprocessor) {
+ public PreprocessorKNNQuery(Relation<O> database, AbstractMaterializeKNNPreprocessor.Factory<O, D, T> preprocessor) {
this(database, preprocessor.instantiate(database));
}
@Override
- public List<DistanceResultPair<D>> getKNNForDBID(DBID id, int k) {
+ public KNNResult<D> getKNNForDBID(DBID id, int k) {
if(!warned && k > preprocessor.getK()) {
LoggingUtil.warning("Requested more neighbors than preprocessed!");
}
if(!warned && k < preprocessor.getK()) {
- List<DistanceResultPair<D>> dr = preprocessor.get(id);
+ KNNResult<D> dr = preprocessor.get(id);
int subk = k;
D kdist = dr.get(subk - 1).getDistance();
while(subk < dr.size()) {
@@ -98,7 +96,7 @@ public class PreprocessorKNNQuery<O, D extends Distance<D>> extends AbstractData
}
}
if(subk < dr.size()) {
- return dr.subList(0, subk);
+ return KNNUtil.subList(dr, subk);
}
else {
return dr;
@@ -108,14 +106,14 @@ public class PreprocessorKNNQuery<O, D extends Distance<D>> extends AbstractData
}
@Override
- public List<List<DistanceResultPair<D>>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) {
+ public List<KNNResult<D>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) {
if(!warned && k > preprocessor.getK()) {
LoggingUtil.warning("Requested more neighbors than preprocessed!");
}
- List<List<DistanceResultPair<D>>> result = new ArrayList<List<DistanceResultPair<D>>>(ids.size());
+ List<KNNResult<D>> result = new ArrayList<KNNResult<D>>(ids.size());
if(k < preprocessor.getK()) {
for(DBID id : ids) {
- List<DistanceResultPair<D>> dr = preprocessor.get(id);
+ KNNResult<D> dr = preprocessor.get(id);
int subk = k;
D kdist = dr.get(subk - 1).getDistance();
while(subk < dr.size()) {
@@ -129,7 +127,7 @@ public class PreprocessorKNNQuery<O, D extends Distance<D>> extends AbstractData
}
}
if(subk < dr.size()) {
- result.add(dr.subList(0, subk));
+ result.add(KNNUtil.subList(dr, subk));
}
else {
result.add(dr);
@@ -156,7 +154,7 @@ public class PreprocessorKNNQuery<O, D extends Distance<D>> extends AbstractData
}
@Override
- public List<DistanceResultPair<D>> getKNNForObject(O obj, int k) {
+ public KNNResult<D> getKNNForObject(O obj, int k) {
throw new AbortException("Preprocessor KNN query only supports ID queries.");
}
@@ -165,18 +163,7 @@ public class PreprocessorKNNQuery<O, D extends Distance<D>> extends AbstractData
*
* @return preprocessor instance
*/
- public AbstractMaterializeKNNPreprocessor<O, D> getPreprocessor() {
+ public AbstractMaterializeKNNPreprocessor<O, D, T> getPreprocessor() {
return preprocessor;
}
-
- @Override
- public D getDistanceFactory() {
- return preprocessor.getDistanceFactory();
- }
-
- @Override
- public DistanceQuery<O, D> getDistanceQuery() {
- // TODO: remove? throw an exception?
- return preprocessor.getDistanceQuery();
- }
} \ No newline at end of file
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 71d5433f..891ed296 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
@@ -7,7 +7,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2011
+Copyright (C) 2012
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 42c9bab6..05c635a0 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
@@ -78,7 +78,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2011
+Copyright (C) 2012
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 e35cb99f..60426034 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,10 +23,8 @@ package de.lmu.ifi.dbs.elki.database.query.range;
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.DBID;
import de.lmu.ifi.dbs.elki.database.query.AbstractDataBasedQuery;
import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
@@ -63,18 +61,4 @@ public abstract class AbstractDistanceRangeQuery<O, D extends Distance<D>> exten
@Override
abstract public List<DistanceResultPair<D>> getRangeForObject(O obj, D range);
-
- @Override
- public List<List<DistanceResultPair<D>>> getRangeForBulkDBIDs(ArrayDBIDs ids, D range) {
- final List<List<DistanceResultPair<D>>> lists = new ArrayList<List<DistanceResultPair<D>>>(ids.size());
- for(DBID id : ids) {
- lists.add(getRangeForDBID(id, range));
- }
- return lists;
- }
-
- @Override
- public D getDistanceFactory() {
- return distanceQuery.getDistanceFactory();
- }
} \ No newline at end of file
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 6031a30e..dfe0b581 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) 2011
+ Copyright (C) 2012
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/LinearScanRangeQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/range/LinearScanRangeQuery.java
index d4b7296e..a7bb7db9 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) 2011
+ Copyright (C) 2012
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/LinearScanRawDoubleDistanceRangeQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/range/LinearScanRawDoubleDistanceRangeQuery.java
index b33c871e..18d1d173 100644
--- a/src/de/lmu/ifi/dbs/elki/database/query/range/LinearScanRawDoubleDistanceRangeQuery.java
+++ b/src/de/lmu/ifi/dbs/elki/database/query/range/LinearScanRawDoubleDistanceRangeQuery.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) 2011
+ Copyright (C) 2012
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/RangeQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/range/RangeQuery.java
index 7d9ebd42..c2dbecd6 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,11 +25,9 @@ package de.lmu.ifi.dbs.elki.database.query.range;
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.query.DatabaseQuery;
import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
-import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
/**
@@ -54,15 +52,6 @@ public interface RangeQuery<O, D extends Distance<D>> extends DatabaseQuery {
public List<DistanceResultPair<D>> getRangeForDBID(DBID id, D range);
/**
- * Bulk query method
- *
- * @param ids query object IDs
- * @param range Query range
- * @return neighbors
- */
- public List<List<DistanceResultPair<D>>> getRangeForBulkDBIDs(ArrayDBIDs ids, D range);
-
- /**
* Get the nearest neighbors for a particular object in a given query range
*
* @param obj Query object
@@ -70,16 +59,4 @@ public interface RangeQuery<O, D extends Distance<D>> extends DatabaseQuery {
* @return neighbors
*/
public List<DistanceResultPair<D>> getRangeForObject(O obj, D range);
-
- /**
- * Get the distance data type of the function.
- */
- public D getDistanceFactory();
-
- /**
- * Access the underlying data query.
- *
- * @return data query in use
- */
- public abstract Relation<? extends O> getRelation();
} \ 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 21bd4f9a..a176e43d 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) 2011
+Copyright (C) 2012
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 5cecaf88..86e82c7e 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -54,9 +54,4 @@ public abstract class AbstractRKNNQuery<O, D extends Distance<D>> extends Abstra
@Override
abstract public List<DistanceResultPair<D>> getRKNNForDBID(DBID id, int k);
-
- @Override
- public D getDistanceFactory() {
- return distanceQuery.getDistanceFactory();
- }
} \ 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 b3e581e7..1449d7f0 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) 2011
+ Copyright (C) 2012
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.database.query.GenericDistanceResultPair;
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.database.query.knn.KNNResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
/**
@@ -72,11 +73,11 @@ public class LinearScanRKNNQuery<O, D extends Distance<D>> extends AbstractRKNNQ
ArrayList<DistanceResultPair<D>> rNNlist = new ArrayList<DistanceResultPair<D>>();
ArrayDBIDs allIDs = DBIDUtil.ensureArray(relation.getDBIDs());
- List<List<DistanceResultPair<D>>> kNNLists = knnQuery.getKNNForBulkDBIDs(allIDs, k);
+ List<? extends KNNResult<D>> kNNLists = knnQuery.getKNNForBulkDBIDs(allIDs, k);
int i = 0;
for(DBID qid : allIDs) {
- List<DistanceResultPair<D>> knn = kNNLists.get(i);
+ KNNResult<D> knn = kNNLists.get(i);
int last = Math.min(k - 1, knn.size() - 1);
D dist = distanceQuery.distance(obj, qid);
if(last < k - 1 || dist.compareTo(knn.get(last).getDistance()) < 1) {
@@ -101,15 +102,15 @@ public class LinearScanRKNNQuery<O, D extends Distance<D>> extends AbstractRKNNQ
}
ArrayDBIDs allIDs = DBIDUtil.ensureArray(relation.getDBIDs());
- List<List<DistanceResultPair<D>>> kNNList = knnQuery.getKNNForBulkDBIDs(allIDs, k);
+ List<? extends KNNResult<D>> kNNList = knnQuery.getKNNForBulkDBIDs(allIDs, k);
int i = 0;
for(DBID qid : allIDs) {
- List<DistanceResultPair<D>> knn = kNNList.get(i);
+ KNNResult<D> knn = kNNList.get(i);
for(DistanceResultPair<D> n : knn) {
int j = 0;
for(DBID id : ids) {
- if(n.getDBID() == id) {
+ if(n.getDBID().equals(id)) {
List<DistanceResultPair<D>> rNN = rNNList.get(j);
rNN.add(new GenericDistanceResultPair<D>(n.getDistance(), qid));
}
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 5303666f..2f8e841a 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -32,7 +32,6 @@ import de.lmu.ifi.dbs.elki.database.query.AbstractDataBasedQuery;
import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
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.preprocessed.knn.AbstractMaterializeKNNPreprocessor;
import de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNAndRKNNPreprocessor;
import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
@@ -98,18 +97,4 @@ public class PreprocessorRKNNQuery<O, D extends Distance<D>> extends AbstractDat
}
return result;
}
-
- /**
- * Get the preprocessor instance.
- *
- * @return preprocessor instance
- */
- public AbstractMaterializeKNNPreprocessor<O, D> getPreprocessor() {
- return preprocessor;
- }
-
- @Override
- public D getDistanceFactory() {
- return preprocessor.getDistanceFactory();
- }
} \ No newline at end of file
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 df5ac43c..e707b6ce 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,7 +29,6 @@ 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.query.DatabaseQuery;
import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
-import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
/**
@@ -69,16 +68,4 @@ public interface RKNNQuery<O, D extends Distance<D>> extends DatabaseQuery {
* @return reverse k nearest neighbors
*/
public List<List<DistanceResultPair<D>>> getRKNNForBulkDBIDs(ArrayDBIDs ids, int k);
-
- /**
- * Get the distance data type of the function.
- */
- public D getDistanceFactory();
-
- /**
- * Access the underlying data query.
- *
- * @return data query in use
- */
- public abstract Relation<? extends O> getRelation();
} \ 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 80bcd988..a7e2bf37 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) 2011
+Copyright (C) 2012
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 2e263cd9..1af1c624 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) 2011
+ Copyright (C) 2012
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 3dba474e..316d155c 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) 2011
+ Copyright (C) 2012
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 71dc0c4a..f57e0bd5 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) 2011
+ Copyright (C) 2012
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 91d7b84b..c3fdaaa4 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) 2011
+ Copyright (C) 2012
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 a6dca739..d601d0a4 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) 2011
+Copyright (C) 2012
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 55015fa9..9d9ad672 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) 2011
+ Copyright (C) 2012
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 72b278a6..62a6fd36 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) 2011
+ Copyright (C) 2012
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/MaterializedRelation.java b/src/de/lmu/ifi/dbs/elki/database/relation/MaterializedRelation.java
index 14aa54ea..af65e84d 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) 2011
+ Copyright (C) 2012
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
new file mode 100644
index 00000000..190b15c6
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/database/relation/ProjectedView.java
@@ -0,0 +1,114 @@
+package de.lmu.ifi.dbs.elki.database.relation;
+
+import de.lmu.ifi.dbs.elki.data.projection.Projection;
+import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
+import de.lmu.ifi.dbs.elki.database.Database;
+import de.lmu.ifi.dbs.elki.database.ids.DBID;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.result.AbstractHierarchicalResult;
+import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
+
+/*
+ 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/>.
+ */
+
+/**
+ * Projected relation view (non-materialized)
+ *
+ * @author Erich Schubert
+ *
+ * @param <IN> Vector type
+ * @param <OUT> Vector type
+ */
+public class ProjectedView<IN, OUT> extends AbstractHierarchicalResult implements Relation<OUT> {
+ /**
+ * The wrapped representation where we get the IDs from.
+ */
+ private final Relation<IN> inner;
+
+ /**
+ * The projection we use.
+ */
+ private Projection<IN, OUT> projection;
+
+ /**
+ * Constructor.
+ *
+ * @param inner Inner relation
+ * @param projection Projection function
+ */
+ public ProjectedView(Relation<IN> inner, Projection<IN, OUT> projection) {
+ super();
+ this.inner = inner;
+ this.projection = projection;
+ }
+
+ @Override
+ public String getLongName() {
+ return "projection";
+ }
+
+ @Override
+ public String getShortName() {
+ return "projection";
+ }
+
+ @Override
+ public Database getDatabase() {
+ return inner.getDatabase();
+ }
+
+ @Override
+ public OUT get(DBID id) {
+ return projection.project(inner.get(id));
+ }
+
+ @Override
+ public void set(DBID id, OUT val) {
+ throw new UnsupportedOperationException("Projections are read-only.");
+ }
+
+ @Override
+ public void delete(DBID id) {
+ inner.delete(id);
+ }
+
+ @Override
+ public SimpleTypeInformation<OUT> getDataTypeInformation() {
+ return projection.getOutputDataTypeInformation();
+ }
+
+ @Override
+ public DBIDs getDBIDs() {
+ return inner.getDBIDs();
+ }
+
+ @Override
+ public IterableIterator<DBID> iterDBIDs() {
+ return inner.iterDBIDs();
+ }
+
+ @Override
+ public int size() {
+ return inner.size();
+ }
+} \ No newline at end of file
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 e7a6396f..1ae761f3 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -88,13 +88,13 @@ public class ProxyView<O> extends AbstractHierarchicalResult implements Relation
@Override
public O get(DBID id) {
- assert (idview.contains(id));
+ assert (idview.contains(id)) : "Accessing object not included in view.";
return inner.get(id);
}
@Override
public void set(DBID id, O val) {
- assert (idview.contains(id));
+ assert (idview.contains(id)) : "Accessing object not included in view.";
inner.set(id, val);
}
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 75f91aa7..ebe1be3c 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) 2011
+ Copyright (C) 2012
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 2c9c0690..12ecf968 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) 2011
+Copyright (C) 2012
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 aa90c74b..dfd9f981 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,13 +25,18 @@ package de.lmu.ifi.dbs.elki.datasource;
import java.util.List;
+import de.lmu.ifi.dbs.elki.datasource.bundle.BundleStreamSource;
import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle;
+import de.lmu.ifi.dbs.elki.datasource.bundle.StreamFromBundle;
import de.lmu.ifi.dbs.elki.datasource.filter.ObjectFilter;
+import de.lmu.ifi.dbs.elki.datasource.filter.StreamFilter;
+import de.lmu.ifi.dbs.elki.datasource.parser.Parser;
import de.lmu.ifi.dbs.elki.logging.Logging;
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;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
/**
* Abstract super class for all database connections. AbstractDatabaseConnection
@@ -56,6 +61,14 @@ public abstract class AbstractDatabaseConnection implements DatabaseConnection {
public static final OptionID FILTERS_ID = OptionID.getOrCreateOptionID("dbc.filter", "The filters to apply to the input data.");
/**
+ * Parameter to specify the parser to provide a database.
+ * <p>
+ * Key: {@code -dbc.parser}
+ * </p>
+ */
+ public static final OptionID PARSER_ID = OptionID.getOrCreateOptionID("dbc.parser", "Parser to provide the database.");
+
+ /**
* The filters to invoke
*/
protected List<ObjectFilter> filters;
@@ -77,12 +90,82 @@ public abstract class AbstractDatabaseConnection implements DatabaseConnection {
* @return processed objects
*/
protected MultipleObjectsBundle invokeFilters(MultipleObjectsBundle bundle) {
+ BundleStreamSource prevs = null;
+ MultipleObjectsBundle prevb = bundle;
if(filters != null) {
for(ObjectFilter filter : filters) {
- bundle = filter.filter(bundle);
+ if(filter instanceof StreamFilter) {
+ StreamFilter sfilter = (StreamFilter) filter;
+ if(prevs != null) {
+ sfilter.init(prevs);
+ }
+ else {
+ sfilter.init(new StreamFromBundle(prevb));
+ }
+ prevs = sfilter;
+ prevb = null;
+ }
+ else {
+ if(prevs != null) {
+ prevb = filter.filter(MultipleObjectsBundle.fromStream(prevs));
+ prevs = null;
+ }
+ else {
+ prevb = filter.filter(prevb);
+ prevs = null;
+ }
+ }
}
}
- return bundle;
+ if(prevb != null) {
+ return prevb;
+ }
+ else {
+ return MultipleObjectsBundle.fromStream(prevs);
+ }
+ }
+
+ /**
+ * Transforms the specified list of objects and their labels into a list of
+ * objects and their associations.
+ *
+ * @param bundle the objects to process
+ * @return processed objects
+ */
+ protected BundleStreamSource invokeFilters(BundleStreamSource bundle) {
+ BundleStreamSource prevs = bundle;
+ MultipleObjectsBundle prevb = null;
+ if(filters != null) {
+ for(ObjectFilter filter : filters) {
+ if(filter instanceof StreamFilter) {
+ StreamFilter sfilter = (StreamFilter) filter;
+ if(prevs != null) {
+ sfilter.init(prevs);
+ }
+ else {
+ sfilter.init(new StreamFromBundle(prevb));
+ }
+ prevs = sfilter;
+ prevb = null;
+ }
+ else {
+ if(prevs != null) {
+ prevb = filter.filter(MultipleObjectsBundle.fromStream(prevs));
+ prevs = null;
+ }
+ else {
+ prevb = filter.filter(prevb);
+ prevs = null;
+ }
+ }
+ }
+ }
+ if(prevs != null) {
+ return prevs;
+ }
+ else {
+ return new StreamFromBundle(prevb);
+ }
}
/**
@@ -101,6 +184,7 @@ public abstract class AbstractDatabaseConnection implements DatabaseConnection {
*/
public static abstract class Parameterizer extends AbstractParameterizer {
protected List<ObjectFilter> filters;
+ protected Parser parser = null;
@Override
protected void makeOptions(Parameterization config) {
@@ -113,5 +197,12 @@ public abstract class AbstractDatabaseConnection implements DatabaseConnection {
filters = filterParam.instantiateClasses(config);
}
}
+
+ protected void configParser(Parameterization config, Class<?> parserRestrictionClass, Class<?> parserDefaultValueClass) {
+ ObjectParameter<Parser> parserParam = new ObjectParameter<Parser>(PARSER_ID, parserRestrictionClass, parserDefaultValueClass);
+ if(config.grab(parserParam)) {
+ parser = parserParam.instantiateClass(config);
+ }
+ }
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/ArrayAdapterDatabaseConnection.java b/src/de/lmu/ifi/dbs/elki/datasource/ArrayAdapterDatabaseConnection.java
new file mode 100644
index 00000000..4a126d65
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/datasource/ArrayAdapterDatabaseConnection.java
@@ -0,0 +1,78 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.DoubleVector;
+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 an existing data matrix (<code>double[rows][cols]</code>) into an ELKI
+ * database.
+ *
+ * Note: this class is not parameterizable, but can only be used from Java.
+ *
+ * @author Erich Schubert
+ */
+public class ArrayAdapterDatabaseConnection implements DatabaseConnection {
+ /**
+ * The actual data.
+ */
+ double[][] data;
+
+ /**
+ * Constructor.
+ *
+ * @param data Existing data matrix
+ */
+ public ArrayAdapterDatabaseConnection(double[][] data) {
+ super();
+ }
+
+ @Override
+ public MultipleObjectsBundle loadData() {
+ MultipleObjectsBundle b = new MultipleObjectsBundle();
+ int mind = Integer.MAX_VALUE;
+ int maxd = 0;
+ List<DoubleVector> vecs = new ArrayList<DoubleVector>(data.length);
+ for(int i = 0; i < data.length; i++) {
+ mind = Math.min(mind, data[i].length);
+ maxd = Math.max(maxd, data[i].length);
+ vecs.add(new DoubleVector(data[i]));
+ }
+ SimpleTypeInformation<DoubleVector> type;
+ if(mind == maxd) {
+ type = new VectorFieldTypeInformation<DoubleVector>(DoubleVector.class, mind, DoubleVector.STATIC);
+ }
+ else {
+ type = new SimpleTypeInformation<DoubleVector>(DoubleVector.class);
+ }
+ b.appendColumn(type, vecs);
+ return b;
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/ConcatenateFilesDatabaseConnection.java b/src/de/lmu/ifi/dbs/elki/datasource/ConcatenateFilesDatabaseConnection.java
new file mode 100644
index 00000000..1a377d7b
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/datasource/ConcatenateFilesDatabaseConnection.java
@@ -0,0 +1,178 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+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.BundleStreamSource;
+import de.lmu.ifi.dbs.elki.datasource.bundle.BundleStreamSource.Event;
+import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle;
+import de.lmu.ifi.dbs.elki.datasource.bundle.StreamFromBundle;
+import de.lmu.ifi.dbs.elki.datasource.filter.ObjectFilter;
+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.utilities.FileUtil;
+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.optionhandling.parameters.FileListParameter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.FileListParameter.FilesType;
+
+/**
+ * Database that will loading multiple files, concatenating the results.
+ *
+ * @author Erich Schubert
+ */
+public class ConcatenateFilesDatabaseConnection extends AbstractDatabaseConnection {
+ /**
+ * Class logger
+ */
+ private static final Logging logger = Logging.getLogger(ConcatenateFilesDatabaseConnection.class);
+
+ /**
+ * Input file list.
+ */
+ private List<File> files;
+
+ /**
+ * The parser
+ */
+ private Parser parser;
+
+ /**
+ * Constructor.
+ *
+ * @param files Input files
+ * @param parser Parser
+ * @param filters Filters
+ */
+ public ConcatenateFilesDatabaseConnection(List<File> files, Parser parser, List<ObjectFilter> filters) {
+ super(filters);
+ this.files = files;
+ this.parser = parser;
+ }
+
+ @Override
+ public MultipleObjectsBundle loadData() {
+ MultipleObjectsBundle objects = new MultipleObjectsBundle();
+ objects.appendColumn(TypeUtil.STRING, new ArrayList<Object>());
+ for(File file : files) {
+ String filestr = file.getPath();
+ try {
+ InputStream inputStream = new FileInputStream(file);
+ inputStream = FileUtil.tryGzipInput(inputStream);
+
+ final BundleStreamSource source;
+ if(parser instanceof StreamingParser) {
+ final StreamingParser streamParser = (StreamingParser) parser;
+ streamParser.initStream(inputStream);
+ source = streamParser;
+ }
+ else {
+ MultipleObjectsBundle parsingResult = parser.parse(inputStream);
+ // normalize objects and transform labels
+ source = new StreamFromBundle(parsingResult);
+ }
+ BundleMeta meta = null; // NullPointerException on invalid streams
+ loop: for(Event e = source.nextEvent();; e = source.nextEvent()) {
+ switch(e){
+ case END_OF_STREAM:
+ break loop;
+ case META_CHANGED:
+ meta = source.getMeta();
+ for(int i = 0; i < meta.size(); i++) {
+ if(i + 1 >= objects.metaLength()) {
+ objects.appendColumn(meta.get(i), new ArrayList<Object>());
+ }
+ else {
+ // Ensure compatibility:
+ if(!objects.meta(i + 1).isAssignableFromType(meta.get(i))) {
+ throw new AbortException("Incompatible files loaded. Cannot concatenate with unaligned columns, please preprocess manually.");
+ }
+ }
+ }
+ break;
+ case NEXT_OBJECT:
+ Object[] o = new Object[objects.metaLength()];
+ o[0] = filestr;
+ for(int i = 0; i < meta.size(); i++) {
+ o[i + 1] = source.data(i);
+ }
+ objects.appendSimple(o);
+ }
+ }
+ }
+ catch(IOException e) {
+ throw new AbortException("Loading file " + filestr + " failed: " + e.toString(), e);
+ }
+ }
+ // Invoke filters
+ if(logger.isDebugging()) {
+ logger.debugFine("Invoking filters.");
+ }
+ return invokeFilters(objects);
+ }
+
+ @Override
+ protected Logging getLogger() {
+ return logger;
+ }
+
+ /**
+ * Parameterization class
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractDatabaseConnection.Parameterizer {
+ /**
+ * The input files
+ */
+ private List<File> files;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ FileListParameter filesP = new FileListParameter(FileBasedDatabaseConnection.INPUT_ID, FilesType.INPUT_FILES);
+ if(config.grab(filesP)) {
+ files = filesP.getValue();
+ }
+ configParser(config, Parser.class, NumberVectorLabelParser.class);
+ super.makeOptions(config);
+ }
+
+ @Override
+ protected ConcatenateFilesDatabaseConnection makeInstance() {
+ return new ConcatenateFilesDatabaseConnection(files, parser, filters);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/DBIDRangeDatabaseConnection.java b/src/de/lmu/ifi/dbs/elki/datasource/DBIDRangeDatabaseConnection.java
new file mode 100644
index 00000000..05af3cad
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/datasource/DBIDRangeDatabaseConnection.java
@@ -0,0 +1,125 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.type.TypeUtil;
+import de.lmu.ifi.dbs.elki.database.ids.DBID;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+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.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;
+
+/**
+ * This is a fake datasource that produces a static DBID range only.
+ *
+ * This is useful when using e.g. a distance matrix to access external data.
+ *
+ * @author Erich Schubert
+ */
+@Description("This class generates a sequence of DBIDs to 'load' into a database. This is useful when using an external data matrix, and not requiring access to the actual vectors.")
+public class DBIDRangeDatabaseConnection implements DatabaseConnection {
+ /**
+ * Begin of interval
+ */
+ int start;
+
+ /**
+ * Number of records to produce
+ */
+ int count;
+
+ /**
+ * Constructor.
+ *
+ * @param start Starting ID
+ * @param count Number of records to produce
+ */
+ public DBIDRangeDatabaseConnection(int start, int count) {
+ super();
+ }
+
+ @Override
+ public MultipleObjectsBundle loadData() {
+ MultipleObjectsBundle b = new MultipleObjectsBundle();
+ List<DBID> ids = new ArrayList<DBID>(count);
+ for(int i = 0; i < count; i++) {
+ ids.add(DBIDUtil.importInteger(start + i));
+ }
+ b.appendColumn(TypeUtil.DBID, ids);
+ return b;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ /**
+ * Parameter for starting ID to generate
+ */
+ private static final OptionID START_ID = OptionID.getOrCreateOptionID("idgen.start", "First integer DBID to generate.");
+
+ /**
+ * Parameter for number of IDs to generate
+ */
+ private static final OptionID COUNT_ID = OptionID.getOrCreateOptionID("idgen.count", "Number of DBID to generate.");
+
+ /**
+ * Begin of interval
+ */
+ int start;
+
+ /**
+ * Number of records to produce
+ */
+ int count;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ IntParameter startp = new IntParameter(START_ID, 0);
+ if(config.grab(startp)) {
+ start = startp.getValue();
+ }
+ IntParameter countp = new IntParameter(COUNT_ID);
+ if(config.grab(countp)) {
+ count = countp.getValue();
+ }
+ }
+
+ @Override
+ protected Object makeInstance() {
+ return new DBIDRangeDatabaseConnection(start, count);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/DatabaseConnection.java b/src/de/lmu/ifi/dbs/elki/datasource/DatabaseConnection.java
index 72b54f27..7417b4d4 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) 2011
+ Copyright (C) 2012
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 1b04bafb..5a365119 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) 2011
+ Copyright (C) 2012
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 aa777ca1..0b81211b 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) 2011
+ Copyright (C) 2012
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/FileBasedDatabaseConnection.java b/src/de/lmu/ifi/dbs/elki/datasource/FileBasedDatabaseConnection.java
index 39c6d2a2..7973a6f0 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) 2011
+ Copyright (C) 2012
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 40e4d5af..5d3dbbf9 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/GeneratorXMLDatabaseConnection.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/GeneratorXMLDatabaseConnection.java
@@ -1,9 +1,10 @@
package de.lmu.ifi.dbs.elki.datasource;
+
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,7 +29,8 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
-import java.util.LinkedList;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Random;
import java.util.regex.Pattern;
@@ -47,13 +49,13 @@ import de.lmu.ifi.dbs.elki.application.GeneratorXMLSpec;
import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.GeneratorMain;
import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.GeneratorSingleCluster;
import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.GeneratorStatic;
-import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.distribution.Distribution;
-import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.distribution.GammaDistribution;
-import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.distribution.NormalDistribution;
-import de.lmu.ifi.dbs.elki.data.synthetic.bymodel.distribution.UniformDistribution;
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.Distribution;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.GammaDistribution;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.NormalDistribution;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.UniformDistribution;
import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
import de.lmu.ifi.dbs.elki.utilities.exceptions.UnableToComplyException;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
@@ -64,6 +66,14 @@ 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.xml.XMLNodeIterator;
+/**
+ * Data source from an XML specification.
+ *
+ * This data source will generate random (or pseudo-random, fixed seeds are
+ * supported) data sets that satisfy a given specification file.
+ *
+ * @author Erich Schubert
+ */
public class GeneratorXMLDatabaseConnection implements DatabaseConnection {
/**
* Logger
@@ -106,11 +116,6 @@ public class GeneratorXMLDatabaseConnection implements DatabaseConnection {
double sizescale = 1.0;
/**
- * The actual generator class
- */
- public GeneratorMain gen = new GeneratorMain();
-
- /**
* Random generator used for initializing cluster generators.
*/
private Random clusterRandom = null;
@@ -118,7 +123,7 @@ public class GeneratorXMLDatabaseConnection implements DatabaseConnection {
/**
* Set testAgainstModel flag
*/
- private boolean testAgainstModel = true;
+ private Boolean testAgainstModel;
/**
* Constructor.
@@ -142,8 +147,9 @@ public class GeneratorXMLDatabaseConnection implements DatabaseConnection {
if(logger.isVerbose()) {
logger.verbose("Loading specification ...");
}
+ GeneratorMain gen;
try {
- loadXMLSpecification();
+ gen = loadXMLSpecification();
}
catch(UnableToComplyException e) {
throw new AbortException("Cannot load XML specification", e);
@@ -151,10 +157,11 @@ public class GeneratorXMLDatabaseConnection implements DatabaseConnection {
if(logger.isVerbose()) {
logger.verbose("Generating clusters ...");
}
- gen.setTestAgainstModel(testAgainstModel);
+ if(testAgainstModel != null) {
+ gen.setTestAgainstModel(testAgainstModel);
+ }
try {
- gen.generate();
- return gen.getBundle();
+ return gen.generate();
}
catch(UnableToComplyException e) {
throw new AbortException("Data generation failed. ", e);
@@ -165,8 +172,10 @@ public class GeneratorXMLDatabaseConnection implements DatabaseConnection {
* Load the XML configuration file.
*
* @throws UnableToComplyException
+ *
+ * @return Generator
*/
- private void loadXMLSpecification() throws UnableToComplyException {
+ private GeneratorMain loadXMLSpecification() throws UnableToComplyException {
try {
InputStream in = new FileInputStream(specfile);
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
@@ -188,7 +197,9 @@ public class GeneratorXMLDatabaseConnection implements DatabaseConnection {
Document doc = dbf.newDocumentBuilder().parse(in);
Node root = doc.getDocumentElement();
if(root.getNodeName() == "dataset") {
- processElementDataset(root);
+ GeneratorMain gen = new GeneratorMain();
+ processElementDataset(gen, root);
+ return gen;
}
else {
throw new UnableToComplyException("Experiment specification has incorrect document element: " + root.getNodeName());
@@ -211,10 +222,11 @@ public class GeneratorXMLDatabaseConnection implements DatabaseConnection {
/**
* Process a 'dataset' Element in the XML stream.
*
+ * @param gen Generator
* @param cur Current document nod
* @throws UnableToComplyException
*/
- private void processElementDataset(Node cur) throws UnableToComplyException {
+ private void processElementDataset(GeneratorMain gen, Node cur) throws UnableToComplyException {
// *** get parameters
String seedstr = ((Element) cur).getAttribute("random-seed");
if(seedstr != null && seedstr != "") {
@@ -227,10 +239,10 @@ public class GeneratorXMLDatabaseConnection implements DatabaseConnection {
// TODO: check for unknown attributes.
for(Node child : new XMLNodeIterator(cur.getFirstChild())) {
if(child.getNodeName() == "cluster") {
- processElementCluster(child);
+ processElementCluster(gen, child);
}
else if(child.getNodeName() == "static") {
- processElementStatic(child);
+ processElementStatic(gen, child);
}
else if(child.getNodeType() == Node.ELEMENT_NODE) {
logger.warning("Unknown element in XML specification file: " + child.getNodeName());
@@ -241,10 +253,11 @@ public class GeneratorXMLDatabaseConnection implements DatabaseConnection {
/**
* Process a 'cluster' Element in the XML stream.
*
+ * @param gen Generator
* @param cur Current document nod
* @throws UnableToComplyException
*/
- private void processElementCluster(Node cur) throws UnableToComplyException {
+ private void processElementCluster(GeneratorMain gen, Node cur) throws UnableToComplyException {
int size = -1;
double overweight = 1.0;
@@ -257,7 +270,7 @@ public class GeneratorXMLDatabaseConnection implements DatabaseConnection {
String dcostr = ((Element) cur).getAttribute("density-correction");
if(dcostr != null && dcostr != "") {
- overweight = Double.valueOf(dcostr);
+ overweight = Double.parseDouble(dcostr);
}
if(size < 0) {
@@ -312,11 +325,11 @@ public class GeneratorXMLDatabaseConnection implements DatabaseConnection {
String minstr = ((Element) cur).getAttribute("min");
if(minstr != null && minstr != "") {
- min = Double.valueOf(minstr);
+ min = Double.parseDouble(minstr);
}
String maxstr = ((Element) cur).getAttribute("max");
if(maxstr != null && maxstr != "") {
- max = Double.valueOf(maxstr);
+ max = Double.parseDouble(maxstr);
}
// *** new uniform generator
@@ -344,11 +357,11 @@ public class GeneratorXMLDatabaseConnection implements DatabaseConnection {
double stddev = 1.0;
String meanstr = ((Element) cur).getAttribute("mean");
if(meanstr != null && meanstr != "") {
- mean = Double.valueOf(meanstr);
+ mean = Double.parseDouble(meanstr);
}
String stddevstr = ((Element) cur).getAttribute("stddev");
if(stddevstr != null && stddevstr != "") {
- stddev = Double.valueOf(stddevstr);
+ stddev = Double.parseDouble(stddevstr);
}
// *** New normal distribution generator
@@ -376,11 +389,11 @@ public class GeneratorXMLDatabaseConnection implements DatabaseConnection {
double theta = 1.0;
String kstr = ((Element) cur).getAttribute("k");
if(kstr != null && kstr != "") {
- k = Double.valueOf(kstr);
+ k = Double.parseDouble(kstr);
}
String thetastr = ((Element) cur).getAttribute("theta");
if(thetastr != null && thetastr != "") {
- theta = Double.valueOf(thetastr);
+ theta = Double.parseDouble(thetastr);
}
// *** New normal distribution generator
@@ -418,7 +431,7 @@ public class GeneratorXMLDatabaseConnection implements DatabaseConnection {
}
String anstr = ((Element) cur).getAttribute("angle");
if(anstr != null && anstr != "") {
- angle = Double.valueOf(anstr);
+ angle = Double.parseDouble(anstr);
}
if(axis1 <= 0 || axis1 > cluster.getDim()) {
throw new UnableToComplyException("Invalid axis1 number given in specification file.");
@@ -506,16 +519,17 @@ public class GeneratorXMLDatabaseConnection implements DatabaseConnection {
/**
* Process a 'static' cluster Element in the XML stream.
*
+ * @param gen Generator
* @param cur Current document nod
* @throws UnableToComplyException
*/
- private void processElementStatic(Node cur) throws UnableToComplyException {
+ private void processElementStatic(GeneratorMain gen, Node cur) throws UnableToComplyException {
String name = ((Element) cur).getAttribute("name");
if(name == null) {
throw new UnableToComplyException("No cluster name given in specification file.");
}
- LinkedList<Vector> points = new LinkedList<Vector>();
+ ArrayList<Vector> points = new ArrayList<Vector>();
// TODO: check for unknown attributes.
for(Node child : new XMLNodeIterator(cur.getFirstChild())) {
if(child.getNodeName() == "point") {
@@ -541,7 +555,7 @@ public class GeneratorXMLDatabaseConnection implements DatabaseConnection {
* @param cur Current document nod
* @throws UnableToComplyException
*/
- private void processElementPoint(LinkedList<Vector> points, Node cur) throws UnableToComplyException {
+ private void processElementPoint(List<Vector> points, Node cur) throws UnableToComplyException {
Vector point = null;
String vstr = ((Element) cur).getAttribute("vector");
if(vstr != null && vstr != "") {
@@ -576,7 +590,7 @@ public class GeneratorXMLDatabaseConnection implements DatabaseConnection {
double[] d = new double[entries.length];
for(int i = 0; i < entries.length; i++) {
try {
- d[i] = Double.valueOf(entries[i]);
+ d[i] = Double.parseDouble(entries[i]);
}
catch(NumberFormatException e) {
throw new UnableToComplyException("Could not parse vector.");
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/InputStreamDatabaseConnection.java b/src/de/lmu/ifi/dbs/elki/datasource/InputStreamDatabaseConnection.java
index d42f1eb8..9decd34b 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,14 +28,13 @@ import java.util.List;
import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle;
import de.lmu.ifi.dbs.elki.datasource.filter.ObjectFilter;
-import de.lmu.ifi.dbs.elki.datasource.parser.DoubleVectorLabelParser;
+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.utilities.documentation.Description;
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.parameterization.Parameterization;
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
/**
* Provides a database connection expecting input from an input stream such as
@@ -54,14 +53,6 @@ public class InputStreamDatabaseConnection extends AbstractDatabaseConnection {
private static final Logging logger = Logging.getLogger(InputStreamDatabaseConnection.class);
/**
- * Parameter to specify the parser to provide a database.
- * <p>
- * Key: {@code -dbc.parser}
- * </p>
- */
- public static final OptionID PARSER_ID = OptionID.getOrCreateOptionID("dbc.parser", "Parser to provide the database.");
-
- /**
* Holds the instance of the parser.
*/
Parser parser;
@@ -88,14 +79,27 @@ public class InputStreamDatabaseConnection extends AbstractDatabaseConnection {
if(logger.isDebugging()) {
logger.debugFine("Invoking parsers.");
}
- MultipleObjectsBundle parsingResult = parser.parse(in);
+ if(parser instanceof StreamingParser) {
+ final StreamingParser streamParser = (StreamingParser)parser;
+ streamParser.initStream(in);
- // normalize objects and transform labels
- if(logger.isDebugging()) {
- logger.debugFine("Invoking filters.");
+ // normalize objects and transform labels
+ if(logger.isDebugging()) {
+ logger.debugFine("Invoking filters.");
+ }
+ MultipleObjectsBundle objects = MultipleObjectsBundle.fromStream(invokeFilters(streamParser));
+ return objects;
+ }
+ else {
+ MultipleObjectsBundle parsingResult = parser.parse(in);
+
+ // normalize objects and transform labels
+ if(logger.isDebugging()) {
+ logger.debugFine("Invoking filters.");
+ }
+ MultipleObjectsBundle objects = invokeFilters(parsingResult);
+ return objects;
}
- MultipleObjectsBundle objects = invokeFilters(parsingResult);
- return objects;
}
@Override
@@ -111,22 +115,13 @@ public class InputStreamDatabaseConnection extends AbstractDatabaseConnection {
* @apiviz.exclude
*/
public static class Parameterizer extends AbstractDatabaseConnection.Parameterizer {
- Parser parser = null;
-
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- configParser(config, Parser.class, DoubleVectorLabelParser.class);
+ configParser(config, Parser.class, NumberVectorLabelParser.class);
configFilters(config);
}
- protected void configParser(Parameterization config, Class<?> parserRestrictionClass, Class<?> parserDefaultValueClass) {
- ObjectParameter<Parser> parserParam = new ObjectParameter<Parser>(PARSER_ID, parserRestrictionClass, parserDefaultValueClass);
- if(config.grab(parserParam)) {
- parser = parserParam.instantiateClass(config);
- }
- }
-
@Override
protected InputStreamDatabaseConnection makeInstance() {
return new InputStreamDatabaseConnection(filters, parser);
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/LabelJoinDatabaseConnection.java b/src/de/lmu/ifi/dbs/elki/datasource/LabelJoinDatabaseConnection.java
index b34566ae..7015bda9 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) 2011
+ Copyright (C) 2012
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/PresortedBlindJoinDatabaseConnection.java b/src/de/lmu/ifi/dbs/elki/datasource/PresortedBlindJoinDatabaseConnection.java
new file mode 100644
index 00000000..b5b59e40
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/datasource/PresortedBlindJoinDatabaseConnection.java
@@ -0,0 +1,128 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.datasource.bundle.MultipleObjectsBundle;
+import de.lmu.ifi.dbs.elki.datasource.filter.ObjectFilter;
+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.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;
+
+/**
+ * Joins multiple data sources by their existing order. Make sure the data
+ * sources are ordered appropriately!
+ *
+ * @author Erich Schubert
+ */
+@Description("Blindly joins multiple data sources, assuming they are ordered the same way.")
+public class PresortedBlindJoinDatabaseConnection extends AbstractDatabaseConnection implements Parameterizable {
+ /**
+ * Logger
+ */
+ private static final Logging logger = Logging.getLogger(PresortedBlindJoinDatabaseConnection.class);
+
+ /**
+ * The filters to invoke
+ */
+ final protected List<DatabaseConnection> sources;
+
+ /**
+ * Constructor.
+ *
+ * @param filters Filters to use.
+ * @param sources Data sources to join.
+ */
+ public PresortedBlindJoinDatabaseConnection(List<ObjectFilter> filters, List<DatabaseConnection> sources) {
+ super(filters);
+ this.sources = sources;
+ }
+
+ @Override
+ public MultipleObjectsBundle loadData() {
+ List<MultipleObjectsBundle> bundles = new ArrayList<MultipleObjectsBundle>(sources.size());
+ for(DatabaseConnection dbc : sources) {
+ bundles.add(dbc.loadData());
+ }
+
+ MultipleObjectsBundle first = bundles.get(0);
+ // Process additional columns
+ for(int c = 1; c < sources.size(); c++) {
+ MultipleObjectsBundle cur = bundles.get(c);
+ if(cur.dataLength() != first.dataLength()) {
+ throw new AbortException("Data set sizes do not agree - cannot join!");
+ }
+ for(int i = 0; i < cur.metaLength(); i++) {
+ first.appendColumn(cur.meta(i), cur.getColumn(i));
+ }
+ }
+
+ return first;
+ }
+
+ @Override
+ protected Logging getLogger() {
+ return logger;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractDatabaseConnection.Parameterizer {
+ /**
+ * The static option ID
+ */
+ public static final OptionID SOURCES_ID = OptionID.getOrCreateOptionID("join.sources", "The data sources to join.");
+
+ /**
+ * The data souces to use.
+ */
+ protected List<DatabaseConnection> sources;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ super.configFilters(config);
+ final ObjectListParameter<DatabaseConnection> sourcesParam = new ObjectListParameter<DatabaseConnection>(SOURCES_ID, DatabaseConnection.class);
+ if(config.grab(sourcesParam)) {
+ sources = sourcesParam.instantiateClasses(config);
+ }
+ }
+
+ @Override
+ protected PresortedBlindJoinDatabaseConnection makeInstance() {
+ return new PresortedBlindJoinDatabaseConnection(filters, sources);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/RandomDoubleVectorDatabaseConnection.java b/src/de/lmu/ifi/dbs/elki/datasource/RandomDoubleVectorDatabaseConnection.java
index 6e90af51..4cd626ee 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -76,10 +76,9 @@ public class RandomDoubleVectorDatabaseConnection extends AbstractDatabaseConnec
private static final Logging logger = Logging.getLogger(RandomDoubleVectorDatabaseConnection.class);
-
@Override
public MultipleObjectsBundle loadData() {
- VectorFieldTypeInformation<DoubleVector> type = new VectorFieldTypeInformation(DoubleVector.class, dim, new DoubleVector(new double[dim]));
+ VectorFieldTypeInformation<DoubleVector> type = new VectorFieldTypeInformation<DoubleVector>(DoubleVector.class, dim, DoubleVector.STATIC);
List<DoubleVector> vectors = new ArrayList<DoubleVector>(size);
// Setup random generator
@@ -178,4 +177,4 @@ public class RandomDoubleVectorDatabaseConnection extends AbstractDatabaseConnec
return new RandomDoubleVectorDatabaseConnection(dim, size, seed, filters);
}
}
-}
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/RandomDoubleVectorDatabaseConnection.java.rej b/src/de/lmu/ifi/dbs/elki/datasource/RandomDoubleVectorDatabaseConnection.java.rej
deleted file mode 100644
index d339c8ee..00000000
--- a/src/de/lmu/ifi/dbs/elki/datasource/RandomDoubleVectorDatabaseConnection.java.rej
+++ /dev/null
@@ -1,14 +0,0 @@
---- src/de/lmu/ifi/dbs/elki/datasource/RandomDoubleVectorDatabaseConnection.java (Revision 8763)
-+++ src/de/lmu/ifi/dbs/elki/datasource/RandomDoubleVectorDatabaseConnection.java (Revision 8764)
-@@ -76,10 +76,9 @@
-
- private static final Logging logger = Logging.getLogger(RandomDoubleVectorDatabaseConnection.class);
-
--
- @Override
- public MultipleObjectsBundle loadData() {
-- VectorFieldTypeInformation<DoubleVector> type = new VectorFieldTypeInformation<DoubleVector>(DoubleVector.class, DoubleVector.STATIC, dim);
-+ VectorFieldTypeInformation<DoubleVector> type = new VectorFieldTypeInformation<DoubleVector>(DoubleVector.class, dim, DoubleVector.STATIC);
- List<DoubleVector> vectors = new ArrayList<DoubleVector>(size);
-
- // Setup random generator
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 04934e8e..28354bd4 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) 2011
+ Copyright (C) 2012
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/BundleStreamSource.java b/src/de/lmu/ifi/dbs/elki/datasource/bundle/BundleStreamSource.java
new file mode 100644
index 00000000..8b831846
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/datasource/bundle/BundleStreamSource.java
@@ -0,0 +1,71 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Soruce for a bundle stream
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.composedOf BundleMeta
+ */
+public interface BundleStreamSource {
+ /**
+ * Events
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static enum Event {
+ // Metadata has changed
+ META_CHANGED,
+ // Next object available
+ NEXT_OBJECT,
+ // Stream ended
+ END_OF_STREAM,
+ };
+
+ /**
+ * Get the current meta data.
+ *
+ * @return Metadata
+ */
+ public BundleMeta getMeta();
+
+ /**
+ * Access a particular object and representation.
+ *
+ * @param rnum Representation number
+ * @return Contained data
+ */
+ public Object data(int rnum);
+
+ /**
+ * Get the next event
+ *
+ * @return Event type
+ */
+ public Event nextEvent();
+} \ No newline at end of file
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 cb78ed84..51107098 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,6 +27,8 @@ import java.util.ArrayList;
import java.util.List;
import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
+import de.lmu.ifi.dbs.elki.datasource.bundle.BundleStreamSource.Event;
+import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
/**
@@ -207,6 +209,48 @@ public class MultipleObjectsBundle implements ObjectBundle {
}
/**
+ * Convert an object stream to a bundle
+ *
+ * @param source Object stream
+ * @return Static bundle
+ */
+ public static MultipleObjectsBundle fromStream(BundleStreamSource source) {
+ MultipleObjectsBundle bundle = new MultipleObjectsBundle();
+ boolean stop = false;
+ while(!stop) {
+ Event ev = source.nextEvent();
+ switch(ev) {
+ case END_OF_STREAM:
+ stop = true;
+ break;
+ case META_CHANGED:
+ BundleMeta smeta = source.getMeta();
+ // rebuild bundle meta
+ bundle.meta = new BundleMeta();
+ for(int i = 0; i < bundle.columns.size(); i++) {
+ bundle.meta.add(smeta.get(i));
+ }
+ for(int i = bundle.metaLength(); i < smeta.size(); i++) {
+ List<Object> data = new ArrayList<Object>(bundle.dataLength() + 1);
+ bundle.appendColumn(smeta.get(i), data);
+ }
+ continue;
+ case NEXT_OBJECT:
+ for (int i = 0; i < bundle.metaLength(); i++) {
+ @SuppressWarnings("unchecked")
+ final List<Object> col = (List<Object>) bundle.columns.get(i);
+ col.add(source.data(i));
+ }
+ continue;
+ default:
+ LoggingUtil.warning("Unknown event: " + ev);
+ continue;
+ }
+ }
+ return bundle;
+ }
+
+ /**
* Get an object row.
*
* @param row Row number
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 2cb29ed1..56966dcf 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) 2011
+ Copyright (C) 2012
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 493aa53e..8a61426d 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) 2011
+ Copyright (C) 2012
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/StreamFromBundle.java b/src/de/lmu/ifi/dbs/elki/datasource/bundle/StreamFromBundle.java
new file mode 100644
index 00000000..971478da
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/datasource/bundle/StreamFromBundle.java
@@ -0,0 +1,73 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Convert a MultipleObjectsBundle to a stream
+ *
+ * @author Erich Schubert
+ */
+public class StreamFromBundle implements BundleStreamSource {
+ /**
+ * Bundle to access
+ */
+ MultipleObjectsBundle bundle;
+
+ /**
+ * Offset in bundle
+ */
+ int onum = -2;
+
+ /**
+ * Constructor.
+ *
+ * @param bundle Existing object bundle
+ */
+ public StreamFromBundle(MultipleObjectsBundle bundle) {
+ super();
+ this.bundle = bundle;
+ }
+
+ @Override
+ public BundleMeta getMeta() {
+ return bundle.meta();
+ }
+
+ @Override
+ public Object data(int rnum) {
+ return bundle.data(onum, rnum);
+ }
+
+ @Override
+ public Event nextEvent() {
+ onum += 1;
+ if(onum < 0) {
+ return Event.META_CHANGED;
+ }
+ if(onum >= bundle.dataLength()) {
+ return Event.END_OF_STREAM;
+ }
+ return Event.NEXT_OBJECT;
+ }
+} \ No newline at end of file
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 cfd41626..4be6fa79 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
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2011
+Copyright (C) 2012
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 990458bf..34fb6bad 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -65,10 +65,7 @@ public abstract class AbstractConversionFilter<I, O> implements ObjectFilter {
// Get the replacement type information
@SuppressWarnings("unchecked")
final SimpleTypeInformation<I> castType = (SimpleTypeInformation<I>) type;
- @SuppressWarnings("unchecked")
- final List<O> castColumn = (List<O>) column;
- bundle.appendColumn(convertedType(castType), castColumn);
-
+
// When necessary, perform an initialization scan
if(prepareStart(castType)) {
for(Object o : column) {
@@ -79,6 +76,10 @@ public abstract class AbstractConversionFilter<I, O> implements ObjectFilter {
prepareComplete();
}
+ @SuppressWarnings("unchecked")
+ final List<O> castColumn = (List<O>) column;
+ bundle.appendColumn(convertedType(castType), castColumn);
+
// Normalization scan
for(int i = 0; i < objects.dataLength(); i++) {
@SuppressWarnings("unchecked")
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractFeatureSelectionFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractFeatureSelectionFilter.java
index d53dfb94..009296b1 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractFeatureSelectionFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractFeatureSelectionFilter.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -45,7 +45,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntListParameter;
* @param <V> the type of FeatureVector contained in both the original and
* projected data.
*/
-public abstract class AbstractFeatureSelectionFilter<V extends FeatureVector<?, ?>> extends AbstractConversionFilter<V, V> {
+public abstract class AbstractFeatureSelectionFilter<V extends FeatureVector<?, ?>> extends AbstractStreamConversionFilter<V, V> {
/**
* <p>
* Selected attributes parameter.
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractRandomFeatureSelectionFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractRandomFeatureSelectionFilter.java
index 975d5bd5..b52c7887 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractRandomFeatureSelectionFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractRandomFeatureSelectionFilter.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -45,14 +45,13 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
*
* The cardinality of the subset of attributes is specified as a parameter.
*
- *
* @author Arthur Zimek
* @author Erich Schubert
*
* @param <V> the type of FeatureVector contained in both the original data of
* the base parser and the projected data of this ProjectionParser
*/
-public abstract class AbstractRandomFeatureSelectionFilter<V extends FeatureVector<?, ?>> extends AbstractConversionFilter<V, V> {
+public abstract class AbstractRandomFeatureSelectionFilter<V extends FeatureVector<?, ?>> extends AbstractStreamConversionFilter<V, V> {
/**
* The selected attributes
*/
@@ -94,13 +93,17 @@ public abstract class AbstractRandomFeatureSelectionFilter<V extends FeatureVect
super();
this.k = dim;
}
-
- @Override
- protected boolean prepareStart(SimpleTypeInformation<V> in) {
+
+ /**
+ * Initialize random attributes.
+ *
+ * Invoke this from {@link #convertedType}!
+ *
+ * @param in Type information.
+ */
+ void initializeRandomAttributes(SimpleTypeInformation<V> in) {
int d = ((VectorFieldTypeInformation<V>) in).dimensionality();
selectedAttributes = Util.randomBitSet(k, d, random);
- // We don't need the full loop, so return false.
- return false;
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractStreamConversionFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractStreamConversionFilter.java
new file mode 100644
index 00000000..1c8acb72
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractStreamConversionFilter.java
@@ -0,0 +1,117 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.datasource.bundle.BundleMeta;
+
+/**
+ * Abstract base class for simple conversion filters such as normalizations and
+ * projections.
+ *
+ * @author Erich Schubert
+ *
+ * @param <I> Input object type
+ * @param <O> Input object type
+ */
+public abstract class AbstractStreamConversionFilter<I, O> extends AbstractStreamFilter {
+ /**
+ * The filtered meta
+ */
+ BundleMeta meta;
+
+ /**
+ * The column to filter
+ */
+ int column = -1;
+
+ @Override
+ public BundleMeta getMeta() {
+ return meta;
+ }
+
+ @Override
+ public Object data(int rnum) {
+ if(rnum != column) {
+ return source.data(rnum);
+ }
+ // Convert:
+ @SuppressWarnings("unchecked")
+ final I obj = (I) source.data(rnum);
+ return filterSingleObject(obj);
+ }
+
+ @Override
+ public Event nextEvent() {
+ Event ev = source.nextEvent();
+ if(ev == Event.META_CHANGED) {
+ if(meta == null) {
+ meta = new BundleMeta();
+ }
+ BundleMeta origmeta = source.getMeta();
+ for(int i = meta.size(); i < origmeta.size(); i++) {
+ if(column < 0) {
+ @SuppressWarnings("unchecked")
+ SimpleTypeInformation<Object> type = (SimpleTypeInformation<Object>) origmeta.get(i);
+ // Test whether this type matches
+ if(getInputTypeRestriction().isAssignableFromType(type)) {
+ @SuppressWarnings("unchecked")
+ final SimpleTypeInformation<I> castType = (SimpleTypeInformation<I>) type;
+ meta.add(convertedType(castType));
+ column = i;
+ continue;
+ }
+ }
+ meta.add(origmeta.get(i));
+ }
+ }
+ return ev;
+ }
+
+ /**
+ * Normalize a single instance.
+ *
+ * You can implement this as UnsupportedOperationException if you override
+ * both public "normalize" functions!
+ *
+ * @param obj Database object to normalize
+ * @return Normalized database object
+ */
+ abstract protected O filterSingleObject(I obj);
+
+ /**
+ * Get the input type restriction used for negotiating the data query.
+ *
+ * @return Type restriction
+ */
+ abstract protected SimpleTypeInformation<? super I> getInputTypeRestriction();
+
+ /**
+ * Get the output type from the input type after conversion.
+ *
+ * @param in input type restriction
+ * @return output type restriction
+ */
+ abstract protected SimpleTypeInformation<? super O> convertedType(SimpleTypeInformation<I> in);
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractStreamFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractStreamFilter.java
new file mode 100644
index 00000000..368be1a2
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractStreamFilter.java
@@ -0,0 +1,50 @@
+package de.lmu.ifi.dbs.elki.datasource.filter;
+
+import de.lmu.ifi.dbs.elki.datasource.bundle.BundleStreamSource;
+import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle;
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You 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 streaming filters.
+ *
+ * @author Erich Schubert
+ */
+public abstract class AbstractStreamFilter implements StreamFilter {
+ /**
+ * Data source
+ */
+ protected BundleStreamSource source = null;
+
+ @Override
+ public MultipleObjectsBundle filter(MultipleObjectsBundle objects) {
+ init(new StreamFromBundle(objects));
+ return MultipleObjectsBundle.fromStream(this);
+ }
+
+ @Override
+ public void init(BundleStreamSource source) {
+ this.source = source;
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/FilterByLabelFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/ByLabelFilter.java
index b950080d..ebf01cfd 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/FilterByLabelFilter.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) 2011
+ Copyright (C) 2012
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.datasource.filter;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.ArrayList;
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.datasource.bundle.BundleMeta;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
@@ -43,79 +42,103 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.PatternParameter;
*
* @apiviz.uses LabelList oneway - - «reads»
*/
-public class FilterByLabelFilter implements ObjectFilter {
+public class ByLabelFilter extends AbstractStreamFilter {
/**
* Class logger
*/
- private static final Logging logger = Logging.getLogger(FilterByLabelFilter.class);
+ private static final Logging logger = Logging.getLogger(ByLabelFilter.class);
/**
* The filter pattern
*/
private final Pattern pattern;
-
+
/**
* Inversion flag
*/
private final boolean inverted;
/**
+ * Label column
+ */
+ private int lblcol = -1;
+
+ /**
* Constructor.
*
* @param pattern Filter pattern
* @param inverted Inversion flag
*/
- public FilterByLabelFilter(Pattern pattern, boolean inverted) {
+ public ByLabelFilter(Pattern pattern, boolean inverted) {
super();
this.pattern = pattern;
this.inverted = inverted;
}
@Override
- public MultipleObjectsBundle filter(final MultipleObjectsBundle objects) {
- if(logger.isDebugging()) {
- logger.debug("Filtering the data set");
- }
+ public BundleMeta getMeta() {
+ return source.getMeta();
+ }
- // Identify a label column
- final int lblcol;
- {
- int lblc = -1;
- for(int i = 0; i < objects.metaLength(); i++) {
- if(TypeUtil.GUESSED_LABEL.isAssignableFromType(objects.meta(i))) {
- lblc = i;
- break;
- }
- }
- lblcol = lblc; // make static
- }
+ @Override
+ public Object data(int rnum) {
+ return source.data(rnum);
+ }
- MultipleObjectsBundle bundle = new MultipleObjectsBundle();
- for(int j = 0; j < objects.metaLength(); j++) {
- bundle.appendColumn(objects.meta(j), new ArrayList<Object>());
- }
- for(int i = 0; i < objects.dataLength(); i++) {
- Object l = objects.data(i, lblcol);
- if(l instanceof LabelList) {
- boolean good = false;
- for(String label : (LabelList) l) {
- if(pattern.matcher(label).matches()) {
- good = true;
- break;
+ @Override
+ public Event nextEvent() {
+ while(true) {
+ Event ev = source.nextEvent();
+ switch(ev){
+ case END_OF_STREAM:
+ if (lblcol < 0) {
+ logger.warning("By label filter was used, but never saw a label relation!");
+ }
+ return Event.END_OF_STREAM;
+ case META_CHANGED:
+ // Search for the first label column
+ if(lblcol < 0) {
+ BundleMeta meta = source.getMeta();
+ for(int i = 0; i < meta.size(); i++) {
+ if(TypeUtil.GUESSED_LABEL.isAssignableFromType(meta.get(i))) {
+ lblcol = i;
+ break;
+ }
}
}
- if(good == inverted) {
- continue;
+ return Event.META_CHANGED;
+ case NEXT_OBJECT:
+ if(lblcol > 0) {
+ Object l = source.data(lblcol);
+ if(l instanceof LabelList) {
+ boolean good = false;
+ for(String label : (LabelList) l) {
+ if(pattern.matcher(label).matches()) {
+ good = true;
+ break;
+ }
+ }
+ if(good == inverted) {
+ continue;
+ }
+ }
+ else {
+ if(!pattern.matcher(l.toString()).matches()) {
+ continue;
+ }
+ }
}
- }
- else {
- if(!pattern.matcher(l.toString()).matches()) {
- continue;
+ else {
+ // No labels known yet.
+ if(!inverted) {
+ continue;
+ }
}
+ return Event.NEXT_OBJECT;
+ default:
+ logger.warning("Unknown event: " + ev);
}
- bundle.appendSimple(objects.getRow(i));
}
- return bundle;
}
/**
@@ -167,7 +190,7 @@ public class FilterByLabelFilter implements ObjectFilter {
@Override
protected Object makeInstance() {
- return new FilterByLabelFilter(pattern, inverted);
+ return new ByLabelFilter(pattern, inverted);
}
}
} \ No newline at end of file
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 1c9a2274..95596773 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) 2011
+ Copyright (C) 2012
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/DoubleVectorProjectionFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/DoubleVectorProjectionFilter.java
index 21b00b0d..4793b041 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/DoubleVectorProjectionFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/DoubleVectorProjectionFilter.java
@@ -3,7 +3,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) 2011
+Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -61,7 +61,7 @@ public class DoubleVectorProjectionFilter extends AbstractFeatureSelectionFilter
@Override
protected SimpleTypeInformation<? super DoubleVector> convertedType(SimpleTypeInformation<DoubleVector> in) {
- return new VectorFieldTypeInformation<DoubleVector>(DoubleVector.class, getDimensionality(), new DoubleVector(new double[getDimensionality()]));
+ return new VectorFieldTypeInformation<DoubleVector>(DoubleVector.class, DoubleVector.STATIC, getDimensionality(), DoubleVector.STATIC);
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/DoubleVectorRandomProjectionFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/DoubleVectorRandomProjectionFilter.java
index 802b00d6..5aa31967 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/DoubleVectorRandomProjectionFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/DoubleVectorRandomProjectionFilter.java
@@ -3,7 +3,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) 2011
+Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -61,7 +61,8 @@ public class DoubleVectorRandomProjectionFilter extends AbstractRandomFeatureSel
@Override
protected SimpleTypeInformation<? super DoubleVector> convertedType(SimpleTypeInformation<DoubleVector> in) {
- return new VectorFieldTypeInformation<DoubleVector>(DoubleVector.class, k, new DoubleVector(new double[k]));
+ initializeRandomAttributes(in);
+ return new VectorFieldTypeInformation<DoubleVector>(DoubleVector.class, DoubleVector.STATIC, k, DoubleVector.STATIC);
}
/**
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 c53c2e4d..f48810f5 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -48,7 +48,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
// TODO: use a non-string class for external ids?
public class ExternalIDFilter implements ObjectFilter {
/**
- * Optional parameter that specifies the index of the label to be used as
+ * Parameter that specifies the index of the label to be used as
* external Id, must be an integer equal to or greater than 0.
* <p>
* Key: {@code -dbc.externalIdIndex}
@@ -57,8 +57,7 @@ public class ExternalIDFilter implements ObjectFilter {
public static final OptionID EXTERNALID_INDEX_ID = OptionID.getOrCreateOptionID("dbc.externalIdIndex", "The index of the label to be used as external Id.");
/**
- * The index of the label to be used as external Id, null if no external id
- * index is specified.
+ * The index of the label to be used as external Id.
*/
private final int externalIdIndex;
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 b49494e4..c34ecbe7 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,13 +23,10 @@ package de.lmu.ifi.dbs.elki.datasource.filter;
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.type.TypeUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
-import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle;
+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;
@@ -43,7 +40,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
*
* @apiviz.has DBID oneway - - «produces»
*/
-public class FixedDBIDsFilter implements ObjectFilter {
+public class FixedDBIDsFilter extends AbstractStreamFilter {
/**
* Optional parameter to specify the first object ID to use.
* <p>
@@ -53,9 +50,14 @@ public class FixedDBIDsFilter implements ObjectFilter {
public static final OptionID IDSTART_ID = OptionID.getOrCreateOptionID("dbc.startid", "Object ID to start counting with");
/**
- * The first ID to assign
+ * The filtered meta
+ */
+ BundleMeta meta;
+
+ /**
+ * The next ID to assign
*/
- final int startid;
+ int curid = 0;
/**
* Constructor.
@@ -64,22 +66,39 @@ public class FixedDBIDsFilter implements ObjectFilter {
*/
public FixedDBIDsFilter(int startid) {
super();
- this.startid = startid;
+ this.curid = startid;
+ }
+
+ @Override
+ public BundleMeta getMeta() {
+ return meta;
}
@Override
- public MultipleObjectsBundle filter(MultipleObjectsBundle objects) {
- MultipleObjectsBundle bundle = new MultipleObjectsBundle();
- List<DBID> ids = new ArrayList<DBID>(objects.dataLength());
- for(int i = 0; i < objects.dataLength(); i++) {
- ids.add(DBIDUtil.importInteger(startid + i));
+ public Event nextEvent() {
+ Event ev = source.nextEvent();
+ if(ev == Event.META_CHANGED) {
+ if(meta == null) {
+ meta = new BundleMeta();
+ meta.add(TypeUtil.DBID);
+ }
+ BundleMeta origmeta = source.getMeta();
+ // Note -1 for the injected DBID column
+ for(int i = meta.size() - 1; i < origmeta.size(); i++) {
+ meta.add(origmeta.get(i));
+ }
}
- bundle.appendColumn(TypeUtil.DBID, ids);
- // copy other columns
- for(int j = 0; j < objects.metaLength(); j++) {
- bundle.appendColumn(objects.meta(j), objects.getColumn(j));
+ return ev;
+ }
+
+ @Override
+ public Object data(int rnum) {
+ if(rnum == 0) {
+ DBID ret = DBIDUtil.importInteger(curid);
+ curid++;
+ return ret;
}
- return bundle;
+ return source.data(rnum - 1);
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/FilterNoMissingValuesFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/NoMissingValuesFilter.java
index ceb671df..da5f066f 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/FilterNoMissingValuesFilter.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -34,16 +34,16 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
*
* @author Erich Schubert
*/
-public class FilterNoMissingValuesFilter implements ObjectFilter {
+public class NoMissingValuesFilter implements ObjectFilter {
/**
* Class logger
*/
- private static final Logging logger = Logging.getLogger(FilterNoMissingValuesFilter.class);
+ private static final Logging logger = Logging.getLogger(NoMissingValuesFilter.class);
/**
* Constructor.
*/
- public FilterNoMissingValuesFilter() {
+ public NoMissingValuesFilter() {
super();
}
@@ -82,7 +82,7 @@ public class FilterNoMissingValuesFilter implements ObjectFilter {
public static class Parameterizer extends AbstractParameterizer {
@Override
protected Object makeInstance() {
- return new FilterNoMissingValuesFilter();
+ return new NoMissingValuesFilter();
}
}
} \ No newline at end of file
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 9275c3c2..264f58fd 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) 2011
+ Copyright (C) 2012
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.datasource.filter;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import de.lmu.ifi.dbs.elki.datasource.bundle.BundleMeta;
import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle;
/**
@@ -34,7 +35,7 @@ import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle;
*
* @author Erich Schubert
*/
-public class NoOpFilter implements ObjectFilter {
+public class NoOpFilter extends AbstractStreamFilter {
/**
* Constructor.
*/
@@ -46,4 +47,19 @@ public class NoOpFilter implements ObjectFilter {
public MultipleObjectsBundle filter(MultipleObjectsBundle objects) {
return objects;
}
-}
+
+ @Override
+ public BundleMeta getMeta() {
+ return source.getMeta();
+ }
+
+ @Override
+ public Object data(int rnum) {
+ return source.data(rnum);
+ }
+
+ @Override
+ public Event nextEvent() {
+ return source.nextEvent();
+ }
+} \ No newline at end of file
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 1d5c2ba9..b3670e9b 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) 2011
+ Copyright (C) 2012
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.datasource.bundle.MultipleObjectsBundle;
+import de.lmu.ifi.dbs.elki.utilities.InspectionUtilFrequentlyScanned;
/**
* Object filters as part of the input step.
@@ -34,7 +35,7 @@ import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle;
*
* @apiviz.uses MultipleObjectsBundle oneway - - «filters»
*/
-public interface ObjectFilter {
+public interface ObjectFilter extends InspectionUtilFrequentlyScanned {
/**
* Filter a set of object packages.
*
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 6618721f..a8bf2cec 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -50,10 +50,10 @@ public class ShuffleObjectsFilter implements ObjectFilter {
* database. If unused, no shuffling will be performed. Shuffling takes time
* linearly dependent from the size of the database.
* <p>
- * Key: {@code -dbc.seed}
+ * Key: {@code -shuffle.seed}
* </p>
*/
- public static final OptionID SEED_ID = OptionID.getOrCreateOptionID("dbc.seed", "Seed for randomly shuffling the rows for the database. If the parameter is not set, no shuffling will be performed.");
+ public static final OptionID SEED_ID = OptionID.getOrCreateOptionID("shuffle.seed", "Seed for randomly shuffling the rows for the database. If the parameter is not set, no shuffling will be performed.");
/**
* Seed for randomly shuffling the rows of the database. If null, no shuffling
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 74bbe3ac..5aedc79c 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) 2011
+ Copyright (C) 2012
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/SparseFloatVectorProjectionFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/SparseFloatVectorProjectionFilter.java
index 7bbbab2d..06e686c3 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/SparseFloatVectorProjectionFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/SparseFloatVectorProjectionFilter.java
@@ -3,7 +3,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) 2011
+Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -22,9 +22,9 @@ You should 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.hash.TIntFloatHashMap;
+
import java.util.BitSet;
-import java.util.Collections;
-import java.util.Map;
import de.lmu.ifi.dbs.elki.data.SparseFloatVector;
import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
@@ -40,7 +40,6 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameteriz
* </p>
*
* @author Arthur Zimek
- *
*/
public class SparseFloatVectorProjectionFilter extends AbstractFeatureSelectionFilter<SparseFloatVector> {
/**
@@ -64,7 +63,7 @@ public class SparseFloatVectorProjectionFilter extends AbstractFeatureSelectionF
@Override
protected SimpleTypeInformation<? super SparseFloatVector> convertedType(SimpleTypeInformation<SparseFloatVector> in) {
- final Map<Integer, Float> emptyMap = Collections.emptyMap();
+ final TIntFloatHashMap emptyMap = new TIntFloatHashMap();
return new VectorFieldTypeInformation<SparseFloatVector>(SparseFloatVector.class, getDimensionality(), new SparseFloatVector(emptyMap, getDimensionality()));
}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/SparseFloatVectorRandomProjectionFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/SparseFloatVectorRandomProjectionFilter.java
index f8e999b9..fbf26eea 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/SparseFloatVectorRandomProjectionFilter.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/SparseFloatVectorRandomProjectionFilter.java
@@ -3,7 +3,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) 2011
+Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -22,9 +22,6 @@ You should 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.Map;
-
import de.lmu.ifi.dbs.elki.data.SparseFloatVector;
import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
@@ -60,8 +57,8 @@ public class SparseFloatVectorRandomProjectionFilter extends AbstractRandomFeatu
@Override
protected SimpleTypeInformation<? super SparseFloatVector> convertedType(SimpleTypeInformation<SparseFloatVector> in) {
- final Map<Integer, Float> emptyMap = Collections.emptyMap();
- return new VectorFieldTypeInformation<SparseFloatVector>(SparseFloatVector.class, k, new SparseFloatVector(emptyMap, k));
+ initializeRandomAttributes(in);
+ return new VectorFieldTypeInformation<SparseFloatVector>(SparseFloatVector.class, k, new SparseFloatVector(SparseFloatVector.EMPTYMAP, k));
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/SparseVectorFieldFilter.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/SparseVectorFieldFilter.java
new file mode 100644
index 00000000..482fc498
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/SparseVectorFieldFilter.java
@@ -0,0 +1,75 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.SparseFloatVector;
+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;
+
+/**
+ * Class that turns sparse float vectors into a proper vector field, by setting
+ * the maximum dimensionality for each vector.
+ *
+ * @author Erich Schubert
+ */
+public class SparseVectorFieldFilter extends AbstractConversionFilter<SparseFloatVector, SparseFloatVector> {
+ /**
+ * Maximum dimension
+ */
+ int maxdim = -1;
+
+ /**
+ * Constructor.
+ */
+ public SparseVectorFieldFilter() {
+ super();
+ }
+
+ @Override
+ protected boolean prepareStart(SimpleTypeInformation<SparseFloatVector> in) {
+ return true;
+ }
+
+ @Override
+ protected void prepareProcessInstance(SparseFloatVector obj) {
+ maxdim = Math.max(maxdim, obj.getDimensionality());
+ }
+
+ @Override
+ protected SparseFloatVector filterSingleObject(SparseFloatVector obj) {
+ assert(maxdim > 0);
+ obj.setDimensionality(maxdim);
+ return obj;
+ }
+
+ @Override
+ protected SimpleTypeInformation<? super SparseFloatVector> getInputTypeRestriction() {
+ return TypeUtil.SPARSE_FLOAT_FIELD;
+ }
+
+ @Override
+ protected SimpleTypeInformation<? super SparseFloatVector> convertedType(SimpleTypeInformation<SparseFloatVector> in) {
+ return new VectorFieldTypeInformation<SparseFloatVector>(SparseFloatVector.class, maxdim, SparseFloatVector.STATIC);
+ }
+} \ 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 25ab7e89..827a5011 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -82,8 +82,8 @@ public class SplitNumberVectorFilter<V extends NumberVector<V, ?>> implements Ob
final VectorFieldTypeInformation<V> vtype = VectorFieldTypeInformation.class.cast(type);
// Get the replacement type informations
- VectorFieldTypeInformation<V> type1 = new VectorFieldTypeInformation<V>(type.getRestrictionClass(), dims.length, dims.length);
- VectorFieldTypeInformation<V> type2 = new VectorFieldTypeInformation<V>(type.getRestrictionClass(), vtype.dimensionality() - dims.length, vtype.dimensionality() - dims.length);
+ VectorFieldTypeInformation<V> type1 = new VectorFieldTypeInformation<V>(type.getRestrictionClass(), type.getSerializer(), dims.length, dims.length);
+ VectorFieldTypeInformation<V> type2 = new VectorFieldTypeInformation<V>(type.getRestrictionClass(), type.getSerializer(), vtype.dimensionality() - dims.length, vtype.dimensionality() - dims.length);
final List<V> col1 = new ArrayList<V>(column.size());
final List<V> col2 = new ArrayList<V>(column.size());
bundle.appendColumn(type1, col1);
@@ -122,8 +122,8 @@ public class SplitNumberVectorFilter<V extends NumberVector<V, ?>> implements Ob
for(int d = 0; d < odims.length; d++) {
part2[d] = obj.doubleValue(odims[d]);
}
- col1.add(obj.newInstance(part1));
- col2.add(obj.newInstance(part2));
+ col1.add(obj.newNumberVector(part1));
+ col2.add(obj.newNumberVector(part2));
}
}
return bundle;
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/events/ResizedEvent.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/StreamFilter.java
index 6eb6cad3..e40565f9 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/events/ResizedEvent.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/StreamFilter.java
@@ -1,10 +1,12 @@
-package de.lmu.ifi.dbs.elki.visualization.visualizers.events;
+package de.lmu.ifi.dbs.elki.datasource.filter;
+
+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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,27 +25,19 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.events;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import de.lmu.ifi.dbs.elki.visualization.VisualizerContext;
-
/**
- * Event triggered when the contexts view was resized.
+ * Streaming filters are often more efficient (less memory use) and can be used
+ * in more settings.
*
* @author Erich Schubert
*
- * @apiviz.stereotype event
+ * @apiviz.uses BundleStreamSource - - «filters»
*/
-public class ResizedEvent extends ContextChangedEvent {
- /**
- * Serial version
- */
- private static final long serialVersionUID = 1L;
-
+public interface StreamFilter extends ObjectFilter, BundleStreamSource {
/**
- * Constructor.
+ * Connect to the previous stream.
*
- * @param source Visualization context
+ * @param source Stream source
*/
- public ResizedEvent(VisualizerContext source) {
- super(source);
- }
+ public void init(BundleStreamSource source);
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractNormalization.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AbstractNormalization.java
index ae75a979..3a629760 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/AbstractNormalization.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AbstractNormalization.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.datasource.filter;
+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) 2011
+ Copyright (C) 2012
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.datasource.filter;
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.AbstractConversionFilter;
import de.lmu.ifi.dbs.elki.math.linearalgebra.LinearEquationSystem;
/**
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/AttributeWiseErfNormalization.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AttributeWiseErfNormalization.java
index d365a9ae..c0f2a955 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/AttributeWiseErfNormalization.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AttributeWiseErfNormalization.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.datasource.filter;
+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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,7 +26,7 @@ package de.lmu.ifi.dbs.elki.datasource.filter;
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.math.MathUtil;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.NormalDistribution;
/**
* Attribute-wise Normalization using the error function. This mostly makes
@@ -55,9 +55,9 @@ public class AttributeWiseErfNormalization<O extends NumberVector<O, ?>> extends
protected O filterSingleObject(O obj) {
double[] val = new double[obj.getDimensionality()];
for(int i = 0; i < val.length; i++) {
- val[i] = MathUtil.erf(obj.doubleValue(i + 1));
+ val[i] = NormalDistribution.erf(obj.doubleValue(i + 1));
}
- return obj.newInstance(val);
+ return obj.newNumberVector(val);
}
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/AttributeWiseMinMaxNormalization.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AttributeWiseMinMaxNormalization.java
index d9a636ec..4cf3c606 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/AttributeWiseMinMaxNormalization.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AttributeWiseMinMaxNormalization.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.datasource.filter;
+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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,14 +24,13 @@ package de.lmu.ifi.dbs.elki.datasource.filter;
*/
import java.util.ArrayList;
-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.math.linearalgebra.LinearEquationSystem;
import de.lmu.ifi.dbs.elki.utilities.FormatUtil;
-import de.lmu.ifi.dbs.elki.utilities.Util;
+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.AllOrNoneMustBeSetGlobalConstraint;
@@ -118,10 +117,13 @@ public class AttributeWiseMinMaxNormalization<V extends NumberVector<V, ?>> exte
@Override
protected V filterSingleObject(V featureVector) {
double[] values = new double[featureVector.getDimensionality()];
+ if(minima.length != featureVector.getDimensionality()) {
+ throw new IllegalArgumentException("FeatureVectors and given Minima/Maxima differ in length.");
+ }
for(int d = 1; d <= featureVector.getDimensionality(); d++) {
values[d - 1] = (featureVector.doubleValue(d) - minima[d - 1]) / factor(d);
}
- return featureVector.newInstance(values);
+ return featureVector.newNumberVector(values);
}
@Override
@@ -131,7 +133,7 @@ public class AttributeWiseMinMaxNormalization<V extends NumberVector<V, ?>> exte
for(int d = 1; d <= featureVector.getDimensionality(); d++) {
values[d - 1] = (featureVector.doubleValue(d) * (factor(d)) + minima[d - 1]);
}
- return featureVector.newInstance(values);
+ return featureVector.newNumberVector(values);
}
else {
throw new NonNumericFeaturesException("Attributes cannot be resized: current dimensionality: " + featureVector.getDimensionality() + " former dimensionality: " + maxima.length);
@@ -214,13 +216,11 @@ public class AttributeWiseMinMaxNormalization<V extends NumberVector<V, ?>> exte
super.makeOptions(config);
DoubleListParameter minimaP = new DoubleListParameter(MINIMA_ID, true);
if(config.grab(minimaP)) {
- List<Double> min_list = minimaP.getValue();
- minima = Util.unbox(min_list.toArray(new Double[min_list.size()]));
+ minima = ArrayLikeUtil.toPrimitiveDoubleArray(minimaP.getValue());
}
DoubleListParameter maximaP = new DoubleListParameter(MAXIMA_ID, true);
if(config.grab(maximaP)) {
- List<Double> max_list = maximaP.getValue();
- maxima = Util.unbox(max_list.toArray(new Double[max_list.size()]));
+ maxima = ArrayLikeUtil.toPrimitiveDoubleArray(maximaP.getValue());
}
ArrayList<Parameter<?, ?>> global_1 = new ArrayList<Parameter<?, ?>>();
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/AttributeWiseVarianceNormalization.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AttributeWiseVarianceNormalization.java
index 3ae2fdad..52a0499f 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/AttributeWiseVarianceNormalization.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/AttributeWiseVarianceNormalization.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.datasource.filter;
+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) 2011
+ Copyright (C) 2012
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 java.util.ArrayList;
-import java.util.List;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
@@ -33,7 +32,7 @@ import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.math.MeanVariance;
import de.lmu.ifi.dbs.elki.math.linearalgebra.LinearEquationSystem;
import de.lmu.ifi.dbs.elki.utilities.FormatUtil;
-import de.lmu.ifi.dbs.elki.utilities.Util;
+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.WrongParameterValueException;
@@ -145,7 +144,7 @@ public class AttributeWiseVarianceNormalization<V extends NumberVector<V, ?>> ex
for(int d = 1; d <= featureVector.getDimensionality(); d++) {
values[d - 1] = normalize(d - 1, featureVector.doubleValue(d));
}
- return featureVector.newInstance(values);
+ return featureVector.newNumberVector(values);
}
@Override
@@ -155,7 +154,7 @@ public class AttributeWiseVarianceNormalization<V extends NumberVector<V, ?>> ex
for(int d = 1; d <= featureVector.getDimensionality(); d++) {
values[d - 1] = restore(d - 1, featureVector.doubleValue(d));
}
- return featureVector.newInstance(values);
+ return featureVector.newNumberVector(values);
}
else {
throw new NonNumericFeaturesException("Attributes cannot be resized: current dimensionality: " + featureVector.getDimensionality() + " former dimensionality: " + mean.length);
@@ -163,11 +162,21 @@ public class AttributeWiseVarianceNormalization<V extends NumberVector<V, ?>> ex
}
private double normalize(int d, double val) {
- return (val - mean[d]) / stddev[d];
+ if(mean.length == 1) {
+ return (val - mean[0]) / stddev[0];
+ }
+ else {
+ return (val - mean[d]) / stddev[d];
+ }
}
private double restore(int d, double val) {
- return (val * stddev[d]) + mean[d];
+ if(mean.length == 1) {
+ return (val * stddev[0]) + mean[0];
+ }
+ else {
+ return (val * stddev[d]) + mean[d];
+ }
}
@Override
@@ -236,11 +245,8 @@ public class AttributeWiseVarianceNormalization<V extends NumberVector<V, ?>> ex
config.grab(stddevP);
// Note: grab first, then use isDefined, to ensure the stddev is grabbed.
if(meanP.isDefined() && stddevP.isDefined()) {
- List<Double> mean_list = meanP.getValue();
- List<Double> stddev_list = stddevP.getValue();
-
- mean = Util.unbox(mean_list.toArray(new Double[mean_list.size()]));
- stddev = Util.unbox(stddev_list.toArray(new Double[stddev_list.size()]));
+ mean = ArrayLikeUtil.toPrimitiveDoubleArray(meanP.getValue());
+ stddev = ArrayLikeUtil.toPrimitiveDoubleArray(stddevP.getValue());
for(double d : stddev) {
if(d == 0) {
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/InverseDocumentFrequencyNormalization.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/InverseDocumentFrequencyNormalization.java
index d8ffd71c..41cce2b9 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/InverseDocumentFrequencyNormalization.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/InverseDocumentFrequencyNormalization.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.datasource.filter;
+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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,10 +23,12 @@ package de.lmu.ifi.dbs.elki.datasource.filter;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import gnu.trove.iterator.TIntDoubleIterator;
+import gnu.trove.map.TIntDoubleMap;
+import gnu.trove.map.hash.TIntDoubleHashMap;
+import gnu.trove.map.hash.TIntFloatHashMap;
+
import java.util.BitSet;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
import de.lmu.ifi.dbs.elki.data.SparseFloatVector;
import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
@@ -44,7 +46,7 @@ public class InverseDocumentFrequencyNormalization extends AbstractNormalization
/**
* The IDF storage
*/
- Map<Integer, Number> idf = new HashMap<Integer, Number>();
+ TIntDoubleMap idf = new TIntDoubleHashMap();
/**
* The number of objects in the dataset
@@ -88,18 +90,19 @@ public class InverseDocumentFrequencyNormalization extends AbstractNormalization
protected void prepareComplete() {
final double dbsize = objcnt;
// Compute IDF values
- for(Entry<Integer, Number> ent : idf.entrySet()) {
+ for(TIntDoubleIterator iter = idf.iterator(); iter.hasNext();) {
+ iter.advance();
// Note: dbsize is a double!
- ent.setValue(Math.log(dbsize / ent.getValue().intValue()));
+ iter.setValue(Math.log(dbsize / iter.value()));
}
}
@Override
protected SparseFloatVector filterSingleObject(SparseFloatVector featureVector) {
BitSet b = featureVector.getNotNullMask();
- Map<Integer, Float> vals = new HashMap<Integer, Float>();
+ TIntFloatHashMap vals = new TIntFloatHashMap();
for(int i = b.nextSetBit(0); i >= 0; i = b.nextSetBit(i + 1)) {
- vals.put(i, (float) (featureVector.doubleValue(i) * idf.get(i).doubleValue()));
+ vals.put(i, (float) (featureVector.doubleValue(i) * idf.get(i)));
}
return new SparseFloatVector(vals, featureVector.getDimensionality());
}
@@ -107,9 +110,9 @@ public class InverseDocumentFrequencyNormalization extends AbstractNormalization
@Override
public SparseFloatVector restore(SparseFloatVector featureVector) {
BitSet b = featureVector.getNotNullMask();
- Map<Integer, Float> vals = new HashMap<Integer, Float>();
+ TIntFloatHashMap vals = new TIntFloatHashMap();
for(int i = b.nextSetBit(0); i >= 0; i = b.nextSetBit(i + 1)) {
- vals.put(i, (float) (featureVector.doubleValue(i) / idf.get(i).doubleValue()));
+ vals.put(i, (float) (featureVector.doubleValue(i) / idf.get(i)));
}
return new SparseFloatVector(vals, featureVector.getDimensionality());
}
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
new file mode 100644
index 00000000..6de7eaba
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/LengthNormalization.java
@@ -0,0 +1,115 @@
+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) 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.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.math.linearalgebra.LinearEquationSystem;
+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;
+
+/**
+ * Class to perform a normalization on vectors to norm 1.
+ *
+ * @author Heidi Kolb
+ * @author Erich Schubert
+ *
+ * @param <V> vector type
+ */
+public class LengthNormalization<V extends NumberVector<V, ?>> extends AbstractNormalization<V> {
+ /**
+ * Norm to use
+ */
+ DoubleNorm<? super V> norm;
+
+ /**
+ * Constructor
+ *
+ * @param norm Norm to use
+ */
+ public LengthNormalization(DoubleNorm<? super V> norm) {
+ super();
+ this.norm = norm;
+ }
+
+ @Override
+ protected V filterSingleObject(V featureVector) {
+ final double d = norm.doubleNorm(featureVector);
+ return featureVector.newNumberVector(featureVector.getColumnVector().timesEquals(1 / d).getArrayRef());
+ }
+
+ @Override
+ public V restore(V featureVector) throws NonNumericFeaturesException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public LinearEquationSystem transform(LinearEquationSystem linearEquationSystem) {
+ // TODO.
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected SimpleTypeInformation<? super V> getInputTypeRestriction() {
+ return TypeUtil.NUMBER_VECTOR_FIELD;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer<V extends NumberVector<V, ?>> extends AbstractParameterizer {
+ /**
+ * Option ID for normalization norm
+ */
+ public static final OptionID NORM_ID = OptionID.getOrCreateOptionID("normalization.norm", "Norm (length function) to use for computing the vector length.");
+
+ /**
+ * Norm to use
+ */
+ DoubleNorm<? super V> norm;
+
+ @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);
+ if(config.grab(normP)) {
+ norm = normP.instantiateClass(config);
+ }
+ }
+
+ @Override
+ protected LengthNormalization<V> makeInstance() {
+ return new LengthNormalization<V>(norm);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/NonNumericFeaturesException.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/NonNumericFeaturesException.java
index 3206518d..9f26482a 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/NonNumericFeaturesException.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/NonNumericFeaturesException.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.datasource.filter;
+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) 2011
+ Copyright (C) 2012
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.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/Normalization.java
index 417c4456..96f6bdc1 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/Normalization.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/Normalization.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.datasource.filter;
+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) 2011
+ Copyright (C) 2012
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.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;
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
new file mode 100644
index 00000000..be8c1166
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/RankTieNormalization.java
@@ -0,0 +1,113 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.IntegerVector;
+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.ObjectFilter;
+import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleIntPair;
+
+/**
+ * Normalize vectors according to their rank in the attributes.
+ *
+ * Note: ranks are multiplied by 2, to be able to give ties an integer rank.
+ * (e.g. first two records are tied at "1" then, followed by the next on "4")
+ *
+ * @author Erich Schubert
+ */
+public class RankTieNormalization implements ObjectFilter {
+ /**
+ * Constructor.
+ */
+ public RankTieNormalization() {
+ super();
+ }
+
+ @Override
+ public MultipleObjectsBundle filter(MultipleObjectsBundle objects) {
+ final int len = objects.dataLength();
+ MultipleObjectsBundle bundle = new MultipleObjectsBundle();
+
+ for(int r = 0; r < objects.metaLength(); r++) {
+ final SimpleTypeInformation<?> type = objects.meta(r);
+ final List<?> column = objects.getColumn(r);
+ if(!TypeUtil.NUMBER_VECTOR_FIELD.isAssignableFromType(type)) {
+ bundle.appendColumn(type, column);
+ continue;
+ }
+ @SuppressWarnings("unchecked")
+ final List<? extends NumberVector<?, ?>> castColumn = (List<? extends NumberVector<?, ?>>) column;
+ // Get the replacement type information
+ final int dim = ((VectorFieldTypeInformation<?>) type).dimensionality();
+ final VectorFieldTypeInformation<IntegerVector> outType = new VectorFieldTypeInformation<IntegerVector>(IntegerVector.class, dim, IntegerVector.STATIC);
+
+ // Output vectors
+ int[][] posvecs = new int[len][dim];
+ // Sort for each dimension
+ // TODO: an int[] array would be enough, if we could use a comparator...
+ DoubleIntPair[] sorter = new DoubleIntPair[len];
+ for(int i = 0; i < sorter.length; i++) {
+ sorter[i] = new DoubleIntPair(Double.NaN, -1);
+ }
+ for(int d = 1; d <= dim; d++) {
+ // fill array
+ for(int i = 0; i < sorter.length; i++) {
+ sorter[i].first = castColumn.get(i).doubleValue(d);
+ sorter[i].second = i;
+ }
+ // Sort
+ Arrays.sort(sorter);
+ // Transfer positions to output vectors
+ for(int sta = 0; sta < sorter.length;) {
+ // Compute ties
+ int end = sta + 1;
+ while(end < sorter.length && sorter[sta].first == sorter[end].first) {
+ end++;
+ }
+ final int pos = (sta + end - 1);
+ for(int i = sta; i < end; i++) {
+ posvecs[sorter[i].second][d - 1] = pos;
+ }
+ sta = end;
+ }
+ }
+
+ // Prepare output data
+ final List<IntegerVector> outColumn = new ArrayList<IntegerVector>(len);
+ for(int i = 0; i < len; i++) {
+ outColumn.add(new IntegerVector(posvecs[i]));
+ }
+ bundle.appendColumn(outType, outColumn);
+ }
+ return bundle;
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/filter/TFIDFNormalization.java b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/TFIDFNormalization.java
index 65fab4cb..e279c42c 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/filter/TFIDFNormalization.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/TFIDFNormalization.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.datasource.filter;
+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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,9 +23,9 @@ package de.lmu.ifi.dbs.elki.datasource.filter;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import gnu.trove.map.hash.TIntFloatHashMap;
+
import java.util.BitSet;
-import java.util.HashMap;
-import java.util.Map;
import de.lmu.ifi.dbs.elki.data.SparseFloatVector;
@@ -58,9 +58,9 @@ public class TFIDFNormalization extends InverseDocumentFrequencyNormalization {
if(sum <= 0) {
sum = 1.0;
}
- Map<Integer, Float> vals = new HashMap<Integer, Float>();
+ TIntFloatHashMap vals = new TIntFloatHashMap();
for(int i = b.nextSetBit(0); i >= 0; i = b.nextSetBit(i + 1)) {
- vals.put(i, (float) (featureVector.doubleValue(i) / sum * idf.get(i).doubleValue()));
+ vals.put(i, (float) (featureVector.doubleValue(i) / sum * idf.get(i)));
}
return new SparseFloatVector(vals, featureVector.getDimensionality());
}
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
new file mode 100644
index 00000000..c0c10a7c
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/datasource/filter/normalization/package-info.java
@@ -0,0 +1,26 @@
+/**
+ * <p>Data normalization.</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.datasource.filter.normalization; \ No newline at end of file
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 0379c7aa..ca52f814 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
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2011
+Copyright (C) 2012
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 541a78e3..8aba2d30 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) 2011
+Copyright (C) 2012
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 e3bd77a0..dcfb8245 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -54,7 +54,7 @@ public abstract class AbstractParser {
public static final String QUOTE_CHAR = "\"";
/**
- * A pattern catching most numbers that can be parsed using Double.valueOf:
+ * 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>
@@ -124,7 +124,9 @@ public abstract class AbstractParser {
// Closing quote found?
if(m.start() > index + 1 && input.charAt(m.start() - 1) == quoteChar) {
// Strip quote characters
- matchList.add(input.subSequence(index + 1, m.start() - 1).toString());
+ if (index + 1 < m.start() - 1) {
+ matchList.add(input.substring(index + 1, m.start() - 1));
+ }
// Seek past
index = m.end();
// new quote?
@@ -133,7 +135,9 @@ public abstract class AbstractParser {
}
else {
// Add match before separator
- matchList.add(input.subSequence(index, m.start()).toString());
+ if (index < m.start()) {
+ matchList.add(input.substring(index, m.start()));
+ }
// Seek past separator
index = m.end();
// new quote?
@@ -148,15 +152,21 @@ public abstract class AbstractParser {
// Add tail after last separator.
if(inquote) {
if(input.charAt(input.length() - 1) == quoteChar) {
- matchList.add(input.subSequence(index + 1, input.length() - 1).toString());
+ if (index + 1 < input.length() - 1) {
+ matchList.add(input.substring(index + 1, input.length() - 1));
+ }
}
else {
getLogger().warning("Invalid quoted line in input.");
- matchList.add(input.subSequence(index, input.length()).toString());
+ if (index < input.length()) {
+ matchList.add(input.substring(index, input.length()));
+ }
}
}
else {
- matchList.add(input.subSequence(index, input.length()).toString());
+ if (index < input.length()) {
+ matchList.add(input.substring(index, input.length()));
+ }
}
// Return
return matchList;
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/parser/AbstractStreamingParser.java b/src/de/lmu/ifi/dbs/elki/datasource/parser/AbstractStreamingParser.java
new file mode 100644
index 00000000..79f17326
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/datasource/parser/AbstractStreamingParser.java
@@ -0,0 +1,51 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+/**
+ * Base class for streaming parsers.
+ *
+ * @author Erich Schubert
+ */
+public abstract class AbstractStreamingParser extends AbstractParser implements StreamingParser {
+ /**
+ * Constructor.
+ *
+ * @param colSep Column separator pattern
+ * @param quoteChar Quote character
+ */
+ public AbstractStreamingParser(Pattern colSep, char quoteChar) {
+ super(colSep, quoteChar);
+ }
+
+ @Override
+ final public MultipleObjectsBundle parse(InputStream in) {
+ 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 847349f2..9d77b921 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,17 +23,16 @@ package de.lmu.ifi.dbs.elki.datasource.parser;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import gnu.trove.iterator.TIntObjectIterator;
+import gnu.trove.map.hash.TIntFloatHashMap;
+import gnu.trove.map.hash.TIntObjectHashMap;
+
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -61,7 +60,7 @@ 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 supported.
+ * TODO: Sparse vectors are not yet fully supported.
*
* @author Erich Schubert
*/
@@ -94,7 +93,7 @@ public class ArffParser implements Parser {
/**
* Pattern to auto-convert columns to external ids.
*/
- public static final String DEFAULT_ARFF_MAGIC_EID = "(ID|External-?ID)";
+ public static final String DEFAULT_ARFF_MAGIC_EID = "(External-?ID)";
/**
* Pattern to auto-convert columns to class labels.
@@ -206,7 +205,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.");
- Map<Integer, Object> map = new TreeMap<Integer, Object>();
+ TIntObjectHashMap<Object> map = new TIntObjectHashMap<Object>();
while(true) {
nextToken(tokenizer);
assert (tokenizer.ttype != StreamTokenizer.TT_EOF && tokenizer.ttype != StreamTokenizer.TT_EOL);
@@ -248,32 +247,34 @@ public class ArffParser implements Parser {
}
assert (s >= 0);
if(elkitypes[out] == TypeUtil.NUMBER_VECTOR_FIELD) {
- Map<Integer, Float> f = new HashMap<Integer, Float>(dimsize[out]);
- for(Entry<Integer, Object> key : map.entrySet()) {
- int i = key.getKey();
+ TIntFloatHashMap f = new TIntFloatHashMap(dimsize[out]);
+ for(TIntObjectIterator<Object> iter = map.iterator(); iter.hasNext();) {
+ iter.advance();
+ int i = iter.key();
if(i < s) {
continue;
}
if(i >= s + dimsize[out]) {
break;
}
- double v = (Double) key.getValue();
+ double v = (Double) iter.value();
f.put(i - s + 1, (float) v);
}
data[out] = new SparseFloatVector(f, dimsize[out]);
}
else if(elkitypes[out] == TypeUtil.LABELLIST) {
// Build a label list out of successive labels
- LabelList ll = new LabelList();
- for(Entry<Integer, Object> key : map.entrySet()) {
- int i = key.getKey();
+ LabelList ll = new LabelList(1);
+ for(TIntObjectIterator<Object> iter = map.iterator(); iter.hasNext();) {
+ iter.advance();
+ int i = iter.key();
if(i < s) {
continue;
}
if(i >= s + dimsize[out]) {
break;
}
- String v = (String) key.getValue();
+ String v = (String) iter.value();
if(ll.size() < i - s) {
logger.warning("Sparse consecutive labels are currently not correctly supported.");
}
@@ -309,24 +310,33 @@ public class ArffParser implements Parser {
}
private Object[] loadDenseInstance(StreamTokenizer tokenizer, int[] dimsize, TypeInformation[] etyp, int outdim) throws IOException {
- // logger.warning("Regular instance.");
Object[] data = new Object[outdim];
for(int out = 0; out < outdim; out++) {
if(etyp[out] == TypeUtil.NUMBER_VECTOR_FIELD) {
// For multi-column vectors, read successive columns
double[] cur = new double[dimsize[out]];
for(int k = 0; k < dimsize[out]; k++) {
- if(tokenizer.ttype != StreamTokenizer.TT_NUMBER) {
+ if(tokenizer.ttype == '?') {
+ tokenizer.nval = Double.NaN;
+ }
+ else if(tokenizer.ttype == StreamTokenizer.TT_WORD) {
+ try {
+ cur[k] = Double.parseDouble(tokenizer.sval);
+ }
+ catch(NumberFormatException e) {
+ throw new AbortException("Expected number value, got: " + tokenizer.sval);
+ }
+ }
+ else {
throw new AbortException("Expected word token, got: " + tokenizer.toString());
}
- cur[k] = tokenizer.nval;
nextToken(tokenizer);
}
data[out] = new DoubleVector(cur);
}
else if(etyp[out] == TypeUtil.LABELLIST) {
// Build a label list out of successive labels
- LabelList ll = new LabelList();
+ LabelList ll = new LabelList(dimsize[out]);
for(int k = 0; k < dimsize[out]; k++) {
if(tokenizer.ttype != StreamTokenizer.TT_WORD) {
throw new AbortException("Expected word token, got: " + tokenizer.toString());
@@ -369,7 +379,11 @@ public class ArffParser implements Parser {
// Setup tokenizer
StreamTokenizer tokenizer = new StreamTokenizer(br);
{
+ tokenizer.resetSyntax();
tokenizer.whitespaceChars(0, ' ');
+ tokenizer.ordinaryChars('0', '9');
+ tokenizer.ordinaryChar('-');
+ tokenizer.ordinaryChar('.');
tokenizer.wordChars(' ' + 1, '\u00FF');
tokenizer.whitespaceChars(',', ',');
tokenizer.commentChar('%');
@@ -407,12 +421,11 @@ public class ArffParser implements Parser {
labels[i] = names.get(out + i);
}
if(!sparse) {
- VectorFieldTypeInformation<DoubleVector> type = new VectorFieldTypeInformation<DoubleVector>(DoubleVector.class, dimsize[out], labels, new DoubleVector(new double[dimsize[out]]));
+ VectorFieldTypeInformation<DoubleVector> type = new VectorFieldTypeInformation<DoubleVector>(DoubleVector.class, DoubleVector.STATIC, dimsize[out], labels, new DoubleVector(new double[dimsize[out]]));
bundle.appendColumn(type, new ArrayList<DoubleVector>());
}
else {
- Map<Integer, Float> empty = Collections.emptyMap();
- VectorFieldTypeInformation<SparseFloatVector> type = new VectorFieldTypeInformation<SparseFloatVector>(SparseFloatVector.class, dimsize[out], labels, new SparseFloatVector(empty, dimsize[out]));
+ VectorFieldTypeInformation<SparseFloatVector> type = new VectorFieldTypeInformation<SparseFloatVector>(SparseFloatVector.class, dimsize[out], labels, new SparseFloatVector(SparseFloatVector.EMPTYMAP, dimsize[out]));
bundle.appendColumn(type, new ArrayList<SparseFloatVector>());
}
}
@@ -585,20 +598,22 @@ public class ArffParser implements Parser {
else if((tokenizer.ttype == StreamTokenizer.TT_WORD) && (tokenizer.sval.equals("?"))) {
tokenizer.ttype = '?';
}
- if(tokenizer.ttype == StreamTokenizer.TT_NUMBER) {
- logger.debug("token: " + tokenizer.nval);
- }
- else if(tokenizer.ttype == StreamTokenizer.TT_WORD) {
- logger.debug("token: " + tokenizer.sval);
- }
- else if(tokenizer.ttype == StreamTokenizer.TT_EOF) {
- logger.debug("token: EOF");
- }
- else if(tokenizer.ttype == StreamTokenizer.TT_EOL) {
- logger.debug("token: EOL");
- }
- else {
- logger.debug("token type: " + tokenizer.ttype);
+ if(logger.isDebugging()) {
+ if(tokenizer.ttype == StreamTokenizer.TT_NUMBER) {
+ logger.debug("token: " + tokenizer.nval);
+ }
+ else if(tokenizer.ttype == StreamTokenizer.TT_WORD) {
+ logger.debug("token: " + tokenizer.sval);
+ }
+ else if(tokenizer.ttype == StreamTokenizer.TT_EOF) {
+ logger.debug("token: EOF");
+ }
+ else if(tokenizer.ttype == StreamTokenizer.TT_EOL) {
+ logger.debug("token: EOL");
+ }
+ else {
+ logger.debug("token type: " + tokenizer.ttype);
+ }
}
}
@@ -606,7 +621,7 @@ public class ArffParser implements Parser {
* Parameterization class.
*
* @author Erich Schubert
- *
+ *
* @apiviz.exclude
*/
public static class Parameterizer extends AbstractParameterizer {
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 cd206310..c62392b4 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -82,15 +82,18 @@ public class BitVectorLabelParser extends AbstractParser implements Parser {
for(String line; (line = reader.readLine()) != null; lineNumber++) {
if(!line.startsWith(COMMENT) && line.length() > 0) {
List<String> entries = tokenize(line);
- // TODO: use more efficient storage right away?
+ // FIXME: use more efficient storage right away?
List<Bit> attributes = new ArrayList<Bit>();
- LabelList ll = new LabelList();
+ 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);
}
}
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 988b90cc..97c3a8c8 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/parser/DoubleVectorLabelParser.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/parser/DoubleVectorLabelParser.java
@@ -1,34 +1,34 @@
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) 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/>.
-*/
+
+/*
+ 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 java.util.BitSet;
-import java.util.List;
import java.util.regex.Pattern;
import de.lmu.ifi.dbs.elki.data.DoubleVector;
-import de.lmu.ifi.dbs.elki.data.type.VectorFieldTypeInformation;
import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
/**
* <p>
@@ -47,8 +47,6 @@ import de.lmu.ifi.dbs.elki.logging.Logging;
*
* @author Arthur Zimek
*
- * @apiviz.landmark
- *
* @apiviz.has DoubleVector
*/
public class DoubleVectorLabelParser extends NumberVectorLabelParser<DoubleVector> {
@@ -65,7 +63,7 @@ public class DoubleVectorLabelParser extends NumberVectorLabelParser<DoubleVecto
* @param labelIndices
*/
public DoubleVectorLabelParser(Pattern colSep, char quoteChar, BitSet labelIndices) {
- super(colSep, quoteChar, labelIndices);
+ super(colSep, quoteChar, labelIndices, DoubleVector.STATIC);
}
/**
@@ -75,21 +73,6 @@ public class DoubleVectorLabelParser extends NumberVectorLabelParser<DoubleVecto
this(Pattern.compile(WHITESPACE_PATTERN), QUOTE_CHAR.charAt(0), new BitSet());
}
- /**
- * Creates a DoubleVector out of the given attribute values.
- *
- * @see de.lmu.ifi.dbs.elki.datasource.parser.NumberVectorLabelParser#createDBObject(java.util.List)
- */
- @Override
- public DoubleVector createDBObject(List<Double> attributes) {
- return new DoubleVector(attributes);
- }
-
- @Override
- protected VectorFieldTypeInformation<DoubleVector> getTypeInformation(int dimensionality) {
- return new VectorFieldTypeInformation<DoubleVector>(DoubleVector.class, dimensionality, new DoubleVector(new double[dimensionality]));
- }
-
@Override
protected Logging getLogger() {
return logger;
@@ -104,6 +87,11 @@ public class DoubleVectorLabelParser extends NumberVectorLabelParser<DoubleVecto
*/
public static class Parameterizer extends NumberVectorLabelParser.Parameterizer<DoubleVector> {
@Override
+ protected void getFactory(Parameterization config) {
+ // Do nothing: not used
+ }
+
+ @Override
protected DoubleVectorLabelParser makeInstance() {
return new DoubleVectorLabelParser(colSep, quoteChar, labelIndices);
}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/parser/DoubleVectorLabelTransposingParser.java b/src/de/lmu/ifi/dbs/elki/datasource/parser/DoubleVectorLabelTransposingParser.java
deleted file mode 100644
index 2019346c..00000000
--- a/src/de/lmu/ifi/dbs/elki/datasource/parser/DoubleVectorLabelTransposingParser.java
+++ /dev/null
@@ -1,141 +0,0 @@
-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) 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 java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.util.ArrayList;
-import java.util.BitSet;
-import java.util.List;
-import java.util.regex.Pattern;
-
-import de.lmu.ifi.dbs.elki.data.DoubleVector;
-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.logging.Logging;
-import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
-
-/**
- * Parser reads points transposed. Line n gives the n-th attribute for all
- * points.
- *
- * @author Arthur Zimek
- */
-public class DoubleVectorLabelTransposingParser extends DoubleVectorLabelParser {
- /**
- * Class logger
- */
- private static final Logging logger = Logging.getLogger(DoubleVectorLabelTransposingParser.class);
-
- /**
- * Constructor.
- *
- * @param colSep
- * @param quoteChar
- * @param labelIndices
- */
- public DoubleVectorLabelTransposingParser(Pattern colSep, char quoteChar, BitSet labelIndices) {
- super(colSep, quoteChar, labelIndices);
- }
-
- @Override
- public MultipleObjectsBundle parse(InputStream in) {
- BufferedReader reader = new BufferedReader(new InputStreamReader(in));
- int lineNumber = 0;
- List<Double>[] data = null;
- LabelList[] labels = null;
-
- int dimensionality = -1;
-
- try {
- for(String line; (line = reader.readLine()) != null; lineNumber++) {
- if(!line.startsWith(COMMENT) && line.length() > 0) {
- List<String> entries = tokenize(line);
- if(dimensionality == -1) {
- dimensionality = entries.size();
- }
- else if(entries.size() != dimensionality) {
- throw new IllegalArgumentException("Differing dimensionality in line " + (lineNumber) + ", " + "expected: " + dimensionality + ", read: " + entries.size());
- }
-
- if(data == null) {
- data = ClassGenericsUtil.newArrayOfEmptyArrayList(dimensionality);
- /*
- * for (int i = 0; i < data.length; i++) { data[i] = new
- * ArrayList<Double>(); }
- */
- labels = ClassGenericsUtil.newArrayOfNull(dimensionality, LabelList.class);
- for(int i = 0; i < labels.length; i++) {
- labels[i] = new LabelList();
- }
- }
-
- for(int i = 0; i < entries.size(); i++) {
- try {
- Double attribute = Double.valueOf(entries.get(i));
- data[i].add(attribute);
- }
- catch(NumberFormatException e) {
- labels[i].add(entries.get(i));
- }
- }
- }
- }
- }
- catch(IOException e) {
- throw new IllegalArgumentException("Error while parsing line " + lineNumber + ".");
- }
-
- List<DoubleVector> vectors = new ArrayList<DoubleVector>();
- List<LabelList> lblc = new ArrayList<LabelList>();
- for(int i = 0; i < data.length; i++) {
- DoubleVector featureVector = new DoubleVector(data[i]);
- vectors.add(featureVector);
- lblc.add(labels[i]);
- }
- return MultipleObjectsBundle.makeSimple(getTypeInformation(dimensionality), vectors, TypeUtil.LABELLIST, lblc);
- }
-
- @Override
- protected Logging getLogger() {
- return logger;
- }
-
- /**
- * Parameterization class.
- *
- * @author Erich Schubert
- *
- * @apiviz.exclude
- */
- public static class Parameterizer extends NumberVectorLabelParser.Parameterizer<DoubleVector> {
- @Override
- protected DoubleVectorLabelTransposingParser makeInstance() {
- return new DoubleVectorLabelTransposingParser(colSep, quoteChar, 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 ad51ca1a..3ea2ac80 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) 2011
+Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,13 +23,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import java.util.BitSet;
-import java.util.List;
import java.util.regex.Pattern;
import de.lmu.ifi.dbs.elki.data.FloatVector;
-import de.lmu.ifi.dbs.elki.data.type.VectorFieldTypeInformation;
import de.lmu.ifi.dbs.elki.logging.Logging;
-import de.lmu.ifi.dbs.elki.utilities.Util;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
/**
* <p>
@@ -68,22 +66,7 @@ public class FloatVectorLabelParser extends NumberVectorLabelParser<FloatVector>
* @param labelIndices
*/
public FloatVectorLabelParser(Pattern colSep, char quoteChar, BitSet labelIndices) {
- super(colSep, quoteChar, labelIndices);
- }
-
- /**
- * Creates a FloatVector out of the given attribute values.
- *
- * @see de.lmu.ifi.dbs.elki.datasource.parser.NumberVectorLabelParser#createDBObject(java.util.List)
- */
- @Override
- public FloatVector createDBObject(List<Double> attributes) {
- return new FloatVector(Util.convertToFloat(attributes));
- }
-
- @Override
- protected VectorFieldTypeInformation<FloatVector> getTypeInformation(int dimensionality) {
- return new VectorFieldTypeInformation<FloatVector>(FloatVector.class, dimensionality, new FloatVector(new float[dimensionality]));
+ super(colSep, quoteChar, labelIndices, FloatVector.STATIC);
}
@Override
@@ -100,6 +83,11 @@ public class FloatVectorLabelParser extends NumberVectorLabelParser<FloatVector>
*/
public static class Parameterizer extends NumberVectorLabelParser.Parameterizer<FloatVector> {
@Override
+ protected void getFactory(Parameterization config) {
+ // Do nothing: not used
+ }
+
+ @Override
protected FloatVectorLabelParser makeInstance() {
return new FloatVectorLabelParser(colSep, quoteChar, labelIndices);
}
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 a89f6c3a..01606e77 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,26 +23,33 @@ package de.lmu.ifi.dbs.elki.datasource.parser;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import gnu.trove.list.array.TDoubleArrayList;
+
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
-import java.util.ArrayList;
import java.util.BitSet;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;
+import de.lmu.ifi.dbs.elki.data.DoubleVector;
import de.lmu.ifi.dbs.elki.data.LabelList;
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.bundle.SingleObjectBundle;
+import de.lmu.ifi.dbs.elki.datasource.bundle.BundleMeta;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.persistent.ByteBufferSerializer;
+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;
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.IntListParameter;
-import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
/**
* <p>
@@ -59,9 +66,18 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
* </p>
*
* @author Arthur Zimek
+ *
+ * @apiviz.landmark
+ * @apiviz.has NumberVector
+ *
* @param <V> the type of NumberVector used
*/
-public abstract class NumberVectorLabelParser<V extends NumberVector<?, ?>> extends AbstractParser implements LinebasedParser, Parser {
+public class NumberVectorLabelParser<V extends NumberVector<V, ?>> extends AbstractStreamingParser {
+ /**
+ * Logging class.
+ */
+ private static final Logging logger = Logging.getLogger(NumberVectorLabelParser.class);
+
/**
* A comma separated list of the indices of labels (may be numeric), counting
* whitespace separated entries in a line starting with 0. The corresponding
@@ -73,95 +89,186 @@ public abstract class NumberVectorLabelParser<V extends NumberVector<?, ?>> exte
public static final OptionID LABEL_INDICES_ID = OptionID.getOrCreateOptionID("parser.labelIndices", "A comma separated list of the indices of labels (may be numeric), counting whitespace separated entries in a line starting with 0. The corresponding entries will be treated as a label.");
/**
+ * Parameter to specify the type of vectors to produce.
+ * <p>
+ * Key: {@code -parser.vector-type}<br />
+ * Default: DoubleVector
+ * </p>
+ */
+ public static final OptionID VECTOR_TYPE_ID = OptionID.getOrCreateOptionID("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;
/**
+ * Vector factory class
+ */
+ protected V factory;
+
+ /**
+ * Buffer reader
+ */
+ private BufferedReader reader;
+
+ /**
+ * Current line number
+ */
+ protected int lineNumber;
+
+ /**
+ * Dimensionality reported
+ */
+ protected int dimensionality;
+
+ /**
+ * Metadata
+ */
+ protected BundleMeta meta = null;
+
+ /**
+ * Current vector
+ */
+ protected V curvec = null;
+
+ /**
+ * Current labels
+ */
+ protected LabelList curlbl = null;
+
+ /**
+ * Event to report next
+ */
+ Event nextevent = null;
+
+ /**
* Constructor
*
* @param colSep
* @param quoteChar
* @param labelIndices
+ * @param factory Vector factory
*/
- public NumberVectorLabelParser(Pattern colSep, char quoteChar, BitSet labelIndices) {
+ public NumberVectorLabelParser(Pattern colSep, char quoteChar, BitSet labelIndices, V factory) {
super(colSep, quoteChar);
this.labelIndices = labelIndices;
+ this.factory = factory;
+ }
+
+ @Override
+ public void initStream(InputStream in) {
+ reader = new BufferedReader(new InputStreamReader(in));
+ lineNumber = 1;
+ dimensionality = DIMENSIONALITY_UNKNOWN;
+ }
+
+ @Override
+ public BundleMeta getMeta() {
+ return meta;
}
@Override
- public MultipleObjectsBundle parse(InputStream in) {
- BufferedReader reader = new BufferedReader(new InputStreamReader(in));
- int lineNumber = 1;
- int dimensionality = -1;
- List<V> vectors = new ArrayList<V>();
- List<LabelList> labels = new ArrayList<LabelList>();
+ public Event nextEvent() {
+ if(nextevent != null) {
+ Event ret = nextevent;
+ nextevent = null;
+ return ret;
+ }
try {
for(String line; (line = reader.readLine()) != null; lineNumber++) {
if(!line.startsWith(COMMENT) && line.length() > 0) {
- Pair<V, LabelList> objectAndLabels = parseLineInternal(line);
- if(dimensionality < 0) {
- dimensionality = objectAndLabels.getFirst().getDimensionality();
+ parseLineInternal(line);
+ if(dimensionality == DIMENSIONALITY_UNKNOWN) {
+ dimensionality = curvec.getDimensionality();
+ buildMeta();
+ nextevent = Event.NEXT_OBJECT;
+ return Event.META_CHANGED;
}
- else if(dimensionality != objectAndLabels.getFirst().getDimensionality()) {
- throw new IllegalArgumentException("Differing dimensionality in line " + lineNumber + ":" + objectAndLabels.getFirst().getDimensionality() + " != " + dimensionality);
+ else if(dimensionality > 0) {
+ if(dimensionality != curvec.getDimensionality()) {
+ dimensionality = DIMENSIONALITY_VARIABLE;
+ buildMeta();
+ nextevent = Event.NEXT_OBJECT;
+ return Event.META_CHANGED;
+ }
}
- vectors.add(objectAndLabels.first);
- labels.add(objectAndLabels.second);
+ return Event.NEXT_OBJECT;
}
}
+ reader.close();
+ reader = null;
+ return Event.END_OF_STREAM;
}
catch(IOException e) {
throw new IllegalArgumentException("Error while parsing line " + lineNumber + ".");
}
- return MultipleObjectsBundle.makeSimple(getTypeInformation(dimensionality), vectors, TypeUtil.LABELLIST, labels);
+ }
+
+ /**
+ * Update the meta element.
+ */
+ protected void buildMeta() {
+ meta = new BundleMeta(2);
+ meta.add(getTypeInformation(dimensionality));
+ meta.add(TypeUtil.LABELLIST);
}
@Override
- public SingleObjectBundle parseLine(String line) {
- Pair<V, LabelList> objectAndLabels = parseLineInternal(line);
- SingleObjectBundle pkg = new SingleObjectBundle();
- pkg.append(getTypeInformation(objectAndLabels.first.getDimensionality()), objectAndLabels.first);
- pkg.append(TypeUtil.LABELLIST, objectAndLabels.second);
- return pkg;
+ public Object data(int rnum) {
+ if(rnum == 0) {
+ return curvec;
+ }
+ if(rnum == 1) {
+ return curlbl;
+ }
+ throw new ArrayIndexOutOfBoundsException();
}
/**
- * Internal method for parsing a single line. Used by both line based parsig
+ * Internal method for parsing a single line. Used by both line based parsing
* as well as block parsing. This saves the building of meta data for each
* line.
*
* @param line Line to process
- * @return parsing result
*/
- protected Pair<V, LabelList> parseLineInternal(String line) {
+ protected void parseLineInternal(String line) {
List<String> entries = tokenize(line);
-
// Split into numerical attributes and labels
- List<Double> attributes = new ArrayList<Double>(entries.size());
- LabelList labels = new LabelList();
+ TDoubleArrayList attributes = new TDoubleArrayList(entries.size());
+ LabelList labels = null;
Iterator<String> itr = entries.iterator();
for(int i = 0; itr.hasNext(); i++) {
String ent = itr.next();
if(!labelIndices.get(i)) {
try {
- Double attribute = Double.valueOf(ent);
+ double attribute = Double.parseDouble(ent);
attributes.add(attribute);
+ continue;
}
catch(NumberFormatException e) {
- labels.add(ent);
+ // Ignore attempt, add to labels below.
}
}
- else {
- labels.add(ent);
+ if(labels == null) {
+ labels = new LabelList(1);
}
+ labels.add(ent);
}
- Pair<V, LabelList> objectAndLabels;
- V vec = createDBObject(attributes);
- objectAndLabels = new Pair<V, LabelList>(vec, labels);
- return objectAndLabels;
+ curvec = createDBObject(attributes, ArrayLikeUtil.TDOUBLELISTADAPTER);
+ curlbl = labels;
}
/**
@@ -172,7 +279,9 @@ public abstract class NumberVectorLabelParser<V extends NumberVector<?, ?>> exte
* @param attributes the attributes of the vector to create.
* @return a RalVector of type V containing the given attribute values
*/
- protected abstract V createDBObject(List<Double> attributes);
+ protected <A> V createDBObject(A attributes, NumberArrayAdapter<?, A> adapter) {
+ return factory.newNumberVector(attributes, adapter);
+ }
/**
* Get a prototype object for the given dimensionality.
@@ -180,7 +289,37 @@ public abstract class NumberVectorLabelParser<V extends NumberVector<?, ?>> exte
* @param dimensionality Dimensionality
* @return Prototype object
*/
- abstract protected VectorFieldTypeInformation<V> getTypeInformation(int dimensionality);
+ SimpleTypeInformation<V> getTypeInformation(int dimensionality) {
+ @SuppressWarnings("unchecked")
+ Class<V> cls = (Class<V>) factory.getClass();
+ if(dimensionality > 0) {
+ V f = factory.newNumberVector(new double[dimensionality]);
+ if(f instanceof ByteBufferSerializer) {
+ // TODO: Remove, once we have serializers for all types
+ @SuppressWarnings("unchecked")
+ final ByteBufferSerializer<V> ser = (ByteBufferSerializer<V>) f;
+ return new VectorFieldTypeInformation<V>(cls, ser, dimensionality, f);
+ }
+ return new VectorFieldTypeInformation<V>(cls, dimensionality, f);
+ }
+ // Variable dimensionality - return non-vector field type
+ if(dimensionality == DIMENSIONALITY_VARIABLE) {
+ V f = factory.newNumberVector(new double[0]);
+ if(f instanceof ByteBufferSerializer) {
+ // TODO: Remove, once we have serializers for all types
+ @SuppressWarnings("unchecked")
+ final ByteBufferSerializer<V> ser = (ByteBufferSerializer<V>) f;
+ return new SimpleTypeInformation<V>(cls, ser);
+ }
+ return new SimpleTypeInformation<V>(cls);
+ }
+ throw new AbortException("No vectors were read from the input file - cannot determine vector data type.");
+ }
+
+ @Override
+ protected Logging getLogger() {
+ return logger;
+ }
/**
* Parameterization class.
@@ -189,15 +328,32 @@ public abstract class NumberVectorLabelParser<V extends NumberVector<?, ?>> exte
*
* @apiviz.exclude
*/
- public static abstract class Parameterizer<V extends NumberVector<?, ?>> extends AbstractParser.Parameterizer {
+ public static class Parameterizer<V extends NumberVector<V, ?>> extends AbstractParser.Parameterizer {
/**
* Keeps the indices of the attributes to be treated as a string label.
*/
protected BitSet labelIndices = null;
+ /**
+ * Factory
+ */
+ protected V factory;
+
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
+ getLabelIndices(config);
+ getFactory(config);
+ }
+
+ protected void getFactory(Parameterization config) {
+ ObjectParameter<V> factoryP = new ObjectParameter<V>(VECTOR_TYPE_ID, NumberVector.class, DoubleVector.class);
+ if(config.grab(factoryP)) {
+ factory = factoryP.instantiateClass(config);
+ }
+ }
+
+ protected void getLabelIndices(Parameterization config) {
IntListParameter labelIndicesP = new IntListParameter(LABEL_INDICES_ID, true);
labelIndices = new BitSet();
@@ -210,6 +366,8 @@ public abstract class NumberVectorLabelParser<V extends NumberVector<?, ?>> exte
}
@Override
- protected abstract NumberVectorLabelParser<V> makeInstance();
+ protected NumberVectorLabelParser<V> makeInstance() {
+ return new NumberVectorLabelParser<V>(colSep, quoteChar, labelIndices, factory);
+ }
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/parser/ParameterizationFunctionLabelParser.java b/src/de/lmu/ifi/dbs/elki/datasource/parser/ParameterizationFunctionLabelParser.java
index 8c4f44ae..8e240ae9 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/parser/ParameterizationFunctionLabelParser.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/parser/ParameterizationFunctionLabelParser.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) 2011
+ Copyright (C) 2012
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.datasource.parser;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import gnu.trove.list.TDoubleList;
+import gnu.trove.list.array.TDoubleArrayList;
+
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
@@ -37,7 +40,7 @@ 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.logging.Logging;
-import de.lmu.ifi.dbs.elki.utilities.Util;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayLikeUtil;
import de.lmu.ifi.dbs.elki.utilities.documentation.Description;
import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
@@ -80,14 +83,17 @@ public class ParameterizationFunctionLabelParser extends AbstractParser implemen
for(String line; (line = reader.readLine()) != null; lineNumber++) {
if(!line.startsWith(COMMENT) && line.length() > 0) {
List<String> entries = tokenize(line);
- List<Double> attributes = new ArrayList<Double>(entries.size());
- LabelList labellist = new LabelList();
+ TDoubleList attributes = new TDoubleArrayList(entries.size());
+ LabelList labellist = null;
for(String entry : entries) {
try {
- Double attribute = Double.valueOf(entry);
+ double attribute = Double.parseDouble(entry);
attributes.add(attribute);
}
catch(NumberFormatException e) {
+ if(labellist == null) {
+ labellist = new LabelList(1);
+ }
labellist.add(entry);
}
}
@@ -98,8 +104,7 @@ public class ParameterizationFunctionLabelParser extends AbstractParser implemen
else if(dimensionality != attributes.size()) {
throw new IllegalArgumentException("Differing dimensionality in line " + lineNumber + ":" + attributes.size() + " != " + dimensionality);
}
-
- vectors.add(new ParameterizationFunction(Util.convertToDoubles(attributes)));
+ vectors.add(ParameterizationFunction.STATIC.newNumberVector(attributes, ArrayLikeUtil.TDOUBLELISTADAPTER));
labels.add(labellist);
}
}
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 b0222b99..1f078d19 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) 2011
+ Copyright (C) 2012
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/SimplePolygonParser.java b/src/de/lmu/ifi/dbs/elki/datasource/parser/SimplePolygonParser.java
index 98f9888d..baa6f0ec 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -87,15 +87,23 @@ public class SimplePolygonParser extends AbstractParser implements Parser {
int lineNumber = 1;
List<PolygonsObject> polys = new ArrayList<PolygonsObject>();
- List<LabelList> labels = new ArrayList<LabelList>();
+ List<LabelList> labels = null;
List<ExternalID> eids = new ArrayList<ExternalID>();
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]);
- labels.add((LabelList)objs[1]);
- eids.add((ExternalID)objs[2]);
+ 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);
+ }
+ }
+ labels.add((LabelList) objs[1]);
+ }
+ eids.add((ExternalID) objs[2]);
}
}
}
@@ -103,7 +111,12 @@ public class SimplePolygonParser extends AbstractParser implements Parser {
throw new IllegalArgumentException("Error while parsing line " + lineNumber + ".");
}
- return MultipleObjectsBundle.makeSimple(TypeUtil.POLYGON_TYPE, polys, TypeUtil.LABELLIST, labels, TypeUtil.EXTERNALID, eids);
+ if(labels != null) {
+ return MultipleObjectsBundle.makeSimple(TypeUtil.POLYGON_TYPE, polys, TypeUtil.LABELLIST, labels, TypeUtil.EXTERNALID, eids);
+ }
+ else {
+ return MultipleObjectsBundle.makeSimple(TypeUtil.POLYGON_TYPE, polys, TypeUtil.EXTERNALID, eids);
+ }
}
/**
@@ -117,7 +130,8 @@ public class SimplePolygonParser extends AbstractParser implements Parser {
List<String> entries = tokenize(line);
Iterator<String> iter = entries.iterator();
- LabelList labels = new LabelList();
+ ExternalID eid = null;
+ LabelList labels = null;
List<Polygon> polys = new java.util.Vector<Polygon>(1);
List<Vector> coords = new ArrayList<Vector>();
@@ -126,10 +140,10 @@ public class SimplePolygonParser extends AbstractParser implements Parser {
Matcher m = COORD.matcher(cur);
if(m.find()) {
try {
- double c1 = Double.valueOf(m.group(1));
- double c2 = Double.valueOf(m.group(2));
+ double c1 = Double.parseDouble(m.group(1));
+ double c2 = Double.parseDouble(m.group(2));
if(m.group(3) != null) {
- double c3 = Double.valueOf(m.group(3));
+ double c3 = Double.parseDouble(m.group(3));
coords.add(new Vector(new double[] { c1, c2, c3 }));
}
else {
@@ -149,15 +163,22 @@ public class SimplePolygonParser extends AbstractParser implements Parser {
}
continue;
}
- // Label
- labels.add(cur);
+ // First label will become the External ID
+ if(eid == null) {
+ eid = new ExternalID(cur);
+ }
+ else {
+ // Label
+ if(labels == null) {
+ labels = new LabelList(1);
+ }
+ labels.add(cur);
+ }
}
// Complete polygon
if(coords.size() > 0) {
polys.add(new Polygon(coords));
}
- // Use first label as eternal ID
- ExternalID eid = labels.size() > 0 ? new ExternalID(labels.remove(0)) : null;
return new Object[] { new PolygonsObject(polys), labels, eid };
}
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 4b349f6a..70188d38 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -86,7 +86,7 @@ public class SparseBitVectorLabelParser extends AbstractParser implements Parser
if(!line.startsWith(COMMENT) && line.length() > 0) {
List<String> entries = tokenize(line);
BitSet bitSet = new BitSet();
- LabelList labels = new LabelList();
+ LabelList labels = null;
for(String entry : entries) {
try {
@@ -95,6 +95,9 @@ public class SparseBitVectorLabelParser extends AbstractParser implements Parser
dimensionality = Math.max(dimensionality, index);
}
catch(NumberFormatException e) {
+ if(labels == null) {
+ labels = new LabelList(1);
+ }
labels.add(entry);
}
}
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 b4e7ee3e..83d6ed13 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/parser/SparseFloatVectorLabelParser.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/parser/SparseFloatVectorLabelParser.java
@@ -1,48 +1,42 @@
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) 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 java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-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/>.
+ */
+
+import gnu.trove.map.hash.TIntFloatHashMap;
+
import java.util.BitSet;
-import java.util.Collections;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import java.util.regex.Pattern;
import de.lmu.ifi.dbs.elki.data.LabelList;
import de.lmu.ifi.dbs.elki.data.SparseFloatVector;
-import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+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.logging.Logging;
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.pairs.Pair;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
/**
* <p>
@@ -69,6 +63,7 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
*
* @apiviz.has SparseFloatVector
*/
+// FIXME: Maxdim!
@Title("Sparse Float Vector Label Parser")
@Description("Parser for the following line format:\n" + "A single line provides a single point. Entries are separated by whitespace. " + "The values will be parsed as floats (resulting in a set of SparseFloatVectors). A line is expected in the following format: The first entry of each line is the number of attributes with coordinate value not zero. Subsequent entries are of the form (index, value), where index is the number of the corresponding dimension, and value is the value of the corresponding attribute." + "Any pair of two subsequent substrings not containing whitespace is tried to be read as int and float. If this fails for the first of the pair (interpreted ans index), it will be appended to a label. (Thus, any label must not be parseable as Integer.) If the float component is not parseable, an exception will be thrown. Empty lines and lines beginning with \"#\" will be ignored. Having the file parsed completely, the maximum occuring dimensionality is set as dimensionality to all created SparseFloatvectors.")
public class SparseFloatVectorLabelParser extends NumberVectorLabelParser<SparseFloatVector> {
@@ -78,6 +73,12 @@ public class SparseFloatVectorLabelParser extends NumberVectorLabelParser<Sparse
private static final Logging logger = Logging.getLogger(SparseFloatVectorLabelParser.class);
/**
+ * Holds the dimensionality of the parsed data which is the maximum occurring
+ * index of any attribute.
+ */
+ private int maxdim = -1;
+
+ /**
* Constructor.
*
* @param colSep
@@ -85,87 +86,56 @@ public class SparseFloatVectorLabelParser extends NumberVectorLabelParser<Sparse
* @param labelIndices
*/
public SparseFloatVectorLabelParser(Pattern colSep, char quoteChar, BitSet labelIndices) {
- super(colSep, quoteChar, labelIndices);
- }
-
- /**
- * Holds the dimensionality of the parsed data which is the maximum occurring
- * index of any attribute.
- */
- private int dimensionality = -1;
-
- @Override
- public SparseFloatVector createDBObject(List<Double> attributes) {
- throw new UnsupportedOperationException("This method should never be reached.");
+ super(colSep, quoteChar, labelIndices, SparseFloatVector.STATIC);
}
@Override
- public Pair<SparseFloatVector, LabelList> parseLineInternal(String line) {
+ protected void parseLineInternal(String line) {
List<String> entries = tokenize(line);
int cardinality = Integer.parseInt(entries.get(0));
- Map<Integer, Float> values = new HashMap<Integer, Float>(cardinality, 1);
- LabelList labels = new LabelList();
+ TIntFloatHashMap values = new TIntFloatHashMap(cardinality, 1);
+ LabelList labels = null;
for(int i = 1; i < entries.size() - 1; i++) {
if(!labelIndices.get(i)) {
- Integer index;
- Float attribute;
try {
- index = Integer.valueOf(entries.get(i));
- if(index > dimensionality) {
- dimensionality = index;
+ int index = Integer.valueOf(entries.get(i));
+ if(index > maxdim) {
+ maxdim = index;
}
+ float attribute = Float.valueOf(entries.get(i));
+ values.put(index, attribute);
i++;
}
catch(NumberFormatException e) {
+ if(labels == null) {
+ labels = new LabelList(1);
+ }
labels.add(entries.get(i));
continue;
}
- attribute = Float.valueOf(entries.get(i));
- values.put(index, attribute);
}
else {
+ if(labels == null) {
+ labels = new LabelList(1);
+ }
labels.add(entries.get(i));
}
}
- return new Pair<SparseFloatVector, LabelList>(new SparseFloatVector(values, dimensionality), labels);
+ curvec = new SparseFloatVector(values, maxdim);
+ curlbl = labels;
}
- /**
- *
- * @see de.lmu.ifi.dbs.elki.datasource.parser.NumberVectorLabelParser#parse(java.io.InputStream)
- */
@Override
- public MultipleObjectsBundle parse(InputStream in) {
- dimensionality = -1;
- BufferedReader reader = new BufferedReader(new InputStreamReader(in));
- int lineNumber = 1;
- List<SparseFloatVector> vectors = new ArrayList<SparseFloatVector>();
- List<LabelList> lblc = new ArrayList<LabelList>();
- try {
- for(String line; (line = reader.readLine()) != null; lineNumber++) {
- if(!line.startsWith(COMMENT) && line.length() > 0) {
- Pair<SparseFloatVector, LabelList> pair = parseLineInternal(line);
- vectors.add(pair.first);
- lblc.add(pair.second);
- }
- }
+ protected SimpleTypeInformation<SparseFloatVector> getTypeInformation(int dimensionality) {
+ if(dimensionality > 0) {
+ return new VectorFieldTypeInformation<SparseFloatVector>(SparseFloatVector.class, dimensionality, new SparseFloatVector(SparseFloatVector.EMPTYMAP, dimensionality));
}
- catch(IOException e) {
- throw new IllegalArgumentException("Error while parsing line " + lineNumber + ".");
+ if(dimensionality == DIMENSIONALITY_VARIABLE) {
+ return new SimpleTypeInformation<SparseFloatVector>(SparseFloatVector.class);
}
- // Set maximum dimensionality
- for(int i = 0; i < vectors.size(); i++) {
- vectors.get(i).setDimensionality(dimensionality);
- }
- return MultipleObjectsBundle.makeSimple(getTypeInformation(dimensionality), vectors, TypeUtil.LABELLIST, lblc);
- }
-
- @Override
- protected VectorFieldTypeInformation<SparseFloatVector> getTypeInformation(int dimensionality) {
- final Map<Integer, Float> emptyMap = Collections.emptyMap();
- return new VectorFieldTypeInformation<SparseFloatVector>(SparseFloatVector.class, dimensionality, new SparseFloatVector(emptyMap, dimensionality));
+ throw new AbortException("No vectors were read from the input file - cannot determine vector data type.");
}
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/parser/LinebasedParser.java b/src/de/lmu/ifi/dbs/elki/datasource/parser/StreamingParser.java
index 5a9ffe14..01579dc6 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/parser/LinebasedParser.java
+++ b/src/de/lmu/ifi/dbs/elki/datasource/parser/StreamingParser.java
@@ -1,10 +1,14 @@
package de.lmu.ifi.dbs.elki.datasource.parser;
+import java.io.InputStream;
+
+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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,21 +27,17 @@ package de.lmu.ifi.dbs.elki.datasource.parser;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import de.lmu.ifi.dbs.elki.datasource.bundle.SingleObjectBundle;
-import de.lmu.ifi.dbs.elki.utilities.InspectionUtilFrequentlyScanned;
-
/**
- * A parser that can parse single line.
- * Will be used by a parser to re-read results.
- *
+ * Interface for streaming parsers, that may be much more efficient in
+ * combination with filters.
+ *
* @author Erich Schubert
*/
-public interface LinebasedParser extends InspectionUtilFrequentlyScanned {
+public interface StreamingParser extends Parser, BundleStreamSource {
/**
- * Parse a single line into a database object
+ * Init the streaming parser for the given input stream.
*
- * @param line single line
- * @return parsing result
+ * @param in the stream to parse objects from
*/
- public SingleObjectBundle parseLine(String line);
+ void initStream(InputStream in);
} \ No newline at end of file
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 8448e4c4..bb277b17 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,28 +23,25 @@ package de.lmu.ifi.dbs.elki.datasource.parser;
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 gnu.trove.iterator.TIntFloatIterator;
+import gnu.trove.map.hash.TIntFloatHashMap;
+
import java.util.BitSet;
-import java.util.Collections;
import java.util.HashMap;
import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
import java.util.regex.Pattern;
import de.lmu.ifi.dbs.elki.data.LabelList;
import de.lmu.ifi.dbs.elki.data.SparseFloatVector;
-import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+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.logging.Logging;
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.pairs.Pair;
+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;
/**
* A parser to load term frequency data, which essentially are sparse vectors
@@ -54,7 +51,6 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
*
* @apiviz.has SparseFloatVector
*/
-// TODO: add a flag to perform TF normalization when using term counts
@Title("Term frequency parser")
@Description("Parse a file containing term frequencies. The expected format is 'label term1 <freq> term2 <freq> ...'. Terms must not contain the separator character!")
public class TermFrequencyParser extends NumberVectorLabelParser<SparseFloatVector> {
@@ -74,29 +70,32 @@ public class TermFrequencyParser extends NumberVectorLabelParser<SparseFloatVect
HashMap<String, Integer> keymap;
/**
+ * Normalize
+ */
+ boolean normalize;
+
+ /**
* Constructor.
*
+ * @param normalize Normalize
* @param colSep
* @param quoteChar
* @param labelIndices
*/
- public TermFrequencyParser(Pattern colSep, char quoteChar, BitSet labelIndices) {
- super(colSep, quoteChar, labelIndices);
+ public TermFrequencyParser(boolean normalize, Pattern colSep, char quoteChar, BitSet labelIndices) {
+ super(colSep, quoteChar, labelIndices, SparseFloatVector.STATIC);
+ this.normalize = normalize;
this.maxdim = 0;
this.keymap = new HashMap<String, Integer>();
}
@Override
- protected SparseFloatVector createDBObject(List<Double> attributes) {
- throw new UnsupportedOperationException("This method should never be reached.");
- }
-
- @Override
- public Pair<SparseFloatVector, LabelList> parseLineInternal(String line) {
+ protected void parseLineInternal(String line) {
List<String> entries = tokenize(line);
- Map<Integer, Float> values = new TreeMap<Integer, Float>();
- LabelList labels = new LabelList();
+ double len = 0;
+ TIntFloatHashMap values = new TIntFloatHashMap();
+ LabelList labels = null;
String curterm = null;
for(int i = 0; i < entries.size(); i++) {
@@ -105,7 +104,7 @@ public class TermFrequencyParser extends NumberVectorLabelParser<SparseFloatVect
}
else {
try {
- Float attribute = Float.valueOf(entries.get(i));
+ float attribute = Float.valueOf(entries.get(i));
Integer curdim = keymap.get(curterm);
if(curdim == null) {
curdim = maxdim + 1;
@@ -113,10 +112,14 @@ public class TermFrequencyParser extends NumberVectorLabelParser<SparseFloatVect
maxdim += 1;
}
values.put(curdim, attribute);
+ len += attribute;
curterm = null;
}
catch(NumberFormatException e) {
if(curterm != null) {
+ if(labels == null) {
+ labels = new LabelList(1);
+ }
labels.add(curterm);
}
curterm = entries.get(i);
@@ -124,41 +127,33 @@ public class TermFrequencyParser extends NumberVectorLabelParser<SparseFloatVect
}
}
if(curterm != null) {
+ if(labels == null) {
+ labels = new LabelList(1);
+ }
labels.add(curterm);
}
-
- return new Pair<SparseFloatVector, LabelList>(new SparseFloatVector(values, maxdim), labels);
- }
-
- @Override
- public MultipleObjectsBundle parse(InputStream in) {
- BufferedReader reader = new BufferedReader(new InputStreamReader(in));
- int lineNumber = 1;
- List<SparseFloatVector> vectors = new ArrayList<SparseFloatVector>();
- List<LabelList> lblc = new ArrayList<LabelList>();
- try {
- for(String line; (line = reader.readLine()) != null; lineNumber++) {
- if(!line.startsWith(COMMENT) && line.length() > 0) {
- Pair<SparseFloatVector, LabelList> pair = parseLineInternal(line);
- vectors.add(pair.first);
- lblc.add(pair.second);
+ if(normalize) {
+ if(Math.abs(len - 1.0) > 1E-10 && len > 1E-10) {
+ for(TIntFloatIterator iter = values.iterator(); iter.hasNext();) {
+ iter.advance();
+ iter.setValue((float) (iter.value() / len));
}
}
}
- catch(IOException e) {
- throw new IllegalArgumentException("Error while parsing line " + lineNumber + ".");
- }
- // Set maximum dimensionality
- for(int i = 0; i < vectors.size(); i ++) {
- vectors.get(i).setDimensionality(maxdim);
- }
- return MultipleObjectsBundle.makeSimple(getTypeInformation(maxdim), vectors, TypeUtil.LABELLIST, lblc);
+
+ curvec = new SparseFloatVector(values, maxdim);
+ curlbl = labels;
}
@Override
- protected VectorFieldTypeInformation<SparseFloatVector> getTypeInformation(int dimensionality) {
- final Map<Integer, Float> emptyMap = Collections.emptyMap();
- return new VectorFieldTypeInformation<SparseFloatVector>(SparseFloatVector.class, dimensionality, new SparseFloatVector(emptyMap, dimensionality));
+ protected SimpleTypeInformation<SparseFloatVector> getTypeInformation(int dimensionality) {
+ if(dimensionality > 0) {
+ return new VectorFieldTypeInformation<SparseFloatVector>(SparseFloatVector.class, dimensionality, new SparseFloatVector(SparseFloatVector.EMPTYMAP, dimensionality));
+ }
+ if(dimensionality == DIMENSIONALITY_VARIABLE) {
+ return new SimpleTypeInformation<SparseFloatVector>(SparseFloatVector.class);
+ }
+ throw new AbortException("No vectors were read from the input file - cannot determine vector data type.");
}
@Override
@@ -174,9 +169,28 @@ public class TermFrequencyParser extends NumberVectorLabelParser<SparseFloatVect
* @apiviz.exclude
*/
public static class Parameterizer extends NumberVectorLabelParser.Parameterizer<SparseFloatVector> {
+ /**
+ * Option ID for normalization
+ */
+ public static final OptionID NORMALIZE_FLAG = OptionID.getOrCreateOptionID("tf.normalize", "Normalize vectors to manhattan length 1 (convert term counts to term frequencies)");
+
+ /**
+ * Normalization flag
+ */
+ boolean normalize = false;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ Flag normF = new Flag(NORMALIZE_FLAG);
+ if(config.grab(normF)) {
+ normalize = normF.getValue();
+ }
+ }
+
@Override
protected TermFrequencyParser makeInstance() {
- return new TermFrequencyParser(colSep, quoteChar, labelIndices);
+ return new TermFrequencyParser(normalize, colSep, quoteChar, labelIndices);
}
}
} \ No newline at end of file
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 e08a39d9..f1999262 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
@@ -39,7 +39,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2011
+Copyright (C) 2012
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 0b6ccd10..7a394b8b 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) 2011
+ Copyright (C) 2012
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/AbstractCosineDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractCosineDistanceFunction.java
deleted file mode 100644
index 61e4a22f..00000000
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractCosineDistanceFunction.java
+++ /dev/null
@@ -1,107 +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) 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 java.util.BitSet;
-
-import de.lmu.ifi.dbs.elki.data.NumberVector;
-import de.lmu.ifi.dbs.elki.data.SparseNumberVector;
-import de.lmu.ifi.dbs.elki.database.query.distance.PrimitiveDistanceQuery;
-import de.lmu.ifi.dbs.elki.database.relation.Relation;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
-import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
-
-/**
- * Abstract base class for Cosine and ArcCosine distances.
- *
- * @author Erich Schubert
- */
-public abstract class AbstractCosineDistanceFunction extends AbstractVectorDoubleDistanceFunction {
- /**
- * Constructor.
- */
- public AbstractCosineDistanceFunction() {
- super();
- }
-
- /**
- * Compute the angle between two vectors.
- *
- * @param v1 first vector
- * @param v2 second vector
- * @return Angle
- */
- protected double angle(NumberVector<?, ?> v1, NumberVector<?, ?> v2) {
- if(v1 instanceof SparseNumberVector<?, ?> && v2 instanceof SparseNumberVector<?, ?>) {
- return angleSparse((SparseNumberVector<?, ?>) v1, (SparseNumberVector<?, ?>) v2);
- }
- Vector m1 = v1.getColumnVector();
- m1.normalize();
- Vector m2 = v2.getColumnVector();
- m2.normalize();
- return m1.transposeTimes(m2);
- }
-
- /**
- * Compute the angle for sparse vectors.
- *
- * @param v1 First vector
- * @param v2 Second vector
- * @return angle
- */
- protected double angleSparse(SparseNumberVector<?, ?> v1, SparseNumberVector<?, ?> v2) {
- BitSet b1 = v1.getNotNullMask();
- BitSet b2 = v2.getNotNullMask();
- BitSet both = (BitSet) b1.clone();
- both.and(b2);
-
- // Length of first vector
- double l1 = 0.0;
- for(int i = b1.nextSetBit(0); i >= 0; i = b1.nextSetBit(i + 1)) {
- final double val = v1.doubleValue(i);
- l1 += val * val;
- }
- l1 = Math.sqrt(l1);
-
- // Length of second vector
- double l2 = 0.0;
- for(int i = b2.nextSetBit(0); i >= 0; i = b2.nextSetBit(i + 1)) {
- final double val = v2.doubleValue(i);
- l2 += val * val;
- }
- l2 = Math.sqrt(l2);
-
- // Cross product
- double cross = 0.0;
- for(int i = both.nextSetBit(0); i >= 0; i = both.nextSetBit(i + 1)) {
- cross += v1.doubleValue(i) * v2.doubleValue(i);
- }
- return cross / (l1 * l2);
- }
-
- @Override
- public <T extends NumberVector<?, ?>> PrimitiveDistanceQuery<T, DoubleDistance> instantiate(Relation<T> relation) {
- return new PrimitiveDistanceQuery<T, DoubleDistance>(relation, this);
- }
-} \ No newline at end of file
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 71d8d0bb..f1a53803 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) 2011
+ Copyright (C) 2012
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/AbstractDatabaseDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractDatabaseDistanceFunction.java
index 22e0cbc3..845ea0ea 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) 2011
+ Copyright (C) 2012
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/AbstractIndexBasedDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractIndexBasedDistanceFunction.java
index dfefb355..9280b783 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) 2011
+ Copyright (C) 2012
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/AbstractPrimitiveDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractPrimitiveDistanceFunction.java
index d4ec52b1..1c94bc28 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) 2011
+ Copyright (C) 2012
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/AbstractVectorDoubleDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractVectorDoubleDistanceFunction.java
index 4bc2a381..dbda2e96 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) 2011
+ Copyright (C) 2012
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.distance.distancevalue.DoubleDistance;
* @apiviz.uses NumberVector
* @apiviz.has DoubleDistance
*/
-public abstract class AbstractVectorDoubleDistanceFunction extends AbstractPrimitiveDistanceFunction<NumberVector<?, ?>, DoubleDistance> implements PrimitiveDoubleDistanceFunction<NumberVector<?, ?>> {
+public abstract class AbstractVectorDoubleDistanceFunction extends AbstractPrimitiveDistanceFunction<NumberVector<?, ?>, DoubleDistance> implements PrimitiveDoubleDistanceFunction<NumberVector<?, ?>>, NumberVectorDistanceFunction<DoubleDistance> {
/**
* Constructor.
*/
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractVectorDoubleDistanceNorm.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractVectorDoubleDistanceNorm.java
new file mode 100644
index 00000000..7a7785e1
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/AbstractVectorDoubleDistanceNorm.java
@@ -0,0 +1,40 @@
+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.distance.distancevalue.DoubleDistance;
+
+/**
+ * Abstract base class for double-valued number-vector-based distances based on
+ * norms.
+ *
+ * @author Erich Schubert
+ */
+public abstract class AbstractVectorDoubleDistanceNorm extends AbstractVectorDoubleDistanceFunction implements DoubleNorm<NumberVector<?, ?>> {
+ @Override
+ public DoubleDistance norm(NumberVector<?, ?> obj) {
+ return new DoubleDistance(doubleNorm(obj));
+ }
+} \ No newline at end of file
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 fd19bfef..03563c6f 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,6 +24,14 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
*/
import de.lmu.ifi.dbs.elki.data.NumberVector;
+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.optionhandling.AbstractParameterizer;
/**
@@ -34,12 +42,12 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
*
* @author Arthur Zimek
*/
-public class ArcCosineDistanceFunction extends AbstractCosineDistanceFunction {
+public class ArcCosineDistanceFunction extends AbstractVectorDoubleDistanceFunction implements SpatialPrimitiveDoubleDistanceFunction<NumberVector<?, ?>> {
/**
* Static instance
*/
public static final ArcCosineDistanceFunction STATIC = new ArcCosineDistanceFunction();
-
+
/**
* Provides a CosineDistanceFunction.
*
@@ -61,8 +69,8 @@ public class ArcCosineDistanceFunction extends AbstractCosineDistanceFunction {
* @return the cosine distance for two given feature vectors v1 and v2
*/
@Override
- public double doubleDistance(NumberVector<?,?> v1, NumberVector<?,?> v2) {
- double d = Math.acos(angle(v1, v2));
+ public double doubleDistance(NumberVector<?, ?> v1, NumberVector<?, ?> v2) {
+ double d = Math.acos(VectorUtil.cosAngle(v1, v2));
if(d < 0) {
d = 0;
}
@@ -70,6 +78,20 @@ public class ArcCosineDistanceFunction extends AbstractCosineDistanceFunction {
}
@Override
+ public double doubleMinDist(SpatialComparable mbr1, SpatialComparable mbr2) {
+ double d = Math.acos(VectorUtil.minCosAngle(mbr1, mbr2));
+ 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";
}
@@ -85,6 +107,16 @@ public class ArcCosineDistanceFunction extends AbstractCosineDistanceFunction {
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;
+ }
+
/**
* Parameterization class.
*
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/CanberraDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/CanberraDistanceFunction.java
new file mode 100644
index 00000000..6c8647ab
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/CanberraDistanceFunction.java
@@ -0,0 +1,127 @@
+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;
+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.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Canberra distance function, a variation of Manhattan distance.
+ *
+ * <p>
+ * Reference:<br />
+ * G. N. Lance, W. T. Williams<br />
+ * Computer programs for hierarchical polythetic classification ("similarity
+ * analysis")<br />
+ * In: Computer Journal, Volume 9, Issue 1
+ * </p>
+ *
+ * @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<?, ?>> {
+ /**
+ * Static instance. Use this!
+ */
+ public static final CanberraDistanceFunction STATIC = new CanberraDistanceFunction();
+
+ /**
+ * Constructor.
+ */
+ protected CanberraDistanceFunction() {
+ super();
+ }
+
+ @Override
+ public double doubleDistance(NumberVector<?, ?> o1, NumberVector<?, ?> o2) {
+ final int dim = o1.getDimensionality();
+ double sum = 0.0;
+ for(int i = 1; i <= dim; i++) {
+ double v1 = o1.doubleValue(i);
+ double v2 = o2.doubleValue(i);
+ final double div = Math.abs(v1) + Math.abs(v2);
+ if (div > 0) {
+ sum += Math.abs(v1 - v2) / div;
+ }
+ }
+ return sum;
+ }
+
+ @Override
+ public double doubleMinDist(SpatialComparable mbr1, SpatialComparable mbr2) {
+ final int dim = mbr1.getDimensionality();
+ double sum = 0.0;
+ for(int d = 1; 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!
+ 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;
+ }
+ }
+ return sum;
+ }
+
+ @Override
+ public DoubleDistance minDist(SpatialComparable mbr1, SpatialComparable mbr2) {
+ return new DoubleDistance(doubleMinDist(mbr1, mbr2));
+ }
+
+ @Override
+ public <T extends NumberVector<?, ?>> SpatialDistanceQuery<T, DoubleDistance> instantiate(Relation<T> relation) {
+ return new SpatialPrimitiveDistanceQuery<T, DoubleDistance>(relation, this);
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected CanberraDistanceFunction makeInstance() {
+ return CanberraDistanceFunction.STATIC;
+ }
+ }
+} \ No newline at end of file
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 25abe7ef..2d681dad 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,6 +24,14 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
*/
import de.lmu.ifi.dbs.elki.data.NumberVector;
+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.optionhandling.AbstractParameterizer;
/**
@@ -34,7 +42,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
*
* @author Arthur Zimek
*/
-public class CosineDistanceFunction extends AbstractCosineDistanceFunction {
+public class CosineDistanceFunction extends AbstractVectorDoubleDistanceFunction implements SpatialPrimitiveDoubleDistanceFunction<NumberVector<?, ?>> {
/**
* Static instance
*/
@@ -62,7 +70,7 @@ public class CosineDistanceFunction extends AbstractCosineDistanceFunction {
*/
@Override
public double doubleDistance(NumberVector<?, ?> v1, NumberVector<?, ?> v2) {
- double d = 1 - angle(v1, v2);
+ double d = 1 - VectorUtil.cosAngle(v1, v2);
if(d < 0) {
d = 0;
}
@@ -70,6 +78,20 @@ public class CosineDistanceFunction extends AbstractCosineDistanceFunction {
}
@Override
+ public double doubleMinDist(SpatialComparable mbr1, SpatialComparable mbr2) {
+ double d = 1 - VectorUtil.minCosAngle(mbr1, mbr2);
+ 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";
}
@@ -85,6 +107,16 @@ public class CosineDistanceFunction extends AbstractCosineDistanceFunction {
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;
+ }
+
/**
* Parameterization class.
*
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 25a74c19..c4e6a891 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) 2011
+ Copyright (C) 2012
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 cc8a3699..0d38b418 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) 2011
+ Copyright (C) 2012
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
new file mode 100644
index 00000000..3d7ed70f
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/DoubleNorm.java
@@ -0,0 +1,43 @@
+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.distance.distancevalue.DoubleDistance;
+
+/**
+ * Interface for norms in the double domain.
+ *
+ * @author Erich Schubert
+ *
+ * @param <O> Object type
+ */
+public interface DoubleNorm<O> extends Norm<O, DoubleDistance>, PrimitiveDoubleDistanceFunction<O> {
+ /**
+ * Compute the norm of object obj as double value.
+ *
+ * @param obj Object
+ * @return Double
+ */
+ public double doubleNorm(O obj);
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/EuclideanDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/EuclideanDistanceFunction.java
index 235bedb3..c0bc5696 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/EuclideanDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/EuclideanDistanceFunction.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,9 +25,6 @@ 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.utilities.optionhandling.AbstractParameterizer;
/**
@@ -72,6 +69,17 @@ public class EuclideanDistanceFunction extends LPNormDistanceFunction implements
return Math.sqrt(sqrDist);
}
+ @Override
+ public double doubleNorm(NumberVector<?, ?> v) {
+ final int dim = v.getDimensionality();
+ double sqrDist = 0;
+ for(int i = 1; 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()) {
@@ -121,8 +129,8 @@ public class EuclideanDistanceFunction extends LPNormDistanceFunction implements
for(int d = 1; d <= dim1; d++) {
final double m1, m2;
if(mbr1.getMax(d) < mbr2.getMin(d)) {
- m1 = mbr1.getMax(d);
- m2 = mbr2.getMin(d);
+ m1 = mbr2.getMin(d);
+ m2 = mbr1.getMax(d);
}
else if(mbr1.getMin(d) > mbr2.getMax(d)) {
m1 = mbr1.getMin(d);
@@ -138,44 +146,11 @@ public class EuclideanDistanceFunction extends LPNormDistanceFunction implements
}
@Override
- public DoubleDistance centerDistance(SpatialComparable mbr1, SpatialComparable mbr2) {
- return new DoubleDistance(doubleCenterDistance(mbr1, mbr2));
- }
-
- @Override
- public DoubleDistance minDist(SpatialComparable mbr1, SpatialComparable mbr2) {
- return new DoubleDistance(doubleMinDist(mbr1, mbr2));
- }
-
- @Override
- public double doubleCenterDistance(SpatialComparable mbr1, SpatialComparable 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 = 1; d <= dim1; d++) {
- final double c1 = (mbr1.getMin(d) + mbr1.getMax(d)) / 2;
- final double c2 = (mbr2.getMin(d) + mbr2.getMax(d)) / 2;
-
- final double manhattanI = c1 - c2;
- sqrDist += manhattanI * manhattanI;
- }
- return Math.sqrt(sqrDist);
- }
-
- @Override
public boolean isMetric() {
return true;
}
@Override
- public <T extends NumberVector<?, ?>> SpatialPrimitiveDistanceQuery<T, DoubleDistance> instantiate(Relation<T> relation) {
- return new SpatialPrimitiveDistanceQuery<T, DoubleDistance>(relation, this);
- }
-
- @Override
public String toString() {
return "EuclideanDistance";
}
@@ -188,7 +163,7 @@ public class EuclideanDistanceFunction extends LPNormDistanceFunction implements
if(obj == this) {
return true;
}
- if (this.getClass().equals(obj.getClass())) {
+ if(this.getClass().equals(obj.getClass())) {
return true;
}
return super.equals(obj);
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 0bd93ede..03074815 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) 2011
+ Copyright (C) 2012
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 aac19541..8663c8c3 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) 2011
+ Copyright (C) 2012
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/JeffreyDivergenceDistanceFunction.java
new file mode 100644
index 00000000..3aa6908f
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/JeffreyDivergenceDistanceFunction.java
@@ -0,0 +1,100 @@
+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.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Provides the Jeffrey Divergence Distance for FeatureVectors.
+ *
+ * @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 {
+ /**
+ * Static instance. Use this!
+ */
+ public static final JeffreyDivergenceDistanceFunction STATIC = new JeffreyDivergenceDistanceFunction();
+
+ /**
+ * Constructor for the Jeffrey divergence.
+ *
+ * @deprecated Use static instance!
+ */
+ @Deprecated
+ public JeffreyDivergenceDistanceFunction() {
+ }
+
+ @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 = 1; i <= dim1; i++) {
+ final double xi = v1.doubleValue(i);
+ final double yi = v2.doubleValue(i);
+ final double mi = (xi + yi) / 2;
+ dist += xi * Math.log(xi / mi);
+ dist += yi * Math.log(yi / mi);
+ }
+ return dist;
+ }
+
+ @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 JeffreyDivergenceDistanceFunction.STATIC;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/LPNormDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/LPNormDistanceFunction.java
index d17825e9..134b587f 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/LPNormDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/LPNormDistanceFunction.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,6 +24,10 @@ 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.utilities.optionhandling.AbstractParameterizer;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterConstraint;
@@ -37,9 +41,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleParameter;
*
* @apiviz.landmark
*/
-public class LPNormDistanceFunction extends AbstractVectorDoubleDistanceFunction {
- // TODO: implement SpatialPrimitiveDoubleDistanceFunction?
-
+public class LPNormDistanceFunction extends AbstractVectorDoubleDistanceNorm implements SpatialPrimitiveDoubleDistanceFunction<NumberVector<?, ?>> {
/**
* OptionID for the "p" parameter
*/
@@ -84,6 +86,17 @@ public class LPNormDistanceFunction extends AbstractVectorDoubleDistanceFunction
return Math.pow(sqrDist, 1.0 / p);
}
+ @Override
+ public double doubleNorm(NumberVector<?, ?> v) {
+ final int dim = v.getDimensionality();
+ double sqrDist = 0;
+ for(int i = 1; i <= dim; i++) {
+ final double delta = v.doubleValue(i);
+ sqrDist += Math.pow(delta, p);
+ }
+ return Math.pow(sqrDist, 1.0 / p);
+ }
+
/**
* Get the functions p parameter.
*
@@ -94,6 +107,45 @@ public class LPNormDistanceFunction extends AbstractVectorDoubleDistanceFunction
}
@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 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 = 1; 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;
+ sumDist += Math.pow(manhattanI, p);
+ }
+ return Math.pow(sumDist, 1.0 / p);
+ }
+
+ @Override
+ public DoubleDistance minDist(SpatialComparable mbr1, SpatialComparable mbr2) {
+ return new DoubleDistance(doubleMinDist(mbr1, mbr2));
+ }
+
+ @Override
public boolean isMetric() {
return (p >= 1);
}
@@ -114,6 +166,11 @@ public class LPNormDistanceFunction extends AbstractVectorDoubleDistanceFunction
return false;
}
+ @Override
+ public <T extends NumberVector<?, ?>> SpatialPrimitiveDistanceQuery<T, DoubleDistance> instantiate(Relation<T> relation) {
+ return new SpatialPrimitiveDistanceQuery<T, DoubleDistance>(relation, this);
+ }
+
/**
* Parameterization class.
*
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 1345013b..ee3cc438 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -132,11 +132,11 @@ public class LocallyWeightedDistanceFunction<V extends NumberVector<?, ?>> exten
V v1 = relation.get(id1);
V v2 = relation.get(id2);
- Vector v1Mv2 = v1.getColumnVector().minus(v2.getColumnVector());
- Vector v2Mv1 = v2.getColumnVector().minus(v1.getColumnVector());
+ Vector v1Mv2 = v1.getColumnVector().minusEquals(v2.getColumnVector());
+ Vector v2Mv1 = v2.getColumnVector().minusEquals(v1.getColumnVector());
- double dist1 = v1Mv2.transposeTimes(m1).times(v1Mv2).get(0, 0);
- double dist2 = v2Mv1.transposeTimes(m2).times(v2Mv1).get(0, 0);
+ double dist1 = v1Mv2.transposeTimesTimes(m1, v1Mv2);
+ double dist2 = v2Mv1.transposeTimesTimes(m2, v2Mv1);
if(dist1 < 0) {
if(-dist1 < 0.000000000001) {
@@ -180,8 +180,8 @@ public class LocallyWeightedDistanceFunction<V extends NumberVector<?, ?>> exten
}
Matrix m = null; // index.getLocalProjection(v.getID()).similarityMatrix();
- Vector rv1Mrv2 = v.getColumnVector().minus(new Vector(r));
- double dist = rv1Mrv2.transposeTimes(m).times(rv1Mrv2).get(0, 0);
+ Vector rv1Mrv2 = v.getColumnVector().minusEquals(new Vector(r));
+ double dist = rv1Mrv2.transposeTimesTimes(m, rv1Mrv2);
return new DoubleDistance(Math.sqrt(dist));
}
@@ -203,8 +203,8 @@ public class LocallyWeightedDistanceFunction<V extends NumberVector<?, ?>> exten
for(int d = 1; d <= mbr1.getDimensionality(); d++) {
double m1, m2;
if(mbr1.getMax(d) < mbr2.getMin(d)) {
- m1 = mbr1.getMax(d);
- m2 = mbr2.getMin(d);
+ m1 = mbr2.getMin(d);
+ m2 = mbr1.getMax(d);
}
else if(mbr1.getMin(d) > mbr2.getMax(d)) {
m1 = mbr1.getMin(d);
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/ManhattanDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/ManhattanDistanceFunction.java
index 8cbe0fdb..c638ce13 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/ManhattanDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/ManhattanDistanceFunction.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,9 +25,6 @@ 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.utilities.optionhandling.AbstractParameterizer;
/**
@@ -73,8 +70,24 @@ public class ManhattanDistanceFunction extends LPNormDistanceFunction implements
}
return sum;
}
+
+ /**
+ * 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 = 1; i <= dim; i++) {
+ sum += Math.abs(v.doubleValue(i));
+ }
+ return sum;
+ }
- protected double doubleMinDistObject(SpatialComparable mbr, NumberVector<?, ?> v) {
+ 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());
@@ -94,8 +107,8 @@ public class ManhattanDistanceFunction extends LPNormDistanceFunction implements
r = value;
}
- final double manhattanI = value - r;
- sumDist += Math.abs(manhattanI);
+ final double manhattanI = Math.abs(value - r);
+ sumDist += manhattanI;
}
return sumDist;
}
@@ -123,8 +136,8 @@ public class ManhattanDistanceFunction extends LPNormDistanceFunction implements
for(int d = 1; d <= dim1; d++) {
final double m1, m2;
if(mbr1.getMax(d) < mbr2.getMin(d)) {
- m1 = mbr1.getMax(d);
- m2 = mbr2.getMin(d);
+ m1 = mbr2.getMin(d);
+ m2 = mbr1.getMax(d);
}
else if(mbr1.getMin(d) > mbr2.getMax(d)) {
m1 = mbr1.getMin(d);
@@ -134,50 +147,17 @@ public class ManhattanDistanceFunction extends LPNormDistanceFunction implements
continue;
}
final double manhattanI = m1 - m2;
- sumDist += Math.abs(manhattanI);
- }
- return sumDist;
- }
-
- @Override
- public double doubleCenterDistance(SpatialComparable mbr1, SpatialComparable 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 sumDist = 0;
- for(int d = 1; d <= dim1; d++) {
- final double c1 = (mbr1.getMin(d) + mbr1.getMax(d)) / 2;
- final double c2 = (mbr2.getMin(d) + mbr2.getMax(d)) / 2;
-
- final double manhattanI = c1 - c2;
- sumDist += Math.abs(manhattanI);
+ sumDist += manhattanI;
}
return sumDist;
}
@Override
- public DoubleDistance minDist(SpatialComparable mbr1, SpatialComparable mbr2) {
- return new DoubleDistance(doubleMinDist(mbr1, mbr2));
- }
-
- @Override
- public DoubleDistance centerDistance(SpatialComparable mbr1, SpatialComparable mbr2) {
- return new DoubleDistance(doubleCenterDistance(mbr1, mbr2));
- }
-
- @Override
public boolean isMetric() {
return true;
}
@Override
- public <T extends NumberVector<?, ?>> SpatialPrimitiveDistanceQuery<T, DoubleDistance> instantiate(Relation<T> relation) {
- return new SpatialPrimitiveDistanceQuery<T, DoubleDistance>(relation, this);
- }
-
- @Override
public String toString() {
return "ManhattanDistance";
}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/MaximumDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/MaximumDistanceFunction.java
index ece11645..e718d087 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/MaximumDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/MaximumDistanceFunction.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,10 +25,6 @@ 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.optionhandling.AbstractParameterizer;
/**
@@ -69,6 +65,16 @@ public class MaximumDistanceFunction extends LPNormDistanceFunction implements S
}
@Override
+ public double doubleNorm(NumberVector<?, ?> v) {
+ final int dim = v.getDimensionality();
+ double max = 0;
+ for(int i = 1; i <= dim; i++) {
+ max = Math.max(v.doubleValue(i), max);
+ }
+ return max;
+ }
+
+ @Override
public double doubleMinDist(SpatialComparable mbr1, SpatialComparable mbr2) {
final int dim1 = mbr1.getDimensionality();
if(dim1 != mbr2.getDimensionality()) {
@@ -93,42 +99,11 @@ public class MaximumDistanceFunction extends LPNormDistanceFunction implements S
}
@Override
- public double doubleCenterDistance(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 = 1; i <= dim1; i++) {
- final double c1 = (mbr1.getMax(i) - mbr1.getMin(i)) / 2;
- final double c2 = (mbr2.getMax(i) - mbr2.getMin(i)) / 2;
- final double d = Math.abs(c2 - c1);
- max = Math.max(d, max);
- }
- return max;
- }
-
- @Override
- public DoubleDistance minDist(SpatialComparable mbr1, SpatialComparable mbr2) {
- return new DoubleDistance(doubleMinDist(mbr1, mbr2));
- }
-
- @Override
- public DoubleDistance centerDistance(SpatialComparable mbr1, SpatialComparable mbr2) {
- return new DoubleDistance(doubleCenterDistance(mbr1, mbr2));
- }
-
- @Override
public boolean isMetric() {
return true;
}
@Override
- public <T extends NumberVector<?, ?>> SpatialDistanceQuery<T, DoubleDistance> instantiate(Relation<T> relation) {
- return new SpatialPrimitiveDistanceQuery<T, DoubleDistance>(relation, this);
- }
-
- @Override
public String toString() {
return "MaximumDistance";
}
@@ -141,7 +116,7 @@ public class MaximumDistanceFunction extends LPNormDistanceFunction implements S
if(obj == this) {
return true;
}
- if (this.getClass().equals(obj.getClass())) {
+ if(this.getClass().equals(obj.getClass())) {
return true;
}
return super.equals(obj);
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 9c03134c..ef805c6d 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,16 +23,14 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.List;
-
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.DBID;
import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery;
-import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
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.query.knn.KNNResult;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.DistanceUtil;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
@@ -139,6 +137,11 @@ public class MinKDistance<O, D extends Distance<D>> extends AbstractDatabaseDist
private int k;
/**
+ * Distance query for parent distance.
+ */
+ private DistanceQuery<T, D> parentDistanceQuery;
+
+ /**
* Constructor.
*
* @param relation Database
@@ -147,13 +150,14 @@ public class MinKDistance<O, D extends Distance<D>> extends AbstractDatabaseDist
public Instance(Relation<T> relation, int k, DistanceFunction<? super O, D> parentDistance) {
super(relation);
this.k = k;
+ this.parentDistanceQuery = parentDistance.instantiate(relation);
this.knnQuery = QueryUtil.getKNNQuery(relation, parentDistance, k, DatabaseQuery.HINT_HEAVY_USE);
}
@Override
public D distance(DBID id1, DBID id2) {
- List<DistanceResultPair<D>> neighborhood = knnQuery.getKNNForDBID(id1, k);
- D truedist = knnQuery.getDistanceQuery().distance(id1, id2);
+ KNNResult<D> neighborhood = knnQuery.getKNNForDBID(id1, k);
+ D truedist = parentDistanceQuery.distance(id1, id2);
return computeReachdist(neighborhood, truedist);
}
@@ -171,7 +175,7 @@ public class MinKDistance<O, D extends Distance<D>> extends AbstractDatabaseDist
* @param truedist True distance
* @return Reachability distance
*/
- protected D computeReachdist(List<DistanceResultPair<D>> neighborhood, D truedist) {
+ protected D computeReachdist(KNNResult<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?
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/MinimumDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/MinimumDistanceFunction.java
index c9c00cc4..2a31a829 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/MinimumDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/MinimumDistanceFunction.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -37,7 +37,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
* @author Erich Schubert
*/
// TODO: add spatial?
-public class MinimumDistanceFunction extends AbstractVectorDoubleDistanceFunction implements SpatialPrimitiveDoubleDistanceFunction<NumberVector<?, ?>> {
+public class MinimumDistanceFunction extends AbstractVectorDoubleDistanceNorm implements SpatialPrimitiveDoubleDistanceFunction<NumberVector<?, ?>> {
/**
* Static instance. Use this.
*/
@@ -69,6 +69,16 @@ public class MinimumDistanceFunction extends AbstractVectorDoubleDistanceFunctio
}
@Override
+ public double doubleNorm(NumberVector<?, ?> v) {
+ final int dim = v.getDimensionality();
+ double min = Double.POSITIVE_INFINITY;
+ for(int i = 1; i <= dim; i++) {
+ min = Math.min(v.doubleValue(i), min);
+ }
+ return min;
+ }
+
+ @Override
public double doubleMinDist(SpatialComparable mbr1, SpatialComparable mbr2) {
final int dim = mbr1.getDimensionality();
if(dim != mbr2.getDimensionality()) {
@@ -98,30 +108,11 @@ public class MinimumDistanceFunction extends AbstractVectorDoubleDistanceFunctio
}
@Override
- public double doubleCenterDistance(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 = 1; i <= dim; i++) {
- final double d = Math.abs((mbr1.getMin(i) + mbr1.getMax(i)) / 2 - (mbr2.getMin(i) + mbr1.getMax(i)) / 2);
- min = Math.min(d, min);
- }
- return min;
- }
-
- @Override
public DoubleDistance minDist(SpatialComparable mbr1, SpatialComparable mbr2) {
return new DoubleDistance(doubleMinDist(mbr1, mbr2));
}
@Override
- public DoubleDistance centerDistance(SpatialComparable mbr1, SpatialComparable mbr2) {
- return new DoubleDistance(doubleCenterDistance(mbr1, mbr2));
- }
-
- @Override
public String toString() {
return "MinimumDistance";
}
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/Norm.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/Norm.java
new file mode 100644
index 00000000..98ef1f1d
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/Norm.java
@@ -0,0 +1,44 @@
+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.distance.distancevalue.Distance;
+
+/**
+ * Abstract interface for a mathematical norm.
+ *
+ * @author Erich Schubert
+ *
+ * @param <O> Object type
+ * @param <D> Distance type
+ */
+public interface Norm<O, D extends Distance<D>> extends DistanceFunction<O, D> {
+ /**
+ * Compute the norm of object obj.
+ *
+ * @param obj Object
+ * @return Norm
+ */
+ public D norm(O obj);
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/designpattern/Observable.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/NumberVectorDistanceFunction.java
index 82e56164..68034672 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/designpattern/Observable.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/NumberVectorDistanceFunction.java
@@ -1,4 +1,4 @@
-package de.lmu.ifi.dbs.elki.utilities.designpattern;
+package de.lmu.ifi.dbs.elki.distance.distancefunction;
/*
This file is part of ELKI:
@@ -23,27 +23,18 @@ package de.lmu.ifi.dbs.elki.utilities.designpattern;
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.distancevalue.Distance;
/**
- * Observable design pattern.
+ * Base interface for the common case of distance functions defined on numerical vectors.
*
* @author Erich Schubert
*
- * @apiviz.has Observers
- *
- * @param <T> the object to observer
+ * @apiviz.landmark
+ *
+ * @param <D> Distance type
*/
-public interface Observable<T> {
- /**
- * Add an observer to the object.
- *
- * @param o Observer to add
- */
- public void addObserver(Observer<? super T> o);
- /**
- * Remove an observer from the object.
- *
- * @param o Observer to remove
- */
- public void removeObserver(Observer<? super T> o);
-} \ No newline at end of file
+public interface NumberVectorDistanceFunction<D extends Distance<D>> extends PrimitiveDistanceFunction<NumberVector<?, ?>, D> {
+ // Empty - marker interface
+}
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 d27d9a38..f8b62225 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) 2011
+ Copyright (C) 2012
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 03306ef0..e4d19702 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) 2011
+ Copyright (C) 2012
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 909b1120..9afdbecd 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) 2011
+ Copyright (C) 2012
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/RandomStableDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/RandomStableDistanceFunction.java
index 3d5715ec..0632d475 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) 2011
+ Copyright (C) 2012
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 0b80f512..cfc4217e 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,7 +26,7 @@ package de.lmu.ifi.dbs.elki.distance.distancefunction;
import java.util.Iterator;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.database.ids.TreeSetDBIDs;
+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.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.index.preprocessed.snn.SharedNearestNeighborIndex;
@@ -39,7 +39,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameteriz
*
* @author Erich Schubert
*
- * @apiviz.composedOf de.lmu.ifi.dbs.elki.index.preprocessed.snn.SharedNearestNeighborIndex.Factory
+ * @apiviz.composedOf SharedNearestNeighborIndex.Factory
* @apiviz.has SharedNearestNeighborJaccardDistanceFunction.Instance oneway - - «create»
*
* @param <O> object type
@@ -82,7 +82,14 @@ public class SharedNearestNeighborJaccardDistanceFunction<O> extends AbstractInd
super(database, preprocessor, parent);
}
- static protected double jaccardCoefficient(TreeSetDBIDs neighbors1, TreeSetDBIDs neighbors2) {
+ /**
+ * Compute the Jaccard coefficient
+ *
+ * @param neighbors1 SORTED neighbor ids of first
+ * @param neighbors2 SORTED neighbor ids of second
+ * @return Jaccard coefficient
+ */
+ static protected double jaccardCoefficient(DBIDs neighbors1, DBIDs neighbors2) {
int intersection = 0;
int union = 0;
Iterator<DBID> iter1 = neighbors1.iterator();
@@ -118,8 +125,8 @@ public class SharedNearestNeighborJaccardDistanceFunction<O> extends AbstractInd
@Override
public DoubleDistance distance(DBID id1, DBID id2) {
- TreeSetDBIDs neighbors1 = index.getNearestNeighborSet(id1);
- TreeSetDBIDs neighbors2 = index.getNearestNeighborSet(id2);
+ DBIDs neighbors1 = index.getNearestNeighborSet(id1);
+ DBIDs neighbors2 = index.getNearestNeighborSet(id2);
return new DoubleDistance(1.0 - jaccardCoefficient(neighbors1, neighbors2));
}
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 2dd6bd06..27dd1219 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -32,33 +32,22 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
* API for a spatial primitive distance function.
*
* @author Erich Schubert
- *
+ *
* @param <V> Vector type
* @param <D> Distance type
*/
public interface SpatialPrimitiveDistanceFunction<V extends SpatialComparable, D extends Distance<D>> extends PrimitiveDistanceFunction<V, D> {
/**
- * Computes the distance between the two given MBRs according to this
- * distance function.
+ * Computes the distance between the two given MBRs according to this distance
+ * function.
*
* @param mbr1 the first MBR object
* @param mbr2 the second MBR object
- * @return the distance between the two given MBRs according to this
- * distance function
+ * @return the distance between the two given MBRs according to this distance
+ * function
*/
D minDist(SpatialComparable mbr1, SpatialComparable mbr2);
- /**
- * Computes the distance between the centroids of the two given MBRs
- * according to this distance function.
- *
- * @param mbr1 the first MBR object
- * @param mbr2 the second MBR object
- * @return the distance between the centroids of the two given MBRs
- * according to this distance function
- */
- D centerDistance(SpatialComparable mbr1, SpatialComparable mbr2);
-
@Override
public <T extends V> SpatialDistanceQuery<T, D> instantiate(Relation<T> relation);
} \ No newline at end of file
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 07527baa..9ae39089 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -49,15 +49,4 @@ public interface SpatialPrimitiveDoubleDistanceFunction<V extends SpatialCompara
* distance function
*/
double doubleMinDist(SpatialComparable mbr1, SpatialComparable mbr2);
-
- /**
- * Computes the distance between the centroids of the two given MBRs
- * according to this distance function.
- *
- * @param mbr1 the first MBR object
- * @param mbr2 the second MBR object
- * @return the distance between the centroids of the two given MBRs
- * according to this distance function
- */
- double doubleCenterDistance(SpatialComparable mbr1, SpatialComparable mbr2);
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/SquaredEuclideanDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/SquaredEuclideanDistanceFunction.java
index e899b1e2..80edcc09 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/SquaredEuclideanDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/SquaredEuclideanDistanceFunction.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -36,7 +36,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
*
* @author Arthur Zimek
*/
-public class SquaredEuclideanDistanceFunction extends AbstractVectorDoubleDistanceFunction implements SpatialPrimitiveDoubleDistanceFunction<NumberVector<?, ?>> {
+public class SquaredEuclideanDistanceFunction extends AbstractVectorDoubleDistanceNorm implements SpatialPrimitiveDoubleDistanceFunction<NumberVector<?, ?>> {
/**
* Static instance. Use this!
*/
@@ -53,6 +53,17 @@ public class SquaredEuclideanDistanceFunction extends AbstractVectorDoubleDistan
super();
}
+ @Override
+ public double doubleNorm(NumberVector<?, ?> v) {
+ final int dim = v.getDimensionality();
+ double sum = 0;
+ for(int i = 1; i <= dim; i++) {
+ final double val = v.doubleValue(i);
+ sum += val * val;
+ }
+ return sum;
+ }
+
/**
* Provides the squared Euclidean distance between the given two vectors.
*
@@ -122,8 +133,8 @@ public class SquaredEuclideanDistanceFunction extends AbstractVectorDoubleDistan
for(int d = 1; d <= dim1; d++) {
final double m1, m2;
if(mbr1.getMax(d) < mbr2.getMin(d)) {
- m1 = mbr1.getMax(d);
- m2 = mbr2.getMin(d);
+ m1 = mbr2.getMin(d);
+ m2 = mbr1.getMax(d);
}
else if(mbr1.getMin(d) > mbr2.getMax(d)) {
m1 = mbr1.getMin(d);
@@ -139,29 +150,6 @@ public class SquaredEuclideanDistanceFunction extends AbstractVectorDoubleDistan
}
@Override
- public double doubleCenterDistance(SpatialComparable mbr1, SpatialComparable 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 = 1; d <= dim1; d++) {
- final double c1 = (mbr1.getMin(d) + mbr1.getMax(d)) / 2;
- final double c2 = (mbr2.getMin(d) + mbr2.getMax(d)) / 2;
-
- final double manhattanI = c1 - c2;
- sqrDist += manhattanI * manhattanI;
- }
- return sqrDist;
- }
-
- @Override
- public DoubleDistance centerDistance(SpatialComparable mbr1, SpatialComparable mbr2) {
- return new DoubleDistance(doubleCenterDistance(mbr1, mbr2));
- }
-
- @Override
public DoubleDistance minDist(SpatialComparable mbr1, SpatialComparable mbr2) {
return new DoubleDistance(doubleMinDist(mbr1, mbr2));
}
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 201a999d..046cc3e9 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -59,14 +59,10 @@ public class WeightedDistanceFunction extends AbstractVectorDoubleDistanceFuncti
*/
@Override
public double doubleDistance(NumberVector<?, ?> o1, NumberVector<?, ?> o2) {
- if(o1.getDimensionality() != o2.getDimensionality()) {
- throw new IllegalArgumentException("Different dimensionality of FeatureVectors" + "\n first argument: " + o1.toString() + "\n second argument: " + o2.toString());
- }
+ assert (o1.getDimensionality() == o2.getDimensionality()) : "Different dimensionality of FeatureVectors" + "\n first argument: " + o1.toString() + "\n second argument: " + o2.toString();
- Vector o1_minus_o2 = o1.getColumnVector().minus(o2.getColumnVector());
- double dist = MathUtil.mahalanobisDistance(weightMatrix, o1_minus_o2);
-
- return dist;
+ Vector o1_minus_o2 = o1.getColumnVector().minusEquals(o2.getColumnVector());
+ return MathUtil.mahalanobisDistance(weightMatrix, o1_minus_o2);
}
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/WeightedLPNormDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/WeightedLPNormDistanceFunction.java
index a31ed6e7..38302573 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/WeightedLPNormDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/WeightedLPNormDistanceFunction.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) 2011
+ Copyright (C) 2012
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.distance.distancefunction;
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 Euclidean distance function.
@@ -68,6 +69,41 @@ public class WeightedLPNormDistanceFunction extends LPNormDistanceFunction {
}
return Math.pow(sqrDist, 1.0 / p);
}
+
+ @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 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 = 1; 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;
+ sumDist += Math.pow(manhattanI, p) * weights[d - 1];
+ }
+ return Math.pow(sumDist, 1.0 / p);
+ }
@Override
public boolean equals(Object obj) {
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/WeightedSquaredEuclideanDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/WeightedSquaredEuclideanDistanceFunction.java
index d1bcbf26..a2944385 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/WeightedSquaredEuclideanDistanceFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/WeightedSquaredEuclideanDistanceFunction.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) 2011
+ Copyright (C) 2012
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/adapter/AbstractSimilarityAdapter.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/AbstractSimilarityAdapter.java
index 7f610d8b..206a32e7 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) 2011
+ Copyright (C) 2012
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/adapter/SimilarityAdapterArccos.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/SimilarityAdapterArccos.java
index 4f1814ec..d1a5aa4a 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/SimilarityAdapterArccos.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/SimilarityAdapterArccos.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) 2011
+ Copyright (C) 2012
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/adapter/SimilarityAdapterLinear.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/SimilarityAdapterLinear.java
index 664b6421..e2c0f981 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/SimilarityAdapterLinear.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/SimilarityAdapterLinear.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) 2011
+ Copyright (C) 2012
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/adapter/SimilarityAdapterLn.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/SimilarityAdapterLn.java
index 8d7ec170..a45b6108 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/SimilarityAdapterLn.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/SimilarityAdapterLn.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) 2011
+ Copyright (C) 2012
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/adapter/package-info.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/adapter/package-info.java
index 1f92d5fc..303d3500 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) 2011
+Copyright (C) 2012
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 05c766ca..4eff8822 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) 2011
+ Copyright (C) 2012
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/HistogramIntersectionDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/colorhistogram/HistogramIntersectionDistanceFunction.java
index 362f3589..6ed8e744 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -70,11 +70,6 @@ public class HistogramIntersectionDistanceFunction extends AbstractVectorDoubleD
}
@Override
- public DoubleDistance centerDistance(SpatialComparable mbr1, SpatialComparable mbr2) {
- return new DoubleDistance(doubleCenterDistance(mbr1, mbr2));
- }
-
- @Override
public double doubleDistance(NumberVector<?, ?> v1, NumberVector<?, ?> v2) {
final int dim1 = v1.getDimensionality();
if(dim1 != v2.getDimensionality()) {
@@ -117,26 +112,6 @@ public class HistogramIntersectionDistanceFunction extends AbstractVectorDoubleD
}
@Override
- public double doubleCenterDistance(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 = 1; i <= dim1; i++) {
- final double val1 = (mbr1.getMin(i) + mbr1.getMax(i)) / 2;
- final double val2 = (mbr2.getMin(i) + mbr2.getMax(i)) / 2;
- dist += Math.min(val1, val2);
- norm1 += val1;
- norm2 += val2;
- }
- 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);
}
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 b902d43e..5ba02e17 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) 2011
+ Copyright (C) 2012
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 2d1c85bb..43e90206 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) 2011
+Copyright (C) 2012
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 08c4ce3b..d59851b9 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) 2011
+ Copyright (C) 2012
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.index.preprocessed.localpca.FilteredLocalPCAIndex;
import de.lmu.ifi.dbs.elki.index.preprocessed.localpca.KNNQueryFilteredPCAIndex;
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.math.linearalgebra.pca.PCAFilteredResult;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterEqualConstraint;
@@ -135,10 +136,10 @@ public class ERiCDistanceFunction extends AbstractIndexBasedDistanceFunction<Num
Matrix m1_czech = pca1.dissimilarityMatrix();
Matrix v2_strong = pca2.adapatedStrongEigenvectors();
for(int i = 0; i < v2_strong.getColumnDimensionality(); i++) {
- Matrix v2_i = v2_strong.getColumn(i);
+ Vector v2_i = v2_strong.getCol(i);
// check, if distance of v2_i to the space of pca_1 > delta
// (i.e., if v2_i spans up a new dimension)
- double dist = Math.sqrt(v2_i.transposeTimes(v2_i).get(0, 0) - v2_i.transposeTimes(m1_czech).times(v2_i).get(0, 0));
+ double dist = Math.sqrt(v2_i.transposeTimes(v2_i) - v2_i.transposeTimesTimes(m1_czech, v2_i));
// if so, return false
if(dist > delta) {
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 fdfac072..05ae0e13 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) 2011
+ Copyright (C) 2012
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.index.preprocessed.localpca.FilteredLocalPCAIndex;
import de.lmu.ifi.dbs.elki.index.preprocessed.localpca.KNNQueryFilteredPCAIndex;
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.math.linearalgebra.pca.PCAFilteredResult;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterEqualConstraint;
@@ -172,10 +173,10 @@ public class PCABasedCorrelationDistanceFunction extends AbstractIndexBasedDista
// for all strong eigenvectors of rv2
Matrix m1_czech = pca1.dissimilarityMatrix();
for(int i = 0; i < v2_strong.getColumnDimensionality(); i++) {
- Matrix v2_i = v2_strong.getColumn(i);
+ Vector v2_i = v2_strong.getCol(i);
// check, if distance of v2_i to the space of rv1 > delta
// (i.e., if v2_i spans up a new dimension)
- double dist = Math.sqrt(v2_i.transposeTimes(v2_i).get(0, 0) - v2_i.transposeTimes(m1_czech).times(v2_i).get(0, 0));
+ double dist = Math.sqrt(v2_i.transposeTimes(v2_i) - v2_i.transposeTimesTimes(m1_czech, v2_i));
// if so, insert v2_i into v1 and adjust v1
// and compute m1_czech new, increase lambda1
@@ -188,10 +189,10 @@ public class PCABasedCorrelationDistanceFunction extends AbstractIndexBasedDista
// for all strong eigenvectors of rv1
Matrix m2_czech = pca2.dissimilarityMatrix();
for(int i = 0; i < v1_strong.getColumnDimensionality(); i++) {
- Matrix v1_i = v1_strong.getColumn(i);
+ Vector v1_i = v1_strong.getCol(i);
// check, if distance of v1_i to the space of rv2 > delta
// (i.e., if v1_i spans up a new dimension)
- double dist = Math.sqrt(v1_i.transposeTimes(v1_i).get(0, 0) - v1_i.transposeTimes(m2_czech).times(v1_i).get(0, 0));
+ double dist = Math.sqrt(v1_i.transposeTimes(v1_i) - v1_i.transposeTimes(m2_czech).times(v1_i).get(0));
// if so, insert v1_i into v2 and adjust v2
// and compute m2_czech new , increase lambda2
@@ -227,22 +228,22 @@ public class PCABasedCorrelationDistanceFunction extends AbstractIndexBasedDista
* @param vector the vector to be inserted
* @param corrDim the column at which the vector should be inserted
*/
- private void adjust(Matrix v, Matrix e_czech, Matrix vector, int corrDim) {
+ private void adjust(Matrix v, Matrix e_czech, Vector vector, int corrDim) {
int dim = v.getRowDimensionality();
// set e_czech[corrDim][corrDim] := 1
e_czech.set(corrDim, corrDim, 1);
// normalize v
- Matrix v_i = vector.copy();
- Matrix sum = new Matrix(dim, 1);
+ Vector v_i = vector.copy();
+ Vector sum = new Vector(dim);
for(int k = 0; k < corrDim; k++) {
- Matrix v_k = v.getColumn(k);
- sum.plusEquals(v_k.timesEquals(v_i.scalarProduct(0, v_k, 0)));
+ Vector v_k = v.getCol(k);
+ sum.plusTimesEquals(v_k, v_i.transposeTimes(v_k));
}
v_i.minusEquals(sum);
- v_i.timesEquals(1.0 / Math.sqrt(v_i.scalarProduct(0, v_i, 0)));
- v.setColumn(corrDim, v_i);
+ v_i.normalize();
+ v.setCol(corrDim, v_i);
}
/**
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 96e5262e..a618ae36 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) 2011
+ Copyright (C) 2012
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 786fcd82..86d822d3 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) 2011
+ Copyright (C) 2012
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 adabd90f..01e41f1b 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) 2011
+ Copyright (C) 2012
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/WeightedSquaredPearsonCorrelationDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/correlation/WeightedSquaredPearsonCorrelationDistanceFunction.java
index e7abca9b..8b5ecd98 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) 2011
+ Copyright (C) 2012
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 f82c7b92..2033dab1 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) 2011
+Copyright (C) 2012
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 e541452e..9d92d727 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) 2011
+ Copyright (C) 2012
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 b9ebbf9e..ff6b5e3d 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) 2011
+ Copyright (C) 2012
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/DistanceParser.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/DistanceParser.java
index ce8d60e1..93874eaf 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/parser/DistanceParser.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/DistanceParser.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.datasource.parser;
+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) 2011
+ Copyright (C) 2012
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.parser;
import java.io.InputStream;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
/**
* A DistanceParser shall provide a DistanceParsingResult by parsing an InputStream.
@@ -38,6 +39,11 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
*/
public interface DistanceParser<D extends Distance<D>> {
/**
+ * Parameter for distance function.
+ */
+ public static final OptionID DISTANCE_ID = OptionID.getOrCreateOptionID("parser.distance", "Distance type used for parsing values.");
+
+ /**
* Returns a list of the objects parsed from the specified input stream
* and a list of the labels associated with the objects.
*
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/parser/DistanceParsingResult.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/DistanceParsingResult.java
index 48f50e50..1fc15b52 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/parser/DistanceParsingResult.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/DistanceParsingResult.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.datasource.parser;
+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) 2011
+ Copyright (C) 2012
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 46ee475d..50344460 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -34,9 +34,6 @@ 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.DBIDs;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
-import de.lmu.ifi.dbs.elki.datasource.parser.DistanceParser;
-import de.lmu.ifi.dbs.elki.datasource.parser.DistanceParsingResult;
-import de.lmu.ifi.dbs.elki.datasource.parser.NumberDistanceParser;
import de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractDBIDDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.utilities.FileUtil;
@@ -45,6 +42,8 @@ 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.AbstractParameterizer;
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.FileParameter;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
@@ -135,7 +134,7 @@ public class FileBasedDoubleDistanceFunction extends AbstractDBIDDistanceFunctio
* @return Collection of all IDs in the cache.
*/
public DBIDs getIDs() {
- ModifiableDBIDs ids = DBIDUtil.newTreeSet();
+ ModifiableDBIDs ids = DBIDUtil.newHashSet();
for(DBIDPair pair : cache.keySet()) {
ids.add(pair.getFirst());
ids.add(pair.getSecond());
@@ -179,9 +178,14 @@ public class FileBasedDoubleDistanceFunction extends AbstractDBIDDistanceFunctio
if(config.grab(MATRIX_PARAM)) {
matrixfile = MATRIX_PARAM.getValue();
}
+
final ObjectParameter<DistanceParser<DoubleDistance>> PARSER_PARAM = new ObjectParameter<DistanceParser<DoubleDistance>>(PARSER_ID, DistanceParser.class, NumberDistanceParser.class);
if(config.grab(PARSER_PARAM)) {
- parser = PARSER_PARAM.instantiateClass(config);
+ ListParameterization parserConfig = new ListParameterization();
+ parserConfig.addParameter(DistanceParser.DISTANCE_ID, DoubleDistance.class);
+ ChainedParameterization combinedConfig = new ChainedParameterization(parserConfig, config);
+ combinedConfig.errorsTo(config);
+ parser = PARSER_PARAM.instantiateClass(combinedConfig);
}
}
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 d01983af..10a4f206 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -31,9 +31,6 @@ import java.util.Map;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDPair;
-import de.lmu.ifi.dbs.elki.datasource.parser.DistanceParser;
-import de.lmu.ifi.dbs.elki.datasource.parser.DistanceParsingResult;
-import de.lmu.ifi.dbs.elki.datasource.parser.NumberDistanceParser;
import de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractDBIDDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.FloatDistance;
import de.lmu.ifi.dbs.elki.utilities.FileUtil;
@@ -42,6 +39,8 @@ 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.AbstractParameterizer;
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.FileParameter;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
@@ -165,6 +164,10 @@ public class FileBasedFloatDistanceFunction extends AbstractDBIDDistanceFunction
}
final ObjectParameter<DistanceParser<FloatDistance>> PARSER_PARAM = new ObjectParameter<DistanceParser<FloatDistance>>(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);
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/datasource/parser/NumberDistanceParser.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/NumberDistanceParser.java
index dcb20020..c7a09e1a 100644
--- a/src/de/lmu/ifi/dbs/elki/datasource/parser/NumberDistanceParser.java
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/external/NumberDistanceParser.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.datasource.parser;
+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) 2011
+ Copyright (C) 2012
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.DBIDPair;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle;
-import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
+import de.lmu.ifi.dbs.elki.datasource.parser.AbstractParser;
+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.utilities.documentation.Description;
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.parameterization.Parameterization;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
@@ -60,43 +60,37 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
* @apiviz.has NumberDistance
*
* @param <D> distance type
- * @param <N> number type
*/
@Title("Number Distance Parser")
@Description("Parser for the following line format:\n" + "id1 id2 distanceValue, where id1 and is2 are integers representing the two ids belonging to the distance value.\n" + " The ids and the distance value are separated by whitespace. Empty lines and lines beginning with \"#\" will be ignored.")
-public class NumberDistanceParser<D extends NumberDistance<D, N>, N extends Number> extends AbstractParser implements DistanceParser<D> {
+public class NumberDistanceParser<D extends NumberDistance<D, ?>> extends AbstractParser implements DistanceParser<D> {
/**
* The logger for this class.
*/
private static final Logging logger = Logging.getLogger(NumberDistanceParser.class);
/**
- * Parameter for distance function.
- */
- public static final OptionID DISTANCE_FUNCTION_ID = OptionID.getOrCreateOptionID("parser.distancefunction", "Distance function used for parsing values.");
-
- /**
* The distance function.
*/
- private DistanceFunction<?, D> distanceFunction;
+ private final D distanceFactory;
/**
* Constructor.
*
* @param colSep
* @param quoteChar
- * @param distanceFunction
+ * @param distanceFactory Distance factory to use
*/
- public NumberDistanceParser(Pattern colSep, char quoteChar, DistanceFunction<?, D> distanceFunction) {
+ public NumberDistanceParser(Pattern colSep, char quoteChar, D distanceFactory) {
super(colSep, quoteChar);
- this.distanceFunction = distanceFunction;
+ this.distanceFactory = distanceFactory;
}
@Override
public DistanceParsingResult<D> parse(InputStream in) {
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
int lineNumber = 0;
-
+
ModifiableDBIDs ids = DBIDUtil.newHashSet();
Map<DBIDPair, D> distanceCache = new HashMap<DBIDPair, D>();
try {
@@ -127,7 +121,7 @@ public class NumberDistanceParser<D extends NumberDistance<D, N>, N extends Numb
}
try {
- D distance = distanceFunction.getDistanceFactory().parseString(entries.get(2));
+ D distance = distanceFactory.parseString(entries.get(2));
put(id1, id2, distance, distanceCache);
ids.add(id1);
ids.add(id2);
@@ -162,7 +156,12 @@ public class NumberDistanceParser<D extends NumberDistance<D, N>, N extends Numb
logger.debugFine("add to objectAndLabelsList");
}
- List<DBID> objects = new ArrayList<DBID>(ids);
+ // This is unusual for ELKI, but here we really need an ArrayList, not a
+ // DBIDs object. So convert.
+ List<DBID> objects = new ArrayList<DBID>(ids.size());
+ for(DBID id : ids) {
+ objects.add(id);
+ }
return new DistanceParsingResult<D>(MultipleObjectsBundle.makeSimple(TypeUtil.DBID, objects), distanceCache);
}
@@ -218,24 +217,24 @@ public class NumberDistanceParser<D extends NumberDistance<D, N>, N extends Numb
*
* @apiviz.exclude
*/
- public static class Parameterizer<D extends NumberDistance<D, N>, N extends Number> extends AbstractParser.Parameterizer {
+ public static class Parameterizer<D extends NumberDistance<D, ?>> extends AbstractParser.Parameterizer {
/**
* The distance function.
*/
- protected DistanceFunction<?, D> distanceFunction;
+ protected D distanceFactory;
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- ObjectParameter<DistanceFunction<?, D>> distFuncP = new ObjectParameter<DistanceFunction<?, D>>(DISTANCE_FUNCTION_ID, DistanceFunction.class);
+ ObjectParameter<D> distFuncP = new ObjectParameter<D>(DISTANCE_ID, Distance.class);
if(config.grab(distFuncP)) {
- distanceFunction = distFuncP.instantiateClass(config);
+ distanceFactory = distFuncP.instantiateClass(config);
}
}
@Override
- protected NumberDistanceParser<D, N> makeInstance() {
- return new NumberDistanceParser<D, N>(colSep, quoteChar, distanceFunction);
+ protected NumberDistanceParser<D> makeInstance() {
+ return new NumberDistanceParser<D>(colSep, quoteChar, distanceFactory);
}
}
} \ No newline at end of file
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 3db358d3..3099122a 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) 2011
+Copyright (C) 2012
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 f1c8b1b3..d4d7d9f5 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) 2011
+ Copyright (C) 2012
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/LatLngDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/geo/LatLngDistanceFunction.java
index 2b3d3805..c50b3326 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) 2011
+ Copyright (C) 2012
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/LngLatDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/geo/LngLatDistanceFunction.java
index 053e2f18..b48e7cae 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) 2011
+ Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/geo/package-info.java
index e71080fb..913447fd 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) 2011
+Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/package-info.java
index 85bb15f8..c47db2f8 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
@@ -37,7 +37,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2011
+Copyright (C) 2012
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/AbstractDimensionsSelectingDoubleDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/AbstractDimensionsSelectingDoubleDistanceFunction.java
index a7204562..b58979ef 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) 2011
+ Copyright (C) 2012
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.utilities.optionhandling.parameters.IntListParameter;
* @author Elke Achtert
* @param <V> the type of FeatureVector to compute the distances in between
*/
-public abstract class AbstractDimensionsSelectingDoubleDistanceFunction<V extends FeatureVector<?, ?>> extends AbstractPrimitiveDistanceFunction<V, DoubleDistance> implements PrimitiveDoubleDistanceFunction<V> {
+public abstract class AbstractDimensionsSelectingDoubleDistanceFunction<V extends FeatureVector<?, ?>> extends AbstractPrimitiveDistanceFunction<V, DoubleDistance> implements PrimitiveDoubleDistanceFunction<V>, DimensionSelectingSubspaceDistanceFunction<V, DoubleDistance> {
/**
* Dimensions parameter.
*/
@@ -51,7 +51,7 @@ public abstract class AbstractDimensionsSelectingDoubleDistanceFunction<V extend
/**
* The dimensions to be considered for distance computation.
*/
- private BitSet dimensions;
+ protected BitSet dimensions;
/**
* Constructor.
@@ -68,22 +68,12 @@ public abstract class AbstractDimensionsSelectingDoubleDistanceFunction<V extend
return new DoubleDistance(doubleDistance(o1, o2));
}
- /**
- * Returns a bit set representing the selected dimensions.
- *
- * @return a bit set representing the selected dimensions
- */
+ @Override
public BitSet getSelectedDimensions() {
- BitSet dimensions = new BitSet(this.dimensions.size());
- dimensions.or(this.dimensions);
return dimensions;
}
- /**
- * Sets the selected dimensions according to the set bits in the given BitSet.
- *
- * @param dimensions a BitSet designating the new selected dimensions
- */
+ @Override
public void setSelectedDimensions(BitSet dimensions) {
this.dimensions.clear();
this.dimensions.or(dimensions);
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 3d6aab90..8b5f526e 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) 2011
+ Copyright (C) 2012
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 8a58261d..f0eb8289 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) 2011
+ Copyright (C) 2012
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/DimensionSelectingDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/DimensionSelectingDistanceFunction.java
index 83df84f1..382167e9 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -108,20 +108,6 @@ public class DimensionSelectingDistanceFunction extends AbstractPrimitiveDistanc
}
@Override
- public double doubleCenterDistance(SpatialComparable mbr1, SpatialComparable mbr2) {
- if(dim > mbr1.getDimensionality() || dim > mbr2.getDimensionality()) {
- 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 c1 = (mbr1.getMin(dim) + mbr1.getMax(dim)) / 2;
- double c2 = (mbr2.getMin(dim) + mbr2.getMax(dim)) / 2;
-
- double manhattan = c1 - c2;
-
- return Math.abs(manhattan);
- }
-
- @Override
public DoubleDistance distance(NumberVector<?, ?> o1, NumberVector<?, ?> o2) {
return new DoubleDistance(doubleDistance(o1, o2));
}
@@ -131,11 +117,6 @@ public class DimensionSelectingDistanceFunction extends AbstractPrimitiveDistanc
return new DoubleDistance(doubleMinDist(mbr1, mbr2));
}
- @Override
- public DoubleDistance centerDistance(SpatialComparable mbr1, SpatialComparable mbr2) {
- return new DoubleDistance(doubleCenterDistance(mbr1, mbr2));
- }
-
/**
* Returns the selected dimension.
*
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
new file mode 100644
index 00000000..acc24bf7
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/DimensionSelectingSubspaceDistanceFunction.java
@@ -0,0 +1,52 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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 de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
+
+/**
+ * Interface for dimension selecting subspace distance functions.
+ *
+ * @author Erich Schubert
+ *
+ * @param <O> Object type
+ * @param <D> Distance value
+ */
+public interface DimensionSelectingSubspaceDistanceFunction<O, D extends Distance<D>> extends DistanceFunction<O, D> {
+ /**
+ * Returns a bit set representing the selected dimensions.
+ *
+ * @return a bit set representing the selected dimensions
+ */
+ public BitSet getSelectedDimensions();
+
+ /**
+ * Sets the selected dimensions according to the set bits in the given BitSet.
+ *
+ * @param dimensions a BitSet designating the new selected dimensions
+ */
+ public void setSelectedDimensions(BitSet dimensions);
+}
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 dc8c01b2..4835a6c6 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) 2011
+ Copyright (C) 2012
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/SubspaceDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/LocalSubspaceDistanceFunction.java
index 1afced55..b7d36264 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/SubspaceDistanceFunction.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -48,13 +48,13 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameteriz
*
* @apiviz.has Instance
*/
-public class SubspaceDistanceFunction extends AbstractIndexBasedDistanceFunction<NumberVector<?, ?>, FilteredLocalPCAIndex<NumberVector<?, ?>>, SubspaceDistance> implements FilteredLocalPCABasedDistanceFunction<NumberVector<?, ?>, FilteredLocalPCAIndex<NumberVector<?, ?>>, SubspaceDistance> {
+public class LocalSubspaceDistanceFunction extends AbstractIndexBasedDistanceFunction<NumberVector<?, ?>, FilteredLocalPCAIndex<NumberVector<?, ?>>, SubspaceDistance> implements FilteredLocalPCABasedDistanceFunction<NumberVector<?, ?>, FilteredLocalPCAIndex<NumberVector<?, ?>>, SubspaceDistance> {
/**
* Constructor
*
* @param indexFactory Index factory
*/
- public SubspaceDistanceFunction(IndexFactory<NumberVector<?, ?>, FilteredLocalPCAIndex<NumberVector<?, ?>>> indexFactory) {
+ public LocalSubspaceDistanceFunction(IndexFactory<NumberVector<?, ?>, FilteredLocalPCAIndex<NumberVector<?, ?>>> indexFactory) {
super(indexFactory);
}
@@ -76,12 +76,12 @@ public class SubspaceDistanceFunction extends AbstractIndexBasedDistanceFunction
*
* @author Erich Schubert
*/
- public static class Instance<V extends NumberVector<?, ?>> extends AbstractIndexBasedDistanceFunction.Instance<V, FilteredLocalPCAIndex<V>, SubspaceDistance, SubspaceDistanceFunction> implements FilteredLocalPCABasedDistanceFunction.Instance<V, FilteredLocalPCAIndex<V>, SubspaceDistance> {
+ public static class Instance<V extends NumberVector<?, ?>> extends AbstractIndexBasedDistanceFunction.Instance<V, FilteredLocalPCAIndex<V>, SubspaceDistance, LocalSubspaceDistanceFunction> implements FilteredLocalPCABasedDistanceFunction.Instance<V, FilteredLocalPCAIndex<V>, SubspaceDistance> {
/**
* @param database Database
* @param index Index
*/
- public Instance(Relation<V> database, FilteredLocalPCAIndex<V> index, SubspaceDistanceFunction distanceFunction) {
+ public Instance(Relation<V> database, FilteredLocalPCAIndex<V> index, LocalSubspaceDistanceFunction distanceFunction) {
super(database, index, distanceFunction);
}
@@ -145,8 +145,8 @@ public class SubspaceDistanceFunction extends AbstractIndexBasedDistanceFunction
}
@Override
- protected SubspaceDistanceFunction makeInstance() {
- return new SubspaceDistanceFunction(factory);
+ protected LocalSubspaceDistanceFunction makeInstance() {
+ return new LocalSubspaceDistanceFunction(factory);
}
}
} \ No newline at end of file
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
new file mode 100644
index 00000000..6330ed34
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/SubspaceEuclideanDistanceFunction.java
@@ -0,0 +1,149 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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 de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+
+/**
+ * Provides a distance function that computes the Euclidean distance between
+ * feature vectors only in specified dimensions.
+ *
+ * @author Elke Achtert
+ */
+public class SubspaceEuclideanDistanceFunction extends SubspaceLPNormDistanceFunction {
+ /**
+ * Constructor.
+ *
+ * @param dimensions Selected dimensions
+ */
+ public SubspaceEuclideanDistanceFunction(BitSet dimensions) {
+ super(2.0, dimensions);
+ }
+
+ /**
+ * Provides the Euclidean distance between two given feature vectors in the
+ * selected dimensions.
+ *
+ * @param v1 first feature vector
+ * @param v2 second feature vector
+ * @return the Euclidean distance between two given feature vectors in the
+ * selected dimensions
+ */
+ @Override
+ public double doubleDistance(NumberVector<?, ?> v1, NumberVector<?, ?> v2) {
+ if(v1.getDimensionality() != v2.getDimensionality()) {
+ throw new IllegalArgumentException("Different dimensionality of FeatureVectors\n " + "first argument: " + v1 + "\n " + "second argument: " + v2);
+ }
+
+ double sqrDist = 0;
+ for(int d = dimensions.nextSetBit(0); d >= 0; d = dimensions.nextSetBit(d + 1)) {
+ final double delta = v1.doubleValue(d + 1) - v2.doubleValue(d + 1);
+ sqrDist += delta * delta;
+ }
+ return Math.sqrt(sqrDist);
+ }
+
+ @Override
+ protected double doubleMinDistObject(SpatialComparable mbr, NumberVector<?, ?> v) {
+ if(mbr.getDimensionality() != v.getDimensionality()) {
+ throw new IllegalArgumentException("Different dimensionality of objects\n " + "first argument: " + mbr.toString() + "\n " + "second argument: " + v.toString());
+ }
+
+ double sqrDist = 0;
+ for(int d = dimensions.nextSetBit(0); d >= 0; d = dimensions.nextSetBit(d + 1)) {
+ final double delta;
+ final double value = v.doubleValue(d + 1);
+ final double omin = mbr.getMin(d + 1);
+ if(value < omin) {
+ delta = omin - value;
+ }
+ else {
+ final double omax = mbr.getMax(d + 1);
+ if(value > omax) {
+ delta = value - omax;
+ }
+ else {
+ continue;
+ }
+ }
+ sqrDist += delta * delta;
+ }
+ return Math.sqrt(sqrDist);
+ }
+
+ @Override
+ public double doubleMinDist(SpatialComparable mbr1, SpatialComparable mbr2) {
+ if(mbr1.getDimensionality() != 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 = dimensions.nextSetBit(0); d >= 0; d = dimensions.nextSetBit(d + 1)) {
+ final double delta;
+ final double max1 = mbr1.getMax(d + 1);
+ final double min2 = mbr2.getMin(d + 1);
+ if(max1 < min2) {
+ delta = min2 - max1;
+ }
+ else {
+ final double min1 = mbr1.getMin(d + 1);
+ final double max2 = mbr2.getMax(d + 1);
+ if(min1 > max2) {
+ delta = min1 - max2;
+ }
+ else { // The mbrs intersect!
+ continue;
+ }
+ }
+ sqrDist += delta * delta;
+ }
+ return Math.sqrt(sqrDist);
+ }
+
+ @Override
+ public double doubleNorm(NumberVector<?, ?> obj) {
+ double sqrDist = 0;
+ for(int d = dimensions.nextSetBit(0); d >= 0; d = dimensions.nextSetBit(d + 1)) {
+ final double delta = obj.doubleValue(d + 1);
+ sqrDist += delta * delta;
+ }
+ return Math.sqrt(sqrDist);
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractDimensionsSelectingDoubleDistanceFunction.Parameterizer {
+ @Override
+ protected SubspaceEuclideanDistanceFunction makeInstance() {
+ return new SubspaceEuclideanDistanceFunction(dimensions);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/DimensionsSelectingEuclideanDistanceFunction.java b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/SubspaceLPNormDistanceFunction.java
index b9f52de9..7904c333 100644
--- a/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/DimensionsSelectingEuclideanDistanceFunction.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -31,8 +31,13 @@ import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
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.distancevalue.DoubleDistance;
+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;
/**
* Provides a distance function that computes the Euclidean distance between
@@ -40,14 +45,30 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
*
* @author Elke Achtert
*/
-public class DimensionsSelectingEuclideanDistanceFunction extends AbstractDimensionsSelectingDoubleDistanceFunction<NumberVector<?, ?>> implements SpatialPrimitiveDoubleDistanceFunction<NumberVector<?, ?>> {
+public class SubspaceLPNormDistanceFunction extends AbstractDimensionsSelectingDoubleDistanceFunction<NumberVector<?, ?>> implements SpatialPrimitiveDoubleDistanceFunction<NumberVector<?, ?>>, DoubleNorm<NumberVector<?, ?>> {
+ /**
+ * Value of p
+ */
+ private double p;
+
/**
* Constructor.
*
* @param dimensions Selected dimensions
+ * @param p p value
*/
- public DimensionsSelectingEuclideanDistanceFunction(BitSet dimensions) {
+ public SubspaceLPNormDistanceFunction(double p, BitSet dimensions) {
super(dimensions);
+ this.p = p;
+ }
+
+ /**
+ * Get the value of p.
+ *
+ * @return p
+ */
+ public double getP() {
+ return p;
}
/**
@@ -65,44 +86,39 @@ public class DimensionsSelectingEuclideanDistanceFunction extends AbstractDimens
throw new IllegalArgumentException("Different dimensionality of FeatureVectors\n " + "first argument: " + v1 + "\n " + "second argument: " + v2);
}
- if(v1.getDimensionality() < getSelectedDimensions().cardinality()) {
- throw new IllegalArgumentException("The dimensionality of the feature space " + "is not consistent with the specified dimensions " + "to be considered for distance computation.\n " + "dimensionality of the feature space: " + v1.getDimensionality() + "\n " + "specified dimensions: " + getSelectedDimensions());
- }
-
double sqrDist = 0;
- for(int d = getSelectedDimensions().nextSetBit(0); d >= 0; d = getSelectedDimensions().nextSetBit(d + 1)) {
- double manhattanI = v1.doubleValue(d + 1) - v2.doubleValue(d + 1);
- sqrDist += manhattanI * manhattanI;
+ for(int d = dimensions.nextSetBit(0); d >= 0; d = dimensions.nextSetBit(d + 1)) {
+ double delta = Math.abs(v1.doubleValue(d + 1) - v2.doubleValue(d + 1));
+ sqrDist += Math.pow(delta, p);
}
- return Math.sqrt(sqrDist);
+ return Math.pow(sqrDist, 1. / p);
}
protected double doubleMinDistObject(SpatialComparable mbr, NumberVector<?, ?> v) {
if(mbr.getDimensionality() != v.getDimensionality()) {
throw new IllegalArgumentException("Different dimensionality of objects\n " + "first argument: " + mbr.toString() + "\n " + "second argument: " + v.toString());
}
- if(v.getDimensionality() < getSelectedDimensions().size()) {
- throw new IllegalArgumentException("The dimensionality of the feature space " + "is not consistent with the specified dimensions " + "to be considered for distance computation.\n " + "dimensionality of the feature space: " + v.getDimensionality() + "\n " + "specified dimensions: " + getSelectedDimensions());
- }
double sqrDist = 0;
- for(int d = getSelectedDimensions().nextSetBit(0); d >= 0; d = getSelectedDimensions().nextSetBit(d + 1)) {
- 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);
+ for(int d = dimensions.nextSetBit(0); d >= 0; d = dimensions.nextSetBit(d + 1)) {
+ final double delta;
+ final double value = v.doubleValue(d + 1);
+ final double omin = mbr.getMin(d + 1);
+ if(value < omin) {
+ delta = omin - value;
}
else {
- r = value;
+ final double omax = mbr.getMax(d + 1);
+ if(value > omax) {
+ delta = value - omax;
+ }
+ else {
+ continue;
+ }
}
-
- double manhattanI = value - r;
- sqrDist += manhattanI * manhattanI;
+ sqrDist += Math.pow(delta, p);
}
- return Math.sqrt(sqrDist);
+ return Math.pow(sqrDist, 1. / p);
}
@Override
@@ -110,60 +126,54 @@ public class DimensionsSelectingEuclideanDistanceFunction extends AbstractDimens
if(mbr1.getDimensionality() != mbr2.getDimensionality()) {
throw new IllegalArgumentException("Different dimensionality of objects\n " + "first argument: " + mbr1.toString() + "\n " + "second argument: " + mbr2.toString());
}
- if(mbr1.getDimensionality() < getSelectedDimensions().size()) {
- throw new IllegalArgumentException("The dimensionality of the feature space " + "is not consistent with the specified dimensions " + "to be considered for distance computation.\n " + "dimensionality of the feature space: " + mbr1.getDimensionality() + "\n " + "specified dimensions: " + getSelectedDimensions());
- }
-
double sqrDist = 0;
- for(int d = getSelectedDimensions().nextSetBit(0); d >= 0; d = getSelectedDimensions().nextSetBit(d + 1)) {
- final double m1, m2;
- if(mbr1.getMax(d) < mbr2.getMin(d)) {
- m1 = mbr1.getMax(d);
- m2 = mbr2.getMin(d);
+ for(int d = dimensions.nextSetBit(0); d >= 0; d = dimensions.nextSetBit(d + 1)) {
+ final double delta;
+ final double max1 = mbr1.getMax(d + 1);
+ final double min2 = mbr2.getMin(d + 1);
+ if(max1 < min2) {
+ delta = min2 - max1;
}
- else if(mbr1.getMin(d) > mbr2.getMax(d)) {
- m1 = mbr1.getMin(d);
- m2 = mbr2.getMax(d);
- }
- else { // The mbrs intersect!
- continue;
+ else {
+ final double min1 = mbr1.getMin(d + 1);
+ final double max2 = mbr2.getMax(d + 1);
+ if(min1 > max2) {
+ delta = min1 - max2;
+ }
+ else { // The mbrs intersect!
+ continue;
+ }
}
- double manhattanI = m1 - m2;
- sqrDist += manhattanI * manhattanI;
+ sqrDist += Math.pow(delta, p);
}
- return Math.sqrt(sqrDist);
+ return Math.pow(sqrDist, 1. / p);
}
@Override
- public double doubleCenterDistance(SpatialComparable mbr1, SpatialComparable mbr2) {
- if(mbr1.getDimensionality() != mbr2.getDimensionality()) {
- throw new IllegalArgumentException("Different dimensionality of objects\n " + "first argument: " + mbr1.toString() + "\n " + "second argument: " + mbr2.toString());
- }
- if(mbr1.getDimensionality() < getSelectedDimensions().size()) {
- throw new IllegalArgumentException("The dimensionality of the feature space " + "is not consistent with the specified dimensions " + "to be considered for distance computation.\n " + "dimensionality of the feature space: " + mbr1.getDimensionality() + "\n " + "specified dimensions: " + getSelectedDimensions());
- }
-
- double sqrDist = 0;
- for(int d = getSelectedDimensions().nextSetBit(0); d >= 0; d = getSelectedDimensions().nextSetBit(d + 1)) {
- double c1 = (mbr1.getMin(d) + mbr1.getMax(d)) / 2;
- double c2 = (mbr2.getMin(d) + mbr2.getMax(d)) / 2;
+ public DoubleDistance minDist(SpatialComparable mbr1, SpatialComparable mbr2) {
+ return new DoubleDistance(doubleMinDist(mbr1, mbr2));
+ }
- double manhattanI = c1 - c2;
- sqrDist += manhattanI * manhattanI;
- }
- return Math.sqrt(sqrDist);
+ @Override
+ public DoubleDistance norm(NumberVector<?, ?> obj) {
+ return new DoubleDistance(doubleNorm(obj));
}
@Override
- public DoubleDistance minDist(SpatialComparable mbr1, SpatialComparable mbr2) {
- return new DoubleDistance(doubleMinDist(mbr1, mbr2));
+ public double doubleNorm(NumberVector<?, ?> obj) {
+ double sqrDist = 0;
+ for(int d = dimensions.nextSetBit(0); d >= 0; d = dimensions.nextSetBit(d + 1)) {
+ double delta = Math.abs(obj.doubleValue(d + 1));
+ sqrDist += Math.pow(delta, p);
+ }
+ return Math.pow(sqrDist, 1. / p);
}
@Override
- public DoubleDistance centerDistance(SpatialComparable mbr1, SpatialComparable mbr2) {
- return new DoubleDistance(doubleCenterDistance(mbr1, mbr2));
+ public <T extends NumberVector<?, ?>> SpatialPrimitiveDistanceQuery<T, DoubleDistance> instantiate(Relation<T> database) {
+ return new SpatialPrimitiveDistanceQuery<T, DoubleDistance>(database, this);
}
-
+
@Override
public VectorFieldTypeInformation<? super NumberVector<?, ?>> getInputTypeRestriction() {
return TypeUtil.NUMBER_VECTOR_FIELD;
@@ -174,11 +184,6 @@ public class DimensionsSelectingEuclideanDistanceFunction extends AbstractDimens
return true;
}
- @Override
- public <T extends NumberVector<?, ?>> SpatialPrimitiveDistanceQuery<T, DoubleDistance> instantiate(Relation<T> database) {
- return new SpatialPrimitiveDistanceQuery<T, DoubleDistance>(database, this);
- }
-
/**
* Parameterization class.
*
@@ -187,9 +192,29 @@ public class DimensionsSelectingEuclideanDistanceFunction extends AbstractDimens
* @apiviz.exclude
*/
public static class Parameterizer extends AbstractDimensionsSelectingDoubleDistanceFunction.Parameterizer {
+ /**
+ * Value of p
+ */
+ private double p;
+
@Override
- protected DimensionsSelectingEuclideanDistanceFunction makeInstance() {
- return new DimensionsSelectingEuclideanDistanceFunction(dimensions);
+ protected void makeOptions(Parameterization config) {
+ final DoubleParameter paramP = new DoubleParameter(LPNormDistanceFunction.P_ID, new GreaterConstraint(0));
+ if(config.grab(paramP)) {
+ p = paramP.getValue();
+ }
+ super.makeOptions(config);
+ }
+
+ @Override
+ protected SubspaceLPNormDistanceFunction makeInstance() {
+ if(p == 2.0) {
+ return new SubspaceEuclideanDistanceFunction(dimensions);
+ }
+ if(p == 1.0) {
+ return new SubspaceManhattanDistanceFunction(dimensions);
+ }
+ return new SubspaceLPNormDistanceFunction(p, dimensions);
}
}
} \ No newline at end of file
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
new file mode 100644
index 00000000..905ee037
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/distance/distancefunction/subspace/SubspaceManhattanDistanceFunction.java
@@ -0,0 +1,142 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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 de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+
+/**
+ * Provides a distance function that computes the Euclidean distance between
+ * feature vectors only in specified dimensions.
+ *
+ * @author Elke Achtert
+ */
+public class SubspaceManhattanDistanceFunction extends SubspaceLPNormDistanceFunction {
+ /**
+ * Constructor.
+ *
+ * @param dimensions Selected dimensions
+ */
+ public SubspaceManhattanDistanceFunction(BitSet dimensions) {
+ super(1.0, dimensions);
+ }
+
+ /**
+ * Provides the Euclidean distance between two given feature vectors in the
+ * selected dimensions.
+ *
+ * @param v1 first feature vector
+ * @param v2 second feature vector
+ * @return the Euclidean distance between two given feature vectors in the
+ * selected dimensions
+ */
+ @Override
+ public double doubleDistance(NumberVector<?, ?> v1, NumberVector<?, ?> v2) {
+ if(v1.getDimensionality() != v2.getDimensionality()) {
+ throw new IllegalArgumentException("Different dimensionality of FeatureVectors\n " + "first argument: " + v1 + "\n " + "second argument: " + v2);
+ }
+
+ double sum = 0;
+ for(int d = dimensions.nextSetBit(0); d >= 0; d = dimensions.nextSetBit(d + 1)) {
+ sum += Math.abs(v1.doubleValue(d + 1) - v2.doubleValue(d + 1));
+ }
+ return sum;
+ }
+
+ protected double doubleMinDistObject(SpatialComparable mbr, NumberVector<?, ?> v) {
+ if(mbr.getDimensionality() != v.getDimensionality()) {
+ throw new IllegalArgumentException("Different dimensionality of objects\n " + "first argument: " + mbr.toString() + "\n " + "second argument: " + v.toString());
+ }
+
+ double sum = 0;
+ for(int d = dimensions.nextSetBit(0); d >= 0; d = dimensions.nextSetBit(d + 1)) {
+ final double value = v.doubleValue(d + 1);
+ final double omin = mbr.getMin(d + 1);
+ if(value < omin) {
+ sum += omin - value;
+ }
+ else {
+ final double omax = mbr.getMax(d + 1);
+ if(value > omax) {
+ sum += value - omax;
+ }
+ else {
+ continue;
+ }
+ }
+ }
+ return sum;
+ }
+
+ @Override
+ public double doubleMinDist(SpatialComparable mbr1, SpatialComparable mbr2) {
+ if(mbr1.getDimensionality() != mbr2.getDimensionality()) {
+ throw new IllegalArgumentException("Different dimensionality of objects\n " + "first argument: " + mbr1.toString() + "\n " + "second argument: " + mbr2.toString());
+ }
+ double sum = 0;
+ for(int d = dimensions.nextSetBit(0); d >= 0; d = dimensions.nextSetBit(d + 1)) {
+ final double max1 = mbr1.getMax(d + 1);
+ final double min2 = mbr2.getMin(d + 1);
+ if(max1 < min2) {
+ sum += min2 - max1;
+ }
+ else {
+ final double min1 = mbr1.getMin(d + 1);
+ final double max2 = mbr2.getMax(d + 1);
+ if(min1 > max2) {
+ sum += min1 - max2;
+ }
+ else { // The mbrs intersect!
+ continue;
+ }
+ }
+ }
+ return sum;
+ }
+
+ @Override
+ public double doubleNorm(NumberVector<?, ?> obj) {
+ double sum = 0;
+ for(int d = dimensions.nextSetBit(0); d >= 0; d = dimensions.nextSetBit(d + 1)) {
+ sum += Math.abs(obj.doubleValue(d + 1));
+ }
+ return sum;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractDimensionsSelectingDoubleDistanceFunction.Parameterizer {
+ @Override
+ protected SubspaceManhattanDistanceFunction makeInstance() {
+ return new SubspaceManhattanDistanceFunction(dimensions);
+ }
+ }
+} \ No newline at end of file
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 f24e112f..85035eec 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) 2011
+Copyright (C) 2012
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 3360e7ba..a504f680 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) 2011
+ Copyright (C) 2012
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 2f0e9045..4461a680 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) 2011
+ Copyright (C) 2012
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 a0c20f6e..c918ab03 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) 2011
+ Copyright (C) 2012
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 3d41e0c7..40ed00ba 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -48,7 +48,7 @@ public class ERPDistanceFunction extends AbstractEditDistanceFunction {
/**
* Keeps the currently set g.
*/
- private double g;
+ private final double g;
/**
* Constructor.
@@ -76,10 +76,7 @@ public class ERPDistanceFunction extends AbstractEditDistanceFunction {
// size of edit distance band
// bandsize is the maximum allowed distance to the diagonal
- int band = (int) Math.ceil(v2.getDimensionality() * bandSize);
-
- // g parameter for local usage
- double gValue = g;
+ final int band = (int) Math.ceil(v2.getDimensionality() * bandSize);
for(int i = 0; i < v1.getDimensionality(); i++) {
// Swap current and prev arrays. We'll just overwrite the new curr.
@@ -101,11 +98,11 @@ public class ERPDistanceFunction extends AbstractEditDistanceFunction {
if(Math.abs(i - j) <= band) {
// compute squared distance of feature vectors
double val1 = v1.doubleValue(i + 1);
- double val2 = gValue;
+ double val2 = g;
double diff = (val1 - val2);
final double d1 = Math.sqrt(diff * diff);
- val1 = gValue;
+ val1 = g;
val2 = v2.doubleValue(j + 1);
diff = (val1 - val2);
final double d2 = Math.sqrt(diff * diff);
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 3264db7e..b9a26c8b 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) 2011
+ Copyright (C) 2012
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 bb252054..cad7fba9 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) 2011
+Copyright (C) 2012
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 b239cea2..3e5e86af 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) 2011
+ Copyright (C) 2012
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 9b579452..24e33d35 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) 2011
+ Copyright (C) 2012
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/CorrelationDistance.java b/src/de/lmu/ifi/dbs/elki/distance/distancevalue/CorrelationDistance.java
index 4a15ab80..f1203887 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) 2011
+ Copyright (C) 2012
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 838dcfd6..73e11fa6 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) 2011
+ Copyright (C) 2012
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/DoubleDistance.java b/src/de/lmu/ifi/dbs/elki/distance/distancevalue/DoubleDistance.java
index 102fcc94..ce63b4e1 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) 2011
+ Copyright (C) 2012
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/FloatDistance.java b/src/de/lmu/ifi/dbs/elki/distance/distancevalue/FloatDistance.java
index 87fca22f..5aaaab91 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) 2011
+ Copyright (C) 2012
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/IntegerDistance.java b/src/de/lmu/ifi/dbs/elki/distance/distancevalue/IntegerDistance.java
index 0eb77593..b99b88c3 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) 2011
+ Copyright (C) 2012
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/NumberDistance.java b/src/de/lmu/ifi/dbs/elki/distance/distancevalue/NumberDistance.java
index b5b534ee..a3aff609 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) 2011
+ Copyright (C) 2012
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 ff7b6bf4..c2e2da6d 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -147,6 +147,6 @@ public class PCACorrelationDistance extends CorrelationDistance<PCACorrelationDi
@Override
public boolean isUndefinedDistance() {
- return correlationValue == -1 && euclideanValue == Double.NaN;
+ return correlationValue == -1 && Double.isNaN(euclideanValue);
}
} \ No newline at end of file
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 694650cf..c62cacc4 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) 2011
+ Copyright (C) 2012
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/SubspaceDistance.java b/src/de/lmu/ifi/dbs/elki/distance/distancevalue/SubspaceDistance.java
index cb929c44..3d4b7f4c 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) 2011
+ Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/distance/distancevalue/package-info.java
index 430c1456..30fcdf35 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
@@ -10,7 +10,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2011
+Copyright (C) 2012
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 50fc45a2..801d4314 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) 2011
+Copyright (C) 2012
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 12a39916..163438ce 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) 2011
+ Copyright (C) 2012
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 ad065c68..72f44e4d 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) 2011
+ Copyright (C) 2012
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/AbstractPrimitiveSimilarityFunction.java b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/AbstractPrimitiveSimilarityFunction.java
index a37efe9d..c408d1bb 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) 2011
+ Copyright (C) 2012
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/DBIDSimilarityFunction.java b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/DBIDSimilarityFunction.java
index d93c93f9..e7316115 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) 2011
+ Copyright (C) 2012
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 c909cd6c..ec4460d8 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,8 +25,9 @@ package de.lmu.ifi.dbs.elki.distance.similarityfunction;
import java.util.Iterator;
+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.TreeSetDBIDs;
+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.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.index.preprocessed.snn.SharedNearestNeighborIndex;
@@ -47,7 +48,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameteriz
* @param <O> object type
*/
// todo arthur comment class
-public class FractionalSharedNearestNeighborSimilarityFunction<O> extends AbstractIndexBasedSimilarityFunction<O, SharedNearestNeighborIndex<O>, TreeSetDBIDs, DoubleDistance> implements NormalizedSimilarityFunction<O, DoubleDistance> {
+public class FractionalSharedNearestNeighborSimilarityFunction<O> extends AbstractIndexBasedSimilarityFunction<O, SharedNearestNeighborIndex<O>, ArrayDBIDs, DoubleDistance> implements NormalizedSimilarityFunction<O, DoubleDistance> {
/**
* Constructor.
*
@@ -73,7 +74,7 @@ public class FractionalSharedNearestNeighborSimilarityFunction<O> extends Abstra
*
* @param <T> Object type
*/
- public static class Instance<T> extends AbstractIndexBasedSimilarityFunction.Instance<T, SharedNearestNeighborIndex<T>, TreeSetDBIDs, DoubleDistance> {
+ public static class Instance<T> extends AbstractIndexBasedSimilarityFunction.Instance<T, SharedNearestNeighborIndex<T>, ArrayDBIDs, DoubleDistance> {
/**
* Constructor.
*
@@ -84,7 +85,14 @@ public class FractionalSharedNearestNeighborSimilarityFunction<O> extends Abstra
super(database, preprocessor);
}
- static protected int countSharedNeighbors(TreeSetDBIDs neighbors1, TreeSetDBIDs neighbors2) {
+ /**
+ * Compute the intersection size.
+ *
+ * @param neighbors1 SORTED neighbor ids of first
+ * @param neighbors2 SORTED neighbor ids of second
+ * @return Intersection size
+ */
+ static protected int countSharedNeighbors(DBIDs neighbors1, DBIDs neighbors2) {
int intersection = 0;
Iterator<DBID> iter1 = neighbors1.iterator();
Iterator<DBID> iter2 = neighbors2.iterator();
@@ -109,8 +117,8 @@ public class FractionalSharedNearestNeighborSimilarityFunction<O> extends Abstra
@Override
public DoubleDistance similarity(DBID id1, DBID id2) {
- TreeSetDBIDs neighbors1 = index.getNearestNeighborSet(id1);
- TreeSetDBIDs neighbors2 = index.getNearestNeighborSet(id2);
+ DBIDs neighbors1 = index.getNearestNeighborSet(id1);
+ DBIDs neighbors2 = index.getNearestNeighborSet(id2);
int intersection = countSharedNeighbors(neighbors1, neighbors2);
return new DoubleDistance((double) intersection / index.getNumberOfNeighbors());
}
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 95d854c0..29ae9ce3 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) 2011
+ Copyright (C) 2012
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/InvertedDistanceSimilarityFunction.java b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/InvertedDistanceSimilarityFunction.java
new file mode 100644
index 00000000..ad193d9e
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/InvertedDistanceSimilarityFunction.java
@@ -0,0 +1,74 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.distance.distancefunction.PrimitiveDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+
+/**
+ * Adapter to use a primitive number-distance as similarity measure, by computing
+ * 1/distance.
+ *
+ * @author Erich Schubert
+ *
+ * @param <O> Object type
+ */
+public class InvertedDistanceSimilarityFunction<O> extends AbstractPrimitiveSimilarityFunction<O, DoubleDistance> {
+ /**
+ * Parameter to specify the similarity function to derive the distance between
+ * database objects from. Must extend
+ * {@link de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction} .
+ * <p>
+ * Key: {@code -adapter.distancefunction}
+ * </p>
+ * <p>
+ * Default value:
+ * {@link de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction}
+ * </p>
+ */
+ public static final OptionID DISTANCE_FUNCTION_ID = OptionID.getOrCreateOptionID("adapter.distancefunction", "Distance function to derive the similarity between database objects from.");
+
+ /**
+ * Holds the similarity function.
+ */
+ protected PrimitiveDistanceFunction<? super O, ? extends NumberDistance<?, ?>> distanceFunction;
+
+ @Override
+ public DoubleDistance getDistanceFactory() {
+ return DoubleDistance.FACTORY;
+ }
+
+ @Override
+ public SimpleTypeInformation<? super O> getInputTypeRestriction() {
+ return distanceFunction.getInputTypeRestriction();
+ }
+
+ @Override
+ public DoubleDistance similarity(O o1, O o2) {
+ double dist = distanceFunction.distance(o1, o2).doubleValue();
+ return new DoubleDistance(1. / dist);
+ }
+} \ No newline at end of file
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 f5347e71..fc86a3bc 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) 2011
+ Copyright (C) 2012
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 5979ad3f..b2be1a56 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) 2011
+ Copyright (C) 2012
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 edb57ca0..b5642d0c 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) 2011
+ Copyright (C) 2012
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/SharedNearestNeighborSimilarityFunction.java b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/SharedNearestNeighborSimilarityFunction.java
index 74c2534c..0025ee75 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) 2011
+ Copyright (C) 2012
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.distance.similarityfunction;
import java.util.Iterator;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
+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.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancevalue.IntegerDistance;
@@ -60,7 +61,14 @@ public class SharedNearestNeighborSimilarityFunction<O> extends AbstractIndexBas
return IntegerDistance.FACTORY;
}
- static protected int countSharedNeighbors(SetDBIDs neighbors1, SetDBIDs neighbors2) {
+ /**
+ * Compute the intersection size
+ *
+ * @param neighbors1 SORTED neighbors of first
+ * @param neighbors2 SORTED neighbors of second
+ * @return Intersection size
+ */
+ static protected int countSharedNeighbors(DBIDs neighbors1, DBIDs neighbors2) {
int intersection = 0;
Iterator<DBID> iter1 = neighbors1.iterator();
Iterator<DBID> iter2 = neighbors2.iterator();
@@ -112,8 +120,8 @@ public class SharedNearestNeighborSimilarityFunction<O> extends AbstractIndexBas
@Override
public IntegerDistance similarity(DBID id1, DBID id2) {
- SetDBIDs neighbors1 = index.getNearestNeighborSet(id1);
- SetDBIDs neighbors2 = index.getNearestNeighborSet(id2);
+ DBIDs neighbors1 = index.getNearestNeighborSet(id1);
+ DBIDs neighbors2 = index.getNearestNeighborSet(id2);
return new IntegerDistance(countSharedNeighbors(neighbors1, neighbors2));
}
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 687d17d7..d8324a80 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) 2011
+ Copyright (C) 2012
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 24a9efda..093cf652 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) 2011
+ Copyright (C) 2012
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/KernelMatrix.java b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/kernel/KernelMatrix.java
index c41a2e91..a8b6d8fc 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) 2011
+ Copyright (C) 2012
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 7d3f85d3..6cde55a6 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) 2011
+ Copyright (C) 2012
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/PolynomialKernelFunction.java b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/kernel/PolynomialKernelFunction.java
index c3ad7e3e..e32f5b45 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) 2011
+ Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/distance/similarityfunction/kernel/package-info.java
index a059de3a..6d2e46fc 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) 2011
+Copyright (C) 2012
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 033daf1c..ba53fba3 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) 2011
+Copyright (C) 2012
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/Evaluator.java b/src/de/lmu/ifi/dbs/elki/evaluation/Evaluator.java
index f9be3e82..61a1bb63 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) 2011
+ Copyright (C) 2012
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
new file mode 100644
index 00000000..d8087cf6
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/BCubed.java
@@ -0,0 +1,103 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.evaluation.clustering.ClusterContingencyTable.Util;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+
+/**
+ * BCubed measures.
+ *
+ * Reference:
+ * <p>
+ * Bagga, A. and Baldwin, B.<br />
+ * Entity-based cross-document coreferencing using the Vector Space Model<br />
+ * Proc. COLING '98 Proceedings of the 17th international conference on
+ * Computational linguistics
+ * </p>
+ *
+ * @author Sascha Goldhofer
+ */
+@Reference(authors = "Bagga, A. and Baldwin, B.", title = "Entity-based cross-document coreferencing using the Vector Space Model", booktitle = "Proc. COLING '98 Proceedings of the 17th international conference on Computational linguistics", url = "http://dx.doi.org/10.3115/980451.980859")
+public class BCubed {
+ /**
+ * Result cache
+ */
+ protected double bCubedPrecision = -1.0, bCubedRecall = -1.0;
+
+ /**
+ * Constructor.
+ *
+ * @param table Contingency table
+ */
+ protected BCubed(ClusterContingencyTable table) {
+ super();
+ bCubedPrecision = 0.0;
+ bCubedRecall = 0.0;
+
+ for(int i1 = 0; i1 < table.size1; i1++) {
+ for(int i2 = 0; i2 < table.size2; i2++) {
+ // precision of one item
+ double precision = 1.0 * table.contingency[i1][i2] / table.contingency[i1][table.size2];
+ // precision for all items in cluster
+ bCubedPrecision += (precision * table.contingency[i1][i2]);
+
+ // recall of one item
+ double recall = 1.0 * table.contingency[i1][i2] / table.contingency[table.size1][i2];
+ // recall for all items in cluster
+ bCubedRecall += (recall * table.contingency[i1][i2]);
+ }
+ }
+
+ bCubedPrecision = bCubedPrecision / table.contingency[table.size1][table.size2];
+ bCubedRecall = bCubedRecall / table.contingency[table.size1][table.size2];
+ }
+
+ /**
+ * Get the BCubed Precision (first clustering) (normalized, 0 = unequal)
+ *
+ * @return BCubed Precision
+ */
+ public double precision() {
+ return bCubedPrecision;
+ }
+
+ /**
+ * Get the BCubed Recall (first clustering) (normalized, 0 = unequal)
+ *
+ * @return BCubed Recall
+ */
+ public double recall() {
+ return bCubedRecall;
+ }
+
+ /**
+ * Get the BCubed F1-Measure
+ *
+ * @return BCubed F1-Measure
+ */
+ public double f1Measure() {
+ return Util.f1Measure(precision(), recall());
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/clustering/ClusterContingencyTable.java b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/ClusterContingencyTable.java
new file mode 100644
index 00000000..ac156a4e
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/ClusterContingencyTable.java
@@ -0,0 +1,321 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.Iterator;
+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.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.math.MeanVariance;
+
+/**
+ * Class storing the contingency table and related data on two clusterings.
+ *
+ * @author Erich Schubert
+ */
+public class ClusterContingencyTable {
+ /**
+ * Noise cluster handling
+ */
+ protected boolean breakNoiseClusters = false;
+
+ /**
+ * Self pairing
+ */
+ protected boolean selfPairing = true;
+
+ /**
+ * Number of clusters in first
+ */
+ protected int size1 = -1;
+
+ /**
+ * Number of clusters in second
+ */
+ protected int size2 = -1;
+
+ /**
+ * Contingency matrix
+ */
+ protected int[][] contingency = null;
+
+ /**
+ * Noise flags
+ */
+ protected BitSet noise1 = null;
+
+ /**
+ * Noise flags
+ */
+ protected BitSet noise2 = null;
+
+ /**
+ * Pair counting measures
+ */
+ protected PairCounting paircount = null;
+
+ /**
+ * Entropy-based measures
+ */
+ protected Entropy entropy = null;
+
+ /**
+ * Set matching purity measures
+ */
+ protected SetMatchingPurity smp = null;
+
+ /**
+ * Edit-Distance measures
+ */
+ protected EditDistance edit = null;
+
+ /**
+ * BCubed measures
+ */
+ protected BCubed bcubed = null;
+
+ /**
+ * Constructor.
+ *
+ * @param selfPairing Build self-pairs
+ * @param breakNoiseClusters Break noise clusters into individual objects
+ */
+ public ClusterContingencyTable(boolean selfPairing, boolean breakNoiseClusters) {
+ super();
+ this.selfPairing = selfPairing;
+ this.breakNoiseClusters = breakNoiseClusters;
+ }
+
+ /**
+ * Process two clustering results.
+ *
+ * @param result1 First clustering
+ * @param result2 Second clustering
+ */
+ public void process(Clustering<?> result1, Clustering<?> result2) {
+ // Get the clusters
+ final List<? extends Cluster<?>> cs1 = result1.getAllClusters();
+ final List<? extends Cluster<?>> cs2 = result2.getAllClusters();
+
+ // Initialize
+ size1 = cs1.size();
+ size2 = cs2.size();
+ contingency = new int[size1 + 2][size2 + 2];
+ noise1 = new BitSet(size1);
+ noise2 = new BitSet(size2);
+
+ // Fill main part of matrix
+ {
+ {
+ final Iterator<? extends Cluster<?>> it2 = cs2.iterator();
+ for(int i2 = 0; it2.hasNext(); i2++) {
+ final Cluster<?> c2 = it2.next();
+ if(c2.isNoise()) {
+ noise2.set(i2);
+ }
+ contingency[size1 + 1][i2] = c2.size();
+ contingency[size1 + 1][size2] += c2.size();
+ }
+ }
+ final Iterator<? extends Cluster<?>> it1 = cs1.iterator();
+ for(int i1 = 0; it1.hasNext(); i1++) {
+ final Cluster<?> c1 = it1.next();
+ if(c1.isNoise()) {
+ noise1.set(i1);
+ }
+ final DBIDs ids = DBIDUtil.ensureSet(c1.getIDs());
+ contingency[i1][size2 + 1] = c1.size();
+ contingency[size1][size2 + 1] += c1.size();
+
+ final Iterator<? extends Cluster<?>> it2 = cs2.iterator();
+ for(int i2 = 0; it2.hasNext(); i2++) {
+ final Cluster<?> c2 = it2.next();
+ int count = 0;
+ for(DBID id : c2.getIDs()) {
+ if(ids.contains(id)) {
+ count++;
+ }
+ }
+ contingency[i1][i2] = count;
+ contingency[i1][size2] += count;
+ contingency[size1][i2] += count;
+ contingency[size1][size2] += count;
+ }
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ if(contingency != null) {
+ for(int i1 = 0; i1 < size1 + 2; i1++) {
+ if(i1 >= size1) {
+ buf.append("------\n");
+ }
+ for(int i2 = 0; i2 < size2 + 2; i2++) {
+ if(i2 >= size2) {
+ buf.append("| ");
+ }
+ buf.append(contingency[i1][i2]).append(" ");
+ }
+ buf.append("\n");
+ }
+ }
+ // if(pairconfuse != null) {
+ // buf.append(FormatUtil.format(pairconfuse));
+ // }
+ return buf.toString();
+ }
+
+ /**
+ * Get (compute) the pair counting measures.
+ *
+ * @return Pair counting measures
+ */
+ public PairCounting getPaircount() {
+ if(paircount == null) {
+ paircount = new PairCounting(this);
+ }
+ return paircount;
+ }
+
+ /**
+ * Get (compute) the entropy based measures
+ *
+ * @return Entropy based measures
+ */
+ public Entropy getEntropy() {
+ if(entropy == null) {
+ entropy = new Entropy(this);
+ }
+ return entropy;
+ }
+
+ /**
+ * Get (compute) the edit-distance based measures
+ *
+ * @return Edit-distance based measures
+ */
+ public EditDistance getEdit() {
+ if(edit == null) {
+ edit = new EditDistance(this);
+ }
+ return edit;
+ }
+
+ /**
+ * The BCubed based measures
+ *
+ * @return BCubed measures
+ */
+ public BCubed getBCubed() {
+ if(bcubed == null) {
+ bcubed = new BCubed(this);
+ }
+ return bcubed;
+ }
+
+ /**
+ * The set-matching measures
+ *
+ * @return Set-Matching measures
+ */
+ public SetMatchingPurity getSetMatching() {
+ if(smp == null) {
+ smp = new SetMatchingPurity(this);
+ }
+ return smp;
+ }
+
+ /**
+ * Compute the average Gini for each cluster (in both clusterings -
+ * symmetric).
+ *
+ * @return Mean and variance of Gini
+ */
+ public MeanVariance averageSymmetricGini() {
+ MeanVariance mv = new MeanVariance();
+ for(int i1 = 0; i1 < size1; i1++) {
+ double purity = 0.0;
+ if(contingency[i1][size2] > 0) {
+ final double cs = contingency[i1][size2]; // sum, as double.
+ for(int i2 = 0; i2 < size2; i2++) {
+ double rel = contingency[i1][i2] / cs;
+ purity += rel * rel;
+ }
+ mv.put(purity, cs);
+ }
+ }
+ for(int i2 = 0; i2 < size2; i2++) {
+ double purity = 0.0;
+ if(contingency[size1][i2] > 0) {
+ final double cs = contingency[size1][i2]; // sum, as double.
+ for(int i1 = 0; i1 < size1; i1++) {
+ double rel = contingency[i1][i2] / cs;
+ purity += rel * rel;
+ }
+ mv.put(purity, cs);
+ }
+ }
+ return mv;
+ }
+
+ /**
+ * Utility class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static final class Util {
+ /**
+ * F-Measure
+ *
+ * @param precision Precision
+ * @param recall Recall
+ * @param beta Beta value
+ * @return F-Measure
+ */
+ public static double fMeasure(double precision, double recall, double beta) {
+ final double beta2 = beta * beta;
+ return (1 + beta2) * precision * recall / (beta2 * precision + recall);
+ }
+
+ /**
+ * F1-Measure (F-Measure with beta = 1)
+ *
+ * @param precision Precision
+ * @param recall Recall
+ * @return F-Measure
+ */
+ public static double f1Measure(double precision, double recall) {
+ return 2 * precision * recall / (precision + recall);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/clustering/EditDistance.java b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/EditDistance.java
new file mode 100644
index 00000000..9a0f63f8
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/EditDistance.java
@@ -0,0 +1,155 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.evaluation.clustering.ClusterContingencyTable.Util;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+
+/**
+ * Edit distance measures
+ *
+ * <p>
+ * Pantel, P. and Lin, D.<br />
+ * Document clustering with committees<br/>
+ * Proc. 25th ACM SIGIR conference on Research and development in information
+ * retrieval
+ * </p>
+ *
+ * @author Sascha Goldhofer
+ */
+@Reference(authors = "Pantel, P. and Lin, D.", title = "Document clustering with committees", booktitle = "Proc. 25th ACM SIGIR conference on Research and development in information retrieval", url = "http://dx.doi.org/10.1145/564376.564412")
+public class EditDistance {
+ /**
+ * Edit operations for first clustering to second clustering.
+ */
+ int editFirst = -1;
+
+ /**
+ * Edit operations for second clustering to first clustering.
+ */
+ int editSecond = -1;
+
+ /**
+ * Baseline for edit operations
+ */
+ int editOperationsBaseline;
+
+ protected EditDistance(ClusterContingencyTable table) {
+ super();
+ editOperationsBaseline = table.contingency[table.size1][table.size2];
+ {
+ editFirst = 0;
+
+ // iterate over first clustering
+ for(int i1 = 0; i1 < table.size1; i1++) {
+ // get largest cell
+ int largestLabelSet = 0;
+ for(int i2 = 0; i2 < table.size2; i2++) {
+ largestLabelSet = Math.max(largestLabelSet, table.contingency[i1][i2]);
+ }
+
+ // merge: found (largest) cluster to second clusterings cluster
+ editFirst++;
+ // move: wrong objects from this cluster to correct cluster (of second
+ // clustering)
+ editFirst += table.contingency[i1][table.size2] - largestLabelSet;
+ }
+ }
+ {
+ editSecond = 0;
+
+ // iterate over second clustering
+ for(int i2 = 0; i2 < table.size2; i2++) {
+ // get largest cell
+ int largestLabelSet = 0;
+ for(int i1 = 0; i1 < table.size1; i1++) {
+ largestLabelSet = Math.max(largestLabelSet, table.contingency[i1][i2]);
+ }
+
+ // merge: found (largest) cluster to second clusterings cluster
+ editSecond++;
+ // move: wrong objects from this cluster to correct cluster (of second
+ // clustering)
+ editSecond += table.contingency[table.size1][i2] - largestLabelSet;
+ }
+ }
+ }
+
+ /**
+ * Get the baseline editing Operations ( = total Objects)
+ *
+ * @return worst case amount of operations
+ */
+ public int editOperationsBaseline() {
+ return editOperationsBaseline;
+ }
+
+ /**
+ * Get the editing operations required to transform first clustering to
+ * second clustering
+ *
+ * @return Editing operations used to transform first into second clustering
+ */
+ public int editOperationsFirst() {
+ return editFirst;
+ }
+
+ /**
+ * Get the editing operations required to transform second clustering to
+ * first clustering
+ *
+ * @return Editing operations used to transform second into first clustering
+ */
+ public int editOperationsSecond() {
+ return editSecond;
+ }
+
+ /**
+ * Get the editing distance to transform second clustering to first
+ * clustering (normalized, 0 = unequal)
+ *
+ * @return Editing distance first into second clustering
+ */
+ public double editDistanceFirst() {
+ return 1.0 - (1.0 * editOperationsFirst() / editOperationsBaseline());
+ }
+
+ /**
+ * Get the editing distance to transform second clustering to first
+ * clustering (normalized, 0 = unequal)
+ *
+ * @return Editing distance second into first clustering
+ */
+ public double editDistanceSecond() {
+ return 1.0 - (1.0 * editOperationsSecond() / editOperationsBaseline());
+ }
+
+ /**
+ * Get the edit distance F1-Measure
+ *
+ * @return Edit Distance F1-Measure
+ */
+ public double f1Measure() {
+ return Util.f1Measure(editDistanceFirst(), editDistanceSecond());
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/clustering/Entropy.java b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/Entropy.java
new file mode 100644
index 00000000..ded70327
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/Entropy.java
@@ -0,0 +1,237 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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;
+
+/**
+ * Entropy based measures
+ *
+ * References:
+ * <p>
+ * Meilă, M.<br />
+ * Comparing clusterings by the variation of information<br />
+ * Learning theory and kernel machines Volume 2777/2003
+ * </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")
+public class Entropy {
+ /**
+ * Entropy in first
+ */
+ protected double entropyFirst = -1.0;
+
+ /**
+ * Entropy in second
+ */
+ protected double entropySecond = -1.0;
+
+ /**
+ * Joint entropy
+ */
+ protected double entropyJoint = -1.0;
+
+ /**
+ * Constructor.
+ *
+ * @param table Contingency table
+ */
+ protected Entropy(ClusterContingencyTable table) {
+ super();
+ double norm = 1.0 / table.contingency[table.size1][table.size2];
+ {
+ entropyFirst = 0.0;
+ // iterate over first clustering
+ for(int i1 = 0; i1 < table.size1; i1++) {
+ if(table.contingency[i1][table.size2] > 0) {
+ double probability = norm * table.contingency[i1][table.size2];
+ entropyFirst -= probability * Math.log(probability);
+ }
+ }
+ }
+ {
+ entropySecond = 0.0;
+ // iterate over first clustering
+ for(int i2 = 0; i2 < table.size2; i2++) {
+ if(table.contingency[table.size1][i2] > 0) {
+ double probability = norm * table.contingency[table.size1][i2];
+ entropySecond -= probability * Math.log(probability);
+ }
+ }
+ }
+ {
+ entropyJoint = 0.0;
+ for(int i1 = 0; i1 < table.size1; i1++) {
+ for(int i2 = 0; i2 < table.size2; i2++) {
+ if(table.contingency[i1][i2] > 0) {
+ double probability = norm * table.contingency[i1][i2];
+ entropyJoint -= probability * Math.log(probability);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Get the entropy of the first clustering using Log_2. (not normalized, 0 =
+ * equal)
+ *
+ * @return Entropy of first clustering
+ */
+ public double entropyFirst() {
+ return entropyFirst;
+ }
+
+ /**
+ * Get the entropy of the second clustering using Log_2. (not normalized, 0
+ * = equal)
+ *
+ * @return Entropy of second clustering
+ */
+ public double entropySecond() {
+ return entropySecond;
+ }
+
+ /**
+ * Get the joint entropy of both clusterings (not normalized, 0 = equal)
+ *
+ * @return Joint entropy of both clusterings
+ */
+ public double entropyJoint() {
+ return entropyJoint;
+ }
+
+ /**
+ * Get the conditional entropy of the first clustering. (not normalized, 0 =
+ * equal)
+ *
+ * @return Conditional entropy of first clustering
+ */
+ public double entropyConditionalFirst() {
+ return (entropyJoint() - entropySecond());
+ }
+
+ /**
+ * Get the conditional entropy of the first clustering. (not normalized, 0 =
+ * equal)
+ *
+ * @return Conditional entropy of second clustering
+ */
+ public double entropyConditionalSecond() {
+ return (entropyJoint() - entropyFirst());
+ }
+
+ /**
+ * Get Powers entropy (normalized, 0 = equal)
+ * Powers = 1 - NMI_Sum
+ *
+ * @return Powers
+ */
+ public double entropyPowers() {
+ return (2 * entropyJoint() / (entropyFirst() + entropySecond()) - 1);
+ }
+
+ /**
+ * Get the mutual information (not normalized, 0 = equal)
+ *
+ * @return Mutual information
+ */
+ public double entropyMutualInformation() {
+ return (entropyFirst() + entropySecond() - entropyJoint());
+ }
+
+ /**
+ * Get the joint-normalized mutual information (normalized, 0 = unequal)
+ *
+ * @return Joint Normalized Mutual information
+ */
+ public double entropyNMIJoint() {
+ return (entropyMutualInformation() / entropyJoint());
+ }
+
+ /**
+ * Get the min-normalized mutual information (normalized, 0 = unequal)
+ *
+ * @return Min Normalized Mutual information
+ */
+ public double entropyNMIMin() {
+ return (entropyMutualInformation() / Math.min(entropyFirst(), entropySecond()));
+ }
+
+ /**
+ * Get the max-normalized mutual information (normalized, 0 = unequal)
+ *
+ * @return Max Normalized Mutual information
+ */
+ public double entropyNMIMax() {
+ return (entropyMutualInformation() / Math.max(entropyFirst(), entropySecond()));
+ }
+
+ /**
+ * Get the sum-normalized mutual information (normalized, 0 = unequal)
+ *
+ * @return Sum Normalized Mutual information
+ */
+ public double entropyNMISum() {
+ return (2 * entropyMutualInformation() / (entropyFirst() + entropySecond()));
+ }
+
+ /**
+ * Get the sqrt-normalized mutual information (normalized, 0 = unequal)
+ *
+ * @return Sqrt Normalized Mutual information
+ */
+ public double entropyNMISqrt() {
+ return (entropyMutualInformation() / Math.sqrt(entropyFirst() * entropySecond()));
+ }
+
+ /**
+ * Get the variation of information (not normalized, 0 = equal)
+ *
+ * @return Variation of information
+ */
+ public double variationOfInformation() {
+ return (2 * entropyJoint() - (entropyFirst() + entropySecond()));
+ }
+
+ /**
+ * Get the normalized variation of information (normalized, 0 = equal)
+ * NVI = 1 - NMI_Joint
+ *
+ * <p>
+ * Vinh, N.X. and Epps, J. and Bailey, J.<br />
+ * Information theoretic measures for clusterings comparison: is a
+ * correction for chance necessary?<br />
+ * In: Proc. ICML '09 Proceedings of the 26th Annual International
+ * Conference on Machine Learning
+ * </p>
+ *
+ * @return Normalized Variation of information
+ */
+ @Reference(authors = "Vinh, N.X. and Epps, J. and Bailey, J.", title = "Information theoretic measures for clusterings comparison: is a correction for chance necessary?", booktitle = "Proc. ICML '09 Proceedings of the 26th Annual International Conference on Machine Learning", url = "http://dx.doi.org/10.1145/1553374.1553511")
+ public double normalizedVariationOfInformation() {
+ return (1.0 - (entropyMutualInformation() / entropyJoint()));
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/clustering/EvaluateClustering.java b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/EvaluateClustering.java
new file mode 100644
index 00000000..c82f5cf5
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/EvaluateClustering.java
@@ -0,0 +1,288 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.algorithm.clustering.ClusteringAlgorithm;
+import de.lmu.ifi.dbs.elki.algorithm.clustering.trivial.ByLabelClustering;
+import de.lmu.ifi.dbs.elki.data.Clustering;
+import de.lmu.ifi.dbs.elki.database.Database;
+import de.lmu.ifi.dbs.elki.evaluation.Evaluator;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+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.result.ResultUtil;
+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.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;
+
+/**
+ * Evaluate a clustering result by comparing it to an existing cluster label.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.landmark
+ * @apiviz.uses ClusterContingencyTable
+ * @apiviz.has EvaluateClustering.ScoreResult oneway - - «create»
+ */
+public class EvaluateClustering implements Evaluator {
+ /**
+ * Logger for debug output.
+ */
+ protected static final Logging logger = Logging.getLogger(EvaluateClustering.class);
+
+ /**
+ * Parameter to obtain the reference clustering. Defaults to a flat label
+ * clustering.
+ */
+ public static final OptionID REFERENCE_ID = OptionID.getOrCreateOptionID("paircounting.reference", "Reference clustering to compare with. Defaults to a by-label clustering.");
+
+ /**
+ * Parameter flag for special noise handling.
+ */
+ public static final OptionID NOISE_ID = OptionID.getOrCreateOptionID("paircounting.noisespecial", "Use special handling for noise clusters.");
+
+ /**
+ * Parameter flag to disable self-pairing
+ */
+ public static final OptionID SELFPAIR_ID = OptionID.getOrCreateOptionID("paircounting.selfpair", "Enable self-pairing for cluster comparison.");
+
+ /**
+ * Reference algorithm.
+ */
+ private ClusteringAlgorithm<?> referencealg;
+
+ /**
+ * Apply special handling to noise "clusters".
+ */
+ private boolean noiseSpecialHandling;
+
+ /**
+ * Use self-pairing in pair-counting measures
+ */
+ private boolean selfPairing;
+
+ /**
+ * Constructor.
+ *
+ * @param referencealg Reference clustering
+ * @param noiseSpecialHandling Noise handling flag
+ * @param selfPairing Self-pairing flag
+ */
+ public EvaluateClustering(ClusteringAlgorithm<?> referencealg, boolean noiseSpecialHandling, boolean selfPairing) {
+ super();
+ this.referencealg = referencealg;
+ this.noiseSpecialHandling = noiseSpecialHandling;
+ this.selfPairing = selfPairing;
+ }
+
+ @Override
+ public void processNewResult(HierarchicalResult baseResult, Result result) {
+ Database db = ResultUtil.findDatabase(baseResult);
+ List<Clustering<?>> crs = ResultUtil.getClusteringResults(result);
+ if(crs == null || crs.size() < 1) {
+ return;
+ }
+ // Compute the reference clustering
+ Clustering<?> refc = null;
+ // Try to find an existing reference clustering (globally)
+ if(refc == null) {
+ Iterator<Clustering<?>> cs = ResultUtil.filteredResults(baseResult, Clustering.class);
+ while(cs.hasNext()) {
+ Clustering<?> test = cs.next();
+ if(isReferenceResult(test)) {
+ refc = test;
+ break;
+ }
+ }
+ }
+ // Try to find an existing reference clustering (locally)
+ if(refc == null) {
+ Iterator<Clustering<?>> cs = ResultUtil.filteredResults(result, Clustering.class);
+ while(cs.hasNext()) {
+ Clustering<?> test = cs.next();
+ if(isReferenceResult(test)) {
+ refc = test;
+ break;
+ }
+ }
+ }
+ if(refc == null) {
+ logger.debug("Generating a new reference clustering.");
+ Result refres = referencealg.run(db);
+ List<Clustering<?>> refcrs = ResultUtil.getClusteringResults(refres);
+ if(refcrs.size() == 0) {
+ logger.warning("Reference algorithm did not return a clustering result!");
+ return;
+ }
+ if(refcrs.size() > 1) {
+ logger.warning("Reference algorithm returned more than one result!");
+ }
+ refc = refcrs.get(0);
+ }
+ else {
+ logger.debug("Using existing clustering: " + refc.getLongName() + " " + refc.getShortName());
+ }
+ for(Clustering<?> c : crs) {
+ if(c == refc) {
+ continue;
+ }
+ ClusterContingencyTable contmat = new ClusterContingencyTable(selfPairing, noiseSpecialHandling);
+ contmat.process(refc, c);
+
+ db.getHierarchy().add(c, new ScoreResult(contmat));
+ }
+ }
+
+ private boolean isReferenceResult(Clustering<?> t) {
+ // FIXME: don't hard-code strings
+ if(t.getShortName().startsWith("bylabel-")) {
+ return true;
+ }
+ if(t.getShortName().startsWith("bymodel-")) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Result object for outlier score judgements.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.composedOf ClusterContingencyTable
+ */
+ public static class ScoreResult extends BasicResult implements TextWriteable {
+ /**
+ * Cluster contingency table
+ */
+ protected ClusterContingencyTable contmat;
+
+ /**
+ * Constructor.
+ *
+ * @param contmat score result
+ */
+ public ScoreResult(ClusterContingencyTable contmat) {
+ super("Cluster-Evalation", "cluster-evaluation");
+ this.contmat = contmat;
+ }
+
+ /**
+ * Get the contingency table
+ *
+ * @return the contingency table
+ */
+ public ClusterContingencyTable getContingencyTable() {
+ return contmat;
+ }
+
+ @Override
+ public void writeToText(TextWriterStream out, String label) {
+ out.commentPrint("Pair-F1, ");
+ out.commentPrint("Pair-Precision, ");
+ out.commentPrint("Pair-Recall, ");
+ out.commentPrint("Pair-Rand, ");
+ out.commentPrint("Pair-AdjustedRand, ");
+ out.commentPrint("Pair-FowlkesMallows, ");
+ out.commentPrint("Pair-Jaccard, ");
+ out.commentPrint("Pair-Mirkin, ");
+ out.commentPrint("Entropy-VI, ");
+ out.commentPrint("Entropy-NormalizedVI, ");
+ out.commentPrint("Entropy-F1, ");
+ out.commentPrint("Edit-F1, ");
+ out.commentPrint("SM-InvPurity, ");
+ out.commentPrint("SM-Purity, ");
+ out.commentPrint("SM-F1, ");
+ out.commentPrint("BCubed-Precision, ");
+ out.commentPrint("BCubed-Recall, ");
+ out.commentPrint("BCubed-F1");
+ out.flush();
+ out.inlinePrint(contmat.getPaircount().f1Measure());
+ out.inlinePrint(contmat.getPaircount().precision());
+ out.inlinePrint(contmat.getPaircount().recall());
+ out.inlinePrint(contmat.getPaircount().randIndex());
+ out.inlinePrint(contmat.getPaircount().adjustedRandIndex());
+ out.inlinePrint(contmat.getPaircount().fowlkesMallows());
+ out.inlinePrint(contmat.getPaircount().jaccard());
+ out.inlinePrint(contmat.getPaircount().mirkin());
+ out.inlinePrint(contmat.getEntropy().variationOfInformation());
+ out.inlinePrint(contmat.getEntropy().normalizedVariationOfInformation());
+ out.inlinePrint(contmat.getEdit().f1Measure());
+ out.inlinePrint(contmat.getSetMatching().inversePurity());
+ out.inlinePrint(contmat.getSetMatching().purity());
+ out.inlinePrint(contmat.getSetMatching().f1Measure());
+ out.inlinePrint(contmat.getBCubed().precision());
+ out.inlinePrint(contmat.getBCubed().recall());
+ out.inlinePrint(contmat.getBCubed().f1Measure());
+ out.flush();
+ }
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ protected ClusteringAlgorithm<?> referencealg = null;
+
+ protected boolean noiseSpecialHandling = false;
+
+ protected boolean selfPairing = false;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ ObjectParameter<ClusteringAlgorithm<?>> referencealgP = new ObjectParameter<ClusteringAlgorithm<?>>(REFERENCE_ID, ClusteringAlgorithm.class, ByLabelClustering.class);
+ if(config.grab(referencealgP)) {
+ referencealg = referencealgP.instantiateClass(config);
+ }
+
+ Flag noiseSpecialHandlingF = new Flag(NOISE_ID);
+ if(config.grab(noiseSpecialHandlingF)) {
+ noiseSpecialHandling = noiseSpecialHandlingF.getValue();
+ }
+
+ Flag selfPairingF = new Flag(SELFPAIR_ID);
+ if(config.grab(selfPairingF)) {
+ selfPairing = selfPairingF.getValue();
+ }
+ }
+
+ @Override
+ protected EvaluateClustering makeInstance() {
+ return new EvaluateClustering(referencealg, noiseSpecialHandling, !selfPairing);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/clustering/PairCounting.java b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/PairCounting.java
new file mode 100644
index 00000000..500588fa
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/PairCounting.java
@@ -0,0 +1,225 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.logging.LoggingUtil;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+
+/**
+ * Pair-counting measures.
+ *
+ * @author Erich Schubert
+ */
+public class PairCounting {
+ /**
+ * Pair counting confusion matrix (flat: inBoth, inFirst, inSecond, inNone)
+ */
+ protected long[] pairconfuse = null;
+
+ /**
+ * Constructor.
+ */
+ protected PairCounting(ClusterContingencyTable table) {
+ super();
+ // Aggregations
+ long inBoth = 0, in1 = 0, in2 = 0, total = 0;
+ // Process first clustering:
+ {
+ for(int i1 = 0; i1 < table.size1; i1++) {
+ final int size = table.contingency[i1][table.size2 + 1];
+ if(table.breakNoiseClusters && table.noise1.get(i1)) {
+ if(table.selfPairing) {
+ in1 += size;
+ } // else: 0
+ }
+ else {
+ if(table.selfPairing) {
+ in1 += size * size;
+ }
+ else {
+ in1 += size * (size - 1);
+ }
+ }
+ }
+ }
+ // Process second clustering:
+ {
+ for(int i2 = 0; i2 < table.size2; i2++) {
+ final int size = table.contingency[table.size1 + 1][i2];
+ if(table.breakNoiseClusters && table.noise2.get(i2)) {
+ if(table.selfPairing) {
+ in2 += size;
+ } // else: 0
+ }
+ else {
+ if(table.selfPairing) {
+ in2 += size * size;
+ }
+ else {
+ in2 += size * (size - 1);
+ }
+ }
+ }
+ }
+ // Process combinations
+ for(int i1 = 0; i1 < table.size1; i1++) {
+ for(int i2 = 0; i2 < table.size2; i2++) {
+ final int size = table.contingency[i1][i2];
+ if(table.breakNoiseClusters && (table.noise1.get(i1) || table.noise2.get(i2))) {
+ if(table.selfPairing) {
+ inBoth += size;
+ } // else: 0
+ }
+ else {
+ if(table.selfPairing) {
+ inBoth += size * size;
+ }
+ else {
+ inBoth += size * (size - 1);
+ }
+ }
+ }
+ }
+ // The official sum
+ int tsize = table.contingency[table.size1][table.size2];
+ if(table.contingency[table.size1][table.size2 + 1] != tsize || table.contingency[table.size1 + 1][table.size2] != tsize) {
+ LoggingUtil.warning("PairCounting F-Measure is not well defined for overlapping and incomplete clusterings.");
+ }
+ if(tsize >= Math.sqrt(Long.MAX_VALUE)) {
+ LoggingUtil.warning("Your data set size probably is too big for this implementation, which uses only long precision.");
+ }
+ if(table.selfPairing) {
+ total = tsize * tsize;
+ }
+ else {
+ total = tsize * (tsize - 1);
+ }
+ long inFirst = in1 - inBoth, inSecond = in2 - inBoth;
+ long inNone = total - (inBoth + inFirst + inSecond);
+ pairconfuse = new long[] { inBoth, inFirst, inSecond, inNone };
+ }
+
+ /**
+ * Get the pair-counting F-Measure
+ *
+ * @param beta Beta value.
+ * @return F-Measure
+ */
+ public double fMeasure(double beta) {
+ final double beta2 = beta * beta;
+ double fmeasure = ((1 + beta2) * pairconfuse[0]) / ((1 + beta2) * pairconfuse[0] + beta2 * pairconfuse[1] + pairconfuse[2]);
+ return fmeasure;
+ }
+
+ /**
+ * Get the pair-counting F1-Measure.
+ *
+ * @return F1-Measure
+ */
+ public double f1Measure() {
+ return fMeasure(1.0);
+ }
+
+ /**
+ * Computes the pair-counting precision.
+ *
+ * @return pair-counting precision
+ */
+ public double precision() {
+ return ((double) pairconfuse[0]) / (pairconfuse[0] + pairconfuse[2]);
+ }
+
+ /**
+ * Computes the pair-counting recall.
+ *
+ * @return pair-counting recall
+ */
+ public double recall() {
+ return ((double) pairconfuse[0]) / (pairconfuse[0] + pairconfuse[1]);
+ }
+
+ /**
+ * Computes the pair-counting Fowlkes-mallows (flat only, non-hierarchical!)
+ *
+ * <p>
+ * Fowlkes, E.B. and Mallows, C.L.<br />
+ * A method for comparing two hierarchical clusterings<br />
+ * In: Journal of the American Statistical Association, Vol. 78 Issue 383
+ * </p>
+ *
+ * @return pair-counting Fowlkes-mallows
+ */
+ // TODO: implement for non-flat clusterings!
+ @Reference(authors = "Fowlkes, E.B. and Mallows, C.L.", title = "A method for comparing two hierarchical clusterings", booktitle = "Journal of the American Statistical Association, Vol. 78 Issue 383")
+ public double fowlkesMallows() {
+ return Math.sqrt(precision() * recall());
+ }
+
+ /**
+ * Computes the Rand index (RI).
+ *
+ * <p>
+ * Rand, W. M.<br />
+ * Objective Criteria for the Evaluation of Clustering Methods<br />
+ * Journal of the American Statistical Association, Vol. 66 Issue 336
+ * </p>
+ *
+ * @return The Rand index (RI).
+ */
+ @Reference(authors = "Rand, W. M.", title = "Objective Criteria for the Evaluation of Clustering Methods", booktitle = "Journal of the American Statistical Association, Vol. 66 Issue 336", url = "http://www.jstor.org/stable/10.2307/2284239")
+ public double randIndex() {
+ final double sum = pairconfuse[0] + pairconfuse[1] + pairconfuse[2] + pairconfuse[3];
+ return (pairconfuse[0] + pairconfuse[3]) / sum;
+ }
+
+ /**
+ * Computes the adjusted Rand index (ARI).
+ *
+ * @return The adjusted Rand index (ARI).
+ */
+ public double adjustedRandIndex() {
+ final double nom = pairconfuse[0] * pairconfuse[3] - pairconfuse[1] * pairconfuse[2];
+ final long d1 = (pairconfuse[0] + pairconfuse[1]) * (pairconfuse[1] + pairconfuse[3]);
+ final long d2 = (pairconfuse[0] + pairconfuse[2]) * (pairconfuse[2] + pairconfuse[3]);
+ return 2 * nom / (d1 + d2);
+ }
+
+ /**
+ * Computes the Jaccard index
+ *
+ * @return The Jaccard index
+ */
+ public double jaccard() {
+ final double sum = pairconfuse[0] + pairconfuse[1] + pairconfuse[2];
+ return pairconfuse[0] / sum;
+ }
+
+ /**
+ * Computes the Mirkin index
+ *
+ * @return The Mirkin index
+ */
+ public long mirkin() {
+ return 2 * (pairconfuse[1] + pairconfuse[2]);
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/clustering/SetMatchingPurity.java b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/SetMatchingPurity.java
new file mode 100644
index 00000000..1691068a
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/SetMatchingPurity.java
@@ -0,0 +1,168 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.evaluation.clustering.ClusterContingencyTable.Util;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+
+/**
+ * Set matching purity measures
+ *
+ * References:
+ * <p>
+ * Zhao, Y. and Karypis, G.<br />
+ * Criterion functions for document clustering: Experiments and analysis<br />
+ * University of Minnesota, Department of Computer Science, Technical Report
+ * 01-40, 2001
+ * </p>
+ * <p>
+ * Meilă, M<br />
+ * Comparing clusterings<br />
+ * University of Washington, Seattle, Technical Report 418, 2002
+ * </p>
+ * <p>
+ * Steinbach, M. and Karypis, G. and Kumar, V. and others<br />
+ * A comparison of document clustering techniques<br />
+ * KDD workshop on text mining, 2000
+ * </p>
+ *
+ * @author Sascha Goldhofer
+ */
+@Reference(authors = "Meilă, M", title = "Comparing clusterings", booktitle = "University of Washington, Seattle, Technical Report 418, 2002", url = "http://www.stat.washington.edu/mmp/www.stat.washington.edu/mmp/Papers/compare-colt.pdf")
+public class SetMatchingPurity {
+ /**
+ * Result cache
+ */
+ protected double smPurity = -1.0, smInversePurity = -1.0, smFFirst = -1.0, smFSecond = - 1.0;
+
+ /**
+ * Constructor.
+ *
+ * @param table Contingency table
+ */
+ protected SetMatchingPurity(ClusterContingencyTable table) {
+ super();
+ int numobj = table.contingency[table.size1][table.size2];
+ {
+ smPurity = 0.0;
+ smFFirst = 0.0;
+ // iterate first clustering
+ for(int i1 = 0; i1 < table.size1; i1++) {
+ double precisionMax = 0.0;
+ double fMax = 0.0;
+ for(int i2 = 0; i2 < table.size2; i2++) {
+ precisionMax = Math.max(precisionMax, (1.0 * table.contingency[i1][i2]));
+ fMax = Math.max(fMax, (2.0 * table.contingency[i1][i2]) / (table.contingency[i1][table.size2] + table.contingency[table.size1][i2]));
+ // / numobj));
+ }
+ smPurity += (precisionMax / numobj);
+ smFFirst += (table.contingency[i1][table.size2] / table.contingency[table.size1][table.size2]) * fMax;
+ // * contingency[i1][size2]/numobj;
+ }
+ }
+ {
+ smInversePurity = 0.0;
+ smFSecond = 0.0;
+ // iterate second clustering
+ for(int i2 = 0; i2 < table.size2; i2++) {
+ double recallMax = 0.0;
+ double fMax = 0.0;
+ for(int i1 = 0; i1 < table.size1; i1++) {
+ recallMax = Math.max(recallMax, (1.0 * table.contingency[i1][i2]));
+ fMax = Math.max(fMax, (2.0 * table.contingency[i1][i2]) / (table.contingency[i1][table.size2] + table.contingency[table.size1][i2]));
+ // / numobj));
+ }
+ smInversePurity += (recallMax / numobj);
+ smFSecond += (table.contingency[table.size1][i2] / table.contingency[table.size1][table.size2]) * fMax;
+ // * contingency[i1][size2]/numobj;
+ }
+ }
+ }
+
+ /**
+ * Get the set matchings purity (first:second clustering) (normalized, 1 =
+ * equal)
+ *
+ * @return purity
+ */
+ @Reference(authors = "Zhao, Y. and Karypis, G.", title = "Criterion functions for document clustering: Experiments and analysis", booktitle = "University of Minnesota, Department of Computer Science, Technical Report 01-40, 2001", url = "http://www-users.cs.umn.edu/~karypis/publications/Papers/PDF/vscluster.pdf")
+ public double purity() {
+ return smPurity;
+ }
+
+ /**
+ * Get the set matchings inverse purity (second:first clustering)
+ * (normalized, 1 = equal)
+ *
+ * @return Inverse purity
+ */
+ public double inversePurity() {
+ return smInversePurity;
+ }
+
+ /**
+ * Get the set matching F1-Measure
+ *
+ * <p>
+ * Steinbach, M. and Karypis, G. and Kumar, V. and others<br />
+ * A comparison of document clustering techniques<br />
+ * KDD workshop on text mining, 2000
+ * </p>
+ *
+ * @return Set Matching F1-Measure
+ */
+ @Reference(authors = "Steinbach, M. and Karypis, G. and Kumar, V. and others", title = "A comparison of document clustering techniques", booktitle = "KDD workshop on text mining, 2000", url = "http://www-users.itlabs.umn.edu/~karypis/publications/Papers/PDF/doccluster.pdf")
+ public double f1Measure() {
+ return Util.f1Measure(purity(), inversePurity());
+ }
+
+ /**
+ * Get the Van Rijsbergen’s F measure (asymmetric) for first clustering
+ *
+ * <p>
+ * E. Amigó, J. Gonzalo, J. Artiles, and F. Verdejo <br />
+ * A comparison of extrinsic clustering evaluation metrics based on formal constraints<br />
+ * Inf. Retrieval, vol. 12, no. 5, pp. 461–486, 2009
+ * </p>
+ *
+ * @return Set Matching F-Measure of first clustering
+ */
+ public double fMeasureFirst() {
+ return smFFirst;
+ }
+
+ /**
+ * Get the Van Rijsbergen’s F measure (asymmetric) for second clustering
+ *
+ * <p>
+ * E. Amigó, J. Gonzalo, J. Artiles, and F. Verdejo <br />
+ * A comparison of extrinsic clustering evaluation metrics based on formal constraints<br />
+ * Inf. Retrieval, vol. 12, no. 5, pp. 461–486, 2009
+ * </p>
+ *
+ * @return Set Matching F-Measure of second clustering
+ */
+ public double fMeasureSecond() {
+ return smFSecond;
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..0b61fa75
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/package-info.java
@@ -0,0 +1,26 @@
+/**
+ * <p>Evaluation of clustering results.</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.evaluation.clustering; \ No newline at end of file
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
new file mode 100644
index 00000000..2471b135
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/pairsegments/ClusterPairSegmentAnalysis.java
@@ -0,0 +1,47 @@
+package de.lmu.ifi.dbs.elki.evaluation.clustering.pairsegments;
+
+import java.util.List;
+
+import de.lmu.ifi.dbs.elki.data.Clustering;
+import de.lmu.ifi.dbs.elki.evaluation.Evaluator;
+import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
+import de.lmu.ifi.dbs.elki.result.Result;
+import de.lmu.ifi.dbs.elki.result.ResultUtil;
+
+/**
+ * Evaluate clustering results by building segments for their pairs: shared
+ * pairs and differences.
+ *
+ * @author Sascha Goldhofer
+ * @author Erich Schubert
+ *
+ * @apiviz.uses Clustering
+ * @apiviz.uses Segments
+ */
+public class ClusterPairSegmentAnalysis implements Evaluator {
+ /**
+ * Constructor.
+ */
+ public ClusterPairSegmentAnalysis() {
+ super();
+ }
+
+ /**
+ * Perform clusterings evaluation
+ */
+ @Override
+ public void processNewResult(HierarchicalResult baseResult, Result result) {
+ // Get all new clusterings
+ // TODO: handle clusterings added later, too. Can we update the result?
+
+ List<Clustering<?>> clusterings = ResultUtil.getClusteringResults(result);
+ // Abort if not enough clusterings to compare
+ if(clusterings.size() < 2) {
+ return;
+ }
+
+ // create segments
+ Segments segments = new Segments(clusterings, baseResult);
+ baseResult.getHierarchy().add(result, segments);
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..8ce8fd4a
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/pairsegments/Segment.java
@@ -0,0 +1,149 @@
+package de.lmu.ifi.dbs.elki.evaluation.clustering.pairsegments;
+
+import java.util.Arrays;
+
+import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+
+/**
+ * A segment represents a set of pairs that share the same clustering
+ * properties.
+ *
+ * As such, for each ring (= clustering), a cluster number (or the constant
+ * {@link #UNCLUSTERED}) is stored.
+ */
+public class Segment implements Comparable<Segment> {
+ /**
+ * Object is not clustered
+ */
+ public static final int UNCLUSTERED = -1;
+
+ /**
+ * IDs in segment, for object segments.
+ */
+ protected DBIDs objIDs = null;
+
+ /**
+ * Size of cluster, in pairs.
+ */
+ protected long pairsize = 0;
+
+ /**
+ * The cluster numbers in each ring
+ */
+ protected int[] clusterIds;
+
+ public Segment(int clusterings) {
+ clusterIds = new int[clusterings];
+ }
+
+ public long getPairCount() {
+ return pairsize;
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param clone Clone of cluster ids
+ */
+ public Segment(int[] clone) {
+ clusterIds = clone;
+ }
+
+ /**
+ * Get cluster number for index idx.
+ *
+ * @param idx Index
+ * @return Cluster number
+ */
+ public int get(int idx) {
+ return clusterIds[idx];
+ }
+
+ /**
+ * Checks if the segment has a cluster with unpaired objects. Unpaired
+ * clusters are represented by "0" (0 = all).
+ *
+ * @return true when unclustered in at least one dimension.
+ */
+ public boolean isUnpaired() {
+ for(int id : clusterIds) {
+ if(id == UNCLUSTERED) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Check if this segment contains the pairs that are never clustered by any of
+ * the clusterings (all 0).
+ *
+ * @return true when unclustered everywhere
+ */
+ public boolean isNone() {
+ for(int id : clusterIds) {
+ if(id != UNCLUSTERED) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns the index of the first clustering having an unpaired cluster, or -1
+ * no unpaired cluster exists.
+ *
+ * @return clustering id or -1
+ */
+ public int getUnpairedClusteringIndex() {
+ for(int index = 0; index < clusterIds.length; index++) {
+ if(clusterIds[index] == UNCLUSTERED) {
+ return index;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Get the DBIDs of objects contained in this segment.
+ *
+ * @return the segment IDs
+ */
+ public DBIDs getDBIDs() {
+ return objIDs;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if(!(Segment.class.isInstance(obj))) {
+ return false;
+ }
+ Segment other = (Segment) obj;
+ return Arrays.equals(clusterIds, other.clusterIds);
+ }
+
+ @Override
+ public int hashCode() {
+ return Arrays.hashCode(clusterIds);
+ }
+
+ @Override
+ public int compareTo(Segment sid) {
+ for(int i = 0; i < clusterIds.length; i++) {
+ final int a = this.clusterIds[i];
+ final int b = sid.clusterIds[i];
+ if(a != b) {
+ if(a * b > 0) {
+ // Regular comparison
+ return (a < b) ? -1 : +1;
+ // return (a < b) ? +1 : -1;
+ }
+ else {
+ // Inverse, to sort negative last
+ return (a < b) ? +1 : -1;
+ }
+ }
+ }
+ return 0;
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..97c79dfb
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/pairsegments/Segments.java
@@ -0,0 +1,361 @@
+package de.lmu.ifi.dbs.elki.evaluation.clustering.pairsegments;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.TreeMap;
+
+import de.lmu.ifi.dbs.elki.data.Cluster;
+import de.lmu.ifi.dbs.elki.data.Clustering;
+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.HashSetModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.SetDBIDs;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.result.BasicResult;
+import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+
+/**
+ * Creates segments of two or more clusterings.
+ *
+ * <p>
+ * Segments are the equally paired database objects of all given (2+)
+ * clusterings. Given a contingency table, an object Segment represents the
+ * table's cells where an intersection of classes and labels are given. Pair
+ * Segments are created by converting an object Segment into its pair
+ * representation. Converting all object Segments into pair Segments results in
+ * a larger number of pair Segments, if any fragmentation (no perfect match of
+ * clusters) within the contingency table has occurred (multiple cells on one
+ * row or column). Thus for ever object Segment exists a corresponding pair
+ * Segment. Additionally pair Segments represent pairs that are only in one
+ * Clustering which occurs for each split of a clusterings cluster by another
+ * clustering. Here, these pair Segments are referenced as fragmented Segments.
+ * Within the visualization they describe (at least two) pair Segments that have
+ * a corresponding object Segment.
+ * </p>
+ *
+ * <p>
+ * Reference:<br />
+ * Evaluation of Clusterings – Metrics and Visual Support<br />
+ * Elke Achtert, Sascha Goldhofer, Hans-Peter Kriegel, Erich Schubert, Arthur
+ * Zimek<br />
+ * In: Proc. 28th International Conference on Data Engineering (ICDE) 2012
+ * </p>
+ *
+ * @author Sascha Goldhofer
+ * @author Erich Schubert
+ */
+@Reference(title = "Evaluation of Clusterings – Metrics and Visual Support", authors = "Elke Achtert, Sascha Goldhofer, Hans-Peter Kriegel, Erich Schubert, Arthur Zimek", booktitle = "Proc. 28th International Conference on Data Engineering (ICDE) 2012", url = "http://elki.dbs.ifi.lmu.de/wiki/PairSegments")
+public class Segments extends BasicResult implements Iterable<Segment> {
+ /**
+ * Class logger
+ */
+ private static final Logging logger = Logging.getLogger(Segments.class);
+
+ /**
+ * Clusterings
+ */
+ private List<Clustering<?>> clusterings;
+
+ /**
+ * Clusters
+ */
+ private List<List<? extends Cluster<?>>> clusters;
+
+ /**
+ * Number of clusterings in comparison
+ */
+ private int clusteringsCount;
+
+ /**
+ * Number of Clusters for each clustering
+ */
+ private int[] numclusters;
+
+ /**
+ * Total number of objects
+ */
+ private int totalObjects;
+
+ /**
+ * Pairs actually present in the data set
+ */
+ private int actualPairs;
+
+ /**
+ * The actual segments
+ */
+ private TreeMap<Segment, Segment> segments;
+
+ /**
+ * Initialize segments. Add DB objects via addObject method.
+ *
+ * @param clusterings List of clusterings in comparison
+ * @param baseResult used to retrieve db objects
+ */
+ public Segments(List<Clustering<?>> clusterings, HierarchicalResult baseResult) {
+ super("cluster pair segments", "pair-segments");
+ this.clusterings = clusterings;
+ this.clusteringsCount = clusterings.size();
+ segments = new TreeMap<Segment, Segment>(); // TODO: replace with array list
+
+ numclusters = new int[clusteringsCount];
+ clusters = new ArrayList<List<? extends Cluster<?>>>(clusteringsCount);
+
+ // save count of clusters
+ int clusteringIndex = 0;
+ for(Clustering<?> clr : clusterings) {
+ List<? extends Cluster<?>> curClusters = clr.getAllClusters();
+ clusters.add(curClusters);
+ numclusters[clusteringIndex] = curClusters.size();
+
+ clusteringIndex++;
+ }
+
+ recursivelyFill(clusters);
+ for(Segment seg : segments.keySet()) {
+ actualPairs += seg.getPairCount();
+ }
+ }
+
+ private void recursivelyFill(List<List<? extends Cluster<?>>> cs) {
+ final int numclusterings = cs.size();
+ Iterator<? extends Cluster<?>> iter = cs.get(0).iterator();
+ int[] path = new int[numclusterings];
+ for(int cnum = 0; iter.hasNext(); cnum++) {
+ Cluster<?> clust = iter.next();
+ path[0] = cnum;
+ if(numclusterings > 1) {
+ SetDBIDs idset = DBIDUtil.ensureSet(clust.getIDs());
+ recursivelyFill(cs, 1, idset, idset, path, true);
+ }
+ else {
+ // Add to results.
+ makeOrUpdateSegment(path, clust.getIDs(), clust.size() * (clust.size() - 1));
+ }
+
+ totalObjects += clust.size();
+ }
+ }
+
+ private void recursivelyFill(List<List<? extends Cluster<?>>> cs, int depth, SetDBIDs first, SetDBIDs second, int[] path, boolean objectsegment) {
+ final int numclusterings = cs.size();
+ Iterator<? extends Cluster<?>> iter = cs.get(depth).iterator();
+ for(int cnum = 0; iter.hasNext(); cnum++) {
+ Cluster<?> clust = iter.next();
+ // Compute intersections with new cluster.
+ // nfp := intersection( first, cluster )
+ // Adding asymmetric differences to nd1, nd2.
+ // nse := intersection( second, cluster )
+ HashSetModifiableDBIDs nfirstp = DBIDUtil.newHashSet(first.size());
+ HashSetModifiableDBIDs ndelta1 = DBIDUtil.newHashSet(first);
+ HashSetModifiableDBIDs ndelta2 = DBIDUtil.newHashSet();
+ HashSetModifiableDBIDs nsecond = DBIDUtil.newHashSet(second.size());
+ for(DBID id : clust.getIDs()) {
+ if(ndelta1.remove(id)) {
+ nfirstp.add(id);
+ }
+ else {
+ ndelta2.add(id);
+ }
+ if(second.contains(id)) {
+ nsecond.add(id);
+ }
+ }
+ if(nsecond.size() <= 0) {
+ continue; // disjoint
+ }
+ if(nfirstp.size() > 0) {
+ path[depth] = cnum;
+ if(depth < numclusterings - 1) {
+ recursivelyFill(cs, depth + 1, nfirstp, nsecond, path, objectsegment);
+ }
+ else {
+ // Add to results.
+ // In fact, nfirstp should equal nsecond here
+ int selfpairs = DBIDUtil.intersection(nfirstp, nsecond).size();
+ if(objectsegment) {
+ makeOrUpdateSegment(path, nfirstp, (nfirstp.size() * nsecond.size()) - selfpairs);
+ }
+ else {
+ makeOrUpdateSegment(path, null, (nfirstp.size() * nsecond.size()) - selfpairs);
+ }
+ }
+ }
+ // Elements that were in first, but in not in the cluster
+ if(ndelta1.size() > 0) {
+ path[depth] = Segment.UNCLUSTERED;
+ if(depth < numclusterings - 1) {
+ recursivelyFill(cs, depth + 1, ndelta1, nsecond, path, false);
+ }
+ else {
+ // Add to results.
+ int selfpairs = DBIDUtil.intersection(ndelta1, nsecond).size();
+ makeOrUpdateSegment(path, null, (ndelta1.size() * nsecond.size()) - selfpairs);
+ }
+ }
+ // FIXME: this part doesn't work right yet for over 2 clusterings!
+ // It used to work in revision 9236, eventually go back to this code!
+ if(ndelta2.size() > 0 && objectsegment) {
+ int[] npath = new int[path.length];
+ Arrays.fill(npath, Segment.UNCLUSTERED);
+ npath[depth] = cnum;
+ if(depth < numclusterings - 1) {
+ recursivelyFill(cs, depth + 1, ndelta2, nsecond, npath, false);
+ }
+ else {
+ // Add to results.
+ int selfpairs = DBIDUtil.intersection(ndelta2, nsecond).size();
+ makeOrUpdateSegment(npath, null, (ndelta2.size() * nsecond.size()) - selfpairs);
+ }
+ }
+ }
+ }
+
+ private void makeOrUpdateSegment(int[] path, DBIDs ids, int pairsize) {
+ Segment seg = segments.get(new Segment(path));
+ if(seg == null) {
+ seg = new Segment(path.clone());
+ segments.put(seg, seg);
+ }
+ if(ids != null) {
+ if(seg.getDBIDs() != null) {
+ logger.warning("Expected segment to not have IDs.");
+ }
+ seg.objIDs = ids;
+ }
+ seg.pairsize += pairsize;
+ }
+
+ /**
+ * Get the description of the nth clustering.
+ *
+ * @param clusteringID Clustering number
+ * @return long name of clustering
+ */
+ public String getClusteringDescription(int clusteringID) {
+ return clusterings.get(clusteringID).getLongName();
+ }
+
+ /**
+ * Return to a given segment with unpaired objects, the corresponding segments
+ * that result in an unpaired segment. So, one cluster of a clustering is
+ * split by another clustering in multiple segments, resulting in a segment
+ * with unpaired objects, describing the missing pairs between the split
+ * cluster / between the segments.
+ *
+ * Basically we compare only two clusterings at once. If those clusterings do
+ * not have the whole cluster in common, we have at least three segments (two
+ * cluster), one of them containing the unpaired segment. A segmentID 3-0,
+ * describes a cluster 3 in clustering 1 (index 0) and all clusters 3-x in
+ * clustering 2. So we search for all segments 3-x (0 being a wildcard).
+ *
+ * @param unpairedSegment
+ * @return Segments describing the set of objects that result in an unpaired
+ * segment
+ */
+ public List<Segment> getPairedSegments(Segment unpairedSegment) {
+ ArrayList<Segment> pairedSegments = new ArrayList<Segment>();
+ // search the segments. Index at "unpairedClustering" being the wildcard.
+ segments: for(Segment segment : this) {
+ // if mismatch except at unpaired Clustering index => exclude.
+ for(int i = 0; i < clusteringsCount; i++) {
+ if(unpairedSegment.get(i) != Segment.UNCLUSTERED) {
+ // mismatch
+ if(segment.get(i) != unpairedSegment.get(i)) {
+ continue segments;
+ }
+ }
+ // do not add wildcard
+ if(segment.get(i) == Segment.UNCLUSTERED) {
+ continue segments;
+ }
+ }
+
+ // add segment to list
+ pairedSegments.add(segment);
+ }
+
+ return pairedSegments;
+ }
+
+ /**
+ * @param temp Temporary segment to be unified
+ * @return the segmentID given by its string representation
+ */
+ public Segment unifySegment(Segment temp) {
+ Segment found = segments.get(temp);
+ return (found != null) ? found : temp;
+ }
+
+ /**
+ * Get the number of segments
+ *
+ * @return Number of segments
+ */
+ public int size() {
+ return segments.size();
+ }
+
+ /**
+ * Get total number of pairs with or without the unclustered pairs.
+ *
+ * @param withUnclusteredPairs if false, segment with unclustered pairs is
+ * removed
+ * @return pair count, with or without unclusted (non-existant) pairs
+ */
+ public int getPairCount(boolean withUnclusteredPairs) {
+ if(withUnclusteredPairs) {
+ return (totalObjects * (totalObjects - 1)); // / 2;
+ }
+ else {
+ return actualPairs;
+ }
+ }
+
+ /**
+ * Get the number of clusterings
+ *
+ * @return number of clusterings compared
+ */
+ public int getClusterings() {
+ return clusteringsCount;
+ }
+
+ /**
+ * Return the sum of all clusters
+ *
+ * @return sum of all cluster counts
+ */
+ public int getTotalClusterCount() {
+ int clusterCount = 0;
+
+ for(int i = 0; i < numclusters.length; i++) {
+ clusterCount += numclusters[i];
+ }
+
+ return clusterCount;
+ }
+
+ /**
+ * Returns the highest number of Clusters in the clusterings
+ *
+ * @return highest cluster count
+ */
+ public int getHighestClusterCount() {
+ int maxClusters = 0;
+
+ for(int i = 0; i < numclusters.length; i++) {
+ maxClusters = Math.max(maxClusters, numclusters[i]);
+ }
+ return maxClusters;
+ }
+
+ @Override
+ public Iterator<Segment> iterator() {
+ return segments.keySet().iterator();
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..27176ff6
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/clustering/pairsegments/package-info.java
@@ -0,0 +1,26 @@
+/**
+ * <p>Pair-segment analysis of multiple clusterings.</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.evaluation.clustering.pairsegments; \ No newline at end of file
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 733f1d39..124abf9e 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/histogram/ComputeOutlierHistogram.java
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/histogram/ComputeOutlierHistogram.java
@@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.evaluation.histogram;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2011
+Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -36,8 +36,8 @@ import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs;
import de.lmu.ifi.dbs.elki.distance.distancefunction.EuclideanDistanceFunction;
import de.lmu.ifi.dbs.elki.evaluation.Evaluator;
import de.lmu.ifi.dbs.elki.logging.Logging;
-import de.lmu.ifi.dbs.elki.math.AggregatingHistogram;
-import de.lmu.ifi.dbs.elki.math.FlexiHistogram;
+import de.lmu.ifi.dbs.elki.math.histograms.AggregatingHistogram;
+import de.lmu.ifi.dbs.elki.math.histograms.FlexiHistogram;
import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
import de.lmu.ifi.dbs.elki.result.HistogramResult;
import de.lmu.ifi.dbs.elki.result.Result;
@@ -52,7 +52,8 @@ 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.pairs.Pair;
+import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleDoublePair;
+import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleObjPair;
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.OutlierScalingFunction;
@@ -163,7 +164,7 @@ public class ComputeOutlierHistogram implements Evaluator {
ModifiableDBIDs ids = DBIDUtil.newHashSet(or.getScores().getDBIDs());
DBIDs outlierIds = DatabaseUtil.getObjectsByLabelMatch(database, positiveClassName);
// first value for outliers, second for each object
- final AggregatingHistogram<Pair<Double, Double>, Pair<Double, Double>> hist;
+ final AggregatingHistogram<DoubleDoublePair, DoubleDoublePair> hist;
// If we have useful (finite) min/max, use these for binning.
double min = scaling.getMin();
double max = scaling.getMax();
@@ -174,14 +175,14 @@ public class ComputeOutlierHistogram implements Evaluator {
hist = AggregatingHistogram.DoubleSumDoubleSumHistogram(bins, min, max);
}
// first fill histogram only with values of outliers
- Pair<Double, Double> positive, negative;
+ DoubleDoublePair positive, negative;
if(!splitfreq) {
- positive = new Pair<Double, Double>(0., 1. / ids.size());
- negative = new Pair<Double, Double>(1. / ids.size(), 0.);
+ positive = new DoubleDoublePair(0., 1. / ids.size());
+ negative = new DoubleDoublePair(1. / ids.size(), 0.);
}
else {
- positive = new Pair<Double, Double>(0., 1. / outlierIds.size());
- negative = new Pair<Double, Double>(1. / (ids.size() - outlierIds.size()), 0.);
+ positive = new DoubleDoublePair(0., 1. / outlierIds.size());
+ negative = new DoubleDoublePair(1. / (ids.size() - outlierIds.size()), 0.);
}
ids.removeDBIDs(outlierIds);
// fill histogram with values of each object
@@ -199,9 +200,9 @@ public class ComputeOutlierHistogram implements Evaluator {
// turn into Collection
Collection<DoubleVector> collHist = new ArrayList<DoubleVector>(hist.getNumBins());
- for(Pair<Double, Pair<Double, Double>> ppair : hist) {
- Pair<Double, Double> data = ppair.getSecond();
- DoubleVector row = new DoubleVector(new double[] { ppair.getFirst(), data.getFirst(), data.getSecond() });
+ for(DoubleObjPair<DoubleDoublePair> ppair : hist) {
+ DoubleDoublePair data = ppair.getSecond();
+ DoubleVector row = new DoubleVector(new double[] { ppair.first, data.first, data.second });
collHist.add(row);
}
return new HistogramResult<DoubleVector>("Outlier Score Histogram", "outlier-histogram", collHist);
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 8f13f04e..e02426d7 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) 2011
+Copyright (C) 2012
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
new file mode 100644
index 00000000..c28c22d3
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/index/IndexPurity.java
@@ -0,0 +1,104 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map.Entry;
+
+import de.lmu.ifi.dbs.elki.data.DoubleVector;
+import de.lmu.ifi.dbs.elki.database.Database;
+import de.lmu.ifi.dbs.elki.database.ids.DBID;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.evaluation.Evaluator;
+import de.lmu.ifi.dbs.elki.index.tree.Node;
+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.math.MeanVariance;
+import de.lmu.ifi.dbs.elki.result.CollectionResult;
+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.DatabaseUtil;
+
+/**
+ * Compute the purity of index pages as a naive measure for performance
+ * capabilities using the Gini index.
+ *
+ * @author Erich Schubert
+ */
+public class IndexPurity implements Evaluator {
+ /**
+ * Constructor.
+ */
+ public IndexPurity() {
+ super();
+ }
+
+ @Override
+ public void processNewResult(HierarchicalResult baseResult, Result newResult) {
+ Database database = ResultUtil.findDatabase(baseResult);
+ final ArrayList<SpatialIndexTree<?, ?>> indexes = ResultUtil.filterResults(newResult, SpatialIndexTree.class);
+ if(indexes == null || indexes.size() <= 0) {
+ return;
+ }
+ Relation<String> lblrel = DatabaseUtil.guessLabelRepresentation(database);
+ for(SpatialIndexTree<?, ?> index : indexes) {
+ List<? extends SpatialEntry> leaves = index.getLeaves();
+ MeanVariance mv = new MeanVariance();
+ for(SpatialEntry e : leaves) {
+ SpatialDirectoryEntry leaf = (SpatialDirectoryEntry) e;
+ Node<?> n = index.getNode(leaf.getEntryID());
+
+ final int total = n.getNumEntries();
+ HashMap<String, Integer> map = new HashMap<String, Integer>(total);
+ for(int i = 0; i < total; i++) {
+ DBID id = ((SpatialPointLeafEntry) n.getEntry(i)).getDBID();
+ String label = lblrel.get(id);
+ Integer val = map.get(label);
+ if(val == null) {
+ val = 1;
+ }
+ else {
+ val += 1;
+ }
+ map.put(label, val);
+ }
+ double gini = 0.0;
+ for(Entry<String, Integer> ent : map.entrySet()) {
+ double rel = ent.getValue() / (double) total;
+ gini += rel * rel;
+ }
+ mv.put(gini);
+ }
+ Collection<DoubleVector> col = new java.util.Vector<DoubleVector>();
+ 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));
+ }
+ }
+}
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 dc311612..8d7aa0d8 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) 2011
+ Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/evaluation/index/package-info.java
index 242ce455..2532b148 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) 2011
+Copyright (C) 2012
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 c5762308..b92e5bde 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/outlier/JudgeOutlierScores.java
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/outlier/JudgeOutlierScores.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) 2011
+Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/evaluation/outlier/package-info.java
index 4d2d1fb9..f85a1c3a 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) 2011
+Copyright (C) 2012
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 7133ca04..f48a8e9f 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) 2011
+Copyright (C) 2012
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/paircounting/EvaluatePairCountingFMeasure.java b/src/de/lmu/ifi/dbs/elki/evaluation/paircounting/EvaluatePairCountingFMeasure.java
deleted file mode 100644
index e47dbcec..00000000
--- a/src/de/lmu/ifi/dbs/elki/evaluation/paircounting/EvaluatePairCountingFMeasure.java
+++ /dev/null
@@ -1,180 +0,0 @@
-package de.lmu.ifi.dbs.elki.evaluation.paircounting;
-
-/*
- 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 java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import de.lmu.ifi.dbs.elki.algorithm.clustering.ClusteringAlgorithm;
-import de.lmu.ifi.dbs.elki.algorithm.clustering.trivial.ByLabelClustering;
-import de.lmu.ifi.dbs.elki.data.Clustering;
-import de.lmu.ifi.dbs.elki.database.Database;
-import de.lmu.ifi.dbs.elki.evaluation.Evaluator;
-import de.lmu.ifi.dbs.elki.evaluation.outlier.JudgeOutlierScores;
-import de.lmu.ifi.dbs.elki.evaluation.paircounting.generator.PairSortedGeneratorInterface;
-import de.lmu.ifi.dbs.elki.logging.Logging;
-import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
-import de.lmu.ifi.dbs.elki.result.CollectionResult;
-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.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;
-import de.lmu.ifi.dbs.elki.utilities.pairs.Triple;
-
-/**
- * Evaluate a clustering result by comparing it to an existing cluster label.
- *
- * @author Erich Schubert
- *
- * @apiviz.landmark
- * @apiviz.has PairCountingFMeasure
- * @apiviz.has EvaluatePairCountingFMeasure.ScoreResult oneway - - «create»
- */
-public class EvaluatePairCountingFMeasure implements Evaluator {
- /**
- * Logger for debug output.
- */
- protected static final Logging logger = Logging.getLogger(JudgeOutlierScores.class);
-
- /**
- * Parameter to obtain the reference clustering. Defaults to a flat label
- * clustering.
- */
- public static final OptionID REFERENCE_ID = OptionID.getOrCreateOptionID("paircounting.reference", "Reference clustering to compare with. Defaults to a by-label clustering.");
-
- /**
- * Parameter flag for special noise handling.
- */
- public static final OptionID NOISE_ID = OptionID.getOrCreateOptionID("paircounting.noisespecial", "Use special handling for noise clusters.");
-
- /**
- * Reference algorithm.
- */
- private ClusteringAlgorithm<?> referencealg;
-
- /**
- * Apply special handling to noise "clusters".
- */
- private boolean noiseSpecialHandling;
-
- /**
- * Constructor.
- *
- * @param referencealg Reference clustering
- * @param noiseSpecialHandling Noise handling flag
- */
- public EvaluatePairCountingFMeasure(ClusteringAlgorithm<?> referencealg, boolean noiseSpecialHandling) {
- super();
- this.referencealg = referencealg;
- this.noiseSpecialHandling = noiseSpecialHandling;
- }
-
- @Override
- public void processNewResult(HierarchicalResult baseResult, Result result) {
- Database db = ResultUtil.findDatabase(baseResult);
- List<Clustering<?>> crs = ResultUtil.getClusteringResults(result);
- if(crs == null || crs.size() < 1) {
- // logger.warning("No clustering results found - nothing to evaluate!");
- return;
- }
- // Compute the reference clustering
- Result refres = referencealg.run(db);
- List<Clustering<?>> refcrs = ResultUtil.getClusteringResults(refres);
- if(refcrs.size() == 0) {
- logger.warning("Reference algorithm did not return a clustering result!");
- return;
- }
- if(refcrs.size() > 1) {
- logger.warning("Reference algorithm returned more than one result!");
- }
- Clustering<?> refc = refcrs.get(0);
- for(Clustering<?> c : crs) {
- PairSortedGeneratorInterface first = PairCountingFMeasure.getPairGenerator(c, noiseSpecialHandling, false);
- PairSortedGeneratorInterface second = PairCountingFMeasure.getPairGenerator(refc, noiseSpecialHandling, false);
- Triple<Integer, Integer, Integer> countedPairs = PairCountingFMeasure.countPairs(first, second);
- // Use double, since we want double results at the end!
- double sum = countedPairs.first + countedPairs.second + countedPairs.third;
- double inboth = countedPairs.first / sum;
- double infirst = countedPairs.second / sum;
- double insecond = countedPairs.third / sum;
- double fmeasure = PairCountingFMeasure.fMeasure(countedPairs.first, countedPairs.second, countedPairs.third, 1.0);
- ArrayList<Vector> s = new ArrayList<Vector>(4);
- s.add(new Vector(new double[] { fmeasure, inboth, infirst, insecond }));
- db.getHierarchy().add(c, new ScoreResult(s));
- }
- }
-
- /**
- * Result object for outlier score judgements.
- *
- * @author Erich Schubert
- */
- public static class ScoreResult extends CollectionResult<Vector> {
- /**
- * Constructor.
- *
- * @param col score result
- */
- public ScoreResult(Collection<Vector> col) {
- super("Pair Counting F-Measure", "pair-fmeasure", col);
- }
- }
-
- /**
- * Parameterization class.
- *
- * @author Erich Schubert
- *
- * @apiviz.exclude
- */
- public static class Parameterizer extends AbstractParameterizer {
- protected ClusteringAlgorithm< ?> referencealg = null;
-
- protected boolean noiseSpecialHandling = false;
-
- @Override
- protected void makeOptions(Parameterization config) {
- super.makeOptions(config);
- ObjectParameter<ClusteringAlgorithm<?>> referencealgP = new ObjectParameter<ClusteringAlgorithm<?>>(REFERENCE_ID, ClusteringAlgorithm.class, ByLabelClustering.class);
- if(config.grab(referencealgP)) {
- referencealg = referencealgP.instantiateClass(config);
- }
-
- Flag noiseSpecialHandlingF = new Flag(NOISE_ID);
- if(config.grab(noiseSpecialHandlingF)) {
- noiseSpecialHandling = noiseSpecialHandlingF.getValue();
- }
- }
-
- @Override
- protected EvaluatePairCountingFMeasure makeInstance() {
- return new EvaluatePairCountingFMeasure(referencealg, noiseSpecialHandling);
- }
- }
-} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/paircounting/PairCountingFMeasure.java b/src/de/lmu/ifi/dbs/elki/evaluation/paircounting/PairCountingFMeasure.java
deleted file mode 100644
index 4e1d5f01..00000000
--- a/src/de/lmu/ifi/dbs/elki/evaluation/paircounting/PairCountingFMeasure.java
+++ /dev/null
@@ -1,241 +0,0 @@
-package de.lmu.ifi.dbs.elki.evaluation.paircounting;
-
-/*
- 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 java.util.Collection;
-
-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.evaluation.paircounting.generator.PairGeneratorMerge;
-import de.lmu.ifi.dbs.elki.evaluation.paircounting.generator.PairGeneratorNoise;
-import de.lmu.ifi.dbs.elki.evaluation.paircounting.generator.PairGeneratorSingleCluster;
-import de.lmu.ifi.dbs.elki.evaluation.paircounting.generator.PairSortedGeneratorInterface;
-import de.lmu.ifi.dbs.elki.utilities.pairs.Triple;
-
-/**
- * Compare two clustering results using a pair-counting F-Measure.
- *
- * A pair are any two objects that belong to the same cluster.
- *
- * Two clusterings are compared by comparing their pairs; if two clusterings
- * completely agree, they also agree on every pair; even when the clusters and
- * points are ordered differently.
- *
- * An empty clustering will of course have no pairs, the trivial all-in-one
- * clustering of course has n^2 pairs. Therefore neither recall nor precision
- * itself are useful, however their combination -- the F-Measure -- is useful.
- *
- * @author Erich Schubert
- *
- * @apiviz.uses de.lmu.ifi.dbs.elki.evaluation.paircounting.generator.PairSortedGeneratorInterface
- * @apiviz.uses de.lmu.ifi.dbs.elki.evaluation.paircounting.generator.PairGeneratorNoise
- * @apiviz.uses de.lmu.ifi.dbs.elki.evaluation.paircounting.generator.PairGeneratorSingleCluster
- * @apiviz.uses de.lmu.ifi.dbs.elki.evaluation.paircounting.generator.PairGeneratorMerge
- */
-public class PairCountingFMeasure {
- /**
- * Get a pair generator for the given Clustering
- *
- * @param <R> Clustering result class
- * @param <M> Model type
- * @param clusters Clustering result
- * @param noiseSpecial Special handling for "noise clusters"
- * @param hierarchicalSpecial Special handling for hierarchical clusters
- * @return Sorted pair generator
- */
- public static <R extends Clustering<M>, M extends Model> PairSortedGeneratorInterface getPairGenerator(R clusters, boolean noiseSpecial, boolean hierarchicalSpecial) {
- // collect all clusters into a flat list.
- Collection<Cluster<M>> allclusters = clusters.getAllClusters();
-
- // Make generators for each cluster
- PairSortedGeneratorInterface[] gens = new PairSortedGeneratorInterface[allclusters.size()];
- int i = 0;
- for(Cluster<?> c : allclusters) {
- if(noiseSpecial && c.isNoise()) {
- gens[i] = new PairGeneratorNoise(c);
- }
- else {
- gens[i] = new PairGeneratorSingleCluster(c, hierarchicalSpecial);
- }
- i++;
- }
- return new PairGeneratorMerge(gens);
- }
-
- /**
- * Compare two clustering results.
- *
- * @param <R> Result type
- * @param <M> Model type
- * @param <S> Result type
- * @param <N> Model type
- * @param result1 first result
- * @param result2 second result
- * @param beta Beta value for the F-Measure
- * @param noiseSpecial Noise receives special treatment
- * @param hierarchicalSpecial Special handling for hierarchical clusters
- * @return Pair counting F-Measure result.
- */
- public static <R extends Clustering<M>, M extends Model, S extends Clustering<N>, N extends Model> double compareClusterings(R result1, S result2, double beta, boolean noiseSpecial, boolean hierarchicalSpecial) {
- PairSortedGeneratorInterface first = getPairGenerator(result1, noiseSpecial, hierarchicalSpecial);
- PairSortedGeneratorInterface second = getPairGenerator(result2, noiseSpecial, hierarchicalSpecial);
- Triple<Integer, Integer, Integer> countedPairs = countPairs(first, second);
- return fMeasure(countedPairs.first, countedPairs.second, countedPairs.third, beta);
- }
-
- /**
- * Compare two clustering results.
- *
- * @param <R> Result type
- * @param <M> Model type
- * @param <S> Result type
- * @param <N> Model type
- * @param result1 first result
- * @param result2 second result
- * @param beta Beta value for the F-Measure
- * @return Pair counting F-Measure result.
- */
- public static <R extends Clustering<M>, M extends Model, S extends Clustering<N>, N extends Model> double compareClusterings(R result1, S result2, double beta) {
- return compareClusterings(result1, result2, beta, false, false);
- }
-
- /**
- * Compare two clustering results.
- *
- * @param <R> Result type
- * @param <M> Model type
- * @param <S> Result type
- * @param <N> Model type
- * @param result1 first result
- * @param result2 second result
- * @param noiseSpecial Noise receives special treatment
- * @return Pair counting F-1-Measure result.
- */
- public static <R extends Clustering<M>, M extends Model, S extends Clustering<N>, N extends Model> double compareClusterings(R result1, S result2, boolean noiseSpecial, boolean hierarchicalSpecial) {
- return compareClusterings(result1, result2, 1.0, noiseSpecial, hierarchicalSpecial);
- }
-
- /**
- * Compare two clustering results.
- *
- * @param <R> Result type
- * @param <M> Model type
- * @param <S> Result type
- * @param <N> Model type
- * @param result1 first result
- * @param result2 second result
- * @return Pair counting F-1-Measure result.
- */
- public static <R extends Clustering<M>, M extends Model, S extends Clustering<N>, N extends Model> double compareClusterings(R result1, S result2) {
- return compareClusterings(result1, result2, 1.0, false, false);
- }
-
- /**
- * Compare two sets of generated pairs. It determines how many objects of the
- * first set are in both sets, just in the first set or just in the second
- * set.</p>
- *
- *
- * @param <R> Result type
- * @param <M> Model type
- * @param <S> Result type
- * @param <N> Model type
- * @param result1 first result
- * @param result2 second result
- * @return Returns a {@link Triple} that contains the number of objects that
- * are in both sets (FIRST), the number of objects that are just in
- * the first set (SECOND) and the number of object that are just in
- * the second set (THIRD).
- *
- */
- public static <R extends Clustering<M>, M extends Model, S extends Clustering<N>, N extends Model> Triple<Integer, Integer, Integer> countPairs(R result1, S result2) {
- PairSortedGeneratorInterface first = getPairGenerator(result1, false, false);
- PairSortedGeneratorInterface second = getPairGenerator(result2, false, false);
- return countPairs(first, second);
- }
-
- /**
- * Compare two sets of generated pairs. It determines how many objects of the
- * first set are in both sets, just in the first set or just in the second
- * set.</p>
- *
- * @param first first set
- * @param second second set
- * @return Returns a {@link Triple} that contains the number of objects that
- * are in both sets (FIRST), the number of objects that are just in
- * the first set (SECOND) and the number of object that are just in
- * the second set (THIRD).
- */
- public static Triple<Integer, Integer, Integer> countPairs(PairSortedGeneratorInterface first, PairSortedGeneratorInterface second) {
- int inboth = 0;
- int infirst = 0;
- int insecond = 0;
-
- while(first.current() != null && second.current() != null) {
- int cmp = first.current().compareTo(second.current());
- if(cmp == 0) {
- inboth++;
- first.next();
- second.next();
- }
- else if(cmp < 0) {
- infirst++;
- first.next();
- }
- else {
- insecond++;
- second.next();
- }
- }
- while(first.current() != null) {
- infirst++;
- first.next();
- }
- while(second.current() != null) {
- insecond++;
- second.next();
- }
- return new Triple<Integer, Integer, Integer>(inboth, infirst, insecond);
- }
-
- /**
- * Computes the F-measure of the given parameters.</p>
- * <p>
- * Returns
- * <code>((1+beta*beta) * inBoth) / ((1+beta*beta) * inBoth + (beta*beta)*inFirst + inSecond)</code>
- * </p>
- *
- * @param inBoth The number of objects that are in both sets.
- * @param inFirst The number of objects that are in the first set.
- * @param inSecond The number of objects that are in the second set.
- * @param beta The beta values for the f-measure.
- * @return The F-measure.
- */
- public static double fMeasure(int inBoth, int inFirst, int inSecond, double beta) {
- // System.out.println("Both: "+inboth+" First: "+infirst+" Second: "+insecond);
- double fmeasure = ((1 + beta * beta) * inBoth) / ((1 + beta * beta) * inBoth + (beta * beta) * inFirst + inSecond);
- return fmeasure;
- }
-}
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/paircounting/generator/PairGeneratorMerge.java b/src/de/lmu/ifi/dbs/elki/evaluation/paircounting/generator/PairGeneratorMerge.java
deleted file mode 100644
index 88297ebc..00000000
--- a/src/de/lmu/ifi/dbs/elki/evaluation/paircounting/generator/PairGeneratorMerge.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package de.lmu.ifi.dbs.elki.evaluation.paircounting.generator;
-
-/*
- 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.utilities.pairs.IntIntPair;
-
-/**
- * Merge the output of multiple generators.
- *
- * @author Erich Schubert
- */
-public class PairGeneratorMerge extends PairSortedGenerator {
- /**
- * Generators to merge
- */
- private PairSortedGeneratorInterface[] generators;
-
- /**
- * Set up merging generator.
- * param generators will not be copied!
- *
- * @param generators array of generators.
- */
- public PairGeneratorMerge(PairSortedGeneratorInterface[] generators) {
- this.generators = generators;
- setCurrent(advance());
- }
-
- /**
- * Advance iterator and return next pair.
- *
- * This will return the smallest of all the "merged" generator results.
- */
- @Override
- protected IntIntPair advance() {
- IntIntPair min = null;
- PairSortedGeneratorInterface best = null;
- for (PairSortedGeneratorInterface gen : this.generators) {
- IntIntPair n = gen.current();
- if (n != null && (min == null || n.compareTo(min) < 0)) {
- min = n;
- best = gen;
- }
- }
- // advance best generator
- if (best != null) {
- best.next();
- }
- return min;
- }
-} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/paircounting/generator/PairGeneratorNoise.java b/src/de/lmu/ifi/dbs/elki/evaluation/paircounting/generator/PairGeneratorNoise.java
deleted file mode 100644
index 7d3ad8c0..00000000
--- a/src/de/lmu/ifi/dbs/elki/evaluation/paircounting/generator/PairGeneratorNoise.java
+++ /dev/null
@@ -1,91 +0,0 @@
-package de.lmu.ifi.dbs.elki.evaluation.paircounting.generator;
-
-/*
- 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 java.util.Arrays;
-
-import de.lmu.ifi.dbs.elki.data.Cluster;
-import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
-import de.lmu.ifi.dbs.elki.utilities.pairs.IntIntPair;
-
-/**
- * Generator for noise points.
- *
- * This generator will generate pairs (a,a) for all elements a in the given
- * list.
- *
- * @author Erich Schubert
- */
-public class PairGeneratorNoise extends PairSortedGenerator {
- /**
- * Ids to use
- */
- private int[] ids;
-
- /**
- * Current position.
- */
- private int pos;
-
- /**
- * Crate new generator for a base cluster object.
- *
- * @param cluster object
- */
- public PairGeneratorNoise(Cluster<?> cluster) {
- // build int array for the cluster
- // TODO: copy less.
- DBIDs dbids = cluster.getIDs();
- ids = new int[dbids.size()];
- int j = 0;
- for (DBID id : dbids) {
- ids[j] = id.getIntegerID();
- j++;
- }
- Arrays.sort(ids);
-
- pos = 0;
- if(ids.length > 0) {
- setCurrent(new IntIntPair(ids[pos], ids[pos]));
- }
- }
-
- /**
- * Advance iterator and return new pair.
- */
- @Override
- protected IntIntPair advance() {
- if(current() == null) {
- return null;
- }
- pos++;
- if(pos >= ids.length) {
- return null;
- }
- else {
- return new IntIntPair(ids[pos], ids[pos]);
- }
- }
-} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/paircounting/generator/PairGeneratorSingleCluster.java b/src/de/lmu/ifi/dbs/elki/evaluation/paircounting/generator/PairGeneratorSingleCluster.java
deleted file mode 100644
index da769837..00000000
--- a/src/de/lmu/ifi/dbs/elki/evaluation/paircounting/generator/PairGeneratorSingleCluster.java
+++ /dev/null
@@ -1,136 +0,0 @@
-package de.lmu.ifi.dbs.elki.evaluation.paircounting.generator;
-
-/*
- 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 java.util.Arrays;
-
-import de.lmu.ifi.dbs.elki.data.Cluster;
-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.ModifiableDBIDs;
-import de.lmu.ifi.dbs.elki.utilities.pairs.IntIntPair;
-
-/**
- * Generate sorted ID pairs for a {@link Cluster}.
- *
- * @author Erich Schubert
- */
-public class PairGeneratorSingleCluster extends PairSortedGenerator {
- /**
- * Ids in parent clusters
- */
- private int[] parentids;
-
- /**
- * ids in this cluster
- */
- private int[] thisids;
-
- /**
- * Position in first set
- */
- private int pos1;
-
- /**
- * Position in second set
- */
- private int pos2;
-
- /**
- * Generate pairs for a hierarchical cluster.
- *
- * @param cluster Cluster
- * @param useHierarchical Use hierarchical mode
- */
- public PairGeneratorSingleCluster(Cluster<?> cluster, boolean useHierarchical) {
- // collect all parent clusters into a flat list.
- java.util.Vector<Cluster<?>> allparents = new java.util.Vector<Cluster<?>>();
- if(useHierarchical && cluster.isHierarchical()) {
- allparents.addAll(cluster.getParents());
- for(int i = 0; i < allparents.size(); i++) {
- for(Cluster<?> newc : allparents.get(i).getParents()) {
- if(!allparents.contains(newc)) {
- allparents.add(newc);
- }
- }
- }
- }
-
- // build int array for the cluster
- DBIDs cids = cluster.getIDs();
- thisids = new int[cids.size()];
- {
- int j = 0;
- for(DBID id : cids) {
- thisids[j] = id.getIntegerID();
- j++;
- }
- Arrays.sort(thisids);
- }
- // TODO: ensure there are no duplicate IDs?
-
- ModifiableDBIDs idsset = DBIDUtil.newHashSet(cids);
- for(Cluster<?> parent : allparents) {
- idsset.addAll(parent.getIDs().asCollection());
- }
- parentids = new int[idsset.size()];
- {
- int j = 0;
- for(DBID in : idsset) {
- parentids[j] = in.getIntegerID();
- j++;
- }
- Arrays.sort(parentids);
- }
-
- // initialize iterator.
- pos1 = 0;
- pos2 = 0;
- if(thisids.length > 0) {
- setCurrent(new IntIntPair(parentids[pos1], thisids[pos2]));
- }
- }
-
- /**
- * Advance iterator
- */
- @Override
- protected IntIntPair advance() {
- if(current() == null) {
- return null;
- }
- pos2++;
- if(pos2 >= thisids.length) {
- pos2 = 0;
- pos1++;
- }
- if(pos1 >= parentids.length) {
- return null;
- }
- else {
- return new IntIntPair(parentids[pos1], thisids[pos2]);
- }
- }
-} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/paircounting/generator/PairSortedGenerator.java b/src/de/lmu/ifi/dbs/elki/evaluation/paircounting/generator/PairSortedGenerator.java
deleted file mode 100644
index 6c342bc9..00000000
--- a/src/de/lmu/ifi/dbs/elki/evaluation/paircounting/generator/PairSortedGenerator.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package de.lmu.ifi.dbs.elki.evaluation.paircounting.generator;
-
-/*
- 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.utilities.pairs.IntIntPair;
-
-/**
- * Implement the common functionality of caching the current result in a base class.
- *
- * @author Erich Schubert
- *
- */
-public abstract class PairSortedGenerator implements PairSortedGeneratorInterface {
- /**
- * Current pair
- */
- private IntIntPair cur = null;
-
- /**
- * Set the current pair.
- *
- * @param cur new current pair.
- */
- protected final void setCurrent(IntIntPair cur) {
- this.cur = cur;
- }
-
- /**
- * Return current pair.
- *
- * Marked as final to avoid bad implementations.
- * If you intend to override this, just implement the interface!
- */
- @Override
- public final IntIntPair current() {
- return cur;
- }
-
- /**
- * Return next pair.
- *
- * Marked as final to avoid bad implementations.
- * If you intend to override this, just implement the interface!
- */
- @Override
- public final IntIntPair next() {
- setCurrent(advance());
- return current();
- }
-
- /**
- * Main advance method.
- */
- protected abstract IntIntPair advance();
-} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/paircounting/package-info.java b/src/de/lmu/ifi/dbs/elki/evaluation/paircounting/package-info.java
deleted file mode 100644
index 0c1a11cc..00000000
--- a/src/de/lmu/ifi/dbs/elki/evaluation/paircounting/package-info.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- * <p>Evaluation of clustering results via pair counting.</p>
- * */
-/*
-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/>.
-*/
-package de.lmu.ifi.dbs.elki.evaluation.paircounting; \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/roc/ComputeROCCurve.java b/src/de/lmu/ifi/dbs/elki/evaluation/roc/ComputeROCCurve.java
index 08dd38a5..232089ed 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/roc/ComputeROCCurve.java
+++ b/src/de/lmu/ifi/dbs/elki/evaluation/roc/ComputeROCCurve.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -38,7 +38,6 @@ import de.lmu.ifi.dbs.elki.evaluation.Evaluator;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.result.CollectionResult;
import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
-import de.lmu.ifi.dbs.elki.result.IterableResult;
import de.lmu.ifi.dbs.elki.result.OrderingResult;
import de.lmu.ifi.dbs.elki.result.Result;
import de.lmu.ifi.dbs.elki.result.ResultUtil;
@@ -144,22 +143,6 @@ public class ComputeROCCurve implements Evaluator {
return rocresult;
}
- /**
- * Wrap the uncheckable cast with the manual check.
- *
- * @param ir Interable result
- * @return Iterator if Integer iterable, null otherwise.
- */
- @SuppressWarnings("unchecked")
- private Iterator<DBID> getDBIDIterator(IterableResult<?> ir) {
- Iterator<?> testit = ir.iterator();
- if(testit.hasNext() && (testit.next() instanceof DBID)) {
- // note: we DO want a fresh iterator here!
- return (Iterator<DBID>) ir.iterator();
- }
- return null;
- }
-
@Override
public void processNewResult(HierarchicalResult baseResult, Result result) {
Database db = ResultUtil.findDatabase(baseResult);
@@ -173,7 +156,6 @@ public class ComputeROCCurve implements Evaluator {
boolean nonefound = true;
List<OutlierResult> oresults = ResultUtil.getOutlierResults(result);
- List<IterableResult<?>> iterables = ResultUtil.getIterableResults(result);
List<OrderingResult> orderings = ResultUtil.getOrderingResults(result);
// Outlier results are the main use case.
for(OutlierResult o : oresults) {
@@ -183,15 +165,6 @@ public class ComputeROCCurve implements Evaluator {
nonefound = false;
}
- // try iterable results first
- // FIXME: find the appropriate place to call addDerivedResult
- for(IterableResult<?> ir : iterables) {
- Iterator<DBID> iter = getDBIDIterator(ir);
- if(iter != null) {
- db.getHierarchy().add(ir, computeROCResult(db.size(), positiveids, iter));
- nonefound = false;
- }
- }
// FIXME: find appropriate place to add the derived result
// otherwise apply an ordering to the database IDs.
for(OrderingResult or : orderings) {
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 1b37bfff..f7fdd254 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) 2011
+ Copyright (C) 2012
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.database.ids.DBID;
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.DBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.SetDBIDs;
import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
@@ -150,6 +151,87 @@ 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.
+ *
+ * @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
+ */
+ public static <C extends Comparable<? super C>> List<DoubleDoublePair> materializeROC(int size, SetDBIDs ids, Iterator<? extends PairInterface<C, DBID>> nei) {
+ int postot = ids.size();
+ int negtot = size - postot;
+ int poscnt = 0;
+ int negcnt = 0;
+ ArrayList<DoubleDoublePair> res = new ArrayList<DoubleDoublePair>(postot + 2);
+
+ // start in bottom left
+ res.add(new DoubleDoublePair(0.0, 0.0));
+
+ PairInterface<C, DBID> prev = null;
+ while(nei.hasNext()) {
+ // Previous positive rate - y axis
+ double curpos = ((double) poscnt) / postot;
+ // Previous negative rate - x axis
+ double curneg = ((double) negcnt) / negtot;
+
+ // Analyze next point
+ PairInterface<C, DBID> cur = nei.next();
+ // positive or negative match?
+ if(ids.contains(cur.getSecond())) {
+ poscnt += 1;
+ }
+ else {
+ negcnt += 1;
+ }
+ // defer calculation for ties
+ if((prev != null) && (prev.getFirst().compareTo(cur.getFirst()) == 0)) {
+ continue;
+ }
+ // simplify curve when possible:
+ if(res.size() >= 2) {
+ DoubleDoublePair last1 = res.get(res.size() - 2);
+ DoubleDoublePair last2 = res.get(res.size() - 1);
+ final double ldx = last2.first - last1.first;
+ final double cdx = curneg - last2.first;
+ final double ldy = last2.second - last1.second;
+ final double cdy = curpos - last2.second;
+ // vertical simplification
+ if((ldx == 0) && (cdx == 0)) {
+ res.remove(res.size() - 1);
+ }
+ // horizontal simplification
+ else if((ldy == 0) && (cdy == 0)) {
+ res.remove(res.size() - 1);
+ }
+ // diagonal simplification
+ else if(ldy > 0 && cdy > 0) {
+ if(Math.abs((ldx / ldy) - (cdx / cdy)) < 1E-10) {
+ res.remove(res.size() - 1);
+ }
+ }
+ }
+ // Add a new point (for the previous entry!)
+ res.add(new DoubleDoublePair(curneg, curpos));
+ prev = cur;
+ }
+ // ensure we end up in the top right corner.
+ // Since we didn't add a point for the last entry yet, this likely is
+ // needed.
+ {
+ DoubleDoublePair last = res.get(res.size() - 1);
+ if(last.first < 1.0 || last.second < 1.0) {
+ res.add(new DoubleDoublePair(1.0, 1.0));
+ }
+ }
+ return res;
+ }
+
+ /**
* This adapter can be used for an arbitrary collection of Integers, and uses
* that id1.compareTo(id2) != 0 for id1 != id2 to satisfy the comparability.
*
@@ -207,14 +289,14 @@ public class ROC {
/**
* Original Iterator
*/
- private Iterator<DistanceResultPair<D>> iter;
+ private Iterator<? extends DistanceResultPair<D>> iter;
/**
* Constructor
*
* @param iter Iterator for distance results
*/
- public DistanceResultAdapter(Iterator<DistanceResultPair<D>> iter) {
+ public DistanceResultAdapter(Iterator<? extends DistanceResultPair<D>> iter) {
super();
this.iter = iter;
}
@@ -326,7 +408,7 @@ public class ROC {
* @param nei Query result
* @return area under curve
*/
- public static <D extends Distance<D>> double computeROCAUCDistanceResult(int size, Cluster<?> clus, List<DistanceResultPair<D>> nei) {
+ public static <D extends Distance<D>> double computeROCAUCDistanceResult(int size, Cluster<?> clus, Iterable<? extends DistanceResultPair<D>> nei) {
// TODO: ensure the collection has efficient "contains".
return ROC.computeROCAUCDistanceResult(size, clus.getIDs(), nei);
}
@@ -340,7 +422,7 @@ public class ROC {
* @param nei Query Result
* @return area under curve
*/
- public static <D extends Distance<D>> double computeROCAUCDistanceResult(int size, DBIDs ids, List<DistanceResultPair<D>> nei) {
+ public static <D extends Distance<D>> double computeROCAUCDistanceResult(int size, DBIDs ids, Iterable<? extends DistanceResultPair<D>> nei) {
// TODO: do not materialize the ROC, but introduce an iterator interface
List<DoubleDoublePair> roc = materializeROC(size, DBIDUtil.ensureSet(ids), new DistanceResultAdapter<D>(nei.iterator()));
return computeAUC(roc);
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 4dc52d2a..5ee2de70 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) 2011
+Copyright (C) 2012
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 9408be91..5344da15 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) 2011
+ Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/evaluation/similaritymatrix/package-info.java
index ae156539..619c3f83 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) 2011
+Copyright (C) 2012
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 316ecc26..2ce3bb08 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) 2011
+ Copyright (C) 2012
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 dc5166c5..1d90f869 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) 2011
+ Copyright (C) 2012
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 7be929b2..65c93fb5 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) 2011
+ Copyright (C) 2012
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/ClassParameterConfigurator.java b/src/de/lmu/ifi/dbs/elki/gui/configurator/ClassParameterConfigurator.java
index 34580f16..272513bd 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) 2011
+ Copyright (C) 2012
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/ConfiguratorPanel.java b/src/de/lmu/ifi/dbs/elki/gui/configurator/ConfiguratorPanel.java
index 5be0da35..d286be48 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) 2011
+ Copyright (C) 2012
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/EnumParameterConfigurator.java b/src/de/lmu/ifi/dbs/elki/gui/configurator/EnumParameterConfigurator.java
index ad12b7ce..62184bf4 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) 2011
+ Copyright (C) 2012
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/FileParameterConfigurator.java b/src/de/lmu/ifi/dbs/elki/gui/configurator/FileParameterConfigurator.java
index fd7168d3..bd34a995 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) 2011
+ Copyright (C) 2012
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 15a4506f..5c905e47 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) 2011
+ Copyright (C) 2012
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 174240b0..90c8f62f 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) 2011
+ Copyright (C) 2012
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 3bf3dbb2..68b977ff 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) 2011
+ Copyright (C) 2012
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 4c42582b..004ad3da 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) 2011
+Copyright (C) 2012
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 a21122aa..fc346331 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) 2011
+ Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/gui/icons/package-info.java
index 50f3e3f8..986b2de1 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) 2011
+Copyright (C) 2012
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 5e5c8caa..ed59e8a4 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -69,7 +69,7 @@ import de.lmu.ifi.dbs.elki.workflow.OutputStep;
* Minimal GUI built around a table-based parameter editor.
*
* @author Erich Schubert
- *
+ *
* @apiviz.composedOf SettingsComboboxModel
* @apiviz.composedOf LoggingStep
* @apiviz.owns de.lmu.ifi.dbs.elki.gui.util.ParameterTable
@@ -376,8 +376,9 @@ public class MiniGUI extends JPanel {
else {
reportErrors(config);
}
+ logger.debug("Task completed successfully.");
}
- catch(Exception e) {
+ catch(Throwable e) {
logger.exception(e);
}
return null;
@@ -435,7 +436,7 @@ public class MiniGUI extends JPanel {
// Create and set up the content pane.
MiniGUI newContentPane = new MiniGUI();
- if (args != null && args.length > 0) {
+ if(args != null && args.length > 0) {
newContentPane.doSetParameters(Arrays.asList(args));
}
newContentPane.setOpaque(true); // content panes must be opaque
@@ -508,7 +509,7 @@ public class MiniGUI extends JPanel {
@Override
public Object getElementAt(int index) {
- return store.getElementAt(index).first;
+ return store.getElementAt(store.size() - 1 - index).first;
}
@Override
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 67998ff4..944b4a8e 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) 2011
+Copyright (C) 2012
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 49745002..886612b7 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) 2011
+ Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/gui/multistep/package-info.java
index 0b2c1f6a..35a08689 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) 2011
+Copyright (C) 2012
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 4f294468..c3a6f1d8 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) 2011
+ Copyright (C) 2012
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/EvaluationTabPanel.java b/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/EvaluationTabPanel.java
index 4f6d0879..c6d73133 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) 2011
+ Copyright (C) 2012
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/InputTabPanel.java b/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/InputTabPanel.java
index 833d5ba8..fb6d9cae 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) 2011
+ Copyright (C) 2012
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 143887fc..617008fc 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) 2011
+ Copyright (C) 2012
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/OutputTabPanel.java b/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/OutputTabPanel.java
index acbde125..4cc84c8a 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) 2011
+ Copyright (C) 2012
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/ParameterTabPanel.java b/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/ParameterTabPanel.java
index 1bfe0000..fd005de0 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -40,7 +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.Observable;
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;
@@ -56,7 +55,7 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
*
* @author Erich Schubert
*/
-public abstract class ParameterTabPanel extends JPanel implements Observable<ParameterTabPanel>, ChangeListener {
+public abstract class ParameterTabPanel extends JPanel implements ChangeListener {
/**
* Serial version
*/
@@ -323,12 +322,10 @@ public abstract class ParameterTabPanel extends JPanel implements Observable<Par
runButton.setEnabled(canRun());
}
- @Override
public void addObserver(Observer<? super ParameterTabPanel> o) {
observers.add(o);
}
- @Override
public void removeObserver(Observer<? super ParameterTabPanel> o) {
observers.remove(o);
}
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 ab7fc852..8777a95c 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
@@ -3,7 +3,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) 2011
+ Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/gui/multistep/panels/package-info.java
index 2ea42e88..b9d4d90a 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) 2011
+Copyright (C) 2012
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 30cd9ac5..34a29371 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) 2011
+Copyright (C) 2012
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 c2860d6a..e59965b1 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) 2011
+ Copyright (C) 2012
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/LogPane.java b/src/de/lmu/ifi/dbs/elki/gui/util/LogPane.java
index 50d4e784..e1c9bc53 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) 2011
+ Copyright (C) 2012
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 99c28dee..cb410ee9 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) 2011
+ Copyright (C) 2012
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/ParameterTable.java b/src/de/lmu/ifi/dbs/elki/gui/util/ParameterTable.java
index fc7deac8..dd674041 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) 2011
+ Copyright (C) 2012
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/ParametersModel.java b/src/de/lmu/ifi/dbs/elki/gui/util/ParametersModel.java
index 454ed486..e9fba0fd 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) 2011
+ Copyright (C) 2012
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 9e74b695..daa2bab0 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) 2011
+ Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/gui/util/package-info.java
index 46817140..de9f582a 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) 2011
+Copyright (C) 2012
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 061d7893..30966fd1 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) 2011
+ Copyright (C) 2012
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/AbstractRefiningIndex.java b/src/de/lmu/ifi/dbs/elki/index/AbstractRefiningIndex.java
new file mode 100644
index 00000000..30abb4a4
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/AbstractRefiningIndex.java
@@ -0,0 +1,192 @@
+package de.lmu.ifi.dbs.elki.index;
+
+import java.util.List;
+import java.util.Map;
+
+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.DBIDs;
+import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
+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.knn.KNNResult;
+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.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.persistent.PageFileStatistics;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.KNNHeap;
+
+/**
+ * Abstract base class for Filter-refinement indexes.
+ *
+ * The number of refinements will be counted as individual page accesses.
+ *
+ * @author Erich Schubert
+ *
+ * @param <O> Object type
+ */
+public abstract class AbstractRefiningIndex<O> extends AbstractIndex<O> implements PageFileStatistics {
+ /**
+ * Refinement counter.
+ */
+ private int refinements;
+
+ /**
+ * Constructor.
+ *
+ * @param relation Relation indexed
+ */
+ public AbstractRefiningIndex(Relation<O> relation) {
+ super(relation);
+ }
+
+ /**
+ * Initialize the index.
+ *
+ * @param relation Relation to index
+ * @param ids database ids
+ */
+ abstract protected void initialize(Relation<O> relation, DBIDs ids);
+
+ /**
+ * Refine a given object (and count the refinement!)
+ *
+ * @param id Object id
+ * @return refined object
+ */
+ 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;
+ }
+
+ @Override
+ public PageFileStatistics getInnerStatistics() {
+ return null;
+ }
+
+ @Override
+ public void insertAll(DBIDs ids) {
+ initialize(relation, ids);
+ }
+
+ /**
+ * Range query for this index.
+ *
+ * @author Erich Schubert
+ */
+ 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 List<DistanceResultPair<D>> getRangeForDBID(DBID id, D range) {
+ return getRangeForObject(relation.get(id), range);
+ }
+
+ /**
+ * Refinement distance computation.
+ *
+ * @param id Candidate ID
+ * @param q Query object
+ * @return Distance
+ */
+ protected D refine(DBID id, O q) {
+ AbstractRefiningIndex.this.refinements++;
+ return distanceQuery.distance(q, id);
+ }
+
+ /**
+ * Count extra refinements.
+ *
+ * @param c Refinements
+ */
+ protected void incRefinements(int c) {
+ AbstractRefiningIndex.this.refinements += c;
+ }
+ }
+
+ /**
+ * KNN query for this index.
+ *
+ * @author Erich Schubert
+ */
+ abstract public class AbstractKNNQuery<D extends Distance<D>> extends AbstractDistanceKNNQuery<O, D> implements KNNQuery<O, D> {
+ /**
+ * Constructor.
+ *
+ * @param distanceQuery Distance query object
+ */
+ public AbstractKNNQuery(DistanceQuery<O, D> distanceQuery) {
+ super(distanceQuery);
+ }
+
+ @Override
+ public List<KNNResult<D>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ @Override
+ public void getKNNForBulkHeaps(Map<DBID, KNNHeap<D>> heaps) {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ @Override
+ public KNNResult<D> getKNNForDBID(DBID id, int k) {
+ return getKNNForObject(relation.get(id), k);
+ }
+
+ /**
+ * Refinement distance computation.
+ *
+ * @param id Candidate ID
+ * @param q Query object
+ * @return Distance
+ */
+ protected D refine(DBID id, O q) {
+ AbstractRefiningIndex.this.refinements++;
+ return distanceQuery.distance(q, id);
+ }
+
+ /**
+ * Count extra refinements.
+ *
+ * @param c Refinements
+ */
+ protected void incRefinements(int c) {
+ AbstractRefiningIndex.this.refinements += c;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/index/Index.java b/src/de/lmu/ifi/dbs/elki/index/Index.java
index 2021fbbb..9e77073c 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) 2011
+ Copyright (C) 2012
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/IndexFactory.java b/src/de/lmu/ifi/dbs/elki/index/IndexFactory.java
index b1eb649b..ac34c53f 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) 2011
+ Copyright (C) 2012
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/KNNIndex.java b/src/de/lmu/ifi/dbs/elki/index/KNNIndex.java
index 7fcb7376..83a37f88 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) 2011
+ Copyright (C) 2012
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/RKNNIndex.java b/src/de/lmu/ifi/dbs/elki/index/RKNNIndex.java
index f29fbe89..6c990cd8 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) 2011
+ Copyright (C) 2012
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/RangeIndex.java b/src/de/lmu/ifi/dbs/elki/index/RangeIndex.java
index 1bcfad12..5d64a8fa 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) 2011
+ Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/index/package-info.java
index 3f9c7cce..ca7dbe28 100644
--- a/src/de/lmu/ifi/dbs/elki/index/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/index/package-info.java
@@ -2,25 +2,25 @@
* <p>Index structure implementations</p>
*/
/*
-This file is part of ELKI:
-Environment for Developing KDD-Applications Supported by Index-Structures
+ 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
+ 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 free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
+ You 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; \ No newline at end of file
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 4b6fbe3a..0160480f 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -43,7 +43,7 @@ public abstract class AbstractPreprocessorIndex<O, R> extends AbstractIndex<O> {
/**
* The data store
*/
- protected WritableDataStore<R> storage;
+ protected WritableDataStore<R> storage = null;
/**
* Constructor.
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 8b4272d5..cef2fbdc 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) 2011
+ Copyright (C) 2012
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 0579262b..b9b72d87 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,14 +23,15 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.knn;
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.data.type.TypeInformation;
-import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
+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.DBIDs;
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.KNNResult;
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;
@@ -54,7 +55,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
* @param <O> Object type
* @param <D> Distance type
*/
-public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D>> extends AbstractPreprocessorIndex<O, List<DistanceResultPair<D>>> implements KNNIndex<O> {
+public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D>, T extends KNNResult<D>> extends AbstractPreprocessorIndex<O, T> implements KNNIndex<O> {
/**
* The query k value.
*/
@@ -71,11 +72,6 @@ public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D
protected final DistanceQuery<O, D> distanceQuery;
/**
- * Holds the listener.
- */
- protected final EventListenerList listenerList = new EventListenerList();
-
- /**
* Constructor.
*
* @param relation Relation
@@ -121,6 +117,42 @@ public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D
*/
protected abstract void preprocess();
+ /**
+ * Get the k nearest neighbors.
+ *
+ * @param objid Object ID
+ * @return Neighbors
+ */
+ public KNNResult<D> get(DBID objid) {
+ if(storage == null) {
+ if(getLogger().isDebugging()) {
+ getLogger().debug("Running kNN preprocessor: " + this.getClass());
+ }
+ preprocess();
+ }
+ return storage.get(objid);
+ }
+
+ /**
+ * Create the default storage.
+ */
+ void createStorage() {
+ WritableDataStore<T> s = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT, KNNResult.class);
+ storage = s;
+ }
+
+ @Override
+ public void insertAll(DBIDs ids) {
+ if(storage == null) {
+ if(ids.size() > 0) {
+ preprocess();
+ }
+ }
+ else {
+ throw new UnsupportedOperationException("Preprocessor already ran.");
+ }
+ }
+
@SuppressWarnings("unchecked")
@Override
public <S extends Distance<S>> KNNQuery<O, S> getKNNQuery(DistanceQuery<O, S> distanceQuery, Object... hints) {
@@ -136,7 +168,9 @@ public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D
break;
}
}
- return new PreprocessorKNNQuery<O, S>(relation, (MaterializeKNNPreprocessor<O, S>) this);
+ // To make compilers happy:
+ AbstractMaterializeKNNPreprocessor<?, ?, ?> tmp = this;
+ return new PreprocessorKNNQuery<O, S, KNNResult<S>>(relation, (AbstractMaterializeKNNPreprocessor<O, S, KNNResult<S>>) tmp);
}
/**
@@ -151,7 +185,7 @@ public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D
* @param <O> The object type
* @param <D> The distance type
*/
- public static abstract class Factory<O, D extends Distance<D>> implements IndexFactory<O, KNNIndex<O>> {
+ public static abstract class Factory<O, D extends Distance<D>, T extends KNNResult<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.
@@ -197,7 +231,7 @@ public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D
}
@Override
- abstract public AbstractMaterializeKNNPreprocessor<O, D> instantiate(Relation<O> relation);
+ abstract public AbstractMaterializeKNNPreprocessor<O, D, T> instantiate(Relation<O> relation);
/**
* Get the distance function.
@@ -217,7 +251,7 @@ public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D
public D getDistanceFactory() {
return distanceFunction.getDistanceFactory();
}
-
+
@Override
public TypeInformation getInputTypeRestriction() {
return distanceFunction.getInputTypeRestriction();
@@ -258,7 +292,7 @@ public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D
}
@Override
- abstract protected Factory<O, D> makeInstance();
+ abstract protected Factory<O, D, ?> makeInstance();
}
}
} \ No newline at end of file
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 ef26d62b..6c677fda 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) 2011
+Copyright (C) 2012
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
new file mode 100644
index 00000000..b7c3f0ac
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/KNNJoinMaterializeKNNPreprocessor.java
@@ -0,0 +1,128 @@
+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.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.tree.spatial.SpatialEntry;
+import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rstar.RStarTreeNode;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.KNNList;
+
+/*
+ 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 materialize the kNN using a spatial join on an R-tree.
+ *
+ * @author Erich Schubert
+ *
+ * @param <V> vector type
+ * @param <D> distance type
+ */
+public class KNNJoinMaterializeKNNPreprocessor<V extends NumberVector<V, ?>, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor<V, D, KNNList<D>> {
+ /**
+ * Logging class.
+ */
+ private static final Logging logger = Logging.getLogger(KNNJoinMaterializeKNNPreprocessor.class);
+
+ /**
+ * Constructor.
+ *
+ * @param relation Relation to index
+ * @param distanceFunction Distance function
+ * @param k k
+ */
+ public KNNJoinMaterializeKNNPreprocessor(Relation<V> relation, DistanceFunction<? super V, D> distanceFunction, int k) {
+ super(relation, distanceFunction, k);
+ }
+
+ @Override
+ protected void preprocess() {
+ // Run KNNJoin
+ KNNJoin<V, D, ?, ?> knnjoin = new KNNJoin<V, D, RStarTreeNode, SpatialEntry>(distanceFunction, k);
+ storage = knnjoin.run(relation.getDatabase(), relation);
+ }
+
+ @Override
+ protected Logging getLogger() {
+ return logger;
+ }
+
+ @Override
+ public String getLongName() {
+ return "knn-join materialized neighbors";
+ }
+
+ @Override
+ public String getShortName() {
+ return "knn-join";
+ }
+
+ /**
+ * The parameterizable factory.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.landmark
+ * @apiviz.stereotype factory
+ * @apiviz.uses AbstractMaterializeKNNPreprocessor oneway - - «create»
+ *
+ * @param <O> The object type
+ * @param <D> The distance type
+ */
+ public static class Factory<O extends NumberVector<O, ?>, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor.Factory<O, D, KNNList<D>> {
+ /**
+ * Constructor.
+ *
+ * @param k K
+ * @param distanceFunction distance function
+ */
+ public Factory(int k, DistanceFunction<? super O, D> distanceFunction) {
+ super(k, distanceFunction);
+ }
+
+ @Override
+ public KNNJoinMaterializeKNNPreprocessor<O, D> instantiate(Relation<O> relation) {
+ return new KNNJoinMaterializeKNNPreprocessor<O, D>(relation, distanceFunction, k);
+ }
+
+ /**
+ * Parameterization class
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ *
+ * @param <O> Object type
+ * @param <D> Distance type
+ */
+ public static class Parameterizer<O extends NumberVector<O, ?>, 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);
+ }
+ }
+ }
+} \ No newline at end of file
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 c4456f83..4a726ad0 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) 2011
+ Copyright (C) 2012
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 9abd4a74..1436efe2 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -34,13 +34,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.WritableDataStore;
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.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
-import de.lmu.ifi.dbs.elki.database.ids.TreeSetDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.SetDBIDs;
import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
import de.lmu.ifi.dbs.elki.database.query.GenericDistanceResultPair;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
+import de.lmu.ifi.dbs.elki.database.query.knn.KNNResult;
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;
@@ -51,6 +53,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.StepProgress;
import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.KNNHeap;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.KNNList;
import de.lmu.ifi.dbs.elki.utilities.documentation.Description;
import de.lmu.ifi.dbs.elki.utilities.documentation.Title;
@@ -88,7 +91,7 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends
@Override
protected void preprocess() {
- storage = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT, List.class);
+ createStorage();
materialized_RkNN = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT, Set.class);
FiniteProgress progress = getLogger().isVerbose() ? new FiniteProgress("Materializing k nearest neighbors and reverse k nearest neighbors (k=" + k + ")", relation.size(), getLogger()) : null;
materializeKNNAndRKNNs(DBIDUtil.ensureArray(relation.getDBIDs()), progress);
@@ -100,7 +103,6 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends
* @param ids the IDs of the objects
*/
private void materializeKNNAndRKNNs(ArrayDBIDs ids, FiniteProgress progress) {
-
// add an empty list to each rknn
for(DBID id : ids) {
if(materialized_RkNN.get(id) == null) {
@@ -109,10 +111,10 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends
}
// knn query
- List<List<DistanceResultPair<D>>> kNNList = knnQuery.getKNNForBulkDBIDs(ids, k);
+ List<KNNResult<D>> kNNList = knnQuery.getKNNForBulkDBIDs(ids, k);
for(int i = 0; i < ids.size(); i++) {
DBID id = ids.get(i);
- List<DistanceResultPair<D>> kNNs = kNNList.get(i);
+ KNNResult<D> kNNs = kNNList.get(i);
storage.put(id, kNNs);
for(DistanceResultPair<D> kNN : kNNs) {
Set<DistanceResultPair<D>> rknns = materialized_RkNN.get(kNN.getDBID());
@@ -165,13 +167,12 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends
* updated
*/
private ArrayDBIDs updateKNNsAndRkNNs(DBIDs ids) {
- ArrayDBIDs rkNN_ids = DBIDUtil.newArray();
+ ArrayModifiableDBIDs rkNN_ids = DBIDUtil.newArray();
DBIDs oldids = DBIDUtil.difference(relation.getDBIDs(), ids);
for(DBID id1 : oldids) {
- List<DistanceResultPair<D>> kNNs = storage.get(id1);
- D knnDist = kNNs.get(kNNs.size() - 1).getDistance();
+ KNNResult<D> kNNs = storage.get(id1);
+ D knnDist = kNNs.getKNNDistance();
// look for new kNNs
- List<DistanceResultPair<D>> newKNNs = new ArrayList<DistanceResultPair<D>>();
KNNHeap<D> heap = null;
for(DBID id2 : ids) {
D dist = distanceQuery.distance(id1, id2);
@@ -184,7 +185,7 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends
}
}
if(heap != null) {
- newKNNs = heap.toSortedArrayList();
+ KNNList<D> newKNNs = heap.toKNNList();
storage.put(id1, newKNNs);
// get the difference
@@ -234,7 +235,7 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends
if(stepprog != null) {
stepprog.beginStep(1, "New deletions ocurred, remove their materialized kNNs and RkNNs.", getLogger());
}
- List<List<DistanceResultPair<D>>> kNNs = new ArrayList<List<DistanceResultPair<D>>>(ids.size());
+ List<KNNResult<D>> kNNs = new ArrayList<KNNResult<D>>(ids.size());
List<List<DistanceResultPair<D>>> rkNNs = new ArrayList<List<DistanceResultPair<D>>>(ids.size());
for(DBID id : aids) {
kNNs.add(storage.get(id));
@@ -250,7 +251,7 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends
stepprog.beginStep(2, "New deletions ocurred, update the affected kNNs and RkNNs.", getLogger());
}
// update the kNNs of the RkNNs
- List<List<DistanceResultPair<D>>> kNNList = knnQuery.getKNNForBulkDBIDs(rkNN_ids, k);
+ List<KNNResult<D>> kNNList = knnQuery.getKNNForBulkDBIDs(rkNN_ids, k);
for(int i = 0; i < rkNN_ids.size(); i++) {
DBID id = rkNN_ids.get(i);
storage.put(id, kNNList.get(i));
@@ -260,7 +261,7 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends
}
}
// update the RkNNs of the kNNs
- TreeSetDBIDs idsSet = DBIDUtil.newTreeSet(ids);
+ SetDBIDs idsSet = DBIDUtil.ensureSet(ids);
for(int i = 0; i < kNN_ids.size(); i++) {
DBID id = kNN_ids.get(i);
SortedSet<DistanceResultPair<D>> rkNN = materialized_RkNN.get(id);
@@ -289,7 +290,7 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends
* @param id the query id
* @return the kNNs
*/
- public List<DistanceResultPair<D>> getKNN(DBID id) {
+ public KNNResult<D> getKNN(DBID id) {
return storage.get(id);
}
@@ -333,7 +334,7 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends
public String getShortName() {
return "knn and rknn preprocessor";
}
-
+
@Override
protected Logging getLogger() {
return logger;
@@ -373,8 +374,8 @@ 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);
+ protected Factory<O, D> makeInstance() {
+ return new Factory<O, D>(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 9d55e916..fcd6fad1 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,19 +23,22 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.knn;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
-import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory;
-import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
+import javax.swing.event.EventListenerList;
+
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.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
-import de.lmu.ifi.dbs.elki.database.ids.TreeSetModifiableDBIDs;
+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.query.DatabaseQuery;
import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
+import de.lmu.ifi.dbs.elki.database.query.knn.KNNResult;
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;
@@ -64,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> {
+public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor<O, D, KNNResult<D>> {
/**
* Logger to use.
*/
@@ -83,30 +86,20 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra
protected final KNNQuery<O, D> knnQuery;
/**
- * Constructor with preprocessing step.
- *
- * @param relation Relation to preprocess
- * @param distanceFunction the distance function to use
- * @param k query k
+ * Holds the listener.
*/
- public MaterializeKNNPreprocessor(Relation<O> relation, DistanceFunction<? super O, D> distanceFunction, int k) {
- this(relation, distanceFunction, k, true);
- }
+ protected final EventListenerList listenerList = new EventListenerList();
/**
- * Constructor.
+ * Constructor with preprocessing step.
*
* @param relation Relation to preprocess
* @param distanceFunction the distance function to use
* @param k query k
*/
- protected MaterializeKNNPreprocessor(Relation<O> relation, DistanceFunction<? super O, D> distanceFunction, int k, boolean preprocess) {
+ public MaterializeKNNPreprocessor(Relation<O> relation, DistanceFunction<? super O, D> distanceFunction, int k) {
super(relation, distanceFunction, k);
this.knnQuery = relation.getDatabase().getKNNQuery(distanceQuery, k, DatabaseQuery.HINT_BULK, DatabaseQuery.HINT_HEAVY_USE, DatabaseQuery.HINT_NO_CACHE);
-
- if(preprocess) {
- preprocess();
- }
}
/**
@@ -114,13 +107,13 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra
*/
@Override
protected void preprocess() {
- storage = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, List.class);
+ createStorage();
ArrayDBIDs ids = DBIDUtil.ensureArray(relation.getDBIDs());
FiniteProgress progress = getLogger().isVerbose() ? new FiniteProgress("Materializing k nearest neighbors (k=" + k + ")", ids.size(), getLogger()) : null;
// Try bulk
- List<List<DistanceResultPair<D>>> kNNList = null;
+ List<KNNResult<D>> kNNList = null;
if(usebulk) {
kNNList = knnQuery.getKNNForBulkDBIDs(ids, k);
if(kNNList != null) {
@@ -135,7 +128,7 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra
}
else {
for(DBID id : ids) {
- List<DistanceResultPair<D>> knn = knnQuery.getKNNForDBID(id, k);
+ KNNResult<D> knn = knnQuery.getKNNForDBID(id, k);
storage.put(id, knn);
if(progress != null) {
progress.incrementProcessed(getLogger());
@@ -148,16 +141,6 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra
}
}
- /**
- * Get the k nearest neighbors.
- *
- * @param objid Object ID
- * @return Neighbors
- */
- public List<DistanceResultPair<D>> get(DBID objid) {
- return storage.get(objid);
- }
-
@Override
public final void insert(DBID id) {
objectsInserted(id);
@@ -165,6 +148,9 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra
@Override
public void insertAll(DBIDs ids) {
+ if(storage == null && ids.size() > 0) {
+ preprocess();
+ }
objectsInserted(ids);
}
@@ -193,7 +179,7 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra
if(stepprog != null) {
stepprog.beginStep(1, "New insertions ocurred, materialize their new kNNs.", getLogger());
}
- List<List<DistanceResultPair<D>>> kNNList = knnQuery.getKNNForBulkDBIDs(aids, k);
+ List<KNNResult<D>> kNNList = knnQuery.getKNNForBulkDBIDs(aids, k);
for(int i = 0; i < aids.size(); i++) {
DBID id = aids.get(i);
storage.put(id, kNNList.get(i));
@@ -225,13 +211,12 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra
* updated
*/
private ArrayDBIDs updateKNNsAfterInsertion(DBIDs ids) {
- ArrayDBIDs rkNN_ids = DBIDUtil.newArray();
+ ArrayModifiableDBIDs rkNN_ids = DBIDUtil.newArray();
DBIDs oldids = DBIDUtil.difference(relation.getDBIDs(), ids);
for(DBID id1 : oldids) {
- List<DistanceResultPair<D>> kNNs = storage.get(id1);
+ KNNResult<D> kNNs = storage.get(id1);
D knnDist = kNNs.get(kNNs.size() - 1).getDistance();
// look for new kNNs
- List<DistanceResultPair<D>> newKNNs = new ArrayList<DistanceResultPair<D>>();
KNNHeap<D> heap = null;
for(DBID id2 : ids) {
D dist = distanceQuery.distance(id1, id2);
@@ -244,8 +229,8 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra
}
}
if(heap != null) {
- newKNNs = heap.toSortedArrayList();
- storage.put(id1, newKNNs);
+ kNNs = heap.toKNNList();
+ storage.put(id1, kNNs);
rkNN_ids.add(id1);
}
}
@@ -260,10 +245,10 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra
* updated
*/
private ArrayDBIDs updateKNNsAfterDeletion(DBIDs ids) {
- TreeSetModifiableDBIDs idsSet = DBIDUtil.newTreeSet(ids);
- ArrayDBIDs rkNN_ids = DBIDUtil.newArray();
+ SetDBIDs idsSet = DBIDUtil.ensureSet(ids);
+ ArrayModifiableDBIDs rkNN_ids = DBIDUtil.newArray();
for(DBID id1 : relation.iterDBIDs()) {
- List<DistanceResultPair<D>> kNNs = storage.get(id1);
+ KNNResult<D> kNNs = storage.get(id1);
for(DistanceResultPair<D> kNN : kNNs) {
if(idsSet.contains(kNN.getDBID())) {
rkNN_ids.add(id1);
@@ -273,7 +258,7 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra
}
// update the kNNs of the RkNNs
- List<List<DistanceResultPair<D>>> kNNList = knnQuery.getKNNForBulkDBIDs(rkNN_ids, k);
+ List<KNNResult<D>> kNNList = knnQuery.getKNNForBulkDBIDs(rkNN_ids, k);
for(int i = 0; i < rkNN_ids.size(); i++) {
DBID id = rkNN_ids.get(i);
storage.put(id, kNNList.get(i));
@@ -360,16 +345,18 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra
* @param remove the ids to remove
* @return the DBIDs in the given collection
*/
- protected ArrayDBIDs extractAndRemoveIDs(List<List<DistanceResultPair<D>>> extraxt, ArrayDBIDs remove) {
- TreeSetModifiableDBIDs ids = DBIDUtil.newTreeSet();
- for(List<DistanceResultPair<D>> drps : extraxt) {
+ protected ArrayDBIDs extractAndRemoveIDs(List<? extends Collection<DistanceResultPair<D>>> extraxt, ArrayDBIDs remove) {
+ HashSetModifiableDBIDs ids = DBIDUtil.newHashSet();
+ for(Collection<DistanceResultPair<D>> drps : extraxt) {
for(DistanceResultPair<D> drp : drps) {
ids.add(drp.getDBID());
}
}
- ids.removeAll(remove);
- return DBIDUtil.ensureArray(ids);
-
+ for(DBID id : remove) {
+ ids.remove(id);
+ }
+ // Convert back to array
+ return DBIDUtil.newArray(ids);
}
/**
@@ -423,7 +410,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> {
+ public static class Factory<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor.Factory<O, D, KNNResult<D>> {
/**
* Index factory.
*
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 f20e6e39..5ac7d2d2 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,12 +28,11 @@ import java.util.HashMap;
import java.util.List;
import de.lmu.ifi.dbs.elki.data.NumberVector;
-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.DBID;
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.query.distance.DistanceQuery;
+import de.lmu.ifi.dbs.elki.database.query.knn.KNNResult;
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;
@@ -69,7 +68,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<? super O, ?>, D extends Distance<D>, N extends Node<E>, E extends MTreeEntry<D>> extends AbstractMaterializeKNNPreprocessor<O, D> {
+public class MetricalIndexApproximationMaterializeKNNPreprocessor<O extends NumberVector<? super O, ?>, D extends Distance<D>, N extends Node<E>, E extends MTreeEntry<D>> extends AbstractMaterializeKNNPreprocessor<O, D, KNNResult<D>> {
/**
* Logger to use
*/
@@ -92,7 +91,7 @@ public class MetricalIndexApproximationMaterializeKNNPreprocessor<O extends Numb
MetricalIndexTree<O, D, N, E> index = getMetricalIndex(relation);
- storage = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, List.class);
+ createStorage();
MeanVariance pagesize = new MeanVariance();
MeanVariance ksize = new MeanVariance();
if(getLogger().isVerbose()) {
@@ -133,7 +132,7 @@ public class MetricalIndexApproximationMaterializeKNNPreprocessor<O extends Numb
}
}
ksize.put(kNN.size());
- storage.put(id, kNN.toSortedArrayList());
+ storage.put(id, kNN.toKNNList());
}
if(getLogger().isDebugging()) {
if(cache.size() > 0) {
@@ -203,7 +202,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<? super O, ?>, D extends Distance<D>, N extends Node<E>, E extends MTreeEntry<D>> extends AbstractMaterializeKNNPreprocessor.Factory<O, D> {
+ public static class Factory<O extends NumberVector<? super O, ?>, D extends Distance<D>, N extends Node<E>, E extends MTreeEntry<D>> extends AbstractMaterializeKNNPreprocessor.Factory<O, D, KNNResult<D>> {
/**
* Constructor.
*
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 3e7d1b8f..90813b92 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) 2011
+ Copyright (C) 2012
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.preprocessed.knn;
*/
import java.util.HashMap;
-import java.util.List;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
@@ -34,6 +33,7 @@ import de.lmu.ifi.dbs.elki.database.ids.DBID;
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.query.distance.DistanceQuery;
+import de.lmu.ifi.dbs.elki.database.query.knn.KNNResult;
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;
@@ -61,7 +61,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
*/
@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> {
+public class PartitionApproximationMaterializeKNNPreprocessor<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor<O, D, KNNResult<D>> {
// TODO: randomize/shuffle?
/**
@@ -85,14 +85,12 @@ public class PartitionApproximationMaterializeKNNPreprocessor<O, D extends Dista
public PartitionApproximationMaterializeKNNPreprocessor(Relation<O> relation, DistanceFunction<? super O, D> distanceFunction, int k, int partitions) {
super(relation, distanceFunction, k);
this.partitions = partitions;
- // preprocess now
- preprocess();
}
@Override
protected void preprocess() {
DistanceQuery<O, D> distanceQuery = relation.getDatabase().getDistanceQuery(relation, distanceFunction);
- storage = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, List.class);
+ storage = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, KNNResult.class);
MeanVariance ksize = new MeanVariance();
if(logger.isVerbose()) {
logger.verbose("Approximating nearest neighbor lists to database objects");
@@ -130,7 +128,7 @@ public class PartitionApproximationMaterializeKNNPreprocessor<O, D extends Dista
}
}
ksize.put(kNN.size());
- storage.put(id, kNN.toSortedArrayList());
+ storage.put(id, kNN.toKNNList());
}
if(logger.isDebugging()) {
if(cache.size() > 0) {
@@ -176,7 +174,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> {
+ public static class Factory<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor.Factory<O, D, KNNResult<D>> {
/**
* Parameter to specify the number of partitions to use for materializing
* the kNN. Must be an integer greater than 1.
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
new file mode 100644
index 00000000..924c7c3c
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/RandomSampleKNNPreprocessor.java
@@ -0,0 +1,237 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.datastore.DataStoreFactory;
+import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil;
+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.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.query.GenericDistanceResultPair;
+import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
+import de.lmu.ifi.dbs.elki.database.query.knn.KNNResult;
+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.datastructures.heap.KNNHeap;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.IntervalConstraint;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.IntervalConstraint.IntervalBoundary;
+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.LongParameter;
+
+/**
+ * Class that computed the kNN only on a random sample.
+ *
+ * @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>> {
+ /**
+ * Logger
+ */
+ private static final Logging logger = Logging.getLogger(RandomSampleKNNPreprocessor.class);
+
+ /**
+ * Relative share of objects to get
+ */
+ private final double share;
+
+ /**
+ * Random seed
+ */
+ private final Long seed;
+
+ /**
+ * Constructor.
+ *
+ * @param relation Relation to index
+ * @param distanceFunction distance function
+ * @param k k
+ * @param share Relative share
+ * @param seed Random seed (may be null)
+ */
+ public RandomSampleKNNPreprocessor(Relation<O> relation, DistanceFunction<? super O, D> distanceFunction, int k, double share, Long seed) {
+ super(relation, distanceFunction, k);
+ this.share = share;
+ this.seed = seed;
+ }
+
+ @Override
+ protected void preprocess() {
+ DistanceQuery<O, D> distanceQuery = relation.getDatabase().getDistanceQuery(relation, distanceFunction);
+ storage = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, KNNResult.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);
+ final long iseed = (seed != null) ? seed : (new Random()).nextLong();
+
+ int i = 0;
+ for(DBID id : ids) {
+ KNNHeap<D> kNN = new KNNHeap<D>(k, distanceQuery.infiniteDistance());
+
+ long rseed = i * 0x7FFFFFFFFFFFFFE7L + iseed;
+ DBIDs rsamp = DBIDUtil.randomSample(ids, samplesize, rseed);
+ for(DBID oid : rsamp) {
+ D dist = distanceQuery.distance(id, oid);
+ kNN.add(new GenericDistanceResultPair<D>(dist, oid));
+ }
+
+ storage.put(id, kNN.toKNNList());
+ if(progress != null) {
+ progress.incrementProcessed(getLogger());
+ }
+ }
+
+ if(progress != null) {
+ progress.ensureCompleted(getLogger());
+ }
+ }
+
+ @Override
+ protected Logging getLogger() {
+ return logger;
+ }
+
+ @Override
+ public String getLongName() {
+ return "random sample kNN";
+ }
+
+ @Override
+ public String getShortName() {
+ return "random-sample-knn";
+ }
+
+ /**
+ * The parameterizable factory.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.landmark
+ * @apiviz.stereotype factory
+ * @apiviz.uses AbstractMaterializeKNNPreprocessor oneway - - «create»
+ *
+ * @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>> {
+ /**
+ * Relative share of objects to get
+ */
+ private final double share;
+
+ /**
+ * Random seed
+ */
+ private final Long seed;
+
+ /**
+ * Constructor.
+ *
+ * @param k K
+ * @param distanceFunction distance function
+ * @param share Sample size (relative)
+ * @param seed Random seed
+ */
+ public Factory(int k, DistanceFunction<? super O, D> distanceFunction, double share, Long seed) {
+ super(k, distanceFunction);
+ this.share = share;
+ this.seed = seed;
+ }
+
+ @Override
+ public RandomSampleKNNPreprocessor<O, D> instantiate(Relation<O> relation) {
+ return new RandomSampleKNNPreprocessor<O, D>(relation, distanceFunction, k, share, seed);
+ }
+
+ /**
+ * 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 AbstractMaterializeKNNPreprocessor.Factory.Parameterizer<O, D> {
+ /**
+ * Parameter to specify how many objects to consider for computing the
+ * kNN.
+ *
+ * <p>
+ * Key: {@code -randomknn.share}
+ * </p>
+ */
+ public static final OptionID SHARE_ID = OptionID.getOrCreateOptionID("randomknn.share", "The relative amount of objects to consider for kNN computations.");
+
+ /**
+ * Random number generator seed.
+ *
+ * <p>
+ * Key: {@code -randomknn.seed}
+ * </p>
+ */
+ public static final OptionID SEED_ID = OptionID.getOrCreateOptionID("randomknn.seed", "The random number seed.");
+
+ /**
+ * Relative share of objects to get
+ */
+ private double share = 0.0;
+
+ /**
+ * Random seed
+ */
+ private Long seed = null;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ DoubleParameter shareP = new DoubleParameter(SHARE_ID, new IntervalConstraint(0.0, IntervalBoundary.OPEN, 1.0, IntervalBoundary.OPEN));
+ if(config.grab(shareP)) {
+ share = shareP.getValue();
+ }
+ LongParameter seedP = new LongParameter(SEED_ID, true);
+ if(config.grab(seedP)) {
+ seed = seedP.getValue();
+ }
+ }
+
+ @Override
+ protected RandomSampleKNNPreprocessor.Factory<O, D> makeInstance() {
+ return new RandomSampleKNNPreprocessor.Factory<O, D>(k, distanceFunction, share, seed);
+ }
+ }
+ }
+} \ No newline at end of file
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 320a3636..e78f5e89 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) 2011
+ Copyright (C) 2012
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.DBID;
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.query.distance.DistanceQuery;
+import de.lmu.ifi.dbs.elki.database.query.knn.KNNResult;
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;
@@ -68,7 +69,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> {
+public class SpatialApproximationMaterializeKNNPreprocessor<O extends NumberVector<?, ?>, D extends Distance<D>, N extends SpatialNode<N, E>, E extends SpatialEntry> extends AbstractMaterializeKNNPreprocessor<O, D, KNNResult<D>> {
/**
* Logger to use
*/
@@ -83,7 +84,6 @@ public class SpatialApproximationMaterializeKNNPreprocessor<O extends NumberVect
*/
public SpatialApproximationMaterializeKNNPreprocessor(Relation<O> relation, DistanceFunction<? super O, D> distanceFunction, int k) {
super(relation, distanceFunction, k);
- preprocess();
}
@Override
@@ -96,7 +96,7 @@ public class SpatialApproximationMaterializeKNNPreprocessor<O extends NumberVect
}
SpatialIndexTree<N, E> index = indexes.iterator().next();
- storage = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, List.class);
+ storage = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, KNNResult.class);
MeanVariance pagesize = new MeanVariance();
MeanVariance ksize = new MeanVariance();
if(getLogger().isVerbose()) {
@@ -137,7 +137,7 @@ public class SpatialApproximationMaterializeKNNPreprocessor<O extends NumberVect
}
}
ksize.put(kNN.size());
- storage.put(id, kNN.toSortedArrayList());
+ storage.put(id, kNN.toKNNList());
}
if(getLogger().isDebugging()) {
if(cache.size() > 0) {
@@ -185,7 +185,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> {
+ public static class Factory<D extends Distance<D>, N extends SpatialNode<N, E>, E extends SpatialEntry> extends AbstractMaterializeKNNPreprocessor.Factory<NumberVector<?, ?>, D, KNNResult<D>> {
/**
* Constructor.
*
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 57fe5fbd..1780cdc0 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) 2011
+Copyright (C) 2012
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 3def22a1..9cb2b997 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) 2011
+ Copyright (C) 2012
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.preprocessed.localpca;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.List;
+import java.util.Collection;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
@@ -100,7 +100,7 @@ public abstract class AbstractFilteredPCAIndex<NV extends NumberVector<? extends
// TODO: use a bulk operation?
for(DBID id : relation.iterDBIDs()) {
- List<DistanceResultPair<DoubleDistance>> objects = objectsForPCA(id);
+ Collection<DistanceResultPair<DoubleDistance>> objects = objectsForPCA(id);
PCAFilteredResult pcares = pca.processQueryResult(objects, relation);
@@ -137,7 +137,7 @@ public abstract class AbstractFilteredPCAIndex<NV extends NumberVector<? extends
* @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 List<DistanceResultPair<DoubleDistance>> objectsForPCA(DBID id);
+ protected abstract Collection<DistanceResultPair<DoubleDistance>> objectsForPCA(DBID id);
/**
* Factory class
@@ -185,7 +185,7 @@ public abstract class AbstractFilteredPCAIndex<NV extends NumberVector<? extends
public TypeInformation getInputTypeRestriction() {
return pcaDistanceFunction.getInputTypeRestriction();
}
-
+
/**
* Parameterization class.
*
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 18835caa..8130f6b3 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) 2011
+ Copyright (C) 2012
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 7565ab32..8d766391 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,13 +23,11 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.localpca;
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.database.QueryUtil;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
+import de.lmu.ifi.dbs.elki.database.query.knn.KNNResult;
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;
@@ -88,7 +86,7 @@ public class KNNQueryFilteredPCAIndex<NV extends NumberVector<? extends NV, ?>>
}
@Override
- protected List<DistanceResultPair<DoubleDistance>> objectsForPCA(DBID id) {
+ protected KNNResult<DoubleDistance> objectsForPCA(DBID id) {
return knnQuery.getKNNForDBID(id, k);
}
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 26f08ae3..7d5da770 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) 2011
+ Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/package-info.java
index f097bd14..2bd9cc7d 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) 2011
+Copyright (C) 2012
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 4c482cd2..98a55d88 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) 2011
+Copyright (C) 2012
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 13b6e28b..95c698ee 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) 2011
+ Copyright (C) 2012
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/DiSHPreferenceVectorIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/DiSHPreferenceVectorIndex.java
index 8626e5b7..ade6c114 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) 2011
+ Copyright (C) 2012
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/HiSCPreferenceVectorIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/HiSCPreferenceVectorIndex.java
index 849e0fd6..44ddb17c 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) 2011
+ Copyright (C) 2012
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.preprocessed.preference;
import java.util.BitSet;
import java.util.Iterator;
-import java.util.List;
import de.lmu.ifi.dbs.elki.algorithm.clustering.subspace.HiSC;
import de.lmu.ifi.dbs.elki.data.NumberVector;
@@ -33,11 +32,9 @@ 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.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.ModifiableDBIDs;
-import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
+import de.lmu.ifi.dbs.elki.database.query.knn.KNNResult;
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.distancevalue.DoubleDistance;
@@ -120,16 +117,8 @@ public class HiSCPreferenceVectorIndex<V extends NumberVector<?, ?>> extends Abs
msg.append("\n knns: ");
}
- List<DistanceResultPair<DoubleDistance>> knns = knnQuery.getKNNForDBID(id, k);
- ModifiableDBIDs knnIDs = DBIDUtil.newArray(knns.size());
- for(DistanceResultPair<DoubleDistance> knn : knns) {
- knnIDs.add(knn.getDBID());
- //if(logger.isDebugging()) {
- // msg.append(database.getObjectLabelQuery().get(knn.getID())).append(" ");
- //}
- }
-
- BitSet preferenceVector = determinePreferenceVector(relation, id, knnIDs, msg);
+ KNNResult<DoubleDistance> knns = knnQuery.getKNNForDBID(id, k);
+ BitSet preferenceVector = determinePreferenceVector(relation, id, knns.asDBIDs(), msg);
storage.put(id, preferenceVector);
if(progress != null) {
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 1f2dd10b..c01e9ddb 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) 2011
+ Copyright (C) 2012
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 7676879c..69d0855b 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) 2011
+Copyright (C) 2012
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 7920fc2b..7efe26e0 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) 2011
+ Copyright (C) 2012
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.index.preprocessed.snn;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+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.TreeSetDBIDs;
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;
@@ -41,7 +41,7 @@ public interface SharedNearestNeighborIndex<O> extends Index {
* @param objid Object ID
* @return Neighbor DBIDs
*/
- public TreeSetDBIDs getNearestNeighborSet(DBID objid);
+ public ArrayDBIDs getNearestNeighborSet(DBID objid);
/**
* Get the number of neighbors
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 43bd7e30..46f47a33 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,19 +23,16 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.snn;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.List;
-
import de.lmu.ifi.dbs.elki.data.type.TypeInformation;
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.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.DBIDUtil;
-import de.lmu.ifi.dbs.elki.database.ids.SetDBIDs;
-import de.lmu.ifi.dbs.elki.database.ids.TreeSetDBIDs;
-import de.lmu.ifi.dbs.elki.database.ids.TreeSetModifiableDBIDs;
-import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
+import de.lmu.ifi.dbs.elki.database.query.knn.KNNResult;
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;
@@ -75,7 +72,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
*/
@Title("Shared nearest neighbor Preprocessor")
@Description("Computes the k nearest neighbors of objects of a certain database.")
-public class SharedNearestNeighborPreprocessor<O, D extends Distance<D>> extends AbstractPreprocessorIndex<O, TreeSetDBIDs> implements SharedNearestNeighborIndex<O> {
+public class SharedNearestNeighborPreprocessor<O, D extends Distance<D>> extends AbstractPreprocessorIndex<O, ArrayDBIDs> implements SharedNearestNeighborIndex<O> {
/**
* Get a logger for this class.
*/
@@ -111,23 +108,24 @@ public class SharedNearestNeighborPreprocessor<O, D extends Distance<D>> extends
if(getLogger().isVerbose()) {
getLogger().verbose("Assigning nearest neighbor lists to database objects");
}
- storage = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP, SetDBIDs.class);
+ storage = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP, ArrayDBIDs.class);
KNNQuery<O, D> knnquery = QueryUtil.getKNNQuery(relation, distanceFunction, numberOfNeighbors);
FiniteProgress progress = getLogger().isVerbose() ? new FiniteProgress("assigning nearest neighbor lists", relation.size(), getLogger()) : null;
for(DBID id : relation.iterDBIDs()) {
- TreeSetModifiableDBIDs neighbors = DBIDUtil.newTreeSet(numberOfNeighbors);
- List<DistanceResultPair<D>> kNN = knnquery.getKNNForDBID(id, numberOfNeighbors);
+ ArrayModifiableDBIDs neighbors = DBIDUtil.newArray(numberOfNeighbors);
+ KNNResult<D> kNN = knnquery.getKNNForDBID(id, numberOfNeighbors);
for(int i = 0; i < kNN.size(); i++) {
final DBID nid = kNN.get(i).getDBID();
// if(!id.equals(nid)) {
neighbors.add(nid);
// }
- // Size limitation to exaclty numberOfNeighbors
+ // Size limitation to exactly numberOfNeighbors
if(neighbors.size() >= numberOfNeighbors) {
break;
}
}
+ neighbors.sort();
storage.put(id, neighbors);
if(progress != null) {
progress.incrementProcessed(getLogger());
@@ -139,7 +137,7 @@ public class SharedNearestNeighborPreprocessor<O, D extends Distance<D>> extends
}
@Override
- public TreeSetDBIDs getNearestNeighborSet(DBID objid) {
+ public ArrayDBIDs getNearestNeighborSet(DBID objid) {
if(storage == null) {
preprocess();
}
@@ -269,7 +267,7 @@ public class SharedNearestNeighborPreprocessor<O, D extends Distance<D>> extends
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- final IntParameter numberOfNeighborsP = new IntParameter(NUMBER_OF_NEIGHBORS_ID, new GreaterEqualConstraint(1), 1);
+ final IntParameter numberOfNeighborsP = new IntParameter(NUMBER_OF_NEIGHBORS_ID, new GreaterEqualConstraint(1));
if(config.grab(numberOfNeighborsP)) {
numberOfNeighbors = numberOfNeighborsP.getValue();
}
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 e29cd0e0..98065df6 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) 2011
+Copyright (C) 2012
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 8aef442b..4a265fc9 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) 2011
+ Copyright (C) 2012
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/FourCSubspaceIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/FourCSubspaceIndex.java
index 5a7fe2e0..83a9469c 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) 2011
+ Copyright (C) 2012
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/PreDeConSubspaceIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/PreDeConSubspaceIndex.java
index cc05bcd1..1e83ae80 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) 2011
+ Copyright (C) 2012
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/SubspaceProjectionIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/SubspaceProjectionIndex.java
index d0630aac..d5070986 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) 2011
+ Copyright (C) 2012
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 b364aa09..f6e5e925 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) 2011
+Copyright (C) 2012
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/AbstractDirectoryEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/AbstractDirectoryEntry.java
index 2c764231..03572b35 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) 2011
+ Copyright (C) 2012
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 2183888f..d2d38976 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) 2011
+ Copyright (C) 2012
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 242267d6..42f4fa11 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,14 +28,16 @@ import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.BitSet;
import java.util.Enumeration;
import java.util.List;
import java.util.NoSuchElementException;
-import java.util.logging.Logger;
+import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.LoggingConfiguration;
-import de.lmu.ifi.dbs.elki.persistent.AbstractPage;
+import de.lmu.ifi.dbs.elki.persistent.AbstractExternalizablePage;
import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
/**
* Abstract superclass for nodes in an tree based index structure.
@@ -43,7 +45,7 @@ import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
* @author Elke Achtert
* @param <E> the type of Entry used in the index
*/
-public abstract class AbstractNode<E extends Entry> extends AbstractPage implements Node<E> {
+public abstract class AbstractNode<E extends Entry> extends AbstractExternalizablePage implements Node<E> {
/**
* The number of entries in this node.
*/
@@ -155,7 +157,7 @@ public abstract class AbstractNode<E extends Entry> extends AbstractPage impleme
* both nodes are of the same type (leaf node or directory node) and have
* contain the same entries, <code>false</code> otherwise.
*
- * @see de.lmu.ifi.dbs.elki.persistent.AbstractPage#equals(Object)
+ * @see de.lmu.ifi.dbs.elki.persistent.AbstractExternalizablePage#equals(Object)
*/
@Override
public boolean equals(Object o) {
@@ -276,11 +278,17 @@ public abstract class AbstractNode<E extends Entry> extends AbstractPage impleme
* Returns a list of the entries.
*
* @return a list of the entries
+ *
+ * @deprecated Using this method means an extra copy - usually at the cost of
+ * performance.
*/
+ @Deprecated
public final List<E> getEntries() {
- List<E> result = new ArrayList<E>();
+ List<E> result = new ArrayList<E>(numEntries);
for(E entry : entries) {
- result.add(entry);
+ if(entry != null) {
+ result.add(entry);
+ }
}
return result;
}
@@ -298,6 +306,32 @@ public abstract class AbstractNode<E extends Entry> extends AbstractPage impleme
}
/**
+ * Remove entries according to the given mask.
+ *
+ * @param mask Mask to remove
+ */
+ public void removeMask(BitSet mask) {
+ int dest = mask.nextSetBit(0);
+ if(dest < 0) {
+ return;
+ }
+ int src = mask.nextClearBit(dest);
+ while(src < numEntries) {
+ if(!mask.get(src)) {
+ entries[dest] = entries[src];
+ dest++;
+ }
+ src++;
+ }
+ int rm = src - dest;
+ while(dest < numEntries) {
+ entries[dest] = null;
+ dest++;
+ }
+ numEntries -= rm;
+ }
+
+ /**
* Redistribute entries according to the given sorting.
*
* @param newNode Node to split to
@@ -305,7 +339,7 @@ public abstract class AbstractNode<E extends Entry> extends AbstractPage impleme
* @param splitPoint Split point
*/
public final void splitTo(AbstractNode<E> newNode, List<E> sorting, int splitPoint) {
- assert(isLeaf() == newNode.isLeaf());
+ assert (isLeaf() == newNode.isLeaf());
deleteAllEntries();
StringBuffer msg = LoggingConfiguration.DEBUG ? new StringBuffer("\n") : null;
@@ -325,7 +359,7 @@ public abstract class AbstractNode<E extends Entry> extends AbstractPage impleme
}
}
if(msg != null) {
- Logger.getLogger(this.getClass().getName()).fine(msg.toString());
+ Logging.getLogger(this.getClass().getName()).fine(msg.toString());
}
}
@@ -337,7 +371,7 @@ public abstract class AbstractNode<E extends Entry> extends AbstractPage impleme
* @param assignmentsToSecond the assignment to the new node
*/
public final void splitTo(AbstractNode<E> newNode, List<E> assignmentsToFirst, List<E> assignmentsToSecond) {
- assert(isLeaf() == newNode.isLeaf());
+ assert (isLeaf() == newNode.isLeaf());
deleteAllEntries();
StringBuffer msg = LoggingConfiguration.DEBUG ? new StringBuffer() : null;
@@ -357,7 +391,40 @@ public abstract class AbstractNode<E extends Entry> extends AbstractPage impleme
newNode.addEntry(entry);
}
if(msg != null) {
- Logger.getLogger(this.getClass().getName()).fine(msg.toString());
+ Logging.getLogger(this.getClass()).fine(msg.toString());
+ }
+ }
+
+ /**
+ * Splits the entries of this node into a new node using the given assignments
+ *
+ * @param newNode Node to split to
+ * @param assignment Assignment mask
+ */
+ public final void splitByMask(AbstractNode<E> newNode, BitSet assignment) {
+ assert (isLeaf() == newNode.isLeaf());
+ int dest = assignment.nextSetBit(0);
+ if(dest < 0) {
+ throw new AbortException("No bits set in splitting mask.");
+ }
+ int pos = dest;
+ while(pos < numEntries) {
+ if(assignment.get(pos)) {
+ // Move to new node
+ newNode.addEntry(entries[pos]);
+ }
+ else {
+ // Move to new position
+ entries[dest] = entries[pos];
+ dest++;
+ }
+ pos++;
+ }
+ final int rm = numEntries - dest;
+ while(dest < numEntries) {
+ entries[dest] = null;
+ dest++;
}
+ numEntries -= rm;
}
} \ No newline at end of file
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 f7f1c247..6f43de11 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) 2011
+ Copyright (C) 2012
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/DirectoryEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/DirectoryEntry.java
index c380dd4f..68924cae 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) 2011
+ Copyright (C) 2012
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/DistanceEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/DistanceEntry.java
index b7bf3e0c..3cf6dfb9 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/DistanceEntry.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/DistanceEntry.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) 2011
+ Copyright (C) 2012
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/Entry.java b/src/de/lmu/ifi/dbs/elki/index/tree/Entry.java
index 9ac01380..77c13d8e 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) 2011
+ Copyright (C) 2012
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/IndexTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/IndexTree.java
index fa9c0e0a..e4cdc71f 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -121,7 +121,7 @@ public abstract class IndexTree<N extends Node<E>, E extends Entry> {
*
* @return page id
*/
- public final Integer getRootID() {
+ public final int getRootID() {
return getPageID(rootEntry);
}
@@ -141,7 +141,7 @@ public abstract class IndexTree<N extends Node<E>, E extends Entry> {
* @return Whether the page ID is the root
*/
protected boolean isRoot(N page) {
- return getRootID().equals(page.getPageID());
+ return getRootID() == page.getPageID();
}
/**
@@ -150,7 +150,7 @@ public abstract class IndexTree<N extends Node<E>, E extends Entry> {
* @param entry Entry
* @return Page ID
*/
- protected Integer getPageID(Entry entry) {
+ protected int getPageID(Entry entry) {
if (entry.isLeafEntry()) {
throw new AbortException("Leafs do not have page ids!");
}
@@ -163,7 +163,7 @@ public abstract class IndexTree<N extends Node<E>, E extends Entry> {
* @param nodeID the page id of the node to be returned
* @return the node with the specified id
*/
- public N getNode(Integer nodeID) {
+ public N getNode(int nodeID) {
if(nodeID == getPageID(rootEntry)) {
return getRoot();
}
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 feb134e3..560bd250 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) 2011
+ Copyright (C) 2012
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/LeafEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/LeafEntry.java
index 362e2daf..c6eb1269 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) 2011
+ Copyright (C) 2012
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/Node.java b/src/de/lmu/ifi/dbs/elki/index/tree/Node.java
index 62892a22..c288a1fe 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) 2011
+ Copyright (C) 2012
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/TreeIndexFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexFactory.java
index b55700ec..a170ca5b 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexFactory.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexFactory.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) 2011
+ Copyright (C) 2012
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.tree;
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.Page;
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;
@@ -124,7 +124,7 @@ public abstract class TreeIndexFactory<O, I extends Index> implements IndexFacto
* @return Page file
*/
// FIXME: make this single-shot when filename is set!
- protected <N extends Page> PageFile<N> makePageFile(Class<N> cls) {
+ protected <N extends ExternalizablePage> PageFile<N> makePageFile(Class<N> cls) {
final PageFile<N> inner;
if(fileName == null) {
inner = new MemoryPageFile<N>(pageSize);
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 3bb901e3..017c3571 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) 2011
+ Copyright (C) 2012
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/TreeIndexPathComponent.java b/src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexPathComponent.java
index 2309c7e5..d2800d54 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) 2011
+ Copyright (C) 2012
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 606921df..b98841aa 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) 2011
+ Copyright (C) 2012
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/AbstractMTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTree.java
index db4b5c07..5e949e0b 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) 2011
+ Copyright (C) 2012
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/AbstractMTreeFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTreeFactory.java
index a7d701fa..9ae50bbe 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) 2011
+ Copyright (C) 2012
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/AbstractMTreeNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTreeNode.java
index 3fec4706..85a9571d 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) 2011
+ Copyright (C) 2012
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/MTreeDirectoryEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeDirectoryEntry.java
index 5729115a..0b07c446 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) 2011
+ Copyright (C) 2012
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/MTreeEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeEntry.java
index 0683a061..f6969b92 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) 2011
+ Copyright (C) 2012
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/MTreeLeafEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeLeafEntry.java
index aae51378..27fbc1ba 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) 2011
+ Copyright (C) 2012
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/AbstractMkTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTree.java
index 00cf45a7..ffd38a74 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) 2011
+ Copyright (C) 2012
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/AbstractMkTreeUnified.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTreeUnified.java
index f7135682..88013000 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) 2011
+ Copyright (C) 2012
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/AbstractMkTreeUnifiedFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTreeUnifiedFactory.java
index dd1648a0..51df5077 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) 2011
+ Copyright (C) 2012
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/MkTreeHeader.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/MkTreeHeader.java
index 809bc72b..c067a86c 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) 2011
+ Copyright (C) 2012
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/MkAppDirectoryEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppDirectoryEntry.java
index 39d420ba..ce7cf104 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) 2011
+ Copyright (C) 2012
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/MkAppEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppEntry.java
index ef50e3bc..b6eabf7e 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) 2011
+ Copyright (C) 2012
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/MkAppLeafEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppLeafEntry.java
index 961cdd92..4dbf0244 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) 2011
+ Copyright (C) 2012
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/MkAppTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTree.java
index c0fe4523..5f92ba70 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) 2011
+ Copyright (C) 2012
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/MkAppTreeFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeFactory.java
index 540182e8..233129b4 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) 2011
+ Copyright (C) 2012
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/MkAppTreeIndex.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeIndex.java
index cd7042d6..eedc52ed 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) 2011
+ Copyright (C) 2012
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/MkAppTreeNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeNode.java
index cd1a1c3b..bc6a83a9 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) 2011
+ Copyright (C) 2012
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/PolynomialApproximation.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/PolynomialApproximation.java
index d32c1c0c..83e60e0e 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) 2011
+ Copyright (C) 2012
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 674ac861..0f3cfde9 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) 2011
+Copyright (C) 2012
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 0e7ccaf7..7f2aa3fe 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) 2011
+ Copyright (C) 2012
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/ConvexHull.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/ConvexHull.java
index 7924c13d..7cb5a16b 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) 2011
+ Copyright (C) 2012
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 dd267d95..22b4efa4 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) 2011
+ Copyright (C) 2012
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/MkCoPEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPEntry.java
index cd1155c3..077fb1ec 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) 2011
+ Copyright (C) 2012
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/MkCoPLeafEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPLeafEntry.java
index 9f4da83f..0daf7950 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) 2011
+ Copyright (C) 2012
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/MkCoPTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTree.java
index a2f684ad..7fe67a03 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) 2011
+ Copyright (C) 2012
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/MkCoPTreeIndex.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTreeIndex.java
index d920cdab..2c4ffb06 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) 2011
+ Copyright (C) 2012
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/MkCoPTreeNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTreeNode.java
index 3fafb5fc..01fca2f2 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) 2011
+ Copyright (C) 2012
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/MkCopTreeFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCopTreeFactory.java
index 67968259..8d88ee79 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) 2011
+ Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/package-info.java
index 3679e608..516af071 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) 2011
+Copyright (C) 2012
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 0de76f2f..0781dcb1 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) 2011
+ Copyright (C) 2012
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/MkMaxEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxEntry.java
index 141037c7..0a7032f3 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) 2011
+ Copyright (C) 2012
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/MkMaxLeafEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxLeafEntry.java
index 0a8ee091..29221fdc 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) 2011
+ Copyright (C) 2012
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/MkMaxTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTree.java
index 0e637c57..5b7dc8fc 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) 2011
+ Copyright (C) 2012
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/MkMaxTreeFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeFactory.java
index ba630c4e..7e9a7753 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) 2011
+ Copyright (C) 2012
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/MkMaxTreeIndex.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeIndex.java
index e3aed27e..9e1b6d6b 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) 2011
+ Copyright (C) 2012
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/MkMaxTreeNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeNode.java
index 345829f1..17f85498 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) 2011
+ Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/package-info.java
index 4ea34e49..bcde11b4 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) 2011
+Copyright (C) 2012
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 cc431b1e..f8410ad9 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) 2011
+ Copyright (C) 2012
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/MkTabEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabEntry.java
index dfecc0d8..88000f5d 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) 2011
+ Copyright (C) 2012
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/MkTabLeafEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabLeafEntry.java
index ad3e999f..81446718 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) 2011
+ Copyright (C) 2012
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/MkTabTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTree.java
index 0014593c..750dfb72 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) 2011
+ Copyright (C) 2012
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/MkTabTreeFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTreeFactory.java
index ea4fbd36..2bc6c256 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) 2011
+ Copyright (C) 2012
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/MkTabTreeIndex.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTreeIndex.java
index dc59b7cc..0eb54bd1 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,9 +29,10 @@ import java.util.List;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
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.DistanceResultPair;
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.KNNResult;
+import de.lmu.ifi.dbs.elki.database.query.knn.KNNUtil;
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;
@@ -46,7 +47,6 @@ import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query.MetricalIndex
import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query.MetricalIndexRangeQuery;
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.datastructures.heap.KNNList;
import de.lmu.ifi.dbs.elki.utilities.exceptions.ExceptionMessages;
/**
@@ -103,8 +103,8 @@ public class MkTabTreeIndex<O, D extends Distance<D>> extends MkTabTree<O, D> im
* @return the knn distance of the object with the specified id
*/
private List<D> knnDistances(O object) {
- List<DistanceResultPair<D>> knns = knnQuery.getKNNForObject(object, getKmax() - 1);
- return KNNList.asDistanceList(knns);
+ KNNResult<D> knns = knnQuery.getKNNForObject(object, getKmax() - 1);
+ return KNNUtil.asDistanceList(knns);
}
@Override
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 55dfcbde..b09ac314 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) 2011
+ Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/package-info.java
index f03cf84a..353acaa5 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) 2011
+Copyright (C) 2012
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 4fbf50bb..201d57c3 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) 2011
+Copyright (C) 2012
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 4e9b4f9e..80955b8a 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) 2011
+ Copyright (C) 2012
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/MTreeFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeFactory.java
index 190a009d..2567f81f 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) 2011
+ Copyright (C) 2012
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/MTreeIndex.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeIndex.java
index 2a6d8a91..9bcd1b02 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) 2011
+ Copyright (C) 2012
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/MTreeNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeNode.java
index 26c2ae00..017e7d6c 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) 2011
+ Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/package-info.java
index 4233b17b..a34162a8 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) 2011
+Copyright (C) 2012
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 27fc5a22..b30d1193 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) 2011
+Copyright (C) 2012
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/MetricalIndexKNNQuery.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MetricalIndexKNNQuery.java
index ab99bdd9..b591f700 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,9 +28,9 @@ import java.util.Map;
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.query.DistanceResultPair;
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.KNNResult;
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.DirectoryEntry;
@@ -82,7 +82,7 @@ public class MetricalIndexKNNQuery<O, D extends Distance<D>> extends AbstractDis
final Heap<GenericMTreeDistanceSearchCandidate<D>> pq = new UpdatableHeap<GenericMTreeDistanceSearchCandidate<D>>();
// push root
- pq.add(new GenericMTreeDistanceSearchCandidate<D>(getDistanceFactory().nullDistance(), index.getRootID(), null));
+ pq.add(new GenericMTreeDistanceSearchCandidate<D>(distanceQuery.nullDistance(), index.getRootID(), null));
D d_k = knnList.getKNNDistance();
// search in tree
@@ -102,8 +102,8 @@ public class MetricalIndexKNNQuery<O, D extends Distance<D>> extends AbstractDis
MTreeEntry<D> entry = node.getEntry(i);
DBID o_r = entry.getRoutingObjectID();
D r_or = entry.getCoveringRadius();
- D d1 = o_p != null ? distanceQuery.distance(o_p, q) : getDistanceFactory().nullDistance();
- D d2 = o_p != null ? distanceQuery.distance(o_r, o_p) : getDistanceFactory().nullDistance();
+ D d1 = o_p != null ? distanceQuery.distance(o_p, q) : distanceQuery.nullDistance();
+ D d2 = o_p != null ? distanceQuery.distance(o_r, o_p) : distanceQuery.nullDistance();
D diff = d1.compareTo(d2) > 0 ? d1.minus(d2) : d2.minus(d1);
@@ -111,7 +111,7 @@ public class MetricalIndexKNNQuery<O, D extends Distance<D>> extends AbstractDis
if(diff.compareTo(sum) <= 0) {
D d3 = distanceQuery.distance(o_r, q);
- D d_min = DistanceUtil.max(d3.minus(r_or), getDistanceFactory().nullDistance());
+ D d_min = DistanceUtil.max(d3.minus(r_or), distanceQuery.nullDistance());
if(d_min.compareTo(d_k) <= 0) {
pq.add(new GenericMTreeDistanceSearchCandidate<D>(d_min, ((DirectoryEntry)entry).getPageID(), o_r));
}
@@ -126,8 +126,8 @@ public class MetricalIndexKNNQuery<O, D extends Distance<D>> extends AbstractDis
MTreeEntry<D> entry = node.getEntry(i);
DBID o_j = entry.getRoutingObjectID();
- D d1 = o_p != null ? distanceQuery.distance(o_p, q) : getDistanceFactory().nullDistance();
- D d2 = o_p != null ? distanceQuery.distance(o_j, o_p) : getDistanceFactory().nullDistance();
+ D d1 = o_p != null ? distanceQuery.distance(o_p, q) : distanceQuery.nullDistance();
+ D d2 = o_p != null ? distanceQuery.distance(o_j, o_p) : distanceQuery.nullDistance();
D diff = d1.compareTo(d2) > 0 ? d1.minus(d2) : d2.minus(d1);
@@ -144,23 +144,23 @@ public class MetricalIndexKNNQuery<O, D extends Distance<D>> extends AbstractDis
}
@Override
- public List<DistanceResultPair<D>> getKNNForObject(O obj, int k) {
+ public KNNResult<D> getKNNForObject(O obj, int k) {
if(k < 1) {
throw new IllegalArgumentException("At least one object has to be requested!");
}
final KNNHeap<D> knnList = new KNNHeap<D>(k, distanceQuery.getDistanceFactory().infiniteDistance());
doKNNQuery(obj, knnList);
- return knnList.toSortedArrayList();
+ return knnList.toKNNList();
}
@Override
- public List<DistanceResultPair<D>> getKNNForDBID(DBID id, int k) {
+ public KNNResult<D> getKNNForDBID(DBID id, int k) {
return getKNNForObject(relation.get(id), k);
}
@Override
- public List<List<DistanceResultPair<D>>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) {
+ 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 5854df8a..8536cc52 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -80,8 +80,8 @@ public class MetricalIndexRangeQuery<O, D extends Distance<D>> extends AbstractD
DBID o_r = entry.getRoutingObjectID();
D r_or = entry.getCoveringRadius();
- D d1 = o_p != null ? distanceQuery.distance(o_p, q) : getDistanceFactory().nullDistance();
- D d2 = o_p != null ? entry.getParentDistance() : getDistanceFactory().nullDistance();
+ D d1 = o_p != null ? distanceQuery.distance(o_p, q) : distanceQuery.nullDistance();
+ D d2 = o_p != null ? entry.getParentDistance() : distanceQuery.nullDistance();
// o_p != null ? distanceFunction.distance(o_r, o_p) :/ distanceFunction.nullDistance();
D diff = d1.compareTo(d2) > 0 ? d1.minus(d2) : d2.minus(d1);
@@ -104,8 +104,8 @@ public class MetricalIndexRangeQuery<O, D extends Distance<D>> extends AbstractD
MTreeEntry<D> entry = node.getEntry(i);
DBID o_j = entry.getRoutingObjectID();
- D d1 = o_p != null ? distanceQuery.distance(o_p, q) : getDistanceFactory().nullDistance();
- D d2 = o_p != null ? distanceQuery.distance(o_j, o_p) : getDistanceFactory().nullDistance();
+ D d1 = o_p != null ? distanceQuery.distance(o_p, q) : distanceQuery.nullDistance();
+ D d2 = o_p != null ? distanceQuery.distance(o_j, o_p) : distanceQuery.nullDistance();
D diff = d1.compareTo(d2) > 0 ? d1.minus(d2) : d2.minus(d1);
@@ -138,8 +138,8 @@ public class MetricalIndexRangeQuery<O, D extends Distance<D>> extends AbstractD
DBID o_r = entry.getRoutingObjectID();
D r_or = entry.getCoveringRadius();
- D d1 = o_p != null ? distanceQuery.distance(o_p, q) : getDistanceFactory().nullDistance();
- D d2 = o_p != null ? entry.getParentDistance() : getDistanceFactory().nullDistance();
+ D d1 = o_p != null ? distanceQuery.distance(o_p, q) : distanceQuery.nullDistance();
+ D d2 = o_p != null ? entry.getParentDistance() : distanceQuery.nullDistance();
// o_p != null ? distanceFunction.distance(o_r, o_p) : distanceFunction.nullDistance();
D diff = d1.compareTo(d2) > 0 ? d1.minus(d2) : d2.minus(d1);
@@ -160,8 +160,8 @@ public class MetricalIndexRangeQuery<O, D extends Distance<D>> extends AbstractD
MTreeEntry<D> entry = node.getEntry(i);
DBID o_j = entry.getRoutingObjectID();
- D d1 = o_p != null ? distanceQuery.distance(o_p, q) : getDistanceFactory().nullDistance();
- D d2 = o_p != null ? distanceQuery.distance(o_j, o_p) : getDistanceFactory().nullDistance();
+ D d1 = o_p != null ? distanceQuery.distance(o_p, q) : distanceQuery.nullDistance();
+ D d2 = o_p != null ? distanceQuery.distance(o_j, o_p) : distanceQuery.nullDistance();
D diff = d1.compareTo(d2) > 0 ? d1.minus(d2) : d2.minus(d1);
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 38641128..370f26ad 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) 2011
+ Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/package-info.java
index 9fa70aab..fa7e6248 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) 2011
+Copyright (C) 2012
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/Assignments.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/Assignments.java
index c639f37e..5cb6c794 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/split/Assignments.java
@@ -4,7 +4,7 @@ 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) 2011
+ Copyright (C) 2012
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/MLBDistSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/MLBDistSplit.java
index dc322960..f4da4a1a 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/split/MLBDistSplit.java
@@ -4,7 +4,7 @@ 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) 2011
+ Copyright (C) 2012
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/MRadSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/MRadSplit.java
index c78367ed..5d6c985c 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/split/MRadSplit.java
@@ -4,7 +4,7 @@ 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) 2011
+ Copyright (C) 2012
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
index a5fcb349..f9a3c248 100644
--- 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
@@ -4,7 +4,7 @@ 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) 2011
+ Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/split/package-info.java
index 66ead37c..ed13ae73 100644
--- 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
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2011
+Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/package-info.java
index bcfbd4a1..2ca4396c 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) 2011
+Copyright (C) 2012
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 40adc7c4..3ba785f2 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) 2011
+Copyright (C) 2012
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 7b1b4a03..699c8290 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) 2011
+ Copyright (C) 2012
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/GenericDistanceSearchCandidate.java b/src/de/lmu/ifi/dbs/elki/index/tree/query/GenericDistanceSearchCandidate.java
index 7338bdd1..dd764990 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) 2011
+ Copyright (C) 2012
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/GenericMTreeDistanceSearchCandidate.java b/src/de/lmu/ifi/dbs/elki/index/tree/query/GenericMTreeDistanceSearchCandidate.java
index b9d8ef46..e7fc0b19 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) 2011
+ Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/query/package-info.java
index 2eb1d284..5b8f56f6 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) 2011
+Copyright (C) 2012
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 cf83a1a2..9833e5b5 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,7 +27,8 @@ import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
-import de.lmu.ifi.dbs.elki.data.HyperBoundingBox;
+import de.lmu.ifi.dbs.elki.data.ModifiableHyperBoundingBox;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
import de.lmu.ifi.dbs.elki.index.tree.AbstractDirectoryEntry;
/**
@@ -45,7 +46,7 @@ public class SpatialDirectoryEntry extends AbstractDirectoryEntry implements Spa
/**
* The minimum bounding rectangle of the underlying spatial node.
*/
- private HyperBoundingBox mbr;
+ private ModifiableHyperBoundingBox mbr;
/**
* Empty constructor for serialization purposes.
@@ -60,7 +61,7 @@ public class SpatialDirectoryEntry extends AbstractDirectoryEntry implements Spa
* @param id the unique id of the underlying spatial node
* @param mbr the minimum bounding rectangle of the underlying spatial node
*/
- public SpatialDirectoryEntry(int id, HyperBoundingBox mbr) {
+ public SpatialDirectoryEntry(int id, ModifiableHyperBoundingBox mbr) {
super(id);
this.mbr = mbr;
}
@@ -89,11 +90,20 @@ public class SpatialDirectoryEntry extends AbstractDirectoryEntry implements Spa
}
/**
+ * Test whether this entry already has an MBR.
+ *
+ * @return True when an MBR exists.
+ */
+ public boolean hasMBR() {
+ return (this.mbr != null);
+ }
+
+ /**
* Sets the MBR of this entry.
*
* @param mbr the MBR to be set
*/
- public void setMBR(HyperBoundingBox mbr) {
+ public void setMBR(ModifiableHyperBoundingBox mbr) {
this.mbr = mbr;
}
@@ -122,7 +132,17 @@ public class SpatialDirectoryEntry extends AbstractDirectoryEntry implements Spa
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
super.readExternal(in);
- this.mbr = new HyperBoundingBox();
+ this.mbr = new ModifiableHyperBoundingBox();
this.mbr.readExternal(in);
}
-}
+
+ /**
+ * Extend the MBR of this node.
+ *
+ * @param responsibleMBR
+ * @return true when the MBR changed
+ */
+ public boolean extendMBR(SpatialComparable responsibleMBR) {
+ return this.mbr.extend(responsibleMBR);
+ }
+} \ No newline at end of file
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 ffc96b40..c50a5ebf 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) 2011
+ Copyright (C) 2012
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 1d0094dd..3b9eaa6b 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) 2011
+ Copyright (C) 2012
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 2d0dd857..8bf25766 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) 2011
+ Copyright (C) 2012
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.spatial;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
import de.lmu.ifi.dbs.elki.index.tree.Node;
/**
@@ -38,6 +37,6 @@ import de.lmu.ifi.dbs.elki.index.tree.Node;
* @param <N> Self reference
* @param <E> Entry type
*/
-public interface SpatialNode<N extends SpatialNode<N, E>, E extends SpatialEntry> extends Node<E>, SpatialComparable {
+public interface SpatialNode<N extends SpatialNode<N, E>, E extends SpatialEntry> extends Node<E> {
// No additional methods.
-}
+} \ No newline at end of file
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 57fb6932..f29680e7 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) 2011
+ Copyright (C) 2012
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 c3cd20d3..0911a9c0 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) 2011
+ Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/package-info.java
index f7a747fe..fb5c67ee 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) 2011
+Copyright (C) 2012
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 4fafe1bb..e50e0cb4 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,22 +27,17 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
+import java.util.BitSet;
import java.util.List;
-import java.util.Map;
import java.util.Stack;
import de.lmu.ifi.dbs.elki.data.HyperBoundingBox;
+import de.lmu.ifi.dbs.elki.data.ModifiableHyperBoundingBox;
import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil;
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.distancefunction.EuclideanDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
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.LeafEntry;
import de.lmu.ifi.dbs.elki.index.tree.TreeIndexHeader;
@@ -51,16 +46,17 @@ 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.bulk.BulkSplit;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.Enlargement;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.InsertionStrategy;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.LeastOverlapInsertionStrategy;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.SplitStrategy;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.TopologicalSplitter;
+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.persistent.PageFile;
import de.lmu.ifi.dbs.elki.persistent.PageFileUtil;
import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
-import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
/**
* Abstract superclass for index structures based on a R*-Tree.
@@ -87,13 +83,6 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
protected final static boolean extraIntegrityChecks = false;
/**
- * Contains a boolean for each level of this R*-Tree that indicates if there
- * was already a reinsert operation in this level during the current insert /
- * delete operation.
- */
- protected final Map<Integer, Boolean> reinsertions = new HashMap<Integer, Boolean>();
-
- /**
* The height of this R*-Tree.
*/
protected int height;
@@ -116,33 +105,88 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
/**
* The split strategy
*/
- protected SplitStrategy<? super E> nodeSplitter = new TopologicalSplitter();
+ protected SplitStrategy nodeSplitter = TopologicalSplitter.STATIC;
/**
* The insertion strategy to use
*/
- protected final InsertionStrategy insertionStrategy;
+ protected InsertionStrategy insertionStrategy = LeastOverlapInsertionStrategy.STATIC;
+
+ /**
+ * Overflow treatment
+ */
+ protected OverflowTreatment overflowTreatment = LimitedReinsertOverflowTreatment.RSTAR_OVERFLOW;
+
+ /**
+ * Relative minimum fill
+ */
+ protected double relativeMinFill = 0.4;
/**
* Constructor
*
* @param pagefile Page file
- * @param bulkSplitter bulk load strategy
- * @param insertionStrategy the strategy for finding the insertion candidate.
*/
- public AbstractRStarTree(PageFile<N> pagefile, BulkSplit bulkSplitter, InsertionStrategy insertionStrategy) {
+ public AbstractRStarTree(PageFile<N> pagefile) {
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("No insertion strategy given - falling back to " + LeastOverlapInsertionStrategy.class.getSimpleName());
- this.insertionStrategy = new LeastOverlapInsertionStrategy();
+ 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;
+ }
+
+ /**
* Returns the path to the leaf entry in the specified subtree that represents
* the data object with the specified mbr and id.
*
@@ -181,7 +225,7 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
if(!initialized) {
initialize(leaf);
}
- reinsertions.clear();
+ overflowTreatment.reinitialize();
preInsert(leaf);
insertLeafEntry(leaf);
@@ -200,7 +244,7 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
IndexTreePath<E> subtree = choosePath(getRootPath(), entry, 1);
if(getLogger().isDebugging()) {
- getLogger().debugFine("insertion-subtree " + subtree + "\n");
+ getLogger().debugFine("insertion-subtree " + subtree);
}
N parent = getNode(subtree.getLastPathComponent().getEntry());
@@ -257,7 +301,7 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
N node = stack.pop();
if(node.isLeaf()) {
for(int i = 0; i < node.getNumEntries(); i++) {
- reinsertions.clear();
+ overflowTreatment.reinitialize(); // Intended?
this.insertLeafEntry(node.getEntry(i));
}
}
@@ -315,7 +359,7 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
int cap = 0;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
- HyperBoundingBox hb = new HyperBoundingBox(new double[exampleLeaf.getDimensionality()], new double[exampleLeaf.getDimensionality()]);
+ ModifiableHyperBoundingBox hb = new ModifiableHyperBoundingBox(new double[exampleLeaf.getDimensionality()], new double[exampleLeaf.getDimensionality()]);
SpatialDirectoryEntry sl = new SpatialDirectoryEntry(0, hb);
while(baos.size() <= getPageSize()) {
sl.writeExternal(oos);
@@ -337,7 +381,7 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
}
// minimum entries per directory node
- dirMinimum = (int) Math.round((dirCapacity - 1) * 0.4);
+ dirMinimum = (int) Math.round((dirCapacity - 1) * relativeMinFill);
if(dirMinimum < 2) {
dirMinimum = 2;
}
@@ -351,7 +395,7 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
}
// minimum entries per leaf node
- leafMinimum = (int) Math.round((leafCapacity - 1) * 0.4);
+ leafMinimum = (int) Math.round((leafCapacity - 1) * relativeMinFill);
if(leafMinimum < 2) {
leafMinimum = 2;
}
@@ -376,33 +420,31 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
* @param objects the objects to be inserted
* @return the array of leaf nodes containing the objects
*/
- protected List<N> createBulkLeafNodes(List<E> objects) {
+ protected List<E> createBulkLeafNodes(List<E> objects) {
int minEntries = leafMinimum;
int maxEntries = leafCapacity - 1;
-
- ArrayList<N> result = new ArrayList<N>();
+
+ ArrayList<E> result = new ArrayList<E>();
List<List<E>> partitions = bulkSplitter.partition(objects, minEntries, maxEntries);
-
+
for(List<E> partition : partitions) {
// create leaf node
N leafNode = createNewLeafNode();
- result.add(leafNode);
-
+
// insert data
for(E o : partition) {
leafNode.addLeafEntry(o);
}
-
// write to file
writeNode(leafNode);
-
+
+ result.add(createNewDirectoryEntry(leafNode));
+
if(getLogger().isDebugging()) {
- StringBuffer msg = new StringBuffer();
- msg.append("pageNo ").append(leafNode.getPageID()).append("\n");
- getLogger().debugFine(msg.toString());
+ getLogger().debugFine("Created leaf page "+leafNode.getPageID());
}
}
-
+
if(getLogger().isDebugging()) {
getLogger().debugFine("numDataPages = " + result.size());
}
@@ -441,13 +483,6 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
abstract protected int computeHeight();
/**
- * Clears the reinsertions.
- */
- protected void clearReinsertions() {
- reinsertions.clear();
- }
-
- /**
* Returns true if in the specified node an overflow occurred, false
* otherwise.
*
@@ -486,7 +521,7 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
protected IndexTreePath<E> createNewRoot(final N oldRoot, final N newNode) {
N root = createNewDirectoryNode();
writeNode(root);
-
+
// switch the ids
oldRoot.setPageID(root.getPageID());
if(!oldRoot.isLeaf()) {
@@ -495,24 +530,24 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
writeNode(node);
}
}
-
+
root.setPageID(getRootID());
E oldRootEntry = createNewDirectoryEntry(oldRoot);
E newNodeEntry = createNewDirectoryEntry(newNode);
root.addDirectoryEntry(oldRootEntry);
root.addDirectoryEntry(newNodeEntry);
-
+
writeNode(root);
writeNode(oldRoot);
writeNode(newNode);
if(getLogger().isDebugging()) {
String msg = "Create new Root: ID=" + root.getPageID();
- msg += "\nchild1 " + oldRoot + " " + new HyperBoundingBox(oldRoot) + " " + new HyperBoundingBox(oldRootEntry);
- msg += "\nchild2 " + newNode + " " + new HyperBoundingBox(newNode) + " " + new HyperBoundingBox(newNodeEntry);
+ msg += "\nchild1 " + oldRoot + " " + new HyperBoundingBox(oldRootEntry);
+ msg += "\nchild2 " + newNode + " " + new HyperBoundingBox(newNodeEntry);
msg += "\n";
getLogger().debugFine(msg);
}
-
+
return new IndexTreePath<E>(new TreeIndexPathComponent<E>(getRootEntry(), null));
}
@@ -591,10 +626,11 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
}
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);
// children are leafs
if(childNode.isLeaf()) {
if(height - subtree.getPathCount() == level) {
- TreeIndexPathComponent<E> comp = insertionStrategy.findInsertChild(node, mbr);
return subtree.pathByAddingChild(comp);
}
else {
@@ -603,7 +639,7 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
}
// children are directory nodes
else {
- IndexTreePath<E> newSubtree = subtree.pathByAddingChild(getLeastEnlargement(node, mbr));
+ IndexTreePath<E> newSubtree = subtree.pathByAddingChild(comp);
// desired level is reached
if(height - subtree.getPathCount() == level) {
return newSubtree;
@@ -615,34 +651,6 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
}
/**
- * Returns the path information of the entry of the specified node with the
- * least enlargement if the given mbr would be inserted into.
- *
- * @param node the node which children have to be tested
- * @param mbr the mbr of the node to be inserted
- * @return the path information of the entry with the least enlargement if the
- * given mbr would be inserted into
- */
- private TreeIndexPathComponent<E> getLeastEnlargement(N node, SpatialComparable mbr) {
- Enlargement<E> min = null;
-
- for(int i = 0; i < node.getNumEntries(); i++) {
- E entry = node.getEntry(i);
- double volume = SpatialUtil.volume(entry);
- HyperBoundingBox newMBR = SpatialUtil.union(entry, mbr);
- double inc = SpatialUtil.volume(newMBR) - volume;
- Enlargement<E> enlargement = new Enlargement<E>(new TreeIndexPathComponent<E>(entry, i), volume, inc, 0);
-
- if(min == null || min.compareTo(enlargement) > 0) {
- min = enlargement;
- }
- }
-
- assert min != null;
- return min.getPathComponent();
- }
-
- /**
* Treatment of overflow in the specified node: if the node is not the root
* node and this is the first call of overflowTreatment in the given level
* during insertion the specified node will be reinserted, otherwise the node
@@ -654,23 +662,10 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
* reinsertion
*/
private N overflowTreatment(N node, IndexTreePath<E> path) {
- int level = height - path.getPathCount() + 1;
- Boolean reInsert = reinsertions.get(level);
-
- // there was still no reinsert operation at this level
- if(node.getPageID() != 0 && (reInsert == null || !reInsert)) {
- reinsertions.put(level, true);
- if(getLogger().isDebugging()) {
- getLogger().debugFine("REINSERT " + reinsertions + "\n");
- }
- reInsert(node, level, path);
+ if(overflowTreatment.handleOverflow(this, node, path)) {
return null;
}
-
- // there was already a reinsert operation at this level
- else {
- return split(node);
- }
+ return split(node);
}
/**
@@ -682,7 +677,7 @@ 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;
- Pair<List<E>, List<E>> split = nodeSplitter.split(node.getEntries(), minimum);
+ BitSet split = nodeSplitter.split(node, NodeArrayAdapter.STATIC, minimum);
// New node
final N newNode;
@@ -693,22 +688,12 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
newNode = createNewDirectoryNode();
}
// do the split
- node.deleteAllEntries();
- node.splitTo(newNode, split.first, split.second);
+ node.splitByMask(newNode, split);
// write changes to file
writeNode(node);
writeNode(newNode);
- // if(getLogger().isDebugging()) {
- // StringBuffer msg = new StringBuffer();
- // msg.append("Split Node ").append(node.getPageID()).append(" (").append(getClass()).append(")\n");
- // msg.append(" splitAxis ").append(split.getSplitAxis()).append("\n");
- // msg.append(" splitPoint ").append(split.getSplitPoint()).append("\n");
- // msg.append(" newNode ").append(newNode.getPageID()).append("\n");
- // getLogger().debugFine(msg.toString());
- // }
-
return newNode;
}
@@ -716,29 +701,20 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
* Reinserts the specified node at the specified level.
*
* @param node the node to be reinserted
- * @param level the level of the node
* @param path the path to the node
+ * @param offs the nodes indexes to reinsert
*/
- @SuppressWarnings("unchecked")
- protected void reInsert(N node, int level, IndexTreePath<E> path) {
- EuclideanDistanceFunction distFunction = EuclideanDistanceFunction.STATIC;
- DistanceEntry<DoubleDistance, E>[] reInsertEntries = new DistanceEntry[node.getNumEntries()];
+ public void reInsert(N node, IndexTreePath<E> path, int[] offs) {
+ final int level = height - (path.getPathCount() - 1);
- // compute the center distances of entries to the node and sort it
- // in decreasing order to their distances
- for(int i = 0; i < node.getNumEntries(); i++) {
- E entry = node.getEntry(i);
- DoubleDistance dist = distFunction.centerDistance(node, entry);
- reInsertEntries[i] = new DistanceEntry<DoubleDistance, E>(entry, dist, i);
+ BitSet remove = new BitSet();
+ List<E> reInsertEntries = new ArrayList<E>(offs.length);
+ for(int i = 0; i < offs.length; i++) {
+ reInsertEntries.add(node.getEntry(offs[i]));
+ remove.set(offs[i]);
}
- Arrays.sort(reInsertEntries, Collections.reverseOrder());
-
- // define, how many entries will be reinserted
- int start = (int) (0.3 * node.getNumEntries());
-
- // initialize the reinsertion operation: move the remaining entries
- // forward
- node.initReInsert(start, reInsertEntries);
+ // Remove the entries we reinsert
+ node.removeMask(remove);
writeNode(node);
// and adapt the mbrs
@@ -747,26 +723,30 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
while(childPath.getParentPath() != null) {
N parent = getNode(childPath.getParentPath().getLastPathComponent().getEntry());
int indexOfChild = childPath.getLastPathComponent().getIndex();
- child.adjustEntry(parent.getEntry(indexOfChild));
- writeNode(parent);
- childPath = childPath.getParentPath();
- child = parent;
+ if(child.adjustEntry(parent.getEntry(indexOfChild))) {
+ writeNode(parent);
+ childPath = childPath.getParentPath();
+ child = parent;
+ }
+ else {
+ break;
+ // TODO: stop writing when MBR didn't change!
+ }
}
// reinsert the first entries
- for(int i = 0; i < start; i++) {
- DistanceEntry<DoubleDistance, E> re = reInsertEntries[i];
+ for(E entry : reInsertEntries) {
if(node.isLeaf()) {
if(getLogger().isDebugging()) {
- getLogger().debugFine("reinsert " + re.getEntry());
+ getLogger().debug("reinsert " + entry);
}
- insertLeafEntry(re.getEntry());
+ insertLeafEntry(entry);
}
else {
if(getLogger().isDebugging()) {
- getLogger().debugFine("reinsert " + re.getEntry() + " at " + level);
+ getLogger().debug("reinsert " + entry + " at " + level);
}
- insertDirectoryEntry(re.getEntry(), level);
+ insertDirectoryEntry(entry, level);
}
}
}
@@ -778,7 +758,7 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
*/
protected void adjustTree(IndexTreePath<E> subtree) {
if(getLogger().isDebugging()) {
- getLogger().debugFine("Adjust tree " + subtree + "\n");
+ getLogger().debugFine("Adjust tree " + subtree);
}
// get the root of the subtree
@@ -826,11 +806,13 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
if(!isRoot(node)) {
N parent = getNode(subtree.getParentPath().getLastPathComponent().getEntry());
E entry = parent.getEntry(subtree.getLastPathComponent().getIndex());
- lastInsertedEntry = node.adjustEntryIncremental(entry, lastInsertedEntry);
- // node.adjustEntry(parent.getEntry(index));
- // write changes in parent to file
- writeNode(parent);
- adjustTree(subtree.getParentPath());
+ boolean changed = node.adjustEntryIncremental(entry, lastInsertedEntry);
+ if(changed) {
+ // node.adjustEntry(parent.getEntry(index));
+ // write changes in parent to file
+ writeNode(parent);
+ adjustTree(subtree.getParentPath());
+ }
}
// root level is reached
else {
@@ -896,12 +878,12 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
@Override
public final List<E> getLeaves() {
List<E> result = new ArrayList<E>();
-
+
if(height == 1) {
result.add(getRootEntry());
return result;
}
-
+
getLeafNodes(getRoot(), result, height);
return result;
}
@@ -949,11 +931,11 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
int leafNodes = 0;
int objects = 0;
int levels = 0;
-
+
if(initialized) {
N node = getRoot();
- int dim = node.getDimensionality();
-
+ int dim = getRootEntry().getDimensionality();
+
while(!node.isLeaf()) {
if(node.getNumEntries() > 0) {
E entry = node.getEntry(0);
@@ -961,7 +943,7 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
levels++;
}
}
-
+
BreadthFirstEnumeration<N, E> enumeration = new BreadthFirstEnumeration<N, E>(this, getRootPath());
while(enumeration.hasMoreElements()) {
IndexTreePath<E> indexPath = enumeration.nextElement();
@@ -988,7 +970,7 @@ public abstract class AbstractRStarTree<N extends AbstractRStarTreeNode<N, E>, E
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 5a0b9975..e2bb3abb 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,12 +29,18 @@ 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.tree.spatial.SpatialEntry;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.bulk.BulkSplit;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.InsertionStrategy;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.LeastOverlapInsertionStrategy;
+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;
+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.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.utilities.optionhandling.OptionID;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.IntervalConstraint;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.IntervalConstraint.IntervalBoundary;
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.DoubleParameter;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter;
/**
@@ -57,11 +63,26 @@ public abstract class AbstractRStarTreeFactory<O extends NumberVector<O, ?>, N e
public static OptionID INSERTION_STRATEGY_ID = OptionID.getOrCreateOptionID("rtree.insertionstrategy", "The strategy to use for object insertion.");
/**
+ * Split strategy parameter. Optional.
+ */
+ public static OptionID SPLIT_STRATEGY_ID = OptionID.getOrCreateOptionID("rtree.splitstrategy", "The strategy to use for node splitting.");
+
+ /**
* Parameter for bulk strategy
*/
public static final OptionID BULK_SPLIT_ID = OptionID.getOrCreateOptionID("spatial.bulkstrategy", "The class to perform the bulk split with.");
/**
+ * Parameter for the relative minimum fill.
+ */
+ public static final OptionID MINIMUM_FILL_ID = OptionID.getOrCreateOptionID("rtree.minimum-fill", "Minimum relative fill required for data pages.");
+
+ /**
+ * Overflow treatment.
+ */
+ public static OptionID OVERFLOW_STRATEGY_ID = OptionID.getOrCreateOptionID("rtree.overflowtreatment", "The strategy to use for handling overflows.");
+
+ /**
* Strategy to find the insertion node with.
*/
protected InsertionStrategy insertionStrategy;
@@ -72,6 +93,21 @@ public abstract class AbstractRStarTreeFactory<O extends NumberVector<O, ?>, N e
protected BulkSplit bulkSplitter;
/**
+ * The strategy for splitting nodes
+ */
+ protected SplitStrategy nodeSplitter;
+
+ /**
+ * Overflow treatment strategy
+ */
+ protected OverflowTreatment overflowTreatment;
+
+ /**
+ * Relative minimum fill
+ */
+ protected double minimumFill;
+
+ /**
* Constructor.
*
* @param fileName
@@ -79,11 +115,17 @@ public abstract class AbstractRStarTreeFactory<O extends NumberVector<O, ?>, N e
* @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
*/
- public AbstractRStarTreeFactory(String fileName, int pageSize, long cacheSize, BulkSplit bulkSplitter, InsertionStrategy insertionStrategy) {
+ 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;
}
@Override
@@ -99,18 +141,51 @@ public abstract class AbstractRStarTreeFactory<O extends NumberVector<O, ?>, N e
* @apiviz.exclude
*/
public static abstract class Parameterizer<O extends NumberVector<O, ?>> extends TreeIndexFactory.Parameterizer<O> {
+ /**
+ * Insertion strategy
+ */
+ protected InsertionStrategy insertionStrategy = null;
+
+ /**
+ * The strategy for splitting nodes
+ */
+ protected SplitStrategy nodeSplitter = null;
+
+ /**
+ * Bulk loading strategy
+ */
protected BulkSplit bulkSplitter = null;
- protected InsertionStrategy insertionStrategy = null;
+ /**
+ * Overflow treatment strategy
+ */
+ protected OverflowTreatment overflowTreatment = null;
+
+ /**
+ * Relative minimum fill
+ */
+ protected double minimumFill;
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
- configBulkLoad(config);
- ClassParameter<InsertionStrategy> insertionStrategyP = new ClassParameter<InsertionStrategy>(INSERTION_STRATEGY_ID, InsertionStrategy.class, LeastOverlapInsertionStrategy.class);
+ ObjectParameter<InsertionStrategy> insertionStrategyP = new ObjectParameter<InsertionStrategy>(INSERTION_STRATEGY_ID, InsertionStrategy.class, CombinedInsertionStrategy.class);
if(config.grab(insertionStrategyP)) {
insertionStrategy = insertionStrategyP.instantiateClass(config);
}
+ ObjectParameter<SplitStrategy> splitStrategyP = new ObjectParameter<SplitStrategy>(SPLIT_STRATEGY_ID, SplitStrategy.class, TopologicalSplitter.class);
+ if(config.grab(splitStrategyP)) {
+ nodeSplitter = splitStrategyP.instantiateClass(config);
+ }
+ DoubleParameter minimumFillP = new DoubleParameter(MINIMUM_FILL_ID, new IntervalConstraint(0.0, IntervalBoundary.OPEN, 0.5, IntervalBoundary.OPEN), 0.4);
+ if (config.grab(minimumFillP)) {
+ minimumFill = minimumFillP.getValue();
+ }
+ ObjectParameter<OverflowTreatment> overflowP = new ObjectParameter<OverflowTreatment>(OVERFLOW_STRATEGY_ID, OverflowTreatment.class, LimitedReinsertOverflowTreatment.class);
+ if(config.grab(overflowP)) {
+ overflowTreatment = overflowP.instantiateClass(config);
+ }
+ configBulkLoad(config);
}
/**
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 330d5aa7..46e3003e 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,11 +29,10 @@ import java.io.ObjectOutput;
import java.util.logging.Logger;
import de.lmu.ifi.dbs.elki.data.HyperBoundingBox;
+import de.lmu.ifi.dbs.elki.data.ModifiableHyperBoundingBox;
import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.index.tree.AbstractNode;
-import de.lmu.ifi.dbs.elki.index.tree.DistanceEntry;
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.SpatialNode;
@@ -67,56 +66,22 @@ public abstract class AbstractRStarTreeNode<N extends AbstractRStarTreeNode<N, E
super(capacity, isLeaf, eclass);
}
- @Override
- public double getMin(int dimension) {
- double min = getEntry(0).getMin(dimension);
- for(int i = 1; i < getNumEntries(); i++) {
- min = Math.min(min, getEntry(i).getMin(dimension));
- }
- return min;
- }
-
- @Override
- public double getMax(int dimension) {
- double max = getEntry(0).getMax(dimension);
- for(int i = 1; i < getNumEntries(); i++) {
- max = Math.min(max, getEntry(i).getMax(dimension));
- }
- return max;
- }
-
/**
* Recomputing the MBR is rather expensive.
*
* @return MBR
*/
- public HyperBoundingBox computeMBR() {
+ public ModifiableHyperBoundingBox computeMBR() {
E firstEntry = getEntry(0);
if(firstEntry == null) {
return null;
}
- int dim = firstEntry.getDimensionality();
// Note: we deliberately get a cloned copy here, since we will modify it.
- double[] min = SpatialUtil.getMin(firstEntry);
- double[] max = SpatialUtil.getMax(firstEntry);
-
- for(int i = 1; i < getNumEntries(); i++) {
- SpatialComparable mbr = getEntry(i);
- for(int d = 1; d <= dim; d++) {
- if(min[d - 1] > mbr.getMin(d)) {
- min[d - 1] = mbr.getMin(d);
- }
- if(max[d - 1] < mbr.getMax(d)) {
- max[d - 1] = mbr.getMax(d);
- }
- }
+ ModifiableHyperBoundingBox mbr = new ModifiableHyperBoundingBox(firstEntry);
+ for(int i = 1; i < numEntries; i++) {
+ mbr.extend(getEntry(i));
}
- return new HyperBoundingBox(min, max);
- }
-
- @Override
- public int getDimensionality() {
- return getEntry(0).getDimensionality();
+ return mbr;
}
/**
@@ -124,8 +89,31 @@ public abstract class AbstractRStarTreeNode<N extends AbstractRStarTreeNode<N, E
*
* @param entry the entry representing this node
*/
- public void adjustEntry(E entry) {
- ((SpatialDirectoryEntry)entry).setMBR(computeMBR());
+ public boolean adjustEntry(E entry) {
+ final SpatialDirectoryEntry se = (SpatialDirectoryEntry) entry;
+ final ModifiableHyperBoundingBox mbr = computeMBR();
+ boolean changed = false;
+ if(se.hasMBR()) {
+ final int dim = se.getDimensionality();
+ // Test for changes
+ for(int i = 1; i <= dim; i++) {
+ if(Math.abs(se.getMin(i) - mbr.getMin(i)) > Float.MIN_NORMAL) {
+ changed = true;
+ break;
+ }
+ if(Math.abs(se.getMax(i) - mbr.getMax(i)) > Float.MIN_NORMAL) {
+ changed = true;
+ break;
+ }
+ }
+ }
+ else { // No preexisting MBR.
+ changed = true;
+ }
+ if(changed) {
+ se.setMBR(mbr);
+ }
+ return changed;
}
/**
@@ -135,33 +123,10 @@ public abstract class AbstractRStarTreeNode<N extends AbstractRStarTreeNode<N, E
* @param entry the entry representing this node
* @param responsibleMBR the MBR of the object or node which is responsible
* for the call of the method
- * @return the MBR of the new Node
- */
- public E adjustEntryIncremental(E entry, SpatialComparable responsibleMBR) {
- ((SpatialDirectoryEntry)entry).setMBR(SpatialUtil.union(entry, responsibleMBR));
- return entry;
- }
-
- /**
- * * Initializes a reinsert operation. Deletes all entries in this node and
- * adds all entries from start index on to this node's children.
- *
- * @param start the start index of the entries that will be reinserted
- * @param reInsertEntries the array of entries to be reinserted
+ * @return true when the entry has changed
*/
- protected <D extends Distance<D>> void initReInsert(int start, DistanceEntry<D, E>[] reInsertEntries) {
- deleteAllEntries();
-
- if(isLeaf()) {
- for(int i = start; i < reInsertEntries.length; i++) {
- addLeafEntry(reInsertEntries[i].getEntry());
- }
- }
- else {
- for(int i = start; i < reInsertEntries.length; i++) {
- addDirectoryEntry(reInsertEntries[i].getEntry());
- }
- }
+ public boolean adjustEntryIncremental(E entry, SpatialComparable responsibleMBR) {
+ return ((SpatialDirectoryEntry) entry).extendMBR(responsibleMBR);
}
/**
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 20ae3826..41882ce2 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,13 +26,9 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants;
import java.util.ArrayList;
import java.util.List;
-import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
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.bulk.BulkSplit;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.InsertionStrategy;
import de.lmu.ifi.dbs.elki.persistent.PageFile;
-import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
/**
* Abstract superclass for all non-flat R*-Tree variants.
@@ -47,11 +43,9 @@ public abstract class NonFlatRStarTree<N extends AbstractRStarTreeNode<N, E>, E
* Constructor.
*
* @param pagefile Page file
- * @param bulkSplitter bulk load strategy
- * @param insertionStrategy the strategy to find the child to insert to
*/
- public NonFlatRStarTree(PageFile<N> pagefile, BulkSplit bulkSplitter, InsertionStrategy insertionStrategy) {
- super(pagefile, bulkSplitter, insertionStrategy);
+ public NonFlatRStarTree(PageFile<N> pagefile) {
+ super(pagefile);
}
/**
@@ -128,7 +122,7 @@ public abstract class NonFlatRStarTree<N extends AbstractRStarTreeNode<N, E>, E
StringBuffer msg = getLogger().isDebuggingFine() ? new StringBuffer() : null;
- // Tiny tree that fit into a single page
+ // Tiny tree that fits into a single page
if(spatialObjects.size() <= leafCapacity) {
N root = createNewLeafNode();
root.setPageID(getRootID());
@@ -146,7 +140,7 @@ public abstract class NonFlatRStarTree<N extends AbstractRStarTreeNode<N, E>, E
writeNode(root);
// create leaf nodes
- List<N> nodes = createBulkLeafNodes(spatialObjects);
+ List<E> nodes = createBulkLeafNodes(spatialObjects);
int numNodes = nodes.size();
if(msg != null) {
@@ -156,13 +150,13 @@ public abstract class NonFlatRStarTree<N extends AbstractRStarTreeNode<N, E>, E
// create directory nodes
while(nodes.size() > (dirCapacity - 1)) {
- nodes = createDirectoryNodes(nodes);
+ nodes = createBulkDirectoryNodes(nodes);
numNodes += nodes.size();
setHeight(getHeight() + 1);
}
// create root
- createRoot(root, new ArrayList<N>(nodes));
+ createRoot(root, nodes);
numNodes++;
setHeight(getHeight() + 1);
if(msg != null) {
@@ -182,30 +176,26 @@ public abstract class NonFlatRStarTree<N extends AbstractRStarTreeNode<N, E>, E
* @param nodes the nodes to be inserted
* @return the directory nodes containing the nodes
*/
- private List<N> createDirectoryNodes(List<N> nodes) {
+ private List<E> createBulkDirectoryNodes(List<E> nodes) {
int minEntries = dirMinimum;
int maxEntries = dirCapacity - 1;
- ArrayList<N> result = new ArrayList<N>();
- List<List<N>> partitions = bulkSplitter.partition(nodes, minEntries, maxEntries);
+ ArrayList<E> result = new ArrayList<E>();
+ List<List<E>> partitions = bulkSplitter.partition(nodes, minEntries, maxEntries);
- for(List<N> partition : partitions) {
+ for(List<E> partition : partitions) {
// create node
N dirNode = createNewDirectoryNode();
- writeNode(dirNode);
- result.add(dirNode);
-
// insert nodes
- for(N o : partition) {
- dirNode.addDirectoryEntry(createNewDirectoryEntry(o));
+ for(E o : partition) {
+ dirNode.addDirectoryEntry(o);
}
-
// write to file
writeNode(dirNode);
+
+ result.add(createNewDirectoryEntry(dirNode));
if(getLogger().isDebuggingFiner()) {
- StringBuffer msg = new StringBuffer();
- msg.append("\npageNo ").append(dirNode.getPageID());
- getLogger().debugFiner(msg.toString() + "\n");
+ getLogger().debugFiner("Directory page no: "+dirNode.getPageID());
}
}
@@ -221,17 +211,14 @@ public abstract class NonFlatRStarTree<N extends AbstractRStarTreeNode<N, E>, E
* @param objects the spatial objects to be inserted
* @return the root node
*/
- @SuppressWarnings("unchecked")
- private N createRoot(N root, List<? extends SpatialComparable> objects) {
+ private N createRoot(N root, List<E> objects) {
// insert data
- for(SpatialComparable object : objects) {
- if(object instanceof SpatialEntry) {
- E entry = (E) object;
+ for(E entry : objects) {
+ if (entry.isLeafEntry()) {
root.addLeafEntry(entry);
- throw new AbortException("Unexpected spatial comparable encountered.");
}
else {
- root.addDirectoryEntry(createNewDirectoryEntry((N) object));
+ root.addDirectoryEntry(entry);
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/bulk/ZCurveBulkSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/bulk/ZCurveBulkSplit.java
deleted file mode 100644
index 61e07960..00000000
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/bulk/ZCurveBulkSplit.java
+++ /dev/null
@@ -1,184 +0,0 @@
-package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.bulk;
-
-/*
- 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 java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
-import de.lmu.ifi.dbs.elki.logging.Logging;
-import de.lmu.ifi.dbs.elki.math.spacefillingcurves.ZCurve;
-
-/**
- * Bulk split that orders object by their Z curve position, then splits them
- * into pages accordingly.
- *
- * @author Elke Achtert
- */
-public class ZCurveBulkSplit extends AbstractBulkSplit {
- /**
- * Logger.
- */
- private static final Logging logger = Logging.getLogger(ZCurveBulkSplit.class);
-
- /**
- * Constructor
- */
- public ZCurveBulkSplit() {
- // Nothing to do
- }
-
- /**
- * Partitions the specified feature vectors
- *
- * @param spatialObjects the spatial objects to be partitioned
- * @param minEntries the minimum number of entries in a partition
- * @param maxEntries the maximum number of entries in a partition
- * @param <N> object type
- * @return the partition of the specified spatial objects
- */
- @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);
-
- // one dimensional special case
- if(spatialObjects.size() > 0 && spatialObjects.get(0).getDimensionality() == 1) {
- // TODO: move this Comparator into shared code.
- Collections.sort(objects, new Comparator<SpatialComparable>() {
- @Override
- public int compare(SpatialComparable o1, SpatialComparable o2) {
- return Double.compare(o1.getMin(1), o2.getMin(1));
- }
- });
-
- // build partitions
- // reinitialize array with correct size. Array will not use more space
- // than necessary.
- int numberPartitions = (int) Math.ceil(1d * spatialObjects.size() / maxEntries);
- partitions = new ArrayList<List<N>>(numberPartitions);
- List<N> onePartition = null;
- for(N o : objects) {
- if(onePartition == null || onePartition.size() >= maxEntries) {
- onePartition = new ArrayList<N>(maxEntries);
- partitions.add(onePartition);
- }
- onePartition.add(o);
- }
-
- // okay, check last partition for underfill
- // only check if there is more than 1 partition
- if(partitions.size() > 1) {
- List<N> last = partitions.get(partitions.size() - 1);
- List<N> nextToLast = partitions.get(partitions.size() - 2);
- while(last.size() < minEntries) {
- last.add(0, nextToLast.remove(nextToLast.size() - 1));
- }
- }
- return partitions;
- }
-
- // get z-values
- List<double[]> valuesList = new ArrayList<double[]>();
- for(SpatialComparable o : spatialObjects) {
- double[] values = new double[o.getDimensionality()];
- for(int d = 0; d < o.getDimensionality(); d++) {
- values[d] = o.getMin(d + 1);
- }
- valuesList.add(values);
- }
- if(logger.isDebugging()) {
- logger.debugFine(valuesList.toString());
- }
- List<byte[]> zValuesList = ZCurve.zValues(valuesList);
-
- // map z-values
- final Map<SpatialComparable, byte[]> zValues = new HashMap<SpatialComparable, byte[]>();
- for(int i = 0; i < spatialObjects.size(); i++) {
- SpatialComparable o = spatialObjects.get(i);
- byte[] zValue = zValuesList.get(i);
- zValues.put(o, zValue);
- }
-
- // create a comparator
- Comparator<SpatialComparable> comparator = new Comparator<SpatialComparable>() {
- @Override
- public int compare(SpatialComparable o1, SpatialComparable o2) {
- byte[] z1 = zValues.get(o1);
- byte[] z2 = zValues.get(o2);
-
- for(int i = 0; i < z1.length; i++) {
- byte z1_i = z1[i];
- byte z2_i = z2[i];
- if(z1_i < z2_i) {
- return -1;
- }
- else if(z1_i > z2_i) {
- return +1;
- }
- }
- if(o1 instanceof Comparable) {
- try {
- @SuppressWarnings("unchecked")
- final Comparable<Object> comparable = (Comparable<Object>) o1;
- return comparable.compareTo(o2);
- }
- catch(ClassCastException e) {
- // ignore
- }
- }
- return 0;
- }
- };
- Collections.sort(objects, comparator);
-
- // insert into partition
- while(objects.size() > 0) {
- StringBuffer msg = new StringBuffer();
- int splitPoint = chooseBulkSplitPoint(objects.size(), minEntries, maxEntries);
- List<N> partition1 = new ArrayList<N>();
- for(int i = 0; i < splitPoint; i++) {
- N o = objects.remove(0);
- partition1.add(o);
- }
- partitions.add(partition1);
-
- // copy array
- if(logger.isDebugging()) {
- msg.append("\ncurrent partition " + partition1);
- msg.append("\nremaining objects # ").append(objects.size());
- logger.debugFine(msg.toString());
- }
- }
-
- if(logger.isDebugging()) {
- logger.debugFine("partitions " + partitions);
- }
- return partitions;
- }
-}
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 a620ff62..10f25ec0 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) 2011
+ Copyright (C) 2012
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.spatial.rstarvariants.deliclu;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import de.lmu.ifi.dbs.elki.data.HyperBoundingBox;
+import de.lmu.ifi.dbs.elki.data.ModifiableHyperBoundingBox;
import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialDirectoryEntry;
/**
@@ -64,7 +64,7 @@ public class DeLiCluDirectoryEntry extends SpatialDirectoryEntry implements DeLi
* @param hasHandled indicates if this entry has handled nodes
* @param hasUnhandled indicates if this entry has unhandled nodes
*/
- public DeLiCluDirectoryEntry(int id, HyperBoundingBox mbr, boolean hasHandled, boolean hasUnhandled) {
+ public DeLiCluDirectoryEntry(int id, ModifiableHyperBoundingBox mbr, boolean hasHandled, boolean hasUnhandled) {
super(id, mbr);
this.hasHandled = hasHandled;
this.hasUnhandled = hasUnhandled;
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 3dbde624..19cf8a32 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) 2011
+ Copyright (C) 2012
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 b2ec9f9a..c7cfc493 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) 2011
+ Copyright (C) 2012
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 689507cb..bf993c01 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -88,13 +88,14 @@ public class DeLiCluNode extends AbstractRStarTreeNode<DeLiCluNode, DeLiCluEntry
}
@Override
- public void adjustEntry(DeLiCluEntry entry) {
- super.adjustEntry(entry);
+ public boolean adjustEntry(DeLiCluEntry entry) {
+ boolean changed = super.adjustEntry(entry);
// adjust hasHandled and hasUnhandled flag
boolean hasHandled = hasHandled();
boolean hasUnhandled = hasUnhandled();
entry.setHasHandled(hasHandled);
entry.setHasUnhandled(hasUnhandled);
+ return changed;
}
/**
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 ac873815..6f4f782d 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -31,8 +31,6 @@ 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.NonFlatRStarTree;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.bulk.BulkSplit;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.InsertionStrategy;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.persistent.PageFile;
@@ -61,11 +59,9 @@ public class DeLiCluTree extends NonFlatRStarTree<DeLiCluNode, DeLiCluEntry> {
* Constructor.
*
* @param pagefile Page file
- * @param bulkSplitter bulk load strategy
- * @param insertionStrategy the strategy to find the insertion child
*/
- public DeLiCluTree(PageFile<DeLiCluNode> pagefile, BulkSplit bulkSplitter, InsertionStrategy insertionStrategy) {
- super(pagefile, bulkSplitter, insertionStrategy);
+ public DeLiCluTree(PageFile<DeLiCluNode> pagefile) {
+ super(pagefile);
}
/**
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 dd9532a2..3f9627a9 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,8 +26,10 @@ 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.bulk.BulkSplit;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.InsertionStrategy;
+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.persistent.PageFile;
/**
@@ -49,15 +51,24 @@ public class DeLiCluTreeFactory<O extends NumberVector<O, ?>> extends AbstractRS
* @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
*/
- public DeLiCluTreeFactory(String fileName, int pageSize, long cacheSize, BulkSplit bulkSplitter, InsertionStrategy insertionStrategy) {
- super(fileName, pageSize, cacheSize, bulkSplitter, insertionStrategy);
+ 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);
}
@Override
public DeLiCluTreeIndex<O> instantiate(Relation<O> relation) {
PageFile<DeLiCluNode> pagefile = makePageFile(getNodeClass());
- return new DeLiCluTreeIndex<O>(relation, pagefile, bulkSplitter, insertionStrategy);
+ DeLiCluTreeIndex<O> index = new DeLiCluTreeIndex<O>(relation, pagefile);
+ index.setBulkStrategy(bulkSplitter);
+ index.setInsertionStrategy(insertionStrategy);
+ index.setNodeSplitStrategy(nodeSplitter);
+ index.setOverflowTreatment(overflowTreatment);
+ index.setMinimumFill(minimumFill);
+ return index;
}
protected Class<DeLiCluNode> getNodeClass() {
@@ -74,7 +85,7 @@ public class DeLiCluTreeFactory<O extends NumberVector<O, ?>> extends AbstractRS
public static class Parameterizer<O extends NumberVector<O, ?>> extends AbstractRStarTreeFactory.Parameterizer<O> {
@Override
protected DeLiCluTreeFactory<O> makeInstance() {
- return new DeLiCluTreeFactory<O>(fileName, pageSize, cacheSize, bulkSplitter, insertionStrategy);
+ return new DeLiCluTreeFactory<O>(fileName, pageSize, cacheSize, bulkSplitter, insertionStrategy, nodeSplitter, overflowTreatment, minimumFill);
}
}
} \ 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 062ddfb2..dd523ef8 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -39,9 +39,7 @@ 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.bulk.BulkSplit;
import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.query.RStarTreeUtil;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.InsertionStrategy;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.persistent.PageFile;
import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
@@ -64,11 +62,9 @@ public class DeLiCluTreeIndex<O extends NumberVector<?, ?>> extends DeLiCluTree
*
* @param relation Relation to index
* @param pagefile Page file
- * @param bulkSplitter bulk load strategy
- * @param insertionStrategy the strategy to find the insertion child
*/
- public DeLiCluTreeIndex(Relation<O> relation, PageFile<DeLiCluNode> pagefile, BulkSplit bulkSplitter, InsertionStrategy insertionStrategy) {
- super(pagefile, bulkSplitter, insertionStrategy);
+ public DeLiCluTreeIndex(Relation<O> relation, PageFile<DeLiCluNode> pagefile) {
+ super(pagefile);
this.relation = relation;
this.initialize();
}
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 8ebaab8c..b6c0af9b 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) 2011
+Copyright (C) 2012
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 e658ebf5..2774fbe1 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) 2011
+Copyright (C) 2012
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 7d39c08f..9174dc94 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -36,10 +36,10 @@ 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.ModifiableDBIDs;
-import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
import de.lmu.ifi.dbs.elki.database.query.DoubleDistanceResultPair;
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.KNNResult;
import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDoubleDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.index.tree.DirectoryEntry;
@@ -50,16 +50,24 @@ 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.KNNHeap;
-import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.UpdatableHeap;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
/**
* Instance of a KNN query for a particular spatial index.
*
+ * Reference:
+ * <p>
+ * G. R. Hjaltason, H. Samet<br />
+ * Ranking in spatial databases<br />
+ * In: 4th Symposium on Advances in Spatial Databases, SSD'95
+ * </p>
+ *
* @author Erich Schubert
*
* @apiviz.uses AbstractRStarTree
* @apiviz.uses SpatialPrimitiveDoubleDistanceFunction
*/
+@Reference(authors = "G. R. Hjaltason, H. Samet", title = "Ranking in spatial databases", booktitle = "Advances in Spatial Databases - 4th Symposium, SSD'95", url = "http://dx.doi.org/10.1007/3-540-60159-7_6")
public class DoubleDistanceRStarTreeKNNQuery<O extends SpatialComparable> extends AbstractDistanceKNNQuery<O, DoubleDistance> {
/**
* The index to use
@@ -93,7 +101,7 @@ public class DoubleDistanceRStarTreeKNNQuery<O extends SpatialComparable> extend
* @param knnList the knn list containing the result
*/
protected void doKNNQuery(O object, KNNHeap<DoubleDistance> knnList) {
- final Heap<DoubleDistanceSearchCandidate> pq = new UpdatableHeap<DoubleDistanceSearchCandidate>();
+ final Heap<DoubleDistanceSearchCandidate> pq = new Heap<DoubleDistanceSearchCandidate>(Math.min(knnList.getK() * 2, 20));
// push root
pq.add(new DoubleDistanceSearchCandidate(0.0, tree.getRootID()));
@@ -106,32 +114,42 @@ public class DoubleDistanceRStarTreeKNNQuery<O extends SpatialComparable> extend
if(pqNode.mindist > maxDist) {
return;
}
+ maxDist = expandNode(object, knnList, pq, maxDist, pqNode.nodeID);
+ }
+ }
- AbstractRStarTreeNode<?, ?> node = tree.getNode(pqNode.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++;
- if(distance <= maxDist) {
- knnList.add(new DoubleDistanceResultPair(distance, ((LeafEntry) entry).getDBID()));
- maxDist = knnList.getKNNDistance().doubleValue();
- }
+ private double expandNode(O object, KNNHeap<DoubleDistance> knnList, final Heap<DoubleDistanceSearchCandidate> pq, double maxDist, final Integer 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++;
+ if(distance <= maxDist) {
+ knnList.add(new DoubleDistanceResultPair(distance, ((LeafEntry) entry).getDBID()));
+ maxDist = knnList.getKNNDistance().doubleValue();
}
}
- // directory node
- else {
- for(int i = 0; i < node.getNumEntries(); i++) {
- SpatialEntry entry = node.getEntry(i);
- double distance = distanceFunction.doubleMinDist(entry, object);
- tree.distanceCalcs++;
+ }
+ // directory node
+ else {
+ for(int i = 0; i < node.getNumEntries(); i++) {
+ SpatialEntry entry = node.getEntry(i);
+ double distance = distanceFunction.doubleMinDist(entry, object);
+ tree.distanceCalcs++;
+ // Greedy expand, bypassing the queue
+ if(distance <= 0) {
+ expandNode(object, knnList, pq, maxDist, ((DirectoryEntry) entry).getPageID());
+ }
+ else {
if(distance <= maxDist) {
- pq.add(new DoubleDistanceSearchCandidate(distance, ((DirectoryEntry)entry).getPageID()));
+ pq.add(new DoubleDistanceSearchCandidate(distance, ((DirectoryEntry) entry).getPageID()));
}
}
}
}
+ return maxDist;
}
/**
@@ -161,7 +179,9 @@ public class DoubleDistanceRStarTreeKNNQuery<O extends SpatialComparable> extend
}
else {
ModifiableDBIDs ids = DBIDUtil.newArray(knnLists.size());
- ids.addAll(knnLists.keySet());
+ for(DBID id : knnLists.keySet()) {
+ ids.add(id);
+ }
List<DoubleDistanceEntry> entries = getSortedEntries(node, ids);
for(DoubleDistanceEntry distEntry : entries) {
double minDist = distEntry.distance;
@@ -171,7 +191,7 @@ public class DoubleDistanceRStarTreeKNNQuery<O extends SpatialComparable> extend
if(minDist <= knn_q_maxDist) {
SpatialEntry entry = distEntry.entry;
- AbstractRStarTreeNode<?, ?> child = tree.getNode(((DirectoryEntry)entry).getPageID());
+ AbstractRStarTreeNode<?, ?> child = tree.getNode(((DirectoryEntry) entry).getPageID());
batchNN(child, knnLists);
break;
}
@@ -210,7 +230,7 @@ public class DoubleDistanceRStarTreeKNNQuery<O extends SpatialComparable> extend
* Optimized double distance entry implementation.
*
* @author Erich Schubert
- *
+ *
* @apiviz.hidden
*/
class DoubleDistanceEntry implements Comparable<DoubleDistanceEntry> {
@@ -226,7 +246,7 @@ public class DoubleDistanceRStarTreeKNNQuery<O extends SpatialComparable> extend
/**
* Constructor.
- *
+ *
* @param entry Entry
* @param distance Distance
*/
@@ -242,23 +262,23 @@ public class DoubleDistanceRStarTreeKNNQuery<O extends SpatialComparable> extend
}
@Override
- public List<DistanceResultPair<DoubleDistance>> getKNNForObject(O obj, int k) {
+ public KNNResult<DoubleDistance> getKNNForObject(O obj, int k) {
if(k < 1) {
throw new IllegalArgumentException("At least one enumeration has to be requested!");
}
final KNNHeap<DoubleDistance> knnList = new KNNHeap<DoubleDistance>(k, distanceFunction.getDistanceFactory().infiniteDistance());
doKNNQuery(obj, knnList);
- return knnList.toSortedArrayList();
+ return knnList.toKNNList();
}
@Override
- public List<DistanceResultPair<DoubleDistance>> getKNNForDBID(DBID id, int k) {
+ public KNNResult<DoubleDistance> getKNNForDBID(DBID id, int k) {
return getKNNForObject(relation.get(id), k);
}
@Override
- public List<List<DistanceResultPair<DoubleDistance>>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) {
+ public List<KNNResult<DoubleDistance>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) {
if(k < 1) {
throw new IllegalArgumentException("At least one enumeration has to be requested!");
}
@@ -271,9 +291,9 @@ public class DoubleDistanceRStarTreeKNNQuery<O extends SpatialComparable> extend
batchNN(tree.getRoot(), knnLists);
- List<List<DistanceResultPair<DoubleDistance>>> result = new ArrayList<List<DistanceResultPair<DoubleDistance>>>();
+ List<KNNResult<DoubleDistance>> result = new ArrayList<KNNResult<DoubleDistance>>();
for(DBID id : ids) {
- result.add(knnLists.get(id).toSortedArrayList());
+ result.add(knnLists.get(id).toKNNList());
}
return result;
}
@@ -283,9 +303,4 @@ public class DoubleDistanceRStarTreeKNNQuery<O extends SpatialComparable> extend
AbstractRStarTreeNode<?, ?> root = tree.getRoot();
batchNN(root, heaps);
}
-
- @Override
- public DoubleDistance getDistanceFactory() {
- return distanceQuery.getDistanceFactory();
- }
} \ No newline at end of file
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 96d1e8c5..069db6d4 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -41,16 +41,25 @@ 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.documentation.Reference;
/**
* Instance of a range query for a particular spatial index.
*
+ * Reference:
+ * <p>
+ * J. Kuan, P. Lewis<br />
+ * Fast k nearest neighbour search for R-tree family<br />
+ * In Proc. Int. Conf Information, Communications and Signal Processing, ICICS
+ * 1997
+ * </p>
+ *
* @author Erich Schubert
*
* @apiviz.uses AbstractRStarTree
* @apiviz.uses SpatialPrimitiveDoubleDistanceFunction
*/
-//TODO: add bulk range queries.
+@Reference(authors = "J. Kuan, P. Lewis", title = "Fast k nearest neighbour search for R-tree family", booktitle = "Proc. Int. Conf Information, Communications and Signal Processing, ICICS 1997", url = "http://dx.doi.org/10.1109/ICICS.1997.652114")
public class DoubleDistanceRStarTreeRangeQuery<O extends SpatialComparable> extends AbstractDistanceRangeQuery<O, DoubleDistance> {
/**
* The index to use
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 be3ed994..5129f5ca 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -36,9 +36,9 @@ 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.ModifiableDBIDs;
-import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
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.database.query.knn.KNNResult;
import de.lmu.ifi.dbs.elki.distance.DistanceUtil;
import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
@@ -51,16 +51,24 @@ 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.KNNHeap;
-import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.UpdatableHeap;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
/**
* Instance of a KNN query for a particular spatial index.
*
+ * Reference:
+ * <p>
+ * G. R. Hjaltason, H. Samet<br />
+ * Ranking in spatial databases<br />
+ * In: 4th Symposium on Advances in Spatial Databases, SSD'95
+ * </p>
+ *
* @author Erich Schubert
*
* @apiviz.uses AbstractRStarTree
* @apiviz.uses SpatialPrimitiveDistanceFunction
*/
+@Reference(authors = "G. R. Hjaltason, H. Samet", title = "Ranking in spatial databases", booktitle = "Advances in Spatial Databases - 4th Symposium, SSD'95", url = "http://dx.doi.org/10.1007/3-540-60159-7_6")
public class GenericRStarTreeKNNQuery<O extends SpatialComparable, D extends Distance<D>> extends AbstractDistanceKNNQuery<O, D> {
/**
* The index to use
@@ -93,7 +101,7 @@ 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 UpdatableHeap<GenericDistanceSearchCandidate<D>>();
+ final Heap<GenericDistanceSearchCandidate<D>> pq = new Heap<GenericDistanceSearchCandidate<D>>(Math.min(knnList.getK() * 2, 20));
// push root
pq.add(new GenericDistanceSearchCandidate<D>(distanceFunction.getDistanceFactory().nullDistance(), tree.getRootID()));
@@ -106,32 +114,42 @@ public class GenericRStarTreeKNNQuery<O extends SpatialComparable, D extends Dis
if(pqNode.mindist.compareTo(maxDist) > 0) {
return;
}
+ maxDist = expandNode(object, knnList, pq, maxDist, pqNode.nodeID);
+ }
+ }
- AbstractRStarTreeNode<?, ?> node = tree.getNode(pqNode.nodeID);
- // data node
- 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) {
- knnList.add(distance, ((LeafEntry) entry).getDBID());
- maxDist = knnList.getKNNDistance();
- }
+ private D expandNode(O object, KNNHeap<D> knnList, final Heap<GenericDistanceSearchCandidate<D>> pq, D maxDist, final Integer nodeID) {
+ AbstractRStarTreeNode<?, ?> node = tree.getNode(nodeID);
+ // data node
+ 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) {
+ knnList.add(distance, ((LeafEntry) entry).getDBID());
+ maxDist = knnList.getKNNDistance();
}
}
- // directory node
- else {
- for(int i = 0; i < node.getNumEntries(); i++) {
- SpatialEntry entry = node.getEntry(i);
- D distance = distanceFunction.minDist(entry, object);
- tree.distanceCalcs++;
+ }
+ // directory node
+ else {
+ for(int i = 0; i < node.getNumEntries(); i++) {
+ SpatialEntry entry = node.getEntry(i);
+ D distance = distanceFunction.minDist(entry, object);
+ tree.distanceCalcs++;
+ // Greedy expand, bypassing the queue
+ 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()));
+ pq.add(new GenericDistanceSearchCandidate<D>(distance, ((DirectoryEntry) entry).getPageID()));
}
}
}
}
+ return maxDist;
}
/**
@@ -160,7 +178,9 @@ public class GenericRStarTreeKNNQuery<O extends SpatialComparable, D extends Dis
}
else {
ModifiableDBIDs ids = DBIDUtil.newArray(knnLists.size());
- ids.addAll(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();
@@ -170,7 +190,7 @@ public class GenericRStarTreeKNNQuery<O extends SpatialComparable, D extends Dis
if(minDist.compareTo(knn_q_maxDist) <= 0) {
SpatialEntry entry = distEntry.getEntry();
- AbstractRStarTreeNode<?, ?> child = tree.getNode(((DirectoryEntry)entry).getPageID());
+ AbstractRStarTreeNode<?, ?> child = tree.getNode(((DirectoryEntry) entry).getPageID());
batchNN(child, knnLists);
break;
}
@@ -211,23 +231,23 @@ public class GenericRStarTreeKNNQuery<O extends SpatialComparable, D extends Dis
}
@Override
- public List<DistanceResultPair<D>> getKNNForObject(O obj, int k) {
+ 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 = new KNNHeap<D>(k, distanceFunction.getDistanceFactory().infiniteDistance());
doKNNQuery(obj, knnList);
- return knnList.toSortedArrayList();
+ return knnList.toKNNList();
}
@Override
- public List<DistanceResultPair<D>> getKNNForDBID(DBID id, int k) {
+ public KNNResult<D> getKNNForDBID(DBID id, int k) {
return getKNNForObject(relation.get(id), k);
}
@Override
- public List<List<DistanceResultPair<D>>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) {
+ public List<KNNResult<D>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) {
if(k < 1) {
throw new IllegalArgumentException("At least one enumeration has to be requested!");
}
@@ -239,15 +259,10 @@ public class GenericRStarTreeKNNQuery<O extends SpatialComparable, D extends Dis
batchNN(tree.getRoot(), knnLists);
- List<List<DistanceResultPair<D>>> result = new ArrayList<List<DistanceResultPair<D>>>();
+ List<KNNResult<D>> result = new ArrayList<KNNResult<D>>();
for(DBID id : ids) {
- result.add(knnLists.get(id).toSortedArrayList());
+ result.add(knnLists.get(id).toKNNList());
}
return result;
}
-
- @Override
- public D getDistanceFactory() {
- return distanceQuery.getDistanceFactory();
- }
} \ 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 c4d68828..d2086cb1 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -41,16 +41,25 @@ 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.documentation.Reference;
/**
* Instance of a range query for a particular spatial index.
*
+ * Reference:
+ * <p>
+ * J. Kuan, P. Lewis<br />
+ * Fast k nearest neighbour search for R-tree family<br />
+ * In Proc. Int. Conf Information, Communications and Signal Processing, ICICS
+ * 1997
+ * </p>
+ *
* @author Erich Schubert
*
* @apiviz.uses AbstractRStarTree
* @apiviz.uses SpatialPrimitiveDistanceFunction
*/
-// TODO: add bulk range queries.
+@Reference(authors = "J. Kuan, P. Lewis", title = "Fast k nearest neighbour search for R-tree family", booktitle = "Proc. Int. Conf Information, Communications and Signal Processing, ICICS 1997", url = "http://dx.doi.org/10.1109/ICICS.1997.652114")
public class GenericRStarTreeRangeQuery<O extends SpatialComparable, D extends Distance<D>> extends AbstractDistanceRangeQuery<O, D> {
/**
* The index to use
@@ -69,7 +78,7 @@ public class GenericRStarTreeRangeQuery<O extends SpatialComparable, D extends D
* @param distanceQuery Distance query to use
*/
public GenericRStarTreeRangeQuery(AbstractRStarTree<?, ?> tree, SpatialDistanceQuery<O, D> distanceQuery) {
- super( distanceQuery);
+ super(distanceQuery);
this.tree = tree;
this.distanceFunction = distanceQuery.getDistanceFunction();
}
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 8e4b36e6..477e3a36 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) 2011
+ Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/package-info.java
index fffaa6bf..0b47cab0 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) 2011
+Copyright (C) 2012
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 4d208e46..53b32c6b 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) 2011
+ Copyright (C) 2012
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.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.NonFlatRStarTree;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.bulk.BulkSplit;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.InsertionStrategy;
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;
@@ -56,11 +54,9 @@ public class RStarTree extends NonFlatRStarTree<RStarTreeNode, SpatialEntry> {
* Constructor.
*
* @param pagefile Page file
- * @param bulkSplitter bulk load strategy
- * @param insertionStrategy the strategy to find the insertion child
*/
- public RStarTree(PageFile<RStarTreeNode> pagefile, BulkSplit bulkSplitter, InsertionStrategy insertionStrategy) {
- super(pagefile, bulkSplitter, insertionStrategy);
+ public RStarTree(PageFile<RStarTreeNode> pagefile) {
+ super(pagefile);
}
@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 f8da714c..79aac0bd 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,8 +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.bulk.BulkSplit;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.InsertionStrategy;
+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.persistent.PageFile;
/**
@@ -50,15 +52,24 @@ public class RStarTreeFactory<O extends NumberVector<O, ?>> extends AbstractRSta
* @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
*/
- public RStarTreeFactory(String fileName, int pageSize, long cacheSize, BulkSplit bulkSplitter, InsertionStrategy insertionStrategy) {
- super(fileName, pageSize, cacheSize, bulkSplitter, insertionStrategy);
+ 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);
}
@Override
public RStarTreeIndex<O> instantiate(Relation<O> relation) {
PageFile<RStarTreeNode> pagefile = makePageFile(getNodeClass());
- return new RStarTreeIndex<O>(relation, pagefile, bulkSplitter, insertionStrategy);
+ 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;
}
protected Class<RStarTreeNode> getNodeClass() {
@@ -75,7 +86,7 @@ public class RStarTreeFactory<O extends NumberVector<O, ?>> extends AbstractRSta
public static class Parameterizer<O extends NumberVector<O, ?>> extends AbstractRStarTreeFactory.Parameterizer<O> {
@Override
protected RStarTreeFactory<O> makeInstance() {
- return new RStarTreeFactory<O>(fileName, pageSize, cacheSize, bulkSplitter, insertionStrategy);
+ return new RStarTreeFactory<O>(fileName, pageSize, cacheSize, bulkSplitter, insertionStrategy, nodeSplitter, overflowTreatment, minimumFill);
}
}
} \ 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 30286ca9..46ef2628 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -40,9 +40,7 @@ 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.bulk.BulkSplit;
import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.query.RStarTreeUtil;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.InsertionStrategy;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.persistent.PageFile;
@@ -69,11 +67,9 @@ public class RStarTreeIndex<O extends NumberVector<?, ?>> extends RStarTree impl
*
* @param relation Relation to index
* @param pagefile Page file
- * @param bulkSplitter bulk load strategy
- * @param insertionStrategy the strategy to find the insertion child
*/
- public RStarTreeIndex(Relation<O> relation, PageFile<RStarTreeNode> pagefile, BulkSplit bulkSplitter, InsertionStrategy insertionStrategy) {
- super(pagefile, bulkSplitter, insertionStrategy);
+ public RStarTreeIndex(Relation<O> relation, PageFile<RStarTreeNode> pagefile) {
+ super(pagefile);
this.relation = relation;
this.initialize();
}
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 248ddfc5..b51d191a 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) 2011
+ Copyright (C) 2012
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 7bfd1b9a..e15569c5 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) 2011
+Copyright (C) 2012
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/bulk/AbstractBulkSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/AbstractBulkSplit.java
index 999fa019..4a0304f1 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/bulk/AbstractBulkSplit.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/AbstractBulkSplit.java
@@ -1,10 +1,13 @@
-package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.bulk;
+package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk;
+
+import java.util.ArrayList;
+import java.util.List;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,14 +26,12 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.bulk;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable;
-
/**
* Encapsulates the required parameters for a bulk split of a spatial index.
*
* @author Elke Achtert
*/
-public abstract class AbstractBulkSplit implements BulkSplit, Parameterizable {
+public abstract class AbstractBulkSplit implements BulkSplit {
/**
* Constructor
*/
@@ -61,4 +62,30 @@ public abstract class AbstractBulkSplit implements BulkSplit, Parameterizable {
return maxEntries;
}
}
+
+ /**
+ * Perform the trivial partitioning of the given list.
+ *
+ * @param objects Objects to partition
+ * @param minEntries Minimum number of objects per page
+ * @param maxEntries Maximum number of objects per page.
+ * @return List with partitions
+ */
+ protected <T> List<List<T>> trivialPartition(List<T> objects, int minEntries, int maxEntries) {
+ // 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);
+ int start = 0;
+ for(int pnum = 0; pnum < numberPartitions; pnum++) {
+ int end = (int) ((pnum + 1.) * size / numberPartitions);
+ if(pnum == numberPartitions - 1) {
+ end = size;
+ }
+ assert ((end - start) >= minEntries && (end - start) <= maxEntries);
+ partitions.add(objects.subList(start, end));
+ start = end;
+ }
+ return partitions;
+ }
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/bulk/BulkSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/BulkSplit.java
index 23c0f077..1eb88f7c 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/bulk/BulkSplit.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/BulkSplit.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.bulk;
+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) 2011
+ Copyright (C) 2012
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.index.tree.spatial.rstarvariants.bulk;
import java.util.List;
import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable;
/**
* Interface for a bulk split strategy.
*
* @author Erich Schubert
*/
-public interface BulkSplit {
+public interface BulkSplit extends Parameterizable {
/**
* Partitions the specified feature vectors
*
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
new file mode 100644
index 00000000..308c70cb
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/FileOrderBulkSplit.java
@@ -0,0 +1,67 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Trivial bulk loading - assumes that the file has been appropriately sorted
+ * before.
+ *
+ * @author Erich Schubert
+ */
+public class FileOrderBulkSplit extends AbstractBulkSplit {
+ /**
+ * Static instance
+ */
+ public static final FileOrderBulkSplit STATIC = new FileOrderBulkSplit();
+
+ /**
+ * Constructor.
+ */
+ protected FileOrderBulkSplit() {
+ super();
+ }
+
+ @Override
+ public <T extends SpatialComparable> List<List<T>> partition(List<T> spatialObjects, int minEntries, int maxEntries) {
+ return trivialPartition(spatialObjects, minEntries, maxEntries);
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected FileOrderBulkSplit makeInstance() {
+ return FileOrderBulkSplit.STATIC;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/bulk/MaxExtensionBulkSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/MaxExtensionBulkSplit.java
index 0a830aab..90a8b622 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/bulk/MaxExtensionBulkSplit.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/MaxExtensionBulkSplit.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.bulk;
+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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -31,6 +31,7 @@ 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.logging.Logging;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
/**
* Split strategy for bulk-loading a spatial tree where the split axes are the
@@ -45,6 +46,11 @@ public class MaxExtensionBulkSplit extends AbstractBulkSplit {
* Logger.
*/
private static final Logging logger = Logging.getLogger(MaxExtensionBulkSplit.class);
+
+ /**
+ * Static instance
+ */
+ public static final MaxExtensionBulkSplit STATIC = new MaxExtensionBulkSplit();
/**
* Constructor
@@ -146,4 +152,18 @@ public class MaxExtensionBulkSplit extends AbstractBulkSplit {
}
return splitAxis;
}
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected MaxExtensionBulkSplit makeInstance() {
+ return MaxExtensionBulkSplit.STATIC;
+ }
+ }
} \ No newline at end of file
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
new file mode 100644
index 00000000..b99ae01e
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/OneDimSortBulkSplit.java
@@ -0,0 +1,86 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.Comparator;
+import java.util.List;
+
+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;
+
+/**
+ * Simple bulk loading strategy by sorting the data along the first dimension.
+ *
+ * This is also known as Nearest-X, and attributed to:
+ * <p>
+ * Roussopoulos, N. and Leifker, D.:<br />
+ * Direct spatial search on pictorial databases using packed R-trees<br />
+ * In: ACM SIGMOD Record 14-4
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@Reference(authors = "Roussopoulos, N. and Leifker, D.", title = "Direct spatial search on pictorial databases using packed R-trees", booktitle = "ACM SIGMOD Record 14-4", url = "http://dx.doi.org/10.1145/971699.318900")
+public class OneDimSortBulkSplit extends AbstractBulkSplit {
+ /**
+ * Static instance
+ */
+ public static final AbstractBulkSplit STATIC = new OneDimSortBulkSplit();
+
+ /**
+ * Constructor.
+ */
+ protected OneDimSortBulkSplit() {
+ super();
+ }
+
+ @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(1) + o1.getMin(1)) / 2;
+ double min2 = (o2.getMax(1) + o2.getMin(1)) / 2;
+ return Double.compare(min1, min2);
+ }
+ });
+ return trivialPartition(spatialObjects, minEntries, maxEntries);
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected AbstractBulkSplit 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
new file mode 100644
index 00000000..28e96da6
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/SortTileRecursiveBulkSplit.java
@@ -0,0 +1,115 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.Comparator;
+import java.util.List;
+
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.QuickSelect;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+
+/**
+ * Sort-Tile-Recursive aims at tiling the data space with a grid-like structure
+ * for partitioning the dataset into the required number of buckets.
+ *
+ * Reference:
+ * <p>
+ * Leutenegger, S.T. and Lopez, M.A. and Edgington, J.:<br />
+ * STR: A simple and efficient algorithm for R-tree packing<br />
+ * In: Proc. 13th International Conference on Data Engineering, 1997
+ * </p>
+ *
+ * @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")
+public class SortTileRecursiveBulkSplit extends AbstractBulkSplit {
+ @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);
+ return ret;
+ }
+
+ /**
+ * Recursively partition.
+ *
+ * @param objs Object list
+ * @param start Subinterval start
+ * @param end Subinteval 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
+ */
+ 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) {
+ c.dim = depth + 1;
+ 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++) {
+ // 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) {
+ 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);
+ }
+ }
+ }
+
+ /**
+ * Comparison helper.
+ *
+ * @apiviz.exclude
+ *
+ * @author Erich Schubert
+ *
+ * @param <T> Type
+ */
+ private static class Compare<T extends SpatialComparable> implements Comparator<T> {
+ /**
+ * Current dimension
+ */
+ public int dim;
+
+ @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);
+ }
+ }
+} \ 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
new file mode 100644
index 00000000..9c3a41a1
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/SpatialSortBulkSplit.java
@@ -0,0 +1,107 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.math.spacefillingcurves.SpatialSorter;
+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.ObjectParameter;
+
+/**
+ * Bulk loading by spatially sorting the objects, then partitioning the sorted
+ * list appropriately.
+ *
+ * Based conceptually on:
+ * <p>
+ * On packing R-trees<br/>
+ * Kamel, I. and Faloutsos, C.<br/>
+ * Proc. 2of the second international conference on Information and knowledge
+ * management
+ * </p>
+ *
+ * @apiviz.composedOf SpatialSorter
+ *
+ * @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")
+public class SpatialSortBulkSplit extends AbstractBulkSplit {
+ /**
+ * Sorting class
+ */
+ final SpatialSorter sorter;
+
+ /**
+ * Constructor.
+ *
+ * @param sorter Sorting strategy
+ */
+ protected SpatialSortBulkSplit(SpatialSorter sorter) {
+ super();
+ this.sorter = sorter;
+ }
+
+ @Override
+ public <T extends SpatialComparable> List<List<T>> partition(List<T> spatialObjects, int minEntries, int maxEntries) {
+ sorter.sort(spatialObjects);
+ return super.trivialPartition(spatialObjects, minEntries, maxEntries);
+ }
+
+ /**
+ * Parametization class
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ /**
+ * Option ID for spatial sorting
+ */
+ public static final OptionID SORTER_ID = OptionID.getOrCreateOptionID("rtree.bulk.spatial-sort", "Strategy for spatial sorting in bulk loading.");
+
+ /**
+ * Sorting class
+ */
+ SpatialSorter sorter;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+
+ ObjectParameter<SpatialSorter> sorterP = new ObjectParameter<SpatialSorter>(SORTER_ID, SpatialSorter.class);
+ if(config.grab(sorterP)) {
+ sorter = sorterP.instantiateClass(config);
+ }
+ }
+
+ @Override
+ protected SpatialSortBulkSplit makeInstance() {
+ return new SpatialSortBulkSplit(sorter);
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/bulk/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/package-info.java
index ab849373..0d01ba83 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/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) 2011
+Copyright (C) 2012
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.index.tree.spatial.rstarvariants.bulk; \ No newline at end of file
+package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk; \ No newline at end of file
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
new file mode 100644
index 00000000..418e92c5
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/ApproximativeLeastOverlapInsertionStrategy.java
@@ -0,0 +1,168 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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 de.lmu.ifi.dbs.elki.data.HyperBoundingBox;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.TopBoundedHeap;
+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.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
+import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleIntPair;
+
+/**
+ * The choose subtree method proposed by the R*-Tree with slightly better
+ * performance for large leaf sizes (linear approximation).
+ *
+ * <p>
+ * N. Beckmann, H.-P. Kriegel, R. Schneider, B. Seeger:<br />
+ * The R*-tree: an efficient and robust access method for points and rectangles<br />
+ * in: Proceedings of the 1990 ACM SIGMOD International Conference on Management
+ * of Data, Atlantic City, NJ, May 23-25, 1990
+ * </p>
+ *
+ * @author Erich Schubert
+ * @author Franz Graf
+ * @author Marisa Petri
+ */
+@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 ApproximativeLeastOverlapInsertionStrategy extends LeastOverlapInsertionStrategy {
+ /**
+ * Number of candidates to consider
+ */
+ private int numCandidates = 32;
+
+ /**
+ * Constructor.
+ */
+ public ApproximativeLeastOverlapInsertionStrategy(int candidates) {
+ super();
+ this.numCandidates = candidates;
+ }
+
+ @Override
+ public <A> int choose(A options, ArrayAdapter<? extends SpatialComparable, A> getter, SpatialComparable obj, int height, int depth) {
+ final int size = getter.size(options);
+ assert (size > 0) : "Choose from empty set?";
+ if(size <= numCandidates) {
+ // Skip building the heap.
+ return super.choose(options, getter, obj, height, depth);
+ }
+
+ // Heap of candidates
+ TopBoundedHeap<DoubleIntPair> candidates = new TopBoundedHeap<DoubleIntPair>(numCandidates, Collections.reverseOrder());
+ for(int i = 0; i < size; i++) {
+ // Existing object and extended rectangle:
+ SpatialComparable entry = getter.get(options, i);
+ HyperBoundingBox mbr = SpatialUtil.union(entry, obj);
+ // Area increase
+ final double inc_area = SpatialUtil.volume(mbr) - SpatialUtil.volume(entry);
+ candidates.add(new DoubleIntPair(inc_area, i));
+ }
+
+ // R*-Tree: overlap increase for leaves.
+ int best = -1;
+ double least_overlap = Double.POSITIVE_INFINITY;
+ double least_areainc = Double.POSITIVE_INFINITY;
+ double least_area = Double.POSITIVE_INFINITY;
+ // least overlap increase, on reduced candidate set:
+ while(!candidates.isEmpty()) {
+ DoubleIntPair pair = candidates.poll();
+ final double inc_area = pair.first;
+
+ // Existing object and extended rectangle:
+ SpatialComparable entry = getter.get(options, pair.second);
+ HyperBoundingBox mbr = SpatialUtil.union(entry, obj);
+ // Compute relative overlap increase.
+ double overlap_wout = 0.0;
+ double overlap_with = 0.0;
+ for(int k = 0; k < size; k++) {
+ if(pair.second != k) {
+ SpatialComparable other = getter.get(options, k);
+ overlap_wout += SpatialUtil.relativeOverlap(entry, other);
+ overlap_with += SpatialUtil.relativeOverlap(mbr, other);
+ }
+ }
+ double inc_overlap = overlap_with - overlap_wout;
+ if(inc_overlap < least_overlap) {
+ final double area = SpatialUtil.volume(entry);
+ // Volume increase and overlap increase:
+ least_overlap = inc_overlap;
+ least_areainc = inc_area;
+ least_area = area;
+ best = pair.second;
+ }
+ else if(inc_overlap == least_overlap) {
+ final double area = SpatialUtil.volume(entry);
+ if(inc_area < least_areainc || (inc_area == least_areainc && area < least_area)) {
+ least_overlap = inc_overlap;
+ least_areainc = inc_area;
+ least_area = area;
+ best = pair.second;
+ }
+ }
+ }
+ assert (best > -1) : "No split found? Volume outside of double precision?";
+ return best;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ /**
+ * Fast-insertion parameter. Optional.
+ */
+ public static OptionID INSERTION_CANDIDATES_ID = OptionID.getOrCreateOptionID("rtree.insertion-candidates", "defines how many children are tested for finding the child generating the least overlap when inserting an object.");
+
+ /**
+ * The number of candidates to use
+ */
+ int numCandidates = 32;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ IntParameter insertionCandidatesP = new IntParameter(INSERTION_CANDIDATES_ID, new GreaterConstraint(0), numCandidates);
+ if(config.grab(insertionCandidatesP)) {
+ numCandidates = insertionCandidatesP.getValue();
+ }
+ }
+
+ @Override
+ protected ApproximativeLeastOverlapInsertionStrategy makeInstance() {
+ return new ApproximativeLeastOverlapInsertionStrategy(numCandidates);
+ }
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..c90d99b2
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/CombinedInsertionStrategy.java
@@ -0,0 +1,127 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayAdapter;
+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.ClassParameter;
+
+/**
+ * Use two different insertion strategies for directory and leaf nodes.
+ *
+ * Using two different strategies was likely first suggested in:
+ * <p>
+ * N. Beckmann, H.-P. Kriegel, R. Schneider, B. Seeger:<br />
+ * The R*-tree: an efficient and robust access method for points and rectangles<br />
+ * in: Proceedings of the 1990 ACM SIGMOD International Conference on Management
+ * of Data, Atlantic City, NJ, May 23-25, 1990
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@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 CombinedInsertionStrategy implements InsertionStrategy {
+ /**
+ * Strategy when inserting into directory nodes
+ */
+ InsertionStrategy dirStrategy;
+
+ /**
+ * Strategy when inserting into leaf nodes.
+ */
+ InsertionStrategy leafStrategy;
+
+ /**
+ * Constructor.
+ *
+ * @param dirStrategy Strategy for directory nodes
+ * @param leafStrategy Strategy for leaf nodes
+ */
+ public CombinedInsertionStrategy(InsertionStrategy dirStrategy, InsertionStrategy leafStrategy) {
+ super();
+ this.dirStrategy = dirStrategy;
+ this.leafStrategy = leafStrategy;
+ }
+
+ @Override
+ public <A> int choose(A options, ArrayAdapter<? extends SpatialComparable, A> getter, SpatialComparable obj, int height, int depth) {
+ if(depth + 1 >= height) {
+ return leafStrategy.choose(options, getter, obj, height, depth);
+ }
+ else {
+ return dirStrategy.choose(options, getter, obj, height, depth);
+ }
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ /**
+ * Insertion strategy for directory nodes.
+ */
+ public static final OptionID DIR_STRATEGY_ID = OptionID.getOrCreateOptionID("rtree.insert-directory", "Insertion strategy for directory nodes.");
+
+ /**
+ * Insertion strategy for leaf nodes.
+ */
+ public static final OptionID LEAF_STRATEGY_ID = OptionID.getOrCreateOptionID("rtree.insert-leaf", "Insertion strategy for leaf nodes.");
+
+ /**
+ * Strategy when inserting into directory nodes
+ */
+ InsertionStrategy dirStrategy;
+
+ /**
+ * Strategy when inserting into leaf nodes.
+ */
+ InsertionStrategy leafStrategy;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ ClassParameter<InsertionStrategy> dirP = new ClassParameter<InsertionStrategy>(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);
+ if(config.grab(leafP)) {
+ leafStrategy = leafP.instantiateClass(config);
+ }
+ }
+
+ @Override
+ protected CombinedInsertionStrategy makeInstance() {
+ return new CombinedInsertionStrategy(dirStrategy, leafStrategy);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/InsertionStrategy.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/InsertionStrategy.java
index 32f841b9..96294514 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/InsertionStrategy.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/InsertionStrategy.java
@@ -1,10 +1,9 @@
-package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util;
-
+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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,26 +23,24 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util;
*/
import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
-import de.lmu.ifi.dbs.elki.index.tree.Node;
-import de.lmu.ifi.dbs.elki.index.tree.TreeIndexPathComponent;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayAdapter;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable;
/**
- * Interface for implementing insertion strategies, i.e. in which path of the
- * tree to insert the new element.
+ * RTree insertion strategy interface.
*
* @author Erich Schubert
*/
public interface InsertionStrategy extends Parameterizable {
/**
- * Find the child to insert into.
+ * Choose insertion rectangle.
*
- * @param <N> Node type
- * @param <E> Entry type
- * @param node Node to use
- * @param mbr MBR of entry to insert
- * @return Entry to insert into
+ * @param options Options to choose from
+ * @param getter Array adapter for options
+ * @param obj Insertion object
+ * @param height Tree height
+ * @param depth Insertion depth (depth == height - 1 indicates leaf level)
+ * @return Subtree index in array.
*/
- public <N extends Node<E>, E extends SpatialEntry> TreeIndexPathComponent<E> findInsertChild(N node, SpatialComparable mbr);
-}
+ public <A> int choose(A options, ArrayAdapter<? extends SpatialComparable, A> getter, SpatialComparable obj, int height, int depth);
+} \ No newline at end of file
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
new file mode 100644
index 00000000..eb211cb6
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastEnlargementInsertionStrategy.java
@@ -0,0 +1,89 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * The default R-Tree insertion strategy: find rectangle with least volume
+ * enlargement.
+ *
+ * <p>
+ * Antonin Guttman:<br/>
+ * R-Trees: A Dynamic Index Structure For Spatial Searching<br />
+ * in Proceedings of the 1984 ACM SIGMOD international conference on Management
+ * of data.
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@Reference(authors = "Antonin Guttman", title = "R-Trees: A Dynamic Index Structure For Spatial Searching", booktitle = "Proceedings of the 1984 ACM SIGMOD international conference on Management of data", url = "http://dx.doi.org/10.1145/971697.602266")
+public class LeastEnlargementInsertionStrategy implements InsertionStrategy {
+ /**
+ * Static instance.
+ */
+ public static final LeastEnlargementInsertionStrategy STATIC = new LeastEnlargementInsertionStrategy();
+
+ /**
+ * Constructor.
+ */
+ public LeastEnlargementInsertionStrategy() {
+ super();
+ }
+
+ @Override
+ public <A> int choose(A options, ArrayAdapter<? extends SpatialComparable, A> getter, SpatialComparable obj, int height, int depth) {
+ final int size = getter.size(options);
+ assert (size > 0) : "Choose from empty set?";
+ double leastEnlargement = Double.POSITIVE_INFINITY;
+ int best = -1;
+ for(int i = 0; i < size; i++) {
+ SpatialComparable entry = getter.get(options, i);
+ double enlargement = SpatialUtil.enlargement(entry, obj);
+ if(enlargement < leastEnlargement) {
+ leastEnlargement = enlargement;
+ best = i;
+ }
+ }
+ assert (best > -1);
+ return best;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected LeastEnlargementInsertionStrategy makeInstance() {
+ return LeastEnlargementInsertionStrategy.STATIC;
+ }
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..977a132b
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastEnlargementWithAreaInsertionStrategy.java
@@ -0,0 +1,102 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * A slight modification of the default R-Tree insertion strategy: find
+ * rectangle with least volume enlargement, but choose least area on ties.
+ *
+ * Proposed for non-leaf entries in:
+ * <p>
+ * N. Beckmann, H.-P. Kriegel, R. Schneider, B. Seeger:<br />
+ * The R*-tree: an efficient and robust access method for points and rectangles<br />
+ * in: Proceedings of the 1990 ACM SIGMOD International Conference on Management
+ * of Data, Atlantic City, NJ, May 23-25, 1990
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@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 LeastEnlargementWithAreaInsertionStrategy implements InsertionStrategy {
+ /**
+ * Static instance.
+ */
+ public static final LeastEnlargementWithAreaInsertionStrategy STATIC = new LeastEnlargementWithAreaInsertionStrategy();
+
+ /**
+ * Constructor.
+ */
+ public LeastEnlargementWithAreaInsertionStrategy() {
+ super();
+ }
+
+ @Override
+ public <A> int choose(A options, ArrayAdapter<? extends SpatialComparable, A> getter, SpatialComparable obj, int height, int depth) {
+ final int size = getter.size(options);
+ assert (size > 0) : "Choose from empty set?";
+ // As in R-Tree, with a slight modification for ties
+ double leastEnlargement = Double.POSITIVE_INFINITY;
+ double minArea = -1;
+ int best = -1;
+ for(int i = 0; i < size; i++) {
+ SpatialComparable entry = getter.get(options, i);
+ double enlargement = SpatialUtil.enlargement(entry, obj);
+ if(enlargement < leastEnlargement) {
+ leastEnlargement = enlargement;
+ best = i;
+ minArea = SpatialUtil.volume(entry);
+ }
+ else if(enlargement == leastEnlargement) {
+ final double area = SpatialUtil.volume(entry);
+ if(area < minArea) {
+ // Tie handling proposed by R*:
+ best = i;
+ minArea = area;
+ }
+ }
+ }
+ assert (best > -1);
+ return best;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected LeastEnlargementWithAreaInsertionStrategy makeInstance() {
+ return LeastEnlargementWithAreaInsertionStrategy.STATIC;
+ }
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..2eba8912
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastOverlapInsertionStrategy.java
@@ -0,0 +1,120 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.HyperBoundingBox;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * The choose subtree method proposed by the R*-Tree for leaf nodes.
+ *
+ * <p>
+ * N. Beckmann, H.-P. Kriegel, R. Schneider, B. Seeger:<br />
+ * The R*-tree: an efficient and robust access method for points and rectangles<br />
+ * in: Proceedings of the 1990 ACM SIGMOD International Conference on Management
+ * of Data, Atlantic City, NJ, May 23-25, 1990
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@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 LeastOverlapInsertionStrategy implements InsertionStrategy {
+ /**
+ * Static instance.
+ */
+ public static final LeastOverlapInsertionStrategy STATIC = new LeastOverlapInsertionStrategy();
+
+ /**
+ * Constructor.
+ */
+ public LeastOverlapInsertionStrategy() {
+ super();
+ }
+
+ @Override
+ public <A> int choose(A options, ArrayAdapter<? extends SpatialComparable, A> getter, SpatialComparable obj, int height, int depth) {
+ final int size = getter.size(options);
+ assert (size > 0) : "Choose from empty set?";
+ // R*-Tree: overlap increase for leaves.
+ int best = -1;
+ double least_overlap = Double.POSITIVE_INFINITY;
+ double least_areainc = Double.POSITIVE_INFINITY;
+ double least_area = Double.POSITIVE_INFINITY;
+ // least overlap increase, on reduced candidate set:
+ for(int i = 0; i < size; i++) {
+ // Existing object and extended rectangle:
+ SpatialComparable entry = getter.get(options, i);
+ HyperBoundingBox mbr = SpatialUtil.union(entry, obj);
+ // Compute relative overlap increase.
+ double overlap_wout = 0.0;
+ double overlap_with = 0.0;
+ for(int k = 0; k < size; k++) {
+ if(i != k) {
+ SpatialComparable other = getter.get(options, k);
+ overlap_wout += SpatialUtil.relativeOverlap(entry, other);
+ overlap_with += SpatialUtil.relativeOverlap(mbr, other);
+ }
+ }
+ double inc_overlap = overlap_with - overlap_wout;
+ if(inc_overlap < least_overlap) {
+ final double area = SpatialUtil.volume(entry);
+ final double inc_area = SpatialUtil.volume(mbr) - area;
+ // Volume increase and overlap increase:
+ least_overlap = inc_overlap;
+ least_areainc = inc_area;
+ least_area = area;
+ best = i;
+ }
+ else if(inc_overlap == least_overlap) {
+ final double area = SpatialUtil.volume(entry);
+ final double inc_area = SpatialUtil.volume(mbr) - area;
+ if(inc_area < least_areainc || (inc_area == least_areainc && area < least_area)) {
+ least_overlap = inc_overlap;
+ least_areainc = inc_area;
+ least_area = area;
+ best = i;
+ }
+ }
+ }
+ assert (best > -1) : "No split found? Volume outside of double precision?";
+ return best;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected LeastOverlapInsertionStrategy makeInstance() {
+ return LeastOverlapInsertionStrategy.STATIC;
+ }
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..ad54e1e1
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/package-info.java
@@ -0,0 +1,26 @@
+/**
+ * <p>Insertion strategies for R-Trees</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.spatial.rstarvariants.strategies.insert; \ No newline at end of file
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
new file mode 100644
index 00000000..2532f351
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/LimitedReinsertOverflowTreatment.java
@@ -0,0 +1,135 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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 de.lmu.ifi.dbs.elki.distance.distancefunction.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;
+import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRStarTreeNode;
+import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.reinsert.CloseReinsert;
+import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.reinsert.ReinsertStrategy;
+import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.NodeArrayAdapter;
+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.ObjectParameter;
+
+/**
+ * Limited reinsertions, as proposed by the R*-Tree: For each real insert, allow
+ * reinsertions to happen only once per level.
+ *
+ * @author Erich Schubert
+ */
+@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 LimitedReinsertOverflowTreatment implements OverflowTreatment {
+ /**
+ * Default insert strategy used by R*-tree
+ */
+ public static final LimitedReinsertOverflowTreatment RSTAR_OVERFLOW = new LimitedReinsertOverflowTreatment(new CloseReinsert(0.3, SquaredEuclideanDistanceFunction.STATIC));
+
+ /**
+ * Bitset to keep track of levels a reinsert has been performed at.
+ */
+ private BitSet reinsertions = new BitSet();
+
+ /**
+ * Strategy for the actual reinsertions
+ */
+ private final ReinsertStrategy reinsertStrategy;
+
+ /**
+ * Constructor.
+ *
+ * @param reinsertStrategy Reinsertion strategy
+ */
+ public LimitedReinsertOverflowTreatment(ReinsertStrategy reinsertStrategy) {
+ super();
+ this.reinsertStrategy = reinsertStrategy;
+ }
+
+ @Override
+ 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) {
+ return false;
+ }
+ // Earlier reinsertions at the same level
+ if(reinsertions.get(level)) {
+ return false;
+ }
+
+ reinsertions.set(level);
+ final E entry = path.getLastPathComponent().getEntry();
+ assert (!entry.isLeafEntry()) : "Unexpected leaf entry";
+ int[] cands = reinsertStrategy.computeReinserts(node, NodeArrayAdapter.STATIC, entry);
+ if(cands == null || cands.length == 0) {
+ return false;
+ }
+ tree.reInsert(node, path, cands);
+ return true;
+ }
+
+ @Override
+ public void reinitialize() {
+ reinsertions.clear();
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ /**
+ * Fast-insertion parameter. Optional.
+ */
+ public static OptionID REINSERT_STRATEGY_ID = OptionID.getOrCreateOptionID("rtree.reinsertion-strategy", "The strategy to select candidates for reinsertion.");
+
+ /**
+ * The actual reinsertion strategy
+ */
+ ReinsertStrategy reinsertStrategy = null;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ ObjectParameter<ReinsertStrategy> strategyP = new ObjectParameter<ReinsertStrategy>(REINSERT_STRATEGY_ID, ReinsertStrategy.class, CloseReinsert.class);
+ if(config.grab(strategyP)) {
+ reinsertStrategy = strategyP.instantiateClass(config);
+ }
+ }
+
+ @Override
+ protected LimitedReinsertOverflowTreatment makeInstance() {
+ return new LimitedReinsertOverflowTreatment(reinsertStrategy);
+ }
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..87d09038
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/OverflowTreatment.java
@@ -0,0 +1,53 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.index.tree.IndexTreePath;
+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;
+
+/**
+ * Reinsertion strategy to resolve overflows in the RStarTree.
+ *
+ * @author Erich Schubert
+ */
+public interface OverflowTreatment {
+ /**
+ * Reinitialize the reinsertion treatment (for a new primary insertion).
+ */
+ public void reinitialize();
+
+ /**
+ * Handle overflow in the given node.
+ *
+ * @param <N> Node
+ * @param <E> Entry
+ * @param tree Tree
+ * @param node Node
+ * @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);
+} \ 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
new file mode 100644
index 00000000..cfbcf6a9
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/SplitOnlyOverflowTreatment.java
@@ -0,0 +1,73 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.index.tree.IndexTreePath;
+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.optionhandling.AbstractParameterizer;
+
+/**
+ * Always split, as in the original R-Tree
+ *
+ * @author Erich Schubert
+ */
+public class SplitOnlyOverflowTreatment implements OverflowTreatment {
+ /**
+ * Static instance
+ */
+ public static final SplitOnlyOverflowTreatment STATIC = new SplitOnlyOverflowTreatment();
+
+ /**
+ * Constructor
+ */
+ public SplitOnlyOverflowTreatment() {
+ super();
+ }
+
+ @Override
+ public <N extends AbstractRStarTreeNode<N, E>, E extends SpatialEntry> boolean handleOverflow(AbstractRStarTree<N, E> tree, N node, IndexTreePath<E> path) {
+ return false;
+ }
+
+ @Override
+ public void reinitialize() {
+ // Nothing to do
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected SplitOnlyOverflowTreatment makeInstance() {
+ return SplitOnlyOverflowTreatment.STATIC;
+ }
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..30899736
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/package-info.java
@@ -0,0 +1,26 @@
+/**
+ * <p>Overflow treatment strategies for R-Trees</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.spatial.rstarvariants.strategies.overflow; \ No newline at end of file
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
new file mode 100644
index 00000000..41e2eb0b
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/package-info.java
@@ -0,0 +1,26 @@
+/**
+ * <p>Various strategies for R-Trees 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.spatial.rstarvariants.strategies; \ No newline at end of file
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
new file mode 100644
index 00000000..e0277606
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/AbstractPartialReinsert.java
@@ -0,0 +1,105 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.SpatialPrimitiveDoubleDistanceFunction;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.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.IntervalConstraint;
+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;
+
+/**
+ * Abstract base class for reinsertion strategies that have a "relative amount"
+ * parameter to partially reinsert entries.
+ *
+ * @author Erich Schubert
+ */
+public abstract class AbstractPartialReinsert implements ReinsertStrategy {
+ /**
+ * Amount of entries to reinsert
+ */
+ protected double reinsertAmount = 0.3;
+
+ /**
+ * Distance function to use for measuring
+ */
+ SpatialPrimitiveDoubleDistanceFunction<?> distanceFunction;
+
+ /**
+ * Constructor.
+ *
+ * @param reinsertAmount Relative amount of objects to reinsert.
+ * @param distanceFunction Distance function to use
+ */
+ public AbstractPartialReinsert(double reinsertAmount, SpatialPrimitiveDoubleDistanceFunction<?> distanceFunction) {
+ super();
+ this.reinsertAmount = reinsertAmount;
+ this.distanceFunction = distanceFunction;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static abstract class Parameterizer extends AbstractParameterizer {
+ /**
+ * Reinsertion share
+ */
+ public static OptionID REINSERT_AMOUNT_ID = OptionID.getOrCreateOptionID("rtree.reinsertion-amount", "The amount of entries to reinsert.");
+
+ /**
+ * Reinsertion share
+ */
+ public static OptionID REINSERT_DISTANCE_ID = OptionID.getOrCreateOptionID("rtree.reinsertion-distancce", "The distance function to compute reinsertion candidates by.");
+
+ /**
+ * The actual reinsertion strategy
+ */
+ double reinsertAmount = 0.3;
+
+ /**
+ * Distance function to use for measuring
+ */
+ SpatialPrimitiveDoubleDistanceFunction<?> distanceFunction;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ DoubleParameter reinsertAmountP = new DoubleParameter(REINSERT_AMOUNT_ID, new IntervalConstraint(0.0, IntervalConstraint.IntervalBoundary.OPEN, 0.5, IntervalConstraint.IntervalBoundary.OPEN), 0.3);
+ if(config.grab(reinsertAmountP)) {
+ reinsertAmount = reinsertAmountP.getValue();
+ }
+ ObjectParameter<SpatialPrimitiveDoubleDistanceFunction<?>> distanceP = new ObjectParameter<SpatialPrimitiveDoubleDistanceFunction<?>>(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
new file mode 100644
index 00000000..12a4ed0f
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/CloseReinsert.java
@@ -0,0 +1,88 @@
+package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.reinsert;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import de.lmu.ifi.dbs.elki.data.DoubleVector;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDoubleDistanceFunction;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Reinsert objects on page overflow, starting with close objects first (even
+ * when they will likely be inserted into the same page again!)
+ *
+ * The strategy preferred by the R*-Tree
+ *
+ * @author Erich Schubert
+ */
+@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 CloseReinsert extends AbstractPartialReinsert {
+ /**
+ * Constructor.
+ *
+ * @param reinsertAmount Amount of objects to reinsert
+ * @param distanceFunction Distance function to use for reinsertion
+ */
+ public CloseReinsert(double reinsertAmount, SpatialPrimitiveDoubleDistanceFunction<?> distanceFunction) {
+ super(reinsertAmount, distanceFunction);
+ }
+
+ @Override
+ public <A> int[] computeReinserts(A entries, ArrayAdapter<? extends SpatialComparable, ? super A> getter, SpatialComparable page) {
+ DoubleIntPair[] order = new DoubleIntPair[getter.size(entries)];
+ DoubleVector centroid = new DoubleVector(SpatialUtil.centroid(page));
+ for(int i = 0; i < order.length; i++) {
+ double distance = distanceFunction.doubleMinDist(new DoubleVector(SpatialUtil.centroid(getter.get(entries, i))), centroid);
+ order[i] = new DoubleIntPair(distance, i);
+ }
+ Arrays.sort(order, Collections.reverseOrder());
+
+ int num = (int) (reinsertAmount * order.length);
+ int[] re = new int[num];
+ for(int i = 0; i < num; i++) {
+ re[i] = order[num - 1 - i].second;
+ }
+ return re;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractPartialReinsert.Parameterizer {
+ @Override
+ protected Object makeInstance() {
+ return new CloseReinsert(reinsertAmount, distanceFunction);
+ }
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..771f56fb
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/FarReinsert.java
@@ -0,0 +1,88 @@
+package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.reinsert;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import de.lmu.ifi.dbs.elki.data.DoubleVector;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil;
+import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDoubleDistanceFunction;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Reinsert objects on page overflow, starting with farther objects first (even
+ * when they will likely be inserted into the same page again!)
+ *
+ * Alternative strategy mentioned in the R*-tree
+ *
+ * @author Erich Schubert
+ */
+@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 FarReinsert extends AbstractPartialReinsert {
+ /**
+ * Constructor.
+ *
+ * @param reinsertAmount Amount to reinsert
+ * @param distanceFunction Distance function
+ */
+ public FarReinsert(double reinsertAmount, SpatialPrimitiveDoubleDistanceFunction<?> distanceFunction) {
+ super(reinsertAmount, distanceFunction);
+ }
+
+ @Override
+ public <A> int[] computeReinserts(A entries, ArrayAdapter<? extends SpatialComparable, ? super A> getter, SpatialComparable page) {
+ DoubleIntPair[] order = new DoubleIntPair[getter.size(entries)];
+ DoubleVector centroid = new DoubleVector(SpatialUtil.centroid(page));
+ for(int i = 0; i < order.length; i++) {
+ double distance = distanceFunction.doubleMinDist(new DoubleVector(SpatialUtil.centroid(getter.get(entries, i))), centroid);
+ order[i] = new DoubleIntPair(distance, i);
+ }
+ Arrays.sort(order, Collections.reverseOrder());
+
+ int num = (int) (reinsertAmount * order.length);
+ int[] re = new int[num];
+ for(int i = 0; i < num; i++) {
+ re[i] = order[i].second;
+ }
+ return re;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractPartialReinsert.Parameterizer {
+ @Override
+ protected Object makeInstance() {
+ return new CloseReinsert(reinsertAmount, distanceFunction);
+ }
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..cba96367
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/ReinsertStrategy.java
@@ -0,0 +1,44 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayAdapter;
+
+/**
+ * Reinsertion strategy to resolve overflows in the RStarTree.
+ *
+ * @author Erich Schubert
+ */
+public interface ReinsertStrategy {
+ /**
+ * Perform reinsertions.
+ *
+ * @param entries Entries in overflowing node
+ * @param getter Adapter for the entries array
+ * @param page Spatial extend of the page
+ * @return index of pages to reinsert.
+ */
+ public <A> int[] computeReinserts(A entries, ArrayAdapter<? extends SpatialComparable, ? super A> getter, SpatialComparable page);
+}
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
new file mode 100644
index 00000000..f6a6f6e9
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/package-info.java
@@ -0,0 +1,26 @@
+/**
+ * <p>Reinsertion strategies for R-Trees</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.spatial.rstarvariants.strategies.reinsert; \ No newline at end of file
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
new file mode 100644
index 00000000..e59fe10e
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/AngTanLinearSplit.java
@@ -0,0 +1,193 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.Random;
+
+import de.lmu.ifi.dbs.elki.data.ModifiableHyperBoundingBox;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.utilities.Util;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayAdapter;
+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;
+
+/**
+ * Line-time complexity split proposed by Ang and Tan.
+ *
+ * This split strategy tries to minimize overlap only, which can however
+ * degenerate to "slices".
+ *
+ * <p>
+ * C. H. Ang and T. C. Tan:<br />
+ * New linear node splitting algorithm for R-trees<br />
+ * In: Proceedings of the 5th International Symposium on Advances in Spatial
+ * Databases
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@Reference(authors = "C. H. Ang and T. C. Tan", title = "New linear node splitting algorithm for R-trees", booktitle = "Proceedings of the 5th International Symposium on Advances in Spatial Databases", url = "http://dx.doi.org/10.1007/3-540-63238-7_38")
+public class AngTanLinearSplit implements SplitStrategy {
+ /**
+ * Logger class
+ */
+ private static final Logging logger = Logging.getLogger(AngTanLinearSplit.class);
+
+ /**
+ * Static instance.
+ */
+ public static final AngTanLinearSplit STATIC = new AngTanLinearSplit();
+
+ @Override
+ public <E extends SpatialComparable, A> BitSet split(A entries, ArrayAdapter<E, A> getter, int minEntries) {
+ final int num = getter.size(entries);
+ // We need the overall MBR for computing edge preferences
+ ModifiableHyperBoundingBox total = new ModifiableHyperBoundingBox(getter.get(entries, 0));
+ {
+ for(int i = 1; i < num; i++) {
+ total.extend(getter.get(entries, i));
+ }
+ }
+ final int dim = total.getDimensionality();
+ // Prepare the axis lists (we use bitsets)
+ BitSet[] closer = new BitSet[dim];
+ {
+ for(int d = 0; d < dim; d++) {
+ closer[d] = new BitSet();
+ }
+ for(int i = 0; i < num; i++) {
+ E e = getter.get(entries, i);
+ for(int d = 1; d <= dim; d++) {
+ double low = e.getMin(d) - total.getMin(d);
+ double hig = total.getMax(d) - e.getMax(d);
+ if(low >= hig) {
+ closer[d - 1].set(i);
+ }
+ }
+ }
+ }
+ // Find the most even split
+ {
+ int axis = -1;
+ int bestcard = Integer.MAX_VALUE;
+ BitSet bestset = null;
+ double bestover = Double.NaN;
+ for(int d = 0; d < dim; d++) {
+ BitSet cand = closer[d];
+ int card = cand.cardinality();
+ card = Math.max(card, num - card);
+ if(card == num) {
+ continue;
+ }
+ if(card < bestcard) {
+ axis = d + 1;
+ bestcard = card;
+ bestset = cand;
+ bestover = Double.NaN;
+ }
+ else if(card == bestcard) {
+ // Tie handling
+ if(Double.isNaN(bestover)) {
+ bestover = computeOverlap(entries, getter, bestset);
+ }
+ double overlap = computeOverlap(entries, getter, cand);
+ if(overlap < bestover) {
+ axis = d + 1;
+ bestcard = card;
+ bestset = cand;
+ bestover = overlap;
+ }
+ else if(overlap == bestover) {
+ double bestlen = total.getMax(axis) - total.getMin(axis);
+ double candlen = total.getMax(d + 1) - total.getMin(d + 1);
+ if(candlen < bestlen) {
+ axis = d + 1;
+ bestcard = card;
+ bestset = cand;
+ bestover = overlap;
+ }
+ }
+ }
+ }
+ if(bestset == null) {
+ logger.warning("No Ang-Tan-Split found. Probably all points are the same? Returning random split.");
+ return Util.randomBitSet(num / 2, num, new Random());
+ }
+ return bestset;
+ }
+ }
+
+ /**
+ * Compute overlap of assignment
+ *
+ * @param entries Entries
+ * @param getter Entry accessor
+ * @param assign Assignment
+ * @return Overlap amount
+ */
+ protected <E extends SpatialComparable, A> double computeOverlap(A entries, ArrayAdapter<E, A> getter, BitSet assign) {
+ ModifiableHyperBoundingBox mbr1 = null, mbr2 = null;
+ for(int i = 0; i < getter.size(entries); i++) {
+ E e = getter.get(entries, i);
+ if(assign.get(i)) {
+ if(mbr1 == null) {
+ mbr1 = new ModifiableHyperBoundingBox(e);
+ }
+ else {
+ mbr1.extend(e);
+ }
+ }
+ else {
+ if(mbr2 == null) {
+ mbr2 = new ModifiableHyperBoundingBox(e);
+ }
+ else {
+ mbr2.extend(e);
+ }
+ }
+ }
+ if(mbr1 == null || mbr2 == null) {
+ throw new AbortException("Invalid state in split: one of the sets is empty.");
+ }
+ return SpatialUtil.overlap(mbr1, mbr2);
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected AngTanLinearSplit makeInstance() {
+ return AngTanLinearSplit.STATIC;
+ }
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..7401fbe5
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/GreeneSplit.java
@@ -0,0 +1,158 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.BitSet;
+
+import de.lmu.ifi.dbs.elki.data.ModifiableHyperBoundingBox;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayAdapter;
+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.DoubleIntPair;
+
+/**
+ * Quadratic-time complexity split as used by Diane Greene for the R-Tree.
+ *
+ * Seed selection is quadratic, distribution is O(n log n).
+ *
+ * This contains a slight modification to improve performance with point data:
+ * with points as seeds, the normalized separation is always 1, so we choose the
+ * raw separation then.
+ *
+ * <p>
+ * Diane Greene:<br />
+ * An implementation and performance analysis of spatial data access methods<br />
+ * In: Proceedings of the Fifth International Conference on Data Engineering
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@Reference(authors = "Diane Greene", title = "An implementation and performance analysis of spatial data access methods", booktitle = "Proceedings of the Fifth International Conference on Data Engineering", url = "http://dx.doi.org/10.1109/ICDE.1989.47268")
+public class GreeneSplit implements SplitStrategy {
+ /**
+ * Static instance.
+ */
+ public static final GreeneSplit STATIC = new GreeneSplit();
+
+ @Override
+ public <E extends SpatialComparable, A> BitSet split(A entries, ArrayAdapter<E, A> getter, int minEntries) {
+ final int num = getter.size(entries);
+ // Choose axis by best normalized separation
+ int axis = -1;
+ {
+ // PickSeeds - find the two most distant rectangles
+ double worst = Double.NEGATIVE_INFINITY;
+ int w1 = 0, w2 = 0;
+
+ // Compute individual areas
+ double[] areas = new double[num];
+ for(int e1 = 0; e1 < num - 1; e1++) {
+ final E e1i = getter.get(entries, e1);
+ areas[e1] = SpatialUtil.volume(e1i);
+ }
+ // Compute area increase
+ for(int e1 = 0; e1 < num - 1; e1++) {
+ final E e1i = getter.get(entries, e1);
+ for(int e2 = e1 + 1; e2 < num; e2++) {
+ final E e2i = getter.get(entries, e2);
+ final double areaJ = SpatialUtil.volumeUnion(e1i, e2i);
+ final double d = areaJ - areas[e1] - areas[e2];
+ if(d > worst) {
+ worst = d;
+ w1 = e1;
+ w2 = e2;
+ }
+ }
+ }
+ // Data to keep
+ // Initial mbrs and areas
+ E m1 = getter.get(entries, w1);
+ E m2 = getter.get(entries, w2);
+
+ double bestsep = Double.NEGATIVE_INFINITY;
+ double bestsep2 = Double.NEGATIVE_INFINITY;
+ for(int d = 1; d <= m1.getDimensionality(); d++) {
+ final double s1 = m1.getMin(d) - m2.getMax(d);
+ final double s2 = m2.getMin(d) - m1.getMax(d);
+ final double sm = Math.max(s1, s2);
+ final double no = Math.max(m1.getMax(d), m2.getMax(d)) - Math.min(m1.getMin(d), m2.getMin(d));
+ final double sep = sm / no;
+ if(sep > bestsep || (sep == bestsep && sm > bestsep2)) {
+ bestsep = sep;
+ bestsep2 = sm;
+ axis = d;
+ }
+ }
+ }
+ // Sort by minimum value
+ DoubleIntPair[] data = new DoubleIntPair[num];
+ for(int i = 0; i < num; i++) {
+ data[i] = new DoubleIntPair(getter.get(entries, i).getMin(axis), i);
+ }
+ Arrays.sort(data);
+ // Object assignment
+ final BitSet assignment = new BitSet(num);
+ final int half = (num + 1) / 2;
+ // Put the first half into second node
+ for(int i = 0; i < half; i++) {
+ assignment.set(data[i].second);
+ }
+ // Tie handling
+ if(num % 2 == 0) {
+ // We need to compute the bounding boxes
+ ModifiableHyperBoundingBox mbr1 = new ModifiableHyperBoundingBox(getter.get(entries, data[0].second));
+ for(int i = 1; i < half; i++) {
+ mbr1.extend(getter.get(entries, data[i].second));
+ }
+ ModifiableHyperBoundingBox mbr2 = new ModifiableHyperBoundingBox(getter.get(entries, data[num - 1].second));
+ for(int i = half + 1; i < num - 1; i++) {
+ mbr2.extend(getter.get(entries, data[i].second));
+ }
+ E e = getter.get(entries, data[half].second);
+ double inc1 = SpatialUtil.volumeUnion(mbr1, e) - SpatialUtil.volume(mbr1);
+ double inc2 = SpatialUtil.volumeUnion(mbr2, e) - SpatialUtil.volume(mbr2);
+ if(inc1 < inc2) {
+ assignment.set(data[half].second);
+ }
+ }
+ return assignment;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected GreeneSplit makeInstance() {
+ return GreeneSplit.STATIC;
+ }
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..296f6b3b
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/RTreeLinearSplit.java
@@ -0,0 +1,219 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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 de.lmu.ifi.dbs.elki.data.ModifiableHyperBoundingBox;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Linear-time complexity greedy split as used by the original R-Tree.
+ *
+ * <p>
+ * Antonin Guttman:<br/>
+ * R-Trees: A Dynamic Index Structure For Spatial Searching<br />
+ * in Proceedings of the 1984 ACM SIGMOD international conference on Management
+ * of data.
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@Reference(authors = "Antonin Guttman", title = "R-Trees: A Dynamic Index Structure For Spatial Searching", booktitle = "Proceedings of the 1984 ACM SIGMOD international conference on Management of data", url = "http://dx.doi.org/10.1145/971697.602266")
+public class RTreeLinearSplit implements SplitStrategy {
+ /**
+ * Static instance.
+ */
+ public static final RTreeLinearSplit STATIC = new RTreeLinearSplit();
+
+ @Override
+ public <E extends SpatialComparable, A> BitSet split(A entries, ArrayAdapter<E, A> getter, int minEntries) {
+ final int num = getter.size(entries);
+ // Object assignment, and processed objects
+ BitSet assignment = new BitSet(num);
+ BitSet assigned = new BitSet(num);
+ // MBRs and Areas of current assignments
+ ModifiableHyperBoundingBox mbr1, mbr2;
+ double area1 = 0, area2 = 0;
+ // LinearPickSeeds - find worst pair
+ {
+ final int dim = getter.get(entries, 0).getDimensionality();
+ // Best candidates
+ double bestsep = Double.NEGATIVE_INFINITY;
+ int w1 = -1, w2 = -1;
+ // LPS1: find extreme rectangles
+ for(int d = 1; d <= dim; d++) {
+ // We need to find two candidates each, in case of el==eh!
+ double minlow = Double.POSITIVE_INFINITY;
+ double maxlow = Double.NEGATIVE_INFINITY, maxlow2 = Double.NEGATIVE_INFINITY;
+ double minhig = Double.POSITIVE_INFINITY, minhig2 = Double.POSITIVE_INFINITY;
+ double maxhig = Double.NEGATIVE_INFINITY;
+ int el = -1, el2 = -1;
+ int eh = -1, eh2 = -1;
+ for(int i = 0; i < num; i++) {
+ E ei = getter.get(entries, i);
+ final double low = ei.getMin(d);
+ final double hig = ei.getMax(d);
+ minlow = Math.min(minlow, low);
+ maxhig = Math.max(maxhig, hig);
+ if(low >= maxlow) {
+ maxlow2 = maxlow;
+ maxlow = low;
+ el2 = el;
+ el = i;
+ }
+ else if(low > maxlow2) {
+ maxlow2 = low;
+ el2 = i;
+ }
+ if(hig <= minhig) {
+ minhig2 = minhig;
+ minhig = hig;
+ eh2 = eh;
+ eh = i;
+ }
+ else if(hig < minhig2) {
+ minhig2 = hig;
+ eh2 = i;
+ }
+ }
+ // Compute normalized separation
+ final double normsep;
+ if(el != eh) {
+ normsep = minhig - maxlow / (maxhig - minlow);
+ }
+ else {
+ // Resolve tie.
+ double normsep1 = minhig - maxlow2 / (maxhig - minlow);
+ double normsep2 = minhig2 - maxlow / (maxhig - minlow);
+ if(normsep1 > normsep2) {
+ el = el2;
+ normsep = normsep1;
+ }
+ else {
+ eh = eh2;
+ normsep = normsep2;
+ }
+ }
+ assert (eh != -1 && el != -1 && (eh != el));
+ if(normsep > bestsep) {
+ bestsep = normsep;
+ w1 = el;
+ w2 = eh;
+ }
+ }
+
+ // Data to keep
+ // Mark both as used
+ assigned.set(w1);
+ assigned.set(w2);
+ // Assign second to second set
+ assignment.set(w2);
+ // Initial mbrs and areas
+ final E w1i = getter.get(entries, w1);
+ final E w2i = getter.get(entries, w2);
+ area1 = SpatialUtil.volume(w1i);
+ area2 = SpatialUtil.volume(w2i);
+ mbr1 = new ModifiableHyperBoundingBox(w1i);
+ mbr2 = new ModifiableHyperBoundingBox(w2i);
+ }
+ // Second phase, QS2+QS3
+ {
+ int in1 = 1, in2 = 1;
+ int remaining = num - 2;
+ // Choose any element, for example the next.
+ for(int next = assigned.nextClearBit(0); remaining > 0 && next < num; next = assigned.nextClearBit(next + 1)) {
+ // Shortcut when minEntries must be fulfilled
+ if(in1 + remaining <= minEntries) {
+ // No need to updated assigned, no changes to assignment.
+ break;
+ }
+ if(in2 + remaining <= minEntries) {
+ // Mark unassigned for second.
+ // Don't bother to update assigned, though
+ for(; next < num; next = assigned.nextClearBit(next + 1)) {
+ assignment.set(next);
+ }
+ break;
+ }
+ // PickNext
+ boolean preferSecond = false;
+
+ // Cost of putting object into both mbrs
+ final E next_i = getter.get(entries, next);
+ final double d1 = SpatialUtil.volumeUnion(mbr1, next_i) - area1;
+ final double d2 = SpatialUtil.volumeUnion(mbr2, next_i) - area2;
+ // Prefer smaller increase
+ preferSecond = (d2 < d1);
+ // QS3: tie handling
+ if(d1 == d2) {
+ // Prefer smaller area
+ if(area1 != area2) {
+ preferSecond = (area2 < area1);
+ }
+ else {
+ // Prefer smaller group size
+ preferSecond = (in2 < in1);
+ }
+ }
+ // Mark as used.
+ assigned.set(next);
+ remaining--;
+ // Assign
+ if(!preferSecond) {
+ in1++;
+ mbr1.extend(next_i);
+ area1 = SpatialUtil.volume(mbr1);
+ }
+ else {
+ in2++;
+ assignment.set(next);
+ mbr2.extend(next_i);
+ area2 = SpatialUtil.volume(mbr2);
+ }
+ // Loop from QS2
+ }
+ // Note: "assigned" and "remaining" likely not updated!
+ }
+ return assignment;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected RTreeLinearSplit makeInstance() {
+ return RTreeLinearSplit.STATIC;
+ }
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..8f61771d
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/RTreeQuadraticSplit.java
@@ -0,0 +1,183 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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 de.lmu.ifi.dbs.elki.data.ModifiableHyperBoundingBox;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
+
+/**
+ * Quadratic-time complexity greedy split as used by the original R-Tree.
+ *
+ * <p>
+ * Antonin Guttman:<br/>
+ * R-Trees: A Dynamic Index Structure For Spatial Searching<br />
+ * in Proceedings of the 1984 ACM SIGMOD international conference on Management
+ * of data.
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@Reference(authors = "Antonin Guttman", title = "R-Trees: A Dynamic Index Structure For Spatial Searching", booktitle = "Proceedings of the 1984 ACM SIGMOD international conference on Management of data", url = "http://dx.doi.org/10.1145/971697.602266")
+public class RTreeQuadraticSplit implements SplitStrategy {
+ /**
+ * Static instance.
+ */
+ public static final RTreeQuadraticSplit STATIC = new RTreeQuadraticSplit();
+
+ @Override
+ public <E extends SpatialComparable, A> BitSet split(A entries, ArrayAdapter<E, A> getter, int minEntries) {
+ final int num = getter.size(entries);
+ // Object assignment, and processed objects
+ BitSet assignment = new BitSet(num);
+ BitSet assigned = new BitSet(num);
+ // MBRs and Areas of current assignments
+ ModifiableHyperBoundingBox mbr1, mbr2;
+ double area1 = 0, area2 = 0;
+ // PickSeeds - find worst pair
+ {
+ double worst = Double.NEGATIVE_INFINITY;
+ int w1 = 0, w2 = 0;
+
+ // Compute individual areas
+ double[] areas = new double[num];
+ for(int e1 = 0; e1 < num - 1; e1++) {
+ final E e1i = getter.get(entries, e1);
+ areas[e1] = SpatialUtil.volume(e1i);
+ }
+ // Compute area increase
+ for(int e1 = 0; e1 < num - 1; e1++) {
+ final E e1i = getter.get(entries, e1);
+ for(int e2 = e1 + 1; e2 < num; e2++) {
+ final E e2i = getter.get(entries, e2);
+ final double areaJ = SpatialUtil.volumeUnion(e1i, e2i);
+ final double d = areaJ - areas[e1] - areas[e2];
+ if(d > worst) {
+ worst = d;
+ w1 = e1;
+ w2 = e2;
+ }
+ }
+ }
+ // Data to keep
+ // Mark both as used
+ assigned.set(w1);
+ assigned.set(w2);
+ // Assign second to second set
+ assignment.set(w2);
+ // Initial mbrs and areas
+ area1 = areas[w1];
+ area2 = areas[w2];
+ mbr1 = new ModifiableHyperBoundingBox(getter.get(entries, w1));
+ mbr2 = new ModifiableHyperBoundingBox(getter.get(entries, w2));
+ }
+ // Second phase, QS2+QS3
+ {
+ int in1 = 1, in2 = 1;
+ int remaining = num - 2;
+ while(remaining > 0) {
+ // Shortcut when minEntries must be fulfilled
+ if(in1 + remaining <= minEntries) {
+ // No need to updated assigned, no changes to assignment.
+ break;
+ }
+ if(in2 + remaining <= minEntries) {
+ // Mark unassigned for second.
+ // Don't bother to update assigned, though
+ for(int pos = assigned.nextClearBit(0); pos < num; pos = assigned.nextClearBit(pos + 1)) {
+ assignment.set(pos);
+ }
+ break;
+ }
+ // PickNext
+ double greatestPreference = Double.NEGATIVE_INFINITY;
+ int best = -1;
+ E best_i = null;
+ boolean preferSecond = false;
+ for(int pos = assigned.nextClearBit(0); pos < num; pos = assigned.nextClearBit(pos + 1)) {
+ // Cost of putting object into both mbrs
+ final E pos_i = getter.get(entries, pos);
+ final double d1 = SpatialUtil.volumeUnion(mbr1, pos_i) - area1;
+ final double d2 = SpatialUtil.volumeUnion(mbr2, pos_i) - area2;
+ // Preference
+ final double preference = Math.abs(d1 - d2);
+ if(preference > greatestPreference) {
+ greatestPreference = preference;
+ best = pos;
+ best_i = pos_i;
+ // Prefer smaller increase
+ preferSecond = (d2 < d1);
+ }
+ }
+ // QS3: tie handling
+ if(greatestPreference == 0) {
+ // Prefer smaller area
+ if(area1 != area2) {
+ preferSecond = (area2 < area1);
+ }
+ else {
+ // Prefer smaller group size
+ preferSecond = (in2 < in1);
+ }
+ }
+ // Mark as used.
+ assigned.set(best);
+ remaining--;
+ if(!preferSecond) {
+ in1++;
+ mbr1.extend(best_i);
+ area1 = SpatialUtil.volume(mbr1);
+ }
+ else {
+ in2++;
+ assignment.set(best);
+ mbr2.extend(best_i);
+ area2 = SpatialUtil.volume(mbr2);
+ }
+ // Loop from QS2
+ }
+ // Note: "assigned" and "remaining" likely not updated!
+ }
+ return assignment;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected RTreeQuadraticSplit makeInstance() {
+ return RTreeQuadraticSplit.STATIC;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/SplitStrategy.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/SplitStrategy.java
index 272dcbc6..658a63da 100644
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/SplitStrategy.java
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/SplitStrategy.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util;
+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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,25 +23,25 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.List;
+import java.util.BitSet;
-import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable;
/**
* Generic interface for split strategies.
*
* @author Erich Schubert
- *
- * @param <B> Base type that can be processed by this strategy
*/
-public interface SplitStrategy<B> {
+public interface SplitStrategy extends Parameterizable {
/**
* Split a page
*
- * @param <E> Actual data type
* @param entries Entries to split
+ * @param getter Adapter for the entries array
* @param minEntries Minimum number of entries in each part
- * @return Pair containing the two sets of objects
+ * @return BitSet containing the assignment.
*/
- public <E extends B> Pair<List<E>, List<E>> split(List<E> entries, int minEntries);
-}
+ public <E extends SpatialComparable, A> BitSet split(A entries, ArrayAdapter<E, A> getter, int minEntries);
+} \ No newline at end of file
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
new file mode 100644
index 00000000..1789ab22
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/TopologicalSplitter.java
@@ -0,0 +1,309 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.BitSet;
+
+import de.lmu.ifi.dbs.elki.data.HyperBoundingBox;
+import de.lmu.ifi.dbs.elki.data.ModifiableHyperBoundingBox;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayAdapter;
+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.DoubleIntPair;
+
+/**
+ * Encapsulates the required parameters for a topological split of a R*-Tree.
+ *
+ * @author Elke Achtert
+ *
+ * @apiviz.has Split
+ */
+@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 TopologicalSplitter implements SplitStrategy {
+ /**
+ * Static instance.
+ */
+ public static final TopologicalSplitter STATIC = new TopologicalSplitter();
+
+ /**
+ * constructor.
+ */
+ public TopologicalSplitter() {
+ // Nothing to do.
+ }
+
+ @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.chooseSplitAxis(minEntries);
+ split.chooseSplitPoint(minEntries);
+
+ assert (split.splitPoint < split.size) : "Invalid split produced. Size: " + getter.size(entries) + " minEntries: " + minEntries + " split.size: " + split.size;
+ BitSet assignment = new BitSet(split.size);
+ for(int i = split.splitPoint; i < split.size; i++) {
+ assignment.set(split.bestSorting[i].second);
+ }
+ return assignment;
+ }
+
+ /**
+ * Internal data for an actual split.
+ *
+ * @author Erich Schubert
+ *
+ * @param <E> Actual entry type
+ */
+ private class Split<A, E extends SpatialComparable> {
+ /**
+ * The index of the split point.
+ */
+ int splitPoint = -1;
+
+ /**
+ * Indicates whether the sorting according to maximal or to minimal value
+ * has been used for choosing the split axis and split point.
+ */
+ DoubleIntPair[] bestSorting;
+
+ /**
+ * The entries sorted according to their max values of their MBRs.
+ */
+ DoubleIntPair[] maxSorting;
+
+ /**
+ * The entries sorted according to their min values of their MBRs.
+ */
+ DoubleIntPair[] minSorting;
+
+ /**
+ * The entries we process.
+ */
+ private A entries;
+
+ /**
+ * The getter class for the entries
+ */
+ private ArrayAdapter<E, A> getter;
+
+ /**
+ * List size
+ */
+ private int size;
+
+ /**
+ * Dimensionality
+ */
+ private int dimensionality;
+
+ /**
+ * Constructor.
+ */
+ public Split(A entries, ArrayAdapter<E, A> getter) {
+ this.entries = entries;
+ this.getter = getter;
+ this.size = getter.size(entries);
+ this.dimensionality = getter.get(entries, 0).getDimensionality();
+ initMinMaxArrays();
+ }
+
+ /**
+ * Chooses a split axis.
+ *
+ * @param minEntries number of minimum entries in the node to be split
+ */
+ void chooseSplitAxis(int minEntries) {
+ // best value for the surface
+ double minSurface = Double.MAX_VALUE;
+ int splitAxis = -1;
+
+ for(int d = 1; d <= dimensionality; d++) {
+ double sumOfAllMargins = 0;
+ fillAndSort(d);
+
+ // Note: this has a somewhat surprising evaluation order.
+ // We compute the sum as in the original paper:
+ // it says "sum of all margin-values".
+ // Except that we don't match them as you would do in a split, but
+ // Iterate over all possible splits from both sides (as well as min and
+ // max) in parallel, since union can be computed incrementally.
+ ModifiableHyperBoundingBox mbr_min_left = new ModifiableHyperBoundingBox(get(minSorting[0]));
+ ModifiableHyperBoundingBox mbr_min_right = new ModifiableHyperBoundingBox(get(minSorting[size - 1]));
+ ModifiableHyperBoundingBox mbr_max_left = new ModifiableHyperBoundingBox(get(maxSorting[0]));
+ ModifiableHyperBoundingBox mbr_max_right = new ModifiableHyperBoundingBox(get(maxSorting[size - 1]));
+
+ for(int k = 1; k < size - minEntries; k++) {
+ mbr_min_left.extend(get(minSorting[k]));
+ mbr_min_right.extend(get(minSorting[size - 1 - k]));
+ mbr_max_left.extend(get(maxSorting[k]));
+ mbr_max_right.extend(get(maxSorting[size - 1 - k]));
+ if(k >= minEntries - 1) {
+ // Yes, build the sum. This value is solely used for finding the
+ // preferred split axis!
+ // Note that mbr_min_left and mbr_max_left do not add up to a
+ // complete split, but when the sum is complete, it will also
+ // include their proper counterpart.
+ sumOfAllMargins += SpatialUtil.perimeter(mbr_min_left) + SpatialUtil.perimeter(mbr_min_right) + SpatialUtil.perimeter(mbr_max_left) + SpatialUtil.perimeter(mbr_max_right);
+ }
+ }
+ if(sumOfAllMargins < minSurface) {
+ splitAxis = d;
+ minSurface = sumOfAllMargins;
+ }
+ }
+ if(splitAxis != dimensionality) {
+ fillAndSort(splitAxis);
+ }
+ }
+
+ /**
+ * Init the arrays we use
+ */
+ protected void initMinMaxArrays() {
+ maxSorting = new DoubleIntPair[size];
+ minSorting = new DoubleIntPair[size];
+ // Prefill
+ for(int j = 0; j < size; j++) {
+ minSorting[j] = new DoubleIntPair(0, -1);
+ maxSorting[j] = new DoubleIntPair(0, -1);
+ }
+ }
+
+ /**
+ * Fill the array with the dimension projection needed for sorting.
+ *
+ * @param dim Relevant dimension.
+ */
+ protected void fillAndSort(final int dim) {
+ // sort the entries according to their minimal and according to their
+ // maximal value in the current dimension.
+ for(int j = 0; j < size; j++) {
+ E e = get(j);
+ minSorting[j].first = e.getMin(dim);
+ minSorting[j].second = j;
+ maxSorting[j].first = e.getMax(dim);
+ maxSorting[j].second = j;
+ }
+ Arrays.sort(minSorting);
+ Arrays.sort(maxSorting);
+ }
+
+ /**
+ * Chooses a split axis.
+ *
+ * @param minEntries number of minimum entries in the node to be split
+ */
+ void chooseSplitPoint(int minEntries) {
+ // the split point (first set to minimum entries in the node)
+ splitPoint = size;
+ // best value for the overlap
+ double minOverlap = Double.POSITIVE_INFINITY;
+ // the volume of mbr1 and mbr2
+ double volume = Double.POSITIVE_INFINITY;
+ // indicates whether the sorting according to maximal or to minimal value
+ // is best for the split axis
+ bestSorting = null;
+
+ assert (size - 2 * minEntries > 0) : "Cannot split underfull nodes.";
+ // test the sorting with respect to the minimal values
+ {
+ ModifiableHyperBoundingBox mbr1 = mbr(minSorting, 0, minEntries - 1);
+ for(int i = 0; i <= size - 2 * minEntries; i++) {
+ mbr1.extend(getter.get(entries, minSorting[minEntries + i - 1].second));
+ HyperBoundingBox mbr2 = mbr(minSorting, minEntries + i, size);
+ double currentOverlap = SpatialUtil.relativeOverlap(mbr1, mbr2);
+ if(currentOverlap <= minOverlap) {
+ double vol = SpatialUtil.volume(mbr1) + SpatialUtil.volume(mbr2);
+ if(currentOverlap < minOverlap || vol < volume) {
+ minOverlap = currentOverlap;
+ volume = vol;
+ splitPoint = minEntries + i;
+ bestSorting = minSorting;
+ }
+ }
+ }
+ }
+ // test the sorting with respect to the maximal values
+ {
+ ModifiableHyperBoundingBox mbr1 = mbr(maxSorting, 0, minEntries - 1);
+ for(int i = 0; i <= size - 2 * minEntries; i++) {
+ mbr1.extend(getter.get(entries, maxSorting[minEntries + i - 1].second));
+ HyperBoundingBox mbr2 = mbr(maxSorting, minEntries + i, size);
+ double currentOverlap = SpatialUtil.relativeOverlap(mbr1, mbr2);
+ if(currentOverlap <= minOverlap) {
+ double vol = SpatialUtil.volume(mbr1) + SpatialUtil.volume(mbr2);
+ if(currentOverlap < minOverlap || vol < volume) {
+ minOverlap = currentOverlap;
+ volume = vol;
+ splitPoint = minEntries + i;
+ bestSorting = maxSorting;
+ }
+ }
+ }
+ }
+ assert (splitPoint < size) : "No split found? Volume outside of double precision?";
+ }
+
+ private E get(int off) {
+ return getter.get(entries, off);
+ }
+
+ private E get(DoubleIntPair pair) {
+ return getter.get(entries, pair.second);
+ }
+
+ /**
+ * Computes and returns the mbr of the specified nodes, only the nodes
+ * between from and to index are considered.
+ *
+ * @param sorting the array of nodes
+ * @param from the start index
+ * @param to the end index
+ * @return the mbr of the specified nodes
+ */
+ private ModifiableHyperBoundingBox mbr(final DoubleIntPair[] sorting, final int from, final int to) {
+ ModifiableHyperBoundingBox mbr = new ModifiableHyperBoundingBox(get(sorting[from]));
+ for(int i = from + 1; i < to; i++) {
+ mbr.extend(get(sorting[i]));
+ }
+ return mbr;
+ }
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ @Override
+ protected TopologicalSplitter makeInstance() {
+ return TopologicalSplitter.STATIC;
+ }
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..9e8291be
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/package-info.java
@@ -0,0 +1,26 @@
+/**
+ * <p>Splitting strategies for R-Trees</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.spatial.rstarvariants.strategies.split; \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/ApproximateLeastOverlapInsertionStrategy.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/ApproximateLeastOverlapInsertionStrategy.java
deleted file mode 100644
index 1e9afdca..00000000
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/ApproximateLeastOverlapInsertionStrategy.java
+++ /dev/null
@@ -1,150 +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) 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 java.util.Collections;
-
-import de.lmu.ifi.dbs.elki.data.HyperBoundingBox;
-import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
-import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil;
-import de.lmu.ifi.dbs.elki.index.tree.Node;
-import de.lmu.ifi.dbs.elki.index.tree.TreeIndexPathComponent;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry;
-import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.TopBoundedHeap;
-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.pairs.FCPair;
-
-/**
- * Insertion strategy that exhaustively tests all childs for the least overlap
- * when inserting.
- *
- * @author Elke Achtert
- * @author Franz Graf
- * @author Marisa Petri
- */
-public class ApproximateLeastOverlapInsertionStrategy implements InsertionStrategy {
- /**
- * Defines how many children are tested for finding the child generating the
- * least overlap when inserting an object. Default 0 means all children
- */
- private int insertionCandidates = 0;
-
- /**
- * Constructor. s
- *
- * @param insertionCandidates Number of children to test.
- */
- public ApproximateLeastOverlapInsertionStrategy(int insertionCandidates) {
- super();
- this.insertionCandidates = insertionCandidates;
- }
-
- /**
- * Returns the path information of the entry of the specified node which needs
- * least overlap enlargement if the given mbr would be inserted into.
- *
- * @param node the node of which the children should be tested
- * @param mbr the mbr to be inserted into the children
- * @return the path information of the entry which needs least overlap
- * enlargement if the given mbr would be inserted into
- */
- @Override
- public <N extends Node<E>, E extends SpatialEntry> TreeIndexPathComponent<E> findInsertChild(N node, SpatialComparable mbr) {
- Enlargement<E> min = null;
-
- TopBoundedHeap<FCPair<Double, E>> entriesToTest = new TopBoundedHeap<FCPair<Double, E>>(insertionCandidates, Collections.reverseOrder());
- for(int i = 0; i < node.getNumEntries(); i++) {
- E entry_i = node.getEntry(i);
- HyperBoundingBox newMBR = SpatialUtil.unionTolerant(mbr, entry_i);
- double volume = /* entry_i.getMBR() == null ? 0 : */SpatialUtil.volume(entry_i);
- double inc_volume = SpatialUtil.volume(newMBR) - volume;
- entriesToTest.add(new FCPair<Double, E>(inc_volume, entry_i));
- }
-
- while(!entriesToTest.isEmpty()) {
- E entry_i = entriesToTest.poll().getSecond();
- int index = -1;
- HyperBoundingBox newMBR = SpatialUtil.unionTolerant(mbr, entry_i);
-
- double currOverlap = 0;
- double newOverlap = 0;
- for(int k = 0; k < node.getNumEntries(); k++) {
- E entry_k = node.getEntry(k);
- if(entry_i != entry_k) {
- currOverlap += SpatialUtil.relativeOverlap(entry_i, entry_k);
- newOverlap += SpatialUtil.relativeOverlap(newMBR, entry_k);
- }
- else {
- index = k;
- }
- }
-
- double volume = /* entry_i.getMBR() == null ? 0 : */SpatialUtil.volume(entry_i);
- double inc_volume = SpatialUtil.volume(newMBR) - volume;
- double inc_overlap = newOverlap - currOverlap;
- Enlargement<E> enlargement = new Enlargement<E>(new TreeIndexPathComponent<E>(entry_i, index), volume, inc_volume, inc_overlap);
-
- if(min == null || min.compareTo(enlargement) > 0) {
- min = enlargement;
- }
- }
-
- assert min != null;
- return min.getPathComponent();
- }
-
- /**
- * Parameterization class.
- *
- * @author Erich Schubert
- *
- * @apiviz.exclude
- */
- public static class Parameterizer extends AbstractParameterizer {
- /**
- * Fast-insertion parameter. Optional.
- */
- public static OptionID INSERTION_CANDIDATES_ID = OptionID.getOrCreateOptionID("rtree.insertion-candidates", "defines how many children are tested for finding the child generating the least overlap when inserting an object.");
-
- int insertionCandidates = 0;
-
- @Override
- protected void makeOptions(Parameterization config) {
- super.makeOptions(config);
- IntParameter insertionCandidatesP = new IntParameter(INSERTION_CANDIDATES_ID, new GreaterConstraint(0));
- if(config.grab(insertionCandidatesP)) {
- insertionCandidates = insertionCandidatesP.getValue();
- }
- }
-
- @Override
- protected ApproximateLeastOverlapInsertionStrategy makeInstance() {
- return new ApproximateLeastOverlapInsertionStrategy(insertionCandidates);
- }
- }
-} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/Enlargement.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/Enlargement.java
deleted file mode 100644
index 79c8c0ef..00000000
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/Enlargement.java
+++ /dev/null
@@ -1,119 +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) 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.index.tree.DirectoryEntry;
-import de.lmu.ifi.dbs.elki.index.tree.TreeIndexPathComponent;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry;
-
-/**
- * Encapsulates the parameters for enlargement of nodes after insertion of new
- * objects.
- *
- * @author Elke Achtert
- * @param <E> Entry type
- */
-public class Enlargement<E extends SpatialEntry> implements Comparable<Enlargement<E>> {
- /**
- * The path information of the entry representing the node.
- */
- private TreeIndexPathComponent<E> pathComponent;
-
- /**
- * The volume of the node's MBR.
- */
- private double volume;
-
- /**
- * The increment of the volume.
- */
- private double volInc;
-
- /**
- * The increment of the overlap.
- */
- private double overlapInc;
-
- /**
- * Creates an new Enlargement object with the specified parameters.
- *
- * @param pathComponent the path information of the entry representing the
- * node
- * @param volume the volume of the node's MBR
- * @param volInc the increment of the volume
- * @param overlapInc the increment of the overlap
- */
- public Enlargement(TreeIndexPathComponent<E> pathComponent, double volume, double volInc, double overlapInc) {
- this.pathComponent = pathComponent;
- this.volume = volume;
- this.volInc = volInc;
- this.overlapInc = overlapInc;
- }
-
- /**
- * Compares this Enlargement with the specified Enlargement. First the
- * increment of the overlap will be compared. If both are equal the increment
- * of the volume will be compared. If also both are equal the volumes of both
- * nodes will be compared. If both are equal the ids of the nodes will be
- * compared.
- *
- * @param other the Enlargement to be compared.
- * @return a negative integer, zero, or a positive integer as this Enlargement
- * is less than, equal to, or greater than the specified Enlargement.
- */
- @Override
- public int compareTo(Enlargement<E> other) {
- if(this.overlapInc < other.overlapInc) {
- return -1;
- }
- if(this.overlapInc > other.overlapInc) {
- return +1;
- }
-
- if(this.volInc < other.volInc) {
- return -1;
- }
- if(this.volInc > other.volInc) {
- return +1;
- }
-
- if(this.volume < other.volume) {
- return -1;
- }
- if(this.volume > other.volume) {
- return +1;
- }
-
- return ((DirectoryEntry)this.pathComponent.getEntry()).getPageID() - ((DirectoryEntry)other.pathComponent.getEntry()).getPageID();
- }
-
- /**
- * Returns the path information of the entry representing the node.
- *
- * @return the path information of the entry representing the node
- */
- public TreeIndexPathComponent<E> getPathComponent() {
- return pathComponent;
- }
-} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/LeastOverlapInsertionStrategy.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/LeastOverlapInsertionStrategy.java
deleted file mode 100644
index 90f0c91b..00000000
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/LeastOverlapInsertionStrategy.java
+++ /dev/null
@@ -1,87 +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) 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.HyperBoundingBox;
-import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
-import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil;
-import de.lmu.ifi.dbs.elki.index.tree.Node;
-import de.lmu.ifi.dbs.elki.index.tree.TreeIndexPathComponent;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry;
-
-/**
- * Insertion strategy that exhaustively tests all childs for the least overlap
- * when inserting.
- *
- * @author Elke Achtert
- */
-public class LeastOverlapInsertionStrategy implements InsertionStrategy {
- /**
- * Constructor.
- */
- public LeastOverlapInsertionStrategy() {
- super();
- }
-
- /**
- * Returns the path information of the entry of the specified node which needs
- * least overlap enlargement if the given mbr would be inserted into.
- *
- * @param node the node of which the children should be tested
- * @param mbr the mbr to be inserted into the children
- * @return the path information of the entry which needs least overlap
- * enlargement if the given mbr would be inserted into
- */
- @Override
- public <N extends Node<E>, E extends SpatialEntry> TreeIndexPathComponent<E> findInsertChild(N node, SpatialComparable mbr) {
- Enlargement<E> min = null;
-
- for(int i = 0; i < node.getNumEntries(); i++) {
- E entry_i = node.getEntry(i);
- HyperBoundingBox newMBR = SpatialUtil.unionTolerant(mbr, entry_i);
-
- double currOverlap = 0;
- double newOverlap = 0;
- for(int k = 0; k < node.getNumEntries(); k++) {
- if(i != k) {
- E entry_k = node.getEntry(k);
- currOverlap += SpatialUtil.relativeOverlap(entry_i, entry_k);
- newOverlap += SpatialUtil.relativeOverlap(newMBR, entry_k);
- }
- }
-
- double volume = /* entry_i.getMBR() == null ? 0 : */SpatialUtil.volume(entry_i);
- double inc_volume = SpatialUtil.volume(newMBR) - volume;
- double inc_overlap = newOverlap - currOverlap;
- Enlargement<E> enlargement = new Enlargement<E>(new TreeIndexPathComponent<E>(entry_i, i), volume, inc_volume, inc_overlap);
-
- if(min == null || min.compareTo(enlargement) > 0) {
- min = enlargement;
- }
- }
-
- assert min != null;
- return min.getPathComponent();
- }
-}
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
new file mode 100644
index 00000000..3bf35d9d
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/NodeArrayAdapter.java
@@ -0,0 +1,58 @@
+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 de.lmu.ifi.dbs.elki.index.tree.AbstractNode;
+import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayAdapter;
+
+/**
+ * Access the entries of a node as array-like.
+ *
+ * @author Erich Schubert
+ */
+public class NodeArrayAdapter implements ArrayAdapter<SpatialEntry, AbstractNode<? extends SpatialEntry>> {
+ /**
+ * Static adapter.
+ */
+ public static NodeArrayAdapter STATIC = new NodeArrayAdapter();
+
+ /**
+ * Constructor.
+ */
+ protected NodeArrayAdapter() {
+ super();
+ // TODO Auto-generated constructor stub
+ }
+
+ @Override
+ public int size(AbstractNode<? extends SpatialEntry> array) {
+ return array.getNumEntries();
+ }
+
+ @Override
+ public SpatialEntry get(AbstractNode<? extends SpatialEntry> array, int off) throws IndexOutOfBoundsException {
+ return array.getEntry(off);
+ }
+} \ No newline at end of file
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
index fe3f322b..2f1ea9b1 100644
--- 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
@@ -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) 2011
+ Copyright (C) 2012
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/TopologicalSplitter.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/TopologicalSplitter.java
deleted file mode 100644
index 011e56ab..00000000
--- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/TopologicalSplitter.java
+++ /dev/null
@@ -1,270 +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) 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 java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import de.lmu.ifi.dbs.elki.data.HyperBoundingBox;
-import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
-import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil;
-import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry;
-import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
-import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
-
-/**
- * Encapsulates the required parameters for a topological split of a R*-Tree.
- *
- * @author Elke Achtert
- *
- * @apiviz.has Split
- * @apiviz.uses SpatialComparator
- */
-@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 TopologicalSplitter implements SplitStrategy<SpatialEntry> {
- /**
- * constructor.
- */
- public TopologicalSplitter() {
- // Nothing to do.
- }
-
- @Override
- public <E extends SpatialEntry> Pair<List<E>, List<E>> split(List<E> entries, int minEntries) {
- Split<E> split = new Split<E>();
- split.chooseSplitAxis(entries, minEntries);
- split.chooseSplitPoint(minEntries);
- int splitpoint = split.getSplitPoint();
- List<E> sorted = split.getBestSorting();
-
- return new Pair<List<E>, List<E>>(sorted.subList(0, splitpoint), sorted.subList(splitpoint, sorted.size()));
- }
-
- /**
- * Internal data for an actual split.
- *
- * @author Erich Schubert
- *
- * @param <E> Actual entry type
- */
- private class Split<E extends SpatialEntry> {
- /**
- * The split axis.
- */
- int splitAxis = 0;
-
- /**
- * The index of the split point.
- */
- int splitPoint = -1;
-
- /**
- * Indicates whether the sorting according to maximal or to minimal value
- * has been used for choosing the split axis and split point.
- */
- int bestSorting;
-
- /**
- * The entries sorted according to their max values of their MBRs.
- */
- List<E> maxSorting;
-
- /**
- * The entries sorted according to their min values of their MBRs.
- */
- List<E> minSorting;
-
- /**
- * Constructor.
- */
- public Split() {
- // Initialized by calling chooseSplitAxis.
- }
-
- /**
- * Chooses a split axis.
- *
- * @param entries the entries to be split
- * @param minEntries number of minimum entries in the node to be split
- */
- void chooseSplitAxis(List<E> entries, int minEntries) {
- int dim = entries.get(0).getDimensionality();
-
- maxSorting = new ArrayList<E>(entries);
- minSorting = new ArrayList<E>(entries);
-
- // best value for the surface
- double minSurface = Double.MAX_VALUE;
- // comparator used by sort method
-
- for(int i = 1; i <= dim; i++) {
- double sumOfAllMargins = 0;
- // sort the entries according to their minimal and according to their
- // maximal value
- final SpatialComparator compMin = new SpatialComparator(i, SpatialComparator.MIN);
- Collections.sort(minSorting, compMin);
- final SpatialComparator compMax = new SpatialComparator(i, SpatialComparator.MAX);
- Collections.sort(maxSorting, compMax);
-
- SpatialComparable mbr_min_left = minSorting.get(0);
- SpatialComparable mbr_min_right = minSorting.get(minSorting.size() - 1);
- SpatialComparable mbr_max_left = maxSorting.get(0);
- SpatialComparable mbr_max_right = maxSorting.get(maxSorting.size() - 1);
-
- for(int k = 1; k < entries.size() - minEntries; k++) {
- mbr_min_left = SpatialUtil.union(mbr_min_left, minSorting.get(k));
- mbr_min_right = SpatialUtil.union(mbr_min_right, minSorting.get(minSorting.size() - 1 - k));
- mbr_max_left = SpatialUtil.union(mbr_max_left, maxSorting.get(k));
- mbr_max_right = SpatialUtil.union(mbr_max_right, maxSorting.get(maxSorting.size() - 1 - k));
- if(k >= minEntries - 1) {
- // Yes, build the sum. This value is solely used for finding the
- // split axis!
- // Compare with the original paper, "sum of all margin-values".
- // Note that mbr_min_left and mbr_max_left do not add up to a
- // complete split, but when the sum is complete, it will also
- // include their proper counterpart.
- sumOfAllMargins += SpatialUtil.perimeter(mbr_min_left) + SpatialUtil.perimeter(mbr_min_right) + SpatialUtil.perimeter(mbr_max_left) + SpatialUtil.perimeter(mbr_max_right);
- }
- }
- if(sumOfAllMargins < minSurface) {
- splitAxis = i;
- minSurface = sumOfAllMargins;
- }
- }
- }
-
- /**
- * Chooses a split axis.
- *
- * @param minEntries number of minimum entries in the node to be split
- */
- void chooseSplitPoint(int minEntries) {
- // numEntries
- int numEntries = maxSorting.size();
- // sort upper and lower in the right dimension
- final SpatialComparator compMin = new SpatialComparator(splitAxis, SpatialComparator.MIN);
- Collections.sort(minSorting, compMin);
- final SpatialComparator compMax = new SpatialComparator(splitAxis, SpatialComparator.MAX);
- Collections.sort(maxSorting, compMax);
-
- // the split point (first set to minimum entries in the node)
- splitPoint = minEntries;
- // best value for the overlap
- double minOverlap = Double.MAX_VALUE;
- // the volume of mbr1 and mbr2
- double volume = 0.0;
- // indicates whether the sorting according to maximal or to minimal value
- // is
- // best for the split axis
- bestSorting = -1;
-
- for(int i = 0; i <= numEntries - 2 * minEntries; i++) {
- // test the sorting with respect to the minimal values
- HyperBoundingBox mbr1 = mbr(minSorting, 0, minEntries + i);
- HyperBoundingBox mbr2 = mbr(minSorting, minEntries + i, numEntries);
- double currentOverlap = SpatialUtil.relativeOverlap(mbr1, mbr2);
- double vol1 = SpatialUtil.volume(mbr1);
- double vol2 = SpatialUtil.volume(mbr2);
- if(currentOverlap < minOverlap || (currentOverlap == minOverlap && (vol1 + vol2) < volume)) {
- minOverlap = currentOverlap;
- splitPoint = minEntries + i;
- bestSorting = SpatialComparator.MIN;
- volume = vol1 + vol2;
- }
- // test the sorting with respect to the maximal values
- mbr1 = mbr(maxSorting, 0, minEntries + i);
- mbr2 = mbr(maxSorting, minEntries + i, numEntries);
- currentOverlap = SpatialUtil.relativeOverlap(mbr1, mbr2);
- vol1 = SpatialUtil.volume(mbr1);
- vol2 = SpatialUtil.volume(mbr2);
- if(currentOverlap < minOverlap || (currentOverlap == minOverlap && (vol1 + vol2) < volume)) {
- minOverlap = currentOverlap;
- splitPoint = minEntries + i;
- bestSorting = SpatialComparator.MAX;
- volume = vol1 + vol2;
- }
- }
- }
-
- /**
- * Computes and returns the mbr of the specified nodes, only the nodes
- * between from and to index are considered.
- *
- * @param entries the array of nodes
- * @param from the start index
- * @param to the end index
- * @return the mbr of the specified nodes
- */
- private HyperBoundingBox mbr(final List<E> entries, final int from, final int to) {
- double[] min = new double[entries.get(from).getDimensionality()];
- double[] max = new double[entries.get(from).getDimensionality()];
-
- for(int d = 1; d <= min.length; d++) {
- min[d - 1] = entries.get(from).getMin(d);
- max[d - 1] = entries.get(from).getMax(d);
- }
-
- for(int i = from + 1; i < to; i++) {
- SpatialComparable currMBR = entries.get(i);
- for(int d = 1; d <= min.length; d++) {
- if(min[d - 1] > currMBR.getMin(d)) {
- min[d - 1] = currMBR.getMin(d);
- }
- if(max[d - 1] < currMBR.getMax(d)) {
- max[d - 1] = currMBR.getMax(d);
- }
- }
- }
- return new HyperBoundingBox(min, max);
- }
-
- /**
- * Returns the split point.
- *
- * @return the split point
- */
- public int getSplitPoint() {
- return splitPoint;
- }
-
- /**
- * Returns whether the sorting according to maximal or to minimal value has
- * been used for choosing the split axis and split point.
- *
- * @return The sorting to use
- */
- public List<E> getBestSorting() {
- if(bestSorting == SpatialComparator.MIN) {
- return minSorting;
- }
- if(bestSorting == SpatialComparator.MAX) {
- return maxSorting;
- }
- else {
- throw new IllegalStateException("split.bestSort is undefined: " + bestSorting);
- }
- }
- }
-}
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 382faeb3..10991028 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) 2011
+Copyright (C) 2012
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/VAFile.java b/src/de/lmu/ifi/dbs/elki/index/vafile/VAFile.java
new file mode 100644
index 00000000..c426c1d6
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/vafile/VAFile.java
@@ -0,0 +1,518 @@
+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) 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 java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+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.ids.DBID;
+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.DistanceResultPair;
+import de.lmu.ifi.dbs.elki.database.query.DoubleDistanceResultPair;
+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.KNNResult;
+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.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.utilities.DatabaseUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.Heap;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.KNNHeap;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.TopBoundedHeap;
+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.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.pairs.DoubleObjPair;
+
+/**
+ * Vector-approximation file (VAFile)
+ *
+ * Reference:
+ * <p>
+ * Weber, R. and Blott, S.<br>
+ * An approximation based data structure for similarity search<br />
+ * in: Report TR1997b, ETH Zentrum, Zurich, Switzerland
+ * </p>
+ *
+ * @author Thomas Bernecker
+ * @author Erich Schubert
+ */
+@Title("An approximation based data structure for similarity search")
+@Reference(authors = "Weber, R. and Blott, S.", title = "An approximation based data structure for similarity search", booktitle = "Report TR1997b, ETH Zentrum, Zurich, Switzerland", url = "http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.40.480&rep=rep1&type=pdf")
+public class VAFile<V extends NumberVector<?, ?>> extends AbstractRefiningIndex<V> implements KNNIndex<V>, RangeIndex<V> {
+ /**
+ * Logging class
+ */
+ private static final Logging log = Logging.getLogger(VAFile.class);
+
+ /**
+ * Approximation index
+ */
+ private List<VectorApproximation> vectorApprox;
+
+ /**
+ * Number of partitions.
+ */
+ private int partitions;
+
+ /**
+ * Quantile grid we use
+ */
+ private double[][] splitPositions;
+
+ /**
+ * Page size, for estimating the VA file size
+ */
+ int pageSize;
+
+ /**
+ * Number of scans we performed.
+ */
+ int scans;
+
+ /**
+ * Constructor.
+ *
+ * @param pageSize Page size of simulated index
+ * @param relation Relation to index
+ * @param partitions Number of partitions for each dimension.
+ */
+ public VAFile(int pageSize, Relation<V> relation, int partitions) {
+ super(relation);
+ this.partitions = partitions;
+ this.pageSize = pageSize;
+ this.scans = 0;
+ this.vectorApprox = new ArrayList<VectorApproximation>();
+ }
+
+ @Override
+ protected void initialize(Relation<V> relation, DBIDs ids) {
+ setPartitions(relation);
+ for(DBID id : relation.getDBIDs()) {
+ vectorApprox.add(calculateApproximation(id, relation.get(id)));
+ }
+ }
+
+ /**
+ * Initialize the data set grid by computing quantiles.
+ *
+ * @param relation Data relation
+ * @throws IllegalArgumentException
+ */
+ public void setPartitions(Relation<V> relation) throws IllegalArgumentException {
+ 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!");
+ }
+
+ final int dimensions = DatabaseUtil.dimensionality(relation);
+ final int size = relation.size();
+ splitPositions = new double[dimensions][partitions + 1];
+
+ for(int d = 0; d < dimensions; d++) {
+ double[] tempdata = new double[size];
+ int j = 0;
+ for(DBID id : relation.iterDBIDs()) {
+ tempdata[j] = relation.get(id).doubleValue(d + 1);
+ j += 1;
+ }
+ Arrays.sort(tempdata);
+
+ for(int b = 0; b < partitions; b++) {
+ int start = (int) (b * size / (double) partitions);
+ splitPositions[d][b] = tempdata[start];
+ }
+ // make sure that last object will be included
+ splitPositions[d][partitions] = tempdata[size - 1] + 0.000001;
+ }
+ }
+
+ /**
+ * Calculate the VA file position given the existing borders.
+ *
+ * @param id Object ID
+ * @param dv Data vector
+ * @return Vector approximation
+ */
+ public VectorApproximation calculateApproximation(DBID id, V dv) {
+ int approximation[] = new int[dv.getDimensionality()];
+ for(int d = 0; d < splitPositions.length; d++) {
+ final double val = dv.doubleValue(d + 1);
+ final int lastBorderIndex = splitPositions[d].length - 1;
+
+ // Value is below data grid
+ if(val < splitPositions[d][0]) {
+ approximation[d] = 0;
+ if(id != null) {
+ log.warning("Vector outside of VAFile grid!");
+ }
+ } // Value is above data grid
+ else if(val > splitPositions[d][lastBorderIndex]) {
+ approximation[d] = lastBorderIndex - 1;
+ if(id != null) {
+ log.warning("Vector outside of VAFile grid!");
+ }
+ } // normal case
+ else {
+ // Search grid position
+ int pos = Arrays.binarySearch(splitPositions[d], val);
+ pos = (pos >= 0) ? pos : ((-pos) - 2);
+ approximation[d] = pos;
+ }
+ }
+ 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.
+ */
+ public long getScannedPages() {
+ int vacapacity = pageSize / VectorApproximation.byteOnDisk(splitPositions.length, partitions);
+ int vasize = (int) Math.ceil((vectorApprox.size()) / (1.0 * vacapacity));
+ return vasize * scans;
+ }
+
+ @Override
+ public long getWriteOperations() {
+ return -1;
+ }
+
+ @Override
+ public void resetPageAccess() {
+ super.resetPageAccess();
+ scans = 0;
+ // FIXME: writes
+ }
+
+ @Override
+ public String getLongName() {
+ return "VA-file index";
+ }
+
+ @Override
+ public String getShortName() {
+ return "va-file";
+ }
+
+ @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) {
+ // FIXME: support bulk?
+ return null;
+ }
+ }
+ DistanceFunction<? super V, ?> df = distanceQuery.getDistanceFunction();
+ 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);
+ return (KNNQuery<V, D>) dq;
+ }
+ // Not supported.
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ @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) {
+ double p = ((LPNormDistanceFunction) df).getP();
+ DistanceQuery<V, ?> ddq = (DistanceQuery<V, ?>) distanceQuery;
+ RangeQuery<V, ?> dq = new VAFileRangeQuery((DistanceQuery<V, DoubleDistance>) ddq, p);
+ return (RangeQuery<V, D>) dq;
+ }
+ // Not supported.
+ return null;
+ }
+
+ /**
+ * Range query for this index.
+ *
+ * @author Erich Schubert
+ */
+ class VAFileRangeQuery extends AbstractRefiningIndex<V>.AbstractRangeQuery<DoubleDistance> {
+ /**
+ * LP Norm p parameter.
+ */
+ final double p;
+
+ /**
+ * Constructor.
+ *
+ * @param distanceQuery Distance query object
+ * @param p LP norm p
+ */
+
+ public VAFileRangeQuery(DistanceQuery<V, DoubleDistance> distanceQuery, double p) {
+ super(distanceQuery);
+ this.p = p;
+ }
+
+ @Override
+ public List<DistanceResultPair<DoubleDistance>> getRangeForObject(V query, DoubleDistance range) {
+ final double eps = range.doubleValue();
+ // generate query approximation and lookup table
+ VectorApproximation queryApprox = calculateApproximation(null, query);
+
+ // Approximative distance function
+ VALPNormDistance vadist = new VALPNormDistance(p, splitPositions, query, queryApprox);
+
+ // Count a VA file scan
+ scans += 1;
+
+ List<DistanceResultPair<DoubleDistance>> result = new ArrayList<DistanceResultPair<DoubleDistance>>();
+ // Approximation step
+ for(int i = 0; i < vectorApprox.size(); i++) {
+ VectorApproximation va = vectorApprox.get(i);
+ double minDist = vadist.getMinDist(va);
+
+ if(minDist > eps) {
+ continue;
+ }
+
+ // TODO: we don't need to refine always (maxDist < eps), if we are
+ // interested in the DBID only! But this needs an API change.
+
+ // refine the next element
+ final double dist = refine(va.id, query).doubleValue();
+ if(dist <= eps) {
+ result.add(new DoubleDistanceResultPair(dist, va.id));
+ }
+ }
+ Collections.sort(result);
+ return result;
+ }
+ }
+
+ /**
+ * KNN query for this index.
+ *
+ * @author Erich Schubert
+ */
+ class VAFileKNNQuery extends AbstractRefiningIndex<V>.AbstractKNNQuery<DoubleDistance> {
+ /**
+ * LP Norm p parameter.
+ */
+ final double p;
+
+ /**
+ * Constructor.
+ *
+ * @param distanceQuery Distance query object
+ * @param p LP norm p
+ */
+ public VAFileKNNQuery(DistanceQuery<V, DoubleDistance> distanceQuery, double p) {
+ super(distanceQuery);
+ this.p = p;
+ }
+
+ @Override
+ public KNNResult<DoubleDistance> getKNNForObject(V query, int k) {
+ // generate query approximation and lookup table
+ VectorApproximation queryApprox = calculateApproximation(null, query);
+
+ // Approximative distance function
+ VALPNormDistance vadist = new VALPNormDistance(p, splitPositions, query, queryApprox);
+
+ // Heap for the kth smallest maximum distance
+ Heap<Double> minMaxHeap = new TopBoundedHeap<Double>(k, Collections.reverseOrder());
+ double minMaxDist = Double.POSITIVE_INFINITY;
+ // Candidates with minDist <= kth maxDist
+ ArrayList<DoubleObjPair<DBID>> candidates = new ArrayList<DoubleObjPair<DBID>>(vectorApprox.size());
+
+ // Count a VA file scan
+ scans += 1;
+
+ // Approximation step
+ 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) {
+ continue;
+ }
+ candidates.add(new DoubleObjPair<DBID>(minDist, va.id));
+
+ // Update candidate pruning heap
+ minMaxHeap.add(maxDist);
+ if(minMaxHeap.size() >= k) {
+ minMaxDist = minMaxHeap.peek();
+ }
+ }
+ // sort candidates by lower bound (minDist)
+ Collections.sort(candidates);
+
+ // refinement step
+ KNNHeap<DoubleDistance> result = new KNNHeap<DoubleDistance>(k);
+
+ // log.fine("candidates size " + candidates.size());
+ // retrieve accurate distances
+ for(DoubleObjPair<DBID> va : candidates) {
+ // Stop when we are sure to have all elements
+ if(result.size() >= k) {
+ double kDist = result.getKNNDistance().doubleValue();
+ if(va.first > kDist) {
+ break;
+ }
+ }
+
+ // refine the next element
+ final double dist = refine(va.second, query).doubleValue();
+ result.add(new DoubleDistanceResultPair(dist, va.second));
+ }
+ if(log.isDebuggingFinest()) {
+ log.finest("query = (" + query + ")");
+ log.finest("database: " + vectorApprox.size() + ", candidates: " + candidates.size() + ", results: " + result.size());
+ }
+
+ return result.toKNNList();
+ }
+ }
+
+ /**
+ * Index factory class
+ *
+ * @author Erich Schubert
+ *
+ * @param <V> Vector type
+ */
+ public static class Factory<V extends NumberVector<?, ?>> implements IndexFactory<V, VAFile<V>> {
+ /**
+ * Number of partitions to use in each dimension.
+ *
+ * <pre>
+ * -vafile.partitions 8
+ * </pre>
+ */
+ public static final OptionID PARTITIONS_ID = OptionID.getOrCreateOptionID("vafile.partitions", "Number of partitions to use in each dimension.");
+
+ /**
+ * Page size
+ */
+ int pagesize = 1;
+
+ /**
+ * Number of partitions
+ */
+ int numpart = 2;
+
+ /**
+ * Constructor.
+ *
+ * @param pagesize Page size
+ * @param numpart Number of partitions
+ */
+ public Factory(int pagesize, int numpart) {
+ super();
+ this.pagesize = pagesize;
+ this.numpart = numpart;
+ }
+
+ @Override
+ public VAFile<V> instantiate(Relation<V> relation) {
+ return new VAFile<V>(pagesize, relation, numpart);
+ }
+
+ @Override
+ public TypeInformation getInputTypeRestriction() {
+ return TypeUtil.NUMBER_VECTOR_FIELD;
+ }
+
+ /**
+ * Parameterization class
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ /**
+ * Page size
+ */
+ int pagesize = 1;
+
+ /**
+ * Number of partitions
+ */
+ int numpart = 2;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ IntParameter pagesizeP = new IntParameter(TreeIndexFactory.PAGE_SIZE_ID, new GreaterConstraint(0), 1024);
+ if(config.grab(pagesizeP)) {
+ pagesize = pagesizeP.getValue();
+ }
+ IntParameter partitionsP = new IntParameter(Factory.PARTITIONS_ID, new GreaterConstraint(2));
+ if(config.grab(partitionsP)) {
+ numpart = partitionsP.getValue();
+ }
+ }
+
+ @Override
+ protected Factory<?> makeInstance() {
+ return new Factory<NumberVector<?, ?>>(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
new file mode 100644
index 00000000..77815c97
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/vafile/VALPNormDistance.java
@@ -0,0 +1,169 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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;
+
+/**
+ * Lp-Norm distance function for partially computed objects
+ *
+ * @author Erich Schubert
+ */
+public class VALPNormDistance {
+ /**
+ * Value of 1/p for lP norm
+ */
+ private final double onebyp;
+
+ /**
+ * Lookup table for grid cells
+ */
+ private double[][] lookup;
+
+ /**
+ * Approximation of the query vector
+ */
+ private VectorApproximation queryApprox;
+
+ /**
+ * Constructor.
+ *
+ * @param p Value of p
+ * @param splitPositions Split positions
+ * @param query Query vector
+ * @param queryApprox
+ */
+ public VALPNormDistance(double p, double[][] splitPositions, NumberVector<?, ?> query, VectorApproximation queryApprox) {
+ super();
+ this.onebyp = 1.0 / p;
+ this.queryApprox = queryApprox;
+ initializeLookupTable(splitPositions, query, p);
+ }
+
+ /**
+ * Get the minimum distance contribution of a single dimension
+ *
+ * @param dimension Dimension
+ * @param vp Vector position
+ * @return Increment
+ */
+ public double getPartialMinDist(int dimension, int vp) {
+ final int qp = queryApprox.getApproximation(dimension);
+ if(vp < qp) {
+ return lookup[dimension][vp + 1];
+ }
+ else if(vp > qp) {
+ return lookup[dimension][vp];
+ }
+ else {
+ return 0.0;
+ }
+ }
+
+ /**
+ * Get the minimum distance to approximated vector vec
+ *
+ * @param vec Vector approximation
+ * @return Minimum distance
+ */
+ public double getMinDist(VectorApproximation vec) {
+ final int dim = lookup.length;
+ double minDist = 0;
+ for(int d = 0; d < dim; d++) {
+ final int vp = vec.getApproximation(d);
+ minDist += getPartialMinDist(d, vp);
+ }
+ return Math.pow(minDist, onebyp);
+ }
+
+ /**
+ * Get the maximum distance contribution of a single dimension
+ *
+ * @param dimension Dimension
+ * @param vp Vector position
+ * @return Increment
+ */
+ public double getPartialMaxDist(int dimension, int vp) {
+ final int qp = queryApprox.getApproximation(dimension);
+ if(vp < qp) {
+ return lookup[dimension][vp];
+ }
+ else if(vp > qp) {
+ return lookup[dimension][vp + 1];
+ }
+ else {
+ return Math.max(lookup[dimension][vp], lookup[dimension][vp + 1]);
+ }
+ }
+
+ /**
+ * Get the maximum distance.
+ *
+ * @param vec Approximation vector
+ * @return Maximum distance of the vector
+ */
+ public double getMaxDist(VectorApproximation vec) {
+ final int dim = lookup.length;
+ double maxDist = 0;
+ for(int d = 0; d < dim; d++) {
+ final int vp = vec.getApproximation(d);
+ maxDist += getPartialMaxDist(d, vp);
+ }
+ return Math.pow(maxDist, onebyp);
+ }
+
+ /**
+ * Get the maximum distance.
+ *
+ * @param dimension Dimension
+ * @return Maximum distance in the given dimension
+ */
+ public double getPartialMaxMaxDist(int dimension) {
+ double[] data = lookup[dimension];
+ double max = data[0];
+ for(int i = 1; i < data.length; i++) {
+ max = Math.max(max, data[i]);
+ }
+ return max;
+ }
+
+ /**
+ * Initialize the lookup table
+ *
+ * @param splitPositions Split positions
+ * @param query Query vector
+ * @param p p
+ */
+ private void initializeLookupTable(double[][] splitPositions, NumberVector<?, ?> query, double p) {
+ final int dimensions = splitPositions.length;
+ final int bordercount = splitPositions[0].length;
+ lookup = new double[dimensions][bordercount];
+ for(int d = 0; d < dimensions; d++) {
+ final double val = query.doubleValue(d + 1);
+ for(int i = 0; i < bordercount; i++) {
+ lookup[d][i] = Math.pow(splitPositions[d][i] - val, p);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/index/vafile/VectorApproximation.java b/src/de/lmu/ifi/dbs/elki/index/vafile/VectorApproximation.java
new file mode 100644
index 00000000..4b170eb8
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/vafile/VectorApproximation.java
@@ -0,0 +1,103 @@
+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) 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 java.util.Arrays;
+
+import de.lmu.ifi.dbs.elki.database.ids.DBID;
+
+/**
+ * Object in a VA approximation.
+ *
+ * @author Thomas Bernecker
+ * @author Erich Schubert
+ */
+public class VectorApproximation {
+ /**
+ * approximation (va cell ids)
+ */
+ int[] approximation;
+
+ /**
+ * Object represented by this approximation
+ */
+ protected DBID id;
+
+ /**
+ * Constructor.
+ *
+ * @param id Object represented (may be <code>null</code> for query objects)
+ * @param approximation Approximation
+ */
+ public VectorApproximation(DBID id, int[] approximation) {
+ super();
+ this.id = id;
+ this.approximation = approximation;
+ }
+
+ /**
+ * @return the id
+ */
+ public DBID getId() {
+ return id;
+ }
+
+ /**
+ * Get the dimensionality
+ *
+ * @return Dimensionality
+ */
+ public int getDimensionality() {
+ return approximation.length;
+ }
+
+ /**
+ * Get the VA approximation
+ *
+ * @param dim Dimension
+ * @return Bin number
+ */
+ public int getApproximation(int dim) {
+ return approximation[dim];
+ }
+
+ @Override
+ public String toString() {
+ return id + " (" + Arrays.toString(approximation) + ")";
+ }
+
+ /**
+ * Computes IO costs (in bytes) needed for reading the candidates. For one
+ * object, log2(numberOfPartitions) bits have to be read per dimension.
+ *
+ * @param numberOfDimensions the number of relevant dimensions
+ * @param numberOfPartitions the number of relevant partitions
+ * @return the cost values (in bytes)
+ */
+ //nicht gleich in bytes umwandeln, sonst rundungsfehler erst nachdem *anzahl objekte
+ public static int byteOnDisk(int numberOfDimensions, int numberOfPartitions) {
+ //(partition*dimension+id) alles in Bit 32bit für 4 byte id
+ return (int) (Math.ceil(numberOfDimensions * ((Math.log(numberOfPartitions) / Math.log(2)))+32) /8);
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..f38b1dca
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/index/vafile/package-info.java
@@ -0,0 +1,27 @@
+/**
+ * <p>Vector Approximation File</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/>.
+ */
+// TODO: add projected VA files, allow different binning and projection strategies.
+package de.lmu.ifi.dbs.elki.index.vafile; \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/logging/CLISmartHandler.java b/src/de/lmu/ifi/dbs/elki/logging/CLISmartHandler.java
index c425e5fb..4aa6f89b 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) 2011
+ Copyright (C) 2012
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 211b788b..98a25b01 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) 2011
+ Copyright (C) 2012
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 a2d43bbc..ea412905 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) 2011
+ Copyright (C) 2012
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/LoggingConfiguration.java b/src/de/lmu/ifi/dbs/elki/logging/LoggingConfiguration.java
index 2d191f7c..e6a61bef 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -48,7 +48,7 @@ public final class LoggingConfiguration {
/**
* Configuration file name
*/
- private static final String CLIConffile = "logging-cli.properties";
+ private static final String LOGGING_PROPERTIES_FILE = "logging.properties";
/**
* Top level ELKI package (for setting 'verbose')
@@ -63,7 +63,7 @@ public final class LoggingConfiguration {
/**
* Static instance of the configuration
*/
- protected static LoggingConfiguration config = new LoggingConfiguration(confbase, CLIConffile);
+ protected static LoggingConfiguration config = new LoggingConfiguration(confbase, LOGGING_PROPERTIES_FILE);
/**
* Configure Java Logging API: {@link java.util.logging.LogManager}
@@ -95,8 +95,15 @@ public final class LoggingConfiguration {
if(pkg == null) {
pkg = "";
}
- // Load logging configuration from resources.
- String cfgfile = pkg.replace('.', File.separatorChar) + File.separatorChar + name;
+ // Load logging configuration from current directory
+ String cfgfile = name;
+ if(new File(name).exists()) {
+ cfgfile = name;
+ }
+ else {
+ // Fall back to full path / resources.
+ cfgfile = pkg.replace('.', File.separatorChar) + File.separatorChar + name;
+ }
try {
InputStream cfgdata = FileUtil.openSystemFile(cfgfile);
logManager.readConfiguration(cfgdata);
diff --git a/src/de/lmu/ifi/dbs/elki/logging/LoggingUtil.java b/src/de/lmu/ifi/dbs/elki/logging/LoggingUtil.java
index a9413eab..808a648c 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) 2011
+ Copyright (C) 2012
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 5ea5c489..9c1f6046 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) 2011
+ Copyright (C) 2012
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 6d8a23f5..7bd09da0 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) 2011
+ Copyright (C) 2012
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-cli.properties b/src/de/lmu/ifi/dbs/elki/logging/logging.properties
index 538da540..538da540 100644
--- a/src/de/lmu/ifi/dbs/elki/logging/logging-cli.properties
+++ b/src/de/lmu/ifi/dbs/elki/logging/logging.properties
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 d7a3321e..cb6f3377 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) 2011
+Copyright (C) 2012
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 2fb6764e..070dbdb9 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) 2011
+ Copyright (C) 2012
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 4319255f..6d70b560 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) 2011
+ Copyright (C) 2012
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 404a990a..9a13947c 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) 2011
+ Copyright (C) 2012
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 092ec49c..972f0c58 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) 2011
+ Copyright (C) 2012
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 8f54f75e..64e8214e 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) 2011
+ Copyright (C) 2012
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 b7c125c9..d39e3107 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) 2011
+ Copyright (C) 2012
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/StepProgress.java b/src/de/lmu/ifi/dbs/elki/logging/progress/StepProgress.java
index b5eee462..df6e3b13 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) 2011
+ Copyright (C) 2012
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 bad21ca9..8b25c703 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) 2011
+Copyright (C) 2012
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/DoubleMinMax.java b/src/de/lmu/ifi/dbs/elki/math/DoubleMinMax.java
index 5c7d3d74..cedfb389 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -165,4 +165,12 @@ public class DoubleMinMax extends DoubleDoublePair {
}
return ret;
}
+
+ /**
+ * Reset statistics.
+ */
+ public void reset() {
+ first = Double.POSITIVE_INFINITY;
+ second = Double.NEGATIVE_INFINITY;
+ }
}
diff --git a/src/de/lmu/ifi/dbs/elki/math/MathUtil.java b/src/de/lmu/ifi/dbs/elki/math/MathUtil.java
index 83fbca92..7eea5ed7 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -55,6 +55,11 @@ public final class MathUtil {
public static final double SQRT2 = Math.sqrt(2);
/**
+ * Square root of 5
+ */
+ public static final double SQRT5 = Math.sqrt(5);
+
+ /**
* Square root of 0.5 == 1 / Sqrt(2)
*/
public static final double SQRTHALF = Math.sqrt(.5);
@@ -65,6 +70,16 @@ public final class MathUtil {
public static final double ONE_BY_SQRTPI = 1 / Math.sqrt(Math.PI);
/**
+ * Logarithm of 2 to the basis e, for logarithm conversion.
+ */
+ public static final double LOG2 = Math.log(2);
+
+ /**
+ * Math.log(Math.PI)
+ */
+ public static final double LOGPI = Math.log(Math.PI);
+
+ /**
* Fake constructor for static class.
*/
private MathUtil() {
@@ -75,18 +90,27 @@ public final class MathUtil {
* Computes the square root of the sum of the squared arguments without under
* or overflow.
*
+ * Note: this code is <em>not</em> redundant to {@link Math#hypot}, since the
+ * latter is significantly slower (but maybe has a higher precision).
+ *
* @param a first cathetus
* @param b second cathetus
* @return {@code sqrt(a<sup>2</sup> + b<sup>2</sup>)}
*/
- public static double hypotenuse(double a, double b) {
- if(Math.abs(a) > Math.abs(b)) {
+ public static double fastHypot(double a, double b) {
+ if(a < 0) {
+ a = -a;
+ }
+ if(b < 0) {
+ b = -b;
+ }
+ if(a > b) {
final double r = b / a;
- return Math.abs(a) * Math.sqrt(1 + r * r);
+ return a * Math.sqrt(1 + r * r);
}
else if(b != 0) {
final double r = a / b;
- return Math.abs(b) * Math.sqrt(1 + r * r);
+ return b * Math.sqrt(1 + r * r);
}
else {
return 0.0;
@@ -94,6 +118,38 @@ public final class MathUtil {
}
/**
+ * Computes the square root of the sum of the squared arguments without under
+ * or overflow.
+ *
+ * Note: this code is <em>not</em> redundant to {@link Math#hypot}, since the
+ * latter is significantly slower (but has a higher precision).
+ *
+ * @param a first cathetus
+ * @param b second cathetus
+ * @param c second cathetus
+ * @return {@code sqrt(a<sup>2</sup> + b<sup>2</sup> + c<sup>2</sup>)}
+ */
+ public static double fastHypot3(double a, double b, double c) {
+ if(a < 0) {
+ a = -a;
+ }
+ if(b < 0) {
+ b = -b;
+ }
+ if(c < 0) {
+ c = -c;
+ }
+ double m = (a > b) ? ((a > c) ? a : c) : ((b > c) ? b : c);
+ if(m <= 0) {
+ return 0.0;
+ }
+ a = a / m;
+ b = b / m;
+ c = c / m;
+ return m * Math.sqrt(a * a + b * b + c * c);
+ }
+
+ /**
* Compute the Mahalanobis distance using the given weight matrix
*
* @param weightMatrix Weight Matrix
@@ -101,7 +157,7 @@ public final class MathUtil {
* @return Mahalanobis distance
*/
public static double mahalanobisDistance(Matrix weightMatrix, Vector o1_minus_o2) {
- double sqrDist = o1_minus_o2.transposeTimes(weightMatrix).times(o1_minus_o2).get(0);
+ double sqrDist = o1_minus_o2.transposeTimesTimes(weightMatrix, o1_minus_o2);
if(sqrDist < 0 && Math.abs(sqrDist) < 0.000000001) {
sqrDist = Math.abs(sqrDist);
@@ -128,36 +184,11 @@ public final class MathUtil {
if(xdim <= 0) {
throw new IllegalArgumentException("Invalid arguments: dimensionality not positive.");
}
- double sumXX = 0;
- double sumYY = 0;
- double sumXY = 0;
- {
- // Incremental computation
- double meanX = x.doubleValue(1);
- double meanY = y.doubleValue(1);
- for(int i = 2; i <= xdim; i++) {
- // Delta to previous mean
- final double deltaX = x.doubleValue(i) - meanX;
- final double deltaY = y.doubleValue(i) - meanY;
- // Update means
- meanX += deltaX / i;
- meanY += deltaY / i;
- // Delta to new mean
- final double neltaX = x.doubleValue(i) - meanX;
- final double neltaY = y.doubleValue(i) - meanY;
- // Update
- sumXX += deltaX * neltaX;
- sumYY += deltaY * neltaY;
- sumXY += deltaX * neltaY; // should equal deltaY * neltaX!
- }
- }
- final double popSdX = Math.sqrt(sumXX / xdim);
- final double popSdY = Math.sqrt(sumYY / ydim);
- final double covXY = sumXY / xdim;
- if(popSdX == 0 || popSdY == 0) {
- return 0;
+ PearsonCorrelation pc = new PearsonCorrelation();
+ for(int i = 0; i < xdim; i++) {
+ pc.put(x.doubleValue(i + 1), y.doubleValue(i + 1), 1.0);
}
- return covXY / (popSdX * popSdY);
+ return pc.getCorrelation();
}
/**
@@ -179,42 +210,37 @@ public final class MathUtil {
if(xdim != weights.length) {
throw new IllegalArgumentException("Dimensionality doesn't agree to weights.");
}
- // Compute means
- double sumWe;
- double sumXX = 0;
- double sumYY = 0;
- double sumXY = 0;
- {
- // Incremental computation
- double meanX = x.doubleValue(1);
- double meanY = y.doubleValue(1);
- sumWe = weights[0];
- for(int i = 2; i <= xdim; i++) {
- final double weight = weights[i - 1];
- sumWe += weight;
- // Delta to previous mean
- final double deltaX = x.doubleValue(i) - meanX;
- final double deltaY = y.doubleValue(i) - meanY;
- // Update means
- meanX += deltaX * weight / sumWe;
- meanY += deltaY * weight / sumWe;
- // Delta to new mean
- final double neltaX = x.doubleValue(i) - meanX;
- final double neltaY = y.doubleValue(i) - meanY;
- // Update
- sumXX += weight * deltaX * neltaX;
- sumYY += weight * deltaY * neltaY;
- sumXY += weight * deltaX * neltaY; // should equal weight * deltaY *
- // neltaX!
- }
+ PearsonCorrelation pc = new PearsonCorrelation();
+ for(int i = 0; i < xdim; i++) {
+ pc.put(x.doubleValue(i + 1), y.doubleValue(i + 1), weights[i]);
}
- final double popSdX = Math.sqrt(sumXX / sumWe);
- final double popSdY = Math.sqrt(sumYY / sumWe);
- final double covXY = sumXY / sumWe;
- if(popSdX == 0 || popSdY == 0) {
- return 0;
+ return pc.getCorrelation();
+ }
+
+ /**
+ * <p>
+ * Provides the Pearson product-moment correlation coefficient for two
+ * FeatureVectors.
+ * </p>
+ *
+ * @param x first FeatureVector
+ * @param y second FeatureVector
+ * @return the Pearson product-moment correlation coefficient for x and y
+ */
+ public static double weightedPearsonCorrelationCoefficient(NumberVector<?, ?> x, NumberVector<?, ?> y, NumberVector<?, ?> weights) {
+ final int xdim = x.getDimensionality();
+ final int ydim = y.getDimensionality();
+ if(xdim != ydim) {
+ throw new IllegalArgumentException("Invalid arguments: feature vectors differ in dimensionality.");
+ }
+ if(xdim != weights.getDimensionality()) {
+ throw new IllegalArgumentException("Dimensionality doesn't agree to weights.");
}
- return covXY / (popSdX * popSdY);
+ PearsonCorrelation pc = new PearsonCorrelation();
+ for(int i = 0; i < xdim; i++) {
+ pc.put(x.doubleValue(i + 1), y.doubleValue(i + 1), weights.doubleValue(i + 1));
+ }
+ return pc.getCorrelation();
}
/**
@@ -233,40 +259,11 @@ public final class MathUtil {
if(xdim != ydim) {
throw new IllegalArgumentException("Invalid arguments: feature vectors differ in dimensionality.");
}
- if(xdim <= 0) {
- throw new IllegalArgumentException("Invalid arguments: dimensionality not positive.");
- }
- double sumXX = 0;
- double sumYY = 0;
- double sumXY = 0;
- {
- // Incremental computation
- double meanX = x[0];
- double meanY = y[0];
- for(int i = 1; i < xdim; i++) {
- int sumWe = i + 1;
- // Delta to previous mean
- final double deltaX = x[i] - meanX;
- final double deltaY = y[i] - meanY;
- // Update means
- meanX += deltaX / sumWe;
- meanY += deltaY / sumWe;
- // Delta to new mean
- final double neltaX = x[i] - meanX;
- final double neltaY = y[i] - meanY;
- // Update
- sumXX += deltaX * neltaX;
- sumYY += deltaY * neltaY;
- sumXY += deltaX * neltaY; // should equal deltaY * neltaX!
- }
- }
- final double popSdX = Math.sqrt(sumXX / xdim);
- final double popSdY = Math.sqrt(sumYY / ydim);
- final double covXY = sumXY / xdim;
- if(popSdX == 0 || popSdY == 0) {
- return 0;
+ PearsonCorrelation pc = new PearsonCorrelation();
+ for(int i = 0; i < xdim; i++) {
+ pc.put(x[i], y[i], 1.0);
}
- return covXY / (popSdX * popSdY);
+ return pc.getCorrelation();
}
/**
@@ -288,42 +285,11 @@ public final class MathUtil {
if(xdim != weights.length) {
throw new IllegalArgumentException("Dimensionality doesn't agree to weights.");
}
- // Compute means
- double sumWe;
- double sumXX = 0;
- double sumYY = 0;
- double sumXY = 0;
- {
- // Incremental computation
- double meanX = x[0];
- double meanY = y[0];
- sumWe = weights[0];
- for(int i = 1; i < xdim; i++) {
- final double weight = weights[i];
- sumWe += weight;
- // Delta to previous mean
- final double deltaX = x[i] - meanX;
- final double deltaY = y[i] - meanY;
- // Update means
- meanX += deltaX * weight / sumWe;
- meanY += deltaY * weight / sumWe;
- // Delta to new mean
- final double neltaX = x[i] - meanX;
- final double neltaY = y[i] - meanY;
- // Update
- sumXX += weight * deltaX * neltaX;
- sumYY += weight * deltaY * neltaY;
- sumXY += weight * deltaX * neltaY; // should equal weight * deltaY *
- // neltaX!
- }
- }
- final double popSdX = Math.sqrt(sumXX / sumWe);
- final double popSdY = Math.sqrt(sumYY / sumWe);
- final double covXY = sumXY / sumWe;
- if(popSdX == 0 || popSdY == 0) {
- return 0;
+ PearsonCorrelation pc = new PearsonCorrelation();
+ for(int i = 0; i < xdim; i++) {
+ pc.put(x[i], y[i], weights[i]);
}
- return covXY / (popSdX * popSdY);
+ return pc.getCorrelation();
}
/**
@@ -415,462 +381,356 @@ public final class MathUtil {
}
/**
- * Coefficients for erf approximation.
+ * Compute the sum of the i first integers.
*
- * Loosely based on http://www.netlib.org/specfun/erf
+ * @param i maximum summand
+ * @return Sum
*/
- static final double ERFAPP_A[] = { 1.85777706184603153e-1, 3.16112374387056560e+0, 1.13864154151050156E+2, 3.77485237685302021e+2, 3.20937758913846947e+3 };
+ public static long sumFirstIntegers(final long i) {
+ return ((i - 1L) * i) / 2;
+ }
/**
- * Coefficients for erf approximation.
+ * Produce an array of random numbers in [0:1]
*
- * Loosely based on http://www.netlib.org/specfun/erf
+ * @param len Length
+ * @return Array
*/
- static final double ERFAPP_B[] = { 1.00000000000000000e00, 2.36012909523441209e01, 2.44024637934444173e02, 1.28261652607737228e03, 2.84423683343917062e03 };
+ public static double[] randomDoubleArray(int len) {
+ return randomDoubleArray(len, new Random());
+ }
/**
- * Coefficients for erf approximation.
+ * Produce an array of random numbers in [0:1]
*
- * Loosely based on http://www.netlib.org/specfun/erf
+ * @param len Length
+ * @param r Random generator
+ * @return Array
*/
- static final double ERFAPP_C[] = { 2.15311535474403846e-8, 5.64188496988670089e-1, 8.88314979438837594e00, 6.61191906371416295e01, 2.98635138197400131e02, 8.81952221241769090e02, 1.71204761263407058e03, 2.05107837782607147e03, 1.23033935479799725E03 };
+ public static double[] randomDoubleArray(int len, Random r) {
+ final double[] ret = new double[len];
+ for(int i = 0; i < len; i++) {
+ ret[i] = r.nextDouble();
+ }
+ return ret;
+ }
/**
- * Coefficients for erf approximation.
+ * Convert Degree to Radians
*
- * Loosely based on http://www.netlib.org/specfun/erf
+ * @param deg Degree value
+ * @return Radian value
*/
- static final double ERFAPP_D[] = { 1.00000000000000000e00, 1.57449261107098347e01, 1.17693950891312499e02, 5.37181101862009858e02, 1.62138957456669019e03, 3.29079923573345963e03, 4.36261909014324716e03, 3.43936767414372164e03, 1.23033935480374942e03 };
+ public static double deg2rad(double deg) {
+ return deg * Math.PI / 180.0;
+ }
/**
- * Coefficients for erf approximation.
+ * Radians to Degree
*
- * Loosely based on http://www.netlib.org/specfun/erf
+ * @param rad Radians value
+ * @return Degree value
*/
- static final double ERFAPP_P[] = { 1.63153871373020978e-2, 3.05326634961232344e-1, 3.60344899949804439e-1, 1.25781726111229246e-1, 1.60837851487422766e-2, 6.58749161529837803e-4 };
+ public static double rad2deg(double rad) {
+ return rad * 180 / Math.PI;
+ }
/**
- * Coefficients for erf approximation.
+ * Compute the approximate on-earth-surface distance of two points.
*
- * Loosely based on http://www.netlib.org/specfun/erf
+ * @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)
*/
- static final double ERFAPP_Q[] = { 1.00000000000000000e00, 2.56852019228982242e00, 1.87295284992346047e00, 5.27905102951428412e-1, 6.05183413124413191e-2, 2.33520497626869185e-3 };
+ public static double latlngDistance(double lat1, double lon1, double lat2, double lon2) {
+ final double EARTH_RADIUS = 6371; // km.
+ // Work in radians
+ lat1 = MathUtil.deg2rad(lat1);
+ lat2 = MathUtil.deg2rad(lat2);
+ lon1 = MathUtil.deg2rad(lon1);
+ lon2 = MathUtil.deg2rad(lon2);
+ // Delta
+ final double dlat = lat1 - lat2;
+ final double dlon = lon1 - lon2;
- /**
- * Complementary error function for Gaussian distributions = Normal
- * distributions.
- *
- * Numerical approximation using taylor series. Implementation loosely based
- * on http://www.netlib.org/specfun/erf
- *
- * @param x parameter value
- * @return erfc(x)
- */
- public static double erfc(double x) {
- if(Double.isNaN(x)) {
- return Double.NaN;
- }
- 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) {
- 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) {
- 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) {
- result = 2.0 - result;
- }
- }
- // Third approximation interval
- else {
- double z = 1.0 / (absx * absx);
- result = z * (((((ERFAPP_P[0] * z + ERFAPP_P[1]) * z + ERFAPP_P[2]) * z + ERFAPP_P[3]) * z + ERFAPP_P[4]) * z + ERFAPP_P[5]) / (((((ERFAPP_Q[0] * z + ERFAPP_Q[1]) * z + ERFAPP_Q[2]) * z + ERFAPP_Q[3]) * z + ERFAPP_Q[4]) * z + ERFAPP_Q[5]);
- result = (ONE_BY_SQRTPI - result) / absx;
- 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) {
- result = 2.0 - result;
- }
- }
- return result;
+ // Spherical Law of Cosines
+ // NOTE: there seems to be a signedness issue in this code!
+ // double dist = Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) *
+ // Math.cos(lat2) * Math.cos(dlon);
+ // return EARTH_RADIUS * Math.atan(dist);
+
+ // Alternative: Havestine formula, higher precision at < 1 meters:
+ final double a = Math.sin(dlat / 2) * Math.sin(dlat / 2) + Math.sin(dlon / 2) * Math.sin(dlon / 2) * Math.cos(lat1) * Math.cos(lat2);
+ final double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
+ return EARTH_RADIUS * c;
}
/**
- * Error function for Gaussian distributions = Normal distributions.
- *
- * Numerical approximation using taylor series. Implementation loosely based
- * on http://www.netlib.org/specfun/erf
+ * Compute the angle between two vectors.
*
- * @param x parameter value
- * @return erf(x)
+ * @param v1 first vector
+ * @param v2 second vector
+ * @return Angle
*/
- public static double erf(double x) {
- return 1 - erfc(x);
+ public static double angle(Vector v1, Vector v2) {
+ return angle(v1.getArrayRef(), v2.getArrayRef());
}
/**
- * Inverse error function.
+ * Compute the angle between two vectors.
*
- * @param x parameter value
- * @return erfinv(x)
+ * @param v1 first vector
+ * @param v2 second vector
+ * @return Angle
*/
- public static double erfinv(double x) {
- return standardNormalProbit(0.5 * (x + 1)) / SQRT2;
+ public static double angle(double[] v1, double[] v2) {
+ // Essentially, we want to compute this:
+ // v1.transposeTimes(v2) / (v1.euclideanLength() * v2.euclideanLength());
+ // We can just compute all three in parallel.
+ double s = 0, e1 = 0, e2 = 0;
+ for(int k = 0; k < v1.length; k++) {
+ final double r1 = v1[k];
+ final double r2 = v2[k];
+ s += r1 * r2;
+ e1 += r1 * r1;
+ e2 += r2 * r2;
+ }
+ return Math.sqrt((s / e1) * (s / e2));
}
/**
- * Treshold for switching nethods for erfinv approximation
- */
- static final double P_LOW = 0.02425D;
-
- /**
- * Treshold for switching nethods for erfinv approximation
- */
- static final double P_HIGH = 1.0D - P_LOW;
-
- /**
- * Coefficients for erfinv approximation, rational version
- */
- static final double ERFINV_A[] = { -3.969683028665376e+01, 2.209460984245205e+02, -2.759285104469687e+02, 1.383577518672690e+02, -3.066479806614716e+01, 2.506628277459239e+00 };
-
- /**
- * Coefficients for erfinv approximation, rational version
- */
- static final double ERFINV_B[] = { -5.447609879822406e+01, 1.615858368580409e+02, -1.556989798598866e+02, 6.680131188771972e+01, -1.328068155288572e+01 };
-
- /**
- * Coefficients for erfinv approximation, rational version
- */
- static final double ERFINV_C[] = { -7.784894002430293e-03, -3.223964580411365e-01, -2.400758277161838e+00, -2.549732539343734e+00, 4.374664141464968e+00, 2.938163982698783e+00 };
-
- /**
- * Coefficients for erfinv approximation, rational version
+ * Compute the angle between two vectors.
+ *
+ * @param v1 first vector
+ * @param v2 second vector
+ * @param o Origin
+ * @return Angle
*/
- static final double ERFINV_D[] = { 7.784695709041462e-03, 3.224671290700398e-01, 2.445134137142996e+00, 3.754408661907416e+00 };
+ public static double angle(Vector v1, Vector v2, Vector o) {
+ return angle(v1.getArrayRef(), v2.getArrayRef(), o.getArrayRef());
+ }
/**
- * 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>
+ * Compute the angle between two vectors.
*
- * @param d Quantile. Must be in [0:1], obviously.
- * @return Inverse erf.
+ * @param v1 first vector
+ * @param v2 second vector
+ * @param o Origin
+ * @return Angle
*/
- public static double standardNormalProbit(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 angle(double[] v1, double[] v2, double[] o) {
+ // Essentially, we want to compute this:
+ // v1' = v1 - o, v2' = v2 - o
+ // v1'.transposeTimes(v2') / (v1'.euclideanLength()*v2'.euclideanLength());
+ // We can just compute all three in parallel.
+ double s = 0, e1 = 0, e2 = 0;
+ for(int k = 0; k < v1.length; k++) {
+ final double r1 = v1[k] - o[k];
+ final double r2 = v2[k] - o[k];
+ s += r1 * r2;
+ e1 += r1 * r1;
+ e2 += r2 * r2;
}
+ return Math.sqrt((s / e1) * (s / e2));
}
/**
- * Probability density function of the normal distribution.
+ * Find the next power of 2.
*
- * <pre>
- * 1/(SQRT(2*pi*sigma^2)) * e^(-(x-mu)^2/2sigma^2)
- * </pre>
+ * Classic bit operation, for signed 32-bit. Valid for positive integers only
+ * (0 otherwise).
*
- * @param x The value.
- * @param mu The mean.
- * @param sigma The standard deviation.
- * @return PDF of the given normal distribution at x.
+ * @param x original integer
+ * @return Next power of 2
*/
- public static double normalPDF(double x, double mu, double sigma) {
- final double x_mu = x - mu;
- final double sigmasq = sigma * sigma;
- return 1 / (Math.sqrt(TWOPI * sigmasq)) * Math.exp(-1 * x_mu * x_mu / 2 / sigmasq);
+ public static int nextPow2Int(int x) {
+ --x;
+ x |= x >>> 1;
+ x |= x >>> 2;
+ x |= x >>> 4;
+ x |= x >>> 8;
+ x |= x >>> 16;
+ return ++x;
}
/**
- * Cumulative probability density function (CDF) of a normal distribution.
+ * Find the next power of 2.
*
- * @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.
- */
- public static double normalCDF(double x, double mu, double sigma) {
- return (1 + erf(x / Math.sqrt(2))) / 2;
- }
-
- /**
- * Inverse cumulative probability density function (probit) of a normal
- * distribution.
+ * Classic bit operation, for signed 64-bit. Valid for positive integers only
+ * (0 otherwise).
*
- * @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.
+ * @param x original long integer
+ * @return Next power of 2
*/
- public static double normalProbit(double x, double mu, double sigma) {
- return mu + sigma * standardNormalProbit(x);
+ public static long nextPow2Long(long x) {
+ --x;
+ x |= x >>> 1;
+ x |= x >>> 2;
+ x |= x >>> 4;
+ x |= x >>> 16;
+ x |= x >>> 32;
+ return ++x;
}
/**
- * LANCZOS-Coefficients for Gamma approximation.
+ * Find the next larger number with all ones.
*
- * These are said to have higher precision than those in "Numerical Recipes".
- * They probably come from
+ * Classic bit operation, for signed 32-bit. Valid for positive integers only
+ * (-1 otherwise).
*
- * Paul Godfrey: http://my.fit.edu/~gabdo/gamma.txt
- */
- 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
+ * @param x original integer
+ * @return Next number with all bits set
*/
- static final double NUM_PRECISION = 1E-15;
+ public static int nextAllOnesInt(int x) {
+ x |= x >>> 1;
+ x |= x >>> 2;
+ x |= x >>> 4;
+ x |= x >>> 8;
+ x |= x >>> 16;
+ return x;
+ }
/**
- * Compute logGamma.
- *
- * Based loosely on "Numerical Recpies" and the work of Paul Godfrey at
- * http://my.fit.edu/~gabdo/gamma.txt
+ * Find the next larger number with all ones.
*
- * TODO: find out which approximation really is the best...
+ * Classic bit operation, for signed 64-bit. Valid for positive integers only
+ * (-1 otherwise).
*
- * @param x Parameter x
- * @return @return log(&#915;(x))
+ * @param x original long integer
+ * @return Next number with all bits set
*/
- public static double logGamma(final double x) {
- 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) {
- ser += LANCZOS[i] / (x + i);
- }
- return tmp + Math.log(SQRTTWOPI * ser / x);
+ public static long nextAllOnesLong(long x) {
+ x |= x >>> 1;
+ x |= x >>> 2;
+ x |= x >>> 4;
+ x |= x >>> 16;
+ x |= x >>> 32;
+ return x;
}
/**
- * Returns the regularized gamma function P(a, x).
- *
- * Includes the quadrature way of computing.
+ * Return the largest double that rounds down to this float.
*
- * TODO: find "the" most accurate version of this. We seem to agree with
- * others for the first 10+ digits, but diverge a bit later than that.
+ * Note: Probably not always correct - subnormal values are quite tricky. So
+ * some of the bounds might not be tight.
*
- * @param a Parameter a
- * @param x Parameter x
- * @return Gamma value
+ * @param f Float value
+ * @return Double value
*/
- 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)) {
+ public static double floatToDoubleUpper(float f) {
+ if(Float.isNaN(f)) {
return Double.NaN;
}
- if(x == 0.0) {
- return 0.0;
+ if(Float.isInfinite(f)) {
+ if(f > 0) {
+ return Double.POSITIVE_INFINITY;
+ }
+ else {
+ return Double.longBitsToDouble(0xc7efffffffffffffl);
+ }
}
- 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++) {
- // compute next element in the series
- del *= x / (a + n);
- sum = sum + del;
- if(Math.abs(del / sum) < NUM_PRECISION || sum >= Double.POSITIVE_INFINITY) {
- break;
+ long bits = Double.doubleToRawLongBits((double) f);
+ if((bits & 0x8000000000000000l) == 0) { // Positive
+ if(bits == 0l) {
+ return Double.longBitsToDouble(0x3690000000000000l);
}
+ if(f == Float.MIN_VALUE) {
+ // bits += 0x7_ffff_ffff_ffffl;
+ return Double.longBitsToDouble(0x36a7ffffffffffffl);
+ }
+ if(Float.MIN_NORMAL > f && f >= Double.MIN_NORMAL) {
+ // The most tricky case:
+ // a denormalized float, but a normalized double
+ final long bits2 = Double.doubleToRawLongBits((double) Math.nextUp(f));
+ bits = (bits >>> 1) + (bits2 >>> 1) - 1l;
+ }
+ else {
+ bits += 0xfffffffl; // 28 extra bits
+ }
+ return Double.longBitsToDouble(bits);
}
- if(Double.isInfinite(sum)) {
- return 1.0;
+ else {
+ if(bits == 0x8000000000000000l) {
+ return -0.0d;
+ }
+ if(f == -Float.MIN_VALUE) {
+ // bits -= 0xf_ffff_ffff_ffffl;
+ return Double.longBitsToDouble(0xb690000000000001l);
+ }
+ if(-Float.MIN_NORMAL < f && f <= -Double.MIN_NORMAL) {
+ // The most tricky case:
+ // a denormalized float, but a normalized double
+ final long bits2 = Double.doubleToRawLongBits((double) Math.nextUp(f));
+ bits = (bits >>> 1) + (bits2 >>> 1) + 1l;
+ }
+ else {
+ bits -= 0xfffffffl; // 28 extra bits
+ }
+ return Double.longBitsToDouble(bits);
}
- return Math.exp(-x + (a * Math.log(x)) - logGamma(a)) * sum;
}
/**
- * Returns the regularized gamma function Q(a, x) = 1 - P(a, x).
- *
- * Includes the continued fraction way of computing, based loosely on the book
- * "Numerical Recipes"; but probably not with the exactly same precision,
- * since we reimplemented this in our coding style, not literally.
+ * Return the largest double that rounds up to this float.
*
- * TODO: find "the" most accurate version of this. We seem to agree with
- * others for the first 10+ digits, but diverge a bit later than that.
+ * Note: Probably not always correct - subnormal values are quite tricky. So
+ * some of the bounds might not be tight.
*
- * @param a parameter a
- * @param x parameter x
- * @return Result
+ * @param f Float value
+ * @return Double value
*/
- public static double regularizedGammaQ(final double a, final double x) {
- if(Double.isNaN(a) || Double.isNaN(x) || (a <= 0.0) || (x < 0.0)) {
+ public static double floatToDoubleLower(float f) {
+ if(Float.isNaN(f)) {
return Double.NaN;
}
- if(x == 0.0) {
- return 1.0;
- }
- if(x < a + 1.0) {
- // Expected to converge faster
- return 1.0 - regularizedGammaP(a, x);
- }
- // Compute using continued fraction approach.
- final double FPMIN = Double.MIN_VALUE / NUM_PRECISION;
- double b = x + 1 - a;
- double c = 1.0 / FPMIN;
- double d = 1.0 / b;
- double fac = d;
- for(int i = 1; i < Integer.MAX_VALUE; i++) {
- double an = i * (a - i);
- b += 2;
- d = an * d + b;
- if(Math.abs(d) < FPMIN) {
- d = FPMIN;
+ if(Float.isInfinite(f)) {
+ if(f < 0) {
+ return Double.NEGATIVE_INFINITY;
+ }
+ else {
+ return Double.longBitsToDouble(0x47efffffffffffffl);
+ }
+ }
+ long bits = Double.doubleToRawLongBits((double) f);
+ if((bits & 0x8000000000000000l) == 0) { // Positive
+ if(bits == 0l) {
+ return +0.0d;
+ }
+ if(f == Float.MIN_VALUE) {
+ // bits -= 0xf_ffff_ffff_ffffl;
+ return Double.longBitsToDouble(0x3690000000000001l);
}
- c = b + an / c;
- if(Math.abs(c) < FPMIN) {
- c = FPMIN;
+ if(Float.MIN_NORMAL > f /* && f >= Double.MIN_NORMAL */) {
+ // The most tricky case:
+ // a denormalized float, but a normalized double
+ final long bits2 = Double.doubleToRawLongBits((double) -Math.nextUp(-f));
+ bits = (bits >>> 1) + (bits2 >>> 1) + 1l; // + (0xfff_ffffl << 18);
}
- d = 1 / d;
- double del = d * c;
- fac *= del;
- if(Math.abs(del - 1.0) <= NUM_PRECISION) {
- break;
+ else {
+ bits -= 0xfffffffl; // 28 extra bits
}
+ return Double.longBitsToDouble(bits);
}
- return fac * Math.exp(-x + a * Math.log(x) - logGamma(a));
- }
-
- /**
- * Compute the sum of the i first integers.
- *
- * @param i maximum summand
- * @return Sum
- */
- public static long sumFirstIntegers(final long i) {
- return ((i - 1L) * i) / 2;
- }
-
- /**
- * Produce an array of random numbers in [0:1]
- *
- * @param len Length
- * @return Array
- */
- public static double[] randomDoubleArray(int len) {
- return randomDoubleArray(len, new Random());
- }
-
- /**
- * Produce an array of random numbers in [0:1]
- *
- * @param len Length
- * @param r Random generator
- * @return Array
- */
- public static double[] randomDoubleArray(int len, Random r) {
- final double[] ret = new double[len];
- for(int i = 0; i < len; i++) {
- ret[i] = r.nextDouble();
+ else {
+ if(bits == 0x8000000000000000l) {
+ return Double.longBitsToDouble(0xb690000000000000l);
+ }
+ if(f == -Float.MIN_VALUE) {
+ // bits += 0x7_ffff_ffff_ffffl;
+ return Double.longBitsToDouble(0xb6a7ffffffffffffl);
+ }
+ if(-Float.MIN_NORMAL < f /* && f <= -Double.MIN_NORMAL */) {
+ // The most tricky case:
+ // a denormalized float, but a normalized double
+ final long bits2 = Double.doubleToRawLongBits((double) -Math.nextUp(-f));
+ bits = (bits >>> 1) + (bits2 >>> 1) - 1l;
+ }
+ else {
+ bits += 0xfffffffl; // 28 extra bits
+ }
+ return Double.longBitsToDouble(bits);
}
- return ret;
- }
-
- /**
- * Convert Degree to Radians
- *
- * @param deg Degree value
- * @return Radian value
- */
- public static double deg2rad(double deg) {
- return deg * Math.PI / 180.0;
- }
-
- /**
- * Radians to Degree
- *
- * @param rad Radians value
- * @return Degree value
- */
- public static double rad2deg(double rad) {
- return rad * 180 / Math.PI;
- }
-
- /**
- * Compute the approximate on-earth-surface distance of two points.
- *
- * @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)
- */
- public static double latlngDistance(double lat1, double lon1, double lat2, double lon2) {
- final double EARTH_RADIUS = 6371; // km.
- // Work in radians
- lat1 = MathUtil.deg2rad(lat1);
- lat2 = MathUtil.deg2rad(lat2);
- lon1 = MathUtil.deg2rad(lon1);
- lon2 = MathUtil.deg2rad(lon2);
- // Delta
- final double dlat = lat1 - lat2;
- final double dlon = lon1 - lon2;
-
- // Spherical Law of Cosines
- // NOTE: there seems to be a signedness issue in this code!
- // double dist = Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) *
- // Math.cos(lat2) * Math.cos(dlon);
- // return EARTH_RADIUS * Math.atan(dist);
-
- // Alternative: Havestine formula, higher precision at < 1 meters:
- final double a = Math.sin(dlat / 2) * Math.sin(dlat / 2) + Math.sin(dlon / 2) * Math.sin(dlon / 2) * 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 cosine similarity for two vectors.
- *
- * @param v1 First vector
- * @param v2 Second vector
- * @return Cosine similarity
- */
- public static double cosineSimilarity(Vector v1, Vector v2) {
- return v1.scalarProduct(v2) / (v1.euclideanLength() * v2.euclideanLength());
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/math/Mean.java b/src/de/lmu/ifi/dbs/elki/math/Mean.java
index 6f63c59e..56f73f8e 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -157,4 +157,12 @@ public class Mean {
public String toString() {
return "Mean(" + getMean() + ")";
}
+
+ /**
+ * Reset the value.
+ */
+ public void reset() {
+ mean = 0;
+ wsum = 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 49f00856..0210b0fb 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -176,7 +176,7 @@ public class MeanVariance extends Mean {
* @return sample variance
*/
public double getSampleVariance() {
- assert (wsum > 1);
+ assert (wsum > 1) : "Cannot compute a reasonable sample variance with weight <= 1.0!";
return nvar / (wsum - 1);
}
@@ -240,4 +240,10 @@ public class MeanVariance extends Mean {
public String toString() {
return "MeanVariance(mean=" + getMean() + ",var=" + getSampleVariance() + ")";
}
+
+ @Override
+ public void reset() {
+ super.reset();
+ nvar = 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
new file mode 100644
index 00000000..23e53bb5
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/MeanVarianceMinMax.java
@@ -0,0 +1,139 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You 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 collecting mean, variance, minimum and maximum statistics.
+ *
+ * @author Erich Schubert
+ */
+public class MeanVarianceMinMax extends MeanVariance {
+ /**
+ * Minimum value
+ */
+ double min = Double.POSITIVE_INFINITY;
+
+ /**
+ * Maximum value
+ */
+ double max = Double.NEGATIVE_INFINITY;
+
+ /**
+ * Constructor.
+ */
+ public MeanVarianceMinMax() {
+ super();
+ }
+
+ /**
+ * Constructor cloning existing statistics.
+ *
+ * @param other Existing statistics
+ */
+ public MeanVarianceMinMax(MeanVarianceMinMax other) {
+ super(other);
+ this.min = other.min;
+ this.max = other.max;
+ }
+
+ @Override
+ public void put(double val) {
+ super.put(val);
+ min = Math.min(min, val);
+ max = Math.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);
+ }
+
+ @Override
+ public void put(Mean other) {
+ if(other instanceof MeanVarianceMinMax) {
+ super.put(other);
+ min = Math.min(min, ((MeanVarianceMinMax) other).min);
+ max = Math.max(max, ((MeanVarianceMinMax) other).max);
+ }
+ else {
+ throw new AbortException("Cannot aggregate into a minmax statistic: " + other.getClass());
+ }
+ }
+
+ /**
+ * Get the current minimum.
+ *
+ * @return current minimum.
+ */
+ public double getMin() {
+ return this.min;
+ }
+
+ /**
+ * Get the current maximum.
+ *
+ * @return current maximum.
+ */
+ public double getMax() {
+ return this.max;
+ }
+
+ /**
+ * Return the difference between minimum and maximum.
+ *
+ * @return Difference of current Minimum and Maximum.
+ */
+ public double getDiff() {
+ return this.getMax() - this.getMin();
+ }
+
+ /**
+ * Create and initialize a new array of MeanVarianceMinMax
+ *
+ * @param dimensionality Dimensionality
+ * @return New and initialized Array
+ */
+ public static MeanVarianceMinMax[] newArray(int dimensionality) {
+ MeanVarianceMinMax[] arr = new MeanVarianceMinMax[dimensionality];
+ for(int i = 0; i < dimensionality; i++) {
+ arr[i] = new MeanVarianceMinMax();
+ }
+ return arr;
+ }
+
+ @Override
+ public String toString() {
+ return "MeanVarianceMinMax(mean=" + getMean() + ",var=" + getSampleVariance() + ",min=" + getMin() + ",max=" + getMax() + ")";
+ }
+
+ @Override
+ public void reset() {
+ super.reset();
+ 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 e3dd9517..98b66173 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) 2011
+ Copyright (C) 2012
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/PearsonCorrelation.java b/src/de/lmu/ifi/dbs/elki/math/PearsonCorrelation.java
new file mode 100644
index 00000000..175f128d
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/PearsonCorrelation.java
@@ -0,0 +1,269 @@
+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/>.
+ */
+/**
+ * Class to incrementally compute pearson correlation.
+ *
+ * In fact, this actually computes Var(X), Var(Y) and Cov(X, Y), all of which
+ * can be obtained from this class. If you need more than two variables, use
+ * {@link de.lmu.ifi.dbs.elki.math.linearalgebra.CovarianceMatrix} which uses
+ * slightly more memory (by using arrays) but essentially does the same.
+ *
+ * @author Erich Schubert
+ */
+public class PearsonCorrelation {
+ /**
+ * Sum for XX
+ */
+ private double sumXX = 0;
+
+ /**
+ * Sum for YY
+ */
+ private double sumYY = 0;
+
+ /**
+ * Sum for XY
+ */
+ private double sumXY = 0;
+
+ /**
+ * Current mean for X
+ */
+ private double meanX = 0;
+
+ /**
+ * Current mean for Y
+ */
+ private double meanY = 0;
+
+ /**
+ * Weight sum
+ */
+ private double sumWe = 0;
+
+ /**
+ * Constructor.
+ */
+ public PearsonCorrelation() {
+ super();
+ }
+
+ /**
+ * Put a single value into the correlation statistic.
+ *
+ * @param x Value in X
+ * @param y Value in Y
+ * @param w Weight
+ */
+ public void put(double x, double y, double w) {
+ if(sumWe <= 0.0) {
+ meanX = x;
+ meanY = y;
+ sumWe = w;
+ return;
+ }
+ // Incremental update
+ sumWe += w;
+ // Delta to previous mean
+ final double deltaX = x - meanX;
+ final double deltaY = y - meanY;
+ // Update means
+ meanX += deltaX * w / sumWe;
+ meanY += deltaY * w / sumWe;
+ // Delta to new mean
+ final double neltaX = x - meanX;
+ final double neltaY = y - meanY;
+ // Update
+ sumXX += w * deltaX * neltaX;
+ sumYY += w * deltaY * neltaY;
+ // should equal weight * deltaY * neltaX!
+ sumXY += w * deltaX * neltaY;
+ }
+
+ /**
+ * Put a single value into the correlation statistic.
+ *
+ * @param x Value in X
+ * @param y Value in Y
+ */
+ public void put(double x, double y) {
+ put(x, y, 1.0);
+ }
+
+ /**
+ * Get the pearson correlation value.
+ *
+ * @return Correlation value
+ */
+ public double getCorrelation() {
+ final double popSdX = getNaiveStddevX();
+ final double popSdY = getNaiveStddevY();
+ final double covXY = getNaiveCovariance();
+ if(popSdX == 0 || popSdY == 0) {
+ return 0;
+ }
+ return covXY / (popSdX * popSdY);
+ }
+
+ /**
+ * Get the number of points the average is based on.
+ *
+ * @return number of data points
+ */
+ public double getCount() {
+ return sumWe;
+ }
+
+ /**
+ * Return mean of X
+ *
+ * @return mean
+ */
+ public double getMeanX() {
+ return meanX;
+ }
+
+ /**
+ * Return mean of Y
+ *
+ * @return mean
+ */
+ public double getMeanY() {
+ return meanY;
+ }
+
+ /**
+ * Get the covariance of X and Y (not taking sampling into account)
+ *
+ * @return Covariance
+ */
+ public double getNaiveCovariance() {
+ return sumXY / sumWe;
+ }
+
+ /**
+ * Get the covariance of X and Y (with sampling correction)
+ *
+ * @return Covariance
+ */
+ public double getSampleCovariance() {
+ assert (sumWe > 1);
+ return sumXY / (sumWe - 1);
+ }
+
+ /**
+ * Return the naive variance (not taking sampling into account)
+ *
+ * Note: usually, you should be using {@link #getSampleVarianceX} instead!
+ *
+ * @return variance
+ */
+ public double getNaiveVarianceX() {
+ return sumXX / sumWe;
+ }
+
+ /**
+ * Return sample variance.
+ *
+ * @return sample variance
+ */
+ public double getSampleVarianceX() {
+ assert (sumWe > 1);
+ return sumXX / (sumWe - 1);
+ }
+
+ /**
+ * Return standard deviation using the non-sample variance
+ *
+ * Note: usually, you should be using {@link #getSampleStddevX} instead!
+ *
+ * @return stddev
+ */
+ public double getNaiveStddevX() {
+ return Math.sqrt(getNaiveVarianceX());
+ }
+
+ /**
+ * Return standard deviation
+ *
+ * @return stddev
+ */
+ public double getSampleStddevX() {
+ return Math.sqrt(getSampleVarianceX());
+ }
+
+ /**
+ * Return the naive variance (not taking sampling into account)
+ *
+ * Note: usually, you should be using {@link #getSampleVarianceY} instead!
+ *
+ * @return variance
+ */
+ public double getNaiveVarianceY() {
+ return sumYY / sumWe;
+ }
+
+ /**
+ * Return sample variance.
+ *
+ * @return sample variance
+ */
+ public double getSampleVarianceY() {
+ assert (sumWe > 1);
+ return sumYY / (sumWe - 1);
+ }
+
+ /**
+ * Return standard deviation using the non-sample variance
+ *
+ * Note: usually, you should be using {@link #getSampleStddevY} instead!
+ *
+ * @return stddev
+ */
+ public double getNaiveStddevY() {
+ return Math.sqrt(getNaiveVarianceY());
+ }
+
+ /**
+ * Return standard deviation
+ *
+ * @return stddev
+ */
+ public double getSampleStddevY() {
+ return Math.sqrt(getSampleVarianceY());
+ }
+
+ /**
+ * Reset the value.
+ */
+ public void reset() {
+ sumXX = 0;
+ sumXY = 0;
+ sumYY = 0;
+ meanX = 0;
+ meanY = 0;
+ sumWe = 0;
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/math/geometry/AlphaShape.java b/src/de/lmu/ifi/dbs/elki/math/geometry/AlphaShape.java
new file mode 100644
index 00000000..8d2eb0f6
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/geometry/AlphaShape.java
@@ -0,0 +1,116 @@
+package de.lmu.ifi.dbs.elki.math.geometry;
+
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.List;
+
+import de.lmu.ifi.dbs.elki.data.spatial.Polygon;
+import de.lmu.ifi.dbs.elki.math.geometry.SweepHullDelaunay2D.Triangle;
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Compute the alpha-Shape of a point set, using Delaunay triangulation.
+ *
+ * @author Erich Schubert
+ */
+public class AlphaShape {
+ /**
+ * Alpha shape
+ */
+ private double alpha2;
+
+ /**
+ * Points
+ */
+ private List<Vector> points;
+
+ /**
+ * Delaunay triangulation
+ */
+ private ArrayList<Triangle> delaunay = null;
+
+ public AlphaShape(List<Vector> points, double alpha) {
+ this.alpha2 = alpha * alpha;
+ this.points = points;
+ }
+
+ public List<Polygon> compute() {
+ // Compute delaunay triangulation:
+ delaunay = (new SweepHullDelaunay2D(points)).getDelaunay();
+
+ List<Polygon> polys = new ArrayList<Polygon>();
+
+ // Working data
+ BitSet used = new BitSet(delaunay.size());
+ List<Vector> cur = new ArrayList<Vector>();
+
+ for(int i = 0 /* = used.nextClearBit(0) */; i < delaunay.size() && i >= 0; i = used.nextClearBit(i + 1)) {
+ if(used.get(i) == false) {
+ used.set(i);
+ Triangle tri = delaunay.get(i);
+ if(tri.r2 <= alpha2) {
+ // Check neighbors
+ processNeighbor(cur, used, i, tri.ab, tri.b);
+ processNeighbor(cur, used, i, tri.bc, tri.c);
+ processNeighbor(cur, used, i, tri.ca, tri.a);
+ }
+ if(cur.size() > 0) {
+ polys.add(new Polygon(cur));
+ cur = new ArrayList<Vector>();
+ }
+ }
+ }
+
+ return polys;
+ }
+
+ private void processNeighbor(List<Vector> cur, BitSet used, int i, int ab, int b) {
+ if(ab >= 0) {
+ if(used.get(ab)) {
+ return;
+ }
+ used.set(ab);
+ final Triangle next = delaunay.get(ab);
+ if(next.r2 < alpha2) {
+ // Continue where we left off...
+ if(next.ab == i) {
+ processNeighbor(cur, used, ab, next.bc, next.c);
+ processNeighbor(cur, used, ab, next.ca, next.a);
+ }
+ else if(next.bc == i) {
+ processNeighbor(cur, used, ab, next.ca, next.a);
+ processNeighbor(cur, used, ab, next.ab, next.b);
+ }
+ else if(next.ca == i) {
+ processNeighbor(cur, used, ab, next.ab, next.b);
+ processNeighbor(cur, used, ab, next.bc, next.c);
+ }
+ return;
+ }
+ }
+ cur.add(points.get(b));
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/math/ConvexHull2D.java b/src/de/lmu/ifi/dbs/elki/math/geometry/GrahamScanConvexHull2D.java
index 10a27f38..6d71bbf1 100644
--- a/src/de/lmu/ifi/dbs/elki/math/ConvexHull2D.java
+++ b/src/de/lmu/ifi/dbs/elki/math/geometry/GrahamScanConvexHull2D.java
@@ -1,26 +1,27 @@
-package de.lmu.ifi.dbs.elki.math;
-/*
-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/>.
-*/
+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) 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 java.util.Collections;
import java.util.Comparator;
@@ -30,6 +31,7 @@ import java.util.List;
import java.util.Stack;
import de.lmu.ifi.dbs.elki.data.spatial.Polygon;
+import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
@@ -40,7 +42,7 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
* @author Erich Schubert
*/
@Reference(authors = "Paul Graham", title = "An Efficient Algorithm for Determining the Convex Hull of a Finite Planar Set", booktitle = "Information Processing Letters 1")
-public class ConvexHull2D {
+public class GrahamScanConvexHull2D {
/**
* The current set of points
*/
@@ -71,7 +73,7 @@ public class ConvexHull2D {
/**
* Constructor.
*/
- public ConvexHull2D() {
+ public GrahamScanConvexHull2D() {
this.points = new LinkedList<Vector>();
}
@@ -81,7 +83,7 @@ public class ConvexHull2D {
* @param point Point to add
*/
public void add(Vector point) {
- if (this.ok) {
+ if(this.ok) {
this.points = new LinkedList<Vector>(this.points);
this.ok = false;
}
@@ -116,18 +118,17 @@ public class ConvexHull2D {
Collections.sort(this.points, new Comparator<Vector>() {
@Override
public int compare(Vector o1, Vector o2) {
- return isLeft(o1, o2, origin) ? +1 : -1;
+ return isLeft(o1, o2, origin);
}
});
-
grahamScan();
this.ok = true;
}
/**
* Find the starting point, and sort it to the beginning of the list. The
- * starting point must be on the outer hull. Any "most extreme" point will do, e.g.
- * the one with the lowest Y coordinate and for ties with the lowest X.
+ * starting point must be on the outer hull. Any "most extreme" point will do,
+ * e.g. the one with the lowest Y coordinate and for ties with the lowest X.
*/
private void findStartingPoint() {
// Well, we already know the best Y value...
@@ -177,17 +178,17 @@ public class ConvexHull2D {
* @param a Vector A
* @param b Vector B
* @param o Origin vector
- * @return true when left
+ * @return +1 when left, 0 when same, -1 when right
*/
- protected final boolean isLeft(Vector a, Vector b, Vector o) {
+ protected final int isLeft(Vector a, Vector b, Vector o) {
final double cross = getRX(a, o) * getRY(b, o) - getRY(a, o) * getRX(b, o);
if(cross == 0) {
// Compare manhattan distances - same angle!
final double dista = Math.abs(getRX(a, o)) + Math.abs(getRY(a, o));
final double distb = Math.abs(getRX(b, o)) + Math.abs(getRY(b, o));
- return dista > distb;
+ return Double.compare(dista, distb);
}
- return cross > 0;
+ return Double.compare(cross, 0);
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/math/geometry/SweepHullDelaunay2D.java b/src/de/lmu/ifi/dbs/elki/math/geometry/SweepHullDelaunay2D.java
new file mode 100644
index 00000000..2533a2b0
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/geometry/SweepHullDelaunay2D.java
@@ -0,0 +1,929 @@
+package de.lmu.ifi.dbs.elki.math.geometry;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.BitSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Random;
+
+import de.lmu.ifi.dbs.elki.data.spatial.Polygon;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleIntPair;
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+/**
+ * Compute the Convex Hull and/or Delaunay Triangulation, using the sweep-hull
+ * approach of David Sinclair.
+ *
+ * Note: This implementation does not check or handle duplicate points!
+ *
+ * @author Erich Schubert
+ */
+@Reference(authors = "David Sinclair", title = "S-hull: a fast sweep-hull routine for Delaunay triangulation", booktitle = "Online: http://s-hull.org/")
+public class SweepHullDelaunay2D {
+ /**
+ * Class logger
+ */
+ private static final Logging logger = Logging.getLogger(SweepHullDelaunay2D.class);
+
+ /**
+ * The current set of points.
+ *
+ * Note: this list should not be changed after running the algorithm, since we
+ * use it for object indexing, and the ids should not change
+ */
+ private List<Vector> points;
+
+ /**
+ * Triangles
+ */
+ private ArrayList<Triangle> tris = null;
+
+ /**
+ * Internal representation of the hull
+ */
+ private LinkedList<IntIntPair> hull = null;
+
+ /**
+ * Constructor.
+ */
+ public SweepHullDelaunay2D() {
+ this(new ArrayList<Vector>());
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param points Existing points
+ */
+ public SweepHullDelaunay2D(List<Vector> points) {
+ this.points = points;
+ }
+
+ /**
+ * Add a single point to the list (this does not compute or update the
+ * triangulation!)
+ *
+ * @param point Point to add
+ */
+ public void add(Vector point) {
+ this.points.add(point);
+ // Invalidate
+ hull = null;
+ tris = null;
+ }
+
+ /**
+ * Run the actual algorithm
+ *
+ * @param hullonly
+ */
+ void run(boolean hullonly) {
+ if(points.size() < 3) {
+ throw new UnsupportedOperationException("There is no delaunay triangulation for less than three objects!");
+ }
+ int len = points.size() - 1;
+ hull = new LinkedList<IntIntPair>();
+ tris = hullonly ? null : new ArrayList<Triangle>(len);
+
+ final Vector seed;
+ final int seedid = 0;
+ final DoubleIntPair[] sort = new DoubleIntPair[len];
+ // TODO: remove duplicates.
+
+ // Select seed, sort by squared euclidean distance
+ {
+ Iterator<Vector> iter = points.iterator();
+ seed = iter.next();
+ for(int i = 0; iter.hasNext(); i++) {
+ assert (i < len);
+ Vector p = iter.next();
+ // Pair with distance, list-position
+ sort[i] = new DoubleIntPair(quadraticEuclidean(seed, p), i + 1);
+ }
+ assert (sort[len - 1] != null);
+ Arrays.sort(sort);
+ }
+ assert (sort[0].first > 0);
+ // final Vector seed2 = points.get(sort[0].second);
+ final int seed2id = sort[0].second;
+ int start = 1;
+
+ // Find minimal triangle for these two points:
+ Triangle besttri = new Triangle(seedid, seed2id, -1);
+ {
+ besttri.r2 = Double.MAX_VALUE;
+ Triangle testtri = new Triangle(seedid, seed2id, -1);
+ int besti = -1;
+ for(int i = start; i < len; i++) {
+ // Update test triad
+ testtri.c = sort[i].second;
+ if(testtri.updateCircumcircle(points) && testtri.r2 < besttri.r2) {
+ besttri.copyFrom(testtri);
+ besti = i;
+ }
+ else if(besttri.r2 * 4 < sort[i].first) {
+ // Stop early, points are too far away from seed.
+ break;
+ }
+ }
+ assert (besti != -1);
+ // Rearrange - remove third seed point.
+ if(besti > 1) {
+ DoubleIntPair tmp = sort[besti];
+ System.arraycopy(sort, 1, sort, 2, besti - 1);
+ sort[1] = tmp;
+ }
+ }
+ start = 2; // First two points have already been processed.
+
+ // Make right-handed:
+ besttri.makeClockwise(points);
+ // Seed triangulation
+ if(!hullonly) {
+ tris.add(besttri);
+ }
+ // Seed convex hull
+ hull.add(new IntIntPair(besttri.a, 0));
+ hull.add(new IntIntPair(besttri.b, 0));
+ hull.add(new IntIntPair(besttri.c, 0));
+
+ if(logger.isDebuggingFinest()) {
+ debugHull();
+ }
+
+ // Resort from triangle center
+ Vector center = besttri.m;
+ for(int i = start; i < len; i++) {
+ sort[i].first = quadraticEuclidean(center, points.get(sort[i].second));
+ }
+ Arrays.sort(sort, start, len);
+
+ // Grow hull and triangles
+ for(int i = start; i < len; i++) {
+ final int pointId = sort[i].second;
+ final Vector newpoint = points.get(pointId);
+
+ LinkedList<Triangle> newtris = hullonly ? null : new LinkedList<Triangle>();
+ // We identify edges by their starting point. -1 is invalid.
+ int hstart = -1, hend = -1;
+ // Find first and last consecutive visible edge, backwards:
+ {
+ Iterator<IntIntPair> iter = hull.descendingIterator();
+ IntIntPair next = hull.getFirst();
+ Vector nextV = points.get(next.first);
+ for(int pos = hull.size() - 1; iter.hasNext(); pos--) {
+ IntIntPair prev = iter.next();
+ Vector prevV = points.get(prev.first);
+ // Not yet visible:
+ if(hend < 0) {
+ if(leftOf(prevV, nextV, newpoint)) {
+ hstart = pos;
+ hend = pos;
+ if(!hullonly) {
+ // Clockwise, A is new point!
+ Triangle tri = new Triangle(pointId, next.first, prev.first);
+ assert (tri.isClockwise(points));
+ assert (prev.second >= 0);
+ tri.updateCircumcircle(points);
+ tri.bc = prev.second;
+ newtris.addFirst(tri);
+ }
+ }
+ }
+ else {
+ if(leftOf(prevV, nextV, newpoint)) {
+ hstart = pos;
+ // Add triad:
+ if(!hullonly) {
+ // Clockwise, A is new point!
+ Triangle tri = new Triangle(pointId, next.first, prev.first);
+ assert (tri.isClockwise(points));
+ assert (prev.second >= 0);
+ tri.updateCircumcircle(points);
+ tri.bc = prev.second;
+ newtris.addFirst(tri);
+ }
+ }
+ else {
+ break;
+ }
+ }
+ next = prev;
+ nextV = prevV;
+ }
+ }
+ // If the last edge was visible, we also need to scan forwards:
+ if(hend == hull.size() - 1) {
+ Iterator<IntIntPair> iter = hull.iterator();
+ IntIntPair prev = iter.next();
+ Vector prevV = points.get(prev.first);
+ while(iter.hasNext()) {
+ IntIntPair next = iter.next();
+ Vector nextV = points.get(next.first);
+ if(leftOf(prevV, nextV, newpoint)) {
+ hend++;
+ // Add triad:
+ if(!hullonly) {
+ // Clockwise, A is new point!
+ Triangle tri = new Triangle(pointId, next.first, prev.first);
+ assert (tri.isClockwise(points));
+ assert (prev.second >= 0);
+ tri.updateCircumcircle(points);
+ tri.bc = prev.second;
+ newtris.addLast(tri);
+ }
+ }
+ else {
+ break;
+ }
+ prev = next;
+ prevV = nextV;
+ }
+ }
+ assert (hstart >= 0 && hend >= hstart);
+ // Note that hend can be larger than hull.size() now, interpret as
+ // "hend % hull.size()"
+ // Update hull, remove points
+ final int firsttri, lasttri;
+ if(hullonly) {
+ firsttri = -1;
+ lasttri = -1;
+ }
+ else {
+ final int tristart = tris.size();
+ firsttri = tristart;
+ lasttri = tristart + newtris.size() - 1;
+ }
+ final int hullsize = hull.size();
+ if(logger.isDebuggingFinest()) {
+ logger.debugFinest("Size: " + hullsize + " start: " + hstart + " end: " + hend);
+ }
+ if(hend < hullsize) {
+ ListIterator<IntIntPair> iter = hull.listIterator();
+ int p = 0;
+ // Skip
+ for(; p <= hstart; p++) {
+ iter.next();
+ }
+ // Remove
+ for(; p <= hend; p++) {
+ iter.next();
+ iter.remove();
+ }
+ // Insert, and update edge->triangle mapping
+ iter.add(new IntIntPair(pointId, lasttri));
+ iter.previous();
+ if(!hullonly) {
+ if(iter.hasPrevious()) {
+ iter.previous().second = firsttri;
+ }
+ else {
+ hull.getLast().second = firsttri;
+ }
+ }
+ }
+ else {
+ // System.err.println("Case #2 "+pointId+" "+hstart+" "+hend+" "+hullsize);
+ ListIterator<IntIntPair> iter = hull.listIterator();
+ // Remove end
+ int p = hullsize;
+ for(; p <= hend; p++) {
+ iter.next();
+ iter.remove();
+ }
+ // Insert
+ iter.add(new IntIntPair(pointId, lasttri));
+ // Wrap around
+ p -= hullsize;
+ IntIntPair pre = null;
+ for(; p <= hstart; p++) {
+ pre = iter.next();
+ }
+ assert (pre != null);
+ pre.second = firsttri;
+ // Remove remainder
+ while(iter.hasNext()) {
+ iter.next();
+ iter.remove();
+ }
+ }
+ if(logger.isDebuggingFinest()) {
+ debugHull();
+ }
+ if(!hullonly) {
+ final int tristart = tris.size();
+ // Connect triads (they are ordered)
+ Iterator<Triangle> iter = newtris.iterator();
+ for(int o = 0; iter.hasNext(); o++) {
+ // This triangle has num tristart + o.
+ Triangle cur = iter.next();
+ if(o > 0) {
+ cur.ca = tristart + o - 1; // previously added triangle
+ }
+ else {
+ cur.ca = -1; // outside
+ }
+ if(iter.hasNext()) {
+ cur.ab = tristart + o + 1; // next triangle
+ }
+ else {
+ cur.ab = -1; // outside
+ }
+ // cur.bc was set upon creation
+ assert (cur.bc >= 0);
+ Triangle other = tris.get(cur.bc);
+ Orientation orient = cur.findOrientation(other);
+ assert (orient != null) : "Inconsistent triangles: " + cur + " " + other;
+ switch(orient){
+ case ORIENT_BC_BA:
+ assert (other.ab == -1) : "Inconsistent triangles: " + cur + " " + other;
+ other.ab = tristart + o;
+ break;
+ case ORIENT_BC_CB:
+ assert (other.bc == -1) : "Inconsistent triangles: " + cur + " " + other;
+ other.bc = tristart + o;
+ break;
+ case ORIENT_BC_AC:
+ assert (other.ca == -1) : "Inconsistent triangles: " + cur + " " + other;
+ other.ca = tristart + o;
+ break;
+ default:
+ assert (cur.isClockwise(points));
+ assert (other.isClockwise(points));
+ throw new RuntimeException("Inconsistent triangles: " + cur + " " + other + " size:" + tris.size());
+ }
+ tris.add(cur);
+ }
+ assert (tris.size() == lasttri + 1);
+ }
+ }
+ // Now check for triangles that need flipping.
+ if(!hullonly) {
+ final int size = tris.size();
+ BitSet flippedA = new BitSet(size);
+ BitSet flippedB = new BitSet(size);
+ // Initial flip
+ int flipped = flipTriangles(null, flippedA);
+ for(int iterations = 1; iterations < 2000 && flipped > 0; iterations++) {
+ if(iterations % 2 == 1) {
+ flipped = flipTriangles(flippedA, flippedB);
+ }
+ else {
+ flipped = flipTriangles(flippedB, flippedA);
+ }
+ }
+ }
+ }
+
+ /**
+ * Debug helper
+ */
+ void debugHull() {
+ StringBuffer buf = new StringBuffer();
+ for(IntIntPair p : hull) {
+ buf.append(p).append(" ");
+ }
+ logger.debugFinest(buf);
+ }
+
+ /**
+ * Flip triangles as necessary
+ *
+ * @param flippedA Bit set for triangles to test
+ * @param flippedB Bit set to mark triangles as done
+ */
+ int flipTriangles(BitSet flippedA, BitSet flippedB) {
+ final int size = tris.size();
+ int numflips = 0;
+ flippedB.clear();
+ if(flippedA == null) {
+ for(int i = 0; i < size; i++) {
+ if(flipTriangle(i, flippedB) > 0) {
+ numflips += 2;
+ }
+ }
+ }
+ else {
+ for(int i = flippedA.nextSetBit(0); i > -1; i = flippedA.nextSetBit(i + 1)) {
+ if(flipTriangle(i, flippedB) > 0) {
+ numflips += 2;
+ }
+ }
+ }
+ return numflips;
+ }
+
+ /**
+ * Flip a single triangle, if necessary.
+ *
+ * @param i Triangle number
+ * @param flipped Bitset to modify
+ * @return number of other triangle, or -1
+ */
+ int flipTriangle(int i, BitSet flipped) {
+ final Triangle cur = tris.get(i);
+ // Test edge AB:
+ if(cur.ab >= 0) {
+ final int ot = cur.ab;
+ Triangle oth = tris.get(ot);
+ Orientation orient = cur.findOrientation(oth);
+ final int opp, lef, rig;
+ switch(orient){
+ case ORIENT_AB_BA:
+ opp = oth.c;
+ lef = oth.bc;
+ rig = oth.ca;
+ break;
+ case ORIENT_AB_CB:
+ opp = oth.a;
+ lef = oth.ca;
+ rig = oth.ab;
+ break;
+ case ORIENT_AB_AC:
+ opp = oth.b;
+ lef = oth.ab;
+ rig = oth.bc;
+ break;
+ default:
+ throw new RuntimeException("Neighbor triangles not aligned?");
+ }
+ if(cur.inCircle(points.get(opp))) {
+ // Replace edge AB, connect c with "opp" instead.
+ final int a = cur.c, b = cur.a, c = opp, d = cur.b;
+ final int ab = cur.ca, bc = lef, cd = rig, da = cur.bc;
+ final int ca = ot, ac = i;
+ // Update current:
+ cur.set(a, ab, b, bc, c, ca);
+ cur.updateCircumcircle(points);
+ // Update other:
+ oth.set(c, cd, d, da, a, ac);
+ oth.updateCircumcircle(points);
+ // Update tri touching on BC and DA:
+ if(bc >= 0) {
+ tris.get(bc).replaceEdge(c, b, ot, i);
+ }
+ if(da >= 0) {
+ tris.get(da).replaceEdge(a, d, i, ot);
+ }
+ flipped.set(i);
+ flipped.set(ot);
+ return ot;
+ }
+ }
+ // Test edge BC:
+ if(cur.bc >= 0) {
+ final int ot = cur.bc;
+ Triangle oth = tris.get(ot);
+ Orientation orient = cur.findOrientation(oth);
+ final int opp, lef, rig;
+ switch(orient){
+ case ORIENT_BC_BA:
+ opp = oth.c;
+ lef = oth.bc;
+ rig = oth.ca;
+ break;
+ case ORIENT_BC_CB:
+ opp = oth.a;
+ lef = oth.ca;
+ rig = oth.ab;
+ break;
+ case ORIENT_BC_AC:
+ opp = oth.b;
+ lef = oth.ab;
+ rig = oth.bc;
+ break;
+ default:
+ throw new RuntimeException("Neighbor triangles not aligned?");
+ }
+ if(cur.inCircle(points.get(opp))) {
+ // Replace edge BC, connect A with "opp" instead.
+ final int a = cur.a, b = cur.b, c = opp, d = cur.c;
+ final int ab = cur.ab, bc = lef, cd = rig, da = cur.ca;
+ final int ca = ot, ac = i;
+ // Update current:
+ cur.set(a, ab, b, bc, c, ca);
+ cur.updateCircumcircle(points);
+ // Update other:
+ oth.set(c, cd, d, da, a, ac);
+ oth.updateCircumcircle(points);
+ // Update tri touching on BC and DA:
+ if(bc >= 0) {
+ tris.get(bc).replaceEdge(c, b, ot, i);
+ }
+ if(da >= 0) {
+ tris.get(da).replaceEdge(a, d, i, ot);
+ }
+ flipped.set(i);
+ flipped.set(ot);
+ return ot;
+ }
+ }
+ // Test edge CA:
+ if(cur.ca >= 0) {
+ final int ot = cur.ca;
+ Triangle oth = tris.get(ot);
+ Orientation orient = cur.findOrientation(oth);
+ final int opp, lef, rig;
+ switch(orient){
+ case ORIENT_CA_BA:
+ opp = oth.c;
+ lef = oth.bc;
+ rig = oth.ca;
+ break;
+ case ORIENT_CA_CB:
+ opp = oth.a;
+ lef = oth.ca;
+ rig = oth.ab;
+ break;
+ case ORIENT_CA_AC:
+ opp = oth.b;
+ lef = oth.ab;
+ rig = oth.bc;
+ break;
+ default:
+ throw new RuntimeException("Neighbor triangles not aligned?");
+ }
+ if(cur.inCircle(points.get(opp))) {
+ // Replace edge CA, connect B with "opp" instead.
+ final int a = cur.b, b = cur.c, c = opp, d = cur.a;
+ final int ab = cur.bc, bc = lef, cd = rig, da = cur.ab;
+ final int ca = ot, ac = i;
+ // Update current:
+ cur.set(a, ab, b, bc, c, ca);
+ cur.updateCircumcircle(points);
+ // Update other:
+ oth.set(c, cd, d, da, a, ac);
+ oth.updateCircumcircle(points);
+ // Update tri touching on BC and DA:
+ if(bc >= 0) {
+ tris.get(bc).replaceEdge(c, b, ot, i);
+ }
+ if(da >= 0) {
+ tris.get(da).replaceEdge(a, d, i, ot);
+ }
+ flipped.set(i);
+ flipped.set(ot);
+ return ot;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Get the convex hull only.
+ *
+ * Note: if you also want the Delaunay Triangulation, you should get that
+ * first!
+ *
+ * @return Convex hull
+ */
+ public Polygon getHull() {
+ if(hull == null) {
+ run(true);
+ }
+ DoubleMinMax minmaxX = new DoubleMinMax();
+ DoubleMinMax minmaxY = new DoubleMinMax();
+ List<Vector> hullp = new ArrayList<Vector>(hull.size());
+ for(IntIntPair pair : hull) {
+ Vector v = points.get(pair.first);
+ hullp.add(v);
+ minmaxX.put(v.get(0));
+ minmaxY.put(v.get(1));
+ }
+ return new Polygon(hullp, minmaxX.getMin(), minmaxX.getMax(), minmaxY.getMin(), minmaxY.getMax());
+ }
+
+ /**
+ * Get the Delaunay triangulation.
+ *
+ * @return Triangle list
+ */
+ public ArrayList<Triangle> getDelaunay() {
+ if(tris == null) {
+ run(false);
+ }
+ return tris;
+ }
+
+ /**
+ * Squared euclidean distance. 2d.
+ *
+ * @param v1 First vector
+ * @param v2 Second vector
+ * @return Quadratic distance
+ */
+ public static double quadraticEuclidean(Vector v1, Vector v2) {
+ final double d1 = v1.get(0) - v2.get(0);
+ final double d2 = v1.get(1) - v2.get(1);
+ return (d1 * d1) + (d2 * d2);
+ }
+
+ /**
+ * Test if the vector AD is right of AB.
+ *
+ * @param a Starting point
+ * @param b Reference point
+ * @param d Test point
+ * @return true when on the left side
+ */
+ boolean leftOf(Vector a, Vector b, Vector d) {
+ final double bax = b.get(0) - a.get(0);
+ final double bay = b.get(1) - a.get(1);
+ final double dax = d.get(0) - a.get(0);
+ final double day = d.get(1) - a.get(1);
+ final double cross = bax * day - bay * dax;
+ return cross > 0;
+ }
+
+ /**
+ * The possible orientations two triangles can have to each other. (Shared
+ * edges must have different directions!)
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ static enum Orientation {
+ ORIENT_AB_BA, ORIENT_AB_CB, ORIENT_AB_AC, ORIENT_BC_BA, ORIENT_BC_CB, ORIENT_BC_AC, ORIENT_CA_BA, ORIENT_CA_CB, ORIENT_CA_AC
+ }
+
+ /**
+ * Class representing a triangle, by referencing points in a list.
+ *
+ * @author Erich Schubert
+ */
+ public static class Triangle {
+ /**
+ * References to points in Delaunay2D.points
+ */
+ public int a, b, c;
+
+ /**
+ * References to neighbor triangles
+ */
+ public int ab = -1, ca = -1, bc = -1;
+
+ /**
+ * Circumcircle parameters
+ */
+ public double r2 = -1;
+
+ /**
+ * Center vector
+ */
+ public Vector m = new Vector(2);
+
+ /**
+ * Constructor.
+ *
+ * @param x
+ * @param y
+ * @param z
+ */
+ public Triangle(int x, int y, int z) {
+ a = x;
+ b = y;
+ c = z;
+ }
+
+ /**
+ * Replace an edge
+ *
+ * @param a First point
+ * @param b Second point
+ * @param ol Previous value
+ * @param ne New value
+ */
+ void replaceEdge(int a, int b, int ol, int ne) {
+ if(this.a == a && this.b == b) {
+ assert (this.ab == ol) : "Edge doesn't match: " + this + " " + a + " " + b + " " + ol + " " + ne;
+ this.ab = ne;
+ return;
+ }
+ if(this.b == a && this.c == b) {
+ assert (this.bc == ol) : "Edge doesn't match: " + this + " " + a + " " + b + " " + ol + " " + ne;
+ this.bc = ne;
+ return;
+ }
+ if(this.c == a && this.a == b) {
+ assert (this.ca == ol) : "Edge doesn't match: " + this + " " + a + " " + b + " " + ol + " " + ne;
+ this.ca = ne;
+ return;
+ }
+ }
+
+ /**
+ * Update the triangle.
+ *
+ * @param a First point
+ * @param ab Edge
+ * @param b Second point
+ * @param bc Edge
+ * @param c Third point
+ * @param ca Edge
+ */
+ void set(int a, int ab, int b, int bc, int c, int ca) {
+ this.a = a;
+ this.ab = ab;
+ this.b = b;
+ this.bc = bc;
+ this.c = c;
+ this.ca = ca;
+ }
+
+ /**
+ * Test whether a point is within the circumference circle.
+ *
+ * @param opp Test vector
+ * @return true when contained
+ */
+ public boolean inCircle(Vector opp) {
+ double dx = opp.get(0) - m.get(0);
+ double dy = opp.get(1) - m.get(1);
+ return (dx * dx + dy * dy) <= r2;
+ }
+
+ /**
+ * Find the orientation of the triangles to each other.
+ *
+ * @param oth Other triangle
+ * @return shared edge
+ */
+ Orientation findOrientation(Triangle oth) {
+ if(this.a == oth.a) {
+ if(this.b == oth.c) {
+ return Orientation.ORIENT_AB_AC;
+ }
+ if(this.c == oth.b) {
+ return Orientation.ORIENT_CA_BA;
+ }
+ }
+ if(this.a == oth.b) {
+ if(this.b == oth.a) {
+ return Orientation.ORIENT_AB_BA;
+ }
+ if(this.c == oth.c) {
+ return Orientation.ORIENT_CA_CB;
+ }
+ }
+ if(this.a == oth.c) {
+ if(this.b == oth.b) {
+ return Orientation.ORIENT_AB_CB;
+ }
+ if(this.c == oth.a) {
+ return Orientation.ORIENT_CA_AC;
+ }
+ }
+ if(this.b == oth.b) {
+ if(this.c == oth.a) {
+ return Orientation.ORIENT_BC_BA;
+ }
+ }
+ if(this.b == oth.c) {
+ if(this.c == oth.b) {
+ return Orientation.ORIENT_BC_CB;
+ }
+ }
+ if(this.b == oth.a) {
+ if(this.c == oth.c) {
+ return Orientation.ORIENT_BC_AC;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Make the triangle clockwise
+ */
+ void makeClockwise(List<Vector> points) {
+ if(!isClockwise(points)) {
+ // Swap points B, C
+ int t = b;
+ b = c;
+ c = t;
+ // And the associated edges
+ t = ab;
+ ab = ca;
+ ca = t;
+ }
+ }
+
+ /**
+ * Verify that the triangle is clockwise
+ */
+ boolean isClockwise(List<Vector> points) {
+ // Mean
+ double centX = (points.get(a).get(0) + points.get(b).get(0) + points.get(c).get(0)) / 3.0f;
+ double centY = (points.get(a).get(1) + points.get(b).get(1) + points.get(c).get(1)) / 3.0f;
+
+ double dr0 = points.get(a).get(0) - centX, dc0 = points.get(a).get(1) - centY;
+ double dx01 = points.get(b).get(0) - points.get(a).get(0), dy01 = points.get(b).get(1) - points.get(a).get(1);
+
+ double df = -dx01 * dc0 + dy01 * dr0;
+ return (df <= 0);
+ }
+
+ /**
+ * Copy the values from another triangle.
+ *
+ * @param o object to copy from
+ */
+ void copyFrom(Triangle o) {
+ this.a = o.a;
+ this.b = o.b;
+ this.c = o.c;
+ this.r2 = o.r2;
+ this.m.set(0, o.m.get(0));
+ this.m.set(1, o.m.get(1));
+ }
+
+ /**
+ * Recompute the location and squared radius of circumcircle.
+ *
+ * Note: numerical stability is important!
+ *
+ * @return success
+ */
+ boolean updateCircumcircle(List<Vector> points) {
+ Vector pa = points.get(a), pb = points.get(b), pc = points.get(c);
+
+ // Compute vectors from A: AB, AC:
+ final double abx = pb.get(0) - pa.get(0), aby = pb.get(1) - pa.get(1);
+ final double acx = pc.get(0) - pa.get(0), acy = pc.get(1) - pa.get(1);
+
+ // Squared euclidean lengths
+ final double ablen = abx * abx + aby * aby;
+ final double aclen = acx * acx + acy * acy;
+
+ // Compute D
+ final double D = 2 * (abx * acy - aby * acx);
+
+ // No circumcircle:
+ if(D == 0) {
+ return false;
+ }
+
+ // Compute offset:
+ final double offx = (acy * ablen - aby * aclen) / D;
+ final double offy = (abx * aclen - acx * ablen) / D;
+
+
+ // Avoid degeneration:
+ r2 = offx * offx + offy * offy;
+ if((r2 > 1e10 * ablen || r2 > 1e10 * aclen)) {
+ return false;
+ }
+
+ m.set(0, pa.get(0) + offx);
+ m.set(1, pa.get(1) + offy);
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "Triangle [a=" + a + ", b=" + b + ", c=" + c + ", ab=" + ab + ", ac=" + ca + ", bc=" + bc + "]";
+ }
+ }
+
+ public static void main(String[] args) {
+ SweepHullDelaunay2D d = new SweepHullDelaunay2D();
+
+ Random r = new Random(1);
+ final int num = 100000;
+ for(int i = 0; i < num; i++) {
+ final Vector v = new Vector(r.nextDouble(), r.nextDouble());
+ // System.err.println(i + ": " + FormatUtil.format(v.getArrayRef(), " "));
+ d.add(v);
+ }
+ d.run(false);
+ }
+} \ 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
new file mode 100644
index 00000000..a7bb6e6e
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/geometry/package-info.java
@@ -0,0 +1,26 @@
+/**
+ * <p>Algorithms from computational geometry.</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.math.geometry; \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/math/AggregatingHistogram.java b/src/de/lmu/ifi/dbs/elki/math/histograms/AggregatingHistogram.java
index 47919752..baa9eb54 100644
--- a/src/de/lmu/ifi/dbs/elki/math/AggregatingHistogram.java
+++ b/src/de/lmu/ifi/dbs/elki/math/histograms/AggregatingHistogram.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.math;
+package de.lmu.ifi.dbs.elki.math.histograms;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2011
+ Copyright (C) 2012
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.math;
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.utilities.pairs.DoubleDoublePair;
+import de.lmu.ifi.dbs.elki.utilities.pairs.IntIntPair;
import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
/**
@@ -46,7 +49,7 @@ public class AggregatingHistogram<T, D> extends ReplacingHistogram<T> {
* Adapter class for an AggregatingHistogram
*
* @author Erich Schubert
- *
+ *
* @param <T> Histogram bin type
* @param <D> Incoming data type
*/
@@ -62,7 +65,7 @@ public class AggregatingHistogram<T, D> extends ReplacingHistogram<T> {
}
/**
- * Constructor with Adapter.
+ * Constructor with Adapter.
*
* @param bins Number of bins
* @param min Minimum value
@@ -181,31 +184,31 @@ public class AggregatingHistogram<T, D> extends ReplacingHistogram<T> {
* Histograms that work like two {@link #IntSumHistogram}, component wise.
*
* @param bins Number of bins.
- * @param min Minimum value
+ * @param min Minimum value
* @param max Maximum value
* @return Histogram object
*/
- public static AggregatingHistogram<Pair<Integer, Integer>, Pair<Integer, Integer>> IntSumIntSumHistogram(int bins, double min, double max) {
- return new AggregatingHistogram<Pair<Integer, Integer>, Pair<Integer, Integer>>(bins, min, max, new Adapter<Pair<Integer, Integer>, Pair<Integer, Integer>>() {
+ public static AggregatingHistogram<IntIntPair, IntIntPair> IntSumIntSumHistogram(int bins, double min, double max) {
+ return new AggregatingHistogram<IntIntPair, IntIntPair>(bins, min, max, new Adapter<IntIntPair, IntIntPair>() {
@Override
- public Pair<Integer, Integer> make() {
- return new Pair<Integer, Integer>(0,0);
+ public IntIntPair make() {
+ return new IntIntPair(0, 0);
}
@Override
- public Pair<Integer, Integer> aggregate(Pair<Integer, Integer> existing, Pair<Integer, Integer> data) {
- existing.setFirst(existing.getFirst() + data.getFirst());
- existing.setSecond(existing.getSecond() + data.getSecond());
+ public IntIntPair aggregate(IntIntPair existing, IntIntPair data) {
+ existing.first = existing.first + data.first;
+ existing.second = existing.second + data.second;
return existing;
}
});
}
-
+
/**
* Histograms that work like two {@link #LongSumHistogram}, component wise.
*
* @param bins Number of bins.
- * @param min Minimum value
+ * @param min Minimum value
* @param max Maximum value
* @return Histogram object
*/
@@ -213,7 +216,7 @@ public class AggregatingHistogram<T, D> extends ReplacingHistogram<T> {
return new AggregatingHistogram<Pair<Long, Long>, Pair<Long, Long>>(bins, min, max, new Adapter<Pair<Long, Long>, Pair<Long, Long>>() {
@Override
public Pair<Long, Long> make() {
- return new Pair<Long, Long>(0L,0L);
+ return new Pair<Long, Long>(0L, 0L);
}
@Override
@@ -224,26 +227,26 @@ public class AggregatingHistogram<T, D> extends ReplacingHistogram<T> {
}
});
}
-
+
/**
* Histograms that work like two {@link #DoubleSumHistogram}, component wise.
*
* @param bins Number of bins.
- * @param min Minimum value
+ * @param min Minimum value
* @param max Maximum value
* @return Histogram object
*/
- public static AggregatingHistogram<Pair<Double, Double>, Pair<Double, Double>> DoubleSumDoubleSumHistogram(int bins, double min, double max) {
- return new AggregatingHistogram<Pair<Double, Double>, Pair<Double, Double>>(bins, min, max, new Adapter<Pair<Double, Double>, Pair<Double, Double>>() {
+ public static AggregatingHistogram<DoubleDoublePair, DoubleDoublePair> DoubleSumDoubleSumHistogram(int bins, double min, double max) {
+ return new AggregatingHistogram<DoubleDoublePair, DoubleDoublePair>(bins, min, max, new Adapter<DoubleDoublePair, DoubleDoublePair>() {
@Override
- public Pair<Double, Double> make() {
- return new Pair<Double, Double>(0.,0.);
+ public DoubleDoublePair make() {
+ return new DoubleDoublePair(0., 0.);
}
@Override
- public Pair<Double, Double> aggregate(Pair<Double, Double> existing, Pair<Double, Double> data) {
- existing.setFirst(existing.getFirst() + data.getFirst());
- existing.setSecond(existing.getSecond() + data.getSecond());
+ public DoubleDoublePair aggregate(DoubleDoublePair existing, DoubleDoublePair data) {
+ existing.first = existing.first + data.first;
+ existing.second = existing.second + data.second;
return existing;
}
});
diff --git a/src/de/lmu/ifi/dbs/elki/math/FlexiHistogram.java b/src/de/lmu/ifi/dbs/elki/math/histograms/FlexiHistogram.java
index 9023a126..cee151ed 100644
--- a/src/de/lmu/ifi/dbs/elki/math/FlexiHistogram.java
+++ b/src/de/lmu/ifi/dbs/elki/math/histograms/FlexiHistogram.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.math;
+package de.lmu.ifi.dbs.elki.math.histograms;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,8 +26,12 @@ package de.lmu.ifi.dbs.elki.math;
import java.util.ArrayList;
import java.util.Iterator;
+import de.lmu.ifi.dbs.elki.math.MeanVariance;
+import de.lmu.ifi.dbs.elki.math.scales.LinearScale;
+import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleDoublePair;
+import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleObjPair;
+import de.lmu.ifi.dbs.elki.utilities.pairs.IntIntPair;
import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
-import de.lmu.ifi.dbs.elki.visualization.scales.LinearScale;
/**
* Histogram with flexible size, guaranteed to be in [bin, 2*bin[
@@ -39,16 +43,16 @@ import de.lmu.ifi.dbs.elki.visualization.scales.LinearScale;
* @param <T> Type of data in histogram
* @param <D> Type of input data
*/
-public class FlexiHistogram<T,D> extends AggregatingHistogram<T,D> {
+public class FlexiHistogram<T, D> extends AggregatingHistogram<T, D> {
/**
* Adapter class, extended "maker".
*/
- private Adapter<T,D> downsampler;
+ private Adapter<T, D> downsampler;
/**
* Cache for elements when not yet initialized.
*/
- private ArrayList<Pair<Double, D>> tempcache = null;
+ private ArrayList<DoubleObjPair<D>> tempcache = null;
/**
* Destination (minimum) size of the structure. At most 2*destsize bins are
@@ -64,7 +68,7 @@ public class FlexiHistogram<T,D> extends AggregatingHistogram<T,D> {
* @param <T> Type of data in histogram
* @param <D> Type of input data
*/
- public static abstract class Adapter<T,D> extends AggregatingHistogram.Adapter<T,D> {
+ public static abstract class Adapter<T, D> extends AggregatingHistogram.Adapter<T, D> {
/**
* Rule to combine two bins into one.
*
@@ -94,11 +98,11 @@ public class FlexiHistogram<T,D> extends AggregatingHistogram<T,D> {
* @param bins Target number of bins
* @param adapter Adapter for data types and combination rules.
*/
- public FlexiHistogram(int bins, Adapter<T,D> adapter) {
+ public FlexiHistogram(int bins, Adapter<T, D> adapter) {
super(bins, 0.0, 1.0, adapter);
this.destsize = bins;
this.downsampler = adapter;
- tempcache = new ArrayList<Pair<Double, D>>(this.destsize * 2);
+ tempcache = new ArrayList<DoubleObjPair<D>>(this.destsize * 2);
}
private synchronized void materialize() {
@@ -114,7 +118,7 @@ public class FlexiHistogram<T,D> extends AggregatingHistogram<T,D> {
}
double min = Double.MAX_VALUE;
double max = Double.MIN_VALUE;
- for(Pair<Double, D> pair : tempcache) {
+ for(DoubleObjPair<D> pair : tempcache) {
min = Math.min(min, pair.first);
max = Math.max(max, pair.first);
}
@@ -131,7 +135,7 @@ public class FlexiHistogram<T,D> extends AggregatingHistogram<T,D> {
this.data.add(downsampler.make());
}
// re-insert data we have
- for(Pair<Double, D> pair : tempcache) {
+ for(DoubleObjPair<D> pair : tempcache) {
super.aggregate(pair.first, pair.second);
}
// delete cache, signal that we're initialized
@@ -152,9 +156,10 @@ public class FlexiHistogram<T,D> extends AggregatingHistogram<T,D> {
// Resampling.
ArrayList<T> newdata = new ArrayList<T>(this.destsize * 2);
for(int i = 0; i < super.size; i += 2) {
- if (i + 1 < super.size) {
+ if(i + 1 < super.size) {
newdata.add(downsampler.downsample(super.data.get(i), super.data.get(i + 1)));
- } else {
+ }
+ else {
newdata.add(downsampler.downsample(super.data.get(i), super.make()));
}
}
@@ -208,13 +213,31 @@ public class FlexiHistogram<T,D> extends AggregatingHistogram<T,D> {
}
@Override
- public Iterator<Pair<Double, T>> iterator() {
+ public double getBinMean(int bin) {
+ materialize();
+ return super.getBinMean(bin);
+ }
+
+ @Override
+ public double getBinMin(int bin) {
+ materialize();
+ return super.getBinMin(bin);
+ }
+
+ @Override
+ public double getBinMax(int bin) {
+ materialize();
+ return super.getBinMax(bin);
+ }
+
+ @Override
+ public Iterator<DoubleObjPair<T>> iterator() {
materialize();
return super.iterator();
}
@Override
- public Iterator<Pair<Double, T>> reverseIterator() {
+ public Iterator<DoubleObjPair<T>> reverseIterator() {
materialize();
return super.reverseIterator();
}
@@ -223,7 +246,7 @@ public class FlexiHistogram<T,D> extends AggregatingHistogram<T,D> {
public void aggregate(double coord, D value) {
if(tempcache != null) {
if(tempcache.size() < this.destsize * 2) {
- tempcache.add(new Pair<Double, D>(coord, downsampler.cloneForCache(value)));
+ tempcache.add(new DoubleObjPair<D>(coord, downsampler.cloneForCache(value)));
return;
}
else {
@@ -372,32 +395,32 @@ public class FlexiHistogram<T,D> extends AggregatingHistogram<T,D> {
* @param bins Number of bins.
* @return New Histogram object
*/
- public static FlexiHistogram<Pair<Integer, Integer>, Pair<Integer, Integer>> IntSumIntSumHistogram(int bins) {
- return new FlexiHistogram<Pair<Integer, Integer>, Pair<Integer, Integer>>(bins, new Adapter<Pair<Integer, Integer>, Pair<Integer, Integer>>() {
+ public static FlexiHistogram<IntIntPair, IntIntPair> IntSumIntSumHistogram(int bins) {
+ return new FlexiHistogram<IntIntPair, IntIntPair>(bins, new Adapter<IntIntPair, IntIntPair>() {
@Override
- public Pair<Integer, Integer> make() {
- return new Pair<Integer, Integer>(0,0);
+ public IntIntPair make() {
+ return new IntIntPair(0, 0);
}
@Override
- public Pair<Integer, Integer> cloneForCache(Pair<Integer, Integer> data) {
- return new Pair<Integer, Integer>(data.getFirst(), data.getSecond());
+ public IntIntPair cloneForCache(IntIntPair data) {
+ return new IntIntPair(data.first, data.second);
}
@Override
- public Pair<Integer, Integer> downsample(Pair<Integer, Integer> first, Pair<Integer, Integer> second) {
- return new Pair<Integer, Integer>(first.getFirst() + second.getFirst(), first.getSecond() + second.getSecond());
+ public IntIntPair downsample(IntIntPair first, IntIntPair second) {
+ return new IntIntPair(first.first + second.first, first.second + second.second);
}
@Override
- public Pair<Integer, Integer> aggregate(Pair<Integer, Integer> existing, Pair<Integer, Integer> data) {
- existing.setFirst(existing.getFirst() + data.getFirst());
- existing.setSecond(existing.getSecond() + data.getSecond());
+ public IntIntPair aggregate(IntIntPair existing, IntIntPair data) {
+ existing.first = existing.first + data.first;
+ existing.second = existing.second + data.second;
return existing;
}
});
}
-
+
/**
* Histograms that work like two {@link #LongSumHistogram}, component wise.
*
@@ -408,7 +431,7 @@ public class FlexiHistogram<T,D> extends AggregatingHistogram<T,D> {
return new FlexiHistogram<Pair<Long, Long>, Pair<Long, Long>>(bins, new Adapter<Pair<Long, Long>, Pair<Long, Long>>() {
@Override
public Pair<Long, Long> make() {
- return new Pair<Long, Long>(0L,0L);
+ return new Pair<Long, Long>(0L, 0L);
}
@Override
@@ -436,27 +459,27 @@ public class FlexiHistogram<T,D> extends AggregatingHistogram<T,D> {
* @param bins Number of bins.
* @return New Histogram object
*/
- public static FlexiHistogram<Pair<Double, Double>, Pair<Double, Double>> DoubleSumDoubleSumHistogram(int bins) {
- return new FlexiHistogram<Pair<Double, Double>, Pair<Double, Double>>(bins, new Adapter<Pair<Double, Double>, Pair<Double, Double>>() {
+ public static FlexiHistogram<DoubleDoublePair, DoubleDoublePair> DoubleSumDoubleSumHistogram(int bins) {
+ return new FlexiHistogram<DoubleDoublePair, DoubleDoublePair>(bins, new Adapter<DoubleDoublePair, DoubleDoublePair>() {
@Override
- public Pair<Double, Double> make() {
- return new Pair<Double, Double>(0.,0.);
+ public DoubleDoublePair make() {
+ return new DoubleDoublePair(0., 0.);
}
@Override
- public Pair<Double, Double> cloneForCache(Pair<Double, Double> data) {
- return new Pair<Double, Double>(data.getFirst(), data.getSecond());
+ public DoubleDoublePair cloneForCache(DoubleDoublePair data) {
+ return new DoubleDoublePair(data.first, data.second);
}
@Override
- public Pair<Double, Double> downsample(Pair<Double, Double> first, Pair<Double, Double> second) {
- return new Pair<Double, Double>(first.getFirst() + second.getFirst(), first.getSecond() + second.getSecond());
+ public DoubleDoublePair downsample(DoubleDoublePair first, DoubleDoublePair second) {
+ return new DoubleDoublePair(first.first + second.first, first.second + second.second);
}
@Override
- public Pair<Double, Double> aggregate(Pair<Double, Double> existing, Pair<Double, Double> data) {
- existing.setFirst(existing.getFirst() + data.getFirst());
- existing.setSecond(existing.getSecond() + data.getSecond());
+ public DoubleDoublePair aggregate(DoubleDoublePair existing, DoubleDoublePair data) {
+ existing.first = existing.first + data.first;
+ existing.second = existing.second + data.second;
return existing;
}
});
diff --git a/src/de/lmu/ifi/dbs/elki/math/ReplacingHistogram.java b/src/de/lmu/ifi/dbs/elki/math/histograms/ReplacingHistogram.java
index 689fceec..304a434b 100644
--- a/src/de/lmu/ifi/dbs/elki/math/ReplacingHistogram.java
+++ b/src/de/lmu/ifi/dbs/elki/math/histograms/ReplacingHistogram.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.math;
+package de.lmu.ifi.dbs.elki.math.histograms;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,7 +26,9 @@ package de.lmu.ifi.dbs.elki.math;
import java.util.ArrayList;
import java.util.Iterator;
-import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
+import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleDoublePair;
+import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleObjPair;
+import de.lmu.ifi.dbs.elki.utilities.pairs.IntIntPair;
/**
* Class to manage a simple Histogram.
@@ -34,27 +36,28 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
* Note: the iterator returns pairs containing the coordinate and the bin value!
*
* @author Erich Schubert
- *
+ *
* @apiviz.composedOf de.lmu.ifi.dbs.elki.math.ReplacingHistogram.Adapter
*
* @param <T> Histogram data type.
*/
-public class ReplacingHistogram<T> implements Iterable<Pair<Double, T>> {
+public class ReplacingHistogram<T> implements Iterable<DoubleObjPair<T>> {
/**
* Interface to plug in a data type T.
*
* @author Erich Schubert
- *
+ *
* @param <T> Data type
*/
public static abstract class Adapter<T> {
/**
* Construct a new T when needed.
+ *
* @return new T
*/
public abstract T make();
}
-
+
/**
* Array shift to account for negative indices.
*/
@@ -66,16 +69,15 @@ public class ReplacingHistogram<T> implements Iterable<Pair<Double, T>> {
protected int size;
/**
- * Array 'base', i.e. the point of 0.0.
- * Usually the minimum.
+ * Array 'base', i.e. the point of 0.0. Usually the minimum.
*/
protected double base;
-
+
/**
* To avoid introducing an extra bucket for the maximum value.
*/
protected double max;
-
+
/**
* Width of a bin.
*/
@@ -85,7 +87,7 @@ public class ReplacingHistogram<T> implements Iterable<Pair<Double, T>> {
* Data storage
*/
protected ArrayList<T> data;
-
+
/**
* Constructor for new elements
*/
@@ -106,14 +108,14 @@ public class ReplacingHistogram<T> implements Iterable<Pair<Double, T>> {
this.size = bins;
this.data = new ArrayList<T>(bins);
this.maker = maker;
- for (int i = 0; i < bins; i++) {
+ for(int i = 0; i < bins; i++) {
this.data.add(maker.make());
}
}
/**
- * Histogram constructor without 'Constructor' to generate new elements.
- * Empty bins will be initialized with 'null'.
+ * Histogram constructor without 'Constructor' to generate new elements. Empty
+ * bins will be initialized with 'null'.
*
* @param bins Number of bins
* @param min Minimum value
@@ -122,7 +124,7 @@ public class ReplacingHistogram<T> implements Iterable<Pair<Double, T>> {
public ReplacingHistogram(int bins, double min, double max) {
this(bins, min, max, null);
}
-
+
/**
* Get the data at a given Coordinate.
*
@@ -144,8 +146,8 @@ public class ReplacingHistogram<T> implements Iterable<Pair<Double, T>> {
}
/**
- * Put data at a given coordinate.
- * Note: this replaces the contents, it doesn't "add" or "count".
+ * Put data at a given coordinate. Note: this replaces the contents, it
+ * doesn't "add" or "count".
*
* @param coord Coordinate
* @param d New Data
@@ -156,18 +158,19 @@ public class ReplacingHistogram<T> implements Iterable<Pair<Double, T>> {
}
/**
- * Compute the bin number.
- * Has a special case for rounding max down to the last bin.
- *
+ * Compute the bin number. Has a special case for rounding max down to the
+ * last bin.
+ *
* @param coord Coordinate
* @return bin number
*/
protected int getBinNr(double coord) {
- if (Double.isInfinite(coord) || Double.isNaN(coord)) {
- throw new UnsupportedOperationException("Encountered non-finite value in Histogram: "+coord);
+ if(Double.isInfinite(coord) || Double.isNaN(coord)) {
+ throw new UnsupportedOperationException("Encountered non-finite value in Histogram: " + coord);
}
- if (coord == max) {
- //System.err.println("Triggered special case: "+ (Math.floor((coord - base) / binsize) + offset) + " vs. " + (size - 1));
+ if(coord == max) {
+ // System.err.println("Triggered special case: "+ (Math.floor((coord -
+ // base) / binsize) + offset) + " vs. " + (size - 1));
return size - 1;
}
return (int) Math.floor((coord - base) / binsize) + offset;
@@ -198,7 +201,7 @@ public class ReplacingHistogram<T> implements Iterable<Pair<Double, T>> {
}
else if(bin >= size) {
this.data.ensureCapacity(bin + 1);
- while (data.size() < bin) {
+ while(data.size() < bin) {
data.add(maker.make());
}
// add the new data.
@@ -212,7 +215,7 @@ public class ReplacingHistogram<T> implements Iterable<Pair<Double, T>> {
this.data.set(bin, d);
}
}
-
+
/**
* Get the number of bins actually in use.
*
@@ -232,6 +235,36 @@ public class ReplacingHistogram<T> implements Iterable<Pair<Double, T>> {
}
/**
+ * Mean of bin
+ *
+ * @param bin Bin number
+ * @return Mean
+ */
+ public double getBinMean(int bin) {
+ return base + (bin + 0.5 - offset) * binsize;
+ }
+
+ /**
+ * Minimum of bin
+ *
+ * @param bin Bin number
+ * @return Lower bound
+ */
+ public double getBinMin(int bin) {
+ return base + (bin - offset) * binsize;
+ }
+
+ /**
+ * Maximum of bin
+ *
+ * @param bin Bin number
+ * @return Upper bound
+ */
+ public double getBinMax(int bin) {
+ return base + (bin + 1 - offset) * binsize;
+ }
+
+ /**
* Get minimum (covered by bins, not data!)
*
* @return minimum
@@ -257,7 +290,7 @@ public class ReplacingHistogram<T> implements Iterable<Pair<Double, T>> {
public ArrayList<T> getData() {
return data;
}
-
+
/**
* Make a new bin.
*
@@ -266,7 +299,7 @@ public class ReplacingHistogram<T> implements Iterable<Pair<Double, T>> {
protected T make() {
return maker.make();
}
-
+
/**
* Iterator class to iterate over all bins.
*
@@ -274,20 +307,20 @@ public class ReplacingHistogram<T> implements Iterable<Pair<Double, T>> {
*
* @apiviz.exclude
*/
- protected class Iter implements Iterator<Pair<Double, T>> {
+ protected class Iter implements Iterator<DoubleObjPair<T>> {
/**
* Current bin number
*/
int bin = 0;
-
+
@Override
public boolean hasNext() {
return bin < size;
}
@Override
- public Pair<Double, T> next() {
- Pair<Double, T> pair = new Pair<Double, T>(base + (bin + 0.5 - offset) * binsize, data.get(bin));
+ public DoubleObjPair<T> next() {
+ DoubleObjPair<T> pair = new DoubleObjPair<T>(base + (bin + 0.5 - offset) * binsize, data.get(bin));
bin++;
return pair;
}
@@ -305,20 +338,20 @@ public class ReplacingHistogram<T> implements Iterable<Pair<Double, T>> {
*
* @apiviz.exclude
*/
- protected class RIter implements Iterator<Pair<Double, T>> {
+ protected class RIter implements Iterator<DoubleObjPair<T>> {
/**
* Current bin number
*/
int bin = size - 1;
-
+
@Override
public boolean hasNext() {
return bin >= 0;
}
@Override
- public Pair<Double, T> next() {
- Pair<Double, T> pair = new Pair<Double, T>(base + (bin + 0.5 - offset) * binsize, data.get(bin));
+ public DoubleObjPair<T> next() {
+ DoubleObjPair< T> pair = new DoubleObjPair<T>(base + (bin + 0.5 - offset) * binsize, data.get(bin));
bin--;
return pair;
}
@@ -333,21 +366,21 @@ public class ReplacingHistogram<T> implements Iterable<Pair<Double, T>> {
* Get an iterator over all histogram bins.
*/
@Override
- public Iterator<Pair<Double, T>> iterator() {
+ public Iterator<DoubleObjPair<T>> iterator() {
return new Iter();
}
-
+
/**
* Get an iterator over all histogram bins.
*/
// TODO: is there some interface to implement.
- public Iterator<Pair<Double, T>> reverseIterator() {
+ public Iterator<DoubleObjPair<T>> reverseIterator() {
return new RIter();
}
-
+
/**
- * Convenience constructor for Integer-based Histograms.
- * Uses a constructor to initialize bins with Integer(0)
+ * Convenience constructor for Integer-based Histograms. Uses a constructor to
+ * initialize bins with Integer(0)
*
* @param bins Number of bins
* @param min Minimum coordinate
@@ -364,8 +397,8 @@ public class ReplacingHistogram<T> implements Iterable<Pair<Double, T>> {
}
/**
- * Convenience constructor for Double-based Histograms.
- * Uses a constructor to initialize bins with Double(0)
+ * Convenience constructor for Double-based Histograms. Uses a constructor to
+ * initialize bins with Double(0)
*
* @param bins Number of bins
* @param min Minimum coordinate
@@ -382,37 +415,37 @@ public class ReplacingHistogram<T> implements Iterable<Pair<Double, T>> {
}
/**
- * Convenience constructor for Histograms with pairs of Integers
- * Uses a constructor to initialize bins with Pair(Integer(0),Integer(0))
+ * Convenience constructor for Histograms with pairs of Integers Uses a
+ * constructor to initialize bins with Pair(Integer(0),Integer(0))
*
* @param bins Number of bins
* @param min Minimum coordinate
* @param max Maximum coordinate
* @return New histogram for Integer pairs.
*/
- public static ReplacingHistogram<Pair<Integer,Integer>> IntIntHistogram(int bins, double min, double max) {
- return new ReplacingHistogram<Pair<Integer,Integer>>(bins, min, max, new Adapter<Pair<Integer,Integer>>() {
+ public static ReplacingHistogram<IntIntPair> IntIntHistogram(int bins, double min, double max) {
+ return new ReplacingHistogram<IntIntPair>(bins, min, max, new Adapter<IntIntPair>() {
@Override
- public Pair<Integer,Integer> make() {
- return new Pair<Integer,Integer>(0,0);
+ public IntIntPair make() {
+ return new IntIntPair(0, 0);
}
});
}
/**
- * Convenience constructor for Histograms with pairs of Doubles
- * Uses a constructor to initialize bins with Pair(Double(0),Double(0))
+ * Convenience constructor for Histograms with pairs of Doubles Uses a
+ * constructor to initialize bins with Pair(Double(0),Double(0))
*
* @param bins Number of bins
* @param min Minimum coordinate
* @param max Maximum coordinate
* @return New histogram for Double pairs.
*/
- public static ReplacingHistogram<Pair<Double,Double>> DoubleDoubleHistogram(int bins, double min, double max) {
- return new ReplacingHistogram<Pair<Double,Double>>(bins, min, max, new Adapter<Pair<Double,Double>>() {
+ public static ReplacingHistogram<DoubleDoublePair> DoubleDoubleHistogram(int bins, double min, double max) {
+ return new ReplacingHistogram<DoubleDoublePair>(bins, min, max, new Adapter<DoubleDoublePair>() {
@Override
- public Pair<Double,Double> make() {
- return new Pair<Double,Double>(0.0,0.0);
+ public DoubleDoublePair make() {
+ return new DoubleDoublePair(0.0, 0.0);
}
});
}
diff --git a/src/de/lmu/ifi/dbs/elki/math/histograms/package-info.java b/src/de/lmu/ifi/dbs/elki/math/histograms/package-info.java
new file mode 100644
index 00000000..b4b23466
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/histograms/package-info.java
@@ -0,0 +1,26 @@
+/**
+ * <p>Classes for computing histograms.</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.math.histograms; \ No newline at end of file
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 6200164b..5d185ec5 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/AffineTransformation.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/AffineTransformation.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -150,7 +150,7 @@ public class AffineTransformation {
* @param v translation vector
*/
public void addTranslation(Vector v) {
- assert (v.getRowDimensionality() == dim);
+ assert (v.getDimensionality() == dim);
// reset inverse transformation - needs recomputation.
inv = null;
@@ -295,7 +295,7 @@ public class AffineTransformation {
* @return vector of dim+1, with new column having the value 1.0
*/
public Vector homogeneVector(Vector v) {
- assert (v.getRowDimensionality() == dim);
+ assert (v.getDimensionality() == dim);
double[] dv = new double[dim + 1];
for(int i = 0; i < dim; i++) {
dv[i] = v.get(i);
@@ -311,7 +311,7 @@ public class AffineTransformation {
* @return vector of dim+1, with new column having the value 0.0
*/
public Vector homogeneRelativeVector(Vector v) {
- assert (v.getRowDimensionality() == dim);
+ assert (v.getDimensionality() == dim);
// TODO: this only works properly when trans[dim][dim] == 1.0, right?
double[] dv = new double[dim + 1];
for(int i = 0; i < dim; i++) {
@@ -328,7 +328,7 @@ public class AffineTransformation {
* @return vector of dimension dim
*/
public Vector unhomogeneVector(Vector v) {
- assert (v.getRowDimensionality() == dim + 1);
+ assert (v.getDimensionality() == dim + 1);
// TODO: this only works properly when trans[dim][dim] == 1.0, right?
double[] dv = new double[dim];
double scale = v.get(dim);
@@ -346,7 +346,7 @@ public class AffineTransformation {
* @return vector of dimension dim
*/
public Vector unhomogeneRelativeVector(Vector v) {
- assert (v.getRowDimensionality() == dim + 1);
+ assert (v.getDimensionality() == dim + 1);
double[] dv = new double[dim];
double scale = v.get(dim);
assert (Math.abs(scale) == 0.0);
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 5ba3d4a6..cf3bb25b 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -41,11 +41,6 @@ import de.lmu.ifi.dbs.elki.utilities.DatabaseUtil;
*/
public class Centroid extends Vector {
/**
- * Serial version
- */
- private static final long serialVersionUID = 1L;
-
- /**
* The current weight
*/
protected double wsum;
@@ -147,7 +142,7 @@ public class Centroid extends Vector {
* @return the data
*/
public <F extends NumberVector<? extends F, ?>> F toVector(Relation<? extends F> relation) {
- return DatabaseUtil.assumeVectorField(relation).getFactory().newInstance(elements);
+ return DatabaseUtil.assumeVectorField(relation).getFactory().newNumberVector(elements);
}
/**
@@ -160,7 +155,7 @@ public class Centroid extends Vector {
int n = mat.getColumnDimensionality();
for(int i = 0; i < n; i++) {
// TODO: avoid constructing the vector objects?
- c.put(mat.getColumnVector(i));
+ c.put(mat.getCol(i));
}
return c;
}
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 ff3b8cfb..5209468f 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) 2011
+ Copyright (C) 2012
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 24ea740b..5d9d27a1 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -245,7 +245,7 @@ public class CovarianceMatrix {
* @return Mean vector
*/
public <F extends NumberVector<? extends F, ?>> F getMeanVector(Relation<? extends F> relation) {
- return DatabaseUtil.assumeVectorField(relation).getFactory().newInstance(mean);
+ return DatabaseUtil.assumeVectorField(relation).getFactory().newNumberVector(mean);
}
/**
@@ -332,7 +332,7 @@ public class CovarianceMatrix {
int n = mat.getColumnDimensionality();
for(int i = 0; i < n; i++) {
// TODO: avoid constructing the vector objects?
- c.put(mat.getColumnVector(i));
+ c.put(mat.getCol(i));
}
return c;
}
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 6b747dae..132393c6 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) 2011
+ Copyright (C) 2012
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 67d77089..48ce9c7b 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -253,7 +253,7 @@ public class EigenvalueDecomposition implements java.io.Serializable {
double g = d[l];
double p = (d[l + 1] - g) / (2.0 * e[l]);
- double r = MathUtil.hypotenuse(p, 1.0);
+ double r = MathUtil.fastHypot(p, 1.0);
if(p < 0) {
r = -r;
}
@@ -281,7 +281,7 @@ public class EigenvalueDecomposition implements java.io.Serializable {
s2 = s;
g = c * e[i];
h = c * p;
- r = MathUtil.hypotenuse(p, e[i]);
+ r = MathUtil.fastHypot(p, e[i]);
e[i + 1] = s * r;
s = e[i] / r;
c = p / r;
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 5adafe10..08634279 100644
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/LUDecomposition.java
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/LUDecomposition.java
@@ -1,10 +1,11 @@
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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,7 +24,6 @@ package de.lmu.ifi.dbs.elki.math.linearalgebra;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
/**
* LU Decomposition.
* <P>
@@ -78,11 +78,21 @@ public class LUDecomposition implements java.io.Serializable {
* @param A Rectangular matrix
*/
public LUDecomposition(Matrix A) {
- // Use a "left-looking", dot-product, Crout/Doolittle algorithm.
+ this(A.getArrayCopy(), A.getRowDimensionality(), A.getColumnDimensionality());
+ }
- LU = A.getArrayCopy();
- m = A.getRowDimensionality();
- n = A.getColumnDimensionality();
+ /**
+ * LU Decomposition
+ *
+ * @param LU Rectangular matrix
+ * @param m row dimensionality
+ * @param n column dimensionality
+ */
+ public LUDecomposition(double[][] LU, int m, int n) {
+ this.LU = LU;
+ this.m = m;
+ this.n = n;
+ // Use a "left-looking", dot-product, Crout/Doolittle algorithm.
piv = new int[m];
for(int i = 0; i < m; i++) {
piv[i] = i;
@@ -273,25 +283,57 @@ public class LUDecomposition implements java.io.Serializable {
Matrix Xmat = B.getMatrix(piv, 0, nx - 1);
double[][] X = Xmat.getArrayRef();
+ solveInplace(X, nx);
+ return Xmat;
+ }
+
+ /**
+ * Solve A*X = B
+ *
+ * @param B A Matrix with as many rows as A and any number of columns.
+ * @return X so that L*U*X = B(piv,:)
+ * @exception IllegalArgumentException Matrix row dimensions must agree.
+ * @exception RuntimeException Matrix is singular.
+ */
+ public double[][] solve(double[][] B) {
+ int mx = B.length;
+ int nx = B[0].length;
+ if(mx != m) {
+ throw new IllegalArgumentException("Matrix row dimensions must agree.");
+ }
+ if(!this.isNonsingular()) {
+ throw new RuntimeException("Matrix is singular.");
+ }
+ double[][] Xmat = new Matrix(B).getMatrix(piv, 0, nx - 1).getArrayRef();
+ solveInplace(Xmat, nx);
+ return Xmat;
+ }
+
+ /**
+ * Solve A*X = B
+ *
+ * @param B A Matrix with as many rows as A and any number of columns.
+ * @param nx Number of columns
+ */
+ private void solveInplace(double[][] B, int nx) {
// Solve L*Y = B(piv,:)
for(int k = 0; k < n; k++) {
for(int i = k + 1; i < n; i++) {
for(int j = 0; j < nx; j++) {
- X[i][j] -= X[k][j] * LU[i][k];
+ B[i][j] -= B[k][j] * LU[i][k];
}
}
}
// Solve U*X = Y;
for(int k = n - 1; k >= 0; k--) {
for(int j = 0; j < nx; j++) {
- X[k][j] /= LU[k][k];
+ B[k][j] /= LU[k][k];
}
for(int i = 0; i < k; i++) {
for(int j = 0; j < nx; j++) {
- X[i][j] -= X[k][j] * LU[i][k];
+ B[i][j] -= B[k][j] * LU[i][k];
}
}
}
- return Xmat;
}
} \ No newline at end of file
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 decec2b6..b6a53aa2 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) 2011
+ Copyright (C) 2012
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 fefe7e16..f64b1129 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) 2011
+ Copyright (C) 2012
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.math.linearalgebra;
*/
import java.io.BufferedReader;
-import java.io.Serializable;
import java.io.StreamTokenizer;
import java.util.Arrays;
import java.util.logging.Logger;
@@ -50,12 +49,7 @@ import de.lmu.ifi.dbs.elki.utilities.FormatUtil;
* @apiviz.uses Vector
* @apiviz.landmark
*/
-public class Matrix implements MatrixLike<Matrix>, Serializable {
- /**
- * Serial version
- */
- private static final long serialVersionUID = 1L;
-
+public class Matrix {
/**
* A small number to handle numbers near 0 as 0.
*/
@@ -278,7 +272,6 @@ public class Matrix implements MatrixLike<Matrix>, Serializable {
*
* @return a new matrix containing the same values as this matrix
*/
- @Override
public final Matrix copy() {
final Matrix X = new Matrix(elements.length, columndimension);
for(int i = 0; i < elements.length; i++) {
@@ -324,7 +317,6 @@ public class Matrix implements MatrixLike<Matrix>, Serializable {
*
* @return m, the number of rows.
*/
- @Override
public final int getRowDimensionality() {
return elements.length;
}
@@ -334,7 +326,6 @@ public class Matrix implements MatrixLike<Matrix>, Serializable {
*
* @return n, the number of columns.
*/
- @Override
public final int getColumnDimensionality() {
return columndimension;
}
@@ -347,7 +338,6 @@ public class Matrix implements MatrixLike<Matrix>, Serializable {
* @return A(i,j)
* @throws ArrayIndexOutOfBoundsException on bounds error
*/
- @Override
public final double get(final int i, final int j) {
return elements[i][j];
}
@@ -361,7 +351,6 @@ public class Matrix implements MatrixLike<Matrix>, Serializable {
* @return modified matrix
* @throws ArrayIndexOutOfBoundsException on bounds error
*/
- @Override
public final Matrix set(final int i, final int j, final double s) {
elements[i][j] = s;
return this;
@@ -376,7 +365,6 @@ public class Matrix implements MatrixLike<Matrix>, Serializable {
* @return modified matrix
* @throws ArrayIndexOutOfBoundsException on bounds error
*/
- @Override
public final Matrix increment(final int i, final int j, final double s) {
elements[i][j] += s;
return this;
@@ -597,22 +585,12 @@ public class Matrix implements MatrixLike<Matrix>, Serializable {
}
/**
- * Returns the <code>i</code>th row of this matrix.
- *
- * @param i the index of the row to be returned
- * @return the <code>i</code>th row of this matrix
- */
- public final Matrix getRow(final int i) {
- return getMatrix(i, i, 0, columndimension - 1);
- }
-
- /**
* Returns the <code>i</code>th row of this matrix as vector.
*
* @param i the index of the row to be returned
* @return the <code>i</code>th row of this matrix
*/
- public final Vector getRowVector(final int i) {
+ public final Vector getRow(final int i) {
double[] row = elements[i].clone();
return new Vector(row);
}
@@ -620,26 +598,10 @@ public class Matrix implements MatrixLike<Matrix>, Serializable {
/**
* Sets the <code>j</code>th row of this matrix to the specified vector.
*
- * @param j the index of the row to be set
- * @param row the value of the row to be set
- */
- public final void setRow(final int j, final Matrix row) {
- if(row.columndimension != columndimension) {
- throw new IllegalArgumentException("Matrix must consist of the same no of columns!");
- }
- if(row.elements.length != 1) {
- throw new IllegalArgumentException("Matrix must consist of one row!");
- }
- setMatrix(elements.length - 1, 0, j, j, row);
- }
-
- /**
- * Sets the <code>j</code>th row of this matrix to the specified vector.
- *
* @param j the index of the column to be set
* @param row the value of the column to be set
*/
- public final void setRowVector(final int j, final Vector row) {
+ public final void setRow(final int j, final Vector row) {
if(row.elements.length != columndimension) {
throw new IllegalArgumentException("Matrix must consist of the same no of columns!");
}
@@ -649,23 +611,12 @@ public class Matrix implements MatrixLike<Matrix>, Serializable {
}
/**
- * Returns the <code>j</code>th column of this matrix.
- *
- * @param j the index of the column to be returned
- * @return the <code>j</code>th column of this matrix
- */
- public final Matrix getColumn(final int j) {
- return getMatrix(0, elements.length - 1, j, j);
- }
-
- /**
* Returns the <code>j</code>th column of this matrix as vector.
*
* @param j the index of the column to be returned
* @return the <code>j</code>th column of this matrix
*/
- @Override
- public final Vector getColumnVector(final int j) {
+ public final Vector getCol(final int j) {
final Vector v = new Vector(elements.length);
for(int i = 0; i < elements.length; i++) {
v.elements[i] = elements[i][j];
@@ -679,23 +630,7 @@ public class Matrix implements MatrixLike<Matrix>, Serializable {
* @param j the index of the column to be set
* @param column the value of the column to be set
*/
- public final void setColumn(final int j, final Matrix column) {
- if(column.elements.length != elements.length) {
- throw new IllegalArgumentException("Matrix must consist of the same no of rows!");
- }
- if(column.columndimension != 1) {
- throw new IllegalArgumentException("Matrix must consist of one column!");
- }
- setMatrix(0, elements.length - 1, j, j, column);
- }
-
- /**
- * Sets the <code>j</code>th column of this matrix to the specified column.
- *
- * @param j the index of the column to be set
- * @param column the value of the column to be set
- */
- public final void setColumnVector(final int j, final Vector column) {
+ public final void setCol(final int j, final Vector column) {
if(column.elements.length != elements.length) {
throw new IllegalArgumentException("Matrix must consist of the same no of rows!");
}
@@ -709,7 +644,6 @@ public class Matrix implements MatrixLike<Matrix>, Serializable {
*
* @return A<sup>T</sup>
*/
- @Override
public final Matrix transpose() {
final Matrix X = new Matrix(columndimension, elements.length);
for(int i = 0; i < elements.length; i++) {
@@ -726,7 +660,6 @@ public class Matrix implements MatrixLike<Matrix>, Serializable {
* @param B another matrix
* @return A + B in a new Matrix
*/
- @Override
public final Matrix plus(final Matrix B) {
return copy().plusEquals(B);
}
@@ -738,7 +671,6 @@ public class Matrix implements MatrixLike<Matrix>, Serializable {
* @param s scalar
* @return A + s * B in a new Matrix
*/
- @Override
public final Matrix plusTimes(final Matrix B, final double s) {
return copy().plusTimesEquals(B, s);
}
@@ -749,7 +681,6 @@ public class Matrix implements MatrixLike<Matrix>, Serializable {
* @param B another matrix
* @return A + B in this Matrix
*/
- @Override
public final Matrix plusEquals(final Matrix B) {
checkMatrixDimensions(B);
for(int i = 0; i < elements.length; i++) {
@@ -767,7 +698,6 @@ public class Matrix implements MatrixLike<Matrix>, Serializable {
* @param s Scalar
* @return A + s * B in this Matrix
*/
- @Override
public final Matrix plusTimesEquals(final Matrix B, final double s) {
checkMatrixDimensions(B);
for(int i = 0; i < elements.length; i++) {
@@ -784,7 +714,6 @@ public class Matrix implements MatrixLike<Matrix>, Serializable {
* @param B another matrix
* @return A - B in a new Matrix
*/
- @Override
public final Matrix minus(final Matrix B) {
return copy().minusEquals(B);
}
@@ -796,7 +725,6 @@ public class Matrix implements MatrixLike<Matrix>, Serializable {
* @param s Scalar
* @return A - s * B in a new Matrix
*/
- @Override
public final Matrix minusTimes(final Matrix B, final double s) {
return copy().minusTimesEquals(B, s);
}
@@ -807,7 +735,6 @@ public class Matrix implements MatrixLike<Matrix>, Serializable {
* @param B another matrix
* @return A - B in this Matrix
*/
- @Override
public final Matrix minusEquals(final Matrix B) {
checkMatrixDimensions(B);
for(int i = 0; i < elements.length; i++) {
@@ -825,7 +752,6 @@ public class Matrix implements MatrixLike<Matrix>, Serializable {
* @param s Scalar
* @return A - s * B in this Matrix
*/
- @Override
public final Matrix minusTimesEquals(final Matrix B, final double s) {
checkMatrixDimensions(B);
for(int i = 0; i < elements.length; i++) {
@@ -842,7 +768,6 @@ public class Matrix implements MatrixLike<Matrix>, Serializable {
* @param s scalar
* @return s*A
*/
- @Override
public final Matrix times(final double s) {
return copy().timesEquals(s);
}
@@ -853,7 +778,6 @@ public class Matrix implements MatrixLike<Matrix>, Serializable {
* @param s scalar
* @return replace A by s*A
*/
- @Override
public final Matrix timesEquals(final double s) {
for(int i = 0; i < elements.length; i++) {
for(int j = 0; j < columndimension; j++) {
@@ -1036,91 +960,6 @@ public class Matrix implements MatrixLike<Matrix>, Serializable {
}
/**
- * Returns the scalar product of the colA column of this and the colB column
- * of B.
- *
- * @param colA The column of A to compute scalar product for
- * @param B second Matrix
- * @param colB The column of B to compute scalar product for
- * @return double The scalar product of the first column of this and B
- */
- public double scalarProduct(int colA, Matrix B, int colB) {
- double scalarProduct = 0.0;
- for(int row = 0; row < getRowDimensionality(); row++) {
- double prod = elements[row][colA] * B.elements[row][colB];
- scalarProduct += prod;
- }
- return scalarProduct;
- }
-
- /**
- * Returns the scalar product of the colA column of this and the colB column
- * of B.
- *
- * @param colA The column of A to compute scalar product for
- * @param B Vector
- * @return double The scalar product of the first column of this and B
- */
- public double scalarProduct(int colA, Vector B) {
- double scalarProduct = 0.0;
- for(int row = 0; row < getRowDimensionality(); row++) {
- double prod = elements[row][colA] * B.elements[row];
- scalarProduct += prod;
- }
- return scalarProduct;
- }
-
- /**
- * LU Decomposition
- *
- * @return LUDecomposition
- * @see LUDecomposition
- */
- public final LUDecomposition lu() {
- return new LUDecomposition(this);
- }
-
- /**
- * QR Decomposition
- *
- * @return QRDecomposition
- * @see QRDecomposition
- */
- public final QRDecomposition qr() {
- return new QRDecomposition(this);
- }
-
- /**
- * Cholesky Decomposition
- *
- * @return CholeskyDecomposition
- * @see CholeskyDecomposition
- */
- public final CholeskyDecomposition chol() {
- return new CholeskyDecomposition(this);
- }
-
- /**
- * Singular Value Decomposition
- *
- * @return SingularValueDecomposition
- * @see SingularValueDecomposition
- */
- public final SingularValueDecomposition svd() {
- return new SingularValueDecomposition(this);
- }
-
- /**
- * Eigenvalue Decomposition
- *
- * @return EigenvalueDecomposition
- * @see EigenvalueDecomposition
- */
- public final EigenvalueDecomposition eig() {
- return new EigenvalueDecomposition(this);
- }
-
- /**
* Solve A*X = B
*
* @param B right hand side
@@ -1131,16 +970,6 @@ public class Matrix implements MatrixLike<Matrix>, Serializable {
}
/**
- * Solve X*A = B, which is also A'*X' = B'
- *
- * @param B right hand side
- * @return solution if A is square, least squares solution otherwise.
- */
- public final Matrix solveTranspose(final Matrix B) {
- return transpose().solve(B.transpose());
- }
-
- /**
* Matrix inverse or pseudoinverse
*
* @return inverse(A) if A is square, pseudoinverse otherwise.
@@ -1194,7 +1023,7 @@ public class Matrix implements MatrixLike<Matrix>, Serializable {
*
* @return maximum column sum.
*/
- public double norm1() {
+ public final double norm1() {
double f = 0;
for(int j = 0; j < columndimension; j++) {
double s = 0;
@@ -1220,7 +1049,7 @@ public class Matrix implements MatrixLike<Matrix>, Serializable {
*
* @return maximum row sum.
*/
- public double normInf() {
+ public final double normInf() {
double f = 0;
for(int i = 0; i < elements.length; i++) {
double s = 0;
@@ -1237,56 +1066,20 @@ public class Matrix implements MatrixLike<Matrix>, Serializable {
*
* @return sqrt of sum of squares of all elements.
*/
- public double normF() {
+ public final double normF() {
double f = 0;
for(int i = 0; i < elements.length; i++) {
for(int j = 0; j < columndimension; j++) {
- f = MathUtil.hypotenuse(f, elements[i][j]);
+ f = MathUtil.fastHypot(f, elements[i][j]);
}
}
return f;
}
/**
- * distanceCov returns distance of two Matrices A and B, i.e. the root of the
- * sum of the squared distances A<sub>ij</sub>-B<sub>ij</sub>.
- *
- * @param B Matrix to compute distance from this (A)
- * @return distance of Matrices
- */
- // TODO: unused - remove / move into a MatrixDistance helper?
- public final double distanceCov(final Matrix B) {
- double distance = 0.0;
- double distIJ;
- int row;
- for(int col = 0; col < columndimension; col++) {
- for(row = 0; row < elements.length; row++) {
- distIJ = elements[row][col] - B.elements[row][col];
- distance += (distIJ * distIJ);
- }
- }
- distance = Math.sqrt(distance);
- return distance;
- }
-
- /**
- * getDiagonal returns array of diagonal-elements.
- *
- * @return double[] the values on the diagonal of the Matrix
- */
- public final double[] getDiagonal() {
- int n = Math.min(columndimension, elements.length);
- final double[] diagonal = new double[n];
- for(int i = 0; i < n; i++) {
- diagonal[i] = elements[i][i];
- }
- return diagonal;
- }
-
- /**
* Normalizes the columns of this matrix to length of 1.0.
*/
- public void normalizeColumns() {
+ public final void normalizeColumns() {
for(int col = 0; col < columndimension; col++) {
double norm = 0.0;
for(int row = 0; row < elements.length; row++) {
@@ -1592,10 +1385,10 @@ public class Matrix implements MatrixLike<Matrix>, Serializable {
for(int i = 0; i < result.columndimension; i++) {
// FIXME: optimize - excess copying!
if(i < columndimension) {
- result.setColumn(i, getColumn(i));
+ result.setCol(i, getCol(i));
}
else {
- result.setColumn(i, columns.getColumn(i - columndimension));
+ result.setCol(i, columns.getCol(i - columndimension));
}
}
return result;
@@ -1607,19 +1400,19 @@ public class Matrix implements MatrixLike<Matrix>, Serializable {
* @return the orthonormalized matrix
*/
public final Matrix orthonormalize() {
- Matrix v = getColumn(0);
+ Matrix v = copy();
// FIXME: optimize - excess copying!
for(int i = 1; i < columndimension; i++) {
- final Matrix u_i = getColumn(i);
- final Matrix sum = new Matrix(elements.length, 1);
+ final Vector u_i = getCol(i);
+ final Vector sum = new Vector(elements.length);
for(int j = 0; j < i; j++) {
- final Matrix v_j = v.getColumn(j);
- double scalar = u_i.scalarProduct(0, v_j, 0) / v_j.scalarProduct(0, v_j, 0);
- sum.plusEquals(v_j.times(scalar));
+ final Vector v_j = v.getCol(j);
+ double scalar = u_i.transposeTimes(v_j) / v_j.transposeTimes(v_j);
+ sum.plusTimesEquals(v_j, scalar);
}
- final Matrix v_i = u_i.minus(sum);
- v = v.appendColumns(v_i);
+ final Vector v_i = u_i.minus(sum);
+ v.setCol(i, v_i);
}
v.normalizeColumns();
@@ -1716,7 +1509,7 @@ public class Matrix implements MatrixLike<Matrix>, Serializable {
/**
* Check if size(A) == size(B)
*/
- protected void checkMatrixDimensions(MatrixLike<?> B) {
+ protected void checkMatrixDimensions(Matrix B) {
if(B.getRowDimensionality() != getRowDimensionality() || B.getColumnDimensionality() != getColumnDimensionality()) {
throw new IllegalArgumentException("Matrix dimensions must agree.");
}
@@ -1807,15 +1600,6 @@ public class Matrix implements MatrixLike<Matrix>, Serializable {
}
/**
- * Returns the dimensionality of this matrix as a string.
- *
- * @return the dimensionality of this matrix as a string
- */
- public String dimensionInfo() {
- return getRowDimensionality() + " x " + getColumnDimensionality();
- }
-
- /**
* toString returns String-representation of Matrix.
*/
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/MatrixLike.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/MatrixLike.java
deleted file mode 100644
index ff1ec5ba..00000000
--- a/src/de/lmu/ifi/dbs/elki/math/linearalgebra/MatrixLike.java
+++ /dev/null
@@ -1,194 +0,0 @@
-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) 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/>.
- */
-
-
-/**
- * Common Interface for Matrix and Vector objects, where M is the actual type.
- *
- * The type M guarantees type safety for many operations.
- *
- * @param M the actual type
- *
- * @apiviz.landmark
- *
- * @author Elke Achtert
- * @author Erich Schubert
- */
-public interface MatrixLike<M extends MatrixLike<M>> extends Cloneable {
- /**
- * Make a deep copy of a matrix.
- *
- * @return a new matrix containing the same values as this matrix
- */
- public M copy();
-
- /**
- * Clone the Matrix object.
- */
- public Object clone();
-
- /**
- * Returns the dimensionality of the rows of this matrix.
- *
- * @return m, the number of rows.
- */
- public int getRowDimensionality();
-
- /**
- * Returns the dimensionality of the columns of this matrix.
- *
- * @return n, the number of columns.
- */
- public int getColumnDimensionality();
-
- /**
- * Get a single element.
- *
- * @param i Row index.
- * @param j Column index.
- * @return A(i,j)
- * @throws ArrayIndexOutOfBoundsException on bounds error
- */
- public double get(int i, int j);
-
- /**
- * Set a single element.
- *
- * @param i Row index.
- * @param j Column index.
- * @param s A(i,j).
- * @throws ArrayIndexOutOfBoundsException on bounds error
- */
- public M set(int i, int j, double s);
-
- /**
- * Increments a single element.
- *
- * @param i the row index
- * @param j the column index
- * @param s the increment value: A(i,j) = A(i.j) + s.
- * @throws ArrayIndexOutOfBoundsException on bounds error
- */
- public M increment(int i, int j, double s);
-
- /**
- * Returns the <code>i</code>th column of this matrix as vector.
- *
- * @param i the index of the column to be returned
- * @return the <code>i</code>th column of this matrix
- */
- public Vector getColumnVector(int i);
-
- /**
- * Matrix transpose.
- *
- * @return A<sup>T</sup>
- */
- public Matrix transpose();
-
- /**
- * C = A + B
- *
- * @param B another matrix
- * @return A + B in a new Matrix
- */
- public M plus(M B);
-
- /**
- * C = A + s*B
- *
- * @param B another matrix
- * @param s scalar
- * @return A + s*B in a new Matrix
- */
- public M plusTimes(M B, double s);
-
- /**
- * A = A + B
- *
- * @param B another matrix
- * @return A + B in this Matrix
- */
- public M plusEquals(M B);
-
- /**
- * C = A + s*B
- *
- * @param B another matrix
- * @param s scalar
- * @return A + s*B in this Matrix
- */
- public M plusTimesEquals(M B, double s);
-
- /**
- * C = A - B
- *
- * @param B another matrix
- * @return A - B in a new Matrix
- */
- public M minus(M B);
-
- /**
- * C = A - s*B
- *
- * @param B another matrix
- * @param s Scalar
- * @return A - s*B in a new Matrix
- */
- public M minusTimes(M B, double s);
-
- /**
- * A = A - B
- *
- * @param B another matrix
- * @return A - B in this Matrix
- */
- public M minusEquals(M B);
-
- /**
- * C = A - s*B
- *
- * @param B another matrix
- * @param s Scalar
- * @return A - s*B in a new Matrix
- */
- public M minusTimesEquals(M B, double s);
-
- /**
- * Multiply a matrix by a scalar, C = s*A
- *
- * @param s scalar
- * @return s*A
- */
- public M times(double s);
-
- /**
- * Multiply a matrix by a scalar in place, A = s*A
- *
- * @param s scalar
- * @return replace A by s*A
- */
- public M timesEquals(double s);
-} \ No newline at end of file
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 e54f75fe..02b5b424 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -43,11 +43,6 @@ import de.lmu.ifi.dbs.elki.utilities.DatabaseUtil;
*/
public class ProjectedCentroid extends Centroid {
/**
- * Serial version
- */
- private static final long serialVersionUID = 1L;
-
- /**
* The selected dimensions.
*/
private BitSet dims;
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 040bd4b1..d8858657 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) 2011
+ Copyright (C) 2012
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 c053de0d..5b52d837 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -74,13 +74,22 @@ public class QRDecomposition implements java.io.Serializable {
* QR Decomposition, computed by Householder reflections.
*
* @param A Rectangular matrix
- *
*/
public QRDecomposition(Matrix A) {
- // Initialize.
- QR = A.getArrayCopy();
- m = A.getRowDimensionality();
- n = A.getColumnDimensionality();
+ this(A.getArrayRef(), A.getRowDimensionality(), A.getColumnDimensionality());
+ }
+
+ /**
+ * QR Decomposition, computed by Householder reflections.
+ *
+ * @param A Rectangular matrix
+ * @param m row dimensionality
+ * @param n column dimensionality
+ */
+ public QRDecomposition(double[][] A, int m, int n) {
+ this.QR = new Matrix(A).getArrayCopy();
+ this.m = QR.length;
+ this.n = QR[0].length;
Rdiag = new double[n];
// Main loop.
@@ -88,7 +97,7 @@ public class QRDecomposition implements java.io.Serializable {
// Compute 2-norm of k-th column without under/overflow.
double nrm = 0;
for(int i = k; i < m; i++) {
- nrm = MathUtil.hypotenuse(nrm, QR[i][k]);
+ nrm = MathUtil.fastHypot(nrm, QR[i][k]);
}
if(nrm != 0.0) {
@@ -227,8 +236,38 @@ public class QRDecomposition implements java.io.Serializable {
// Copy right hand side
int nx = B.getColumnDimensionality();
- double[][] X = B.getArrayCopy();
+ Matrix X = B.copy();
+
+ solveInplace(X.getArrayRef(), nx);
+ return X.getMatrix(0, n - 1, 0, nx - 1);
+ }
+
+ /**
+ * Least squares solution of A*X = B
+ *
+ * @param B A Matrix with as many rows as A and any number of columns.
+ * @return X that minimizes the two norm of Q*R*X-B.
+ * @exception IllegalArgumentException Matrix row dimensions must agree.
+ * @exception RuntimeException Matrix is rank deficient.
+ */
+ public double[][] solve(double[][] B) {
+ int rows = B.length;
+ int cols = B[0].length;
+ if(rows != m) {
+ throw new IllegalArgumentException("Matrix row dimensions must agree.");
+ }
+ if(!this.isFullRank()) {
+ throw new RuntimeException("Matrix is rank deficient.");
+ }
+
+ // Copy right hand side
+ Matrix X = new Matrix(B).copy();
+
+ solveInplace(X.getArrayRef(), cols);
+ return X.getMatrix(0, n - 1, 0, cols - 1).getArrayRef();
+ }
+ private void solveInplace(double[][] X, int nx) {
// Compute Y = transpose(Q)*B
for(int k = 0; k < n; k++) {
for(int j = 0; j < nx; j++) {
@@ -253,6 +292,5 @@ public class QRDecomposition implements java.io.Serializable {
}
}
}
- return (new Matrix(X).getMatrix(0, n - 1, 0, nx - 1));
}
} \ No newline at end of file
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 38d70443..183a8034 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -41,12 +41,7 @@ import de.lmu.ifi.dbs.elki.math.MathUtil;
*
* @apiviz.uses Matrix - - transforms
*/
-@SuppressWarnings("serial")
-public class SingularValueDecomposition implements java.io.Serializable {
- /*
- * ------------------------ Class variables ------------------------
- */
-
+public class SingularValueDecomposition {
/**
* Arrays for internal storage of U and V.
*
@@ -70,23 +65,26 @@ public class SingularValueDecomposition implements java.io.Serializable {
*/
private int m, n;
- /*
- * ------------------------ Constructor ------------------------
- */
-
/**
* Construct the singular value decomposition
*
* @param Arg Rectangular matrix
*/
-
public SingularValueDecomposition(Matrix Arg) {
+ this(Arg.getArrayRef());
+ }
+ /**
+ * Constructor.
+ *
+ * @param Arg Rectangular input matrix
+ */
+ public SingularValueDecomposition(double[][] Arg) {
+ double[][] A = new Matrix(Arg).getArrayCopy();
+ this.m = A.length;
+ this.n = A[0].length;
// Derived from LINPACK code.
// Initialize.
- double[][] A = Arg.getArrayCopy();
- m = Arg.getRowDimensionality();
- n = Arg.getColumnDimensionality();
int nu = Math.min(m, n);
s = new double[Math.min(m + 1, n)];
U = new double[m][nu];
@@ -103,13 +101,12 @@ public class SingularValueDecomposition implements java.io.Serializable {
int nrt = Math.max(0, Math.min(n - 2, m));
for(int k = 0; k < Math.max(nct, nrt); k++) {
if(k < nct) {
-
// Compute the transformation for the k-th column and
// place the k-th diagonal in s[k].
// Compute 2-norm of k-th column without under/overflow.
s[k] = 0;
for(int i = k; i < m; i++) {
- s[k] = MathUtil.hypotenuse(s[k], A[i][k]);
+ s[k] = MathUtil.fastHypot(s[k], A[i][k]);
}
if(s[k] != 0.0) {
if(A[k][k] < 0.0) {
@@ -124,9 +121,7 @@ public class SingularValueDecomposition implements java.io.Serializable {
}
for(int j = k + 1; j < n; j++) {
if((k < nct) & (s[k] != 0.0)) {
-
// Apply the transformation.
-
double t = 0;
for(int i = k; i < m; i++) {
t += A[i][k] * A[i][j];
@@ -143,7 +138,6 @@ public class SingularValueDecomposition implements java.io.Serializable {
e[j] = A[k][j];
}
if(wantu & (k < nct)) {
-
// Place the transformation in U for subsequent back
// multiplication.
@@ -152,13 +146,12 @@ public class SingularValueDecomposition implements java.io.Serializable {
}
}
if(k < nrt) {
-
// Compute the k-th row transformation and place the
// k-th super-diagonal in e[k].
// Compute 2-norm without under/overflow.
e[k] = 0;
for(int i = k + 1; i < n; i++) {
- e[k] = MathUtil.hypotenuse(e[k], e[i]);
+ e[k] = MathUtil.fastHypot(e[k], e[i]);
}
if(e[k] != 0.0) {
if(e[k + 1] < 0.0) {
@@ -171,9 +164,7 @@ public class SingularValueDecomposition implements java.io.Serializable {
}
e[k] = -e[k];
if((k + 1 < m) & (e[k] != 0.0)) {
-
// Apply the transformation.
-
for(int i = k + 1; i < m; i++) {
work[i] = 0.0;
}
@@ -190,10 +181,8 @@ public class SingularValueDecomposition implements java.io.Serializable {
}
}
if(wantv) {
-
// Place the transformation in V for subsequent
// back multiplication.
-
for(int i = k + 1; i < n; i++) {
V[i][k] = e[i];
}
@@ -254,7 +243,6 @@ public class SingularValueDecomposition implements java.io.Serializable {
}
// If required, generate V.
-
if(wantv) {
for(int k = n - 1; k >= 0; k--) {
if((k < nrt) & (e[k] != 0.0)) {
@@ -336,14 +324,13 @@ public class SingularValueDecomposition implements java.io.Serializable {
// Perform the task indicated by kase.
switch(kase){
-
+
// Deflate negligible s(p).
-
case 1: {
double f = e[p - 2];
e[p - 2] = 0.0;
for(int j = p - 2; j >= k; j--) {
- double t = MathUtil.hypotenuse(s[j], f);
+ double t = MathUtil.fastHypot(s[j], f);
double cs = s[j] / t;
double sn = f / t;
s[j] = t;
@@ -363,12 +350,11 @@ public class SingularValueDecomposition implements java.io.Serializable {
break;
// Split at negligible s(k).
-
case 2: {
double f = e[k - 1];
e[k - 1] = 0.0;
for(int j = k; j < p; j++) {
- double t = MathUtil.hypotenuse(s[j], f);
+ double t = MathUtil.fastHypot(s[j], f);
double cs = s[j] / t;
double sn = f / t;
s[j] = t;
@@ -386,11 +372,8 @@ public class SingularValueDecomposition implements java.io.Serializable {
break;
// Perform one qr step.
-
case 3: {
-
// Calculate the shift.
-
double scale = Math.max(Math.max(Math.max(Math.max(Math.abs(s[p - 1]), Math.abs(s[p - 2])), Math.abs(e[p - 2])), Math.abs(s[k])), Math.abs(e[k]));
double sp = s[p - 1] / scale;
double spm1 = s[p - 2] / scale;
@@ -411,9 +394,8 @@ public class SingularValueDecomposition implements java.io.Serializable {
double g = sk * ek;
// Chase zeros.
-
for(int j = k; j < p - 1; j++) {
- double t = MathUtil.hypotenuse(f, g);
+ double t = MathUtil.fastHypot(f, g);
double cs = f / t;
double sn = g / t;
if(j != k) {
@@ -430,7 +412,7 @@ public class SingularValueDecomposition implements java.io.Serializable {
V[i][j] = t;
}
}
- t = MathUtil.hypotenuse(f, g);
+ t = MathUtil.fastHypot(f, g);
cs = f / t;
sn = g / t;
s[j] = t;
@@ -452,11 +434,8 @@ public class SingularValueDecomposition implements java.io.Serializable {
break;
// Convergence.
-
case 4: {
-
// Make the singular values positive.
-
if(s[k] <= 0.0) {
s[k] = (s[k] < 0.0 ? -s[k] : 0.0);
if(wantv) {
@@ -467,7 +446,6 @@ public class SingularValueDecomposition implements java.io.Serializable {
}
// Order the singular values.
-
while(k < pp) {
if(s[k] >= s[k + 1]) {
break;
@@ -499,16 +477,11 @@ public class SingularValueDecomposition implements java.io.Serializable {
}
}
- /*
- * ------------------------ Public Methods ------------------------
- */
-
/**
* Return the left singular vectors
*
* @return U
*/
-
public Matrix getU() {
return new Matrix(U);
}
@@ -518,7 +491,6 @@ public class SingularValueDecomposition implements java.io.Serializable {
*
* @return V
*/
-
public Matrix getV() {
return new Matrix(V);
}
@@ -528,7 +500,6 @@ public class SingularValueDecomposition implements java.io.Serializable {
*
* @return diagonal of S.
*/
-
public double[] getSingularValues() {
return s;
}
@@ -538,7 +509,6 @@ public class SingularValueDecomposition implements java.io.Serializable {
*
* @return S
*/
-
public Matrix getS() {
Matrix X = new Matrix(n, n);
double[][] S = X.getArrayRef();
@@ -556,7 +526,6 @@ public class SingularValueDecomposition implements java.io.Serializable {
*
* @return max(S)
*/
-
public double norm2() {
return s[0];
}
@@ -566,7 +535,6 @@ public class SingularValueDecomposition implements java.io.Serializable {
*
* @return max(S)/min(S)
*/
-
public double cond() {
return s[0] / s[Math.min(m, n) - 1];
}
@@ -576,7 +544,6 @@ public class SingularValueDecomposition implements java.io.Serializable {
*
* @return Number of nonnegligible singular values.
*/
-
public int rank() {
double eps = Math.pow(2.0, -52.0);
double tol = Math.max(m, n) * s[0] * eps;
@@ -588,4 +555,4 @@ public class SingularValueDecomposition implements java.io.Serializable {
}
return r;
}
-}
+} \ No newline at end of file
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 b0264c35..5fa023ca 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -65,7 +65,7 @@ public class SortedEigenPairs {
this.eigenPairs = new EigenPair[eigenvalues.length];
for(int i = 0; i < eigenvalues.length; i++) {
double e = java.lang.Math.abs(eigenvalues[i]);
- Vector v = eigenvectors.getColumnVector(i);
+ Vector v = eigenvectors.getCol(i);
eigenPairs[i] = new EigenPair(v, e);
}
@@ -124,7 +124,7 @@ public class SortedEigenPairs {
Matrix eigenVectors = new Matrix(eigenPairs.length, eigenPairs.length);
for(int i = 0; i < eigenPairs.length; i++) {
EigenPair eigenPair = eigenPairs[i];
- eigenVectors.setColumnVector(i, eigenPair.getEigenvector());
+ eigenVectors.setCol(i, eigenPair.getEigenvector());
}
return eigenVectors;
}
@@ -139,7 +139,7 @@ public class SortedEigenPairs {
Matrix eigenVectors = new Matrix(eigenPairs.length, n);
for(int i = 0; i < n; i++) {
EigenPair eigenPair = eigenPairs[i];
- eigenVectors.setColumnVector(i, eigenPair.getEigenvector());
+ eigenVectors.setCol(i, eigenPair.getEigenvector());
}
return eigenVectors;
}
@@ -154,7 +154,7 @@ public class SortedEigenPairs {
Matrix eigenVectors = new Matrix(eigenPairs.length, n);
for(int i = 0; i < n; i++) {
EigenPair eigenPair = eigenPairs[eigenPairs.length - 1 - i];
- eigenVectors.setColumnVector(i, eigenPair.getEigenvector());
+ eigenVectors.setCol(i, eigenPair.getEigenvector());
}
return eigenVectors;
}
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 3e8815e3..3cab3b51 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) 2011
+ Copyright (C) 2012
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
new file mode 100644
index 00000000..97466b20
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/VMath.java
@@ -0,0 +1,1512 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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;
+
+/**
+ * Class providing basic vector mathematics, for low-level vectors stored as
+ * {@code double[]}. While this is less nice syntactically, it reduces memory
+ * usage and VM overhead.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.landmark
+ */
+public final class VMath {
+ /**
+ * A small number to handle numbers near 0 as 0.
+ */
+ public static final double DELTA = 1E-5;
+
+ /**
+ * Fake constructor. Static class.
+ */
+ private VMath() {
+ // Cannot be instantiated
+ }
+
+ /**
+ * Returns a randomly created vector of length 1.0
+ *
+ * @param dimensionality dimensionality
+ * @return Random vector of length 1.0
+ */
+ public final static double[] randomNormalizedVector(final int dimensionality) {
+ final double[] v = new double[dimensionality];
+ for(int i = 0; i < dimensionality; i++) {
+ v[i] = Math.random();
+ }
+ double norm = euclideanLength(v);
+ if(norm != 0) {
+ for(int row = 0; row < v.length; row++) {
+ v[row] /= norm;
+ }
+ return v;
+ }
+ else {
+ return randomNormalizedVector(dimensionality);
+ }
+ }
+
+ /**
+ * Returns the ith unit vector of the specified dimensionality.
+ *
+ * @param dimensionality the dimensionality of the vector
+ * @param i the index
+ * @return the ith unit vector of the specified dimensionality
+ */
+ public final static double[] unitVector(final int dimensionality, final int i) {
+ final double[] v = new double[dimensionality];
+ v[i] = 1;
+ return v;
+ }
+
+ /**
+ * Returns a copy of this vector.
+ *
+ * @param v original vector
+ * @return a copy of this vector
+ */
+ public final static double[] copy(final double[] v) {
+ return Arrays.copyOf(v, v.length);
+ }
+
+ /**
+ * Transpose vector to a matrix.
+ *
+ * @param v Vector
+ * @return Matrix
+ */
+ public final static double[][] transpose(final double[] v) {
+ double[][] re = new double[v.length][1];
+ for(int i = 0; i < v.length; i++) {
+ re[i][0] = v[i];
+ }
+ return re;
+ }
+
+ /**
+ * Computes v1 + v2 for vectors.
+ *
+ * @param v1 first vector
+ * @param v2 second vector
+ * @return the sum v1 + v2
+ */
+ public final static double[] plus(final double[] v1, final double[] v2) {
+ assert (v1.length == v2.length) : "Vector dimensions must agree.";
+ final double[] result = new double[v1.length];
+ for(int i = 0; i < result.length; i++) {
+ result[i] = v1[i] + v2[i];
+ }
+ return result;
+ }
+
+ /**
+ * Computes v1 + v2 * s2
+ *
+ * @param v1 first vector
+ * @param v2 second vector
+ * @param s2 the scalar
+ * @return the result of v1 + v2 * s2
+ */
+ public final static double[] plusTimes(final double[] v1, final double[] v2, final double s2) {
+ assert (v1.length == v2.length) : "Vector dimensions must agree.";
+ final double[] result = new double[v1.length];
+ for(int i = 0; i < result.length; i++) {
+ result[i] = v1[i] + v2[i] * s2;
+ }
+ return result;
+ }
+
+ /**
+ * Computes v1 * s1 + v2
+ *
+ * @param v1 first vector
+ * @param s1 the scalar for v1
+ * @param v2 second vector
+ * @return the result of v1 * s1 + v2
+ */
+ public final static double[] timesPlus(final double[] v1, final double s1, final double[] v2) {
+ assert (v1.length == v2.length) : "Vector dimensions must agree.";
+ final double[] result = new double[v1.length];
+ for(int i = 0; i < result.length; i++) {
+ result[i] = v1[i] * s1 + v2[i];
+ }
+ return result;
+ }
+
+ /**
+ * Computes v1 * s1 + v2 * s2
+ *
+ * @param v1 first vector
+ * @param s1 the scalar for v1
+ * @param v2 second vector
+ * @param s2 the scalar for v2
+ * @return the result of v1 * s1 + v2 * s2
+ */
+ public final static double[] timesPlusTimes(final double[] v1, final double s1, final double[] v2, final double s2) {
+ assert (v1.length == v2.length) : "Vector dimensions must agree.";
+ final double[] result = new double[v1.length];
+ for(int i = 0; i < result.length; i++) {
+ result[i] = v1[i] * s1 + v2[i] * s2;
+ }
+ return result;
+ }
+
+ /**
+ * Computes v1 = v1 + v2, overwriting v1
+ *
+ * @param v1 first vector (overwritten)
+ * @param v2 second vector
+ * @return v1 = v1 + v2
+ */
+ public final static double[] plusEquals(final double[] v1, final double[] v2) {
+ assert (v1.length == v2.length) : "Vector dimensions must agree.";
+ for(int i = 0; i < v1.length; i++) {
+ v1[i] += v2[i];
+ }
+ return v1;
+ }
+
+ /**
+ * Computes v1 = v1 + v2 * s2, overwriting v1
+ *
+ * @param v1 first vector
+ * @param v2 another vector
+ * @param s2 scalar vor v2
+ * @return v1 = v1 + v2 * s2
+ */
+ public final static double[] plusTimesEquals(final double[] v1, final double[] v2, final double s2) {
+ assert (v1.length == v2.length) : "Vector dimensions must agree.";
+ for(int i = 0; i < v1.length; i++) {
+ v1[i] += s2 * v2[i];
+ }
+ return v1;
+ }
+
+ /**
+ * Computes v1 = v1 * s1 + v2, overwriting v1
+ *
+ * @param v1 first vector
+ * @param s1 scalar for v1
+ * @param v2 another vector
+ * @return v1 = v1 * s1 + v2
+ */
+ public final static double[] timesPlusEquals(final double[] v1, final double s1, final double[] v2) {
+ assert (v1.length == v2.length) : "Vector dimensions must agree.";
+ for(int i = 0; i < v1.length; i++) {
+ v1[i] = v1[i] * s1 + v2[i];
+ }
+ return v1;
+ }
+
+ /**
+ * Computes v1 = v1 * s1 + v2 * s2, overwriting v1
+ *
+ * @param v1 first vector
+ * @param s1 scalar for v1
+ * @param v2 another vector
+ * @param s2 scalar for v2
+ * @return v1 = v1 * s1 + v2 * s2
+ */
+ public final static double[] timesPlusTimesEquals(final double[] v1, final double s1, final double[] v2, final double s2) {
+ assert (v1.length == v2.length) : "Vector dimensions must agree.";
+ for(int i = 0; i < v1.length; i++) {
+ v1[i] = v1[i] * s1 + v2[i] * s2;
+ }
+ return v1;
+ }
+
+ /**
+ * Computes v1 + d
+ *
+ * @param v1 vector to add to
+ * @param d value to add
+ * @return v1 + d
+ */
+ public final static double[] plus(final double[] v1, final double d) {
+ final double[] result = new double[v1.length];
+ for(int i = 0; i < result.length; i++) {
+ result[i] = v1[i] + d;
+ }
+ return result;
+ }
+
+ /**
+ * Computes v1 = v1 + d, overwriting v1
+ *
+ * @param v1 vector to add to
+ * @param d value to add
+ * @return Modified vector
+ */
+ public final static double[] plusEquals(final double[] v1, final double d) {
+ for(int i = 0; i < v1.length; i++) {
+ v1[i] += d;
+ }
+ return v1;
+ }
+
+ /**
+ * Computes v1 - v2
+ *
+ * @param v1 first vector
+ * @param v2 the vector to be subtracted from this vector
+ * @return v1 - v2
+ */
+ public final static double[] minus(final double[] v1, final double[] v2) {
+ final double[] sub = new double[v1.length];
+ for(int i = 0; i < v1.length; i++) {
+ sub[i] = v1[i] - v2[i];
+ }
+ return sub;
+ }
+
+ /**
+ * Computes v1 - v2 * s2
+ *
+ * @param v1 first vector
+ * @param v2 the vector to be subtracted from this vector
+ * @param s2 the scaling factor for v2
+ * @return v1 - v2 * s2
+ */
+ public final static double[] minusTimes(final double[] v1, final double[] v2, final double s2) {
+ final double[] sub = new double[v1.length];
+ for(int i = 0; i < v1.length; i++) {
+ sub[i] = v1[i] - v2[i] * s2;
+ }
+ return sub;
+ }
+
+ /**
+ * Computes v1 * s1 - v2
+ *
+ * @param v1 first vector
+ * @param s1 the scaling factor for v1
+ * @param v2 the vector to be subtracted from this vector
+ * @return v1 * s1 - v2
+ */
+ public final static double[] timesMinus(final double[] v1, final double s1, final double[] v2) {
+ final double[] sub = new double[v1.length];
+ for(int i = 0; i < v1.length; i++) {
+ sub[i] = v1[i] * s1 - v2[i];
+ }
+ return sub;
+ }
+
+ /**
+ * Computes v1 * s1 - v2 * s2
+ *
+ * @param v1 first vector
+ * @param s1 the scaling factor for v1
+ * @param v2 the vector to be subtracted from this vector
+ * @param s2 the scaling factor for v2
+ * @return v1 * s1 - v2 * s2
+ */
+ public final static double[] timesMinusTimes(final double[] v1, final double s1, final double[] v2, final double s2) {
+ final double[] sub = new double[v1.length];
+ for(int i = 0; i < v1.length; i++) {
+ sub[i] = v1[i] * s1 - v2[i] * s2;
+ }
+ return sub;
+ }
+
+ /**
+ * Computes v1 = v1 - v2, overwriting v1
+ *
+ * @param v1 vector
+ * @param v2 another vector
+ * @return v1 = v1 - v2
+ */
+ public final static double[] minusEquals(final double[] v1, final double[] v2) {
+ assert (v1.length == v2.length) : "Vector dimensions must agree.";
+ for(int i = 0; i < v1.length; i++) {
+ v1[i] -= v2[i];
+ }
+ return v1;
+ }
+
+ /**
+ * Computes v1 = v1 - v2 * s2, overwriting v1
+ *
+ * @param v1 vector
+ * @param v2 another vector
+ * @param s2 scalar for v2
+ * @return v1 = v1 - v2 * s2
+ */
+ public final static double[] minusTimesEquals(final double[] v1, final double[] v2, final double s2) {
+ assert (v1.length == v2.length) : "Vector dimensions must agree.";
+ for(int i = 0; i < v1.length; i++) {
+ v1[i] -= v2[i] * s2;
+ }
+ return v1;
+ }
+
+ /**
+ * Computes v1 = v1 * s1 - v2, overwriting v1
+ *
+ * @param v1 vector
+ * @param s1 scalar for v1
+ * @param v2 another vector
+ * @return v1 = v1 * s1 - v2
+ */
+ public final static double[] timesMinusEquals(final double[] v1, final double s1, final double[] v2) {
+ assert (v1.length == v2.length) : "Vector dimensions must agree.";
+ for(int i = 0; i < v1.length; i++) {
+ v1[i] = v1[i] * s1 - v2[i];
+ }
+ return v1;
+ }
+
+ /**
+ * Computes v1 = v1 * s1 - v2 * s2, overwriting v1
+ *
+ * @param v1 vector
+ * @param s1 scalar for v1
+ * @param v2 another vector
+ * @param s2 Scalar
+ * @return v1 = v1 * s1 - v2 * s2
+ */
+ public final static double[] timesMinusTimesEquals(final double[] v1, final double s1, final double[] v2, final double s2) {
+ assert (v1.length == v2.length) : "Vector dimensions must agree.";
+ for(int i = 0; i < v1.length; i++) {
+ v1[i] = v1[i] * s1 - v2[i] * s2;
+ }
+ return v1;
+ }
+
+ /**
+ * Compute v1 - d
+ *
+ * @param v1 original vector
+ * @param d Value to subtract
+ * @return v1 - d
+ */
+ public final static double[] minus(final double[] v1, final double d) {
+ final double[] result = new double[v1.length];
+ for(int i = 0; i < v1.length; i++) {
+ result[i] = v1[i] - d;
+ }
+ return result;
+ }
+
+ /**
+ * Computes v1 = v1 - d, overwriting v1
+ *
+ * @param v1 original vector
+ * @param d Value to subtract
+ * @return v1 = v1 - d
+ */
+ public final static double[] minusEquals(final double[] v1, final double d) {
+ for(int i = 0; i < v1.length; i++) {
+ v1[i] -= d;
+ }
+ return v1;
+ }
+
+ /**
+ * Computes v1 * s1
+ *
+ * @param v1 original vector
+ * @param s1 the scalar to be multiplied
+ * @return v1 * s1
+ */
+ public final static double[] times(final double[] v1, final double s1) {
+ final double[] v = new double[v1.length];
+ for(int i = 0; i < v1.length; i++) {
+ v[i] = v1[i] * s1;
+ }
+ return v;
+ }
+
+ /**
+ * Computes v1 = v1 * s1, overwritings v1
+ *
+ * @param v1 original vector
+ * @param s scalar
+ * @return v1 = v1 * s1
+ */
+ public final static double[] timesEquals(final double[] v1, final double s) {
+ for(int i = 0; i < v1.length; i++) {
+ v1[i] *= s;
+ }
+ return v1;
+ }
+
+ /**
+ * Matrix multiplication: v1 * m2
+ *
+ * @param v1 vector
+ * @param m2 other matrix
+ * @return Matrix product, v1 * m2
+ */
+ public final static double[][] times(final double[] v1, final double[][] m2) {
+ assert (m2.length == 1) : "Matrix inner dimensions must agree.";
+ final int columndimension = m2[0].length;
+ final double[][] re = new double[v1.length][columndimension];
+ for(int j = 0; j < columndimension; j++) {
+ for(int i = 0; i < v1.length; i++) {
+ re[i][j] = v1[i] * m2[0][j];
+ }
+ }
+ return re;
+ }
+
+ /**
+ * Linear algebraic matrix multiplication, v1<sup>T</sup> * m2
+ *
+ * @param v1 vector
+ * @param m2 other matrix
+ * @return Matrix product, v1<sup>T</sup> * m2
+ */
+ public final static double[][] transposeTimes(final double[] v1, final double[][] m2) {
+ assert (m2.length == v1.length) : "Matrix inner dimensions must agree.";
+ final int columndimension = m2[0].length;
+ final double[][] re = new double[1][columndimension];
+ for(int j = 0; j < columndimension; j++) {
+ double s = 0;
+ for(int k = 0; k < v1.length; k++) {
+ s += v1[k] * m2[k][j];
+ }
+ re[0][j] = s;
+ }
+ return re;
+ }
+
+ /**
+ * Linear algebraic matrix multiplication, v1<sup>T</sup> * v2
+ *
+ * @param v1 vector
+ * @param v2 other vector
+ * @return Matrix product, v1<sup>T</sup> * v2
+ */
+ public final static double transposeTimes(final double[] v1, final double[] v2) {
+ assert (v2.length == v1.length) : "Matrix inner dimensions must agree.";
+ double s = 0;
+ for(int k = 0; k < v1.length; k++) {
+ s += v1[k] * v2[k];
+ }
+ return s;
+ }
+
+ /**
+ * Linear algebraic matrix multiplication, v1 * m2^T
+ *
+ * @param v1 vector
+ * @param m2 other matrix
+ * @return Matrix product, v1 * m2^T
+ */
+ public final static double[][] timesTranspose(final double[] v1, final double[][] m2) {
+ assert (m2[0].length == 1) : "Matrix inner dimensions must agree.";
+
+ final double[][] re = new double[v1.length][m2.length];
+ for(int j = 0; j < m2.length; j++) {
+ for(int i = 0; i < v1.length; i++) {
+ re[i][j] = v1[i] * m2[j][0];
+ }
+ }
+ return re;
+ }
+
+ /**
+ * Linear algebraic matrix multiplication, v1 * v2^T
+ *
+ * @param v1 vector
+ * @param v2 other vector
+ * @return Matrix product, v1 * v2^T
+ */
+ public final static double[][] timesTranspose(final double[] v1, final double[] v2) {
+ final double[][] re = new double[v1.length][v2.length];
+ for(int j = 0; j < v2.length; j++) {
+ for(int i = 0; i < v1.length; i++) {
+ re[i][j] = v1[i] * v2[j];
+ }
+ }
+ return re;
+ }
+
+ /**
+ * Returns the scalar product of this vector and the specified vector v.
+ *
+ * This is the same as transposeTimes.
+ *
+ * @param v1 vector
+ * @param v2 other vector
+ * @return double the scalar product of vectors v1 and v2
+ */
+ public final static double scalarProduct(final double[] v1, final double[] v2) {
+ assert (v1.length == v2.length) : "Vector dimensions must agree.";
+ double scalarProduct = 0.0;
+ for(int row = 0; row < v1.length; row++) {
+ scalarProduct += v1[row] * v2[row];
+ }
+ return scalarProduct;
+ }
+
+ /**
+ * Euclidean length of the vector
+ *
+ * @param v1 vector
+ * @return euclidean length of this vector
+ */
+ public final static double euclideanLength(final double[] v1) {
+ double acc = 0.0;
+ for(int row = 0; row < v1.length; row++) {
+ final double v = v1[row];
+ acc += v * v;
+ }
+ return Math.sqrt(acc);
+ }
+
+ /**
+ * Normalizes v1 to the length of 1.0.
+ *
+ * @param v1 vector
+ * @return normalized copy of v1
+ */
+ public final static double[] normalize(final double[] v1) {
+ double norm = euclideanLength(v1);
+ double[] re = new double[v1.length];
+ if(norm != 0) {
+ for(int row = 0; row < v1.length; row++) {
+ re[row] = v1[row] / norm;
+ }
+ }
+ return re;
+ }
+
+ /**
+ * Normalizes v1 to the length of 1.0.
+ *
+ * @param v1 vector
+ * @return normalized v1
+ */
+ public final static double[] normalizeEquals(final double[] v1) {
+ double norm = euclideanLength(v1);
+ if(norm != 0) {
+ for(int row = 0; row < v1.length; row++) {
+ v1[row] /= norm;
+ }
+ }
+ return v1;
+ }
+
+ /**
+ * Projects this row vector into the subspace formed by the specified matrix
+ * v.
+ *
+ * @param m2 the subspace matrix
+ * @return the projection of p into the subspace formed by v
+ */
+ public final static double[] project(final double[] v1, final double[][] m2) {
+ assert (v1.length == m2.length) : "v1 and m2 differ in dimensionality!";
+ final int columndimension = m2[0].length;
+
+ double[] sum = new double[v1.length];
+ for(int i = 0; i < columndimension; i++) {
+ // TODO: optimize - copy less.
+ double[] v_i = getCol(m2, i);
+ plusTimesEquals(sum, v_i, scalarProduct(v1, v_i));
+ }
+ return sum;
+ }
+
+ /**
+ * Compute the hash code for the vector
+ *
+ * @param v1 elements
+ * @return hash code
+ */
+ public final static int hashCode(final double[] v1) {
+ return Arrays.hashCode(v1);
+ }
+
+ /**
+ * Compare for equality.
+ *
+ * @param v1 first vector
+ * @param v2 second vector
+ * @return comparison result
+ */
+ public final static boolean equals(final double[] v1, final double[] v2) {
+ return Arrays.equals(v1, v2);
+ }
+
+ /**
+ * Reset the Vector to 0.
+ *
+ * @param v1 vector
+ */
+ public final static void clear(final double[] v1) {
+ Arrays.fill(v1, 0.0);
+ }
+
+ /**
+ * Rotate vector by 90 degrees.
+ *
+ * @param v1 first vector
+ * @return modified v1, rotated by 90 degrees
+ */
+ public final static double[] rotate90Equals(final double[] v1) {
+ assert (v1.length == 2) : "rotate90Equals is only valid for 2d vectors.";
+ double temp = v1[0];
+ v1[0] = v1[1];
+ v1[1] = -temp;
+ return v1;
+ }
+
+ // *********** MATRIX operations
+
+ /**
+ * Returns the unit matrix of the specified dimension.
+ *
+ * @param dim the dimensionality of the unit matrix
+ * @return the unit matrix of the specified dimension
+ */
+ public final static double[][] unitMatrix(final int dim) {
+ final double[][] e = new double[dim][dim];
+ for(int i = 0; i < dim; i++) {
+ e[i][i] = 1;
+ }
+ return e;
+ }
+
+ /**
+ * Returns the zero matrix of the specified dimension.
+ *
+ * @param dim the dimensionality of the unit matrix
+ * @return the zero matrix of the specified dimension
+ */
+ public final static double[][] zeroMatrix(final int dim) {
+ final double[][] z = new double[dim][dim];
+ return z;
+ }
+
+ /**
+ * Generate matrix with random elements
+ *
+ * @param m Number of rows.
+ * @param n Number of columns.
+ * @return An m-by-n matrix with uniformly distributed random elements.
+ */
+ public final static double[][] random(final int m, final int n) {
+ final double[][] A = new double[m][n];
+ for(int i = 0; i < m; i++) {
+ for(int j = 0; j < n; j++) {
+ A[i][j] = Math.random();
+ }
+ }
+ return A;
+ }
+
+ /**
+ * Generate identity matrix
+ *
+ * @param m Number of rows.
+ * @param n Number of columns.
+ * @return An m-by-n matrix with ones on the diagonal and zeros elsewhere.
+ */
+ public final static double[][] identity(final int m, final int n) {
+ final double[][] A = new double[m][n];
+ for(int i = 0; i < Math.min(m, n); i++) {
+ A[i][i] = 1.0;
+ }
+ return A;
+ }
+
+ /**
+ * Returns a quadratic Matrix consisting of zeros and of the given values on
+ * the diagonal.
+ *
+ * @param v1 the values on the diagonal
+ * @return the resulting matrix
+ */
+ public final static double[][] diagonal(final double[] v1) {
+ final double[][] result = new double[v1.length][v1.length];
+ for(int i = 0; i < v1.length; i++) {
+ result[i][i] = v1[i];
+ }
+ return result;
+ }
+
+ /**
+ * Make a deep copy of a matrix.
+ *
+ * @param m1 Input matrix
+ * @return a new matrix containing the same values as this matrix
+ */
+ public static final double[][] copy(final double[][] m1) {
+ final int columndimension = m1[0].length;
+ final double[][] X = new double[m1.length][columndimension];
+ for(int i = 0; i < m1.length; i++) {
+ System.arraycopy(m1[i], 0, X[i], 0, columndimension);
+ }
+ return X;
+ }
+
+ /**
+ * Make a one-dimensional row packed copy of the internal array.
+ *
+ * @param m1 Input matrix
+ * @return Matrix elements packed in a one-dimensional array by rows.
+ */
+ public static final double[] rowPackedCopy(final double[][] m1) {
+ final int columndimension = m1[0].length;
+ double[] vals = new double[m1.length * columndimension];
+ for(int i = 0; i < m1.length; i++) {
+ for(int j = 0; j < columndimension; j++) {
+ vals[i * columndimension + j] = m1[i][j];
+ }
+ }
+ return vals;
+ }
+
+ /**
+ * Make a one-dimensional column packed copy of the internal array.
+ *
+ * @param m1 Input matrix
+ * @return Matrix elements packed in a one-dimensional array by columns.
+ */
+ public static final double[] columnPackedCopy(final double[][] m1) {
+ final int columndimension = m1[0].length;
+ final double[] vals = new double[m1.length * columndimension];
+ for(int i = 0; i < m1.length; i++) {
+ for(int j = 0; j < columndimension; j++) {
+ vals[i + j * m1.length] = m1[i][j];
+ }
+ }
+ return vals;
+ }
+
+ /**
+ * Get a submatrix.
+ *
+ * @param m1 Input matrix
+ * @param r0 Initial row index
+ * @param r1 Final row index
+ * @param c0 Initial column index
+ * @param c1 Final column index
+ * @return m1(r0:r1,c0:c1)
+ */
+ public static final double[][] getMatrix(final double[][] m1, final int r0, final int r1, final int c0, final int c1) {
+ final double[][] X = new double[r1 - r0 + 1][c1 - c0 + 1];
+ for(int i = r0; i <= r1; i++) {
+ for(int j = c0; j <= c1; j++) {
+ X[i - r0][j - c0] = m1[i][j];
+ }
+ }
+ return X;
+ }
+
+ /**
+ * Get a submatrix.
+ *
+ * @param m1 Input matrix
+ * @param r Array of row indices.
+ * @param c Array of column indices.
+ * @return m1(r(:),c(:))
+ */
+ public static final double[][] getMatrix(final double[][] m1, final int[] r, final int[] c) {
+ final double[][] X = new double[r.length][c.length];
+ for(int i = 0; i < r.length; i++) {
+ for(int j = 0; j < c.length; j++) {
+ X[i][j] = m1[r[i]][c[j]];
+ }
+ }
+ return X;
+ }
+
+ /**
+ * Get a submatrix.
+ *
+ * @param m1 Input matrix
+ * @param r Array of row indices.
+ * @param c0 Initial column index
+ * @param c1 Final column index
+ * @return m1(r(:),c0:c1)
+ */
+ public static final double[][] getMatrix(final double[][] m1, final int[] r, final int c0, final int c1) {
+ final double[][] X = new double[r.length][c1 - c0 + 1];
+ for(int i = 0; i < r.length; i++) {
+ for(int j = c0; j <= c1; j++) {
+ X[i][j - c0] = m1[r[i]][j];
+ }
+ }
+ return X;
+ }
+
+ /**
+ * Get a submatrix.
+ *
+ * @param m1 Input matrix
+ * @param r0 Initial row index
+ * @param r1 Final row index
+ * @param c Array of column indices.
+ * @return m1(r0:r1,c(:))
+ */
+ public static final double[][] getMatrix(final double[][] m1, final int r0, final int r1, final int[] c) {
+ final double[][] X = new double[r1 - r0 + 1][c.length];
+ for(int i = r0; i <= r1; i++) {
+ for(int j = 0; j < c.length; j++) {
+ X[i - r0][j] = m1[i][c[j]];
+ }
+ }
+ return X;
+ }
+
+ /**
+ * Set a submatrix.
+ *
+ * @param m1 Original matrix
+ * @param r0 Initial row index
+ * @param r1 Final row index
+ * @param c0 Initial column index
+ * @param c1 Final column index
+ * @param m2 New values for m1(r0:r1,c0:c1)
+ */
+ public static final void setMatrix(final double[][] m1, final int r0, final int r1, final int c0, final int c1, final double[][] m2) {
+ for(int i = r0; i <= r1; i++) {
+ for(int j = c0; j <= c1; j++) {
+ m1[i][j] = m2[i - r0][j - c0];
+ }
+ }
+ }
+
+ /**
+ * Set a submatrix.
+ *
+ * @param m1 Original matrix
+ * @param r Array of row indices.
+ * @param c Array of column indices.
+ * @param m2 New values for m1(r(:),c(:))
+ */
+ public static final void setMatrix(final double[][] m1, final int[] r, final int[] c, final double[][] m2) {
+ for(int i = 0; i < r.length; i++) {
+ for(int j = 0; j < c.length; j++) {
+ m1[r[i]][c[j]] = m2[i][j];
+ }
+ }
+ }
+
+ /**
+ * Set a submatrix.
+ *
+ * @param m1 Input matrix
+ * @param r Array of row indices.
+ * @param c0 Initial column index
+ * @param c1 Final column index
+ * @param m2 New values for m1(r(:),c0:c1)
+ */
+ public static final void setMatrix(final double[][] m1, final int[] r, final int c0, final int c1, final double[][] m2) {
+ for(int i = 0; i < r.length; i++) {
+ for(int j = c0; j <= c1; j++) {
+ m1[r[i]][j] = m2[i][j - c0];
+ }
+ }
+ }
+
+ /**
+ * Set a submatrix.
+ *
+ * @param m1 Input matrix
+ * @param r0 Initial row index
+ * @param r1 Final row index
+ * @param c Array of column indices.
+ * @param m2 New values for m1(r0:r1,c(:))
+ */
+ public static final void setMatrix(final double[][] m1, final int r0, final int r1, final int[] c, final double[][] m2) {
+ for(int i = r0; i <= r1; i++) {
+ for(int j = 0; j < c.length; j++) {
+ m1[i][c[j]] = m2[i - r0][j];
+ }
+ }
+ }
+
+ /**
+ * Returns the <code>r</code>th row of this matrix as vector.
+ *
+ * @param m1 Input matrix
+ * @param r the index of the row to be returned
+ * @return the <code>r</code>th row of this matrix
+ */
+ public static final double[] getRow(final double[][] m1, final int r) {
+ return m1[r].clone();
+ }
+
+ /**
+ * Sets the <code>r</code>th row of this matrix to the specified vector.
+ *
+ * @param m1 Original matrix
+ * @param r the index of the column to be set
+ * @param row the value of the column to be set
+ */
+ public static final void setRow(final double[][] m1, final int r, final double[] row) {
+ final int columndimension = getColumnDimensionality(m1);
+ assert (row.length == columndimension) : "Matrix must consist of the same no of columns!";
+ for(int i = 0; i < columndimension; i++) {
+ m1[r][i] = row[i];
+ }
+ }
+
+ /**
+ * Get a column from a matrix as vector.
+ *
+ * @param m1 Matrix to extract the column from
+ * @param col Column number
+ * @return Column
+ */
+ public final static double[] getCol(double[][] m1, int col) {
+ double[] ret = new double[m1.length];
+ for(int i = 0; i < ret.length; i++) {
+ ret[i] = m1[i][col];
+ }
+ return ret;
+ }
+
+ /**
+ * Sets the <code>c</code>th column of this matrix to the specified column.
+ *
+ * @param m1 Input matrix
+ * @param c the index of the column to be set
+ * @param column the value of the column to be set
+ */
+ public static final void setCol(final double[][] m1, final int c, final double[] column) {
+ assert (column.length == m1.length) : "Matrix must consist of the same no of rows!";
+ for(int i = 0; i < m1.length; i++) {
+ m1[i][c] = column[i];
+ }
+ }
+
+ /**
+ * Matrix transpose
+ *
+ * @param m1 Input matrix
+ * @return m1<sup>T</sup> as copy
+ */
+ public static final double[][] transpose(final double[][] m1) {
+ final int columndimension = getColumnDimensionality(m1);
+ final double[][] re = new double[columndimension][m1.length];
+ for(int i = 0; i < m1.length; i++) {
+ for(int j = 0; j < columndimension; j++) {
+ re[j][i] = m1[i][j];
+ }
+ }
+ return re;
+ }
+
+ /**
+ * m3 = m1 + m2
+ *
+ * @param m1 Input matrix
+ * @param m2 another matrix
+ * @return m1 + m1 in a new Matrix
+ */
+ public static final double[][] plus(final double[][] m1, final double[][] m2) {
+ return plusEquals(copy(m1), m2);
+ }
+
+ /**
+ * m3 = m1 + s2 * m2
+ *
+ * @param m1 Input matrix
+ * @param m2 another matrix
+ * @param s2 scalar
+ * @return m1 + s2 * m2 in a new Matrix
+ */
+ public static final double[][] plusTimes(final double[][] m1, final double[][] m2, final double s2) {
+ return plusTimesEquals(copy(m1), m2, s2);
+ }
+
+ /**
+ * m1 = m1 + m2, overwriting m1
+ *
+ * @param m1 input matrix
+ * @param m2 another matrix
+ * @return m1 = m1 + m2
+ */
+ public static final double[][] plusEquals(final double[][] m1, final double[][] m2) {
+ final int columndimension = getColumnDimensionality(m1);
+ assert (getRowDimensionality(m1) == getRowDimensionality(m2) && columndimension == getColumnDimensionality(m2)) : "Matrix dimensions must agree.";
+ for(int i = 0; i < m1.length; i++) {
+ for(int j = 0; j < columndimension; j++) {
+ m1[i][j] += m2[i][j];
+ }
+ }
+ return m1;
+ }
+
+ /**
+ * m1 = m1 + s2 * m2, overwriting m1
+ *
+ * @param m1 input matrix
+ * @param m2 another matrix
+ * @param s2 scalar for s2
+ * @return m1 = m1 + s2 * m2, overwriting m1
+ */
+ public static final double[][] plusTimesEquals(final double[][] m1, final double[][] m2, final double s2) {
+ final int columndimension = getColumnDimensionality(m1);
+ assert (getRowDimensionality(m1) == getRowDimensionality(m2) && columndimension == getColumnDimensionality(m2)) : "Matrix dimensions must agree.";
+ for(int i = 0; i < m1.length; i++) {
+ for(int j = 0; j < columndimension; j++) {
+ m1[i][j] += s2 * m2[i][j];
+ }
+ }
+ return m1;
+ }
+
+ /**
+ * m3 = m1 - m2
+ *
+ * @param m1 Input matrix
+ * @param m2 another matrix
+ * @return m1 - m2 in a new matrix
+ */
+ public static final double[][] minus(final double[][] m1, final double[][] m2) {
+ return minusEquals(copy(m1), m2);
+ }
+
+ /**
+ * m3 = m1 - s2 * m2
+ *
+ * @param m1 Input matrix
+ * @param m2 another matrix
+ * @param s2 Scalar
+ * @return m1 - s2 * m2 in a new Matrix
+ */
+ public static final double[][] minusTimes(final double[][] m1, final double[][] m2, final double s2) {
+ return minusTimesEquals(copy(m1), m2, s2);
+ }
+
+ /**
+ * m1 = m1 - m2, overwriting m1
+ *
+ * @param m1 Input matrix
+ * @param m2 another matrix
+ * @return m1 - m2, overwriting m1
+ */
+ public static final double[][] minusEquals(final double[][] m1, final double[][] m2) {
+ final int columndimension = getColumnDimensionality(m1);
+ assert (getRowDimensionality(m1) == getRowDimensionality(m2) && columndimension == getColumnDimensionality(m2)) : "Matrix dimensions must agree.";
+ for(int i = 0; i < m1.length; i++) {
+ for(int j = 0; j < columndimension; j++) {
+ m1[i][j] -= m2[i][j];
+ }
+ }
+ return m1;
+ }
+
+ /**
+ * m1 = m1 - s2 * m2, overwriting m1
+ *
+ * @param m1 Input matrix
+ * @param m2 another matrix
+ * @param s2 Scalar
+ * @return m1 = m1 - s2 * m2, overwriting m1
+ */
+ public static final double[][] minusTimesEquals(final double[][] m1, final double[][] m2, final double s2) {
+ assert (getRowDimensionality(m1) == getRowDimensionality(m2) && getColumnDimensionality(m1) == getColumnDimensionality(m2)) : "Matrix dimensions must agree.";
+ for(int i = 0; i < m1.length; i++) {
+ final double[] row1 = m1[i];
+ final double[] row2 = m2[i];
+ for(int j = 0; j < row1.length; j++) {
+ row1[j] -= s2 * row2[j];
+ }
+ }
+ return m1;
+ }
+
+ /**
+ * Multiply a matrix by a scalar, m3 = s1*m1
+ *
+ * @param m1 Input matrix
+ * @param s1 scalar
+ * @return s1*m1, in a new matrix
+ */
+ public static final double[][] times(final double[][] m1, final double s1) {
+ return timesEquals(copy(m1), s1);
+ }
+
+ /**
+ * Multiply a matrix by a scalar in place, m1 = s1 * m1
+ *
+ * @param m1 Input matrix
+ * @param s1 scalar
+ * @return m1 = s1 * m1, overwriting m1
+ */
+ public static final double[][] timesEquals(final double[][] m1, final double s1) {
+ for(int i = 0; i < m1.length; i++) {
+ final double[] row = m1[i];
+ for(int j = 0; j < row.length; j++) {
+ row[j] *= s1;
+ }
+ }
+ return m1;
+ }
+
+ /**
+ * Linear algebraic matrix multiplication, m1 * m2
+ *
+ * @param m1 Input matrix
+ * @param m2 another matrix
+ * @return Matrix product, m1 * m2
+ */
+ public static final double[][] times(final double[][] m1, final double[][] m2) {
+ final int columndimension = getColumnDimensionality(m1);
+ final int bcolumndimension = getColumnDimensionality(m2);
+ // Optimized implementation, exploiting the storage layout
+ assert (m2.length == columndimension) : "Matrix inner dimensions must agree: " + getRowDimensionality(m1) + "," + getColumnDimensionality(m1) + " * " + getRowDimensionality(m2) + "," + getColumnDimensionality(m2);
+ final double[][] r2 = new double[m1.length][bcolumndimension];
+ // Optimized ala Jama. jik order.
+ final double[] Bcolj = new double[columndimension];
+ for(int j = 0; j < bcolumndimension; j++) {
+ // Make a linear copy of column j from B
+ // TODO: use column getter from B?
+ for(int k = 0; k < columndimension; k++) {
+ Bcolj[k] = m2[k][j];
+ }
+ // multiply it with each row from A
+ for(int i = 0; i < m1.length; i++) {
+ final double[] Arowi = m1[i];
+ double s = 0;
+ for(int k = 0; k < columndimension; k++) {
+ s += Arowi[k] * Bcolj[k];
+ }
+ r2[i][j] = s;
+ }
+ }
+ return r2;
+ }
+
+ /**
+ * Linear algebraic matrix multiplication, m1 * v2
+ *
+ * @param m1 Input matrix
+ * @param v2 a vector
+ * @return Matrix product, m1 * v2
+ */
+ public static final double[] times(final double[][] m1, final double[] v2) {
+ assert (v2.length == getColumnDimensionality(m1)) : "Matrix inner dimensions must agree.";
+ final double[] re = new double[m1.length];
+ // multiply it with each row from A
+ for(int i = 0; i < m1.length; i++) {
+ final double[] Arowi = m1[i];
+ double s = 0;
+ for(int k = 0; k < Arowi.length; k++) {
+ s += Arowi[k] * v2[k];
+ }
+ re[i] = s;
+ }
+ return re;
+ }
+
+ /**
+ * Linear algebraic matrix multiplication, m1<sup>T</sup> * v2
+ *
+ * @param m1 Input matrix
+ * @param v2 another matrix
+ * @return Matrix product, m1<sup>T</sup> * v2
+ */
+ public static final double[] transposeTimes(final double[][] m1, final double[] v2) {
+ final int columndimension = getColumnDimensionality(m1);
+ assert (v2.length == m1.length) : "Matrix inner dimensions must agree.";
+ final double[] re = new double[columndimension];
+ // multiply it with each row from A
+ for(int i = 0; i < columndimension; i++) {
+ double s = 0;
+ for(int k = 0; k < m1.length; k++) {
+ s += m1[k][i] * v2[k];
+ }
+ re[i] = s;
+ }
+ return re;
+ }
+
+ /**
+ * Linear algebraic matrix multiplication, m1<sup>T</sup> * m2
+ *
+ * @param m1 Input matrix
+ * @param m2 another matrix
+ * @return Matrix product, m1<sup>T</sup> * m2
+ */
+ public static final double[][] transposeTimes(final double[][] m1, final double[][] m2) {
+ final int coldim1 = getColumnDimensionality(m1);
+ final int coldim2 = getColumnDimensionality(m2);
+ assert (m2.length == m1.length) : "Matrix inner dimensions must agree.";
+ final double[][] re = new double[coldim1][coldim2];
+ final double[] Bcolj = new double[m1.length];
+ for(int j = 0; j < coldim2; j++) {
+ // Make a linear copy of column j from B
+ for(int k = 0; k < m1.length; k++) {
+ Bcolj[k] = m2[k][j];
+ }
+ // multiply it with each row from A
+ for(int i = 0; i < coldim1; i++) {
+ double s = 0;
+ for(int k = 0; k < m1.length; k++) {
+ s += m1[k][i] * Bcolj[k];
+ }
+ re[i][j] = s;
+ }
+ }
+ return re;
+ }
+
+ /**
+ * Linear algebraic matrix multiplication, m1 * m2^T
+ *
+ * @param m1 Input matrix
+ * @param m2 another matrix
+ * @return Matrix product, m1 * m2^T
+ */
+ public static final double[][] timesTranspose(final double[][] m1, final double[][] m2) {
+ assert (getColumnDimensionality(m2) == getColumnDimensionality(m1)) : "Matrix inner dimensions must agree.";
+ final double[][] re = new double[m1.length][m2.length];
+ for(int j = 0; j < re.length; j++) {
+ final double[] Browj = m2[j];
+ // multiply it with each row from A
+ for(int i = 0; i < m1.length; i++) {
+ final double[] Arowi = m1[i];
+ double s = 0;
+ for(int k = 0; k < Browj.length; k++) {
+ s += Arowi[k] * Browj[k];
+ }
+ re[i][j] = s;
+ }
+ }
+ return re;
+ }
+
+ /**
+ * Linear algebraic matrix multiplication, m1^T * m2^T. Computed as (m2*m1)^T
+ *
+ * @param m1 Input matrix
+ * @param m2 another matrix
+ * @return Matrix product, m1^T * m2^T
+ */
+ public static final double[][] transposeTimesTranspose(final double[][] m1, final double[][] m2) {
+ // Optimized implementation, exploiting the storage layout
+ assert (m1.length == getColumnDimensionality(m2)) : "Matrix inner dimensions must agree: " + getRowDimensionality(m1) + "," + getColumnDimensionality(m1) + " * " + getRowDimensionality(m2) + "," + getColumnDimensionality(m2);
+ final double[][] re = new double[getColumnDimensionality(m1)][m2.length];
+ // Optimized ala Jama. jik order.
+ final double[] Acolj = new double[m1.length];
+ for(int j = 0; j < re.length; j++) {
+ // Make a linear copy of column j from B
+ for(int k = 0; k < m1.length; k++) {
+ Acolj[k] = m1[k][j];
+ }
+ final double[] Xrow = re[j];
+ // multiply it with each row from A
+ for(int i = 0; i < m2.length; i++) {
+ final double[] Browi = m2[i];
+ double s = 0;
+ for(int k = 0; k < m1.length; k++) {
+ s += Browi[k] * Acolj[k];
+ }
+ Xrow[i] = s;
+ }
+ }
+ return re;
+ }
+
+ /**
+ * getDiagonal returns array of diagonal-elements.
+ *
+ * @param m1 Input matrix
+ * @return values on the diagonal of the Matrix
+ */
+ public final static double[] getDiagonal(final double[][] m1) {
+ final int dim = Math.min(getColumnDimensionality(m1), m1.length);
+ final double[] diagonal = new double[dim];
+ for(int i = 0; i < dim; i++) {
+ diagonal[i] = m1[i][i];
+ }
+ return diagonal;
+ }
+
+ /**
+ * Normalizes the columns of this matrix to length of 1.0.
+ *
+ * @param m1 Input matrix
+ */
+ public final static void normalizeColumns(final double[][] m1) {
+ final int columndimension = getColumnDimensionality(m1);
+ for(int col = 0; col < columndimension; col++) {
+ double norm = 0.0;
+ for(int row = 0; row < m1.length; row++) {
+ norm = norm + (m1[row][col] * m1[row][col]);
+ }
+ norm = Math.sqrt(norm);
+ if(norm != 0) {
+ for(int row = 0; row < m1.length; row++) {
+ m1[row][col] /= norm;
+ }
+ }
+ else {
+ // TODO: else: throw an exception?
+ }
+ }
+ }
+
+ /**
+ * Returns a matrix which consists of this matrix and the specified columns.
+ *
+ * @param m1 Input matrix
+ * @param m2 the columns to be appended
+ * @return the new matrix with the appended columns
+ */
+ public static final double[][] appendColumns(final double[][] m1, final double[][] m2) {
+ final int columndimension = getColumnDimensionality(m1);
+ final int ccolumndimension = getColumnDimensionality(m2);
+ assert (m1.length == m2.length) : "m.getRowDimension() != column.getRowDimension()";
+
+ final int rcolumndimension = columndimension + ccolumndimension;
+ final double[][] result = new double[m1.length][rcolumndimension];
+ for(int i = 0; i < rcolumndimension; i++) {
+ // FIXME: optimize - excess copying!
+ if(i < columndimension) {
+ setCol(result, i, getCol(m1, i));
+ }
+ else {
+ setCol(result, i, getCol(m2, i - columndimension));
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Returns an orthonormalization of this matrix.
+ *
+ * @param m1 Input matrix
+ * @return the orthonormalized matrix
+ */
+ public static final double[][] orthonormalize(final double[][] m1) {
+ final int columndimension = getColumnDimensionality(m1);
+ double[][] v = copy(m1);
+
+ // FIXME: optimize - excess copying!
+ for(int i = 1; i < columndimension; i++) {
+ final double[] u_i = getCol(m1, i);
+ final double[] sum = new double[m1.length];
+ for(int j = 0; j < i; j++) {
+ final double[] v_j = getCol(v, j);
+ double scalar = scalarProduct(u_i, v_j) / scalarProduct(v_j, v_j);
+ plusEquals(sum, times(v_j, scalar));
+ }
+ final double[] v_i = minus(u_i, sum);
+ setCol(v, i, v_i);
+ }
+
+ normalizeColumns(v);
+ return v;
+ }
+
+ /**
+ * Compute hash code
+ *
+ * @param m1 Input matrix
+ * @return Hash code
+ */
+ public static final int hashCode(final double[][] m1) {
+ return Arrays.hashCode(m1);
+ }
+
+ /**
+ * Test for equality
+ *
+ * @param m1 Input matrix
+ * @param m2 Other matrix
+ * @return Equality
+ */
+ public static final boolean equals(final double[][] m1, final double[][] m2) {
+ return Arrays.equals(m1, m2);
+ }
+
+ /**
+ * Compare two matrices with a delta parameter to take numerical errors into
+ * account.
+ *
+ * @param m1 Input matrix
+ * @param m2 other matrix to compare with
+ * @param maxdelta maximum delta allowed
+ * @return true if delta smaller than maximum
+ */
+ public static final boolean almostEquals(final double[][] m1, final double[][] m2, final double maxdelta) {
+ if(m1 == m2) {
+ return true;
+ }
+ if(m2 == null) {
+ return false;
+ }
+ if(m1.getClass() != m2.getClass()) {
+ return false;
+ }
+ if(m1.length != m2.length) {
+ return false;
+ }
+ final int columndimension = getColumnDimensionality(m1);
+ if(columndimension != getColumnDimensionality(m2)) {
+ return false;
+ }
+ for(int i = 0; i < m1.length; i++) {
+ for(int j = 0; j < columndimension; j++) {
+ if(Math.abs(m1[i][j] - m2[i][j]) > maxdelta) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Compare two matrices with a delta parameter to take numerical errors into
+ * account.
+ *
+ * @param m1 Input matrix
+ * @param m2 other matrix to compare with
+ * @return almost equals with delta {@link #DELTA}
+ */
+ public static final boolean almostEquals(final double[][] m1, final double[][] m2) {
+ return almostEquals(m1, m2, DELTA);
+ }
+
+ /**
+ * Returns the dimensionality of the rows of this matrix.
+ *
+ * @param m1 Input matrix
+ * @return the number of rows.
+ */
+ public static final int getRowDimensionality(final double[][] m1) {
+ return m1.length;
+ }
+
+ /**
+ * Returns the dimensionality of the columns of this matrix.
+ *
+ * @param m1 Input matrix
+ * @return the number of columns.
+ */
+ public static final int getColumnDimensionality(final double[][] m1) {
+ return m1[0].length;
+ }
+} \ No newline at end of file
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 8cf3cf78..0a674d87 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) 2011
+ Copyright (C) 2012
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.math.linearalgebra;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.io.Serializable;
import java.util.Arrays;
-import de.lmu.ifi.dbs.elki.math.MathUtil;
+import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.utilities.FormatUtil;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayAdapter;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.NumberArrayAdapter;
/**
* Provides a vector object that encapsulates an m x 1 - matrix object.
@@ -36,12 +37,7 @@ import de.lmu.ifi.dbs.elki.utilities.FormatUtil;
*
* @apiviz.landmark
*/
-public class Vector implements MatrixLike<Vector>, Serializable {
- /**
- * Serial version
- */
- private static final long serialVersionUID = 1L;
-
+public class Vector implements NumberVector<Vector, Double> {
/**
* Array for internal storage of elements.
*
@@ -73,13 +69,18 @@ public class Vector implements MatrixLike<Vector>, Serializable {
* @param dimensionality dimensionality
* @return the dimensionality of the vector
*/
- // FIXME: may also return null vector by chance.
public static final Vector randomNormalizedVector(final int dimensionality) {
final Vector v = new Vector(dimensionality);
- for(int i = 0; i < dimensionality; i++) {
- v.elements[i] = Math.random();
+ double norm = 0;
+ while(norm <= 0) {
+ for(int i = 0; i < dimensionality; i++) {
+ v.elements[i] = Math.random();
+ }
+ norm = v.euclideanLength();
+ }
+ for(int row = 0; row < dimensionality; row++) {
+ v.elements[row] /= norm;
}
- v.normalize();
return v;
}
@@ -101,7 +102,6 @@ public class Vector implements MatrixLike<Vector>, Serializable {
*
* @return a copy of this vector
*/
- @Override
public final Vector copy() {
return new Vector(elements.clone());
}
@@ -137,20 +137,11 @@ public class Vector implements MatrixLike<Vector>, Serializable {
*
* @return the dimensionality of this vector
*/
- public final int getDimensionality() {
- return elements.length;
- }
-
@Override
- public final int getRowDimensionality() {
+ public final int getDimensionality() {
return elements.length;
}
- @Override
- public final int getColumnDimensionality() {
- return 1;
- }
-
/**
* Returns the value at the specified row.
*
@@ -161,14 +152,6 @@ public class Vector implements MatrixLike<Vector>, Serializable {
return elements[i];
}
- @Override
- public final double get(final int i, final int j) {
- if(j != 0) {
- throw new ArrayIndexOutOfBoundsException();
- }
- return elements[i];
- }
-
/**
* Sets the value at the specified row.
*
@@ -182,37 +165,6 @@ public class Vector implements MatrixLike<Vector>, Serializable {
return this;
}
- @Override
- public final Vector set(final int i, final int j, final double s) {
- if(j != 0) {
- throw new ArrayIndexOutOfBoundsException();
- }
- elements[i] = s;
- return this;
- }
-
- @Override
- public final Vector increment(final int i, final int j, final double s) {
- if(j != 0) {
- throw new ArrayIndexOutOfBoundsException();
- }
- elements[i] += s;
- return this;
- }
-
- @Override
- public final Vector getColumnVector(final int i) {
- if(i != 0) {
- throw new ArrayIndexOutOfBoundsException();
- }
- return this;
- }
-
- @Override
- public final Matrix transpose() {
- return new Matrix(this.elements, 1);
- }
-
/**
* Returns a new vector which is the result of this vector plus the specified
* vector.
@@ -220,9 +172,8 @@ public class Vector implements MatrixLike<Vector>, Serializable {
* @param v the vector to be added
* @return the resulting vector
*/
- @Override
public final Vector plus(final Vector v) {
- checkDimensions(v);
+ assert (this.elements.length == v.elements.length) : "Vector dimensions must agree.";
final Vector result = new Vector(elements.length);
for(int i = 0; i < elements.length; i++) {
result.elements[i] = elements[i] + v.elements[i];
@@ -238,9 +189,8 @@ public class Vector implements MatrixLike<Vector>, Serializable {
* @param s the scalar
* @return the resulting vector
*/
- @Override
public final Vector plusTimes(final Vector v, final double s) {
- checkDimensions(v);
+ assert (this.elements.length == v.elements.length) : "Vector dimensions must agree.";
final Vector result = new Vector(elements.length);
for(int i = 0; i < elements.length; i++) {
result.elements[i] = elements[i] + v.elements[i] * s;
@@ -254,11 +204,10 @@ public class Vector implements MatrixLike<Vector>, Serializable {
* @param B another matrix
* @return A + B in this Matrix
*/
- @Override
public final Vector plusEquals(final Vector B) {
- checkDimensions(B);
+ assert (this.elements.length == B.elements.length) : "Vector dimensions must agree.";
for(int i = 0; i < elements.length; i++) {
- elements[i] += B.get(i, 0);
+ elements[i] += B.elements[i];
}
return this;
}
@@ -270,11 +219,10 @@ public class Vector implements MatrixLike<Vector>, Serializable {
* @param s Scalar
* @return A + s * B in this Matrix
*/
- @Override
public final Vector plusTimesEquals(final Vector B, final double s) {
- checkDimensions(B);
+ assert (this.elements.length == B.elements.length) : "Vector dimensions must agree.";
for(int i = 0; i < elements.length; i++) {
- elements[i] += s * B.get(i, 0);
+ elements[i] += s * B.elements[i];
}
return this;
}
@@ -298,7 +246,6 @@ public class Vector implements MatrixLike<Vector>, Serializable {
* @param v the vector to be subtracted from this vector
* @return this vector minus the specified vector v
*/
- @Override
public final Vector minus(final Vector v) {
final Vector sub = new Vector(elements.length);
for(int i = 0; i < elements.length; i++) {
@@ -314,7 +261,6 @@ public class Vector implements MatrixLike<Vector>, Serializable {
* @param s the scaling factor
* @return this vector minus the specified vector v
*/
- @Override
public final Vector minusTimes(final Vector v, final double s) {
final Vector sub = new Vector(elements.length);
for(int i = 0; i < elements.length; i++) {
@@ -329,11 +275,10 @@ public class Vector implements MatrixLike<Vector>, Serializable {
* @param B another matrix
* @return A - B in this Matrix
*/
- @Override
public final Vector minusEquals(final Vector B) {
- checkDimensions(B);
+ assert (this.elements.length == B.elements.length) : "Vector dimensions must agree.";
for(int i = 0; i < elements.length; i++) {
- elements[i] -= B.get(i, 0);
+ elements[i] -= B.elements[i];
}
return this;
}
@@ -345,11 +290,10 @@ public class Vector implements MatrixLike<Vector>, Serializable {
* @param s Scalar
* @return A - s * B in this Matrix
*/
- @Override
public final Vector minusTimesEquals(final Vector B, final double s) {
- checkDimensions(B);
+ assert (this.elements.length == B.elements.length) : "Vector dimensions must agree.";
for(int i = 0; i < elements.length; i++) {
- elements[i] -= s * B.get(i, 0);
+ elements[i] -= s * B.elements[i];
}
return this;
}
@@ -374,7 +318,6 @@ public class Vector implements MatrixLike<Vector>, Serializable {
* @param s the scalar to be multiplied
* @return the resulting vector
*/
- @Override
public final Vector times(final double s) {
final Vector v = new Vector(elements.length);
for(int i = 0; i < elements.length; i++) {
@@ -389,7 +332,6 @@ public class Vector implements MatrixLike<Vector>, Serializable {
* @param s scalar
* @return replace A by s*A
*/
- @Override
public final Vector timesEquals(final double s) {
for(int i = 0; i < elements.length; i++) {
elements[i] *= s;
@@ -402,12 +344,9 @@ public class Vector implements MatrixLike<Vector>, Serializable {
*
* @param B another matrix
* @return Matrix product, A * B
- * @throws IllegalArgumentException Matrix inner dimensions must agree.
*/
public final Matrix times(final Matrix B) {
- if(B.elements.length != 1) {
- throw new IllegalArgumentException("Matrix inner dimensions must agree.");
- }
+ assert (B.elements.length == 1) : "Matrix inner dimensions must agree.";
final Matrix X = new Matrix(this.elements.length, B.columndimension);
for(int j = 0; j < B.columndimension; j++) {
for(int i = 0; i < this.elements.length; i++) {
@@ -422,12 +361,9 @@ public class Vector implements MatrixLike<Vector>, Serializable {
*
* @param B another matrix
* @return Matrix product, A<sup>T</sup> * B
- * @throws IllegalArgumentException Matrix inner dimensions must agree.
*/
public final Matrix transposeTimes(final Matrix B) {
- if(B.elements.length != this.elements.length) {
- throw new IllegalArgumentException("Matrix inner dimensions must agree.");
- }
+ assert (B.elements.length == this.elements.length) : "Matrix inner dimensions must agree.";
final Matrix X = new Matrix(1, B.columndimension);
for(int j = 0; j < B.columndimension; j++) {
// multiply it with each row from A
@@ -441,16 +377,34 @@ public class Vector implements MatrixLike<Vector>, Serializable {
}
/**
+ * Linear algebraic matrix multiplication, a<sup>T</sup> * B * c
+ *
+ * @param B matrix
+ * @param c vector on the right
+ * @return Matrix product, a<sup>T</sup> * B
+ */
+ public final double transposeTimesTimes(final Matrix B, final Vector c) {
+ assert (B.elements.length == this.elements.length) : "Matrix inner dimensions must agree.";
+ double sum = 0.0;
+ for(int j = 0; j < B.columndimension; j++) {
+ // multiply it with each row from A
+ double s = 0;
+ for(int k = 0; k < this.elements.length; k++) {
+ s += this.elements[k] * B.elements[k][j];
+ }
+ sum += s * c.elements[j];
+ }
+ return sum;
+ }
+
+ /**
* Linear algebraic matrix multiplication, A<sup>T</sup> * B
*
* @param B another vector
* @return Matrix product, A<sup>T</sup> * B
- * @throws IllegalArgumentException Matrix inner dimensions must agree.
*/
public final double transposeTimes(final Vector B) {
- if(B.elements.length != this.elements.length) {
- throw new IllegalArgumentException("Matrix inner dimensions must agree.");
- }
+ assert (B.elements.length == this.elements.length) : "Matrix inner dimensions must agree.";
double s = 0;
for(int k = 0; k < this.elements.length; k++) {
s += this.elements[k] * B.elements[k];
@@ -463,61 +417,32 @@ public class Vector implements MatrixLike<Vector>, Serializable {
*
* @param B another matrix
* @return Matrix product, A * B^T
- * @throws IllegalArgumentException Matrix inner dimensions must agree.
*/
public final Matrix timesTranspose(final Matrix B) {
- if(B.columndimension != 1) {
- throw new IllegalArgumentException("Matrix inner dimensions must agree.");
- }
+ assert (B.columndimension == 1) : "Matrix inner dimensions must agree.";
final Matrix X = new Matrix(this.elements.length, B.elements.length);
for(int j = 0; j < B.elements.length; j++) {
for(int i = 0; i < this.elements.length; i++) {
- X.elements[i][j] = elements[i] * B.elements[0][j];
+ X.elements[i][j] = elements[i] * B.elements[j][0];
}
}
return X;
}
/**
- * Returns the scalar product of this vector and the specified vector v.
- *
- * @param v the vector
- * @return double the scalar product of this vector and v
- */
- public final double scalarProduct(final Vector v) {
- checkDimensions(v);
- double scalarProduct = 0.0;
- for(int row = 0; row < elements.length; row++) {
- final double prod = elements[row] * v.elements[row];
- scalarProduct += prod;
- }
- return scalarProduct;
- }
-
- /**
- * Inverts every element of the vector.
- *
- * @return the resulting vector
- */
- public final Vector inverseVector() {
- final Vector inv = new Vector(elements.length);
- for(int i = 0; i < elements.length; i++) {
- inv.elements[i] = 1.0 / elements[i];
- }
- return inv;
- }
-
- /**
- * Square roots every element of the vector.
+ * Linear algebraic matrix multiplication, A * B^T
*
- * @return the resulting vector
+ * @param B another matrix
+ * @return Matrix product, A * B^T
*/
- public final Vector sqrtVector() {
- final Vector sqrt = new Vector(elements.length);
- for(int i = 0; i < elements.length; i++) {
- sqrt.elements[i] = Math.sqrt(elements[i]);
+ public final Matrix timesTranspose(final Vector B) {
+ final Matrix X = new Matrix(this.elements.length, B.elements.length);
+ for(int j = 0; j < B.elements.length; j++) {
+ for(int i = 0; i < this.elements.length; i++) {
+ X.elements[i][j] = elements[i] * B.elements[j];
+ }
}
- return sqrt;
+ return X;
}
/**
@@ -526,27 +451,15 @@ public class Vector implements MatrixLike<Vector>, Serializable {
* @return the length of this vector
*/
public final double euclideanLength() {
- double sqlen = 0.0;
+ double acc = 0.0;
for(int row = 0; row < elements.length; row++) {
- sqlen += elements[row] * elements[row];
+ final double v = elements[row];
+ acc += v * v;
}
- return Math.sqrt(sqlen);
+ return Math.sqrt(acc);
}
/**
- * Frobenius norm
- *
- * @return sqrt of sum of squares of all elements.
- */
- public double normF() {
- double f = 0;
- for(int i = 0; i < elements.length; i++) {
- f = MathUtil.hypotenuse(f, elements[i]);
- }
- return f;
- }
-
- /**
* Normalizes this vector to the length of 1.0.
*/
public final Vector normalize() {
@@ -565,40 +478,21 @@ public class Vector implements MatrixLike<Vector>, Serializable {
*
* @param v the subspace matrix
* @return the projection of p into the subspace formed by v
- * @throws IllegalArgumentException if this matrix is no row vector, i.e. this
- * matrix has more than one column or this matrix and v have different
- * length of rows
*/
public final Vector projection(final Matrix v) {
- if(elements.length != v.elements.length) {
- throw new IllegalArgumentException("p and v differ in row dimensionality!");
- }
+ assert (elements.length == v.elements.length) : "p and v differ in row dimensionality!";
Vector sum = new Vector(elements.length);
for(int i = 0; i < v.columndimension; i++) {
- // TODO: optimize - copy less.
- Vector v_i = v.getColumnVector(i);
- sum.plusEquals(v_i.times(scalarProduct(v_i)));
+ // TODO: optimize - copy less?
+ Vector v_i = v.getCol(i);
+ sum.plusTimesEquals(v_i, this.transposeTimes(v_i));
}
return sum;
}
- /**
- * Check if this.getDimensionality() == v.getDimensionality().
- *
- * @throws IllegalArgumentException if the dimensions do not agree
- */
- private final void checkDimensions(final Vector v) {
- if(this.elements.length != v.elements.length) {
- throw new IllegalArgumentException("Vector dimensions must agree.");
- }
- }
-
@Override
public int hashCode() {
- final int PRIME = 31;
- int result = 1;
- result = PRIME * result + Arrays.hashCode(this.elements);
- return result;
+ return Arrays.hashCode(this.elements);
}
@Override
@@ -616,12 +510,7 @@ public class Vector implements MatrixLike<Vector>, Serializable {
if(this.elements.length != other.elements.length) {
return false;
}
- for(int i = 0; i < this.elements.length; i++) {
- if(this.elements[i] != other.elements[i]) {
- return false;
- }
- }
- return true;
+ return Arrays.equals(this.elements, other.elements);
}
/**
@@ -650,4 +539,95 @@ public class Vector implements MatrixLike<Vector>, Serializable {
public void setZero() {
Arrays.fill(elements, 0.0);
}
+
+ /**
+ * Rotate vector by 90 degrees.
+ *
+ * @return self, for operation chaining.
+ */
+ public Vector rotate90Equals() {
+ assert (elements.length == 2);
+ double temp = elements[0];
+ elements[0] = elements[1];
+ elements[1] = -temp;
+ return this;
+ }
+
+ // ////// NumberVector API. A bit hackish. :-(
+
+ @Override
+ public double getMin(int dimension) {
+ return elements[dimension - 1];
+ }
+
+ @Override
+ public double getMax(int dimension) {
+ return elements[dimension - 1];
+ }
+
+ @Override
+ public Double getValue(int dimension) {
+ return elements[dimension - 1];
+ }
+
+ @Override
+ public double doubleValue(int dimension) {
+ return elements[dimension - 1];
+ }
+
+ @Override
+ public float floatValue(int dimension) {
+ return (float) elements[dimension - 1];
+ }
+
+ @Override
+ public int intValue(int dimension) {
+ return (int) elements[dimension - 1];
+ }
+
+ @Override
+ public long longValue(int dimension) {
+ return (long) elements[dimension - 1];
+ }
+
+ @Override
+ public short shortValue(int dimension) {
+ return (short) elements[dimension - 1];
+ }
+
+ @Override
+ public byte byteValue(int dimension) {
+ return (byte) elements[dimension - 1];
+ }
+
+ @Override
+ public Vector getColumnVector() {
+ return copy();
+ }
+
+ @Override
+ public Vector newNumberVector(double[] values) {
+ return new Vector(values);
+ }
+
+ @Override
+ public <A> Vector newNumberVector(A array, NumberArrayAdapter<?, A> adapter) {
+ double[] raw = new double[adapter.size(array)];
+ for(int i = 0; i < raw.length; i++) {
+ raw[i] = adapter.getDouble(array, i);
+ }
+ return new Vector(raw);
+ }
+
+ @Override
+ public <A> Vector newFeatureVector(A array, ArrayAdapter<Double, A> adapter) {
+ if(adapter instanceof NumberArrayAdapter) {
+ return newNumberVector(array, (NumberArrayAdapter<?, A>) adapter);
+ }
+ double[] raw = new double[adapter.size(array)];
+ for(int i = 0; i < raw.length; i++) {
+ raw[i] = adapter.get(array, i);
+ }
+ return new Vector(raw);
+ }
} \ No newline at end of file
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 0cb67acc..b04c64d5 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) 2011
+ Copyright (C) 2012
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 46245349..76f90138 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) 2011
+ Copyright (C) 2012
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 327b92b4..42badb2f 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) 2011
+ Copyright (C) 2012
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/LevenbergMarquardtMethod.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/fitting/LevenbergMarquardtMethod.java
index 8b8253dc..d87e1208 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) 2011
+ Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/fitting/package-info.java
index f2ad8c35..2c4143a8 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) 2011
+Copyright (C) 2012
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 d38b9a7b..5c55dfd1 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) 2011
+Copyright (C) 2012
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 197ad939..c14986bd 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -54,17 +54,17 @@ public abstract class AbstractCovarianceMatrixBuilder<V extends NumberVector<? e
public abstract Matrix processIds(DBIDs ids, Relation<? extends V> database);
@Override
- public <D extends NumberDistance<?, ?>> Matrix processQueryResults(Collection<DistanceResultPair<D>> results, Relation<? extends V> database, int k) {
+ public <D extends NumberDistance<?, ?>> Matrix processQueryResults(Collection<? extends DistanceResultPair<D>> results, Relation<? extends V> database, int k) {
ModifiableDBIDs ids = DBIDUtil.newArray(k);
int have = 0;
- for(Iterator<DistanceResultPair<D>> it = results.iterator(); it.hasNext() && have < k; have++) {
+ for(Iterator<? extends DistanceResultPair<D>> it = results.iterator(); it.hasNext() && have < k; have++) {
ids.add(it.next().getDBID());
}
return processIds(ids, database);
}
@Override
- final public <D extends NumberDistance<?, ?>> Matrix processQueryResults(Collection<DistanceResultPair<D>> results, Relation<? extends V> database) {
+ final public <D extends NumberDistance<?, ?>> Matrix processQueryResults(Collection<? extends DistanceResultPair<D>> results, Relation<? extends V> database) {
return processQueryResults(results, database, results.size());
}
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 112a6df4..bc9486c5 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) 2011
+ Copyright (C) 2012
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/CovarianceMatrixBuilder.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/CovarianceMatrixBuilder.java
index 7416abce..5098ffac 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -67,7 +67,7 @@ public interface CovarianceMatrixBuilder<V extends NumberVector<? extends V, ?>>
* @param k the number of entries to process
* @return Covariance Matrix
*/
- public <D extends NumberDistance<?, ?>> Matrix processQueryResults(Collection<DistanceResultPair<D>> results, Relation<? extends V> database, int k);
+ public <D extends NumberDistance<?, ?>> Matrix processQueryResults(Collection<? extends DistanceResultPair<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<? extends V, ?>>
* @param database the database used
* @return Covariance Matrix
*/
- public <D extends NumberDistance<?, ?>> Matrix processQueryResults(Collection<DistanceResultPair<D>> results, Relation<? extends V> database);
+ public <D extends NumberDistance<?, ?>> Matrix processQueryResults(Collection<? extends DistanceResultPair<D>> results, Relation<? extends V> database);
} \ No newline at end of file
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 3c9d8603..553a111f 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) 2011
+ Copyright (C) 2012
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 9fdac000..a2c83249 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) 2011
+ Copyright (C) 2012
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 c4839109..08482b71 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) 2011
+ Copyright (C) 2012
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/LimitEigenPairFilter.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/LimitEigenPairFilter.java
index c1edb99a..e8d2b844 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) 2011
+ Copyright (C) 2012
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/NormalizingEigenPairFilter.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/NormalizingEigenPairFilter.java
index 47dbb01a..29be965c 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -86,7 +86,7 @@ public class NormalizingEigenPairFilter implements EigenPairFilter {
*/
private void normalizeEigenPair(final EigenPair eigenPair) {
final Vector eigenvector = eigenPair.getEigenvector();
- final double scaling = 1.0 / Math.sqrt(eigenPair.getEigenvalue()) * eigenvector.normF();
+ final double scaling = 1.0 / Math.sqrt(eigenPair.getEigenvalue()) * eigenvector.euclideanLength();
eigenvector.timesEquals(scaling);
}
} \ No newline at end of file
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
new file mode 100644
index 00000000..8b53dc43
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/PCAFilteredAutotuningRunner.java
@@ -0,0 +1,232 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.database.ids.DBID;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
+import de.lmu.ifi.dbs.elki.database.query.DoubleDistanceResultPair;
+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.distancevalue.NumberDistance;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.EigenPair;
+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.utilities.DatabaseUtil;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+
+/**
+ * Performs a self-tuning local PCA based on the covariance matrices of given
+ * objects. At most the closest 'k' points are used in the calculation and a
+ * weight function is applied.
+ *
+ * The number of points actually used depends on when the strong eigenvectors
+ * exhibit the clearest correlation.
+ *
+ * @author Erich Schubert
+ * @param <V> vector type
+ */
+@Reference(authors = "H.-P. Kriegel, P. Kröger, E. Schubert, A. Zimek", title = "A General Framework for Increasing the Robustness of PCA-based Correlation Clustering Algorithms", booktitle = "Proceedings of the 20th International Conference on Scientific and Statistical Database Management (SSDBM), Hong Kong, China, 2008", url = "http://dx.doi.org/10.1007/978-3-540-69497-7_27")
+public class PCAFilteredAutotuningRunner<V extends NumberVector<? extends V, ?>> extends PCAFilteredRunner<V> {
+ /**
+ * Constructor.
+ *
+ * @param covarianceMatrixBuilder
+ * @param eigenPairFilter
+ * @param big
+ * @param small
+ */
+ public PCAFilteredAutotuningRunner(CovarianceMatrixBuilder<V> covarianceMatrixBuilder, EigenPairFilter eigenPairFilter, double big, double small) {
+ super(covarianceMatrixBuilder, eigenPairFilter, big, small);
+ }
+
+ @Override
+ public PCAFilteredResult processIds(DBIDs ids, Relation<? extends V> database) {
+ // Assume Euclidean distance. In the context of PCA, the neighborhood should
+ // be L2-spherical to be unbiased.
+ V center = DatabaseUtil.centroid(database, ids);
+ List<DoubleDistanceResultPair> dres = new ArrayList<DoubleDistanceResultPair>(ids.size());
+ for(DBID id : ids) {
+ final double dist = EuclideanDistanceFunction.STATIC.doubleDistance(center, database.get(id));
+ dres.add(new DoubleDistanceResultPair(dist, id));
+ }
+ Collections.sort(dres);
+ return processQueryResult(dres, database);
+ }
+
+ @Override
+ public <D extends NumberDistance<?, ?>> PCAFilteredResult processQueryResult(Collection<? extends DistanceResultPair<D>> results, Relation<? extends V> database) {
+ assertSortedByDistance(results);
+ final int dim = DatabaseUtil.dimensionality(database);
+
+ List<Matrix> best = new LinkedList<Matrix>();
+ for(int i = 0; i < dim; i++) {
+ best.add(null);
+ }
+ double[] beststrength = new double[dim];
+ for(int i = 0; i < dim; i++) {
+ beststrength[i] = -1;
+ }
+ int[] bestk = new int[dim];
+ // 'history'
+ LinkedList<Matrix> prevM = new LinkedList<Matrix>();
+ LinkedList<Double> prevS = new LinkedList<Double>();
+ LinkedList<Integer> prevD = new LinkedList<Integer>();
+ // TODO: starting parameter shouldn't be hardcoded...
+ int smooth = 3;
+ int startk = 4;
+ if(startk > results.size() - 1) {
+ startk = results.size() - 1;
+ }
+ // TODO: add smoothing options, handle border cases better.
+ for(int k = startk; k < results.size(); k++) {
+ // sorted eigenpairs, eigenvectors, eigenvalues
+ Matrix covMat = covarianceMatrixBuilder.processQueryResults(results, database);
+ EigenvalueDecomposition evd = new EigenvalueDecomposition(covMat);
+ SortedEigenPairs eigenPairs = new SortedEigenPairs(evd, false);
+ FilteredEigenPairs filteredEigenPairs = getEigenPairFilter().filter(eigenPairs);
+
+ // correlationDimension = #strong EV
+ int thisdim = filteredEigenPairs.countStrongEigenPairs();
+
+ // FIXME: handle the case of no strong EVs.
+ assert ((thisdim > 0) && (thisdim <= dim));
+ double thisexplain = computeExplainedVariance(filteredEigenPairs);
+
+ prevM.add(covMat);
+ prevS.add(thisexplain);
+ prevD.add(thisdim);
+ assert (prevS.size() == prevM.size());
+ assert (prevS.size() == prevD.size());
+
+ if(prevS.size() >= 2 * smooth + 1) {
+ // all the same dimension?
+ boolean samedim = true;
+ for(Iterator<Integer> it = prevD.iterator(); it.hasNext();) {
+ if(it.next().intValue() != thisdim) {
+ samedim = false;
+ }
+ }
+ if(samedim) {
+ // average their explain values
+ double avgexplain = 0.0;
+ for(Iterator<Double> it = prevS.iterator(); it.hasNext();) {
+ avgexplain += it.next().doubleValue();
+ }
+ avgexplain /= prevS.size();
+
+ if(avgexplain > beststrength[thisdim - 1]) {
+ beststrength[thisdim - 1] = avgexplain;
+ best.set(thisdim - 1, prevM.get(smooth));
+ bestk[thisdim - 1] = k - smooth;
+ }
+ }
+ prevM.removeFirst();
+ prevS.removeFirst();
+ prevD.removeFirst();
+ assert (prevS.size() == prevM.size());
+ assert (prevS.size() == prevD.size());
+ }
+ }
+ // Try all dimensions, lowest first.
+ for(int i = 0; i < dim; i++) {
+ if(beststrength[i] > 0.0) {
+ // If the best was the lowest or the biggest k, skip it!
+ if(bestk[i] == startk + smooth) {
+ continue;
+ }
+ if(bestk[i] == results.size() - smooth - 1) {
+ continue;
+ }
+ Matrix covMat = best.get(i);
+
+ // We stop at the lowest dimension that did the job for us.
+ // System.err.println("Auto-k: "+bestk[i]+" dim: "+(i+1));
+ return processCovarMatrix(covMat);
+ }
+ }
+ // NOTE: if we didn't get a 'maximum' anywhere, we end up with the data from
+ // the last run of the loop above. I.e. PCA on the full data set. That is
+ // intended.
+ return processCovarMatrix(covarianceMatrixBuilder.processQueryResults(results, database));
+ }
+
+ /**
+ * Compute the explained variance for a FilteredEigenPairs
+ *
+ * @param filteredEigenPairs
+ * @return explained variance by the strong eigenvectors.
+ */
+ private double computeExplainedVariance(FilteredEigenPairs filteredEigenPairs) {
+ double strongsum = 0.0;
+ double weaksum = 0.0;
+ for(EigenPair ep : filteredEigenPairs.getStrongEigenPairs()) {
+ strongsum += ep.getEigenvalue();
+ }
+ for(EigenPair ep : filteredEigenPairs.getWeakEigenPairs()) {
+ weaksum += ep.getEigenvalue();
+ }
+ return strongsum / (strongsum / weaksum);
+ }
+
+ /**
+ * Ensure that the results are sorted by distance.
+ *
+ * @param results
+ */
+ private <D extends NumberDistance<?, ?>> void assertSortedByDistance(Collection<? extends DistanceResultPair<D>> results) {
+ // TODO: sort results instead?
+ double dist = -1.0;
+ for(Iterator<? extends DistanceResultPair<D>> it = results.iterator(); it.hasNext();) {
+ double qr = it.next().getDistance().doubleValue();
+ if(qr < dist) {
+ System.err.println("WARNING: results not sorted by distance!");
+ }
+ dist = qr;
+ }
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer<V extends NumberVector<? extends V, ?>> extends PCAFilteredRunner.Parameterizer<V> {
+ @Override
+ protected PCAFilteredAutotuningRunner<V> makeInstance() {
+ return new PCAFilteredAutotuningRunner<V>(covarianceMatrixBuilder, eigenPairFilter, big, small);
+ }
+ }
+} \ No newline at end of file
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 30453f0c..4aa626a9 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -118,7 +118,7 @@ public class PCAFilteredResult extends PCAResult implements ProjectionResult {
for(Iterator<EigenPair> it = strongEigenPairs.iterator(); it.hasNext(); i++) {
EigenPair eigenPair = it.next();
strongEigenvalues[i] = eigenPair.getEigenvalue();
- strongEigenvectors.setColumnVector(i, eigenPair.getEigenvector());
+ strongEigenvectors.setCol(i, eigenPair.getEigenvector());
sumStrongEigenvalues += strongEigenvalues[i];
}
}
@@ -131,7 +131,7 @@ public class PCAFilteredResult extends PCAResult implements ProjectionResult {
for(Iterator<EigenPair> it = weakEigenPairs.iterator(); it.hasNext(); i++) {
EigenPair eigenPair = it.next();
weakEigenvalues[i] = eigenPair.getEigenvalue();
- weakEigenvectors.setColumnVector(i, eigenPair.getEigenvector());
+ weakEigenvectors.setCol(i, eigenPair.getEigenvector());
sumWeakEigenvalues += weakEigenvalues[i];
}
}
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 799502fa..2391446d 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -141,7 +141,7 @@ public class PCAFilteredRunner<V extends NumberVector<? extends V, ?>> extends P
* @return PCA result
*/
@Override
- public <D extends NumberDistance<?, ?>> PCAFilteredResult processQueryResult(Collection<DistanceResultPair<D>> results, Relation<? extends V> database) {
+ public <D extends NumberDistance<?, ?>> PCAFilteredResult processQueryResult(Collection<? extends DistanceResultPair<D>> results, Relation<? extends V> database) {
return processCovarMatrix(covarianceMatrixBuilder.processQueryResults(results, database));
}
@@ -153,7 +153,7 @@ public class PCAFilteredRunner<V extends NumberVector<? extends V, ?>> extends P
@Override
public PCAFilteredResult processCovarMatrix(Matrix covarMatrix) {
// TODO: add support for a different implementation to do EVD?
- EigenvalueDecomposition evd = covarMatrix.eig();
+ EigenvalueDecomposition evd = new EigenvalueDecomposition(covarMatrix);
return processEVD(evd);
}
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 26497645..6969a3a3 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) 2011
+ Copyright (C) 2012
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 21b4304f..661fa5c5 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -113,7 +113,7 @@ public class PCARunner<V extends NumberVector<? extends V, ?>> implements Parame
* @param database the database used
* @return PCA result
*/
- public <D extends NumberDistance<?, ?>> PCAResult processQueryResult(Collection<DistanceResultPair<D>> results, Relation<? extends V> database) {
+ public <D extends NumberDistance<?, ?>> PCAResult processQueryResult(Collection<? extends DistanceResultPair<D>> results, Relation<? extends V> database) {
return processCovarMatrix(covarianceMatrixBuilder.processQueryResults(results, database));
}
@@ -125,7 +125,7 @@ public class PCARunner<V extends NumberVector<? extends V, ?>> implements Parame
*/
public PCAResult processCovarMatrix(Matrix covarMatrix) {
// TODO: add support for a different implementation to do EVD?
- EigenvalueDecomposition evd = covarMatrix.eig();
+ EigenvalueDecomposition evd = new EigenvalueDecomposition(covarMatrix);
return processEVD(evd);
}
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 b0065eae..321c12cc 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) 2011
+ Copyright (C) 2012
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/ProgressiveEigenPairFilter.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/ProgressiveEigenPairFilter.java
index f43ac424..f66a1e96 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) 2011
+ Copyright (C) 2012
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/RelativeEigenPairFilter.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/RelativeEigenPairFilter.java
index 5109b010..59b2b750 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) 2011
+ Copyright (C) 2012
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/SignificantEigenPairFilter.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/SignificantEigenPairFilter.java
index d09b7312..94636553 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) 2011
+ Copyright (C) 2012
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/StandardCovarianceMatrixBuilder.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/StandardCovarianceMatrixBuilder.java
index 393b26ec..2c88d490 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) 2011
+ Copyright (C) 2012
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 57d21ec1..fbca039d 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) 2011
+ Copyright (C) 2012
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/WeightedCovarianceMatrixBuilder.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/WeightedCovarianceMatrixBuilder.java
index 547737fe..db5e8702 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -158,7 +158,7 @@ public class WeightedCovarianceMatrixBuilder<V extends NumberVector<? extends V,
* @return Covariance Matrix
*/
@Override
- public <D extends NumberDistance<?, ?>> Matrix processQueryResults(Collection<DistanceResultPair<D>> results, Relation<? extends V> database, int k) {
+ public <D extends NumberDistance<?, ?>> Matrix processQueryResults(Collection<? extends DistanceResultPair<D>> results, Relation<? extends V> database, int k) {
final int dim = DatabaseUtil.dimensionality(database);
final CovarianceMatrix cmat = new CovarianceMatrix(dim);
@@ -172,7 +172,7 @@ public class WeightedCovarianceMatrixBuilder<V extends NumberVector<? extends V,
double stddev = 0.0;
{
int i = 0;
- for(Iterator<DistanceResultPair<D>> it = results.iterator(); it.hasNext() && i < k; i++) {
+ for(Iterator<? extends DistanceResultPair<D>> it = results.iterator(); it.hasNext() && i < k; i++) {
DistanceResultPair<D> res = it.next();
final double dist;
if(res instanceof DoubleDistanceResultPair) {
@@ -194,7 +194,7 @@ public class WeightedCovarianceMatrixBuilder<V extends NumberVector<? extends V,
// calculate weighted PCA
int i = 0;
- for(Iterator<DistanceResultPair<D>> it = results.iterator(); it.hasNext() && i < k; i++) {
+ for(Iterator<? extends DistanceResultPair<D>> it = results.iterator(); it.hasNext() && i < k; i++) {
DistanceResultPair<? extends NumberDistance<?, ?>> res = it.next();
final double dist;
if(res instanceof DoubleDistanceResultPair) {
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 94b0f5a5..f08a016c 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) 2011
+Copyright (C) 2012
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 b31d15ea..ef089980 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) 2011
+ Copyright (C) 2012
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 71096f05..656406c3 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) 2011
+ Copyright (C) 2012
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.math.linearalgebra.pca.weightfunctions;
*/
import de.lmu.ifi.dbs.elki.math.MathUtil;
+import de.lmu.ifi.dbs.elki.math.statistics.distribution.NormalDistribution;
/**
* Gaussian Error Function Weight function, scaled using stddev. This probably
@@ -42,6 +43,6 @@ public final class ErfcStddevWeight implements WeightFunction {
if(stddev <= 0) {
return 1;
}
- return MathUtil.erfc(MathUtil.SQRTHALF * distance / stddev);
+ return NormalDistribution.erfc(MathUtil.SQRTHALF * distance / stddev);
}
-}
+} \ No newline at end of file
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 1a6cb5b6..6a8783ed 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) 2011
+ Copyright (C) 2012
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.math.linearalgebra.pca.weightfunctions;
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;
/**
* Gaussian Error Function Weight function, scaled such that the result it 0.1
@@ -48,6 +48,6 @@ public final class ErfcWeight implements WeightFunction {
double relativedistance = distance / max;
// the scaling was picked such that getWeight(a,a,0) is 0.1
// since erfc(1.1630871536766736) == 1.0
- return MathUtil.erfc(1.1630871536766736 * relativedistance);
+ return NormalDistribution.erfc(1.1630871536766736 * relativedistance);
}
}
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 979ccaf5..e6cb9951 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) 2011
+ Copyright (C) 2012
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 96077581..0792e764 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) 2011
+ Copyright (C) 2012
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 33ff90c5..f73d4a7d 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) 2011
+ Copyright (C) 2012
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 00eeb8b1..05c3389f 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) 2011
+ Copyright (C) 2012
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 f618c08b..d5843cf1 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) 2011
+ Copyright (C) 2012
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 da1c0a61..740ec8ca 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) 2011
+ Copyright (C) 2012
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 ee17b25b..c4ae9a97 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) 2011
+ Copyright (C) 2012
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 241c2673..38318133 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) 2011
+ Copyright (C) 2012
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 7d9b41ad..372dc016 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) 2011
+ Copyright (C) 2012
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 9755c963..49cb1aca 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) 2011
+ Copyright (C) 2012
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 c3102350..79c9f8a5 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) 2011
+ Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/math/linearalgebra/pca/weightfunctions/package-info.java
index 268a3e89..649a8fb7 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) 2011
+Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/math/package-info.java
index dabeba0e..e01c3e50 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) 2011
+Copyright (C) 2012
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/scales/LinearScale.java b/src/de/lmu/ifi/dbs/elki/math/scales/LinearScale.java
index 8ae18fb5..32015853 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/scales/LinearScale.java
+++ b/src/de/lmu/ifi/dbs/elki/math/scales/LinearScale.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.visualization.scales;
+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) 2011
+ Copyright (C) 2012
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/scales/Scales.java b/src/de/lmu/ifi/dbs/elki/math/scales/Scales.java
index 8f73d617..ffaaffc7 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/scales/Scales.java
+++ b/src/de/lmu/ifi/dbs/elki/math/scales/Scales.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.visualization.scales;
+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) 2011
+ Copyright (C) 2012
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/scales/package-info.java b/src/de/lmu/ifi/dbs/elki/math/scales/package-info.java
index 0db989f8..1047bb0a 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/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) 2011
+Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,4 +24,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.visualization.scales; \ No newline at end of file
+package de.lmu.ifi.dbs.elki.math.scales; \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/AbstractSpatialSorter.java b/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/AbstractSpatialSorter.java
new file mode 100644
index 00000000..942fe64b
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/AbstractSpatialSorter.java
@@ -0,0 +1,144 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.spatial.SpatialComparable;
+
+/**
+ * Abstract base class for spatial sorters, offering shared functionality.
+ *
+ * @author Erich Schubert
+ */
+public abstract class AbstractSpatialSorter implements SpatialSorter {
+ /**
+ * Constructor.
+ */
+ public AbstractSpatialSorter() {
+ super();
+ }
+
+ @Override
+ public <T extends SpatialComparable> void sort(List<T> objs) {
+ double[] mms = computeMinMax(objs);
+ sort(objs, 0, objs.size(), mms);
+ }
+
+ /**
+ * "Pivotize" the list, such that all elements before the given position are
+ * less than, all elements after the position are larger than the threshold
+ * value in the given dimension. (desc inverts the sorting!)
+ *
+ * Only the elments in the interval <tt>[start: end[</tt> are sorted!
+ *
+ * @param objs List of objects
+ * @param start Start of sorting range
+ * @param end End of sorting range
+ * @param dim Dimension to sort by
+ * @param threshold Threshold value
+ * @param desc Inversion flag
+ * @return Pivot position
+ */
+ protected <T extends SpatialComparable> int pivotizeList1D(List<T> objs, int start, int end, int dim, double threshold, boolean desc) {
+ threshold = 2 * threshold; // faster
+ int s = start, e = end;
+ while(s < e) {
+ if(!desc) {
+ double sminmax = getMinPlusMaxObject(objs, s, dim);
+ while((sminmax < threshold) && s + 1 <= e && s + 1 < end) {
+ s++;
+ sminmax = getMinPlusMaxObject(objs, s, dim);
+ }
+ double eminmax = getMinPlusMaxObject(objs, e - 1, dim);
+ while((eminmax >= threshold) && s < e - 1 && start < e - 1) {
+ e--;
+ eminmax = getMinPlusMaxObject(objs, e - 1, dim);
+ }
+ }
+ else {
+ double sminmax = getMinPlusMaxObject(objs, s, dim);
+ while((sminmax > threshold) && s + 1 <= e && s + 1 < end) {
+ s++;
+ sminmax = getMinPlusMaxObject(objs, s, dim);
+ }
+ double eminmax = getMinPlusMaxObject(objs, e - 1, dim);
+ while((eminmax <= threshold) && s < e - 1 && start < e - 1) {
+ e--;
+ eminmax = getMinPlusMaxObject(objs, e - 1, dim);
+ }
+ }
+ if(s >= e) {
+ assert (s == e);
+ break;
+ }
+ // Swap
+ objs.set(s, objs.set(e - 1, objs.get(s)));
+ s++;
+ e--;
+ }
+ return e;
+ }
+
+ /**
+ * Compute getMin(dim) + getMax(dim) for the spatial object
+ *
+ * @param objs Objects
+ * @param s index
+ * @param dim Dimensionality
+ * @return Min+Max
+ */
+ private double getMinPlusMaxObject(List<? extends SpatialComparable> objs, int s, int dim) {
+ SpatialComparable sobj = objs.get(s);
+ return sobj.getMin(dim) + sobj.getMax(dim);
+ }
+
+ /**
+ * Compute the minimum and maximum for each dimension.
+ *
+ * @param objs Objects
+ * @return Array of min, max pairs (length = 2 * dim)
+ */
+ public static <T extends SpatialComparable> double[] computeMinMax(List<T> objs) {
+ final int dim = objs.get(0).getDimensionality();
+ // Compute min and max for each dimension:
+ double[] mm = new double[dim * 2];
+ {
+ for(int d = 0; d < dim; d++) {
+ mm[d * 2] = Double.POSITIVE_INFINITY;
+ mm[d * 2 + 1] = Double.NEGATIVE_INFINITY;
+ }
+ for(SpatialComparable obj : objs) {
+ for(int d = 0; d < dim; d++) {
+ mm[2 * d] = Math.min(mm[2 * d], obj.getMin(d + 1));
+ mm[2 * d + 1] = Math.max(mm[2 * d + 1], obj.getMax(d + 1));
+ }
+ }
+ for(int d = 0; d < dim; d++) {
+ assert (mm[2 * d] <= mm[2 * d + 1]);
+ }
+ }
+ return mm;
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/BinarySplitSpatialSorter.java b/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/BinarySplitSpatialSorter.java
new file mode 100644
index 00000000..0b45022c
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/BinarySplitSpatialSorter.java
@@ -0,0 +1,112 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.utilities.datastructures.QuickSelect;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+
+/**
+ * Spatially sort the data set by repetitive binary splitting, circulating
+ * through the dimensions. This is essentially the bulk-loading proposed for the
+ * k-d-tree, as it will produce a perfectly balanced k-d-tree. The resulting
+ * order is the sequence in which objects would then be stored in the k-d-tree.
+ *
+ * Note that when using this for bulk-loading an R-tree, the result will
+ * <em>not</em> be a k-d-tree, not even remotely similar, as the splits are not
+ * preserved.
+ *
+ * Reference (for the bulk-loading):
+ * <p>
+ * J. L. Bentley<br/>
+ * Multidimensional binary search trees used for associative searching<br/>
+ * Communications of the ACM, Vol. 18 Issue 9, Sept. 1975
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@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 BinarySplitSpatialSorter extends AbstractSpatialSorter {
+ /**
+ * Constructor.
+ */
+ public BinarySplitSpatialSorter() {
+ super();
+ }
+
+ @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());
+ }
+
+ /**
+ * Sort the array using a binary split in dimension curdim, then recurse with
+ * the next dimension.
+ *
+ * @param objs List of objects
+ * @param start Interval start
+ * @param end Interval end (exclusive)
+ * @param curdim Current dimension
+ * @param dims Number of dimensions
+ * @param comp Comparator to use
+ */
+ private <T extends SpatialComparable> void binarySplitSort(List<T> objs, final int start, final int end, int curdim, final int dims, DimC comp) {
+ final int mid = start + ((end - start) >>> 1);
+ // Make invariant
+ comp.dim = curdim;
+ QuickSelect.quickSelect(objs, comp, start, end, mid);
+ // Recurse
+ final int nextdim = (curdim % dims) + 1;
+ if(start < mid - 1) {
+ binarySplitSort(objs, start, mid, nextdim, dims, comp);
+ }
+ if(mid + 2 < end) {
+ binarySplitSort(objs, mid + 1, end, nextdim, 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> {
+ 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
new file mode 100644
index 00000000..82e41337
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/HilbertSpatialSorter.java
@@ -0,0 +1,346 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.List;
+
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.utilities.BitsUtil;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+
+/**
+ * Sort object along the Hilbert Space Filling curve by mapping them to their
+ * Hilbert numbers and sorting them.
+ *
+ * Objects are mapped using 31 bits per dimension.
+ *
+ * Reference:
+ * <p>
+ * D. Hilbert<br />
+ * Über die stetige Abbildung einer Linie auf ein Flächenstück<br />
+ * In: Mathematische Annalen, 38(3)
+ * </p>
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.uses HilbertRef
+ */
+@Reference(authors = "D. Hilbert", title = "Über die stetige Abbildung einer Linie auf ein Flächenstück", booktitle = "Mathematische Annalen, 38(3)")
+public class HilbertSpatialSorter extends AbstractSpatialSorter {
+ /**
+ * Constructor.
+ */
+ public HilbertSpatialSorter() {
+ super();
+ }
+
+ @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);
+ int[] buf = new int[dim];
+ for(int i = start; i < end; i++) {
+ T v = objs.get(i);
+ // Convert into integers
+ for(int d = 0; d < dim; d++) {
+ double val = (v.getMin(d + 1) + v.getMax(d + 1)) / 2;
+ val = Integer.MAX_VALUE * ((val - minmax[2 * d]) / (minmax[2 * d + 1] - minmax[2 * d]));
+ buf[d] = (int) val;
+ }
+ tmp.add(new HilbertRef<T>(v, coordinatesToHilbert(buf, Integer.SIZE - 1, 1)));
+ }
+ // Sort and copy back
+ Collections.sort(tmp);
+ for(int i = start; i < end; i++) {
+ objs.set(i, tmp.get(i - start).vec);
+ }
+ }
+
+ /**
+ * Object used in spatial sorting, combining the spatial object and the object
+ * ID.
+ *
+ * @author Erich Schubert
+ */
+ private static class HilbertRef<T extends SpatialComparable> implements Comparable<HilbertRef<T>> {
+ /**
+ * The referenced object
+ */
+ protected T vec;
+
+ /**
+ * Hilbert representation
+ */
+ protected long[] bits;
+
+ /**
+ * Constructor.
+ *
+ * @param vec
+ */
+ protected HilbertRef(T vec, long[] bits) {
+ super();
+ this.vec = vec;
+ this.bits = bits;
+ }
+
+ @Override
+ public int compareTo(HilbertRef<T> o) {
+ return BitsUtil.compare(this.bits, o.bits);
+ }
+ }
+
+ /**
+ * Interleave one long per dimension (using the "bitsperdim" highest bits) to
+ * a hilbert address.
+ *
+ * @param coords Original coordinates
+ * @param bitsperdim Number of bits to use.
+ * @return Hilbert address
+ */
+ public static long[] coordinatesToHilbert(long[] coords, int bitsperdim, int offset) {
+ final int numdim = coords.length;
+ final int numbits = numdim * bitsperdim;
+ final long[] output = BitsUtil.zero(numbits);
+
+ int rotation = 0;
+ long[] refl = BitsUtil.zero(numdim);
+ for(int i = 0; i < bitsperdim; i++) {
+ final long[] hist = interleaveBits(coords, i + offset);
+ // System.err.println(BitsUtil.toString(hist,
+ // numdim)+" rot:"+rotation+" refl: "+BitsUtil.toString(refl, numdim));
+ final long[] bits = BitsUtil.copy(hist);
+ BitsUtil.xorI(bits, refl);
+ BitsUtil.cycleRightI(bits, rotation, numdim);
+ final int nextrot = (rotation + BitsUtil.numberOfTrailingZerosSigned(bits) + 2) % numdim;
+ BitsUtil.invgrayI(bits);
+ BitsUtil.orI(output, bits, numbits - (i + 1) * numdim);
+ // System.err.println(BitsUtil.toString(output,
+ // numbits)+" bits: "+BitsUtil.toString(bits, numdim));
+ refl = hist;
+ BitsUtil.flipI(refl, rotation);
+ if(!BitsUtil.get(bits, 0)) {
+ BitsUtil.flipI(refl, (nextrot - 1 + numdim) % numdim);
+ }
+ rotation = nextrot;
+ }
+
+ return output;
+ }
+
+ /**
+ * Interleave one int per dimension (using the "bitsperdim" highest bits) to
+ * a hilbert address.
+ *
+ * @param coords Original coordinates
+ * @param bitsperdim Number of bits to use.
+ * @return Hilbert address
+ */
+ public static long[] coordinatesToHilbert(int[] coords, int bitsperdim, int offset) {
+ final int numdim = coords.length;
+ final int numbits = numdim * bitsperdim;
+ final long[] output = BitsUtil.zero(numbits);
+
+ int rotation = 0;
+ long[] refl = BitsUtil.zero(numdim);
+ for(int i = 0; i < bitsperdim; i++) {
+ final long[] hist = interleaveBits(coords, i + offset);
+ // System.err.println(BitsUtil.toString(hist,
+ // numdim)+" rot:"+rotation+" refl: "+BitsUtil.toString(refl, numdim));
+ final long[] bits = BitsUtil.copy(hist);
+ BitsUtil.xorI(bits, refl);
+ BitsUtil.cycleRightI(bits, rotation, numdim);
+ final int nextrot = (rotation + BitsUtil.numberOfTrailingZerosSigned(bits) + 2) % numdim;
+ BitsUtil.invgrayI(bits);
+ BitsUtil.orI(output, bits, numbits - (i + 1) * numdim);
+ // System.err.println(BitsUtil.toString(output,
+ // numbits)+" bits: "+BitsUtil.toString(bits, numdim));
+ refl = hist;
+ BitsUtil.flipI(refl, rotation);
+ if(!BitsUtil.get(bits, 0)) {
+ BitsUtil.flipI(refl, (nextrot - 1 + numdim) % numdim);
+ }
+ rotation = nextrot;
+ }
+
+ return output;
+ }
+
+ /**
+ * Interleave one short per dimension (using the "bitsperdim" highest bits) to
+ * a hilbert address.
+ *
+ * @param coords Original coordinates
+ * @param bitsperdim Number of bits to use.
+ * @return Hilbert address
+ */
+ public static long[] coordinatesToHilbert(short[] coords, int bitsperdim, int offset) {
+ final int numdim = coords.length;
+ final int numbits = numdim * bitsperdim;
+ final long[] output = BitsUtil.zero(numbits);
+
+ int rotation = 0;
+ long[] refl = BitsUtil.zero(numdim);
+ for(int i = 0; i < bitsperdim; i++) {
+ final long[] hist = interleaveBits(coords, i + offset);
+ // System.err.println(BitsUtil.toString(hist,
+ // numdim)+" rot:"+rotation+" refl: "+BitsUtil.toString(refl, numdim));
+ final long[] bits = BitsUtil.copy(hist);
+ BitsUtil.xorI(bits, refl);
+ BitsUtil.cycleRightI(bits, rotation, numdim);
+ final int nextrot = (rotation + BitsUtil.numberOfTrailingZerosSigned(bits) + 2) % numdim;
+ BitsUtil.invgrayI(bits);
+ BitsUtil.orI(output, bits, numbits - (i + 1) * numdim);
+ // System.err.println(BitsUtil.toString(output,
+ // numbits)+" bits: "+BitsUtil.toString(bits, numdim));
+ refl = hist;
+ BitsUtil.flipI(refl, rotation);
+ if(!BitsUtil.get(bits, 0)) {
+ BitsUtil.flipI(refl, (nextrot - 1 + numdim) % numdim);
+ }
+ rotation = nextrot;
+ }
+
+ return output;
+ }
+
+ /**
+ * Interleave one byte per dimension (using the "bitsperdim" highest bits) to
+ * a hilbert address.
+ *
+ * @param coords Original coordinates
+ * @param bitsperdim Number of bits to use.
+ * @return Hilbert address
+ */
+ public static long[] coordinatesToHilbert(byte[] coords, int bitsperdim, int offset) {
+ final int numdim = coords.length;
+ final int numbits = numdim * bitsperdim;
+ final long[] output = BitsUtil.zero(numbits);
+
+ int rotation = 0;
+ long[] refl = BitsUtil.zero(numdim);
+ for(int i = 0; i < bitsperdim; i++) {
+ final long[] hist = interleaveBits(coords, i + offset);
+ // System.err.println(BitsUtil.toString(hist,
+ // numdim)+" rot:"+rotation+" refl: "+BitsUtil.toString(refl, numdim));
+ final long[] bits = BitsUtil.copy(hist);
+ BitsUtil.xorI(bits, refl);
+ BitsUtil.cycleRightI(bits, rotation, numdim);
+ final int nextrot = (rotation + BitsUtil.numberOfTrailingZerosSigned(bits) + 2) % numdim;
+ BitsUtil.invgrayI(bits);
+ BitsUtil.orI(output, bits, numbits - (i + 1) * numdim);
+ // System.err.println(BitsUtil.toString(output,
+ // numbits)+" bits: "+BitsUtil.toString(bits, numdim));
+ refl = hist;
+ BitsUtil.flipI(refl, rotation);
+ if(!BitsUtil.get(bits, 0)) {
+ BitsUtil.flipI(refl, (nextrot - 1 + numdim) % numdim);
+ }
+ rotation = nextrot;
+ }
+
+ return output;
+ }
+
+ /**
+ * Select the "iter" highest bit from each dimension.
+ *
+ * @param coords Input coordinates
+ * @param iter Bit position (from highest position)
+ * @return One bit per dimension
+ */
+ public static long[] interleaveBits(long[] coords, int iter) {
+ final int numdim = coords.length;
+ final long[] bitset = BitsUtil.zero(numdim);
+ // convert longValues into zValues
+ final long mask = 1L << 63 - iter;
+ for(int dim = 0; dim < numdim; dim++) {
+ if((coords[dim] & mask) != 0) {
+ BitsUtil.setI(bitset, dim);
+ }
+ }
+ return bitset;
+ }
+
+ /**
+ * Select the "iter" highest bit from each dimension.
+ *
+ * @param coords Input coordinates
+ * @param iter Bit position (from highest position)
+ * @return One bit per dimension
+ */
+ public static long[] interleaveBits(int[] coords, int iter) {
+ final int numdim = coords.length;
+ final long[] bitset = BitsUtil.zero(numdim);
+ // convert longValues into zValues
+ final long mask = 1L << 31 - iter;
+ for(int dim = 0; dim < numdim; dim++) {
+ if((coords[dim] & mask) != 0) {
+ BitsUtil.setI(bitset, dim);
+ }
+ }
+ return bitset;
+ }
+
+ /**
+ * Select the "iter" highest bit from each dimension.
+ *
+ * @param coords Input coordinates
+ * @param iter Bit position (from highest position)
+ * @return One bit per dimension
+ */
+ public static long[] interleaveBits(short[] coords, int iter) {
+ final int numdim = coords.length;
+ final long[] bitset = BitsUtil.zero(numdim);
+ // convert longValues into zValues
+ final long mask = 1L << 15 - iter;
+ for(int dim = 0; dim < numdim; dim++) {
+ if((coords[dim] & mask) != 0) {
+ BitsUtil.setI(bitset, dim);
+ }
+ }
+ return bitset;
+ }
+
+ /**
+ * Select the "iter" highest bit from each dimension.
+ *
+ * @param coords Input coordinates
+ * @param iter Bit position (from highest position)
+ * @return One bit per dimension
+ */
+ public static long[] interleaveBits(byte[] coords, int iter) {
+ final int numdim = coords.length;
+ final long[] bitset = BitsUtil.zero(numdim);
+ // convert longValues into zValues
+ final long mask = 1L << 7 - iter;
+ for(int dim = 0; dim < numdim; dim++) {
+ if((coords[dim] & mask) != 0) {
+ BitsUtil.setI(bitset, dim);
+ }
+ }
+ return bitset;
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/PeanoSpatialSorter.java b/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/PeanoSpatialSorter.java
new file mode 100644
index 00000000..50cf1946
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/PeanoSpatialSorter.java
@@ -0,0 +1,149 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.List;
+
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+
+/**
+ * Bulk-load an R-tree index by presorting the objects with their position on
+ * the Peano curve.
+ *
+ * The basic shape of this space-filling curve looks like this:
+ *
+ * <pre>
+ * 3---4 9
+ * | | |
+ * 2 5 8
+ * | | |
+ * 1 6---7
+ * </pre>
+ *
+ * Which then expands to the next level as:
+ *
+ * <pre>
+ * +-+ +-+ +-+ +-+ E
+ * | | | | | | | | |
+ * | +-+ +-+ | | +-+
+ * | | |
+ * | +-+ +-+ | | +-+
+ * | | | | | | | | |
+ * +-+ | | +-+ +-+ |
+ * | | |
+ * +-+ | | +-+ +-+ |
+ * | | | | | | | | |
+ * S +-+ +-+ +-+ +-+
+ * </pre>
+ *
+ * and so on.
+ *
+ * Reference:
+ * <p>
+ * G. Peano<br />
+ * Sur une courbe, qui remplit toute une aire plane<br />
+ * Mathematische Annalen, 36(1)
+ * </p>
+ *
+ * @author Erich Schubert
+ */
+@Reference(authors = "G. Peano", title = "Sur une courbe, qui remplit toute une aire plane", booktitle = "Mathematische Annalen, 36(1)")
+public class PeanoSpatialSorter extends AbstractSpatialSorter {
+ /**
+ * Constructor.
+ */
+ public PeanoSpatialSorter() {
+ super();
+ }
+
+ @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);
+ }
+
+ /**
+ * Sort by Peano curve.
+ *
+ * @param objs Objects
+ * @param start Start index
+ * @param end End
+ * @param mms Minmax values
+ * @param dim 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) {
+ // Find the splitting points.
+ final double min = mms[2 * dim], max = mms[2 * dim + 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) {
+ ok = true;
+ break;
+ }
+ }
+ if(!ok) {
+ return;
+ }
+ }
+ final boolean inv = bits.get(dim) ^ desc;
+ // Split the data set into three parts
+ int fsplit, ssplit;
+ if(!inv) {
+ fsplit = pivotizeList1D(objs, start, end, dim + 1, tfirst, false);
+ ssplit = (fsplit < end - 1) ? pivotizeList1D(objs, fsplit, end, dim + 1, tsecond, false) : fsplit;
+ }
+ else {
+ fsplit = pivotizeList1D(objs, start, end, dim + 1, tsecond, true);
+ ssplit = (fsplit < end - 1) ? pivotizeList1D(objs, fsplit, end, dim + 1, tfirst, true) : fsplit;
+ }
+ int nextdim = (dim + 1) % objs.get(0).getDimensionality();
+ // 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);
+ }
+ 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);
+ }
+ 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);
+ }
+ // Restore ranges
+ mms[2 * dim] = min;
+ mms[2 * dim + 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
new file mode 100644
index 00000000..2473dff5
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/SpatialSorter.java
@@ -0,0 +1,54 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.spatial.SpatialComparable;
+
+/**
+ * Interface for spatial sorting - ZCurves, Peano curves, Hilbert curves, ...
+ *
+ * @author Erich Schubert
+ */
+public interface SpatialSorter {
+ /**
+ * Partitions the specified feature vectors
+ *
+ * @param <T> actual type we sort
+ * @param objs the spatial objects to be sorted
+ */
+ public <T extends SpatialComparable> void sort(List<T> objs);
+
+ /**
+ * Sort part of the list (start to end).
+ *
+ * @param <T> actual type we sort
+ * @param objs the spatial objects to be sorted
+ * @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
+ */
+ public <T extends SpatialComparable> void sort(List<T> objs, int start, int end, double[] minmax);
+}
diff --git a/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/ZCurve.java b/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/ZCurve.java
index 69dd8ff6..38f45aef 100644
--- a/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/ZCurve.java
+++ b/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/ZCurve.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) 2011
+ Copyright (C) 2012
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/ZCurveSpatialSorter.java b/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/ZCurveSpatialSorter.java
new file mode 100644
index 00000000..b8fc63bd
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/spacefillingcurves/ZCurveSpatialSorter.java
@@ -0,0 +1,91 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.spatial.SpatialComparable;
+
+/**
+ * Class to sort the data set by their Z-index, without doing a full
+ * materialization of the Z indexes.
+ *
+ * @author Erich Schubert
+ */
+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);
+ }
+
+ /**
+ * The actual Z sorting function
+ *
+ * @param objs Objects to sort
+ * @param start Start
+ * @param end End
+ * @param mms Min-Max value ranges
+ * @param dim Current dimension
+ */
+ protected <T extends SpatialComparable> void zSort(List<T> objs, int start, int end, double[] mms, int dim) {
+ // Find the splitting points.
+ final double min = mms[2 * dim], max = mms[2 * dim + 1];
+ double spos = (min + max) / 2.;
+ // Safeguard against duplicate points:
+ 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]));
+ ok = true;
+ break;
+ }
+ }
+ if(!ok) {
+ return;
+ }
+ }
+ int split = pivotizeList1D(objs, start, end, dim + 1, 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);
+ }
+ if(split < end - 1) {
+ mms[2 * dim] = spos;
+ mms[2 * dim + 1] = max;
+ zSort(objs, split, end, mms, nextdim);
+ }
+ // Restore ranges
+ mms[2 * dim] = min;
+ mms[2 * dim + 1] = max;
+ // FIXME: implement completely and test.
+ }
+} \ No newline at end of file
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 c3bf1766..9fb9494a 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) 2011
+Copyright (C) 2012
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/EpanechnikovKernelDensityFunction.java b/src/de/lmu/ifi/dbs/elki/math/statistics/EpanechnikovKernelDensityFunction.java
index 0b48a69e..ed9d8d58 100644
--- a/src/de/lmu/ifi/dbs/elki/math/statistics/EpanechnikovKernelDensityFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/EpanechnikovKernelDensityFunction.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) 2011
+ Copyright (C) 2012
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/GaussianKernelDensityFunction.java b/src/de/lmu/ifi/dbs/elki/math/statistics/GaussianKernelDensityFunction.java
index 7adf8ee1..744a9108 100644
--- a/src/de/lmu/ifi/dbs/elki/math/statistics/GaussianKernelDensityFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/GaussianKernelDensityFunction.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) 2011
+ Copyright (C) 2012
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 398e6927..3bb0e1f6 100644
--- a/src/de/lmu/ifi/dbs/elki/math/statistics/KernelDensityEstimator.java
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/KernelDensityEstimator.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) 2011
+ Copyright (C) 2012
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/KernelDensityFunction.java b/src/de/lmu/ifi/dbs/elki/math/statistics/KernelDensityFunction.java
index 4c9100fd..29718fcb 100644
--- a/src/de/lmu/ifi/dbs/elki/math/statistics/KernelDensityFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/KernelDensityFunction.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) 2011
+ Copyright (C) 2012
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/LinearRegression.java b/src/de/lmu/ifi/dbs/elki/math/statistics/LinearRegression.java
index f28986f0..231b2071 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) 2011
+ Copyright (C) 2012
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 90f80135..0e674146 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -139,14 +139,10 @@ public class MultipleLinearRegression {
@Override
public String toString() {
StringBuffer msg = new StringBuffer();
- msg.append("\nx = ");
- msg.append(FormatUtil.format(x, 9, 4));
- msg.append("\ny = ");
- msg.append(FormatUtil.format(y, 9, 4));
- msg.append("\nb = ");
- msg.append(FormatUtil.format(b, 9, 4));
- msg.append("\ne = ");
- msg.append(FormatUtil.format(e, 9, 4));
+ msg.append("x = ").append(FormatUtil.format(x, 9, 4));
+ msg.append("\ny = ").append(FormatUtil.format(y, 9, 4));
+ msg.append("\nb = ").append(FormatUtil.format(b, 9, 4));
+ msg.append("\ne = ").append(FormatUtil.format(e, 9, 4));
msg.append("error variance = ").append(FormatUtil.format(variance, 4));
return msg.toString();
}
@@ -203,7 +199,7 @@ public class MultipleLinearRegression {
* @return the estimation of y
*/
public double estimateY(Matrix x) {
- return x.times(b).get(0, 0);
+ return x.times(b).get(0);
}
/**
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 1b785f75..b1bfe31b 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -62,7 +62,7 @@ public class PolynomialRegression extends MultipleLinearRegression {
}
private static Matrix xMatrix(Vector x, int p) {
- int n = x.getRowDimensionality();
+ int n = x.getDimensionality();
Matrix result = new Matrix(n, p + 1);
for(int i = 0; i < n; i++) {
@@ -79,7 +79,7 @@ public class PolynomialRegression extends MultipleLinearRegression {
* @return the adapted coefficient of determination
*/
public double adaptedCoefficientOfDetermination() {
- int n = getEstimatedResiduals().getRowDimensionality();
+ int n = getEstimatedResiduals().getDimensionality();
return 1.0 - ((n - 1.0) / (n * 1.0 - p)) * (1 - coefficientOfDetermination());
}
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/QuickSelect.java b/src/de/lmu/ifi/dbs/elki/math/statistics/QuickSelect.java
deleted file mode 100644
index efacd395..00000000
--- a/src/de/lmu/ifi/dbs/elki/math/statistics/QuickSelect.java
+++ /dev/null
@@ -1,231 +0,0 @@
-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) 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/>.
- */
-
-
-/**
- * QuickSelect computes ("selects") the element at a given rank and can be used
- * to compute Medians and arbitrary quantiles by computing the appropriate rank.
- *
- * This algorithm is essentially an incomplete QuickSort that only descends into
- * that part of the data that we are interested in, and also attributed to
- * Charles Antony Richard Hoare
- *
- * @author Erich Schubert
- */
-public class QuickSelect {
- /**
- * For small arrays, use a simpler method:
- */
- private static final int SMALL = 10;
-
- /**
- * QuickSelect is essentially quicksort, except that we only "sort" that half
- * of the array that we are interested in.
- *
- * Note: the array is <b>modified</b> by this.
- *
- * @param data Data to process
- * @param rank Rank position that we are interested in (integer!)
- * @return Value at the given rank
- */
- public static double quickSelect(double[] data, int rank) {
- quickSelect(data, 0, data.length - 1, rank);
- return data[rank];
- }
-
- /**
- * Compute the median of an array efficiently using the QuickSelect method.
- *
- * Note: the array is <b>modified</b> by this.
- *
- * @param data Data to process
- * @return Median value
- */
- public static double median(double[] data) {
- return median(data, 0, data.length - 1);
- }
-
- /**
- * Compute the median of an array efficiently using the QuickSelect method.
- *
- * Note: the array is <b>modified</b> by this.
- *
- * @param data Data to process
- * @param begin Begin of valid values
- * @param end End of valid values (inclusive!)
- * @return Median value
- */
- public static double median(double[] data, int begin, int end) {
- final int length = (end + 1) - begin;
- assert (length > 0);
- // Integer division is "floor" since we are non-negative.
- final int left = begin + (length - 1) / 2;
- quickSelect(data, begin, end, left);
- if(length % 2 == 1) {
- return data[left];
- }
- else {
- quickSelect(data, begin, end, left + 1);
- return data[left] + (data[left + 1] - data[left]) / 2;
- }
- }
-
- /**
- * Compute the median of an array efficiently using the QuickSelect method.
- *
- * Note: the array is <b>modified</b> by this.
- *
- * @param data Data to process
- * @param quant Quantile to compute
- * @return Value at quantile
- */
- public static double quantile(double[] data, double quant) {
- return quantile(data, 0, data.length - 1, quant);
- }
-
- /**
- * Compute the median of an array efficiently using the QuickSelect method.
- *
- * Note: the array is <b>modified</b> by this.
- *
- * @param data Data to process
- * @param begin Begin of valid values
- * @param end End of valid values (inclusive!)
- * @param quant Quantile to compute
- * @return Value at quantile
- */
- public static double quantile(double[] data, int begin, int end, double quant) {
- final int length = (end + 1) - begin;
- assert (length > 0) : "Quantile on empty set?";
- // Integer division is "floor" since we are non-negative.
- final double dleft = begin + (length - 1) * quant;
- final int ileft = (int) Math.floor(dleft);
- final double err = dleft - ileft;
-
- quickSelect(data, begin, end, ileft);
- if(err <= Double.MIN_NORMAL) {
- return data[ileft];
- }
- else {
- quickSelect(data, begin, end, ileft + 1);
- // Mix:
- double mix = data[ileft] + (data[ileft + 1] - data[ileft]) * err;
- return mix;
- }
- }
-
- /**
- * 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 (inclusive)
- * @param rank rank position we are interested in (starting at 0)
- */
- public static void quickSelect(double[] data, int start, int end, int rank) {
- // Optimization for small arrays
- // This also ensures a minimum size below
- 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) / 2;
- if(data[start] > data[middle]) {
- swap(data, start, middle);
- }
- if(data[start] > data[end]) {
- swap(data, start, end);
- }
- if(data[middle] > data[end]) {
- swap(data, middle, end);
- }
- // 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 - 1);
-
- // Begin partitioning
- int i = start + 1, j = end - 2;
- // This is classic quicksort stuff
- while(true) {
- while(data[i] <= pivot && i <= j) {
- i++;
- }
- while(data[j] >= pivot && j >= i) {
- j--;
- }
- if(i >= j) {
- break;
- }
- swap(data, i, j);
- }
-
- // Move pivot (former middle element) back into the appropriate place
- swap(data, i, end - 1);
-
- // In contrast to quicksort, we only need to recurse into the half we are
- // interested in.
- if(rank < i) {
- quickSelect(data, start, i - 1, rank);
- }
- else if(rank > i) {
- quickSelect(data, i + 1, end, rank);
- }
- }
-
- /**
- * 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(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--) {
- swap(data, j, j - 1);
- }
- }
- }
-
- /**
- * The usual swap method.
- *
- * @param data Array
- * @param a First index
- * @param b Second index
- */
- private static final void swap(double[] data, int a, int b) {
- double tmp = data[a];
- data[a] = data[b];
- data[b] = tmp;
- }
-} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/StudentDistribution.java b/src/de/lmu/ifi/dbs/elki/math/statistics/StudentDistribution.java
index e9ad4a00..a8f45f9d 100644
--- a/src/de/lmu/ifi/dbs/elki/math/statistics/StudentDistribution.java
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/StudentDistribution.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,8 +23,10 @@ package de.lmu.ifi.dbs.elki.math.statistics;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.HashMap;
-import java.util.Map;
+import gnu.trove.map.TDoubleDoubleMap;
+import gnu.trove.map.TIntObjectMap;
+import gnu.trove.map.hash.TDoubleDoubleHashMap;
+import gnu.trove.map.hash.TIntObjectHashMap;
/**
* Tabelarizes the values for student distribution.
@@ -125,7 +127,7 @@ public class StudentDistribution {
/**
* Holds the t-values.
*/
- private static Map<Integer, Map<Double, Double>> tValues = new HashMap<Integer, Map<Double, Double>>();
+ private static TIntObjectMap<TDoubleDoubleMap> tValues = new TIntObjectHashMap<TDoubleDoubleMap>();
static {
put(31, new double[] { 0.2533, 0.8416, 1.2816, 1.6449, 1.96, 2.3263, 2.5758, 3.0903, 3.2906 });
@@ -142,7 +144,7 @@ public class StudentDistribution {
if(n > 30) {
n = 31;
}
- Map<Double, Double> map = tValues.get(n);
+ TDoubleDoubleMap map = tValues.get(n);
if(map == null) {
throw new IllegalArgumentException("t-values for n=" + n + " not yet tabularized!");
}
@@ -162,7 +164,7 @@ public class StudentDistribution {
* @param values the t-values
*/
private static void put(int n, double[] values) {
- Map<Double, Double> map = new HashMap<Double, Double>();
+ TDoubleDoubleMap map = new TDoubleDoubleHashMap();
map.put(_6000, values[0]);
map.put(_8000, values[1]);
map.put(_9000, values[2]);
diff --git a/src/de/lmu/ifi/dbs/elki/math/statistics/TriangularKernelDensityFunction.java b/src/de/lmu/ifi/dbs/elki/math/statistics/TriangularKernelDensityFunction.java
index 7beb17c3..e3c23b2a 100644
--- a/src/de/lmu/ifi/dbs/elki/math/statistics/TriangularKernelDensityFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/TriangularKernelDensityFunction.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) 2011
+ Copyright (C) 2012
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/UniformKernelDensityFunction.java b/src/de/lmu/ifi/dbs/elki/math/statistics/UniformKernelDensityFunction.java
index 2f000736..8d85528f 100644
--- a/src/de/lmu/ifi/dbs/elki/math/statistics/UniformKernelDensityFunction.java
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/UniformKernelDensityFunction.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) 2011
+ Copyright (C) 2012
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/distribution/ChiDistribution.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/ChiDistribution.java
new file mode 100644
index 00000000..c561c4cd
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/ChiDistribution.java
@@ -0,0 +1,92 @@
+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/>.
+ */
+
+/**
+ * Chi distribution.
+ *
+ * @author Erich Schubert
+ */
+public class ChiDistribution implements Distribution {
+ /**
+ * Degrees of freedom. Usually integer.
+ */
+ private double dof;
+
+ /**
+ * Chi squared distribution (for random generation)
+ */
+ private ChiSquaredDistribution chisq;
+
+ /**
+ * Constructor.
+ *
+ * @param dof Degrees of freedom. Usually integer.
+ */
+ public ChiDistribution(double dof) {
+ super();
+ this.dof = dof;
+ this.chisq = new ChiSquaredDistribution(dof);
+ }
+
+ @Override
+ public double nextRandom() {
+ return Math.sqrt(chisq.nextRandom());
+ }
+
+ @Override
+ public double pdf(double val) {
+ return pdf(val, dof);
+ }
+
+ /**
+ * PDF function
+ *
+ * @param val Value
+ * @param dof Degrees of freedom
+ * @return Pdf value
+ */
+ public static double pdf(double val, double dof) {
+ if(val < 0) {
+ return 0.0;
+ }
+ return Math.sqrt(ChiSquaredDistribution.pdf(val, dof));
+ }
+
+ @Override
+ public double cdf(double val) {
+ return cdf(val, dof);
+ }
+
+ /**
+ * Cumulative density function.
+ *
+ * @param val Value
+ * @param dof Degrees of freedom.
+ * @return CDF value
+ */
+ public static double cdf(double val, double dof) {
+ return GammaDistribution.regularizedGammaP(dof / 2, val * val / 2);
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..0ab39c78
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/ChiSquaredDistribution.java
@@ -0,0 +1,72 @@
+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/>.
+ */
+
+/**
+ * Chi-Squared distribution (a specialization of the Gamma distribution).
+ *
+ * @author Erich Schubert
+ */
+public class ChiSquaredDistribution extends GammaDistribution {
+ /**
+ * Constructor.
+ *
+ * @param dof Degrees of freedom.
+ */
+ public ChiSquaredDistribution(double dof) {
+ super(.5 * dof, 2.0);
+ }
+
+ /**
+ * The CDF, static version.
+ *
+ * @param val Value
+ * @param dof Degrees of freedom.
+ * @return cdf value
+ */
+ public static double cdf(double val, double dof) {
+ return regularizedGammaP(.5 * dof, .5 * val);
+ }
+
+ /**
+ * Chi-Squared distribution PDF (with 0.0 for x &lt; 0)
+ *
+ * @param x query value
+ * @param dof Degrees of freedom.
+ * @return probability density
+ */
+ public static double pdf(double x, double dof) {
+ if(x <= 0) {
+ return 0.0;
+ }
+ if(x == 0) {
+ return 0.0;
+ }
+ final double k = dof / 2;
+ if(k == 1.0) {
+ 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;
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..1f36dd4a
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/ConstantDistribution.java
@@ -0,0 +1,61 @@
+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/>.
+ */
+
+/**
+ * Pseudo distribution, that has a unique constant value.
+ *
+ * @author Erich Schubert
+ */
+public class ConstantDistribution implements Distribution {
+ /**
+ * The constant
+ */
+ final double c;
+
+ /**
+ * Constructor.
+ *
+ * @param c Constant
+ */
+ public ConstantDistribution(double c) {
+ super();
+ this.c = c;
+ }
+
+ @Override
+ public double nextRandom() {
+ return c;
+ }
+
+ @Override
+ public double pdf(double val) {
+ return (val == c) ? 1 : 0;
+ }
+
+ @Override
+ public double cdf(double val) {
+ return (val >= c) ? 1.0 : 0.0;
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/distribution/Distribution.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/Distribution.java
index f93a6459..290e6434 100644
--- a/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/distribution/Distribution.java
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/Distribution.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.data.synthetic.bymodel.distribution;
+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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,28 +23,39 @@ package de.lmu.ifi.dbs.elki.data.synthetic.bymodel.distribution;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
/**
- * Interface for a simple distribution generator
- * with a PDF, i.e. it can also compute a density
+ * Interface for a simple distribution generator with a PDF, i.e. it can also
+ * compute a density
*
* @author Erich Schubert
*/
public interface Distribution {
/**
* Generate a new random value
- * @return new generated value
+ *
+ * @return new random value
*/
- public double generate();
+ public double nextRandom();
+
/**
* Return the density of an existing value
+ *
* @param val existing value
* @return distribution density
*/
- public double explain(double val);
-
+ public double pdf(double val);
+
+ /**
+ * Return the cumulative density function at the given value.
+ *
+ * @param val existing value
+ * @return cumulative density
+ */
+ public double cdf(double val);
+
/**
- * Describe the generator
+ * Describe the distribution
+ *
* @return description
*/
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/distribution/GammaDistribution.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/GammaDistribution.java
index 156ac3c4..6830f25a 100644
--- a/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/distribution/GammaDistribution.java
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/GammaDistribution.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.data.synthetic.bymodel.distribution;
+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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,11 +28,26 @@ import java.util.Random;
import de.lmu.ifi.dbs.elki.math.MathUtil;
/**
- * Simple generator for a Gamma Distribution
+ * Gamma Distribution, with random generation and density functions.
*
* @author Erich Schubert
*/
-public final class GammaDistribution implements Distribution {
+public class GammaDistribution implements Distribution {
+ /**
+ * LANCZOS-Coefficients for Gamma approximation.
+ *
+ * These are said to have higher precision than those in "Numerical Recipes".
+ * They probably come from
+ *
+ * Paul Godfrey: http://my.fit.edu/~gabdo/gamma.txt
+ */
+ 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
+ */
+ static final double NUM_PRECISION = 1E-15;
+
/**
* Alpha == k
*/
@@ -49,7 +64,7 @@ public final class GammaDistribution implements Distribution {
private Random random;
/**
- * Constructor for Gamma distribution generator
+ * Constructor for Gamma distribution.
*
* @param k k, alpha aka. "shape" parameter
* @param theta Theta = 1.0/Beta aka. "scaling" parameter
@@ -67,11 +82,72 @@ public final class GammaDistribution implements Distribution {
}
/**
+ * Constructor for Gamma distribution.
+ *
+ * @param k k, alpha aka. "shape" parameter
+ * @param theta Theta = 1.0/Beta aka. "scaling" parameter
+ */
+ public GammaDistribution(double k, double theta) {
+ this(k, theta, new Random());
+ }
+
+ @Override
+ public double pdf(double val) {
+ return pdf(val, k, theta);
+ }
+
+ @Override
+ public double cdf(double val) {
+ return cdf(val, k, theta);
+ }
+
+ @Override
+ public double nextRandom() {
+ return nextRandom(k, theta, random);
+ }
+
+ /**
+ * Simple toString explaining the distribution parameters.
+ *
+ * Used in producing a model description.
+ */
+ @Override
+ public String toString() {
+ return "Gamma Distribution (k=" + k + ", theta=" + theta + ")";
+ }
+
+ /**
+ * @return the value of k
+ */
+ public double getK() {
+ return k;
+ }
+
+ /**
+ * @return the standard deviation
+ */
+ public double getTheta() {
+ return theta;
+ }
+
+ /**
+ * The CDF, static version.
+ *
+ * @param val Value
+ * @param k Shape k
+ * @param theta Theta = 1.0/Beta aka. "scaling" parameter
+ * @return cdf value
+ */
+ public static double cdf(double val, double k, double theta) {
+ return regularizedGammaP(k, val / theta);
+ }
+
+ /**
* Gamma distribution PDF (with 0.0 for x &lt; 0)
*
* @param x query value
* @param k Alpha
- * @param theta Thetha = 1 / Beta
+ * @param theta Theta = 1 / Beta
* @return probability density
*/
public static double pdf(double x, double k, double theta) {
@@ -90,15 +166,125 @@ public final class GammaDistribution implements Distribution {
return Math.exp(-x * theta) * theta;
}
- return Math.exp((k - 1.0) * Math.log(x * theta) - x * theta - MathUtil.logGamma(k)) * theta;
+ return Math.exp((k - 1.0) * Math.log(x * theta) - x * theta - logGamma(k)) * theta;
}
/**
- * Return the PDF of the generators distribution
+ * Compute logGamma.
+ *
+ * Based loosely on "Numerical Recpies" and the work of Paul Godfrey at
+ * http://my.fit.edu/~gabdo/gamma.txt
+ *
+ * TODO: find out which approximation really is the best...
+ *
+ * @param x Parameter x
+ * @return log(&#915;(x))
*/
- @Override
- public double explain(double val) {
- return pdf(val, k, theta);
+ public static double logGamma(final double x) {
+ 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) {
+ ser += LANCZOS[i] / (x + i);
+ }
+ return tmp + Math.log(MathUtil.SQRTTWOPI * ser / x);
+ }
+
+ /**
+ * Returns the regularized gamma function P(a, x).
+ *
+ * Includes the quadrature way of computing.
+ *
+ * TODO: find "the" most accurate version of this. We seem to agree with
+ * others for the first 10+ digits, but diverge a bit later than that.
+ *
+ * @param a Parameter a
+ * @param x Parameter x
+ * @return Gamma value
+ */
+ 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)) {
+ return Double.NaN;
+ }
+ if(x == 0.0) {
+ return 0.0;
+ }
+ 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++) {
+ // compute next element in the series
+ del *= x / (a + n);
+ sum = sum + del;
+ if(Math.abs(del / sum) < NUM_PRECISION || sum >= Double.POSITIVE_INFINITY) {
+ break;
+ }
+ }
+ if(Double.isInfinite(sum)) {
+ return 1.0;
+ }
+ return Math.exp(-x + (a * Math.log(x)) - logGamma(a)) * sum;
+ }
+
+ /**
+ * Returns the regularized gamma function Q(a, x) = 1 - P(a, x).
+ *
+ * Includes the continued fraction way of computing, based loosely on the book
+ * "Numerical Recipes"; but probably not with the exactly same precision,
+ * since we reimplemented this in our coding style, not literally.
+ *
+ * TODO: find "the" most accurate version of this. We seem to agree with
+ * others for the first 10+ digits, but diverge a bit later than that.
+ *
+ * @param a parameter a
+ * @param x parameter x
+ * @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)) {
+ return Double.NaN;
+ }
+ if(x == 0.0) {
+ return 1.0;
+ }
+ if(x < a + 1.0) {
+ // Expected to converge faster
+ return 1.0 - regularizedGammaP(a, x);
+ }
+ // Compute using continued fraction approach.
+ final double FPMIN = Double.MIN_VALUE / NUM_PRECISION;
+ double b = x + 1 - a;
+ double c = 1.0 / FPMIN;
+ double d = 1.0 / b;
+ double fac = d;
+ for(int i = 1; i < Integer.MAX_VALUE; i++) {
+ double an = i * (a - i);
+ b += 2;
+ d = an * d + b;
+ if(Math.abs(d) < FPMIN) {
+ d = FPMIN;
+ }
+ c = b + an / c;
+ if(Math.abs(c) < FPMIN) {
+ c = FPMIN;
+ }
+ d = 1 / d;
+ double del = d * c;
+ fac *= del;
+ if(Math.abs(del - 1.0) <= NUM_PRECISION) {
+ break;
+ }
+ }
+ return fac * Math.exp(-x + a * Math.log(x) - logGamma(a));
}
/**
@@ -111,9 +297,12 @@ public final class GammaDistribution implements Distribution {
*
* - J.H. Ahrens, U. Dieter (1982): Generating gamma variates by a modified
* rejection technique, Communications of the ACM 25, 47-54.
+ *
+ * @param k K parameter
+ * @param theta Theta parameter
+ * @param random Random generator
*/
- @Override
- public double generate() {
+ public static double nextRandom(double k, double theta, Random random) {
/* Constants */
final double q1 = 0.0416666664, q2 = 0.0208333723, q3 = 0.0079849875;
final double q4 = 0.0015746717, q5 = -0.0003349403, q6 = 0.0003340332;
@@ -124,7 +313,7 @@ public final class GammaDistribution implements Distribution {
final double e1 = 1.000000000, e2 = 0.499999994, e3 = 0.166666848;
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
final double b = 1.0 + 0.36788794412 * k; // Step 1
while(true) {
@@ -171,11 +360,11 @@ public final class GammaDistribution implements Distribution {
/* v2 = tv2; */
v12 = tv12;
}
-
+
// double b = 0.0, c = 0.0;
// double si = 0.0, q0 = 0.0;
final double b, c, si, q0;
-
+
// Simpler accept cases & parameter computation
{
final double t = v1 * Math.sqrt(-2.0 * Math.log(v12) / v12);
@@ -184,14 +373,14 @@ public final class GammaDistribution implements Distribution {
if(t >= 0.0) {
return (gds / theta); // Immediate acceptance
}
-
+
// Random uniform
final double un = random.nextDouble();
// Squeeze acceptance
if(d * un <= t * t * t) {
return (gds / theta);
}
-
+
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;
@@ -236,7 +425,7 @@ public final class GammaDistribution implements Distribution {
}
}
}
-
+
// Double exponential deviate t
while(true) {
double e, u, sign_u, t;
@@ -249,7 +438,7 @@ public final class GammaDistribution implements Distribution {
t = b + (e * si) * sign_u;
}
while(t <= -0.71874483771719);
-
+
// New v(t) and q(t)
final double v = t / (s + s);
final double q;
@@ -278,28 +467,4 @@ public final class GammaDistribution implements Distribution {
}
}
}
-
- /**
- * Simple toString explaining the distribution parameters.
- *
- * Used in producing a model description.
- */
- @Override
- public String toString() {
- return "Gamma Distribution (k=" + k + ", theta=" + theta + ")";
- }
-
- /**
- * @return the value of k
- */
- public double getK() {
- return k;
- }
-
- /**
- * @return the standard deviation
- */
- public double getTheta() {
- return theta;
- }
} \ No newline at end of file
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
new file mode 100644
index 00000000..919cc2e3
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/NormalDistribution.java
@@ -0,0 +1,337 @@
+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 java.util.Random;
+
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+
+/**
+ * Gaussian distribution aka normal distribution
+ *
+ * @author Erich Schubert
+ */
+public class NormalDistribution implements Distribution {
+ /**
+ * Coefficients for erf approximation.
+ *
+ * Loosely based on http://www.netlib.org/specfun/erf
+ */
+ static final double ERFAPP_A[] = { 1.85777706184603153e-1, 3.16112374387056560e+0, 1.13864154151050156E+2, 3.77485237685302021e+2, 3.20937758913846947e+3 };
+
+ /**
+ * Coefficients for erf approximation.
+ *
+ * Loosely based on http://www.netlib.org/specfun/erf
+ */
+ static final double ERFAPP_B[] = { 1.00000000000000000e00, 2.36012909523441209e01, 2.44024637934444173e02, 1.28261652607737228e03, 2.84423683343917062e03 };
+
+ /**
+ * Coefficients for erf approximation.
+ *
+ * Loosely based on http://www.netlib.org/specfun/erf
+ */
+ static final double ERFAPP_C[] = { 2.15311535474403846e-8, 5.64188496988670089e-1, 8.88314979438837594e00, 6.61191906371416295e01, 2.98635138197400131e02, 8.81952221241769090e02, 1.71204761263407058e03, 2.05107837782607147e03, 1.23033935479799725E03 };
+
+ /**
+ * Coefficients for erf approximation.
+ *
+ * Loosely based on http://www.netlib.org/specfun/erf
+ */
+ static final double ERFAPP_D[] = { 1.00000000000000000e00, 1.57449261107098347e01, 1.17693950891312499e02, 5.37181101862009858e02, 1.62138957456669019e03, 3.29079923573345963e03, 4.36261909014324716e03, 3.43936767414372164e03, 1.23033935480374942e03 };
+
+ /**
+ * Coefficients for erf approximation.
+ *
+ * Loosely based on http://www.netlib.org/specfun/erf
+ */
+ static final double ERFAPP_P[] = { 1.63153871373020978e-2, 3.05326634961232344e-1, 3.60344899949804439e-1, 1.25781726111229246e-1, 1.60837851487422766e-2, 6.58749161529837803e-4 };
+
+ /**
+ * Coefficients for erf approximation.
+ *
+ * Loosely based on http://www.netlib.org/specfun/erf
+ */
+ static final double ERFAPP_Q[] = { 1.00000000000000000e00, 2.56852019228982242e00, 1.87295284992346047e00, 5.27905102951428412e-1, 6.05183413124413191e-2, 2.33520497626869185e-3 };
+
+ /**
+ * Treshold for switching nethods for erfinv approximation
+ */
+ static final double P_LOW = 0.02425D;
+
+ /**
+ * Treshold for switching nethods for erfinv approximation
+ */
+ static final double P_HIGH = 1.0D - P_LOW;
+
+ /**
+ * Coefficients for erfinv approximation, rational version
+ */
+ static final double ERFINV_A[] = { -3.969683028665376e+01, 2.209460984245205e+02, -2.759285104469687e+02, 1.383577518672690e+02, -3.066479806614716e+01, 2.506628277459239e+00 };
+
+ /**
+ * Coefficients for erfinv approximation, rational version
+ */
+ static final double ERFINV_B[] = { -5.447609879822406e+01, 1.615858368580409e+02, -1.556989798598866e+02, 6.680131188771972e+01, -1.328068155288572e+01 };
+
+ /**
+ * Coefficients for erfinv approximation, rational version
+ */
+ static final double ERFINV_C[] = { -7.784894002430293e-03, -3.223964580411365e-01, -2.400758277161838e+00, -2.549732539343734e+00, 4.374664141464968e+00, 2.938163982698783e+00 };
+
+ /**
+ * Coefficients for erfinv approximation, rational version
+ */
+ static final double ERFINV_D[] = { 7.784695709041462e-03, 3.224671290700398e-01, 2.445134137142996e+00, 3.754408661907416e+00 };
+
+ /**
+ * Mean value for the generator
+ */
+ private double mean;
+
+ /**
+ * Standard deviation
+ */
+ private double stddev;
+
+ /**
+ * The random generator.
+ */
+ private Random random;
+
+ /**
+ * Constructor for Gaussian distribution
+ *
+ * @param mean Mean
+ * @param stddev Standard Deviation
+ * @param random Random generator
+ */
+ public NormalDistribution(double mean, double stddev, Random random) {
+ super();
+ this.mean = mean;
+ this.stddev = stddev;
+ this.random = random;
+ }
+
+ /**
+ * Constructor for Gaussian distribution
+ *
+ * @param mean Mean
+ * @param stddev Standard Deviation
+ */
+ public NormalDistribution(double mean, double stddev) {
+ this(mean, stddev, new Random());
+ }
+
+ @Override
+ public double pdf(double val) {
+ return pdf(val, mean, stddev);
+ }
+
+ @Override
+ public double cdf(double val) {
+ return cdf(val, mean, stddev);
+ }
+
+ @Override
+ public double nextRandom() {
+ return mean + random.nextGaussian() * stddev;
+ }
+
+ @Override
+ public String toString() {
+ return "Normal Distribution (mean="+mean+", stddev="+stddev+")";
+ }
+
+ /**
+ * @return the mean
+ */
+ public double getMean() {
+ return mean;
+ }
+
+ /**
+ * @return the standard deviation
+ */
+ public double getStddev() {
+ return stddev;
+ }
+
+ /**
+ * Complementary error function for Gaussian distributions = Normal
+ * distributions.
+ *
+ * Numerical approximation using taylor series. Implementation loosely based
+ * on http://www.netlib.org/specfun/erf
+ *
+ * @param x parameter value
+ * @return erfc(x)
+ */
+ public static double erfc(double x) {
+ if(Double.isNaN(x)) {
+ return Double.NaN;
+ }
+ 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) {
+ 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) {
+ 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) {
+ result = 2.0 - result;
+ }
+ }
+ // Third approximation interval
+ else {
+ double z = 1.0 / (absx * absx);
+ result = z * (((((ERFAPP_P[0] * z + ERFAPP_P[1]) * z + ERFAPP_P[2]) * z + ERFAPP_P[3]) * z + ERFAPP_P[4]) * z + ERFAPP_P[5]) / (((((ERFAPP_Q[0] * z + ERFAPP_Q[1]) * z + ERFAPP_Q[2]) * z + ERFAPP_Q[3]) * z + ERFAPP_Q[4]) * z + ERFAPP_Q[5]);
+ result = (MathUtil.ONE_BY_SQRTPI - result) / absx;
+ 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) {
+ result = 2.0 - result;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Error function for Gaussian distributions = Normal distributions.
+ *
+ * Numerical approximation using taylor series. Implementation loosely based
+ * on http://www.netlib.org/specfun/erf
+ *
+ * @param x parameter value
+ * @return erf(x)
+ */
+ public static double erf(double x) {
+ return 1 - erfc(x);
+ }
+
+ /**
+ * Inverse error function.
+ *
+ * @param x parameter value
+ * @return erfinv(x)
+ */
+ public static double erfinv(double x) {
+ return standardNormalProbit(0.5 * (x + 1)) / MathUtil.SQRT2;
+ }
+
+ /**
+ * 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>
+ *
+ * @param d Quantile. Must be in [0:1], obviously.
+ * @return Inverse erf.
+ */
+ public static double standardNormalProbit(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);
+ }
+ }
+
+ /**
+ * Probability density function of the normal distribution.
+ *
+ * <pre>
+ * 1/(SQRT(2*pi*sigma^2)) * e^(-(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) {
+ final double x_mu = x - mu;
+ final double sigmasq = sigma * sigma;
+ return 1 / (Math.sqrt(MathUtil.TWOPI * sigmasq)) * Math.exp(-1 * x_mu * x_mu / 2 / 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 normal given distribution at x.
+ */
+ public static double cdf(double x, double mu, double sigma) {
+ return (1 + erf(x / Math.sqrt(2))) / 2;
+ }
+
+ /**
+ * 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 normal given distribution at x.
+ */
+ public static double probit(double x, double mu, double sigma) {
+ return mu + sigma * standardNormalProbit(x);
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/distribution/UniformDistribution.java b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/UniformDistribution.java
index 0686f1a3..9571cfd3 100644
--- a/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/distribution/UniformDistribution.java
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/UniformDistribution.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.data.synthetic.bymodel.distribution;
+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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,11 +26,11 @@ package de.lmu.ifi.dbs.elki.data.synthetic.bymodel.distribution;
import java.util.Random;
/**
- * Simple uniform distribution class
+ * Uniform distribution.
*
* @author Erich Schubert
*/
-public final class UniformDistribution implements Distribution {
+public class UniformDistribution implements Distribution {
/**
* Minimum
*/
@@ -59,6 +59,7 @@ public final class UniformDistribution implements Distribution {
* @param random Random generator
*/
public UniformDistribution(double min, double max, Random random) {
+ super();
// Swap parameters if they were given incorrectly.
if(min > max) {
double tmp = min;
@@ -72,21 +73,36 @@ public final class UniformDistribution implements Distribution {
}
/**
- * Return the PDF of the generators distribution
+ * Constructor for a uniform distribution on the interval [min, max[
+ *
+ * @param min Minimum value
+ * @param max Maximum value
*/
+ public UniformDistribution(double min, double max) {
+ this(min, max, new Random());
+ }
+
@Override
- public double explain(double val) {
+ public double pdf(double val) {
if(val < min || val >= max) {
return 0.0;
}
return 1.0 / len;
}
- /**
- * Generate a random value with the generators parameters
- */
@Override
- public double generate() {
+ public double cdf(double val) {
+ if(val < min) {
+ return 0.0;
+ }
+ if(val > max) {
+ return 1.0;
+ }
+ return (val - min) / len;
+ }
+
+ @Override
+ public double nextRandom() {
return min + random.nextDouble() * len;
}
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
new file mode 100644
index 00000000..ed9c0e88
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/math/statistics/distribution/package-info.java
@@ -0,0 +1,26 @@
+/**
+ * <p>Standard distributions, with random generation functionalities.</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.math.statistics.distribution; \ 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 bd1195f3..142524e6 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) 2011
+Copyright (C) 2012
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 b37bc467..e7252314 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) 2011
+ Copyright (C) 2012
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/AbstractPage.java b/src/de/lmu/ifi/dbs/elki/persistent/AbstractExternalizablePage.java
index 25ed8b7f..194b594f 100644
--- a/src/de/lmu/ifi/dbs/elki/persistent/AbstractPage.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -31,11 +31,9 @@ import java.io.ObjectOutput;
* Abstract superclass for pages.
*
* @author Elke Achtert
- *
- * @apiviz.uses PageFile
*/
// todo elke revise comments
-public abstract class AbstractPage implements Page {
+public abstract class AbstractExternalizablePage implements ExternalizablePage {
/**
* Serial version
*/
@@ -44,7 +42,7 @@ public abstract class AbstractPage implements Page {
/**
* The unique id if this page.
*/
- private Integer id;
+ private int id;
/**
* The dirty flag of this page.
@@ -54,8 +52,9 @@ public abstract class AbstractPage implements Page {
/**
* Empty constructor for Externalizable interface.
*/
- public AbstractPage() {
+ public AbstractExternalizablePage() {
super();
+ this.id = -1;
}
/**
@@ -64,7 +63,7 @@ public abstract class AbstractPage implements Page {
* @return the unique id of this Page
*/
@Override
- public final Integer getPageID() {
+ public final int getPageID() {
return id;
}
@@ -140,12 +139,7 @@ public abstract class AbstractPage implements Page {
*/
@Override
public String toString() {
- if(id != null) {
- return Integer.toString(id);
- }
- else {
- return "null";
- }
+ return Integer.toString(id);
}
/**
@@ -164,9 +158,9 @@ public abstract class AbstractPage implements Page {
return false;
}
- final AbstractPage that = (AbstractPage) o;
+ final AbstractExternalizablePage that = (AbstractExternalizablePage) o;
- return id.equals(that.getPageID());
+ return id == that.getPageID();
}
/**
@@ -176,6 +170,6 @@ public abstract class AbstractPage implements Page {
*/
@Override
public int hashCode() {
- return id.hashCode();
+ return id;
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/AbstractPageFile.java b/src/de/lmu/ifi/dbs/elki/persistent/AbstractPageFile.java
index 54aa7e39..e05c20c3 100644
--- a/src/de/lmu/ifi/dbs/elki/persistent/AbstractPageFile.java
+++ b/src/de/lmu/ifi/dbs/elki/persistent/AbstractPageFile.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -61,7 +61,7 @@ public abstract class AbstractPageFile<P extends Page> implements PageFile<P> {
*/
@Override
public final synchronized int writePage(P page) {
- Integer pageid = setPageID(page);
+ int pageid = setPageID(page);
writePage(pageid, page);
return pageid;
}
@@ -72,7 +72,7 @@ public abstract class AbstractPageFile<P extends Page> implements PageFile<P> {
* @param pageid Page id
* @param page Page to write
*/
- protected abstract void writePage(Integer pageid, P page);
+ protected abstract void writePage(int pageid, P page);
@Override
public void close() {
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/AbstractStoringPageFile.java b/src/de/lmu/ifi/dbs/elki/persistent/AbstractStoringPageFile.java
index bb4e915d..7151e6dd 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -67,11 +67,11 @@ public abstract class AbstractStoringPageFile<P extends Page> extends AbstractPa
* @param page the page to set the id
*/
@Override
- public Integer setPageID(P page) {
- Integer pageID = page.getPageID();
- if(pageID == null) {
+ public int setPageID(P page) {
+ int pageID = page.getPageID();
+ if(pageID == -1) {
pageID = getNextEmptyPageID();
- if(pageID == null) {
+ if(pageID == -1) {
pageID = nextPageID++;
}
page.setPageID(pageID);
@@ -95,12 +95,12 @@ public abstract class AbstractStoringPageFile<P extends Page> extends AbstractPa
*
* @return the next empty page id
*/
- private Integer getNextEmptyPageID() {
+ private int getNextEmptyPageID() {
if(!emptyPages.empty()) {
return emptyPages.pop();
}
else {
- return null;
+ return -1;
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/ByteArrayUtil.java b/src/de/lmu/ifi/dbs/elki/persistent/ByteArrayUtil.java
index f4959167..42466558 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) 2011
+ Copyright (C) 2012
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 3fd7b35f..586d5535 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) 2011
+ Copyright (C) 2012
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 6c6c5c43..2a2971d9 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) 2011
+ Copyright (C) 2012
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 0a9403ac..e10a365d 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) 2011
+ Copyright (C) 2012
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/DefaultPageHeader.java b/src/de/lmu/ifi/dbs/elki/persistent/DefaultPageHeader.java
index e2be5aaf..e1ca2a41 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) 2011
+ Copyright (C) 2012
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/TreeSetModifiableDBIDs.java b/src/de/lmu/ifi/dbs/elki/persistent/ExternalizablePage.java
index 4212f847..703187ac 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/TreeSetModifiableDBIDs.java
+++ b/src/de/lmu/ifi/dbs/elki/persistent/ExternalizablePage.java
@@ -1,10 +1,12 @@
-package de.lmu.ifi.dbs.elki.database.ids;
+package de.lmu.ifi.dbs.elki.persistent;
+
+import java.io.Externalizable;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,13 +25,12 @@ package de.lmu.ifi.dbs.elki.database.ids;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.NavigableSet;
-
/**
- * Set-oriented implementation of a modifiable DBID collection.
+ * Base interface for externalizable pages.
*
* @author Erich Schubert
*/
-public interface TreeSetModifiableDBIDs extends ModifiableDBIDs, TreeSetDBIDs, NavigableSet<DBID> {
- // empty
-} \ No newline at end of file
+// TODO: replace with the newer ByteSerializers
+public interface ExternalizablePage extends Page, Externalizable {
+ // Empty
+}
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/FixedSizeByteBufferSerializer.java b/src/de/lmu/ifi/dbs/elki/persistent/FixedSizeByteBufferSerializer.java
index d68ac994..56f1f9b3 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) 2011
+ Copyright (C) 2012
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/LRUCache.java b/src/de/lmu/ifi/dbs/elki/persistent/LRUCache.java
index e93924f0..3b6f67dc 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -111,7 +111,7 @@ public class LRUCache<P extends Page> extends AbstractPageFile<P> {
}
@Override
- public synchronized void writePage(Integer pageID, P page) {
+ public synchronized void writePage(int pageID, P page) {
writeAccess++;
page.setDirty(true);
map.put(pageID, page);
@@ -142,8 +142,8 @@ public class LRUCache<P extends Page> extends AbstractPageFile<P> {
}
@Override
- public Integer setPageID(P page) {
- Integer pageID = file.setPageID(page);
+ public int setPageID(P page) {
+ int pageID = file.setPageID(page);
return pageID;
}
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/MemoryPageFile.java b/src/de/lmu/ifi/dbs/elki/persistent/MemoryPageFile.java
index 13e3ec04..7aba9a21 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) 2011
+ Copyright (C) 2012
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.persistent;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.HashMap;
-import java.util.Map;
+import gnu.trove.map.TIntObjectMap;
+import gnu.trove.map.hash.TIntObjectHashMap;
/**
* A memory based implementation of a PageFile that simulates I/O-access.<br>
@@ -38,7 +38,7 @@ public class MemoryPageFile<P extends Page> extends AbstractStoringPageFile<P> {
/**
* Holds the pages.
*/
- private final Map<Integer, P> file;
+ private final TIntObjectMap<P> file;
/**
* Creates a new MemoryPageFile that is supported by a cache with the
@@ -48,7 +48,7 @@ public class MemoryPageFile<P extends Page> extends AbstractStoringPageFile<P> {
*/
public MemoryPageFile(int pageSize) {
super(pageSize);
- this.file = new HashMap<Integer, P>();
+ this.file = new TIntObjectHashMap<P>();
}
@Override
@@ -58,7 +58,7 @@ public class MemoryPageFile<P extends Page> extends AbstractStoringPageFile<P> {
}
@Override
- protected void writePage(Integer pageID, P page) {
+ protected void writePage(int pageID, P page) {
writeAccess++;
file.put(pageID, page);
page.setDirty(false);
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/OnDiskArray.java b/src/de/lmu/ifi/dbs/elki/persistent/OnDiskArray.java
index 2290398c..7c62173d 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -129,8 +129,8 @@ public class OnDiskArray implements Serializable {
this.filename = filename;
this.writable = true;
- // do not allow overwriting.
- if(filename.exists()) {
+ // do not allow overwriting, unless empty
+ if(filename.exists() && filename.length() > 0) {
throw new IOException(ExceptionMessages.FILE_EXISTS);
}
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/OnDiskArrayPageFile.java b/src/de/lmu/ifi/dbs/elki/persistent/OnDiskArrayPageFile.java
index d7a546fe..37a16384 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -139,7 +139,7 @@ public class OnDiskArrayPageFile<P extends Page> extends AbstractStoringPageFile
* @param page the page which has to be written to disk
*/
@Override
- public void writePage(Integer pageID, P page) {
+ public void writePage(int pageID, P page) {
if(page.isDirty()) {
try {
writeAccess++;
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/OnDiskUpperTriangleMatrix.java b/src/de/lmu/ifi/dbs/elki/persistent/OnDiskUpperTriangleMatrix.java
index 6d38348a..638d85cd 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) 2011
+ Copyright (C) 2012
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 d296a840..2c3fb252 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,21 +23,19 @@ package de.lmu.ifi.dbs.elki.persistent;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.io.Externalizable;
-
/**
* Defines the requirements for objects that can be stored in a cache and can be
* persistently saved.
*
* @author Elke Achtert
*/
-public interface Page extends Externalizable {
+public interface Page {
/**
* Returns the unique id of this Page.
*
- * @return the unique id of this Page. May be {@code null}.
+ * @return the unique id of this Page. Return -1 for unassigned page numbers.
*/
- Integer getPageID();
+ int getPageID();
/**
* Sets the unique id of this Page.
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/PageFile.java b/src/de/lmu/ifi/dbs/elki/persistent/PageFile.java
index a65fabeb..f50e829e 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -38,7 +38,7 @@ public interface PageFile<P extends Page> extends PageFileStatistics {
* @param page the page to set the id
* @return the page id
*/
- public Integer setPageID(P page);
+ public int setPageID(P page);
/**
* Writes a page into this file. The method tests if the page has already an
diff --git a/src/de/lmu/ifi/dbs/elki/persistent/PageFileStatistics.java b/src/de/lmu/ifi/dbs/elki/persistent/PageFileStatistics.java
index 2f2bd821..df3de612 100644
--- a/src/de/lmu/ifi/dbs/elki/persistent/PageFileStatistics.java
+++ b/src/de/lmu/ifi/dbs/elki/persistent/PageFileStatistics.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) 2011
+ Copyright (C) 2012
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/PageFileUtil.java b/src/de/lmu/ifi/dbs/elki/persistent/PageFileUtil.java
index 6a0dbb92..5fe11432 100644
--- a/src/de/lmu/ifi/dbs/elki/persistent/PageFileUtil.java
+++ b/src/de/lmu/ifi/dbs/elki/persistent/PageFileUtil.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) 2011
+ Copyright (C) 2012
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/PageHeader.java b/src/de/lmu/ifi/dbs/elki/persistent/PageHeader.java
index 911e81c2..70a31190 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) 2011
+ Copyright (C) 2012
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 b40e56f5..618707a5 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -47,7 +47,7 @@ import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
*
* @param <P> Page type
*/
-public class PersistentPageFile<P extends Page> extends AbstractStoringPageFile<P> {
+public class PersistentPageFile<P extends ExternalizablePage> extends AbstractStoringPageFile<P> {
/**
* Our logger
*/
@@ -156,7 +156,7 @@ public class PersistentPageFile<P extends Page> extends AbstractStoringPageFile<
* @param page the page which has to be written to disk
*/
@Override
- public void writePage(Integer pageID, P page) {
+ public void writePage(int pageID, P page) {
try {
writeAccess++;
byte[] array = pageToByteArray(page);
@@ -167,7 +167,7 @@ public class PersistentPageFile<P extends Page> extends AbstractStoringPageFile<
page.setDirty(false);
}
catch(IOException e) {
- throw new RuntimeException(e);
+ throw new RuntimeException("Error writing to page file.", e);
}
}
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 ce083c88..c2d8614c 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) 2011
+Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/src/de/lmu/ifi/dbs/elki/properties/ELKI.properties b/src/de/lmu/ifi/dbs/elki/properties/ELKI.properties
deleted file mode 100644
index 5c45ecfa..00000000
--- a/src/de/lmu/ifi/dbs/elki/properties/ELKI.properties
+++ /dev/null
@@ -1,646 +0,0 @@
-# #######################################################
-# algorithms - default package: de.lmu.ifi.dbs.elki.algorithm
-de.lmu.ifi.dbs.elki.algorithm.Algorithm=\
- de.lmu.ifi.dbs.elki.algorithm.NullAlgorithm,\
- 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.KMeans,\
- 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,\
- de.lmu.ifi.dbs.elki.algorithm.clustering.correlation.ERiC,\
- de.lmu.ifi.dbs.elki.algorithm.clustering.correlation.FourC,\
- de.lmu.ifi.dbs.elki.algorithm.clustering.correlation.HiCO,\
- de.lmu.ifi.dbs.elki.algorithm.clustering.correlation.ORCLUS,\
- de.lmu.ifi.dbs.elki.algorithm.clustering.subspace.CLIQUE,\
- de.lmu.ifi.dbs.elki.algorithm.clustering.subspace.DiSH,\
- de.lmu.ifi.dbs.elki.algorithm.clustering.subspace.HiSC,\
- de.lmu.ifi.dbs.elki.algorithm.clustering.subspace.PreDeCon,\
- de.lmu.ifi.dbs.elki.algorithm.clustering.subspace.PROCLUS,\
- de.lmu.ifi.dbs.elki.algorithm.clustering.subspace.SUBCLU,\
- de.lmu.ifi.dbs.elki.algorithm.clustering.trivial.ByLabelClustering,\
- de.lmu.ifi.dbs.elki.algorithm.clustering.trivial.ByLabelHierarchicalClustering,\
- de.lmu.ifi.dbs.elki.algorithm.clustering.trivial.TrivialAllInOne,\
- de.lmu.ifi.dbs.elki.algorithm.clustering.trivial.TrivialAllNoise,\
- 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.DBOutlierDetection,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.DBOutlierScore,\
- 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.INFLO,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.KNNOutlier,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.KNNWeightOutlier,\
- 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.OPTICSOF,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.ReferenceBasedOutlierDetection,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.SOD,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.OnlineLOF,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.CTLuGLSBackwardSearchAlgorithm,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.CTLuMeanMultipleAttributes,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.CTLuMedianAlgorithm,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.CTLuMedianMultipleAttributes,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.CTLuMoranScatterplotOutlier,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.CTLuRandomWalkEC,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.CTLuScatterplotOutlier,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.CTLuZTestOutlier,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.SLOM,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.SOF,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.TrimmedMeanApproach,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.meta.ExternalDoubleOutlierScore,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.meta.FeatureBagging,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.meta.RescaleMetaOutlierAlgorithm,\
- 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.statistics.EvaluateRankingQuality,\
- de.lmu.ifi.dbs.elki.algorithm.statistics.RankingQualityHistogram,\
- de.lmu.ifi.dbs.elki.algorithm.statistics.DistanceStatisticsWithClasses,\
-# de.lmu.ifi.dbs.elki.algorithm.DummyAlgorithm,\
- de.lmu.ifi.dbs.elki.algorithm.APRIORI,\
- de.lmu.ifi.dbs.elki.algorithm.DependencyDerivator,\
- de.lmu.ifi.dbs.elki.algorithm.KNNDistanceOrder,\
- de.lmu.ifi.dbs.elki.algorithm.KNNJoin,\
- de.lmu.ifi.dbs.elki.algorithm.MaterializeDistances,\
-# #######################################################
-# distance based algorithm - default package: de.lmu.ifi.dbs.elki.algorithm
-de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm=\
- 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.DBSCAN,\
- 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.correlation.HiCO,\
- de.lmu.ifi.dbs.elki.algorithm.clustering.subspace.HiSC,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.ABOD,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.DBOutlierDetection,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.DBOutlierScore,\
- 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.LDOF,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.LOCI,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.OPTICSOF,\
- 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.RankingQualityHistogram,\
- de.lmu.ifi.dbs.elki.algorithm.statistics.DistanceStatisticsWithClasses,\
- de.lmu.ifi.dbs.elki.algorithm.statistics.EvaluateRankingQuality,\
-# #######################################################
-# distance based algorithm - default package: de.lmu.ifi.dbs.elki.algorithm
-de.lmu.ifi.dbs.elki.algorithm.AbstractPrimitiveDistanceBasedAlgorithm=\
- de.lmu.ifi.dbs.elki.algorithm.DependencyDerivator,\
- de.lmu.ifi.dbs.elki.algorithm.clustering.KMeans,\
-# #######################################################
-# clustering - default package: de.lmu.ifi.dbs.elki.algorithm.clustering
-de.lmu.ifi.dbs.elki.algorithm.clustering.ClusteringAlgorithm=\
- de.lmu.ifi.dbs.elki.algorithm.clustering.DBSCAN,\
- de.lmu.ifi.dbs.elki.algorithm.clustering.EM,\
- de.lmu.ifi.dbs.elki.algorithm.clustering.KMeans,\
- de.lmu.ifi.dbs.elki.algorithm.clustering.OPTICSXi,\
- 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,\
- de.lmu.ifi.dbs.elki.algorithm.clustering.correlation.ERiC,\
- de.lmu.ifi.dbs.elki.algorithm.clustering.correlation.FourC,\
- de.lmu.ifi.dbs.elki.algorithm.clustering.correlation.ORCLUS,\
- de.lmu.ifi.dbs.elki.algorithm.clustering.subspace.CLIQUE,\
- de.lmu.ifi.dbs.elki.algorithm.clustering.subspace.DiSH,\
- de.lmu.ifi.dbs.elki.algorithm.clustering.subspace.PreDeCon,\
- de.lmu.ifi.dbs.elki.algorithm.clustering.subspace.PROCLUS,\
- de.lmu.ifi.dbs.elki.algorithm.clustering.subspace.SUBCLU,\
- de.lmu.ifi.dbs.elki.algorithm.clustering.trivial.ByLabelClustering,\
- de.lmu.ifi.dbs.elki.algorithm.clustering.trivial.ByLabelHierarchicalClustering,\
- de.lmu.ifi.dbs.elki.algorithm.clustering.trivial.TrivialAllInOne,\
- de.lmu.ifi.dbs.elki.algorithm.clustering.trivial.TrivialAllNoise,\
-# #######################################################
-# OPTICS type algorithms - default package: de.lmu.ifi.dbs.elki.algorithm
-de.lmu.ifi.dbs.elki.algorithm.clustering.OPTICSTypeAlgorithm=\
- de.lmu.ifi.dbs.elki.algorithm.clustering.OPTICS,\
- de.lmu.ifi.dbs.elki.algorithm.clustering.DeLiClu,\
- de.lmu.ifi.dbs.elki.algorithm.clustering.correlation.HiCO,\
- de.lmu.ifi.dbs.elki.algorithm.clustering.subspace.HiSC,\
-# #######################################################
-# Outlier detection algorithms - default package: de.lmu.ifi.dbs.elki.algorithm.outlier
-de.lmu.ifi.dbs.elki.algorithm.outlier.OutlierAlgorithm=\
- 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.DBOutlierDetection,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.DBOutlierScore,\
- 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.INFLO,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.KNNOutlier,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.KNNWeightOutlier,\
- 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.OPTICSOF,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.ReferenceBasedOutlierDetection,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.SOD,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.OnlineLOF,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.CTLuGLSBackwardSearchAlgorithm,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.CTLuMeanMultipleAttributes,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.CTLuMedianAlgorithm,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.CTLuMedianMultipleAttributes,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.CTLuMoranScatterplotOutlier,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.CTLuRandomWalkEC,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.CTLuScatterplotOutlier,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.CTLuZTestOutlier,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.SLOM,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.SOF,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.TrimmedMeanApproach,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.meta.ExternalDoubleOutlierScore,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.meta.FeatureBagging,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.meta.RescaleMetaOutlierAlgorithm,\
- 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,\
-# #######################################################
-# Color Histograms - default package: de.lmu.ifi.dbs.elki.data.images
-de.lmu.ifi.dbs.elki.data.images.ComputeColorHistogram=\
- de.lmu.ifi.dbs.elki.data.images.ComputeHSBColorHistogram,\
- de.lmu.ifi.dbs.elki.data.images.ComputeNaiveHSBColorHistogram,\
- de.lmu.ifi.dbs.elki.data.images.ComputeNaiveRGBColorHistogram,\
-# #######################################################
-# Classlabel - default package: de.lmu.ifi.dbs.elki.data
-de.lmu.ifi.dbs.elki.data.ClassLabel$Factory=\
- de.lmu.ifi.dbs.elki.data.SimpleClassLabel$Factory,\
- de.lmu.ifi.dbs.elki.data.HierarchicalClassLabel$Factory,\
-# #######################################################
-# Databases - default package: de.lmu.ifi.dbs.elki.database
-de.lmu.ifi.dbs.elki.database.Database=\
- de.lmu.ifi.dbs.elki.database.StaticArrayDatabase,\
- de.lmu.ifi.dbs.elki.database.HashmapDatabase,\
-# de.lmu.ifi.dbs.elki.database.ProxyDatabase,\
-# #######################################################
-# Updateable Databases - default package: de.lmu.ifi.dbs.elki.database
-de.lmu.ifi.dbs.elki.database.UpdatableDatabase=\
- de.lmu.ifi.dbs.elki.database.HashmapDatabase,\
-# #######################################################
-# Database connections - default package: de.lmu.ifi.dbs.elki.database.connection
-de.lmu.ifi.dbs.elki.datasource.DatabaseConnection=\
- de.lmu.ifi.dbs.elki.datasource.FileBasedDatabaseConnection,\
- de.lmu.ifi.dbs.elki.datasource.ExternalIDJoinDatabaseConnection,\
- de.lmu.ifi.dbs.elki.datasource.LabelJoinDatabaseConnection,\
- de.lmu.ifi.dbs.elki.datasource.GeneratorXMLDatabaseConnection,\
- de.lmu.ifi.dbs.elki.datasource.RandomDoubleVectorDatabaseConnection,\
- de.lmu.ifi.dbs.elki.datasource.EmptyDatabaseConnection,\
-# de.lmu.ifi.dbs.elki.datasource.InputStreamDatabaseConnection,\
-# #######################################################
-# distance functions - default package: de.lmu.ifi.dbs.elki.distance.distancefunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction=\
- 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.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.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.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.colorhistogram.HSBHistogramQuadraticDistanceFunction,\
- de.lmu.ifi.dbs.elki.distance.distancefunction.colorhistogram.HistogramIntersectionDistanceFunction,\
- de.lmu.ifi.dbs.elki.distance.distancefunction.colorhistogram.RGBHistogramQuadraticDistanceFunction,\
- de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.PearsonCorrelationDistanceFunction,\
- de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.SquaredPearsonCorrelationDistanceFunction,\
- de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.ERiCDistanceFunction,\
- de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.PCABasedCorrelationDistanceFunction,\
-# de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.WeightedPearsonCorrelationDistanceFunction,\
-# de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.WeightedSquaredPearsonCorrelationDistanceFunction,\
- 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.subspace.DimensionSelectingDistanceFunction,\
- de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.DimensionsSelectingEuclideanDistanceFunction,\
- de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.DiSHDistanceFunction,\
- de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.HiSCDistanceFunction,\
-# de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.SubspaceDistanceFunction,\
- 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.similarityfunction.kernel.FooKernelFunction,\
-# de.lmu.ifi.dbs.elki.distance.similarityfunction.kernel.LinearKernelFunction,\
-# de.lmu.ifi.dbs.elki.distance.similarityfunction.kernel.PolynomialKernelFunction,\
-# #######################################################
-# primitive distance functions - default package: de.lmu.ifi.dbs.elki.distance.distancefunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction=\
- 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.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.WeightedDistanceFunction,\
-# de.lmu.ifi.dbs.elki.distance.distancefunction.WeightedLPNormDistanceFunction,\
-# de.lmu.ifi.dbs.elki.distance.distancefunction.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,\
- de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.PearsonCorrelationDistanceFunction,\
- de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.SquaredPearsonCorrelationDistanceFunction,\
-# de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.WeightedPearsonCorrelationDistanceFunction,\
-# de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.WeightedSquaredPearsonCorrelationDistanceFunction,\
- 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.subspace.DimensionSelectingDistanceFunction,\
- de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.DimensionsSelectingEuclideanDistanceFunction,\
- 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.similarityfunction.kernel.FooKernelFunction,\
-# de.lmu.ifi.dbs.elki.distance.similarityfunction.kernel.LinearKernelFunction,\
-# de.lmu.ifi.dbs.elki.distance.similarityfunction.kernel.PolynomialKernelFunction,\
-# #######################################################
-# primitive double distance functions - default package: de.lmu.ifi.dbs.elki.distance.distancefunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction=\
- 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.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.WeightedDistanceFunction,\
-# de.lmu.ifi.dbs.elki.distance.distancefunction.WeightedLPNormDistanceFunction,\
-# de.lmu.ifi.dbs.elki.distance.distancefunction.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,\
- de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.PearsonCorrelationDistanceFunction,\
- de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.SquaredPearsonCorrelationDistanceFunction,\
-# de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.WeightedPearsonCorrelationDistanceFunction,\
-# de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.WeightedSquaredPearsonCorrelationDistanceFunction,\
- 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.subspace.DimensionSelectingDistanceFunction,\
- de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.DimensionsSelectingEuclideanDistanceFunction,\
- 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,\
-# #######################################################
-# primitive similarity functions - default package: de.lmu.ifi.dbs.elki.distance.similarityfunction
-de.lmu.ifi.dbs.elki.distance.similarityfunction.PrimitiveSimilarityFunction=\
- 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,\
-# #######################################################
-# spatial distance functions - default package: de.lmu.ifi.dbs.elki.distance.distancefunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDistanceFunction=\
- 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.SquaredEuclideanDistanceFunction,\
- de.lmu.ifi.dbs.elki.distance.distancefunction.colorhistogram.HistogramIntersectionDistanceFunction,\
- de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.DimensionSelectingDistanceFunction,\
- de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.DimensionsSelectingEuclideanDistanceFunction,\
-# #######################################################
-# spatial double distance functions - default package: de.lmu.ifi.dbs.elki.distance.distancefunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDoubleDistanceFunction=\
- 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.SquaredEuclideanDistanceFunction,\
- de.lmu.ifi.dbs.elki.distance.distancefunction.colorhistogram.HistogramIntersectionDistanceFunction,\
- de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.DimensionSelectingDistanceFunction,\
- de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.DimensionsSelectingEuclideanDistanceFunction,\
-# #######################################################
-# preprocessor based distance functions - default package: de.lmu.ifi.dbs.elki.distance.distancefunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.AbstractIndexBasedDistanceFunction=\
- de.lmu.ifi.dbs.elki.distance.distancefunction.LocallyWeightedDistanceFunction,\
- de.lmu.ifi.dbs.elki.distance.distancefunction.SharedNearestNeighborJaccardDistanceFunction,\
- de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.ERiCDistanceFunction,\
- de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.PCABasedCorrelationDistanceFunction,\
- de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.SubspaceDistanceFunction,\
- de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.DiSHDistanceFunction,\
- de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.HiSCDistanceFunction,\
-# #######################################################
-# locally weighted distance functions - default package: de.lmu.ifi.dbs.elki.distance.distancefunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.LocallyWeightedDistanceFunction=\
-# #######################################################
-# distance parser - default package: de.lmu.ifi.dbs.elki.datasource.parser
-de.lmu.ifi.dbs.elki.datasource.parser.DistanceParser=\
- de.lmu.ifi.dbs.elki.datasource.parser.NumberDistanceParser,\
-# #######################################################
-# similarity function - default package: de.lmu.ifi.dbs.elki.distance.similarityfunction
-de.lmu.ifi.dbs.elki.distance.similarityfunction.SimilarityFunction=\
- de.lmu.ifi.dbs.elki.distance.similarityfunction.FractionalSharedNearestNeighborSimilarityFunction,\
- de.lmu.ifi.dbs.elki.distance.similarityfunction.SharedNearestNeighborSimilarityFunction,\
-# 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,\
-# #######################################################
-# normalized similarity function - default package: de.lmu.ifi.dbs.elki.distance.similarityfunction
-de.lmu.ifi.dbs.elki.distance.similarityfunction.NormalizedSimilarityFunction=\
- de.lmu.ifi.dbs.elki.distance.similarityfunction.FractionalSharedNearestNeighborSimilarityFunction,\
-# #######################################################
-# locally weighted distance functions - default package: de.lmu.ifi.dbs.elki.distance.distancefunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.FilteredLocalPCABasedDistanceFunction=\
- de.lmu.ifi.dbs.elki.distance.distancefunction.LocallyWeightedDistanceFunction,\
- de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.ERiCDistanceFunction,\
- de.lmu.ifi.dbs.elki.distance.distancefunction.correlation.PCABasedCorrelationDistanceFunction,\
- de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.SubspaceDistanceFunction,\
-# #######################################################
-# dimensions selecting distance functions - default package: de.lmu.ifi.dbs.elki.distance.distancefunction
-de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.AbstractDimensionsSelectingDoubleDistanceFunction=\
- de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.DimensionsSelectingEuclideanDistanceFunction,\
-# #######################################################
-# evaluators - default package: de.lmu.ifi.dbs.elki.evaluation
-de.lmu.ifi.dbs.elki.evaluation.Evaluator=\
- de.lmu.ifi.dbs.elki.evaluation.histogram.ComputeOutlierHistogram,\
- de.lmu.ifi.dbs.elki.evaluation.index.IndexStatistics,\
- de.lmu.ifi.dbs.elki.evaluation.outlier.JudgeOutlierScores,\
- de.lmu.ifi.dbs.elki.evaluation.paircounting.EvaluatePairCountingFMeasure,\
- de.lmu.ifi.dbs.elki.evaluation.roc.ComputeROCCurve,\
- de.lmu.ifi.dbs.elki.evaluation.similaritymatrix.ComputeSimilarityMatrixImage,\
-# #######################################################
-# Parser - default package: de.lmu.ifi.dbs.elki.datasource.parser
-de.lmu.ifi.dbs.elki.datasource.parser.Parser=\
- de.lmu.ifi.dbs.elki.datasource.parser.DoubleVectorLabelParser,\
- de.lmu.ifi.dbs.elki.datasource.parser.ArffParser,\
- de.lmu.ifi.dbs.elki.datasource.parser.FloatVectorLabelParser,\
- de.lmu.ifi.dbs.elki.datasource.parser.DoubleVectorLabelTransposingParser,\
- de.lmu.ifi.dbs.elki.datasource.parser.SparseBitVectorLabelParser,\
- de.lmu.ifi.dbs.elki.datasource.parser.SparseFloatVectorLabelParser,\
- de.lmu.ifi.dbs.elki.datasource.parser.TermFrequencyParser,\
- de.lmu.ifi.dbs.elki.datasource.parser.BitVectorLabelParser,\
- de.lmu.ifi.dbs.elki.datasource.parser.ParameterizationFunctionLabelParser,\
- de.lmu.ifi.dbs.elki.datasource.parser.SimplePolygonParser,\
-# #######################################################
-# Line based parsers
-de.lmu.ifi.dbs.elki.datasource.parser.LinebasedParser=\
- de.lmu.ifi.dbs.elki.datasource.parser.DoubleVectorLabelParser,\
- de.lmu.ifi.dbs.elki.datasource.parser.FloatVectorLabelParser,\
- de.lmu.ifi.dbs.elki.datasource.parser.DoubleVectorLabelTransposingParser,\
- de.lmu.ifi.dbs.elki.datasource.parser.SparseFloatVectorLabelParser,\
- de.lmu.ifi.dbs.elki.datasource.parser.TermFrequencyParser,\
-# #######################################################
-# Filter - default package: de.lmu.ifi.dbs.elki.datasource.filter
-de.lmu.ifi.dbs.elki.datasource.filter.ObjectFilter=\
- de.lmu.ifi.dbs.elki.datasource.filter.AttributeWiseErfNormalization,\
- de.lmu.ifi.dbs.elki.datasource.filter.AttributeWiseMinMaxNormalization,\
- de.lmu.ifi.dbs.elki.datasource.filter.AttributeWiseVarianceNormalization,\
- de.lmu.ifi.dbs.elki.datasource.filter.ClassLabelFilter,\
- de.lmu.ifi.dbs.elki.datasource.filter.DoubleVectorProjectionFilter,\
- de.lmu.ifi.dbs.elki.datasource.filter.DoubleVectorRandomProjectionFilter,\
- de.lmu.ifi.dbs.elki.datasource.filter.ExternalIDFilter,\
- de.lmu.ifi.dbs.elki.datasource.filter.FilterByLabelFilter,\
- de.lmu.ifi.dbs.elki.datasource.filter.FixedDBIDsFilter,\
- de.lmu.ifi.dbs.elki.datasource.filter.InverseDocumentFrequencyNormalization,\
- de.lmu.ifi.dbs.elki.datasource.filter.FilterNoMissingValuesFilter,\
- de.lmu.ifi.dbs.elki.datasource.filter.ShuffleObjectsFilter,\
- de.lmu.ifi.dbs.elki.datasource.filter.SortByLabelFilter,\
- de.lmu.ifi.dbs.elki.datasource.filter.SparseFloatVectorProjectionFilter,\
- de.lmu.ifi.dbs.elki.datasource.filter.SparseFloatVectorRandomProjectionFilter,\
- de.lmu.ifi.dbs.elki.datasource.filter.SplitNumberVectorFilter,\
- de.lmu.ifi.dbs.elki.datasource.filter.TFIDFNormalization,\
- de.lmu.ifi.dbs.elki.datasource.filter.NoOpFilter,\
-# #######################################################
-# Indexes - default package: de.lmu.ifi.dbs.elki.index
-de.lmu.ifi.dbs.elki.index.IndexFactory=\
- 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.rdknn.RdKNNTreeFactory,\
- 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.preprocessed.knn.MaterializeKNNAndRKNNPreprocessor$Factory,\
- de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNPreprocessor$Factory,\
- de.lmu.ifi.dbs.elki.index.preprocessed.knn.MetricalIndexApproximationMaterializeKNNPreprocessor$Factory,\
- de.lmu.ifi.dbs.elki.index.preprocessed.knn.PartitionApproximationMaterializeKNNPreprocessor$Factory,\
- de.lmu.ifi.dbs.elki.index.preprocessed.knn.SpatialApproximationMaterializeKNNPreprocessor$Factory,\
- de.lmu.ifi.dbs.elki.index.preprocessed.localpca.KNNQueryFilteredPCAIndex$Factory,\
- de.lmu.ifi.dbs.elki.index.preprocessed.localpca.RangeQueryFilteredPCAIndex$Factory,\
- de.lmu.ifi.dbs.elki.index.preprocessed.preference.DiSHPreferenceVectorIndex$Factory,\
- 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,\
-# #######################################################
-# KNN Index - default package: de.lmu.ifi.dbs.elki.index
-de.lmu.ifi.dbs.elki.index.KNNIndex=\
- 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.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.MaterializeKNNAndRKNNPreprocessor,\
- de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNPreprocessor,\
- de.lmu.ifi.dbs.elki.index.preprocessed.knn.MetricalIndexApproximationMaterializeKNNPreprocessor,\
- de.lmu.ifi.dbs.elki.index.preprocessed.knn.PartitionApproximationMaterializeKNNPreprocessor,\
- de.lmu.ifi.dbs.elki.index.preprocessed.knn.SpatialApproximationMaterializeKNNPreprocessor,\
-# #######################################################
-# Range Index - default package: de.lmu.ifi.dbs.elki.index
-de.lmu.ifi.dbs.elki.index.RangeIndex=\
- 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.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,\
-# #######################################################
-# RKNN Index - default package: de.lmu.ifi.dbs.elki.index
-de.lmu.ifi.dbs.elki.index.RKNNIndex=\
- de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNAndRKNNPreprocessor,\
- 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.tree.spatial.rstarvariants.rdknn.RdKNNTree,\
-# #######################################################
-# FilteredLocalPCAIndex - default package: de.lmu.ifi.dbs.elki.index.index.preprocessed.localpca
-de.lmu.ifi.dbs.elki.index.preprocessed.LocalProjectionIndex$Factory=\
- de.lmu.ifi.dbs.elki.index.preprocessed.localpca.KNNQueryFilteredPCAIndex$Factory,\
- de.lmu.ifi.dbs.elki.index.preprocessed.localpca.RangeQueryFilteredPCAIndex$Factory,\
- de.lmu.ifi.dbs.elki.index.preprocessed.subspaceproj.FourCSubspaceIndex$Factory,\
- de.lmu.ifi.dbs.elki.index.preprocessed.subspaceproj.PreDeConSubspaceIndex$Factory,\
-# #######################################################
-# FilteredLocalPCAIndex - default package: de.lmu.ifi.dbs.elki.index.index.preprocessed.localpca
-de.lmu.ifi.dbs.elki.index.preprocessed.localpca.FilteredLocalPCAIndex$Factory=\
- de.lmu.ifi.dbs.elki.index.preprocessed.localpca.KNNQueryFilteredPCAIndex$Factory,\
- de.lmu.ifi.dbs.elki.index.preprocessed.localpca.RangeQueryFilteredPCAIndex$Factory,\
-# #######################################################
-# Materialize KNN Preprocessor - default package: de.lmu.ifi.dbs.elki.index.preprocessed.knn
-de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNPreprocessor=\
- de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNPreprocessor,\
- de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNAndRKNNPreprocessor,\
-# #######################################################
-# PreferenceVectorIndex - default package: de.lmu.ifi.dbs.elki.index.preprocessed.preference
-de.lmu.ifi.dbs.elki.index.preprocessed.preference.PreferenceVectorIndex$Factory=\
- de.lmu.ifi.dbs.elki.index.preprocessed.preference.DiSHPreferenceVectorIndex$Factory,\
- de.lmu.ifi.dbs.elki.index.preprocessed.preference.HiSCPreferenceVectorIndex$Factory,\
-# #######################################################
-# SNN Index - default package: de.lmu.ifi.dbs.elki.index.preprocessed.subspaceproj
-de.lmu.ifi.dbs.elki.index.preprocessed.snn.SharedNearestNeighborIndex$Factory=\
- de.lmu.ifi.dbs.elki.index.preprocessed.snn.SharedNearestNeighborPreprocessor$Factory,\
-# #######################################################
-# ProjectedDBSCANPreprocessor - default package: de.lmu.ifi.dbs.elki.index.preprocessed.subspaceproj
-de.lmu.ifi.dbs.elki.index.preprocessed.subspaceproj.SubspaceProjectionIndex$Factory=\
- de.lmu.ifi.dbs.elki.index.preprocessed.subspaceproj.FourCSubspaceIndex$Factory,\
- de.lmu.ifi.dbs.elki.index.preprocessed.subspaceproj.PreDeConSubspaceIndex$Factory,\
-# #######################################################
-# Bulk split strategy - default package: de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.bulk
-de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.bulk.BulkSplit=\
- de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.bulk.MaxExtensionBulkSplit,\
- de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.bulk.ZCurveBulkSplit,\
-# #######################################################
-# Page split strategy - default package: de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util
-de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.SplitStrategy=\
- de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.TopologicalSplitter,\
-# #######################################################
-# Entry insert strategy - default package: de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util
-de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.InsertionStrategy=\
- de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.ApproximateLeastOverlapInsertionStrategy,\
- de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util.LeastOverlapInsertionStrategy,\
-# #######################################################
-# ResultHandler - default package: de.lmu.ifi.dbs.elki.result
-de.lmu.ifi.dbs.elki.result.ResultHandler=\
- de.lmu.ifi.dbs.elki.result.ResultWriter,\
- de.lmu.ifi.dbs.elki.visualization.gui.ResultVisualizer,\
- de.lmu.ifi.dbs.elki.result.DiscardResultHandler,\
- de.lmu.ifi.dbs.elki.result.KMLOutputHandler,\
- de.lmu.ifi.dbs.elki.application.jsmap.JSONResultHandler,\
-# #######################################################
-# EigenPairFilter - default package: de.lmu.ifi.dbs.elki.math.linearalgebra.pca
-de.lmu.ifi.dbs.elki.math.linearalgebra.pca.EigenPairFilter=\
- de.lmu.ifi.dbs.elki.math.linearalgebra.pca.FirstNEigenPairFilter,\
-# de.lmu.ifi.dbs.elki.math.linearalgebra.pca.NormalizingEigenPairFilter,\
- de.lmu.ifi.dbs.elki.math.linearalgebra.pca.LimitEigenPairFilter,\
- de.lmu.ifi.dbs.elki.math.linearalgebra.pca.PercentageEigenPairFilter,\
- de.lmu.ifi.dbs.elki.math.linearalgebra.pca.ProgressiveEigenPairFilter,\
- de.lmu.ifi.dbs.elki.math.linearalgebra.pca.WeakEigenPairFilter,\
- de.lmu.ifi.dbs.elki.math.linearalgebra.pca.RelativeEigenPairFilter,\
- de.lmu.ifi.dbs.elki.math.linearalgebra.pca.SignificantEigenPairFilter,\
- de.lmu.ifi.dbs.elki.math.linearalgebra.pca.CompositeEigenPairFilter,\
-# #######################################################
-# CovarianceMatrixBuilder - default package: de.lmu.ifi.dbs.elki.math.linearalgebra.pca
-de.lmu.ifi.dbs.elki.math.linearalgebra.pca.CovarianceMatrixBuilder=\
- de.lmu.ifi.dbs.elki.math.linearalgebra.pca.StandardCovarianceMatrixBuilder,\
- de.lmu.ifi.dbs.elki.math.linearalgebra.pca.WeightedCovarianceMatrixBuilder,\
-# #######################################################
-# WeightFunction - default package: de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions
-de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions.WeightFunction=\
- de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions.ConstantWeight,\
- de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions.ErfcStddevWeight,\
- de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions.ErfcWeight,\
- de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions.ExponentialStddevWeight,\
- de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions.ExponentialWeight,\
- de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions.GaussStddevWeight,\
- de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions.GaussWeight,\
- de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions.InverseLinearWeight,\
- de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions.InverseProportionalStddevWeight,\
- de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions.InverseProportionalWeight,\
- de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions.LinearWeight,\
- de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions.QuadraticStddevWeight,\
- de.lmu.ifi.dbs.elki.math.linearalgebra.pca.weightfunctions.QuadraticWeight,\
-# #######################################################
-# Reference point strategies - default package: de.lmu.ifi.dbs.elki.utilities.referencepoints
-de.lmu.ifi.dbs.elki.utilities.referencepoints.ReferencePointsHeuristic=\
- de.lmu.ifi.dbs.elki.utilities.referencepoints.GridBasedReferencePoints,\
- de.lmu.ifi.dbs.elki.utilities.referencepoints.AxisBasedReferencePoints,\
- de.lmu.ifi.dbs.elki.utilities.referencepoints.FullDatabaseReferencePoints,\
- de.lmu.ifi.dbs.elki.utilities.referencepoints.RandomGeneratedReferencePoints,\
- de.lmu.ifi.dbs.elki.utilities.referencepoints.RandomSampleReferencePoints,\
- de.lmu.ifi.dbs.elki.utilities.referencepoints.StarBasedReferencePoints,\
-# #######################################################
-# Scaling Functions - default package: de.lmu.ifi.dbs.elki.utilities.scaling
-de.lmu.ifi.dbs.elki.utilities.scaling.ScalingFunction=\
- de.lmu.ifi.dbs.elki.utilities.scaling.IdentityScaling,\
- de.lmu.ifi.dbs.elki.utilities.scaling.ClipScaling,\
- de.lmu.ifi.dbs.elki.utilities.scaling.GammaScaling,\
- 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.MinusLogGammaScaling,\
- de.lmu.ifi.dbs.elki.utilities.scaling.outlier.MinusLogStandardDeviationScaling,\
- de.lmu.ifi.dbs.elki.utilities.scaling.outlier.MultiplicativeInverseScaling,\
- de.lmu.ifi.dbs.elki.utilities.scaling.outlier.OutlierGammaScaling,\
- de.lmu.ifi.dbs.elki.utilities.scaling.outlier.OutlierMinusLogScaling,\
- de.lmu.ifi.dbs.elki.utilities.scaling.outlier.OutlierSqrtScaling,\
- 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.RankingPseudoOutlierScaling,\
- de.lmu.ifi.dbs.elki.utilities.scaling.outlier.SigmoidOutlierScalingFunction,\
-# #######################################################
-# Scaling Functions - default package: de.lmu.ifi.dbs.elki.utilities.scaling
-de.lmu.ifi.dbs.elki.utilities.scaling.StaticScalingFunction=\
- de.lmu.ifi.dbs.elki.utilities.scaling.IdentityScaling,\
- de.lmu.ifi.dbs.elki.utilities.scaling.ClipScaling,\
- de.lmu.ifi.dbs.elki.utilities.scaling.GammaScaling,\
- de.lmu.ifi.dbs.elki.utilities.scaling.LinearScaling,\
- de.lmu.ifi.dbs.elki.utilities.scaling.MinusLogScaling,\
-# #######################################################
-# Outlier Scaling Functions - default package: de.lmu.ifi.dbs.elki.utilities.scaling.outlier
-de.lmu.ifi.dbs.elki.utilities.scaling.outlier.OutlierScalingFunction=\
- 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.MinusLogGammaScaling,\
- de.lmu.ifi.dbs.elki.utilities.scaling.outlier.MinusLogStandardDeviationScaling,\
- de.lmu.ifi.dbs.elki.utilities.scaling.outlier.MultiplicativeInverseScaling,\
- de.lmu.ifi.dbs.elki.utilities.scaling.outlier.OutlierGammaScaling,\
- de.lmu.ifi.dbs.elki.utilities.scaling.outlier.OutlierMinusLogScaling,\
- de.lmu.ifi.dbs.elki.utilities.scaling.outlier.OutlierSqrtScaling,\
- 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,\
-# #######################################################
-# Spatial outlier neighborhoods - default package: de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.neighborhood
-de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.neighborhood.NeighborSetPredicate$Factory=\
- de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.neighborhood.ExtendedNeighborhood$Factory,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.neighborhood.ExternalNeighborhood$Factory,\
- de.lmu.ifi.dbs.elki.algorithm.outlier.spatial.neighborhood.PrecomputedKNearestNeighborNeighborhood$Factory,\
-# ####################################################### \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/properties/IterateKnownImplementations.java b/src/de/lmu/ifi/dbs/elki/properties/IterateKnownImplementations.java
deleted file mode 100644
index 3cab826f..00000000
--- a/src/de/lmu/ifi/dbs/elki/properties/IterateKnownImplementations.java
+++ /dev/null
@@ -1,152 +0,0 @@
-package de.lmu.ifi.dbs.elki.properties;
-
-/*
- 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 java.util.Iterator;
-import java.util.regex.Pattern;
-
-import de.lmu.ifi.dbs.elki.logging.Logging;
-import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
-
-/**
- * Iterator over all instanciable classes of a given superclass/interface.
- *
- * The list of "known" implementations is obtained via the ELKI properties
- * mechanism.
- *
- * @author Erich Schubert
- *
- * @apiviz.uses Properties oneway - - reads from
- */
-public class IterateKnownImplementations implements IterableIterator<Class<?>> {
- /**
- * Logger
- */
- private static final Logging logger = Logging.getLogger(Properties.class);
-
- /**
- * Pattern to detect comments
- */
- private final static Pattern COMMENTS = Pattern.compile("^\\s*(#.*)?$");
-
- /**
- * Current class = next iterator value
- */
- Class<?> cur = null;
-
- /**
- * Index within the class names array
- */
- int index = 0;
-
- /**
- * Class names array
- */
- String[] classNames = null;
-
- /**
- * Super class
- */
- Class<?> superclass = null;
-
- /**
- * Constructor.
- *
- * @param superclass Superclass to find implementations for.
- */
- public IterateKnownImplementations(Class<?> superclass) {
- this.superclass = superclass;
- this.classNames = Properties.ELKI_PROPERTIES.getProperty(superclass.getName());
- findNext();
- }
-
- /**
- * Find the next 'acceptable' result.
- */
- private void findNext() {
- if(classNames == null) {
- return;
- }
- cur = null;
- for(; index < classNames.length; index++) {
- String name = classNames[index];
- // skip commented classes.
- if (COMMENTS.matcher(name).matches()) {
- continue;
- }
- try {
- cur = Class.forName(name);
- }
- catch(ClassNotFoundException e) {
- logger.warning("Class " + name + " (from properties file) not found for superclass " + this.superclass.getName());
- continue;
- }
- if(!this.superclass.isAssignableFrom(cur)) {
- logger.warning("Class " + name + " (from properties file) is not a subclass of " + this.superclass.getName());
- continue;
- }
- // last iteration - matched!
- {
- index++;
- break;
- }
- }
- }
-
- /**
- * Return if there is a next known implementation
- */
- @Override
- public boolean hasNext() {
- return cur != null;
- }
-
- /**
- * Advance the iterator, returning the 'next' result
- */
- @Override
- public Class<?> next() {
- Class<?> ret = cur;
- findNext();
- return ret;
- }
-
- /**
- * Removals are not supported by this iterator.
- *
- * @throws UnsupportedOperationException Not supported.
- */
- @Override
- public void remove() throws UnsupportedOperationException {
- throw new UnsupportedOperationException();
- }
-
- /**
- * Adapter for {@link java.lang.Iterable} interface for foreach statements
- */
- @Override
- public Iterator<Class<?>> iterator() {
- return this;
- }
-} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/properties/Properties.java b/src/de/lmu/ifi/dbs/elki/properties/Properties.java
deleted file mode 100644
index af777c1e..00000000
--- a/src/de/lmu/ifi/dbs/elki/properties/Properties.java
+++ /dev/null
@@ -1,111 +0,0 @@
-package de.lmu.ifi.dbs.elki.properties;
-
-/*
- 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 java.io.File;
-import java.io.FileNotFoundException;
-import java.io.InputStream;
-import java.util.Set;
-import java.util.regex.Pattern;
-
-import de.lmu.ifi.dbs.elki.logging.Logging;
-import de.lmu.ifi.dbs.elki.logging.LoggingConfiguration;
-import de.lmu.ifi.dbs.elki.utilities.FileUtil;
-
-/**
- * Provides management of properties.
- *
- * @author Arthur Zimek
- */
-public final class Properties {
- /**
- * Out logger
- */
- private static final Logging logger = Logging.getLogger(Properties.class);
-
- /**
- * The pattern to split for separate entries in a property string, which is a
- * &quot;,&quot;.
- */
- public static final Pattern PROPERTY_SEPARATOR = Pattern.compile(",");
-
- /**
- * The Properties for ELKI.
- */
- public static final Properties ELKI_PROPERTIES;
-
- static {
- String name = Properties.class.getPackage().getName().replace('.', File.separatorChar) + File.separatorChar + "ELKI.properties";
- ELKI_PROPERTIES = new Properties(name);
- }
-
- /**
- * Stores the properties as defined by a property-file.
- */
- private final java.util.Properties properties;
-
- /**
- * Provides the properties as defined in the designated file.
- *
- * @param filename name of a file to provide property-definitions.
- */
- private Properties(String filename) {
- LoggingConfiguration.assertConfigured();
- this.properties = new java.util.Properties();
- try {
- InputStream stream = FileUtil.openSystemFile(filename);
- properties.load(stream);
- }
- catch(FileNotFoundException e) {
- logger.warning("Unable to get properties file " + filename + ".\n");
- return;
- }
- catch(Exception e) {
- logger.warning("Error loading properties file " + filename + ".\n", e);
- }
- }
-
- /**
- * Provides the entries (as separated by {@link #PROPERTY_SEPARATOR
- * PROPERTY_SEPARATOR}) for a specified PropertyName.
- *
- * @param propertyName the PropertyName of the property to retrieve
- * @return the entries (separated by {@link #PROPERTY_SEPARATOR
- * PROPERTY_SEPARATOR}) for the specified PropertyName - if the
- * property is undefined, the returned array is of length 0
- */
- public String[] getProperty(String propertyName) {
- String property = properties.getProperty(propertyName);
- return property == null ? new String[0] : PROPERTY_SEPARATOR.split(property);
- }
-
- /**
- * Get a collection of all property names in this file.
- *
- * @return Property names in this file.
- */
- public Set<String> getPropertyNames() {
- return properties.stringPropertyNames();
- }
-}
diff --git a/src/de/lmu/ifi/dbs/elki/result/AbstractHierarchicalResult.java b/src/de/lmu/ifi/dbs/elki/result/AbstractHierarchicalResult.java
index f5e89e13..0eba9564 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) 2011
+ Copyright (C) 2012
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 cbd1acfa..6b289f11 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) 2011
+ Copyright (C) 2012
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 4aa46d0f..0e3bc571 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) 2011
+ Copyright (C) 2012
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 1ce10063..a43c6fd6 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) 2011
+ Copyright (C) 2012
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 41c50bb1..d504ecbc 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) 2011
+Copyright (C) 2012
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 486a47a9..2499ff6a 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) 2011
+ Copyright (C) 2012
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 4b5245b4..695ba1aa 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) 2011
+ Copyright (C) 2012
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 7a6da96b..406eeffc 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) 2011
+ Copyright (C) 2012
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 b8bd27db..b53b4bb0 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) 2011
+ Copyright (C) 2012
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 112ec7b8..7939d0a2 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -138,7 +138,10 @@ public class KMLOutputHandler implements ResultHandler, Parameterizable {
XMLOutputFactory factory = XMLOutputFactory.newInstance();
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(filename));
out.putNextEntry(new ZipEntry("doc.kml"));
- writeKMLData(factory.createXMLStreamWriter(out), ors.get(0), database);
+ final XMLStreamWriter xmlw = factory.createXMLStreamWriter(out);
+ writeKMLData(xmlw, ors.get(0), database);
+ xmlw.flush();
+ xmlw.close();
out.closeEntry();
out.flush();
out.close();
@@ -336,7 +339,13 @@ public class KMLOutputHandler implements ResultHandler, Parameterizable {
}
}
- private static final Color getColorForValue(double val) {
+ /**
+ * Get color from a simple heatmap.
+ *
+ * @param val Score value
+ * @return Color in heatmap
+ */
+ public static final Color getColorForValue(double val) {
// Color positions
double[] pos = new double[] { 0.0, 0.6, 0.8, 1.0 };
// Colors at these positions
diff --git a/src/de/lmu/ifi/dbs/elki/result/KNNDistanceOrderResult.java b/src/de/lmu/ifi/dbs/elki/result/KNNDistanceOrderResult.java
index 1f62c7bc..0e5782bc 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) 2011
+ Copyright (C) 2012
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/OrderingFromDataStore.java b/src/de/lmu/ifi/dbs/elki/result/OrderingFromDataStore.java
index 537f04d8..27178fe5 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) 2011
+ Copyright (C) 2012
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.result;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.Collections;
import java.util.Comparator;
import de.lmu.ifi.dbs.elki.database.datastore.DataStore;
@@ -122,10 +121,10 @@ public class OrderingFromDataStore<T extends Comparable<T>> extends BasicResult
public IterableIterator<DBID> iter(DBIDs ids) {
ArrayModifiableDBIDs sorted = DBIDUtil.newArray(ids);
if(comparator != null) {
- Collections.sort(sorted, new DerivedComparator());
+ sorted.sort(new DerivedComparator());
}
else {
- Collections.sort(sorted, new ImpliedComparator());
+ sorted.sort(new ImpliedComparator());
}
return IterableUtil.fromIterable(sorted);
}
diff --git a/src/de/lmu/ifi/dbs/elki/result/OrderingResult.java b/src/de/lmu/ifi/dbs/elki/result/OrderingResult.java
index 043ec618..4cd01721 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) 2011
+ Copyright (C) 2012
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 ca832ecf..776753e2 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) 2011
+ Copyright (C) 2012
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 87da7a4b..f70c1771 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) 2011
+Copyright (C) 2012
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 5ec78478..3964c418 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) 2011
+Copyright (C) 2012
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 3a90b7ce..ebd0bed1 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) 2011
+ Copyright (C) 2012
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 bdadd2d9..be81a508 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) 2011
+ Copyright (C) 2012
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 04532ec9..1fef628f 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) 2011
+ Copyright (C) 2012
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 0ecf6f82..bf2eefe6 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -76,8 +76,8 @@ public class ResultHierarchy extends HierarchyHashmapList<Result> {
@Override
public void remove(Result parent, Result child) {
- // TODO: unlink from hierarchy, fire event
- throw new UnsupportedOperationException();
+ super.remove(parent, child);
+ fireResultRemoved(child, parent);
}
@Override
@@ -149,7 +149,6 @@ public class ResultHierarchy extends HierarchyHashmapList<Result> {
* @param child result that has been removed
* @param parent Parent result that has been removed
*/
- @SuppressWarnings("unused")
private void fireResultRemoved(Result child, Result parent) {
if(logger.isDebugging()) {
logger.debug("Result removed: " + child + " <- " + parent);
diff --git a/src/de/lmu/ifi/dbs/elki/result/ResultListener.java b/src/de/lmu/ifi/dbs/elki/result/ResultListener.java
index 9dca067f..d675af28 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) 2011
+ Copyright (C) 2012
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 6590b736..47273b89 100644
--- a/src/de/lmu/ifi/dbs/elki/result/ResultProcessor.java
+++ b/src/de/lmu/ifi/dbs/elki/result/ResultProcessor.java
@@ -1,10 +1,12 @@
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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -32,7 +34,7 @@ package de.lmu.ifi.dbs.elki.result;
*
* @apiviz.uses Result oneway - - processes
*/
-public interface ResultProcessor {
+public interface ResultProcessor extends InspectionUtilFrequentlyScanned {
/**
* 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 96cfe9f4..1666d6fc 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) 2011
+ Copyright (C) 2012
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.algorithm.clustering.ClusteringAlgorithm;
import de.lmu.ifi.dbs.elki.algorithm.clustering.trivial.ByLabelHierarchicalClustering;
import de.lmu.ifi.dbs.elki.algorithm.clustering.trivial.TrivialAllInOne;
import de.lmu.ifi.dbs.elki.data.Clustering;
+import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.data.model.Model;
import de.lmu.ifi.dbs.elki.data.type.NoSupportedDataTypeException;
import de.lmu.ifi.dbs.elki.database.Database;
@@ -41,7 +42,6 @@ import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
import de.lmu.ifi.dbs.elki.utilities.iterator.EmptyIterator;
import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
-import de.lmu.ifi.dbs.elki.utilities.iterator.IterableUtil;
import de.lmu.ifi.dbs.elki.utilities.iterator.MergedIterator;
import de.lmu.ifi.dbs.elki.utilities.iterator.OneItemIterator;
import de.lmu.ifi.dbs.elki.utilities.iterator.TypeFilterIterator;
@@ -191,20 +191,14 @@ public class ResultUtil {
@SuppressWarnings("unchecked")
public static <C> ArrayList<C> filterResults(Result r, Class<?> restrictionClass) {
ArrayList<C> res = new ArrayList<C>();
- try {
+ if(restrictionClass.isInstance(r)) {
res.add((C) restrictionClass.cast(r));
}
- catch(ClassCastException e) {
- // ignore
- }
if(r instanceof HierarchicalResult) {
for(Result result : ((HierarchicalResult) r).getHierarchy().iterDescendants(r)) {
- try {
+ if(restrictionClass.isInstance(result)) {
res.add((C) restrictionClass.cast(result));
}
- catch(ClassCastException e) {
- // ignore
- }
}
}
return res;
@@ -215,21 +209,21 @@ public class ResultUtil {
final Class<C> rc = (Class<C>) restrictionClass;
// Include the current item
IterableIterator<C> curIter;
- try {
+ if(rc.isInstance(r)) {
curIter = new OneItemIterator<C>(rc.cast(r));
}
- catch(ClassCastException e) {
+ else {
curIter = null;
}
if(r instanceof HierarchicalResult) {
ResultHierarchy hier = ((HierarchicalResult) r).getHierarchy();
final Iterable<Result> iterDescendants = hier.iterDescendants(r);
- final Iterator<C> others = new TypeFilterIterator<Result, C>(rc, iterDescendants);
+ final IterableIterator<C> others = new TypeFilterIterator<Result, C>(rc, iterDescendants);
if(curIter != null) {
- return IterableUtil.fromIterator(new MergedIterator<C>(curIter, others));
+ return new MergedIterator<C>(curIter, others);
}
else {
- return IterableUtil.fromIterator(others);
+ return others;
}
}
else {
@@ -268,13 +262,48 @@ public class ResultUtil {
* Ensure that there also is a selection container object.
*
* @param db Database
- * @param result Result
+ * @return selection result
*/
- public static void ensureSelectionResult(final Database db, final Result result) {
- Collection<SelectionResult> selections = ResultUtil.filterResults(result, SelectionResult.class);
+ public static SelectionResult ensureSelectionResult(final Database db) {
+ Iterator<SelectionResult> selections = ResultUtil.filteredResults(db, SelectionResult.class);
+ if(selections.hasNext()) {
+ return selections.next();
+ }
+ SelectionResult sel = new SelectionResult();
+ addChildResult(db, sel);
+ return sel;
+ }
+
+ /**
+ * Get the sampling result attached to a relation
+ *
+ * @param rel Relation
+ * @return Sampling result.
+ */
+ public static SamplingResult getSamplingResult(final Relation<?> rel) {
+ Collection<SamplingResult> selections = ResultUtil.filterResults(rel, SamplingResult.class);
if(selections.size() == 0) {
- addChildResult(db, new SelectionResult());
+ final SamplingResult newsam = new SamplingResult(rel);
+ addChildResult(rel, newsam);
+ return newsam;
+ }
+ return selections.iterator().next();
+ }
+
+ /**
+ * Get (or create) a scales result for a relation.
+ *
+ * @param rel Relation
+ * @return associated scales result
+ */
+ public static ScalesResult getScalesResult(final Relation<? extends NumberVector<?, ?>> rel) {
+ Collection<ScalesResult> scas = ResultUtil.filterResults(rel, ScalesResult.class);
+ if(scas.size() == 0) {
+ final ScalesResult newsca = new ScalesResult(rel);
+ addChildResult(rel, newsca);
+ return newsca;
}
+ return scas.iterator().next();
}
/**
@@ -302,4 +331,19 @@ public class ResultUtil {
return null;
}
}
+
+ /**
+ * Recursively remove a result and its children.
+ *
+ * @param hierarchy Result hierarchy
+ * @param child Result to remove
+ */
+ public static void removeRecursive(ResultHierarchy hierarchy, Result child) {
+ for(Result parent : hierarchy.getParents(child)) {
+ hierarchy.remove(parent, child);
+ }
+ for(Result sub : hierarchy.getChildren(child)) {
+ removeRecursive(hierarchy, sub);
+ }
+ }
} \ 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 14e64269..ed8934a6 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) 2011
+ Copyright (C) 2012
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/SamplingResult.java b/src/de/lmu/ifi/dbs/elki/result/SamplingResult.java
new file mode 100644
index 00000000..5e6c3df2
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/result/SamplingResult.java
@@ -0,0 +1,77 @@
+package de.lmu.ifi.dbs.elki.result;
+
+import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Wrapper for storing the current database sample.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.composedOf DBIDs
+ */
+public class SamplingResult implements Result {
+ /**
+ * The actual selection
+ */
+ DBIDs sample = null;
+
+ /**
+ * Constructor.
+ *
+ * @param rel Relation
+ */
+ public SamplingResult(Relation<?> rel) {
+ super();
+ sample = rel.getDBIDs();
+ }
+
+ /**
+ * @return the current sample
+ */
+ public DBIDs getSample() {
+ return sample;
+ }
+
+ /**
+ * Note: trigger a resultchanged event!
+ *
+ * @param sample the new sample
+ */
+ public void setSample(DBIDs sample) {
+ this.sample = sample;
+ }
+
+ @Override
+ public String getLongName() {
+ return "Sample";
+ }
+
+ @Override
+ public String getShortName() {
+ return "sample";
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/result/ScalesResult.java b/src/de/lmu/ifi/dbs/elki/result/ScalesResult.java
new file mode 100644
index 00000000..89cd4af2
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/result/ScalesResult.java
@@ -0,0 +1,85 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.math.scales.LinearScale;
+import de.lmu.ifi.dbs.elki.math.scales.Scales;
+
+/**
+ * Class to keep shared scales across visualizers.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.composedOf LinearScale
+ */
+public class ScalesResult extends BasicResult {
+ /**
+ * The scales in use.
+ */
+ private LinearScale[] scales;
+
+ /**
+ * Constructor.
+ *
+ * @param relation
+ */
+ public ScalesResult(Relation<? extends NumberVector<?, ?>> relation) {
+ super("scales", "scales");
+ scales = Scales.calcScales(relation);
+ }
+
+ /**
+ * Get the scale for dimension dim (starting at 1!).
+ *
+ * @param dim Dimension
+ * @return Scale
+ */
+ public LinearScale getScale(int dim) {
+ return scales[dim - 1];
+ }
+
+ /**
+ * Set the scale for dimension dim (starting at 1!).
+ *
+ * Note: you still need to trigger an event. This is not done automatically,
+ * as you might want to set more than one scale!
+ *
+ * @param dim Dimension
+ * @param scale New scale
+ */
+ public void setScale(int dim, LinearScale scale) {
+ scales[dim - 1] = scale;
+ }
+
+ /**
+ * Get all scales. Note: you must not modify the array.
+ *
+ * @return Scales array.
+ */
+ public LinearScale[] getScales() {
+ return scales;
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/result/SelectionResult.java b/src/de/lmu/ifi/dbs/elki/result/SelectionResult.java
index d3bb2fd4..a8fb4ed5 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) 2011
+ Copyright (C) 2012
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.result;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-
-
/**
* Selection result wrapper.
*
diff --git a/src/de/lmu/ifi/dbs/elki/result/SettingsResult.java b/src/de/lmu/ifi/dbs/elki/result/SettingsResult.java
index 044ceaf4..0d0dc34d 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) 2011
+ Copyright (C) 2012
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 62d54045..06e4766f 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) 2011
+ Copyright (C) 2012
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 4a5a9636..6eea3415 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) 2011
+ Copyright (C) 2012
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/DoubleDistanceClusterOrderEntry.java b/src/de/lmu/ifi/dbs/elki/result/optics/DoubleDistanceClusterOrderEntry.java
index 018c1d4f..8f42e1eb 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) 2011
+ Copyright (C) 2012
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 8813a82a..c9ff0564 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) 2011
+ Copyright (C) 2012
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 8cb59763..a61eb417 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) 2011
+Copyright (C) 2012
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 09aa8dbf..5d56117c 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) 2011
+ Copyright (C) 2012
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 2c978bf2..8658c938 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) 2011
+ Copyright (C) 2012
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 ff211f30..5d35c74a 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) 2011
+ Copyright (C) 2012
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.result.outlier;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.Collections;
import java.util.Comparator;
import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs;
@@ -82,7 +81,7 @@ public class OrderingFromRelation implements OrderingResult {
@Override
public IterableIterator<DBID> iter(DBIDs ids) {
ArrayModifiableDBIDs sorted = DBIDUtil.newArray(ids);
- Collections.sort(sorted, new ImpliedComparator());
+ sorted.sort(new ImpliedComparator());
return new IterableIteratorAdapter<DBID>(sorted);
}
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 4389c7c8..5c4a58ae 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) 2011
+ Copyright (C) 2012
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 fa7fb796..c71f20ce 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) 2011
+ Copyright (C) 2012
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 65ef6f82..844bb919 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) 2011
+ Copyright (C) 2012
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 2cf9875e..e0dc36ec 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) 2011
+ Copyright (C) 2012
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 c6b61bfe..f72e5366 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) 2011
+Copyright (C) 2012
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 aba3dec6..70894b93 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) 2011
+Copyright (C) 2012
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 51eb5f8e..d891f1ee 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) 2011
+ Copyright (C) 2012
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/SingleStreamOutput.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/SingleStreamOutput.java
index 1e4e5773..46472f52 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) 2011
+ Copyright (C) 2012
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/StreamFactory.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/StreamFactory.java
index 1656d76d..0f27b354 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) 2011
+ Copyright (C) 2012
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/TextWriteable.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriteable.java
index ffc522eb..a8de4c46 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) 2011
+ Copyright (C) 2012
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 bbe3212b..d947547f 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,8 +29,8 @@ import java.io.PrintStream;
import java.util.BitSet;
import java.util.Collection;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Iterator;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -51,7 +51,6 @@ import de.lmu.ifi.dbs.elki.datasource.bundle.SingleObjectBundle;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
import de.lmu.ifi.dbs.elki.result.CollectionResult;
-import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
import de.lmu.ifi.dbs.elki.result.IterableResult;
import de.lmu.ifi.dbs.elki.result.OrderingResult;
import de.lmu.ifi.dbs.elki.result.Result;
@@ -225,63 +224,57 @@ public class TextWriter {
* @throws IOException on IO error
*/
public void output(Database db, Result r, StreamFactory streamOpener) throws UnableToComplyException, IOException {
- List<Relation<?>> ra = null;
- List<OrderingResult> ro = null;
- List<Clustering<? extends Model>> rc = null;
- List<IterableResult<?>> ri = null;
- List<SettingsResult> rs = null;
- HashSet<Result> otherres = null;
+ 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>();
- ra = ResultUtil.getRelations(r);
- ro = ResultUtil.getOrderingResults(r);
- rc = ResultUtil.getClusteringResults(r);
- ri = ResultUtil.getIterableResults(r);
- rs = ResultUtil.getSettingsResults(r);
// collect other results
- if(r instanceof HierarchicalResult) {
- final List<Result> resultList = ResultUtil.filterResults((HierarchicalResult) r, Result.class);
- otherres = new HashSet<Result>(resultList);
- otherres.removeAll(ra);
- otherres.removeAll(ro);
- otherres.removeAll(rc);
- otherres.removeAll(ri);
- otherres.removeAll(rs);
- otherres.remove(db);
- Iterator<Result> it = otherres.iterator();
- while(it.hasNext()) {
- if(it.next() instanceof HierarchicalResult) {
- it.remove();
+ {
+ for(Result res : ResultUtil.filteredResults(r, Result.class)) {
+ if(res instanceof Database) {
+ continue;
+ }
+ if(res instanceof Relation) {
+ ra.add((Relation<?>) res);
+ continue;
+ }
+ if(res instanceof OrderingResult) {
+ ro.add((OrderingResult) res);
+ continue;
+ }
+ if(res instanceof Clustering) {
+ rc.add((Clustering<?>) res);
+ continue;
+ }
+ if(res instanceof IterableResult) {
+ ri.add((IterableResult<?>) res);
+ continue;
+ }
+ if(res instanceof SettingsResult) {
+ rs.add((SettingsResult) res);
+ continue;
}
+ otherres.add(res);
}
}
- if(ra == null && ro == null && rc == null && ri == null) {
- throw new UnableToComplyException("No printable result found.");
+ for(IterableResult<?> rii : ri) {
+ writeIterableResult(streamOpener, rii, rs);
}
-
- if(ri != null && ri.size() > 0) {
- // TODO: associations are not passed to ri results.
- for(IterableResult<?> rii : ri) {
- writeIterableResult(streamOpener, rii, rs);
- }
- }
- if(rc != null && rc.size() > 0) {
- for(Clustering<?> c : rc) {
- NamingScheme naming = new SimpleEnumeratingScheme(c);
- for(Cluster<?> clus : c.getAllClusters()) {
- writeClusterResult(db, streamOpener, clus, ra, naming, rs);
- }
+ for(Clustering<?> c : rc) {
+ NamingScheme naming = new SimpleEnumeratingScheme(c);
+ for(Cluster<?> clus : c.getAllClusters()) {
+ writeClusterResult(db, streamOpener, clus, ra, naming, rs);
}
}
- if(ro != null && ro.size() > 0) {
- for(OrderingResult ror : ro) {
- writeOrderingResult(db, streamOpener, ror, ra, rs);
- }
+ for(OrderingResult ror : ro) {
+ writeOrderingResult(db, streamOpener, ror, ra, rs);
}
- if(otherres != null && otherres.size() > 0) {
- for(Result otherr : otherres) {
- writeOtherResult(streamOpener, otherr, rs);
- }
+ for(Result otherr : otherres) {
+ writeOtherResult(streamOpener, otherr, rs);
}
}
@@ -290,16 +283,18 @@ public class TextWriter {
// Write database element itself.
for(int i = 0; i < bundle.metaLength(); i++) {
Object obj = bundle.data(i);
- TextWriterWriterInterface<?> owriter = out.getWriterFor(obj);
- 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))) {
- lbl = "ID";
+ if(obj != null) {
+ TextWriterWriterInterface<?> owriter = out.getWriterFor(obj);
+ 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))) {
+ lbl = "ID";
+ }
+ owriter.writeObject(out, lbl, obj);
}
- owriter.writeObject(out, lbl, obj);
}
Collection<Relation<?>> dbrels = db.getRelations();
@@ -307,7 +302,7 @@ public class TextWriter {
if(ra != null) {
for(Relation<?> a : ra) {
// Avoid duplicated output.
- if (dbrels.contains(a)) {
+ if(dbrels.contains(a)) {
continue;
}
String label = a.getShortName();
@@ -357,7 +352,7 @@ public class TextWriter {
// Write cluster information
out.commentPrintLn("Cluster: " + naming.getNameFor(clus));
Model model = clus.getModel();
- if (model != ClusterModel.CLUSTER) {
+ if(model != ClusterModel.CLUSTER && model != null) {
TextWriterWriterInterface<?> mwri = writers.getHandler(model);
mwri.writeObject(out, null, model);
}
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 b59a09e9..ce60c856 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) 2011
+ Copyright (C) 2012
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/TextWriterWriterInterface.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/TextWriterWriterInterface.java
index ab572896..cfaa3373 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) 2011
+ Copyright (C) 2012
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 c5d9cf72..4b2c099f 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) 2011
+ Copyright (C) 2012
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 2341f258..baff04e2 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) 2011
+ Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/naming/package-info.java
index 8d10da45..600e731e 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) 2011
+Copyright (C) 2012
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 b2abeb5b..872df780 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) 2011
+Copyright (C) 2012
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 b8f25b6a..4af9d8a4 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) 2011
+ Copyright (C) 2012
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 bec183d8..3a73d52a 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) 2011
+ Copyright (C) 2012
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 ddb753ac..d4da18f5 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) 2011
+ Copyright (C) 2012
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 12717da7..a621ab4b 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) 2011
+ Copyright (C) 2012
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 c8bd83b2..3c1440bc 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) 2011
+ Copyright (C) 2012
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 491f803d..87a3661b 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) 2011
+ Copyright (C) 2012
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/TextWriterTriple.java b/src/de/lmu/ifi/dbs/elki/result/textwriter/writers/TextWriterTriple.java
index ce3c3d70..55dd7106 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) 2011
+ Copyright (C) 2012
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 0ebf4ae4..1452c432 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) 2011
+ Copyright (C) 2012
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 66c5f706..c83dd767 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) 2011
+Copyright (C) 2012
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/Base64.java b/src/de/lmu/ifi/dbs/elki/utilities/Base64.java
new file mode 100644
index 00000000..da3b52a7
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/Base64.java
@@ -0,0 +1,100 @@
+package de.lmu.ifi.dbs.elki.utilities;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+/**
+ * Class to wrap various Base64 encoders that could be available.
+ *
+ * This is a rather ugly hack; it would maybe have been sensible to just import
+ * one of the publicly available (and fast) Base64 encoders. The expectation was
+ * that at some point, Oracle will acutally include a public and fast Base64
+ * encoder in Java.
+ *
+ * @author Erich Schubert
+ */
+public final class Base64 {
+ /**
+ * Instance of sun.misc.BASE64Encoder
+ */
+ private static Object sunj6i;
+
+ /**
+ * Encode method
+ */
+ private static Method sunj6m;
+
+ /**
+ * Instance of java.util.prefs.Base64
+ */
+ private static Object jup6i;
+
+ /**
+ * Encode method
+ */
+ private static Method jup6m;
+
+ // Initialize
+ static {
+ // Try Java 6
+ {
+ try {
+ Class<?> c = ClassLoader.getSystemClassLoader().loadClass("sun.misc.BASE64Encoder");
+ sunj6i = c.newInstance();
+ sunj6m = c.getMethod("encode", byte[].class);
+ }
+ catch(Throwable e) {
+ // de.lmu.ifi.dbs.elki.logging.LoggingUtil.exception(e);
+ // Ignore.
+ sunj6i = null;
+ sunj6m = null;
+ }
+ }
+ // Try private class in Java6 preferences
+ {
+ try {
+ Class<?> c = ClassLoader.getSystemClassLoader().loadClass("java.util.prefs.Base64");
+ Constructor<?> cons = c.getDeclaredConstructor();
+ cons.setAccessible(true);
+ jup6i = cons.newInstance();
+ jup6m = c.getDeclaredMethod("byteArrayToBase64", byte[].class);
+ jup6m.setAccessible(true);
+ }
+ catch(Throwable e) {
+ // de.lmu.ifi.dbs.elki.logging.LoggingUtil.exception(e);
+ // Ignore.
+ jup6i = null;
+ jup6m = null;
+ }
+ }
+ if(sunj6i == null && jup6i == null) {
+ de.lmu.ifi.dbs.elki.logging.LoggingUtil.warning("No usable Base64 encoders detected.");
+ }
+ }
+
+ /**
+ * Encode a string as Base64.
+ *
+ * @param s Bytes to encode
+ * @return Result string
+ */
+ public static final String encodeBase64(byte[] s) {
+ if(jup6i != null && jup6m != null) {
+ try {
+ return (String) jup6m.invoke(jup6i, s);
+ }
+ catch(Exception e) {
+ throw new RuntimeException("java.util.prefs.Base64 is not working.");
+ }
+ }
+ if(sunj6i != null && sunj6m != null) {
+ try {
+ return (String) sunj6m.invoke(sunj6i, s);
+ }
+ catch(Exception e) {
+ throw new RuntimeException("sun.misc.BASE64Encoder is not working.");
+ }
+ }
+ throw new RuntimeException("No usable Base64 encoder detected.");
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/BitsUtil.java b/src/de/lmu/ifi/dbs/elki/utilities/BitsUtil.java
new file mode 100644
index 00000000..d2dc6733
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/BitsUtil.java
@@ -0,0 +1,1140 @@
+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/>.
+ */
+
+import java.util.Arrays;
+
+/**
+ * Utilities for bit operations.
+ *
+ * Implementation note: words are stored in little-endian word order. This can
+ * be a bit confusing, because a shift-right means "left" on the word level.
+ *
+ * Naming: methods with a <code>C</code> return a copy, methods with
+ * <code>I</code> modify in-place.
+ *
+ * @author Erich Schubert
+ */
+public final class BitsUtil {
+ /**
+ * Shift factor for a long: 2^6 == 64 == Long.SIZE
+ */
+ private static final int LONG_LOG2_SIZE = 6;
+
+ /**
+ * Masking for long shifts.
+ */
+ private static final int LONG_LOG2_MASK = 0x3f; // 6 bits
+
+ /**
+ * Long with all bits set
+ */
+ private static final long LONG_ALL_BITS = -1L;
+
+ /**
+ * Allocate a new long[].
+ *
+ * @param bits Number of bits in storage
+ * @return New array
+ */
+ public static long[] zero(int bits) {
+ return new long[((bits - 1) >>> LONG_LOG2_SIZE) + 1];
+ }
+
+ /**
+ * Allocate a new long[].
+ *
+ * @param bits Number of bits in storage
+ * @param init Initial value (of at most the size of a long, remaining bits
+ * will be 0)
+ * @return New array
+ */
+ public static long[] make(int bits, long init) {
+ long[] v = new long[((bits - 1) >>> LONG_LOG2_SIZE) + 1];
+ v[0] = init;
+ return v;
+ }
+
+ /**
+ * Create a vector initialized with "bits" ones.
+ *
+ * @param bits Size
+ * @return new vector
+ */
+ public static long[] ones(int bits) {
+ long[] v = new long[((bits - 1) >>> LONG_LOG2_SIZE) + 1];
+ final int fillWords = bits >>> LONG_LOG2_SIZE;
+ final int fillBits = bits & LONG_LOG2_MASK;
+ Arrays.fill(v, 0, fillWords, LONG_ALL_BITS);
+ v[v.length - 1] = (1L << fillBits) - 1;
+ return v;
+ }
+
+ /**
+ * Copy a bitset
+ *
+ * @param v Array to copy
+ * @return Copy
+ */
+ public static long[] copy(long[] v) {
+ return Arrays.copyOf(v, v.length);
+ }
+
+ /**
+ * Copy a bitset.
+ *
+ * Note: Bits beyond mincap <em>may</em> be retained!
+ *
+ * @param v Array to copy
+ * @param mincap Target <em>minimum</em> capacity
+ * @return Copy with space for at least "capacity" bits
+ */
+ public static long[] copy(long[] v, int mincap) {
+ int words = ((mincap - 1) >>> LONG_LOG2_SIZE) + 1;
+ if(v.length == words) {
+ return Arrays.copyOf(v, v.length);
+ }
+ long[] ret = new long[words];
+ System.arraycopy(v, 0, ret, 0, Math.min(v.length, words));
+ return ret;
+ }
+
+ /**
+ * Copy a bitset.
+ *
+ * Note: Bits beyond mincap <em>may</em> be retained!
+ *
+ * @param v Array to copy
+ * @param mincap Target <em>minimum</em> capacity
+ * @param shift Number of bits to shift left
+ * @return Copy with space for at least "capacity" bits
+ */
+ public static long[] copy(long[] v, int mincap, int shift) {
+ int words = ((mincap - 1) >>> LONG_LOG2_SIZE) + 1;
+ if(v.length == words && shift == 0) {
+ return Arrays.copyOf(v, v.length);
+ }
+ long[] ret = new long[words];
+ final int shiftWords = shift >>> LONG_LOG2_SIZE;
+ final int shiftBits = shift & LONG_LOG2_MASK;
+ // Simple case - multiple of word size
+ if(shiftBits == 0) {
+ for(int i = shiftWords; i < ret.length; i++) {
+ ret[i] |= v[i - shiftWords];
+ }
+ return ret;
+ }
+ // Overlapping case
+ final int unshiftBits = Long.SIZE - shiftBits;
+ final int end = Math.min(ret.length, v.length + shiftWords) - 1;
+ for(int i = end; i > shiftWords; i--) {
+ final int src = i - shiftWords;
+ ret[i] |= (v[src] << shiftBits) | (v[src - 1] >>> unshiftBits);
+ }
+ ret[shiftWords] |= v[0] << shiftBits;
+ return ret;
+ }
+
+ /**
+ * Compute corresponding gray code as v XOR (v >>> 1)
+ *
+ * @param v Value
+ * @return Gray code
+ */
+ public static long grayC(long v) {
+ return v ^ (v >>> 1);
+ }
+
+ /**
+ * Compute corresponding gray code as v XOR (v >>> 1)
+ *
+ * @param v Value
+ * @return Gray code
+ */
+ public static long[] grayI(long[] v) {
+ // TODO: copy less
+ long[] t = copy(v);
+ shiftRightI(t, 1);
+ xorI(v, t);
+ return v;
+ }
+
+ /**
+ * Compute the inverted gray code, v XOR (v >>> 1) XOR (v >>> 2) ...
+ *
+ * @param v Value
+ * @return Inverted gray code
+ */
+ public static long invgrayC(long v) {
+ v ^= (v >>> 1);
+ v ^= (v >>> 2);
+ v ^= (v >>> 4);
+ v ^= (v >>> 8);
+ v ^= (v >>> 16);
+ v ^= (v >>> 32);
+ return v;
+ }
+
+ /**
+ * Compute the inverted gray code, v XOR (v >>> 1) XOR (v >>> 2) ...
+ *
+ * @param v Value
+ * @return Inverted gray code
+ */
+ public static long[] invgrayI(long[] v) {
+ final int last = v.length - 1;
+ int o;
+ // Sub word level:
+ for(o = 1; o < Long.SIZE; o <<= 1) {
+ for(int i = 0; i < last; i++) {
+ v[i] ^= (v[i] >>> o) ^ (v[i + 1] << (Long.SIZE - o));
+ }
+ v[last] ^= (v[last] >>> o);
+ }
+ // Word level:
+ for(o = 1; o <= last; o <<= 1) {
+ for(int i = o; i <= last; i++) {
+ v[i - o] ^= v[i];
+ }
+ }
+ return v;
+ }
+
+ /**
+ * Test for the bitstring to be all-zero.
+ *
+ * @param v Bitstring
+ * @return true when all zero
+ */
+ public static boolean isZero(long[] v) {
+ for(int i = 0; i < v.length; i++) {
+ if(v[i] != 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Compute the cardinality (number of set bits)
+ *
+ * @param v Value
+ * @return Number of bits set in long
+ */
+ public static int cardinality(long v) {
+ return Long.bitCount(v);
+ }
+
+ /**
+ * Compute the cardinality (number of set bits)
+ *
+ * Low-endian layout for the array.
+ *
+ * @param v Value
+ * @return Number of bits set in long[]
+ */
+ public static long cardinality(long[] v) {
+ int sum = 0;
+ for(int i = 0; i < v.length; i++) {
+ sum += Long.bitCount(v[i]);
+ }
+ return sum;
+ }
+
+ /**
+ * Invert bit number "off" in v.
+ *
+ * @param v Buffer
+ * @param off Offset to flip
+ */
+ public static long flipC(long v, int off) {
+ v ^= (1L << off);
+ return v;
+ }
+
+ /**
+ * Invert bit number "off" in v.
+ *
+ * Low-endian layout for the array.
+ *
+ * @param v Buffer
+ * @param off Offset to flip
+ */
+ public static long[] flipI(long[] v, int off) {
+ final int wordindex = off >>> LONG_LOG2_SIZE;
+ v[wordindex] ^= (1L << off);
+ return v;
+ }
+
+ /**
+ * Set bit number "off" in v.
+ *
+ * @param v Buffer
+ * @param off Offset to set
+ */
+ public static long setC(long v, int off) {
+ v |= (1L << off);
+ return v;
+ }
+
+ /**
+ * Set bit number "off" in v.
+ *
+ * Low-endian layout for the array.
+ *
+ * @param v Buffer
+ * @param off Offset to set
+ */
+ public static long[] setI(long[] v, int off) {
+ final int wordindex = off >>> LONG_LOG2_SIZE;
+ v[wordindex] |= (1L << off);
+ return v;
+ }
+
+ /**
+ * Clear bit number "off" in v.
+ *
+ * @param v Buffer
+ * @param off Offset to clear
+ */
+ public static long clearC(long v, int off) {
+ v &= ~(1L << off);
+ return v;
+ }
+
+ /**
+ * Clear bit number "off" in v.
+ *
+ * Low-endian layout for the array.
+ *
+ * @param v Buffer
+ * @param off Offset to clear
+ */
+ public static long[] clearI(long[] v, int off) {
+ final int wordindex = off >>> LONG_LOG2_SIZE;
+ v[wordindex] &= ~(1L << off);
+ return v;
+ }
+
+ /**
+ * Set bit number "off" in v.
+ *
+ * @param v Buffer
+ * @param off Offset to set
+ */
+ public static boolean get(long v, int off) {
+ return (v & (1L << off)) != 0;
+ }
+
+ /**
+ * Set bit number "off" in v.
+ *
+ * Low-endian layout for the array.
+ *
+ * @param v Buffer
+ * @param off Offset to set
+ */
+ public static boolean get(long[] v, int off) {
+ final int wordindex = off >>> LONG_LOG2_SIZE;
+ return (v[wordindex] & (1L << off)) != 0;
+ }
+
+ /**
+ * Zero the given set
+ *
+ * Low-endian layout for the array.
+ *
+ * @param v existing set
+ * @return array set to zero
+ */
+ public static long[] zeroI(long[] v) {
+ Arrays.fill(v, 0);
+ return v;
+ }
+
+ /**
+ * XOR o onto v inplace, i.e. v ^= o
+ *
+ * @param v Primary object
+ * @param o data to xor
+ * @return v
+ */
+ public static long[] xorI(long[] v, long[] o) {
+ assert (o.length <= v.length) : "Bit set sizes do not agree.";
+ for(int i = 0; i < o.length; i++) {
+ v[i] ^= o[i];
+ }
+ return v;
+ }
+
+ /**
+ * XOR o onto v inplace, i.e. v ^= (o << off)
+ *
+ * @param v Primary object
+ * @param o data to or
+ * @param off Offset
+ * @return v
+ */
+ public static long[] xorI(long[] v, long[] o, int off) {
+ if(off == 0) {
+ return xorI(v, o);
+ }
+ if(off < 0) {
+ throw new UnsupportedOperationException("Negative shifts are not supported.");
+ }
+ // Break shift into integers to shift and bits to shift
+ final int shiftWords = off >>> LONG_LOG2_SIZE;
+ final int shiftBits = off & LONG_LOG2_MASK;
+
+ if(shiftWords >= v.length) {
+ return v;
+ }
+ // Simple case - multiple of word size
+ if(shiftBits == 0) {
+ final int end = Math.min(v.length, o.length + shiftWords);
+ for(int i = shiftWords; i < end; i++) {
+ v[i] ^= o[i - shiftWords];
+ }
+ return v;
+ }
+ // Overlapping case
+ final int unshiftBits = Long.SIZE - shiftBits;
+ final int end = Math.min(v.length, o.length + shiftWords) - 1;
+ for(int i = end; i > shiftWords; i--) {
+ final int src = i - shiftWords;
+ v[i] ^= (o[src] << shiftBits) | (o[src - 1] >>> unshiftBits);
+ }
+ v[shiftWords] ^= o[0] << shiftBits;
+ return v;
+ }
+
+ /**
+ * OR o onto v inplace, i.e. v |= o
+ *
+ * @param v Primary object
+ * @param o data to or
+ * @return v
+ */
+ public static long[] orI(long[] v, long[] o) {
+ assert (o.length <= v.length) : "Bit set sizes do not agree.";
+ final int max = Math.min(v.length, o.length);
+ for(int i = 0; i < max; i++) {
+ v[i] |= o[i];
+ }
+ return v;
+ }
+
+ /**
+ * OR o onto v inplace, i.e. v |= (o << off)
+ *
+ * Note: Bits that are shifted outside of the size of v are discarded.
+ *
+ * @param v Primary object
+ * @param o data to or
+ * @param off Offset
+ * @return v
+ */
+ public static long[] orI(long[] v, long[] o, int off) {
+ if(off == 0) {
+ return orI(v, o);
+ }
+ if(off < 0) {
+ throw new UnsupportedOperationException("Negative shifts are not supported.");
+ }
+ // Break shift into integers to shift and bits to shift
+ final int shiftWords = off >>> LONG_LOG2_SIZE;
+ final int shiftBits = off & LONG_LOG2_MASK;
+
+ if(shiftWords >= v.length) {
+ return v;
+ }
+ // Simple case - multiple of word size
+ if(shiftBits == 0) {
+ final int end = Math.min(v.length, o.length + shiftWords);
+ for(int i = shiftWords; i < end; i++) {
+ v[i] |= o[i - shiftWords];
+ }
+ return v;
+ }
+ // Overlapping case
+ final int unshiftBits = Long.SIZE - shiftBits;
+ final int end = Math.min(v.length, o.length + shiftWords) - 1;
+ for(int i = end; i > shiftWords; i--) {
+ final int src = i - shiftWords;
+ v[i] |= (o[src] << shiftBits) | (o[src - 1] >>> unshiftBits);
+ }
+ v[shiftWords] |= o[0] << shiftBits;
+ return v;
+ }
+
+ /**
+ * AND o onto v inplace, i.e. v &= o
+ *
+ * @param v Primary object
+ * @param o data to and
+ * @return v
+ */
+ public static long[] andI(long[] v, long[] o) {
+ int i = 0;
+ for(; i < o.length; i++) {
+ v[i] |= o[i];
+ }
+ // Zero higher words
+ Arrays.fill(v, i, v.length, 0);
+ return v;
+ }
+
+ /**
+ * AND o onto v inplace, i.e. v &= (o << off)
+ *
+ * @param v Primary object
+ * @param o data to or
+ * @param off Offset
+ * @return v
+ */
+ public static long[] andI(long[] v, long[] o, int off) {
+ if(off == 0) {
+ return andI(v, o);
+ }
+ if(off < 0) {
+ throw new UnsupportedOperationException("Negative shifts are not supported.");
+ }
+ // Break shift into integers to shift and bits to shift
+ final int shiftWords = off >>> LONG_LOG2_SIZE;
+ final int shiftBits = off & LONG_LOG2_MASK;
+
+ if(shiftWords >= v.length) {
+ return v;
+ }
+ // Simple case - multiple of word size
+ if(shiftBits == 0) {
+ final int end = Math.min(v.length, o.length + shiftWords);
+ for(int i = shiftWords; i < end; i++) {
+ v[i] &= o[i - shiftWords];
+ }
+ // Clear bottom words
+ Arrays.fill(v, 0, shiftWords, 0);
+ return v;
+ }
+ // Overlapping case
+ final int unshiftBits = Long.SIZE - shiftBits;
+ final int end = Math.min(v.length, o.length + shiftWords) - 1;
+ Arrays.fill(v, end + 1, v.length, 0);
+ for(int i = end; i > shiftWords; i--) {
+ final int src = i - shiftWords;
+ v[i] &= (o[src] << shiftBits) | (o[src - 1] >>> unshiftBits);
+ }
+ v[shiftWords] &= o[0] << shiftBits;
+ // Clear bottom words
+ Arrays.fill(v, 0, shiftWords, 0);
+ return v;
+ }
+
+ /**
+ * Invert v inplace.
+ *
+ * @param v Object to invert
+ * @return v
+ */
+ public static long[] invertI(long[] v) {
+ for(int i = 0; i < v.length; i++) {
+ v[i] = ~v[i];
+ }
+ return v;
+ }
+
+ /**
+ * Shift a long[] bitset inplace.
+ *
+ * Low-endian layout for the array.
+ *
+ * @param v existing bitset
+ * @param off Offset to shift by
+ * @return Bitset
+ */
+ public static long[] shiftRightI(long[] v, int off) {
+ if(off == 0) {
+ return v;
+ }
+ if(off < 0) {
+ return shiftLeftI(v, -off);
+ }
+ // Break shift into integers to shift and bits to shift
+ final int shiftWords = off >>> LONG_LOG2_SIZE;
+ final int shiftBits = off & LONG_LOG2_MASK;
+
+ if(shiftWords >= v.length) {
+ return zeroI(v);
+ }
+ // Simple case - multiple of word size
+ if(shiftBits == 0) {
+ // Move whole words down
+ System.arraycopy(v, shiftWords, v, 0, v.length - shiftWords);
+ // Fill top words with zeros
+ Arrays.fill(v, v.length - shiftWords, v.length, 0);
+ return v;
+ }
+ // Overlapping case
+ final int unshiftBits = Long.SIZE - shiftBits;
+ // Bottom-up to not overlap the operations.
+ for(int i = 0; i < v.length - shiftWords - 1; i++) {
+ final int src = i + shiftWords;
+ v[i] = (v[src + 1] << unshiftBits) | (v[src] >>> shiftBits);
+ }
+ // The last original word
+ v[v.length - shiftWords - 1] = v[v.length - 1] >>> shiftBits;
+ // Fill whole words "lost" by the shift
+ Arrays.fill(v, v.length - shiftWords, v.length, 0);
+ return v;
+ }
+
+ /**
+ * Shift a long[] bitset inplace.
+ *
+ * Low-endian layout for the array.
+ *
+ * @param v existing bitset
+ * @param off Offset to shift by
+ * @return Bitset
+ */
+ public static long[] shiftLeftI(long[] v, int off) {
+ if(off == 0) {
+ return v;
+ }
+ if(off < 0) {
+ return shiftRightI(v, -off);
+ }
+ // Break shift into integers to shift and bits to shift
+ final int shiftWords = off >>> LONG_LOG2_SIZE;
+ final int shiftBits = off & LONG_LOG2_MASK;
+
+ if(shiftWords >= v.length) {
+ return zeroI(v);
+ }
+ // Simple case - multiple of word size
+ if(shiftBits == 0) {
+ // Move whole words up
+ System.arraycopy(v, 0, v, shiftWords, v.length - shiftWords);
+ // Fill the initial words with zeros
+ Arrays.fill(v, 0, shiftWords, 0);
+ return v;
+ }
+ // Overlapping case
+ final int unshiftBits = Long.SIZE - shiftBits;
+ // Top-Down to not overlap the operations.
+ for(int i = v.length - 1; i > shiftWords; i--) {
+ final int src = i - shiftWords;
+ v[i] = (v[src] << shiftBits) | (v[src - 1] >>> unshiftBits);
+ }
+ v[shiftWords] = v[0] << shiftBits;
+ // Fill the initial words with zeros
+ Arrays.fill(v, 0, shiftWords, 0);
+ return v;
+ }
+
+ /**
+ * Rotate a long to the right, cyclic with length len
+ *
+ * @param v Bits
+ * @param shift Shift value
+ * @param len Length
+ * @return cycled bit set
+ */
+ public static long cycleRightC(long v, int shift, int len) {
+ if(shift == 0) {
+ return v;
+ }
+ if(shift < 0) {
+ return cycleLeftC(v, -shift, len);
+ }
+ final long ones = (1 << len) - 1;
+ return (((v) >>> (shift)) | ((v) << ((len) - (shift)))) & ones;
+ }
+
+ /**
+ * Cycle a bitstring to the right.
+ *
+ * @param v Bit string
+ * @param shift Number of steps to cycle
+ * @param len Length
+ */
+ public static long[] cycleRightI(long[] v, int shift, int len) {
+ long[] t = copy(v, len, len - shift);
+ truncateI(t, len);
+ shiftRightI(v, shift);
+ orI(v, t);
+ return v;
+ }
+
+ /**
+ * Truncate a bit string to the given length (setting any higher bit to 0).
+ *
+ * @param v String to process
+ * @param len Length (in bits) to truncate to
+ */
+ public static long[] truncateI(long[] v, int len) {
+ final int zap = (v.length * Long.SIZE) - len;
+ final int zapWords = (zap >>> LONG_LOG2_SIZE);
+ final int zapbits = zap & LONG_LOG2_MASK;
+ Arrays.fill(v, v.length - zapWords, v.length, 0);
+ if(zapbits > 0) {
+ v[v.length - zapWords - 1] &= (LONG_ALL_BITS >>> zapbits);
+ }
+ return v;
+ }
+
+ /**
+ * Rotate a long to the left, cyclic with length len
+ *
+ * @param v Bits
+ * @param shift Shift value
+ * @param len Length
+ * @return cycled bit set
+ */
+ public static long cycleLeftC(long v, int shift, int len) {
+ if(shift == 0) {
+ return v;
+ }
+ if(shift < 0) {
+ return cycleRightC(v, -shift, len);
+ }
+ final long ones = (1 << len) - 1;
+ return (((v) << (shift)) | ((v) >>> ((len) - (shift)))) & ones;
+ }
+
+ /**
+ * Cycle a bitstring to the right.
+ *
+ * @param v Bit string
+ * @param shift Number of steps to cycle
+ * @param len Length
+ */
+ public static long[] cycleLeftI(long[] v, int shift, int len) {
+ long[] t = copy(v, len, shift);
+ truncateI(t, len);
+ shiftRightI(v, len - shift);
+ orI(v, t);
+ return v;
+ }
+
+ /**
+ * Convert bitset to a string consisting of "0" and "1", in high-endian order.
+ *
+ * @param v Value to process
+ * @return String representation
+ */
+ public static String toString(long[] v) {
+ final int mag = magnitude(v);
+ if(v.length == 0 || mag == 0) {
+ return "0";
+ }
+ final int words = ((mag - 1) >>> LONG_LOG2_SIZE) + 1;
+ char[] digits = new char[mag];
+
+ int pos = mag - 1;
+ for(int w = 0; w < words; w++) {
+ long f = 1l;
+ for(int i = 0; i < Long.SIZE; i++) {
+ digits[pos] = ((v[w] & f) == 0) ? '0' : '1';
+ pos--;
+ f <<= 1;
+ if(pos < 0) {
+ break;
+ }
+ }
+ }
+ return new String(digits);
+ }
+
+ /**
+ * Convert bitset to a string consisting of "0" and "1", in high-endian order.
+ *
+ * @param v Value to process
+ * @param minw Minimum width
+ * @return String representation
+ */
+ public static String toString(long[] v, int minw) {
+ final int mag = Math.max(magnitude(v), minw);
+ if(v.length == 0 || mag == 0) {
+ return "0";
+ }
+ final int words = ((mag - 1) >>> LONG_LOG2_SIZE) + 1;
+ char[] digits = new char[mag];
+
+ int pos = mag - 1;
+ for(int w = 0; w < words; w++) {
+ long f = 1l;
+ for(int i = 0; i < Long.SIZE; i++) {
+ digits[pos] = ((v[w] & f) == 0) ? '0' : '1';
+ pos--;
+ f <<= 1;
+ if(pos < 0) {
+ break;
+ }
+ }
+ }
+ return new String(digits);
+ }
+
+ /**
+ * Convert bitset to a string consisting of "0" and "1", in high-endian order.
+ *
+ * @param v Value to process
+ * @return String representation
+ */
+ public static String toString(long v) {
+ final int mag = magnitude(v);
+ if(mag == 0) {
+ return "0";
+ }
+ char[] digits = new char[mag];
+
+ int pos = mag - 1;
+ long f = 1l;
+ for(int i = 0; i < Long.SIZE; i++) {
+ digits[pos] = ((v & f) == 0) ? '0' : '1';
+ pos--;
+ f <<= 1;
+ if(pos < 0) {
+ break;
+ }
+ }
+ return new String(digits);
+ }
+
+ /**
+ * Find the number of trailing zeros.
+ *
+ * @param v Bitset
+ * @return Position of first set bit, -1 if no set bit was found.
+ */
+ public static int numberOfTrailingZerosSigned(long[] v) {
+ for(int p = 0;; p++) {
+ if(p == v.length) {
+ return -1;
+ }
+ if(v[p] != 0) {
+ return Long.numberOfTrailingZeros(v[p]) + p * Long.SIZE;
+ }
+ }
+ }
+
+ /**
+ * Find the number of trailing zeros.
+ *
+ * @param v Bitset
+ * @return Position of first set bit, v.length * 64 if no set bit was found.
+ */
+ public static int numberOfTrailingZeros(long[] v) {
+ for(int p = 0;; p++) {
+ if(p == v.length) {
+ return p * Long.SIZE;
+ }
+ if(v[p] != 0) {
+ return Long.numberOfTrailingZeros(v[p]) + p * Long.SIZE;
+ }
+ }
+ }
+
+ /**
+ * Find the number of trailing zeros.
+ *
+ * Note: this has different semantics to {@link Long#numberOfLeadingZeros}
+ * when the number is 0.
+ *
+ * @param v Long
+ * @return Position of first set bit, -1 if no set bit was found.
+ */
+ public static int numberOfTrailingZerosSigned(long v) {
+ return Long.numberOfTrailingZeros(v);
+ }
+
+ /**
+ * Find the number of trailing zeros.
+ *
+ * Note: this is the same as {@link Long#numberOfTrailingZeros}
+ *
+ * @param v Long
+ * @return Position of first set bit, 64 if no set bit was found.
+ */
+ public static int numberOfTrailingZeros(long v) {
+ return Long.numberOfTrailingZeros(v);
+ }
+
+ /**
+ * Find the number of leading zeros.
+ *
+ * @param v Bitset
+ * @return Position of first set bit, -1 if no set bit was found.
+ */
+ public static int numberOfLeadingZerosSigned(long[] v) {
+ for(int p = 0, ip = v.length - 1;; p++, ip--) {
+ if(p == v.length) {
+ return -1;
+ }
+ if(v[ip] != 0) {
+ return Long.numberOfLeadingZeros(v[ip]) + p * Long.SIZE;
+ }
+ }
+ }
+
+ /**
+ * Find the number of leading zeros.
+ *
+ * @param v Bitset
+ * @return Position of first set bit, v.length * 64 if no set bit was found.
+ */
+ public static int numberOfLeadingZeros(long[] v) {
+ for(int p = 0, ip = v.length - 1;; p++, ip--) {
+ if(p == v.length) {
+ return p * Long.SIZE;
+ }
+ if(v[ip] != 0) {
+ return Long.numberOfLeadingZeros(v[ip]) + p * Long.SIZE;
+ }
+ }
+ }
+
+ /**
+ * Find the number of leading zeros; -1 if all zero
+ *
+ * Note: this has different semantics to {@link Long#numberOfLeadingZeros}
+ * when the number is 0.
+ *
+ * @param v Bitset
+ * @return Position of first set bit, -1 if no set bit was found.
+ */
+ public static int numberOfLeadingZerosSigned(long v) {
+ if(v == 0) {
+ return -1;
+ }
+ return Long.numberOfLeadingZeros(v);
+ }
+
+ /**
+ * Find the number of leading zeros; 64 if all zero
+ *
+ * Note: this the same as {@link Long#numberOfLeadingZeros}.
+ *
+ * @param v Bitset
+ * @return Position of first set bit, 64 if no set bit was found.
+ */
+ public static int numberOfLeadingZeros(long v) {
+ return Long.numberOfLeadingZeros(v);
+ }
+
+ /**
+ * Find the previous set bit.
+ *
+ * @param v Values to process
+ * @param start Start position (inclusive)
+ * @return Position of previous set bit, or -1.
+ */
+ public static int previousSetBit(long[] v, int start) {
+ if(start == -1) {
+ return -1;
+ }
+ int wordindex = start >>> LONG_LOG2_SIZE;
+ if(wordindex >= v.length) {
+ return magnitude(v) - 1;
+ }
+ // Initial word
+ final int off = Long.SIZE - 1 - (start & LONG_LOG2_MASK);
+ long cur = v[wordindex] & (LONG_ALL_BITS >>> off);
+ for(;;) {
+ if(cur != 0) {
+ return (wordindex + 1) * Long.SIZE - 1 - Long.numberOfLeadingZeros(cur);
+ }
+ if(wordindex == 0) {
+ return -1;
+ }
+ wordindex--;
+ cur = v[wordindex];
+ }
+ }
+
+ /**
+ * Find the previous clear bit.
+ *
+ * @param v Values to process
+ * @param start Start position (inclusive)
+ * @return Position of previous clear bit, or -1.
+ */
+ public static int previousClearBit(long[] v, int start) {
+ if(start == -1) {
+ return -1;
+ }
+ int wordindex = start >>> LONG_LOG2_SIZE;
+ if(wordindex >= v.length) {
+ return magnitude(v);
+ }
+ final int off = Long.SIZE + 1 - (start & LONG_LOG2_MASK);
+ // Initial word
+ long cur = ~v[wordindex] & (LONG_ALL_BITS >>> off);
+ for(;;) {
+ if(cur != 0) {
+ return (wordindex + 1) * Long.SIZE - 1 - Long.numberOfTrailingZeros(cur);
+ }
+ if(wordindex == 0) {
+ return -1;
+ }
+ wordindex--;
+ cur = ~v[wordindex];
+ }
+ }
+
+ /**
+ * Find the next set bit.
+ *
+ * @param v Value to process
+ * @param start Start position (inclusive)
+ * @return Position of next set bit, or -1.
+ */
+ public static int nextSetBit(long[] v, int start) {
+ int wordindex = start >>> LONG_LOG2_SIZE;
+ if(wordindex >= v.length) {
+ return -1;
+ }
+
+ // Initial word
+ long cur = v[wordindex] & (LONG_ALL_BITS << start);
+ for(;;) {
+ if(cur != 0) {
+ return (wordindex * Long.SIZE) + Long.numberOfTrailingZeros(cur);
+ }
+ wordindex++;
+ if(wordindex == v.length) {
+ return -1;
+ }
+ cur = v[wordindex];
+ }
+ }
+
+ /**
+ * Find the next clear bit.
+ *
+ * @param v Value to process
+ * @param start Start position (inclusive)
+ * @return Position of next clear bit, or -1.
+ */
+ public static int nextClearBit(long[] v, int start) {
+ int wordindex = start >>> LONG_LOG2_SIZE;
+ if(wordindex >= v.length) {
+ return -1;
+ }
+
+ // Initial word
+ long cur = ~v[wordindex] & (LONG_ALL_BITS << start);
+ for(; wordindex < v.length;) {
+ if(cur != 0) {
+ return (wordindex * Long.SIZE) + Long.numberOfTrailingZeros(cur);
+ }
+ wordindex++;
+ cur = ~v[wordindex];
+ }
+ return -1;
+ }
+
+ /**
+ * The magnitude is the position of the highest bit set
+ *
+ * @param v Vector v
+ * @return position of highest bit set, or 0.
+ */
+ public static int magnitude(long[] v) {
+ final int l = numberOfLeadingZerosSigned(v);
+ if(l < 0) {
+ return 0;
+ }
+ return capacity(v) - l;
+ }
+
+ /**
+ * The magnitude is the position of the highest bit set
+ *
+ * @param v Vector v
+ * @return position of highest bit set, or 0.
+ */
+ public static int magnitude(long v) {
+ final int l = numberOfLeadingZerosSigned(v);
+ if(l < 0) {
+ return 0;
+ }
+ return Long.SIZE - l;
+ }
+
+ /**
+ * Capacity of the vector v.
+ *
+ * @param v Vector v
+ * @return Capacity
+ */
+ public static int capacity(long[] v) {
+ return v.length * Long.SIZE;
+ }
+
+ /**
+ * Compare two bitsets.
+ *
+ * @param x First bitset
+ * @param y Second bitset
+ * @return Comparison result
+ */
+ public static int compare(long[] x, long[] y) {
+ int p = Math.min(x.length, y.length) - 1;
+ for(int i = x.length - 1; i > p; i--) {
+ if(x[i] != 0) {
+ return +1;
+ }
+ }
+ for(int i = y.length - 1; i > p; i--) {
+ if(y[i] != 0) {
+ return -1;
+ }
+ }
+ for(; p >= 0; p--) {
+ final long xp = x[p];
+ final long yp = y[p];
+ if(xp != yp) {
+ if(xp < 0) {
+ if(yp < 0) {
+ return (yp < xp) ? -1 : ((yp == xp) ? 0 : 1);
+ }
+ else {
+ return +1;
+ }
+ }
+ else {
+ if(yp < 0) {
+ return -1;
+ }
+ else {
+ return (xp < yp) ? -1 : ((xp == yp) ? 0 : 1);
+ }
+ }
+ }
+ }
+ return 0;
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/ClassGenericsUtil.java b/src/de/lmu/ifi/dbs/elki/utilities/ClassGenericsUtil.java
index 2c81fbf9..bdd9924f 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -68,6 +68,11 @@ public final class ClassGenericsUtil {
private static final Logging logger = Logging.getLogger(ClassGenericsUtil.class);
/**
+ * Class loader.
+ */
+ private static final ClassLoader loader = ClassLoader.getSystemClassLoader();
+
+ /**
* Name for a static "parameterize" factory method.
*/
public static final String FACTORY_METHOD_NAME = "parameterize";
@@ -93,11 +98,11 @@ public final class ClassGenericsUtil {
T instance;
try {
try {
- instance = type.cast(Class.forName(className).newInstance());
+ instance = type.cast(loader.loadClass(className).newInstance());
}
catch(ClassNotFoundException e) {
// try package of type
- instance = type.cast(Class.forName(type.getPackage().getName() + "." + className).newInstance());
+ instance = type.cast(loader.loadClass(type.getPackage().getName() + "." + className).newInstance());
}
}
catch(InstantiationException e) {
@@ -144,11 +149,11 @@ public final class ClassGenericsUtil {
// (probably not because generics are implemented via erasure.
try {
try {
- instance = ((Class<T>) type).cast(Class.forName(className).newInstance());
+ instance = ((Class<T>) type).cast(loader.loadClass(className).newInstance());
}
catch(ClassNotFoundException e) {
// try package of type
- instance = ((Class<T>) type).cast(Class.forName(type.getPackage().getName() + "." + className).newInstance());
+ instance = ((Class<T>) type).cast(loader.loadClass(type.getPackage().getName() + "." + className).newInstance());
}
}
catch(InstantiationException e) {
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/ConstantObject.java b/src/de/lmu/ifi/dbs/elki/utilities/ConstantObject.java
index 6d8f2f78..9c24c500 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/ConstantObject.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/ConstantObject.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) 2011
+ Copyright (C) 2012
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/DatabaseUtil.java b/src/de/lmu/ifi/dbs/elki/utilities/DatabaseUtil.java
index 199c1048..23eba080 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -256,8 +256,8 @@ public final class DatabaseUtil {
}
}
NV factory = assumeVectorField(database).getFactory();
- NV min = factory.newInstance(mins);
- NV max = factory.newInstance(maxs);
+ NV min = factory.newNumberVector(mins);
+ NV max = factory.newNumberVector(maxs);
return new Pair<NV, NV>(min, max);
}
@@ -316,7 +316,7 @@ public final class DatabaseUtil {
}
/**
- * Guess a potentially label-like representation.
+ * Guess a potentially label-like representation, preferring class labels.
*
* @param database
* @return string representation
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/ELKIServiceLoader.java b/src/de/lmu/ifi/dbs/elki/utilities/ELKIServiceLoader.java
new file mode 100644
index 00000000..b9a79d4a
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/ELKIServiceLoader.java
@@ -0,0 +1,207 @@
+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/>.
+ */
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Iterator;
+
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
+
+/**
+ * Class that emulates the behavior of an java ServiceLoader, except that the
+ * classes are <em>not</em> automatically instantiated. This is more lazy, but
+ * also we need to do the instantiations our way with the parameterizable API.
+ *
+ * @author Erich Schubert
+ */
+public class ELKIServiceLoader implements Iterator<Class<?>> {
+ /**
+ * Class logger.
+ */
+ private static final Logging logger = Logging.getLogger(ELKIServiceLoader.class);
+
+ /**
+ * Prefix for the ELKI functionality discovery.
+ */
+ public static final String PREFIX = "META-INF/elki/";
+
+ /**
+ * Comment character
+ */
+ public static final char COMMENT_CHAR = '#';
+
+ /**
+ * Parent class
+ */
+ private Class<?> parent;
+
+ /**
+ * Classloader
+ */
+ private ClassLoader cl;
+
+ /**
+ * Enumeration of configuration files
+ */
+ private Enumeration<URL> configfiles;
+
+ /**
+ * Current iterator
+ */
+ private Iterator<Class<?>> curiter = null;
+
+ /**
+ * Next class to return
+ */
+ private Class<?> nextclass;
+
+ /**
+ * Constructor.
+ *
+ * @param parent Parent class
+ * @param cl Classloader to use
+ */
+ public ELKIServiceLoader(Class<?> parent, ClassLoader cl) {
+ this.parent = parent;
+ this.cl = cl;
+ }
+
+ /**
+ * Constructor, using the system class loader.
+ *
+ * @param parent Parent class
+ */
+ public ELKIServiceLoader(Class<?> parent) {
+ this(parent, ClassLoader.getSystemClassLoader());
+ getServiceFiles(parent);
+ }
+
+ /**
+ * Get services files for a given class.
+ *
+ * @param parent Parent class
+ */
+ private void getServiceFiles(Class<?> parent) {
+ try {
+ String fullName = PREFIX + parent.getName();
+ configfiles = cl.getResources(fullName);
+ }
+ catch(IOException x) {
+ throw new AbortException("Could not load service configuration files.", x);
+ }
+ }
+
+ @Override
+ public boolean hasNext() {
+ if(nextclass != null) {
+ return true;
+ }
+ // Find next iterator
+ while((curiter == null) || !curiter.hasNext()) {
+ if(!configfiles.hasMoreElements()) {
+ return false;
+ }
+ curiter = parseFile(configfiles.nextElement());
+ }
+ nextclass = curiter.next();
+ return true;
+ }
+
+ private Iterator<Class<?>> parseFile(URL nextElement) {
+ ArrayList<Class<?>> classes = new ArrayList<Class<?>>();
+ try {
+ BufferedReader r = new BufferedReader(new InputStreamReader(nextElement.openStream(), "utf-8"));
+ while(parseLine(r.readLine(), classes, nextElement)) {
+ // Continue
+ }
+ }
+ catch(IOException x) {
+ throw new AbortException("Error reading configuration file", x);
+ }
+ return classes.iterator();
+ }
+
+ private boolean parseLine(String line, ArrayList<Class<?>> classes, URL nextElement) throws IOException {
+ if(line == null) {
+ return false;
+ }
+ // Ignore comments, trim whitespace
+ {
+ int begin = 0;
+ int end = line.indexOf(COMMENT_CHAR);
+ if(end < 0) {
+ end = line.length();
+ }
+ while(begin < end && line.charAt(begin) == ' ') {
+ begin++;
+ }
+ while(end - 1 > begin && line.charAt(end - 1) == ' ') {
+ end--;
+ }
+ if(begin > 0 || end < line.length()) {
+ line = line.substring(begin, end);
+ }
+ }
+ 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) {
+ assert (cls != null);
+ return true;
+ }
+ if(parent.isAssignableFrom(cls)) {
+ classes.add(cls);
+ }
+ else {
+ logger.warning("Class " + line + " does not implement " + parent + " but listed in service file " + nextElement);
+ }
+ }
+ catch(ClassNotFoundException e) {
+ logger.warning("Class not found: " + line + "; listed in service file " + nextElement, e);
+ }
+ return true;
+ }
+
+ @Override
+ public Class<?> next() {
+ Class<?> ret = nextclass;
+ nextclass = null;
+ 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/FileUtil.java b/src/de/lmu/ifi/dbs/elki/utilities/FileUtil.java
index 5d2a6a83..8c1c7fc7 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) 2011
+ Copyright (C) 2012
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/FormatUtil.java b/src/de/lmu/ifi/dbs/elki/utilities/FormatUtil.java
index e26a9a49..c61fdb10 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -34,7 +34,6 @@ import java.util.List;
import java.util.Locale;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Matrix;
-import de.lmu.ifi.dbs.elki.math.linearalgebra.MatrixLike;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
/**
@@ -47,6 +46,11 @@ public final class FormatUtil {
public static final NumberFormat NF = NumberFormat.getInstance(Locale.US);
/**
+ * Number Formatter (0 digits) for output purposes.
+ */
+ public static final NumberFormat NF0 = NumberFormat.getInstance(Locale.US);
+
+ /**
* Number Formatter (2 digits) for output purposes.
*/
public static final NumberFormat NF2 = NumberFormat.getInstance(Locale.US);
@@ -70,6 +74,9 @@ public final class FormatUtil {
NF.setMinimumFractionDigits(0);
NF.setMaximumFractionDigits(10);
NF.setGroupingUsed(false);
+ NF0.setMinimumFractionDigits(0);
+ NF0.setMaximumFractionDigits(0);
+ NF0.setGroupingUsed(false);
NF2.setMinimumFractionDigits(2);
NF2.setMaximumFractionDigits(2);
NF2.setGroupingUsed(false);
@@ -595,7 +602,7 @@ public final class FormatUtil {
* @return a string representation of this matrix
*/
// TODO: in use?
- public static String format(MatrixLike<?> m, int w, int d) {
+ public static String format(Matrix m, int w, int d) {
DecimalFormat format = new DecimalFormat();
format.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.US));
format.setMinimumIntegerDigits(1);
@@ -624,13 +631,46 @@ public final class FormatUtil {
}
/**
+ * Returns a string representation of this matrix.
+ *
+ * @param w column width
+ * @param d number of digits after the decimal
+ * @return a string representation of this matrix
+ */
+ // TODO: in use?
+ public static String format(Vector v, int w, int d) {
+ DecimalFormat format = new DecimalFormat();
+ format.setDecimalFormatSymbols(new DecimalFormatSymbols(Locale.US));
+ format.setMinimumIntegerDigits(1);
+ format.setMaximumFractionDigits(d);
+ format.setMinimumFractionDigits(d);
+ format.setGroupingUsed(false);
+
+ int width = w + 1;
+ StringBuffer msg = new StringBuffer();
+ msg.append("\n"); // start on new line.
+ for(int i = 0; i < v.getDimensionality(); i++) {
+ String s = format.format(v.get(i)); // format the number
+ int padding = Math.max(1, width - s.length()); // At _least_ 1
+ // space
+ for(int k = 0; k < padding; k++) {
+ msg.append(' ');
+ }
+ msg.append(s);
+ }
+ // msg.append("\n");
+
+ return msg.toString();
+ }
+
+ /**
* Returns a string representation of this matrix. In each line the specified
* String <code>pre</code> is prefixed.
*
* @param pre the prefix of each line
* @return a string representation of this matrix
*/
- public static String format(MatrixLike<?> m, String pre) {
+ public static String format(Matrix m, String pre) {
StringBuffer output = new StringBuffer();
output.append(pre).append("[\n").append(pre);
for(int i = 0; i < m.getRowDimensionality(); i++) {
@@ -719,13 +759,34 @@ public final class FormatUtil {
/**
* Returns a string representation of this matrix. In each line the specified
+ * String <code>pre</code> is prefixed.
+ *
+ * @param pre the prefix of each line
+ * @return a string representation of this matrix
+ */
+ public static String format(Vector v, String pre) {
+ StringBuffer output = new StringBuffer();
+ output.append(pre).append("[\n").append(pre);
+ for(int j = 0; j < v.getDimensionality(); j++) {
+ output.append(" ").append(v.get(j));
+ if(j < v.getDimensionality() - 1) {
+ output.append(",");
+ }
+ }
+ output.append("]\n").append(pre);
+
+ return (output.toString());
+ }
+
+ /**
+ * Returns a string representation of this matrix. In each line the specified
* String <code>pre<\code> is prefixed.
*
* @param nf number format for output accuracy
* @param pre the prefix of each line
* @return a string representation of this matrix
*/
- public static String format(MatrixLike<?> m, String pre, NumberFormat nf) {
+ public static String format(Matrix m, String pre, NumberFormat nf) {
if(nf == null) {
return FormatUtil.format(m, pre);
}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/HandlerList.java b/src/de/lmu/ifi/dbs/elki/utilities/HandlerList.java
index 02630233..8b5fcaca 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) 2011
+ Copyright (C) 2012
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/InspectionUtil.java b/src/de/lmu/ifi/dbs/elki/utilities/InspectionUtil.java
index 67dad564..66ecde64 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,23 +23,27 @@ package de.lmu.ifi.dbs.elki.utilities;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import gnu.trove.set.hash.THashSet;
+
import java.io.File;
import java.io.IOException;
-import java.lang.ref.WeakReference;
import java.lang.reflect.Modifier;
+import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
-import java.util.Stack;
-import java.util.Vector;
+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.iterator.IterableIterator;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ClassParameter;
+import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
/**
* A collection of inspection-related utility functions.
@@ -50,25 +54,32 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ClassParameter;
*/
public class InspectionUtil {
/**
+ * Class logger
+ */
+ private static final Logging logger = Logging.getLogger(InspectionUtil.class);
+
+ /**
* Default package ignores.
*/
private static final String[] DEFAULT_IGNORES = {
- // Sun Java
+ // Sun Java
"java.", "com.sun.",
- // Batik classes
+ // Batik classes
"org.apache.",
- // W3C / SVG / XML classes
+ // W3C / SVG / XML classes
"org.w3c.", "org.xml.", "javax.xml.",
- // JUnit
+ // JUnit
"org.junit.", "junit.", "org.hamcrest.",
- // Eclipse
+ // Eclipse
"org.eclipse.",
- // ApiViz
+ // ApiViz
"org.jboss.apiviz.",
- // JabRef
+ // JabRef
"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.",
- // Wrappers don't have important own parameters, they just set some defaults
- "experimentalcode.shared.wrapper." };
+ // GNU trove
+ "gnu.trove.",
+ //
+ };
/**
* If we have a non-static classpath, we do more extensive scanning for user
@@ -88,7 +99,15 @@ public class InspectionUtil {
NONSTATIC_CLASSPATH = hasnonstatic;
}
- private static WeakReference<List<Class<?>>> CLASS_CACHE = new WeakReference<List<Class<?>>>(null);
+ /**
+ * Weak hash map for class lookups
+ */
+ private static WeakHashMap<Class<?>, List<Class<?>>> CLASS_CACHE = new WeakHashMap<Class<?>, List<Class<?>>>();
+
+ /**
+ * (Non-weak) cache for all "frequently scanned" classes.
+ */
+ private static List<Class<?>> MASTER_CACHE = null;
/**
* Cached version of "findAllImplementations". For Parameterizable classes
@@ -98,29 +117,15 @@ public class InspectionUtil {
* @return Found implementations
*/
public static List<Class<?>> cachedFindAllImplementations(Class<?> c) {
- if (c == null) {
+ if(c == null) {
return Collections.emptyList();
}
- if(InspectionUtilFrequentlyScanned.class.isAssignableFrom(c)) {
- List<Class<?>> cache = CLASS_CACHE.get();
- if(cache == null) {
- cache = findAllImplementations(InspectionUtilFrequentlyScanned.class, false);
- CLASS_CACHE = new WeakReference<List<Class<?>>>(cache);
- }
- ArrayList<Class<?>> list = new ArrayList<Class<?>>();
- for(Class<?> cls : cache) {
- if(c.isAssignableFrom(cls)) {
- list.add(cls);
- }
- }
- return list;
- }
- else {
- // Need to scan - not cached.
- // LoggingUtil.logExpensive(Level.FINE,
- // "Slow scan for implementations: "+c.getName());
- return findAllImplementations(c, false);
+ List<Class<?>> res = CLASS_CACHE.get(c);
+ if(res == null) {
+ res = findAllImplementations(c, false);
+ CLASS_CACHE.put(c, res);
}
+ return res;
}
/**
@@ -133,71 +138,107 @@ public class InspectionUtil {
* @return List of found classes.
*/
public static List<Class<?>> findAllImplementations(Class<?> c, boolean everything) {
- String[] classpath = System.getProperty("java.class.path").split(System.getProperty("path.separator"));
- return findAllImplementations(classpath, c, DEFAULT_IGNORES, everything);
+ ArrayList<Class<?>> list = new ArrayList<Class<?>>();
+ // Add all from service files (i.e. jars)
+ {
+ Iterator<Class<?>> iter = new ELKIServiceLoader(c);
+ while(iter.hasNext()) {
+ list.add(iter.next());
+ }
+ }
+ if(!InspectionUtil.NONSTATIC_CLASSPATH) {
+ if(list.size() == 0) {
+ logger.warning("No implementations for " + c.getName() + " were found using index files.");
+ }
+ }
+ 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();
+ }
+ 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()))) {
+ continue;
+ }
+ if(c.isAssignableFrom(cls) && !dupes.contains(cls)) {
+ list.add(cls);
+ dupes.add(cls);
+ }
+ }
+ }
+ return list;
}
/**
- * Find all implementations of a given class.
+ * Get (or create) the result of a scan for any "frequent scanned" class.
*
- * @param classpath Classpath to use (JARs and folders supported)
- * @param c Class restriction
- * @param ignorepackages List of packages to ignore
- * @param everything include interfaces, abstract and private classes
- * @return List of found classes.
+ * @return Scan result
*/
- public static List<Class<?>> findAllImplementations(String[] classpath, Class<?> c, String[] ignorepackages, boolean everything) {
- // Collect iterators
- Vector<Iterable<String>> iters = new Vector<Iterable<String>>(classpath.length);
- for(String path : classpath) {
- File p = new File(path);
- if(path.endsWith(".jar")) {
- iters.add(new JarClassIterator(path));
- }
- else if(p.isDirectory()) {
- iters.add(new DirClassIterator(p));
- }
+ private static Iterator<Class<?>> getFrequentScan() {
+ if(MASTER_CACHE == null) {
+ MASTER_CACHE = slowScan(InspectionUtilFrequentlyScanned.class);
}
+ return MASTER_CACHE.iterator();
+ }
+ /**
+ * 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<?>>();
- ClassLoader cl = ClassLoader.getSystemClassLoader();
- for(Iterable<String> iter : iters) {
- for(String classname : iter) {
- boolean ignore = false;
- for(String pkg : ignorepackages) {
- if(classname.startsWith(pkg)) {
- ignore = true;
- break;
- }
- }
- if(ignore) {
- continue;
- }
- try {
- Class<?> cls = cl.loadClass(classname);
- // skip abstract / private classes.
- if(!everything && (Modifier.isInterface(cls.getModifiers()) || Modifier.isAbstract(cls.getModifiers()) || Modifier.isPrivate(cls.getModifiers()))) {
- continue;
+ try {
+ ClassLoader cl = ClassLoader.getSystemClassLoader();
+ Enumeration<URL> cps = cl.getResources("");
+ while(cps.hasMoreElements()) {
+ URL u = cps.nextElement();
+ // Scan file sources only.
+ if(u.getProtocol() == "file") {
+ Iterator<String> it = new DirClassIterator(new File(u.getFile()), DEFAULT_IGNORES);
+ while(it.hasNext()) {
+ String classname = it.next();
+ try {
+ Class<?> cls = cl.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)) {
+ continue;
+ }
+ res.add(cls);
+ }
+ catch(ClassNotFoundException e) {
+ continue;
+ }
+ catch(NoClassDefFoundError e) {
+ continue;
+ }
+ catch(Exception e) {
+ continue;
+ }
+ catch(Error e) {
+ continue;
+ }
}
- // skip classes where we can't get a full name.
- if(cls.getCanonicalName() == null) {
- continue;
- }
- if(c.isAssignableFrom(cls)) {
- res.add(cls);
- }
- }
- catch(ClassNotFoundException e) {
- continue;
- }
- catch(NoClassDefFoundError e) {
- continue;
- }
- catch(Exception e) {
- continue;
}
}
}
+ catch(IOException e) {
+ logger.exception(e);
+ }
Collections.sort(res, new ClassSorter());
return res;
}
@@ -205,21 +246,27 @@ 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>, Iterable<String> {
+ static class JarClassIterator implements IterableIterator<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) {
+ public JarClassIterator(String path, String[] ignorepackages) {
+ this.ignorepackages = ignorepackages;
try {
JarFile jf = new JarFile(path);
this.jarentries = jf.entries();
@@ -244,13 +291,18 @@ public class InspectionUtil {
* @return next entry or null
*/
private String findNext() {
- while(jarentries.hasMoreElements()) {
+ 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());
+ 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 classname.replace('/', '.');
}
}
}
@@ -283,73 +335,92 @@ public class InspectionUtil {
*
* @apiviz.exclude
*/
- static class DirClassIterator implements Iterator<String>, Iterable<String> {
+ static class DirClassIterator implements IterableIterator<String> {
+ private static final String CLASS_EXT = ".class";
+
+ private static final String FACTORY_FILE_EXT = ClassParameter.FACTORY_POSTFIX + CLASS_EXT;
+
+ private static final int CLASS_EXT_LENGTH = CLASS_EXT.length();
+
private String prefix;
- private Stack<File> set = new Stack<File>();
+ private ArrayList<String> files = new ArrayList<String>(100);
+
+ private ArrayList<Pair<File, String>> folders = new ArrayList<Pair<File, String>>(100);
- private String cur;
+ private String[] ignorepackages;
/**
* Constructor from Directory
*
* @param path Directory to iterate over
*/
- public DirClassIterator(File path) {
+ public DirClassIterator(File path, String[] ignorepackages) {
+ this.ignorepackages = ignorepackages;
this.prefix = path.getAbsolutePath();
- this.set.push(path);
- this.cur = findNext();
+ if(prefix.charAt(prefix.length() - 1) != File.separatorChar) {
+ prefix = prefix + File.separatorChar;
+ }
+
+ this.folders.add(new Pair<File, String>(path, ""));
}
@Override
public boolean hasNext() {
- // Do we have a next entry?
- return (cur != null);
+ if(files.size() == 0) {
+ findNext();
+ }
+ return (files.size() > 0);
}
/**
- * Find the next entry, since we need to skip some jar file entries.
- *
- * @return next entry or null
+ * Find the next entry, since we need to skip some directories.
*/
- private String findNext() {
- while(set.size() > 0) {
- File f = set.pop();
+ private void findNext() {
+ while(folders.size() > 0) {
+ Pair<File, String> pair = folders.remove(folders.size() - 1);
// recurse into directories
- if(f.isDirectory()) {
- // TODO: do not recurse into ignored packages!.
- for(File newf : f.listFiles()) {
- set.push(newf);
- }
- continue;
- }
- String name = f.getAbsolutePath();
- if(name.startsWith(prefix)) {
- int l = prefix.length();
- if(name.charAt(l) == File.separatorChar) {
- l += 1;
- }
- name = name.substring(l);
- }
- else {
- LoggingUtil.warning("I was expecting all directories to start with '" + prefix + "' but '" + name + "' did not.");
- }
- if(name.endsWith(".class")) {
- String classname = name.substring(0, name.length() - ".class".length());
- if(classname.endsWith(ClassParameter.FACTORY_POSTFIX) || !classname.contains("$")) {
- return classname.replace(File.separator, ".");
+ if(pair.first.isDirectory()) {
+ nextfile: for(String localname : pair.first.list()) {
+ // Ignore unix-hidden files/dirs
+ if(localname.charAt(0) == '.') {
+ continue;
+ }
+ // Classes
+ if(localname.endsWith(CLASS_EXT)) {
+ if(localname.indexOf('$') >= 0) {
+ if(!localname.endsWith(FACTORY_FILE_EXT)) {
+ continue;
+ }
+ }
+ files.add(pair.second + localname.substring(0, localname.length() - CLASS_EXT_LENGTH));
+ continue;
+ }
+ // Recurse into directories
+ File newf = new File(pair.first, localname);
+ if(newf.isDirectory()) {
+ String newpref = pair.second + localname + '.';
+ for(String ignore : ignorepackages) {
+ if(ignore.equals(newpref)) {
+ continue nextfile;
+ }
+ }
+ folders.add(new Pair<File, String>(newf, newpref));
+ }
}
}
}
- return null;
}
@Override
public String next() {
- // Return the previously stored entry.
- String ret = this.cur;
- this.cur = findNext();
- return ret;
+ if(files.size() == 0) {
+ findNext();
+ }
+ if(files.size() > 0) {
+ return files.remove(files.size() - 1);
+ }
+ return null;
}
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/InspectionUtilFrequentlyScanned.java b/src/de/lmu/ifi/dbs/elki/utilities/InspectionUtilFrequentlyScanned.java
index b666e077..11ea1da8 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/InspectionUtilFrequentlyScanned.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/InspectionUtilFrequentlyScanned.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) 2011
+ Copyright (C) 2012
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/QueryStatistic.java b/src/de/lmu/ifi/dbs/elki/utilities/QueryStatistic.java
index b5afc32b..91acad87 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/QueryStatistic.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/QueryStatistic.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) 2011
+ Copyright (C) 2012
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 fcaca269..6f79c1fa 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,21 +23,20 @@ package de.lmu.ifi.dbs.elki.utilities;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import gnu.trove.map.hash.TIntFloatHashMap;
+
import java.io.PrintStream;
-import java.util.AbstractCollection;
import java.util.ArrayList;
import java.util.BitSet;
-import java.util.Collection;
-import java.util.HashMap;
+import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
-import java.util.Map;
import java.util.Random;
-import java.util.Set;
import java.util.StringTokenizer;
import de.lmu.ifi.dbs.elki.data.DoubleVector;
import de.lmu.ifi.dbs.elki.data.SparseFloatVector;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayLikeUtil;
/**
* This class collects various static helper methods.
@@ -50,34 +49,6 @@ import de.lmu.ifi.dbs.elki.data.SparseFloatVector;
*/
public final class Util {
/**
- * Returns the prefix of the specified fileName (i.e. the name of the file
- * without extension).
- *
- * @param fileName the name of the file
- * @return the prefix of the specified fileName
- */
- public static String getFilePrefix(final String fileName) {
- final int index = fileName.lastIndexOf(Character.getNumericValue('.'));
- if(index < 0) {
- return fileName;
- }
- return fileName.substring(0, index);
- }
-
- /**
- * Returns a new String array containing the same objects as are contained in
- * the given array.
- *
- * @param array an array to copy
- * @return the copied array
- */
- public static String[] copy(String[] array) {
- String[] copy = new String[array.length];
- System.arraycopy(array, 0, copy, 0, array.length);
- return copy;
- }
-
- /**
* Returns a new double array containing the same objects as are contained in
* the given array.
*
@@ -91,49 +62,6 @@ public final class Util {
}
/**
- * Returns the unboxed double array of the given Object Double array.
- *
- * @param array the array to be unboxed
- * @return the unboxed double array
- */
- public static double[] unbox(Double[] array) {
- double[] unboxed = new double[array.length];
- // noinspection ManualArrayCopy
- for(int i = 0; i < unboxed.length; i++) {
- unboxed[i] = array[i];
- }
- return unboxed;
- }
-
- /**
- * Returns the unboxed double array of the given Object Number array.
- *
- * @param array the array to be unboxed
- * @return the unboxed double array
- */
- public static double[] unbox(Number[] array) {
- double[] unboxed = new double[array.length];
- for(int i = 0; i < unboxed.length; i++) {
- unboxed[i] = array[i].doubleValue();
- }
- return unboxed;
- }
-
- /**
- * Returns the unboxed float array of the given Object Number array.
- *
- * @param array the array to be unboxed
- * @return the unboxed float array
- */
- public static float[] unboxToFloat(Number[] array) {
- float[] unboxed = new float[array.length];
- for(int i = 0; i < unboxed.length; i++) {
- unboxed[i] = array[i].floatValue();
- }
- return unboxed;
- }
-
- /**
* Returns a new <code>Double</code> array initialized to the values
* represented by the specified <code>String</code> and separated by comma, as
* performed by the <code>valueOf</code> method of class <code>Double</code>.
@@ -148,81 +76,7 @@ public final class Util {
String d = tokenizer.nextToken();
result.add(Double.parseDouble(d));
}
- return unbox(result.toArray(new Double[result.size()]));
- }
-
- /**
- * Returns a new <code>Float</code> array initialized to the values
- * represented by the specified <code>String</code> and separated by comma, as
- * performed by the <code>valueOf</code> method of class <code>Float</code>.
- *
- * @param s the string to be parsed.
- * @return a new <code>Float</code> array represented by s
- */
- public static float[] parseFloats(String s) {
- List<Float> result = new ArrayList<Float>();
- StringTokenizer tokenizer = new StringTokenizer(s, ",");
- while(tokenizer.hasMoreTokens()) {
- String d = tokenizer.nextToken();
- result.add(Float.parseFloat(d));
- }
- return unboxToFloat(result.toArray(new Float[result.size()]));
- }
-
- /**
- * Converts the specified list of double objects to a list of float objects.
- *
- * @param values the list of double objects to be converted
- * @return the converted list of float objects
- */
- public static List<Float> convertToFloat(List<Double> values) {
- List<Float> result = new ArrayList<Float>(values.size());
- for(Double value : values) {
- result.add(new Float(value));
- }
- return result;
- }
-
- /**
- * Converts the specified array of doubles to an array of floats.
- *
- * @param values the array of doubles to be converted
- * @return the converted array of floats
- */
- public static float[] convertToFloat(double[] values) {
- float[] result = new float[values.length];
- for(int i = 0; i < values.length; i++) {
- result[i] = (float) values[i];
- }
- return result;
- }
-
- /**
- * Converts the specified array of doubles to an array of floats.
- *
- * @param values the array of doubles to be converted
- * @return the converted array of floats
- */
- public static double[] convertToDoubles(float[] values) {
- double[] result = new double[values.length];
- for(int i = 0; i < values.length; i++) {
- result[i] = values[i];
- }
- return result;
- }
-
- /**
- * Converts the specified list of Double objects to an array of doubles.
- *
- * @param values the list of Double objects to be converted
- * @return the converted array of doubles
- */
- public static double[] convertToDoubles(List<Double> values) {
- double[] result = new double[values.size()];
- for(int i = 0; i < result.length; i++) {
- result[i] = values.get(i);
- }
- return result;
+ return ArrayLikeUtil.toPrimitiveDoubleArray(result);
}
/**
@@ -246,105 +100,6 @@ public final class Util {
}
/**
- * Returns the index of the maximum of the given values. If no value is bigger
- * than the first, the index of the first entry is returned.
- *
- * @param values the values to find the index of the maximum
- * @return the index of the maximum in the given values
- * @throws ArrayIndexOutOfBoundsException if <code>values.length==0</code>
- */
- public static int getIndexOfMaximum(double[] values) throws ArrayIndexOutOfBoundsException {
- int index = 0;
- double max = values[index];
- for(int i = 0; i < values.length; i++) {
- if(values[i] > max) {
- max = values[i];
- index = i;
- }
- }
- return index;
- }
-
- /**
- * Returns a new <code>BitSet</code> initialized to the values represented by
- * the specified <code>String</code> only containing 0 and 1 values.
- *
- * @param s the string to be parsed.
- * @return a new <code>BitSet</code> represented by s
- */
- public static BitSet parseBitSet(String s) {
- try {
- return parseBitSet(s.toCharArray());
- }
- catch(IllegalArgumentException e) {
- throw new IllegalArgumentException("The specified String does not represent a bit set " + "containing only 0 and 1 values: " + s);
- }
- }
-
- /**
- * Returns a new <code>BitSet</code> initialized to the values represented by
- * the specified <code>char</code> array only containing '0' and '1' values.
- *
- * @param s the char array to be parsed.
- * @return a new <code>BitSet</code> represented by s
- */
- public static BitSet parseBitSet(char[] s) {
- BitSet result = new BitSet();
- for(int i = 0; i < s.length; i++) {
- if(s[i] == '1') {
- result.set(i);
- }
- else if(s[i] != '0') {
- throw new IllegalArgumentException("The specified String does not represent a bit set " + "containing only 0 and 1 values: " + String.valueOf(s));
- }
- }
- return result;
- }
-
- /**
- * Returns a string that represents the selected bits of the specified
- * <code>BitSet</code>, while the first bit starts with 1. The selected bits
- * are separated by the specified separator <code>sep</code>.
- *
- * If <code>sep</code> is &quot;,&quot;, the result is suitable as a parameter
- * for an IntListParameter.
- *
- * @param b the bit set to be parsed
- * @param sep the separator
- * @return a string representing the selected bits of the specified
- * <code>BitSet</code>
- */
- public static String parseSelectedBits(BitSet b, String sep) {
- StringBuffer result = new StringBuffer();
- for(int i = b.nextSetBit(0); i >= 0; i = b.nextSetBit(i + 1)) {
- if(result.length() != 0) {
- result.append(sep).append(i + 1);
- }
- else {
- result.append((i + 1));
- }
- }
-
- return result.toString();
- }
-
- /**
- * Convert a bit set to a list of integers, representing bits that are set
- *
- * @param b Bitset
- * @param off Offset, set to 0 to start counting at 0, 1 to start counting at
- * 1.
- * @return List
- */
- public static List<Integer> convertBitSetToListInt(BitSet b, int off) {
- List<Integer> list = new ArrayList<Integer>();
- for(int i = b.nextSetBit(0); i >= 0; i = b.nextSetBit(i + 1)) {
- list.add(i + off);
- }
- return list;
- }
-
- /**
* Creates a new BitSet of fixed cardinality with randomly set bits.
*
* @param cardinality the cardinality of the BitSet to create
@@ -357,9 +112,19 @@ public final class Util {
* @return a new BitSet with randomly set bits
*/
public static BitSet randomBitSet(int cardinality, int capacity, Random random) {
+ assert (cardinality >= 0) : "Cannot set a negative number of bits!";
+ assert (cardinality < capacity) : "Cannot set " + cardinality + " of " + capacity + " bits!";
BitSet bitset = new BitSet(capacity);
- while(bitset.cardinality() < cardinality) {
- bitset.set(random.nextInt(capacity));
+ if(cardinality < capacity >>> 1) {
+ while(bitset.cardinality() < cardinality) {
+ bitset.set(random.nextInt(capacity));
+ }
+ }
+ else {
+ bitset.flip(0, capacity);
+ while(bitset.cardinality() > cardinality) {
+ bitset.clear(random.nextInt(capacity));
+ }
}
return bitset;
}
@@ -410,7 +175,7 @@ public final class Util {
* SparseFloatVector.
*/
public static SparseFloatVector project(SparseFloatVector v, BitSet selectedAttributes) {
- Map<Integer, Float> values = new HashMap<Integer, Float>(selectedAttributes.cardinality(), 1);
+ TIntFloatHashMap values = new TIntFloatHashMap(selectedAttributes.cardinality(), 1);
for(int d = selectedAttributes.nextSetBit(0); d >= 0; d = selectedAttributes.nextSetBit(d + 1)) {
if(v.getValue(d + 1) != 0.0f) {
values.put(d, v.getValue(d + 1));
@@ -421,124 +186,6 @@ public final class Util {
}
/**
- * Returns the index of the n<sup>th</sup> set bit in the given BitSet. For
- * the parameter <code>nthSetBit</code>, following condition is assumed:
- * <code>1 &le; nthSetBit &le; bitset.cardinality()</code>. Otherwise, i.e.,
- * if the Bitset contains less than <code>nthSetBit</code> set bits or
- * <code>nthSetBit</code> is not a positive number, the method throws an
- * IllegalArgumentException.
- *
- * The worstcase runtime complexity of this method is in <i>O(
- * <code>bitset.cardinality()</code>)</i>.
- *
- * @param bitset the BitSet to derive the index of the n<sup>th</sup> set bit
- * in
- * @param nthSetBit which set bit to derive the index of
- * @return the index of the n<sup>th</sup> set bit in the given BitSet
- * @throws IllegalArgumentException if the Bitset contains less than
- * <code>nthSetBit</code> set bits or <code>nthSetBit</code> is not a
- * positive number
- */
- public static int indexOfNthSetBit(BitSet bitset, int nthSetBit) throws IllegalArgumentException {
- if(nthSetBit < 1 || nthSetBit > bitset.cardinality()) {
- throw new IllegalArgumentException("Parameter nthSetBit out of range: nthSetBit=" + nthSetBit + ", bitset.cardinality=" + bitset.cardinality());
- }
- int i = 0;
- int index = -1;
- for(int d = bitset.nextSetBit(0); d >= 0 && i < nthSetBit; d = bitset.nextSetBit(d + 1)) {
- i++;
- index = d;
- }
- return index;
- }
-
- /**
- * Provides the intersection of the two specified sets in the given result
- * set.
- *
- * @param <O> object class
- * @param s1 the first set
- * @param s2 the second set
- * @param result the result set
- */
- public static <O> void intersection(Set<O> s1, Set<O> s2, Set<O> result) {
- for(O object : s1) {
- if(s2.contains(object)) {
- result.add(object);
- }
- }
- }
-
- /**
- * Converts the specified positive integer value into a bit representation,
- * where bit 0 denotes 2<sup>0</sup>, bit 1 denotes 2<sup>1</sup> etc.
- *
- * @param n the positive integer value to be converted
- * @return the specified integer value into a bit representation
- */
- public static BitSet int2Bit(int n) {
- if(n < 0) {
- throw new IllegalArgumentException("Parameter n hast to be greater than or equal to zero!");
- }
-
- BitSet result = new BitSet();
- int i = 0;
- while(n > 0) {
- boolean rest = (n % 2 == 1);
- if(rest) {
- result.set(i);
- }
- n = n / 2;
- i++;
- }
- return result;
- }
-
- /**
- * Joins the specified arrays.
- *
- * @param array1 the first array
- * @param array2 the second array
- * @return a new array containing the entries of <code>array1</code> and the
- * <code>array2</code>.
- */
- public static String[] joinArray(String[] array1, String[] array2) {
- String[] newArray = new String[array1.length + array2.length];
- System.arraycopy(array1, 0, newArray, 0, array1.length);
- System.arraycopy(array2, 0, newArray, array1.length, array2.length);
- return newArray;
- }
-
- /**
- * Adds the entries of the specified array to the end of the given list.
- *
- * @param <O> object class
- * @param list the list
- * @param array the array containing the objects to be added to the list
- */
- public static <O> void addToList(List<O> list, O[] array) {
- for(O object : array) {
- list.add(object);
- }
- }
-
- /**
- * Search an (unsorted) array linearly for an object.
- *
- * @param arr Array to search
- * @param ref Object to search for
- * @return Index of object or -1 if not found.
- */
- public static int arrayFind(String[] arr, Object ref) {
- for(int index = 0; index < arr.length; index++) {
- if(ref.equals(arr[index])) {
- return index;
- }
- }
- return -1;
- }
-
- /**
* Mix multiple hashcodes into one.
*
* @param hash Hashcodes to mix
@@ -550,153 +197,40 @@ public final class Util {
return 0;
}
long result = hash[0];
- for (int i = 1; i < hash.length; i++) {
+ for(int i = 1; i < hash.length; i++) {
result = result * prime + hash[i];
}
return (int) result;
}
/**
- * This class is a virtual collection based on masking an array list using a
- * bit mask.
+ * Static instance
+ */
+ private static final Comparator<?> FORWARD = new ForwardComparator();
+
+ /**
+ * Regular comparator. See {@link java.util.Collections#reverseOrder()} for a
+ * reverse comparator.
*
* @author Erich Schubert
*
- * @apiviz.stereotype decorator
- * @apiviz.composedOf java.util.ArrayList
- * @apiviz.composedOf java.util.BitSet
- *
- * @param <T> Object type
+ * @apiviz.exclude
*/
- public static 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();
- }
- }
-
+ private static final class ForwardComparator implements Comparator<Comparable<Object>> {
@Override
- public int size() {
- if(inverse) {
- return data.size() - bits.cardinality();
- }
- else {
- return bits.cardinality();
- }
+ public int compare(Comparable<Object> o1, Comparable<Object> o2) {
+ return o1.compareTo(o2);
}
+ }
- /**
- * 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();
- }
- }
+ /**
+ * Compare two objects, forward. See
+ * {@link java.util.Collections#reverseOrder()} for a reverse comparator.
+ *
+ * @return Forward comparator
+ */
+ @SuppressWarnings("unchecked")
+ public static final <T> Comparator<T> forwardOrder() {
+ return (Comparator<T>) FORWARD;
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/AnyMap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/AnyMap.java
index 9e1307be..763ce105 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/AnyMap.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/AnyMap.java
@@ -4,7 +4,7 @@ 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) 2011
+ Copyright (C) 2012
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/HashMapList.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/HashMapList.java
index 7c5c950b..26fa4d19 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/HashMapList.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/HashMapList.java
@@ -4,7 +4,7 @@ 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) 2011
+ Copyright (C) 2012
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/MaskedArrayList.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/MaskedArrayList.java
new file mode 100644
index 00000000..c24519d1
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/MaskedArrayList.java
@@ -0,0 +1,174 @@
+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
new file mode 100644
index 00000000..4498cf07
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/QuickSelect.java
@@ -0,0 +1,780 @@
+package de.lmu.ifi.dbs.elki.utilities.datastructures;
+
+import java.util.Comparator;
+import java.util.List;
+
+/*
+ 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/>.
+ */
+
+/**
+ * QuickSelect computes ("selects") the element at a given rank and can be used
+ * to compute Medians and arbitrary quantiles by computing the appropriate rank.
+ *
+ * This algorithm is essentially an incomplete QuickSort that only descends into
+ * that part of the data that we are interested in, and also attributed to
+ * Charles Antony Richard Hoare
+ *
+ * @author Erich Schubert
+ */
+public class QuickSelect {
+ /**
+ * For small arrays, use a simpler method:
+ */
+ private static final int SMALL = 10;
+
+ /**
+ * QuickSelect is essentially quicksort, except that we only "sort" that half
+ * of the array that we are interested in.
+ *
+ * Note: the array is <b>modified</b> by this.
+ *
+ * @param data Data to process
+ * @param rank Rank position that we are interested in (integer!)
+ * @return Value at the given rank
+ */
+ public static double quickSelect(double[] data, int rank) {
+ quickSelect(data, 0, data.length, rank);
+ return data[rank];
+ }
+
+ /**
+ * Compute the median of an array efficiently using the QuickSelect method.
+ *
+ * Note: the array is <b>modified</b> by this.
+ *
+ * @param data Data to process
+ * @return Median value
+ */
+ public static double median(double[] data) {
+ return median(data, 0, data.length);
+ }
+
+ /**
+ * Compute the median of an array efficiently using the QuickSelect method.
+ *
+ * Note: the array is <b>modified</b> by this.
+ *
+ * @param data Data to process
+ * @param begin Begin of valid values
+ * @param end End of valid values (exclusive!)
+ * @return Median value
+ */
+ public static double median(double[] data, int begin, int end) {
+ final int length = end - begin;
+ assert (length > 0);
+ // Integer division is "floor" since we are non-negative.
+ final int left = begin + (length - 1) / 2;
+ quickSelect(data, begin, end, left);
+ if(length % 2 == 1) {
+ return data[left];
+ }
+ else {
+ quickSelect(data, begin, end, left + 1);
+ return data[left] + (data[left + 1] - data[left]) / 2;
+ }
+ }
+
+ /**
+ * Compute the median of an array efficiently using the QuickSelect method.
+ *
+ * Note: the array is <b>modified</b> by this.
+ *
+ * @param data Data to process
+ * @param quant Quantile to compute
+ * @return Value at quantile
+ */
+ public static double quantile(double[] data, double quant) {
+ return quantile(data, 0, data.length, quant);
+ }
+
+ /**
+ * Compute the median of an array efficiently using the QuickSelect method.
+ *
+ * Note: the array is <b>modified</b> by this.
+ *
+ * @param data Data to process
+ * @param begin Begin of valid values
+ * @param end End of valid values (exclusive!)
+ * @param quant Quantile to compute
+ * @return Value at quantile
+ */
+ public static double quantile(double[] data, int begin, int end, double quant) {
+ final int length = end - begin;
+ assert (length > 0) : "Quantile on empty set?";
+ // Integer division is "floor" since we are non-negative.
+ final double dleft = begin + (length - 1) * quant;
+ final int ileft = (int) Math.floor(dleft);
+ final double err = dleft - ileft;
+
+ quickSelect(data, begin, end, ileft);
+ if(err <= Double.MIN_NORMAL) {
+ return data[ileft];
+ }
+ else {
+ quickSelect(data, begin, end, ileft + 1);
+ // Mix:
+ double mix = data[ileft] + (data[ileft + 1] - data[ileft]) * err;
+ return mix;
+ }
+ }
+
+ /**
+ * 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 void quickSelect(double[] data, int start, int end, int rank) {
+ // Optimization for small arrays
+ // This also ensures a minimum size below
+ 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) / 2;
+ if(data[start] > data[middle]) {
+ swap(data, start, middle);
+ }
+ if(data[start] > data[end - 1]) {
+ swap(data, start, end - 1);
+ }
+ if(data[middle] > data[end - 1]) {
+ swap(data, middle, end - 1);
+ }
+ // 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);
+
+ // Begin partitioning
+ int i = start + 1, j = end - 3;
+ // This is classic quicksort stuff
+ while(true) {
+ while(data[i] <= pivot && i <= j) {
+ i++;
+ }
+ while(data[j] >= pivot && j >= 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);
+
+ // In contrast to quicksort, we only need to recurse into the half we are
+ // interested in.
+ if(rank < i) {
+ quickSelect(data, start, i, rank);
+ }
+ else if(rank > i) {
+ quickSelect(data, i + 1, end, rank);
+ }
+ }
+
+ /**
+ * 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(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--) {
+ swap(data, j, j - 1);
+ }
+ }
+ }
+
+ /**
+ * The usual swap method.
+ *
+ * @param data Array
+ * @param a First index
+ * @param b Second index
+ */
+ private static final void swap(double[] data, int a, int b) {
+ double tmp = data[a];
+ data[a] = data[b];
+ data[b] = tmp;
+ }
+
+ /**
+ * QuickSelect is essentially quicksort, except that we only "sort" that half
+ * of the array that we are interested in.
+ *
+ * Note: the array is <b>modified</b> by this.
+ *
+ * @param <T> object type
+ * @param data Data to process
+ * @param rank Rank position that we are interested in (integer!)
+ * @return Value at the given rank
+ */
+ public static <T extends Comparable<? super T>> T quickSelect(T[] data, int rank) {
+ quickSelect(data, 0, data.length, rank);
+ return data[rank];
+ }
+
+ /**
+ * Compute the median of an array efficiently using the QuickSelect method.
+ *
+ * Note: the array is <b>modified</b> by this.
+ *
+ * @param data Data to process
+ * @return Median value
+ */
+ public static <T extends Comparable<? super T>> T median(T[] data) {
+ return median(data, 0, data.length);
+ }
+
+ /**
+ * Compute the median of an array efficiently using the QuickSelect method.
+ *
+ * On an odd length, it will return the lower element.
+ *
+ * Note: the array is <b>modified</b> by this.
+ *
+ * @param <T> object type
+ * @param data Data to process
+ * @param begin Begin of valid values
+ * @param end End of valid values (exclusive!)
+ * @return Median value
+ */
+ public static <T extends Comparable<? super T>> T median(T[] data, int begin, int end) {
+ final int length = end - begin;
+ assert (length > 0);
+ // Integer division is "floor" since we are non-negative.
+ final int left = begin + (length - 1) / 2;
+ quickSelect(data, begin, end, left);
+ return data[left];
+ }
+
+ /**
+ * Compute the median of an array efficiently using the QuickSelect method.
+ *
+ * Note: the array is <b>modified</b> by this.
+ *
+ * @param <T> object type
+ * @param data Data to process
+ * @param quant Quantile to compute
+ * @return Value at quantile
+ */
+ public static <T extends Comparable<? super T>> T quantile(T[] data, double quant) {
+ return quantile(data, 0, data.length, quant);
+ }
+
+ /**
+ * Compute the median of an array efficiently using the QuickSelect method.
+ *
+ * It will prefer the lower element.
+ *
+ * Note: the array is <b>modified</b> by this.
+ *
+ * @param <T> object type
+ * @param data Data to process
+ * @param begin Begin of valid values
+ * @param end End of valid values (exclusive!)
+ * @param quant Quantile to compute
+ * @return Value at quantile
+ */
+ public static <T extends Comparable<? super T>> T quantile(T[] data, int begin, int end, double quant) {
+ final int length = end - begin;
+ assert (length > 0) : "Quantile on empty set?";
+ // Integer division is "floor" since we are non-negative.
+ final double dleft = begin + (length - 1) * quant;
+ final int ileft = (int) Math.floor(dleft);
+
+ quickSelect(data, begin, end, ileft);
+ return data[ileft];
+ }
+
+ /**
+ * QuickSelect is essentially quicksort, except that we only "sort" that half
+ * of the array that we are interested in.
+ *
+ * @param <T> object type
+ * @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 extends Comparable<? super T>> void quickSelect(T[] data, int start, int end, int rank) {
+ // Optimization for small arrays
+ // This also ensures a minimum size below
+ 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) / 2;
+ if(data[start].compareTo(data[middle]) > 0) {
+ swap(data, start, middle);
+ }
+ if(data[start].compareTo(data[end - 1]) > 0) {
+ swap(data, start, end - 1);
+ }
+ if(data[middle].compareTo(data[end - 1]) > 0) {
+ swap(data, middle, end - 1);
+ }
+ // 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);
+
+ // Begin partitioning
+ int i = start + 1, j = end - 3;
+ // This is classic quicksort stuff
+ while(true) {
+ while(data[i].compareTo(pivot) <= 0 && i <= j) {
+ i++;
+ }
+ while(data[j].compareTo(pivot) >= 0 && j >= 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);
+
+ // In contrast to quicksort, we only need to recurse into the half we are
+ // interested in.
+ if(rank < i) {
+ quickSelect(data, start, i, rank);
+ }
+ else if(rank > i) {
+ quickSelect(data, i + 1, end, rank);
+ }
+ }
+
+ /**
+ * Sort a small array using repetitive insertion sort.
+ *
+ * @param <T> object type
+ * @param data Data to sort
+ * @param start Interval start
+ * @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--) {
+ swap(data, j, j - 1);
+ }
+ }
+ }
+
+ /**
+ * The usual swap method.
+ *
+ * @param <T> object type
+ * @param data Array
+ * @param a First index
+ * @param b Second index
+ */
+ private static final <T extends Comparable<? super T>> void swap(T[] data, int a, int b) {
+ T tmp = data[a];
+ data[a] = data[b];
+ data[b] = tmp;
+ }
+
+ /**
+ * QuickSelect is essentially quicksort, except that we only "sort" that half
+ * of the array that we are interested in.
+ *
+ * Note: the array is <b>modified</b> by this.
+ *
+ * @param <T> object type
+ * @param data Data to process
+ * @param rank Rank position that we are interested in (integer!)
+ * @return Value at the given rank
+ */
+ public static <T extends Comparable<? super T>> T quickSelect(List<? extends T> data, int rank) {
+ quickSelect(data, 0, data.size(), rank);
+ return data.get(rank);
+ }
+
+ /**
+ * Compute the median of an array efficiently using the QuickSelect method.
+ *
+ * Note: the array is <b>modified</b> by this.
+ *
+ * @param <T> object type
+ * @param data Data to process
+ * @return Median value
+ */
+ public static <T extends Comparable<? super T>> T median(List<? extends T> data) {
+ return median(data, 0, data.size());
+ }
+
+ /**
+ * Compute the median of an array efficiently using the QuickSelect method.
+ *
+ * On an odd length, it will return the lower element.
+ *
+ * Note: the array is <b>modified</b> by this.
+ *
+ * @param <T> object type
+ * @param data Data to process
+ * @param begin Begin of valid values
+ * @param end End of valid values (exclusive!)
+ * @return Median value
+ */
+ public static <T extends Comparable<? super T>> T median(List<? extends T> data, int begin, int end) {
+ final int length = end - begin;
+ assert (length > 0);
+ // Integer division is "floor" since we are non-negative.
+ final int left = begin + (length - 1) / 2;
+ quickSelect(data, begin, end, left);
+ return data.get(left);
+ }
+
+ /**
+ * Compute the median of an array efficiently using the QuickSelect method.
+ *
+ * Note: the array is <b>modified</b> by this.
+ *
+ * @param <T> object type
+ * @param data Data to process
+ * @param quant Quantile to compute
+ * @return Value at quantile
+ */
+ public static <T extends Comparable<? super T>> T quantile(List<? extends T> data, double quant) {
+ return quantile(data, 0, data.size(), quant);
+ }
+
+ /**
+ * Compute the median of an array efficiently using the QuickSelect method.
+ *
+ * It will prefer the lower element.
+ *
+ * Note: the array is <b>modified</b> by this.
+ *
+ * @param <T> object type
+ * @param data Data to process
+ * @param begin Begin of valid values
+ * @param end End of valid values (exclusive!)
+ * @param quant Quantile to compute
+ * @return Value at quantile
+ */
+ public static <T extends Comparable<? super T>> T quantile(List<? extends T> data, int begin, int end, double quant) {
+ final int length = end - begin;
+ assert (length > 0) : "Quantile on empty set?";
+ // Integer division is "floor" since we are non-negative.
+ final double dleft = begin + (length - 1) * quant;
+ final int ileft = (int) Math.floor(dleft);
+
+ quickSelect(data, begin, end, ileft);
+ return data.get(ileft);
+ }
+
+ /**
+ * QuickSelect is essentially quicksort, except that we only "sort" that half
+ * of the array that we are interested in.
+ *
+ * @param <T> object type
+ * @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 extends Comparable<? super T>> void quickSelect(List<? extends T> data, int start, int end, int rank) {
+ // Optimization for small arrays
+ // This also ensures a minimum size below
+ 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) / 2;
+ if(data.get(start).compareTo(data.get(middle)) > 0) {
+ swap(data, start, middle);
+ }
+ if(data.get(start).compareTo(data.get(end - 1)) > 0) {
+ swap(data, start, end - 1);
+ }
+ if(data.get(middle).compareTo(data.get(end - 1)) > 0) {
+ swap(data, middle, end - 1);
+ }
+ // TODO: use more candidates for larger arrays?
+
+ final T pivot = data.get(middle);
+ // Move middle element out of the way, just before end
+ // (Since we already know that "end" is bigger)
+ swap(data, middle, end - 2);
+
+ // Begin partitioning
+ int i = start + 1, j = end - 3;
+ // This is classic quicksort stuff
+ while(true) {
+ while(data.get(i).compareTo(pivot) <= 0 && i <= j) {
+ i++;
+ }
+ while(data.get(j).compareTo(pivot) >= 0 && j >= 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);
+
+ // In contrast to quicksort, we only need to recurse into the half we are
+ // interested in.
+ if(rank < i) {
+ quickSelect(data, start, i, rank);
+ }
+ else if(rank > i) {
+ quickSelect(data, i + 1, end, rank);
+ }
+ }
+
+ /**
+ * Sort a small array using repetitive insertion sort.
+ *
+ * @param <T> object type
+ * @param data Data to sort
+ * @param start Interval start
+ * @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--) {
+ swap(data, j, j - 1);
+ }
+ }
+ }
+
+ /**
+ * The usual swap method.
+ *
+ * @param <T> object type
+ * @param data Array
+ * @param a First index
+ * @param b Second index
+ */
+ private static final <T> void swap(List<T> data, int a, int b) {
+ data.set(b, data.set(a, data.get(b)));
+ }
+
+ /**
+ * QuickSelect is essentially quicksort, except that we only "sort" that half
+ * of the array that we are interested in.
+ *
+ * Note: the array is <b>modified</b> by this.
+ *
+ * @param <T> object type
+ * @param data Data to process
+ * @param comparator Comparator to use
+ * @param rank Rank position that we are interested in (integer!)
+ * @return Value at the given rank
+ */
+ public static <T> T quickSelect(List<? extends T> data, Comparator<? super T> comparator, int rank) {
+ quickSelect(data, comparator, 0, data.size(), rank);
+ return data.get(rank);
+ }
+
+ /**
+ * Compute the median of an array efficiently using the QuickSelect method.
+ *
+ * Note: the array is <b>modified</b> by this.
+ *
+ * @param <T> object type
+ * @param data Data to process
+ * @param comparator Comparator to use
+ * @return Median value
+ */
+ public static <T> T median(List<? extends T> data, Comparator<? super T> comparator) {
+ return median(data, comparator, 0, data.size());
+ }
+
+ /**
+ * Compute the median of an array efficiently using the QuickSelect method.
+ *
+ * On an odd length, it will return the lower element.
+ *
+ * Note: the array is <b>modified</b> by this.
+ *
+ * @param <T> object type
+ * @param data Data to process
+ * @param comparator Comparator to use
+ * @param begin Begin of valid values
+ * @param end End of valid values (exclusive!)
+ * @return Median value
+ */
+ public static <T> T median(List<? extends T> data, Comparator<? super T> comparator, int begin, int end) {
+ final int length = end - begin;
+ assert (length > 0);
+ // Integer division is "floor" since we are non-negative.
+ final int left = begin + (length - 1) / 2;
+ quickSelect(data, comparator, begin, end, left);
+ return data.get(left);
+ }
+
+ /**
+ * Compute the median of an array efficiently using the QuickSelect method.
+ *
+ * Note: the array is <b>modified</b> by this.
+ *
+ * @param <T> object type
+ * @param data Data to process
+ * @param comparator Comparator to use
+ * @param quant Quantile to compute
+ * @return Value at quantile
+ */
+ public static <T> T quantile(List<? extends T> data, Comparator<? super T> comparator, double quant) {
+ return quantile(data, comparator, 0, data.size(), quant);
+ }
+
+ /**
+ * Compute the median of an array efficiently using the QuickSelect method.
+ *
+ * It will prefer the lower element.
+ *
+ * Note: the array is <b>modified</b> by this.
+ *
+ * @param <T> object type
+ * @param data Data to process
+ * @param comparator Comparator to use
+ * @param begin Begin of valid values
+ * @param end End of valid values (inclusive!)
+ * @param quant Quantile to compute
+ * @return Value at quantile
+ */
+ public static <T> T quantile(List<? extends T> data, Comparator<? super T> comparator, int begin, int end, double quant) {
+ final int length = end - begin;
+ assert (length > 0) : "Quantile on empty set?";
+ // Integer division is "floor" since we are non-negative.
+ final double dleft = begin + (length - 1) * quant;
+ final int ileft = (int) Math.floor(dleft);
+
+ quickSelect(data, comparator, begin, end, ileft);
+ return data.get(ileft);
+ }
+
+ /**
+ * QuickSelect is essentially quicksort, except that we only "sort" that half
+ * of the array that we are interested in.
+ *
+ * @param <T> object type
+ * @param data Data to process
+ * @param comparator Comparator to use
+ * @param start Interval start
+ * @param end Interval end (inclusive)
+ * @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) {
+ // Optimization for small arrays
+ // This also ensures a minimum size below
+ 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) / 2;
+ if(comparator.compare(data.get(start), data.get(middle)) > 0) {
+ swap(data, start, middle);
+ }
+ if(comparator.compare(data.get(start), data.get(end - 1)) > 0) {
+ swap(data, start, end - 1);
+ }
+ if(comparator.compare(data.get(middle), data.get(end - 1)) > 0) {
+ swap(data, middle, end - 1);
+ }
+ // TODO: use more candidates for larger arrays?
+
+ final T pivot = data.get(middle);
+ // Move middle element out of the way, just before end
+ // (Since we already know that "end" is bigger)
+ swap(data, middle, end - 2);
+
+ // Begin partitioning
+ int i = start + 1, j = end - 3;
+ // This is classic quicksort stuff
+ while(true) {
+ while(comparator.compare(data.get(i), pivot) <= 0 && i <= j) {
+ i++;
+ }
+ while(comparator.compare(data.get(j), pivot) >= 0 && j >= 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);
+
+ // In contrast to quicksort, we only need to recurse into the half we are
+ // interested in.
+ if(rank < i) {
+ quickSelect(data, comparator, start, i, rank);
+ }
+ else if(rank > i) {
+ quickSelect(data, comparator, i + 1, end, rank);
+ }
+ }
+
+ /**
+ * Sort a small array using repetitive insertion sort.
+ *
+ * @param <T> object type
+ * @param data Data to sort
+ * @param start Interval start
+ * @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--) {
+ swap(data, j, j - 1);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/paircounting/generator/PairSortedGeneratorInterface.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ArrayAdapter.java
index f7b67d60..969d068d 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/paircounting/generator/PairSortedGeneratorInterface.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ArrayAdapter.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.evaluation.paircounting.generator;
+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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,28 +23,30 @@ package de.lmu.ifi.dbs.elki.evaluation.paircounting.generator;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import de.lmu.ifi.dbs.elki.utilities.pairs.IntIntPair;
-
/**
- * Pair generator interface.
- * Implementation must return pairs <em>sorted</em>.
- *
- * Basically this is an Iterator interface, but it deliberately has a current() method,
- * that is useful e.g. for merging.
+ * Adapter for array-like things. For example, arrays and lists.
*
* @author Erich Schubert
+ *
+ * @param <T> Item type
+ * @param <A> Array object type
*/
-public interface PairSortedGeneratorInterface {
+public interface ArrayAdapter<T, A> {
/**
- * Return current pair.
+ * Get the size of the array.
*
- * @return current pair, null if there are no more pairs
+ * @param array Array-like thing
+ * @return Size
*/
- public IntIntPair current();
+ public int size(A array);
+
/**
- * Return next pair, advance generator
+ * Get the off'th item from the array.
*
- * @return next pair, null if there are no more pairs
+ * @param array Array to get from
+ * @param off Offset
+ * @return Item at offset off
+ * @throws IndexOutOfBoundsException for an invalid index.
*/
- public IntIntPair next();
+ public T get(A array, int off) throws IndexOutOfBoundsException;
} \ No newline at end of file
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
new file mode 100644
index 00000000..6e6e8122
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ArrayDBIDsAdapter.java
@@ -0,0 +1,53 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.ArrayDBIDs;
+import de.lmu.ifi.dbs.elki.database.ids.DBID;
+
+/**
+ * Use a DBID array in a generic array-like context.
+ *
+ * @author Erich Schubert
+ */
+public class ArrayDBIDsAdapter implements ArrayAdapter<DBID, ArrayDBIDs> {
+ /**
+ * Constructor.
+ *
+ * Protected - use the static instance from {@link ArrayLikeUtil}!
+ */
+ protected ArrayDBIDsAdapter() {
+ super();
+ }
+
+ @Override
+ public int size(ArrayDBIDs array) {
+ return array.size();
+ }
+
+ @Override
+ public DBID get(ArrayDBIDs array, int off) throws IndexOutOfBoundsException {
+ return array.get(off);
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..2d29f40c
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ArrayLikeUtil.java
@@ -0,0 +1,253 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.FeatureVector;
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+
+/**
+ * Utility class that allows plug-in use of various "array-like" types such as
+ * lists in APIs that can take any kind of array to safe the cost of
+ * reorganizing the objects into a real array.
+ *
+ * @author Erich Schubert
+ */
+public final class ArrayLikeUtil {
+ /**
+ * Static instance for lists
+ */
+ private static final ListArrayAdapter<Object> LISTADAPTER = new ListArrayAdapter<Object>();
+
+ /**
+ * Static instance for lists of numbers
+ */
+ private static final NumberListArrayAdapter<Number> NUMBERLISTADAPTER = new NumberListArrayAdapter<Number>();
+
+ /**
+ * Static instance
+ */
+ private final static IdentityArrayAdapter<?> IDENTITYADAPTER = new IdentityArrayAdapter<Object>();
+
+ /**
+ * Static instance
+ */
+ private static final FeatureVectorAdapter<?> FEATUREVECTORADAPTER = new FeatureVectorAdapter<Number>();
+
+ /**
+ * Use a number vector in the array API.
+ */
+ private static final NumberVectorAdapter<?> NUMBERVECTORADAPTER = new NumberVectorAdapter<Double>();
+
+ /**
+ * Use a double array in the array API.
+ */
+ public static final NumberArrayAdapter<Double, double[]> DOUBLEARRAYADAPTER = new DoubleArrayAdapter();
+
+ /**
+ * Use a float array in the array API.
+ */
+ public static final NumberArrayAdapter<Float, float[]> FLOATARRAYADAPTER = new FloatArrayAdapter();
+
+ /**
+ * Use a Trove double list as array.
+ */
+ public static final TDoubleListAdapter TDOUBLELISTADAPTER = new TDoubleListAdapter();
+
+ /**
+ * Use ArrayDBIDs as array.
+ */
+ public static final ArrayDBIDsAdapter ARRAYDBIDADAPTER = new ArrayDBIDsAdapter();
+
+ /**
+ * Cast the static instance.
+ *
+ * @param dummy Dummy variable, for type inference
+ * @return Static instance
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> ArrayAdapter<T, List<? extends T>> listAdapter(List<? extends T> dummy) {
+ return (ListArrayAdapter<T>) LISTADAPTER;
+ }
+
+ /**
+ * Cast the static instance.
+ *
+ * @param dummy Dummy variable, for type inference
+ * @return Static instance
+ */
+ @SuppressWarnings("unchecked")
+ public static <T extends Number> NumberArrayAdapter<T, List<? extends T>> numberListAdapter(List<? extends T> dummy) {
+ return (NumberListArrayAdapter<T>) NUMBERLISTADAPTER;
+ }
+
+ /**
+ * Get the static instance.
+ *
+ * @param dummy Dummy object for type inference
+ * @return Static instance
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> IdentityArrayAdapter<T> identityAdapter(T dummy) {
+ return (IdentityArrayAdapter<T>) IDENTITYADAPTER;
+ }
+
+ /**
+ * Get the static instance.
+ *
+ * @param prototype Prototype value, for type inference
+ * @return Instance
+ */
+ @SuppressWarnings("unchecked")
+ public static <F> FeatureVectorAdapter<F> featureVectorAdapter(FeatureVector<?, F> prototype) {
+ return (FeatureVectorAdapter<F>) FEATUREVECTORADAPTER;
+ }
+
+ /**
+ * Get the static instance.
+ *
+ * @param prototype Prototype value, for type inference
+ * @return Instance
+ */
+ @SuppressWarnings("unchecked")
+ public static <N extends Number> NumberVectorAdapter<N> numberVectorAdapter(NumberVector<?, N> prototype) {
+ return (NumberVectorAdapter<N>) NUMBERVECTORADAPTER;
+ }
+
+ /**
+ * Get the adapter for double arrays.
+ *
+ * @return double array adapter
+ */
+ public static NumberArrayAdapter<Double, double[]> doubleArrayAdapter() {
+ return DOUBLEARRAYADAPTER;
+ }
+
+ /**
+ * Returns the index of the maximum of the given values. If no value is bigger
+ * than the first, the index of the first entry is returned.
+ *
+ * @param <A> array type
+ * @param array Array to inspect
+ * @param adapter API adapter class
+ * @return the index of the maximum in the given values
+ * @throws IndexOutOfBoundsException if the length of the array is 0.
+ */
+ public static <A> int getIndexOfMaximum(A array, NumberArrayAdapter<?, A> adapter) throws IndexOutOfBoundsException {
+ final int size = adapter.size(array);
+ int index = 0;
+ double max = adapter.getDouble(array, 0);
+ for(int i = 1; i < size; i++) {
+ double val = adapter.getDouble(array, i);
+ if(val > max) {
+ max = val;
+ index = i;
+ }
+ }
+ return index;
+ }
+
+ /**
+ * Returns the index of the maximum of the given values. If no value is bigger
+ * than the first, the index of the first entry is returned.
+ *
+ * @param array Array to inspect
+ * @return the index of the maximum in the given values
+ * @throws IndexOutOfBoundsException if the length of the array is 0.
+ */
+ public static int getIndexOfMaximum(double[] array) throws IndexOutOfBoundsException {
+ return getIndexOfMaximum(array, DOUBLEARRAYADAPTER);
+ }
+
+ /**
+ * Convert a numeric array-like to a <code>double[]</code>
+ *
+ * @param array Array-like
+ * @param adapter Adapter
+ * @return primitive double array
+ */
+ public static <A> double[] toPrimitiveDoubleArray(A array, NumberArrayAdapter<?, ? super A> adapter) {
+ double[] ret = new double[adapter.size(array)];
+ for(int i = 0; i < ret.length; i++) {
+ ret[i] = adapter.getDouble(array, i);
+ }
+ return ret;
+ }
+
+ /**
+ * Convert a list of numbers to <code>double[]</code>.
+ *
+ * @param array List of numbers
+ * @return double array
+ */
+ public static double[] toPrimitiveDoubleArray(List<? extends Number> array) {
+ return toPrimitiveDoubleArray(array, NUMBERLISTADAPTER);
+ }
+
+ /**
+ * Convert a number vector to <code>double[]</code>.
+ *
+ * @param obj Object to convert
+ * @return primitive double array
+ */
+ public static <N extends Number> double[] toPrimitiveDoubleArray(NumberVector<?, N> obj) {
+ return toPrimitiveDoubleArray(obj, numberVectorAdapter(obj));
+ }
+
+ /**
+ * Convert a numeric array-like to a <code>float[]</code>
+ *
+ * @param array Array-like
+ * @param adapter Adapter
+ * @return primitive float array
+ */
+ public static <A> float[] toPrimitiveFloatArray(A array, NumberArrayAdapter<?, ? super A> adapter) {
+ float[] ret = new float[adapter.size(array)];
+ for(int i = 0; i < ret.length; i++) {
+ ret[i] = adapter.getFloat(array, i);
+ }
+ return ret;
+ }
+
+ /**
+ * Convert a list of numbers to <code>float[]</code>.
+ *
+ * @param array List of numbers
+ * @return float array
+ */
+ public static float[] toPrimitiveFloatArray(List<? extends Number> array) {
+ return toPrimitiveFloatArray(array, NUMBERLISTADAPTER);
+ }
+
+ /**
+ * Convert a number vector to <code>float[]</code>.
+ *
+ * @param obj Object to convert
+ * @return primitive float array
+ */
+ public static <N extends Number> float[] toPrimitiveFloatArray(NumberVector<?, N> obj) {
+ return toPrimitiveFloatArray(obj, numberVectorAdapter(obj));
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..43419103
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/DoubleArrayAdapter.java
@@ -0,0 +1,81 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Use a double array as, well, double array in the ArrayAdapter API.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+class DoubleArrayAdapter implements NumberArrayAdapter<Double, double[]> {
+ /**
+ * Constructor.
+ *
+ * Use the static instance from {@link ArrayLikeUtil}!
+ */
+ protected DoubleArrayAdapter() {
+ super();
+ }
+
+ @Override
+ public int size(double[] array) {
+ return array.length;
+ }
+
+ @Override
+ public Double get(double[] array, int off) throws IndexOutOfBoundsException {
+ return 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];
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..a195360b
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ExtendedArray.java
@@ -0,0 +1,96 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You 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 extend an array with a single element virtually.
+ *
+ * @author Erich Schubert
+ *
+ * @param <T> Object type
+ */
+public class ExtendedArray<T> implements ArrayAdapter<T, ExtendedArray<T>> {
+ /**
+ * The array
+ */
+ final Object array;
+
+ /**
+ * The array adapter
+ */
+ final ArrayAdapter<T, Object> getter;
+
+ /**
+ * The extra element
+ */
+ final T extra;
+
+ /**
+ * Our size
+ */
+ final int size;
+
+ /**
+ * Constructor.
+ *
+ * @param array Original array
+ * @param getter Adapter for array
+ * @param extra Extra element
+ */
+ protected ExtendedArray(Object array, ArrayAdapter<T, Object> getter, T extra) {
+ super();
+ this.array = array;
+ this.getter = getter;
+ this.extra = extra;
+ this.size = getter.size(array) + 1;
+ }
+
+ @Override
+ public int size(ExtendedArray<T> array) {
+ assert (array == this);
+ return size;
+ }
+
+ @Override
+ public T get(ExtendedArray<T> array, int off) throws IndexOutOfBoundsException {
+ assert (array == this);
+ if(off == size - 1) {
+ return extra;
+ }
+ return getter.get(this.array, off);
+ }
+
+ /**
+ * Static wrapper that has a nicer generics signature.
+ *
+ * @param array Array to extend
+ * @param getter Getter for array
+ * @param extra Extra element
+ * @return Extended array
+ */
+ @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);
+ }
+} \ 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
new file mode 100644
index 00000000..19c2ec19
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/FeatureVectorAdapter.java
@@ -0,0 +1,56 @@
+package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike;
+
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Adapter to use a feature vector as an array of features.
+ *
+ * Use the static instance from {@link ArrayLikeUtil}!
+ *
+ * @author Erich Schubert
+ *
+ * @param <F> Feature type
+ */
+public class FeatureVectorAdapter<F> implements ArrayAdapter<F, FeatureVector<?, F>> {
+ /**
+ * Constructor.
+ *
+ * Use the static instance from {@link ArrayLikeUtil}!
+ */
+ protected FeatureVectorAdapter() {
+ super();
+ }
+
+ @Override
+ public int size(FeatureVector<?, F> array) {
+ return array.getDimensionality();
+ }
+
+ @Override
+ public F get(FeatureVector<?, F> array, int off) throws IndexOutOfBoundsException {
+ return array.getValue(off);
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..14d42dc5
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/FloatArrayAdapter.java
@@ -0,0 +1,82 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Use a double array as, well, double array in the ArrayAdapter API.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+class FloatArrayAdapter implements NumberArrayAdapter<Float, float[]> {
+ /**
+ * Constructor.
+ *
+ * Use the static instance from {@link ArrayLikeUtil}!
+ */
+ protected FloatArrayAdapter() {
+ super();
+ }
+
+ @Override
+ public int size(float[] array) {
+ return array.length;
+ }
+
+ @Override
+ public Float get(float[] array, int off) throws IndexOutOfBoundsException {
+ return array[off];
+ }
+
+ @Override
+ public double getDouble(float[] array, int off) throws IndexOutOfBoundsException {
+ return (double) array[off];
+ }
+
+ @Override
+ public float getFloat(float[] array, int off) throws IndexOutOfBoundsException {
+ return array[off];
+ }
+
+ @Override
+ public int getInteger(float[] array, int off) throws IndexOutOfBoundsException {
+ return (int) array[off];
+ }
+
+ @Override
+ public short getShort(float[] array, int off) throws IndexOutOfBoundsException {
+ return (short) array[off];
+ }
+
+ @Override
+ public long getLong(float[] array, int off) throws IndexOutOfBoundsException {
+ return (long) array[off];
+ }
+
+ @Override
+ public byte getByte(float[] array, int off) throws IndexOutOfBoundsException {
+ return (byte) array[off];
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..0c6e03dd
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/IdentityArrayAdapter.java
@@ -0,0 +1,55 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Single-item subset adapter
+ *
+ * Use the static instance from {@link ArrayLikeUtil}!
+ *
+ * @author Erich Schubert
+ *
+ * @param <T> Item type
+ */
+public class IdentityArrayAdapter<T> implements ArrayAdapter<T, T> {
+ /**
+ * Constructor.
+ *
+ * Use the static instance from {@link ArrayLikeUtil}!
+ */
+ protected IdentityArrayAdapter() {
+ super();
+ }
+
+ @Override
+ public int size(T array) {
+ return 1;
+ }
+
+ @Override
+ public T get(T array, int off) throws IndexOutOfBoundsException {
+ assert (off == 0) : "Invalid get()";
+ return array;
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..37875ab7
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/ListArrayAdapter.java
@@ -0,0 +1,55 @@
+package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike;
+
+import java.util.List;
+/*
+ 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/>.
+ */
+
+/**
+ * Static adapter class to use a {@link java.util.List} in an array API.
+ *
+ * Use the static instance from {@link ArrayLikeUtil}!
+ *
+ * @author Erich Schubert
+ *
+ * @param <T> Data object type.
+ */
+public class ListArrayAdapter<T> implements ArrayAdapter<T, List<? extends T>> {
+ /**
+ * Constructor.
+ *
+ * Use the static instance from {@link ArrayLikeUtil}!
+ */
+ protected ListArrayAdapter() {
+ super();
+ }
+
+ @Override
+ public int size(List<? extends T> array) {
+ return array.size();
+ }
+
+ @Override
+ public T get(List<? extends T> array, int off) throws IndexOutOfBoundsException {
+ return array.get(off);
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..1dc823b1
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/NumberArrayAdapter.java
@@ -0,0 +1,99 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Adapter for arrays of numbers, to avoid boxing.
+ *
+ * @author Erich Schubert
+ *
+ * @param <N> Number type
+ * @param <A> Array type
+ */
+public interface NumberArrayAdapter<N extends Number, A> extends ArrayAdapter<N, A> {
+ @Override
+ public int size(A array);
+
+ @Override
+ public N get(A array, int off) throws IndexOutOfBoundsException;
+
+ /**
+ * Get the off'th item from the array as double.
+ *
+ * @param array Array to get from
+ * @param off Offset
+ * @return Item at offset off
+ * @throws IndexOutOfBoundsException for an invalid index.
+ */
+ public double getDouble(A array, int off) throws IndexOutOfBoundsException;
+
+ /**
+ * Get the off'th item from the array as float.
+ *
+ * @param array Array to get from
+ * @param off Offset
+ * @return Item at offset off
+ * @throws IndexOutOfBoundsException for an invalid index.
+ */
+ public float getFloat(A array, int off) throws IndexOutOfBoundsException;
+
+ /**
+ * Get the off'th item from the array as integer.
+ *
+ * @param array Array to get from
+ * @param off Offset
+ * @return Item at offset off
+ * @throws IndexOutOfBoundsException for an invalid index.
+ */
+ public int getInteger(A array, int off) throws IndexOutOfBoundsException;
+
+ /**
+ * Get the off'th item from the array as short.
+ *
+ * @param array Array to get from
+ * @param off Offset
+ * @return Item at offset off
+ * @throws IndexOutOfBoundsException for an invalid index.
+ */
+ public short getShort(A array, int off) throws IndexOutOfBoundsException;
+
+ /**
+ * Get the off'th item from the array as long.
+ *
+ * @param array Array to get from
+ * @param off Offset
+ * @return Item at offset off
+ * @throws IndexOutOfBoundsException for an invalid index.
+ */
+ public long getLong(A array, int off) throws IndexOutOfBoundsException;
+
+ /**
+ * Get the off'th item from the array as byte.
+ *
+ * @param array Array to get from
+ * @param off Offset
+ * @return Item at offset off
+ * @throws IndexOutOfBoundsException for an invalid index.
+ */
+ public byte getByte(A array, int off) throws IndexOutOfBoundsException;
+} \ No newline at end of file
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
new file mode 100644
index 00000000..89a4e3d6
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/NumberListArrayAdapter.java
@@ -0,0 +1,87 @@
+package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike;
+
+import java.util.List;
+
+/*
+ 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/>.
+ */
+
+/**
+ * Static adapter class to use a {@link java.util.List} in an array of number
+ * API.
+ *
+ * Use the static instance from {@link ArrayLikeUtil}!
+ *
+ * @author Erich Schubert
+ *
+ * @param <T> Data object type.
+ */
+public class NumberListArrayAdapter<T extends Number> implements NumberArrayAdapter<T, List<? extends T>> {
+ /**
+ * Constructor.
+ *
+ * Use the static instance from {@link ArrayLikeUtil}!
+ */
+ protected NumberListArrayAdapter() {
+ super();
+ }
+
+ @Override
+ public int size(List<? extends T> array) {
+ return array.size();
+ }
+
+ @Override
+ public T get(List<? extends T> array, int off) throws IndexOutOfBoundsException {
+ return array.get(off);
+ }
+
+ @Override
+ public double getDouble(List<? extends T> array, int off) throws IndexOutOfBoundsException {
+ return array.get(off).doubleValue();
+ }
+
+ @Override
+ public float getFloat(List<? extends T> array, int off) throws IndexOutOfBoundsException {
+ return array.get(off).floatValue();
+ }
+
+ @Override
+ public int getInteger(List<? extends T> array, int off) throws IndexOutOfBoundsException {
+ return array.get(off).intValue();
+ }
+
+ @Override
+ public short getShort(List<? extends T> array, int off) throws IndexOutOfBoundsException {
+ return array.get(off).shortValue();
+ }
+
+ @Override
+ public long getLong(List<? extends T> array, int off) throws IndexOutOfBoundsException {
+ return array.get(off).longValue();
+ }
+
+ @Override
+ public byte getByte(List<? extends T> array, int off) throws IndexOutOfBoundsException {
+ return array.get(off).byteValue();
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..c75acd64
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/NumberVectorAdapter.java
@@ -0,0 +1,86 @@
+package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike;
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+
+/*
+ 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/>.
+ */
+
+/**
+ * Adapter to use a feature vector as an array of features.
+ *
+ * Use the static instance from {@link ArrayLikeUtil}!
+ *
+ * @author Erich Schubert
+ *
+ * @param <N> Number type
+ */
+public class NumberVectorAdapter<N extends Number> implements NumberArrayAdapter<N, NumberVector<?, N>> {
+ /**
+ * Constructor.
+ *
+ * Use the static instance from {@link ArrayLikeUtil}!
+ */
+ protected NumberVectorAdapter() {
+ super();
+ }
+
+ @Override
+ public int size(NumberVector<?, N> array) {
+ return array.getDimensionality();
+ }
+
+ @Override
+ public N get(NumberVector<?, N> array, int off) throws IndexOutOfBoundsException {
+ return array.getValue(off + 1);
+ }
+
+ @Override
+ public double getDouble(NumberVector<?, N> array, int off) throws IndexOutOfBoundsException {
+ return array.doubleValue(off + 1);
+ }
+
+ @Override
+ public float getFloat(NumberVector<?, N> array, int off) throws IndexOutOfBoundsException {
+ return array.floatValue(off + 1);
+ }
+
+ @Override
+ public int getInteger(NumberVector<?, N> array, int off) throws IndexOutOfBoundsException {
+ return array.intValue(off + 1);
+ }
+
+ @Override
+ public short getShort(NumberVector<?, N> array, int off) throws IndexOutOfBoundsException {
+ return array.shortValue(off + 1);
+ }
+
+ @Override
+ public long getLong(NumberVector<?, N> array, int off) throws IndexOutOfBoundsException {
+ return array.longValue(off + 1);
+ }
+
+ @Override
+ public byte getByte(NumberVector<?, N> array, int off) throws IndexOutOfBoundsException {
+ return array.byteValue(off + 1);
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..d7483e4d
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/SingleSubsetArrayAdapter.java
@@ -0,0 +1,67 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Single-item subset adapter
+ *
+ * @author Erich Schubert
+ *
+ * @param <T> Entry type
+ * @param <A> Array type
+ */
+public class SingleSubsetArrayAdapter<T, A> implements ArrayAdapter<T, A> {
+ /**
+ * Wrapped adapter
+ */
+ ArrayAdapter<T, ? super A> wrapped;
+
+ /**
+ * Offset to return
+ */
+ int off;
+
+ /**
+ * Constructor.
+ *
+ * @param wrapped Wrapped adapter
+ * @param off Offset
+ */
+ public SingleSubsetArrayAdapter(ArrayAdapter<T, ? super A> wrapped, int off) {
+ super();
+ this.wrapped = wrapped;
+ this.off = off;
+ }
+
+ @Override
+ public int size(A array) {
+ return 1;
+ }
+
+ @Override
+ public T get(A array, int off) throws IndexOutOfBoundsException {
+ assert (off == 0) : "Invalid get()";
+ return wrapped.get(array, off);
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..b2958358
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/SubsetArrayAdapter.java
@@ -0,0 +1,65 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Subset array adapter (allows reordering and projection)
+ *
+ * @author Erich Schubert
+ *
+ * @param <T> Entry type
+ * @param <A> Array type
+ */
+public class SubsetArrayAdapter<T, A> implements ArrayAdapter<T, A> {
+ /**
+ * Wrapped adapter
+ */
+ ArrayAdapter<T, ? super A> wrapped;
+
+ /**
+ * Offsets to return
+ */
+ int[] offs;
+
+ /**
+ * Constructor.
+ *
+ * @param wrapped Wrapped adapter
+ * @param offs Offsets
+ */
+ public SubsetArrayAdapter(ArrayAdapter<T, ? super A> wrapped, int[] offs) {
+ super();
+ this.wrapped = wrapped;
+ this.offs = offs;
+ }
+
+ @Override
+ public int size(A array) {
+ return offs.length;
+ }
+
+ @Override
+ public T get(A array, int off) throws IndexOutOfBoundsException {
+ return wrapped.get(array, offs[off]);
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..889c64e8
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/TDoubleListAdapter.java
@@ -0,0 +1,81 @@
+package de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike;
+
+import gnu.trove.list.TDoubleList;
+
+/*
+ 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/>.
+ */
+/**
+ * Adapter for using Trove TDoubleLists as array-like.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.uses TDoubleList
+ */
+public class TDoubleListAdapter implements NumberArrayAdapter<Double, TDoubleList> {
+ /**
+ * Constructor.
+ */
+ protected TDoubleListAdapter() {
+ super();
+ }
+
+ @Override
+ public int size(TDoubleList array) {
+ return array.size();
+ }
+
+ @Override
+ public Double get(TDoubleList array, int off) throws IndexOutOfBoundsException {
+ return array.get(off);
+ }
+
+ @Override
+ public double getDouble(TDoubleList array, int off) throws IndexOutOfBoundsException {
+ return array.get(off);
+ }
+
+ @Override
+ public float getFloat(TDoubleList array, int off) throws IndexOutOfBoundsException {
+ return (float) array.get(off);
+ }
+
+ @Override
+ public int getInteger(TDoubleList array, int off) throws IndexOutOfBoundsException {
+ return (int) array.get(off);
+ }
+
+ @Override
+ public short getShort(TDoubleList array, int off) throws IndexOutOfBoundsException {
+ return (short) array.get(off);
+ }
+
+ @Override
+ public long getLong(TDoubleList array, int off) throws IndexOutOfBoundsException {
+ return (long) array.get(off);
+ }
+
+ @Override
+ public byte getByte(TDoubleList array, int off) throws IndexOutOfBoundsException {
+ return (byte) array.get(off);
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..55627df4
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/arraylike/package-info.java
@@ -0,0 +1,26 @@
+/**
+ * <p>Common API for accessing objects that are "array-like", including lists, numerical vectors, database vectors and arrays.</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.datastructures.arraylike; \ No newline at end of file
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
new file mode 100644
index 00000000..976a4d0c
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/DoublePriorityObject.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.pairs.PairInterface;
+
+/**
+ * Object for a priority queue with integer priority. Can be used in the
+ * {@link de.lmu.ifi.dbs.elki.utilities.datastructures.heap.UpdatableHeap
+ * UpdatableHeap}, since hashcode and equality use the stored objects only, not
+ * the priority.
+ *
+ * @author Erich Schubert
+ *
+ * @param <O> Stored object type.
+ */
+public class DoublePriorityObject<O> implements PairInterface<Double, O>, Comparable<DoublePriorityObject<?>> {
+ /**
+ * Priority.
+ */
+ double priority;
+
+ /**
+ * Stored object. Private; since changing this will break an
+ * {@link de.lmu.ifi.dbs.elki.utilities.datastructures.heap.UpdatableHeap
+ * UpdatableHeap}s Hash Map!
+ */
+ private O object;
+
+ /**
+ * Constructor.
+ *
+ * @param priority Priority
+ * @param object Payload
+ */
+ public DoublePriorityObject(double priority, O object) {
+ super();
+ this.priority = priority;
+ this.object = object;
+ }
+
+ /**
+ * Get the priority.
+ *
+ * @return Priority
+ */
+ public double getPriority() {
+ return priority;
+ }
+
+ /**
+ * Get the stored object payload
+ *
+ * @return object data
+ */
+ public O getObject() {
+ return object;
+ }
+
+ @Override
+ public Double getFirst() {
+ return priority;
+ }
+
+ @Override
+ public O getSecond() {
+ return object;
+ }
+
+ @Override
+ public int hashCode() {
+ return ((object == null) ? 0 : object.hashCode());
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if(this == obj) {
+ return true;
+ }
+ if(obj == null) {
+ return false;
+ }
+ if(!(obj instanceof DoublePriorityObject)) {
+ return false;
+ }
+ DoublePriorityObject<?> other = (DoublePriorityObject<?>) obj;
+ if(object == null) {
+ return (other.object == null);
+ }
+ else {
+ return object.equals(other.object);
+ }
+ }
+
+ @Override
+ public int compareTo(DoublePriorityObject<?> o) {
+ return Double.compare(o.priority, this.priority);
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ buf.append(priority).append(":").append(object.toString());
+ return buf.toString();
+ }
+} \ No newline at end of file
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 307e3ecc..307a0807 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,14 +27,22 @@ import java.io.Serializable;
import java.util.AbstractQueue;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
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 {@link java.util.PriorityQueue},
- * but here we can override methods to obtain e.g. a {@link TopBoundedHeap}
+ * Basic in-memory heap structure. Closely related to a
+ * {@link java.util.PriorityQueue}, but here we can override methods to obtain
+ * e.g. a {@link TopBoundedHeap}
+ *
+ * Additionally, 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
*
@@ -49,11 +57,8 @@ public class Heap<E> extends AbstractQueue<E> implements Serializable {
/**
* Heap storage
- *
- * Note: keep private; all write access should be done through
- * {@link #putInQueue} for subclasses to track!
*/
- private Object[] queue;
+ protected transient Object[] queue;
/**
* Current number of objects
@@ -61,9 +66,14 @@ public class Heap<E> extends AbstractQueue<E> implements Serializable {
protected int size = 0;
/**
+ * Indicate up to where the heap is valid
+ */
+ protected int validSize = 0;
+
+ /**
* The comparator or {@code null}
*/
- private final Comparator<? super E> comparator;
+ protected final Comparator<Object> comparator;
/**
* (Structural) modification counter. Used to invalidate iterators.
@@ -106,230 +116,288 @@ public class Heap<E> extends AbstractQueue<E> implements Serializable {
* @param size initial capacity
* @param comparator Comparator
*/
+ @SuppressWarnings("unchecked")
public Heap(int size, Comparator<? super E> comparator) {
super();
this.size = 0;
this.queue = new Object[size];
- this.comparator = comparator;
+ this.comparator = (Comparator<Object>) comparator;
+ }
+
+ @Override
+ public boolean add(E e) {
+ // Never full - overriding probably slightly faster
+ return offer(e);
}
@Override
- public synchronized boolean offer(E e) {
+ public boolean offer(E e) {
// resize when needed
- considerResize(size + 1);
- final int parent = parent(size);
- // append element
- modCount++;
- putInQueue(size, e);
- this.size = size + 1;
- heapifyUp(parent);
+ if(size + 1 > queue.length) {
+ resize(size + 1);
+ }
+ // final int pos = size;
+ this.queue[size] = e;
+ this.size += 1;
+ heapifyUp(size - 1, e);
+ validSize += 1;
// We have changed - return true according to {@link Collection#put}
+ modCount++;
return true;
}
@Override
- public synchronized E peek() {
+ public E peek() {
if(size == 0) {
return null;
}
+ ensureValid();
return castQueueElement(0);
}
@Override
public E poll() {
+ ensureValid();
return removeAt(0);
}
/**
+ * Repair the heap
+ */
+ 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.
*/
- protected synchronized E removeAt(int pos) {
+ protected E removeAt(int pos) {
if(pos < 0 || pos >= size) {
return null;
}
+ final E ret = castQueueElement(pos);
+ // 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;
+ }
modCount++;
- E ret = castQueueElement(0);
- // remove!
- putInQueue(pos, queue[size - 1]);
- size = size - 1;
- // avoid dangling references!
- putInQueue(size, null);
- heapifyDown(pos);
return ret;
}
/**
- * Compute parent index in heap array.
- *
- * @param pos Element index
- * @return Parent index
- */
- private int parent(int pos) {
- return (pos - 1) / 2;
- }
-
- /**
- * Compute left child index in heap array.
+ * Execute a "Heapify Upwards" aka "SiftUp". Used in insertions.
*
- * @param pos Element index
- * @return left child index
+ * @param pos insertion position
+ * @param elem Element to insert
*/
- private int leftChild(int pos) {
- return 2 * pos + 1;
+ protected void heapifyUp(int pos, E elem) {
+ assert (pos < size && pos >= 0);
+ if(comparator != null) {
+ heapifyUpComparator(pos, elem);
+ }
+ else {
+ heapifyUpComparable(pos, elem);
+ }
}
/**
- * Compute right child index in heap array.
+ * Execute a "Heapify Upwards" aka "SiftUp". Used in insertions.
*
- * @param pos Element index
- * @return right child index
+ * @param pos insertion position
+ * @param elem Element to insert
*/
- private int rightChild(int pos) {
- return 2 * pos + 2;
+ @SuppressWarnings("unchecked")
+ protected void heapifyUpComparable(int pos, Object elem) {
+ final Comparable<Object> cur = (Comparable<Object>) elem; // queue[pos];
+ while(pos > 0) {
+ final int parent = (pos - 1) >>> 1;
+ Object par = queue[parent];
+
+ if(cur.compareTo(par) >= 0) {
+ break;
+ }
+ queue[pos] = par;
+ pos = parent;
+ }
+ queue[pos] = cur;
}
/**
* Execute a "Heapify Upwards" aka "SiftUp". Used in insertions.
*
* @param pos insertion position
+ * @param cur Element to insert
*/
- protected void heapifyUp(int pos) {
- if(pos < 0 || pos >= size) {
- return;
- }
- // precondition: both child trees are already sorted.
- final int parent = parent(pos);
- final int lchild = leftChild(pos);
- final int rchild = rightChild(pos);
-
- int min = pos;
- if(lchild < size) {
- if(compare(min, lchild) > 0) {
- min = lchild;
- }
- }
- if(rchild < size) {
- if(compare(min, rchild) > 0) {
- min = rchild;
+ protected void heapifyUpComparator(int pos, Object cur) {
+ while(pos > 0) {
+ final int parent = (pos - 1) >>> 1;
+ Object par = queue[parent];
+
+ if(comparator.compare(cur, par) >= 0) {
+ break;
}
+ queue[pos] = par;
+ pos = parent;
}
- if(min != pos) {
- swap(pos, min);
- heapifyUp(parent);
- }
- }
-
- /**
- * Start a heapify up at the parent of this node, since we've changed a child
- *
- * @param pos Position to start the modification.
- */
- protected void heapifyUpParent(int pos) {
- heapifyUp(parent(pos));
+ queue[pos] = cur;
}
/**
* Execute a "Heapify Downwards" aka "SiftDown". Used in deletions.
*
* @param pos re-insertion position
+ * @param reinsert Object to reinsert
+ * @return true when the order was changed
*/
- protected void heapifyDown(int pos) {
- if(pos < 0 || pos >= size) {
- return;
- }
- final int lchild = leftChild(pos);
- final int rchild = rightChild(pos);
-
- int min = pos;
- if(lchild < size) {
- if(compare(min, lchild) > 0) {
- min = lchild;
- }
- }
- if(rchild < size) {
- if(compare(min, rchild) > 0) {
- min = rchild;
- }
+ protected boolean heapifyDown(int pos, Object reinsert) {
+ assert (pos >= 0);
+ if(comparator != null) {
+ return heapifyDownComparator(pos, reinsert);
}
- if(min != pos) {
- // swap with minimal element
- swap(pos, min);
- // recurse down
- heapifyDown(min);
+ else {
+ return heapifyDownComparable(pos, reinsert);
}
}
/**
- * Put an element into the queue at a given position. This allows subclasses
- * to index the queue.
- *
- * @param index Index
- * @param e Element
- */
- protected void putInQueue(int index, Object e) {
- queue[index] = e;
- }
-
- /**
- * Swap two elements in the heap.
+ * Execute a "Heapify Downwards" aka "SiftDown". Used in deletions.
*
- * @param a Element
- * @param b Element
+ * @param ipos re-insertion position
+ * @return true when the order was changed
*/
- protected void swap(int a, int b) {
- Object oa = queue[a];
- Object ob = queue[b];
- putInQueue(a, ob);
- putInQueue(b, oa);
- modCount++;
- }
-
@SuppressWarnings("unchecked")
- protected int compare(int pos1, int pos2) {
- if(comparator != null) {
- return comparator.compare(castQueueElement(pos1), castQueueElement(pos2));
- }
- try {
- Comparable<E> c = (Comparable<E>) castQueueElement(pos1);
- return c.compareTo(castQueueElement(pos2));
- }
- catch(ClassCastException e) {
- throw e;
- }
- }
+ protected boolean heapifyDownComparable(final int ipos, Object reinsert) {
+ Comparable<Object> cur = (Comparable<Object>) reinsert;
+ int pos = ipos;
+ final int half = size >>> 1;
+ 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) {
+ Object right = queue[rchild];
+ if(((Comparable<Object>) child).compareTo(right) > 0) {
+ cpos = rchild;
+ child = right;
+ }
+ }
- @SuppressWarnings("unchecked")
- protected int compareExternal(E o1, int pos2) {
- if(comparator != null) {
- return comparator.compare(o1, castQueueElement(pos2));
- }
- try {
- Comparable<E> c = (Comparable<E>) o1;
- return c.compareTo(castQueueElement(pos2));
- }
- catch(ClassCastException e) {
- throw e;
+ if(cur.compareTo(child) <= 0) {
+ break;
+ }
+ queue[pos] = child;
+ pos = cpos;
}
+ queue[pos] = cur;
+ return (pos == ipos);
}
- @SuppressWarnings("unchecked")
- protected int compareExternalExternal(E o1, E o2) {
- if(comparator != null) {
- return comparator.compare(o1, o2);
- }
- try {
- Comparable<E> c = (Comparable<E>) o1;
- return c.compareTo(o2);
- }
- catch(ClassCastException e) {
- throw e;
+ /**
+ * Execute a "Heapify Downwards" aka "SiftDown". Used in deletions.
+ *
+ * @param ipos re-insertion position
+ * @return true when the order was changed
+ */
+ protected boolean heapifyDownComparator(final int ipos, Object cur) {
+ int pos = ipos;
+ final int half = size >>> 1;
+ 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) {
+ min = lchild;
+ best = left;
+ }
+ final int rchild = lchild + 1;
+ if(rchild < size) {
+ Object right = queue[rchild];
+ if(comparator.compare(best, right) > 0) {
+ min = rchild;
+ best = right;
+ }
+ }
+ if(min == pos) {
+ break;
+ }
+ queue[pos] = best;
+ pos = min;
}
+ queue[pos] = cur;
+ return (pos == ipos);
}
@SuppressWarnings("unchecked")
- protected E castQueueElement(int n) {
+ protected final E castQueueElement(int n) {
return (E) queue[n];
}
@@ -343,46 +411,28 @@ public class Heap<E> extends AbstractQueue<E> implements Serializable {
*
* @param requiredSize required capacity
*/
- private void considerResize(int requiredSize) {
- if(requiredSize > queue.length) {
- // Double until 64, then increase by 50% each time.
- int newCapacity = ((queue.length < 64) ? ((queue.length + 1) * 2) : ((queue.length / 2) * 3));
- // overflow?
- if(newCapacity < 0) {
- newCapacity = Integer.MAX_VALUE;
- }
- if(requiredSize > newCapacity) {
- newCapacity = requiredSize;
- }
- grow(newCapacity);
- }
- }
-
- /**
- * Execute the actual resize operation.
- *
- * @param newsize New size
- */
- private void grow(int newsize) {
- // check for overflows
- if(newsize < 0) {
+ protected final void resize(int requiredSize) {
+ // Double until 64, then increase by 50% each time.
+ int newCapacity = ((queue.length < 64) ? ((queue.length + 1) * 2) : ((queue.length / 2) * 3));
+ // overflow?
+ if(newCapacity < 0) {
throw new OutOfMemoryError();
}
- if(newsize == queue.length) {
- return;
+ if(requiredSize > newCapacity) {
+ newCapacity = requiredSize;
}
- modCount++;
- queue = Arrays.copyOf(queue, newsize);
+ queue = Arrays.copyOf(queue, newCapacity);
}
@Override
public void clear() {
- modCount++;
// clean up references in the array for memory management
for(int i = 0; i < size; i++) {
queue[i] = null;
}
this.size = 0;
+ this.validSize = -1;
+ modCount++;
}
@Override
@@ -398,13 +448,26 @@ public class Heap<E> extends AbstractQueue<E> implements Serializable {
return false;
}
- // TODO: bulk add implementation of addAll?
-
@Override
public Iterator<E> iterator() {
return new Itr();
}
+ @Override
+ public boolean addAll(Collection<? extends E> c) {
+ final int addsize = c.size();
+ if(addsize <= 0) {
+ return false;
+ }
+ if(size + addsize > queue.length) {
+ resize(size + addsize);
+ }
+ for(E elem : c) {
+ add(elem);
+ }
+ return true;
+ }
+
/**
* Iterator over queue elements. No particular order (i.e. heap order!)
*
@@ -453,10 +516,10 @@ public class Heap<E> extends AbstractQueue<E> implements Serializable {
expectedModCount = modCount;
}
}
-
+
/**
- * Return the heap as a sorted array list, by repeated polling.
- * This will empty the heap!
+ * Return the heap as a sorted array list, by repeated polling. This will
+ * empty the heap!
*
* @return new array list
*/
@@ -467,4 +530,34 @@ public class Heap<E> extends AbstractQueue<E> implements Serializable {
}
return ret;
}
+
+ /**
+ * Test whether the heap is still valid.
+ *
+ * Debug method.
+ *
+ * @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;
+ @SuppressWarnings("unchecked")
+ Comparable<Object> po = (Comparable<Object>) queue[parent];
+ if(po.compareTo(queue[i]) > 0) {
+ return "@" + parent + ": " + queue[parent] + " < @" + i + ": " + queue[i];
+ }
+ }
+ }
+ else {
+ for(int i = 1; i < size; i++) {
+ final int parent = (i - 1) >>> 1;
+ if(comparator.compare(queue[parent], queue[i]) > 0) {
+ return "@" + parent + ": " + queue[parent] + " < @" + i + ": " + queue[i];
+ }
+ }
+ }
+ return null;
+ }
} \ No newline at end of file
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 0bfa8a90..9dd941ec 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,8 +27,9 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.PairInterface;
/**
* Object for a priority queue with integer priority. Can be used in the
- * {@link de.lmu.ifi.dbs.elki.utilities.datastructures.heap.UpdatableHeap UpdatableHeap}, since hashcode and equality use the stored objects
- * only, not the priority.
+ * {@link de.lmu.ifi.dbs.elki.utilities.datastructures.heap.UpdatableHeap
+ * UpdatableHeap}, since hashcode and equality use the stored objects only, not
+ * the priority.
*
* @author Erich Schubert
*
@@ -42,13 +43,14 @@ public class IntegerPriorityObject<O> implements PairInterface<Integer, O>, Comp
/**
* Stored object. Private; since changing this will break an
- * {@link de.lmu.ifi.dbs.elki.utilities.datastructures.heap.UpdatableHeap UpdatableHeap}s Hash Map!
+ * {@link de.lmu.ifi.dbs.elki.utilities.datastructures.heap.UpdatableHeap
+ * UpdatableHeap}s Hash Map!
*/
private O object;
/**
* Constructor.
- *
+ *
* @param priority Priority
* @param object Payload
*/
@@ -115,4 +117,11 @@ public class IntegerPriorityObject<O> implements PairInterface<Integer, O>, Comp
public int compareTo(IntegerPriorityObject<?> o) {
return o.priority - this.priority;
}
+
+ @Override
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ buf.append(priority).append(":").append(object.toString());
+ return buf.toString();
+ }
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/KNNHeap.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/KNNHeap.java
index 9f2d29f3..a1706c84 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/KNNHeap.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/KNNHeap.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -87,7 +87,7 @@ public class KNNHeap<D extends Distance<D>> extends TiedTopBoundedHeap<DistanceR
* @return KNNList with the heaps contents.
*/
public KNNList<D> toKNNList() {
- return new KNNList<D>(this, maxdist);
+ return new KNNList<D>(this);
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/KNNList.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/KNNList.java
index 02a5264c..b19612f2 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/KNNList.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/KNNList.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,15 +23,15 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.AbstractList;
-import java.util.ArrayList;
-import java.util.Collection;
+import java.util.AbstractCollection;
import java.util.Iterator;
import java.util.List;
+import java.util.Queue;
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.query.DistanceResultPair;
+import de.lmu.ifi.dbs.elki.database.query.knn.KNNResult;
+import de.lmu.ifi.dbs.elki.database.query.knn.KNNUtil;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
/**
@@ -39,49 +39,60 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
*
* @author Erich Schubert
*
- * @apiviz.composedOf DBIDItr
- * @apiviz.composedOf DBIDView
- * @apiviz.composedOf DistanceItr
- * @apiviz.composedOf DistanceView
- *
- * @param <D>
+ * @param <D> Distance type
*/
-public class KNNList<D extends Distance<D>> extends ArrayList<DistanceResultPair<D>> {
- /**
- * Serial ID
- */
- private static final long serialVersionUID = 1L;
-
+public class KNNList<D extends Distance<D>> extends AbstractCollection<DistanceResultPair<D>> implements KNNResult<D> {
/**
* The value of k this was materialized for.
*/
private final int k;
/**
- * The maximum distance to return if size() &lt; k
+ * The actual data array.
*/
- private final D maxdist;
+ private final Object[] data;
/**
- * Constructor, to be called from KNNHeap only!
+ * Constructor, to be called from KNNHeap only. Use {@link KNNHeap#toKNNList}
+ * instead!
*
- * @param heap Calling heap.
- * @param maxdist infinite distance to return.
+ * @param heap Calling heap
*/
- protected KNNList(KNNHeap<D> heap, D maxdist) {
- super(heap.size());
+ protected KNNList(KNNHeap<D> heap) {
+ super();
+ this.data = new Object[heap.size()];
this.k = heap.getK();
- this.maxdist = maxdist;
+ assert(heap.size() >= this.k) : "Heap doesn't contain enough objects!";
// Get sorted data from heap; but in reverse.
- int i;
- for(i = 0; i < heap.size(); i++) {
- super.add(null);
+ int i = heap.size();
+ while(!heap.isEmpty()) {
+ i--;
+ assert (i >= 0);
+ data[i] = heap.poll();
}
+ assert (data.length == 0 || data[0] != null);
+ assert (heap.size() == 0);
+ }
+
+ /**
+ * Constructor. With a KNNHeap, use {@link KNNHeap#toKNNList} instead!
+ *
+ * @param heap Calling heap
+ * @param k K value
+ */
+ public KNNList(Queue<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()) {
i--;
assert (i >= 0);
- super.set(i, heap.poll());
+ data[i] = heap.poll();
}
+ assert (data.length == 0 || data[0] != null);
assert (heap.size() == 0);
}
@@ -99,30 +110,19 @@ public class KNNList<D extends Distance<D>> extends ArrayList<DistanceResultPair
*
* @return Maximum distance
*/
+ @Override
public D getKNNDistance() {
- if(size() < getK()) {
- return maxdist;
- }
return get(getK() - 1).getDistance();
}
/**
- * Get maximum distance in list
- */
- public D getMaximumDistance() {
- if(isEmpty()) {
- return maxdist;
- }
- return get(size() - 1).getDistance();
- }
-
- /**
* View as ArrayDBIDs
*
* @return Static DBIDs
*/
+ @Override
public ArrayDBIDs asDBIDs() {
- return new DBIDView(this);
+ return KNNUtil.asDBIDs(this);
}
/**
@@ -130,221 +130,73 @@ public class KNNList<D extends Distance<D>> extends ArrayList<DistanceResultPair
*
* @return List of distances view
*/
+ @Override
public List<D> asDistanceList() {
- return new DistanceView<D>(this);
+ return KNNUtil.asDistanceList(this);
}
/* Make the list unmodifiable! */
@Override
- public boolean add(DistanceResultPair<D> e) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void add(int index, DistanceResultPair<D> element) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean addAll(Collection<? extends DistanceResultPair<D>> c) {
- throw new UnsupportedOperationException();
- }
-
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ buf.append("kNNList[");
+ Iterator<DistanceResultPair<D>> iter = this.iterator();
+ while(iter.hasNext()) {
+ DistanceResultPair<D> pair = iter.next();
+ buf.append(pair.getDistance()).append(":").append(pair.getDBID());
+ if(iter.hasNext()) {
+ buf.append(",");
+ }
+ }
+ buf.append("]");
+ return buf.toString();
+ }
+
+ @SuppressWarnings("unchecked")
@Override
- public boolean addAll(int index, Collection<? extends DistanceResultPair<D>> c) {
- throw new UnsupportedOperationException();
+ public DistanceResultPair<D> get(int index) {
+ return (DistanceResultPair<D>) data[index];
}
@Override
- public void clear() {
- throw new UnsupportedOperationException();
+ public Iterator<DistanceResultPair<D>> iterator() {
+ return new Itr();
}
@Override
- public DistanceResultPair<D> remove(int index) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean remove(Object o) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public DistanceResultPair<D> set(int index, DistanceResultPair<D> element) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void trimToSize() {
- throw new UnsupportedOperationException();
+ public int size() {
+ return data.length;
}
/**
- * Proxy iterator for accessing DBIDs.
+ * Iterator
*
* @author Erich Schubert
- */
- protected static class DBIDItr implements Iterator<DBID> {
- /**
- * The real iterator.
- */
- Iterator<? extends DistanceResultPair<?>> itr;
-
- /**
- * Constructor.
- */
- protected DBIDItr(Iterator<? extends DistanceResultPair<?>> itr) {
- super();
- this.itr = itr;
- }
-
- @Override
- public boolean hasNext() {
- return itr.hasNext();
- }
-
- @Override
- public DBID next() {
- return itr.next().getDBID();
- }
-
- @Override
- public void remove() {
- itr.remove();
- }
- }
-
- /**
- * A view on the DBIDs of the result
*
- * @author Erich Schubert
+ * @apiviz.exclude
*/
- protected static class DBIDView extends AbstractList<DBID> implements ArrayDBIDs {
+ private class Itr implements Iterator<DistanceResultPair<D>> {
/**
- * The true list.
+ * Cursor position
*/
- final List<? extends DistanceResultPair<?>> parent;
-
- /**
- * Constructor.
- *
- * @param parent Owner
- */
- public DBIDView(List<? extends DistanceResultPair<?>> parent) {
- super();
- this.parent = parent;
- }
-
- @Override
- public DBID get(int i) {
- return parent.get(i).getDBID();
- }
-
- @Override
- public Collection<DBID> asCollection() {
- return this;
- }
-
- @Override
- public Iterator<DBID> iterator() {
- return new DBIDItr(parent.iterator());
- }
-
- @Override
- public int size() {
- return parent.size();
- }
- }
-
- /**
- * Proxy iterator for accessing DBIDs.
- *
- * @author Erich Schubert
- */
- protected static class DistanceItr<D extends Distance<D>> implements Iterator<D> {
- /**
- * The real iterator.
- */
- Iterator<? extends DistanceResultPair<D>> itr;
-
- /**
- * Constructor.
- */
- protected DistanceItr(Iterator<? extends DistanceResultPair<D>> itr) {
- super();
- this.itr = itr;
- }
+ private int pos = -1;
@Override
public boolean hasNext() {
- return itr.hasNext();
+ return pos + 1 < data.length;
}
+ @SuppressWarnings("unchecked")
@Override
- public D next() {
- return itr.next().getDistance();
+ public DistanceResultPair<D> next() {
+ pos++;
+ return (DistanceResultPair<D>) data[pos];
}
@Override
public void remove() {
- itr.remove();
- }
- }
-
- /**
- * A view on the Distances of the result
- *
- * @author Erich Schubert
- */
- protected static class DistanceView<D extends Distance<D>> extends AbstractList<D> implements List<D> {
- /**
- * The true list.
- */
- final List<? extends DistanceResultPair<D>> parent;
-
- /**
- * Constructor.
- *
- * @param parent Owner
- */
- public DistanceView(List<? extends DistanceResultPair<D>> parent) {
- super();
- this.parent = parent;
+ throw new UnsupportedOperationException("kNN results are unmodifiable.");
}
-
- @Override
- public D get(int i) {
- return parent.get(i).getDistance();
- }
-
- @Override
- public Iterator<D> iterator() {
- return new DistanceItr<D>(parent.iterator());
- }
-
- @Override
- public int size() {
- return parent.size();
- }
- }
-
- /**
- * View as ArrayDBIDs
- *
- * @return Static DBIDs
- */
- public static ArrayDBIDs asDBIDs(List<? extends DistanceResultPair<?>> list) {
- return new DBIDView(list);
- }
-
- /**
- * View as list of distances
- *
- * @return List of distances view
- */
- public static <D extends Distance<D>> List<D> asDistanceList(List<? extends DistanceResultPair<D>> list) {
- return new DistanceView<D>(list);
}
} \ No newline at end of file
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 ba4307b1..c0ce3acf 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) 2011
+ Copyright (C) 2012
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.utilities.datastructures.heap;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
-import java.util.LinkedList;
+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 elements.
+ * A size-limited heap similar to {@link TopBoundedHeap}, discarding elements
+ * with the highest value. However, this variation keeps a list of tied
+ * elements.
*
* @author Erich Schubert
*
@@ -46,7 +48,7 @@ public class TiedTopBoundedHeap<E> extends TopBoundedHeap<E> {
/**
* List to keep ties in.
*/
- private LinkedList<E> ties = new LinkedList<E>();
+ private List<E> ties = new ArrayList<E>();
/**
* Constructor with comparator.
@@ -90,31 +92,44 @@ public class TiedTopBoundedHeap<E> extends TopBoundedHeap<E> {
}
@Override
- public synchronized E peek() {
- if (ties.isEmpty()) {
+ public E peek() {
+ if(ties.isEmpty()) {
return super.peek();
- } else {
- return ties.peek() ;
+ }
+ else {
+ return ties.get(ties.size() - 1);
}
}
@Override
public E poll() {
- if (ties.isEmpty()) {
+ if(ties.isEmpty()) {
return super.poll();
- } else {
- return ties.poll();
+ }
+ else {
+ return ties.remove(ties.size() - 1);
}
}
@Override
protected void handleOverflow(E e) {
- if (super.compareExternal(e, 0) == 0) {
- if (!ties.isEmpty() && super.compareExternalExternal(e, ties.peek()) < 0) {
- ties.clear();
+ boolean tied = false;
+ if(comparator == null) {
+ @SuppressWarnings("unchecked")
+ Comparable<Object> c = (Comparable<Object>) e;
+ if(c.compareTo(queue[0]) == 0) {
+ tied = true;
+ }
+ }
+ else {
+ if(comparator.compare(e, queue[0]) == 0) {
+ tied = true;
}
+ }
+ if(tied) {
ties.add(e);
- } else {
+ }
+ else {
// Also remove old ties.
ties.clear();
}
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
new file mode 100644
index 00000000..4fbc852e
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TiedTopBoundedUpdatableHeap.java
@@ -0,0 +1,175 @@
+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.ArrayList;
+import java.util.Comparator;
+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
+ * with the highest value. However, this variation keeps a list of tied
+ * elements.
+ *
+ * @author Erich Schubert
+ *
+ * @param <E> Object type
+ */
+public class TiedTopBoundedUpdatableHeap<E> extends TopBoundedUpdatableHeap<E> {
+ /**
+ * Serial version
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * List to keep ties in.
+ */
+ private List<E> ties = new ArrayList<E>();
+
+ /**
+ * Constructor with comparator.
+ *
+ * @param maxsize Maximum size of heap (unless tied)
+ * @param comparator Comparator
+ */
+ public TiedTopBoundedUpdatableHeap(int maxsize, Comparator<? super E> comparator) {
+ super(maxsize, comparator);
+ }
+
+ /**
+ * Constructor for Comparable objects.
+ *
+ * @param maxsize Maximum size of heap (unless tied)
+ */
+ public TiedTopBoundedUpdatableHeap(int maxsize) {
+ this(maxsize, null);
+ }
+
+ @Override
+ public int size() {
+ return super.size() + ties.size();
+ }
+
+ @Override
+ public void clear() {
+ super.clear();
+ ties.clear();
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ return ties.contains(o) || super.contains(o);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Iterator<E> iterator() {
+ return new MergedIterator<E>(ties.iterator(), super.iterator());
+ }
+
+ @Override
+ public boolean offerAt(int pos, E e) {
+ if(pos == IN_TIES) {
+ for(Iterator<E> i = ties.iterator(); i.hasNext();) {
+ E e2 = i.next();
+ if(e.equals(e2)) {
+ if(compare(e, e2) <= 0) {
+ i.remove();
+ index.remove(e2);
+ }
+ // while we did not change, this still was "successful".
+ return true;
+ }
+ }
+ throw new AbortException("Heap corrupt - should not be reached");
+ }
+ // Updated object will be worse than the current ties
+ if(pos >= 0 && ties.size() > 0 && compare(e, ties.get(0)) < 0) {
+ removeAt(pos);
+ index.remove(e);
+ // assert(checkHeap() == null) : "removeObject broke heap: "+ checkHeap();
+ // Move one object back from ties
+ final E e2 = ties.remove(ties.size() - 1);
+ // index.remove(e2);
+ super.offerAt(NO_VALUE, e2);
+ return true;
+ }
+ return super.offerAt(pos, e);
+ }
+
+ @Override
+ public E peek() {
+ if(ties.isEmpty()) {
+ return super.peek();
+ }
+ else {
+ return ties.get(ties.size() - 1);
+ }
+ }
+
+ @Override
+ public E poll() {
+ if(ties.isEmpty()) {
+ return super.poll();
+ }
+ else {
+ E e = ties.remove(ties.size() - 1);
+ index.remove(e);
+ return e;
+ }
+ }
+
+ @Override
+ protected void handleOverflow(E e) {
+ boolean tied = false;
+ if(comparator == null) {
+ @SuppressWarnings("unchecked")
+ Comparable<Object> c = (Comparable<Object>) e;
+ if(c.compareTo(queue[0]) == 0) {
+ tied = true;
+ }
+ }
+ else {
+ if(comparator.compare(e, queue[0]) == 0) {
+ tied = true;
+ }
+ }
+ if(tied) {
+ ties.add(e);
+ index.put(e, IN_TIES);
+ }
+ else {
+ index.remove(e);
+ // Also remove old ties.
+ for(E e2 : ties) {
+ index.remove(e2);
+ }
+ ties.clear();
+ }
+ }
+} \ No newline at end of file
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 cd7280a5..5b61e6f3 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,19 +26,20 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
import java.util.Comparator;
/**
- * Heap class that is bounded in size from the top.
- * It will keep the bottom {@code k} Elements only.
+ * Heap class that is bounded in size from the top. It will keep the bottom
+ * {@code k} Elements only.
*
* @author Erich Schubert
- *
- * @param <E> Element type. Should be {@link Comparable} or a {@link Comparator} needs to be given.
+ *
+ * @param <E> Element type. Should be {@link Comparable} or a {@link Comparator}
+ * needs to be given.
*/
public class TopBoundedHeap<E> extends Heap<E> {
/**
* Serial version
*/
private static final long serialVersionUID = 1L;
-
+
/**
* Maximum size
*/
@@ -62,32 +63,40 @@ public class TopBoundedHeap<E> extends Heap<E> {
public TopBoundedHeap(int maxsize, Comparator<? super E> comparator) {
super(maxsize + 1, comparator);
this.maxsize = maxsize;
- assert(maxsize > 0);
+ assert (maxsize > 0);
}
@Override
public boolean offer(E e) {
- // NOTE: we deliberately call super methods here!
- // to have the handleOverflow method called consistently.
-
// don't add if we hit maxsize and are worse
- if (super.size() >= maxsize) {
- if (super.compareExternal(e, 0) < 0) {
- // while we did not change, this still was "successful".
- return true;
+ if(super.size() >= maxsize) {
+ ensureValid();
+ if(comparator == null) {
+ @SuppressWarnings("unchecked")
+ Comparable<Object> c = (Comparable<Object>) e;
+ if(c.compareTo(queue[0]) < 0) {
+ // while we did not change, this still was "successful".
+ return true;
+ }
+ }
+ else {
+ if(comparator.compare(e, queue[0]) < 0) {
+ // while we did not change, this still was "successful".
+ return true;
+ }
}
}
boolean result = super.offer(e);
// purge unneeded entry(s)
- while (super.size() > maxsize) {
+ while(super.size() > maxsize) {
handleOverflow(super.poll());
}
return result;
}
/**
- * Handle an overflow in the structure.
- * This function can be overridden to get overflow treatment.
+ * Handle an overflow in the structure. This function can be overridden to get
+ * overflow treatment.
*
* @param e Overflowing element.
*/
@@ -101,4 +110,4 @@ public class TopBoundedHeap<E> extends Heap<E> {
public int getMaxSize() {
return maxsize;
}
-}
+} \ No newline at end of file
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
new file mode 100644
index 00000000..2b22eba2
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TopBoundedUpdatableHeap.java
@@ -0,0 +1,122 @@
+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.Comparator;
+
+/**
+ * Heap class that is bounded in size from the top. It will keep the bottom
+ * {@code k} Elements only.
+ *
+ * @author Erich Schubert
+ *
+ * @param <E> Element type. Should be {@link Comparable} or a {@link Comparator}
+ * needs to be given.
+ */
+public class TopBoundedUpdatableHeap<E> extends UpdatableHeap<E> {
+ /**
+ * Serial version
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Maximum size
+ */
+ protected int maxsize;
+
+ /**
+ * Constructor with maximum size only.
+ *
+ * @param maxsize Maximum size
+ */
+ public TopBoundedUpdatableHeap(int maxsize) {
+ this(maxsize, null);
+ }
+
+ /**
+ * Constructor with maximum size and {@link Comparator}.
+ *
+ * @param maxsize Maximum size
+ * @param comparator Comparator
+ */
+ public TopBoundedUpdatableHeap(int maxsize, Comparator<? super E> comparator) {
+ super(maxsize + 1, comparator);
+ this.maxsize = maxsize;
+ assert (maxsize > 0);
+ }
+
+ @Override
+ public boolean offerAt(int pos, E e) {
+ // don't add if we hit maxsize and are worse
+ if(pos == NO_VALUE && super.size() >= maxsize) {
+ ensureValid();
+ if(compare(e, queue[0]) < 0) {
+ // while we did not change, this still was "successful".
+ return true;
+ }
+ // pos = index.get(e); // Should not be needed.
+ }
+ boolean result = super.offerAt(pos, e);
+ // purge unneeded entry(s)
+ while(super.size() > maxsize) {
+ handleOverflow(super.poll());
+ }
+ return result;
+ }
+
+ /**
+ * Test if the priority of an object is higher.
+ *
+ * @param e New object
+ * @param object Reference object
+ * @return True when an update is needed
+ */
+ protected int compare(Object e, Object object) {
+ if(comparator == null) {
+ @SuppressWarnings("unchecked")
+ Comparable<Object> c = (Comparable<Object>) e;
+ return c.compareTo(queue[0]);
+ }
+ else {
+ return comparator.compare(e, queue[0]);
+ }
+ }
+
+ /**
+ * Handle an overflow in the structure. This function can be overridden to get
+ * overflow treatment.
+ *
+ * @param e Overflowing element.
+ */
+ protected void handleOverflow(E e) {
+ // index.remove(e); // Should not be needed.
+ }
+
+ /**
+ * @return the maximum size
+ */
+ public int getMaxSize() {
+ return maxsize;
+ }
+} \ No newline at end of file
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 0ccacadc..745d82cc 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,8 +23,10 @@ package de.lmu.ifi.dbs.elki.utilities.datastructures.heap;
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.Comparator;
-import java.util.HashMap;
/**
* A heap as used in OPTICS that allows updating entries.
@@ -35,6 +37,16 @@ import java.util.HashMap;
*/
public class UpdatableHeap<O> extends Heap<O> {
/**
+ * Constant for "not in heap"
+ */
+ protected static final int NO_VALUE = Integer.MIN_VALUE;
+
+ /**
+ * Constant for "in ties list", for tied heaps.
+ */
+ protected static final int IN_TIES = -1;
+
+ /**
* Serial version
*/
private static final long serialVersionUID = 1L;
@@ -42,7 +54,7 @@ public class UpdatableHeap<O> extends Heap<O> {
/**
* Holds the indices in the heap of each element.
*/
- private HashMap<O, Integer> index = new HashMap<O, Integer>();
+ protected final TObjectIntMap<Object> index = new TObjectIntHashMap<Object>(100, 0.5f, NO_VALUE);
/**
* Simple constructor with default size.
@@ -86,60 +98,111 @@ public class UpdatableHeap<O> extends Heap<O> {
}
@Override
- public synchronized boolean offer(O e) {
- Integer pos = index.get(e);
- if(pos == null) {
- // LoggingUtil.logExpensive(Level.INFO, "Inserting: "+e);
- // insert
- return super.offer(e);
+ public boolean offer(O e) {
+ final int pos = index.get(e);
+ return offerAt(pos, e);
+ }
+
+ protected boolean offerAt(final int pos, O e) {
+ if(pos == NO_VALUE) {
+ // resize when needed
+ 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.
+ // We have changed - return true according to {@link Collection#put}
+ modCount++;
+ return true;
}
else {
- // update
- if(compareExternal(e, pos) < 0) {
- // LoggingUtil.logExpensive(Level.INFO,
- // "Updating value: "+e+" vs. "+castQueueElement(pos));
- modCount++;
- putInQueue(pos, e);
- heapifyUpParent(pos);
- // We have changed - return true according to {@link Collection#put}
- return true;
+ assert (pos >= 0) : "Unexpected negative position.";
+ assert (queue[pos].equals(e));
+ // Did the value improve?
+ if(comparator == null) {
+ @SuppressWarnings("unchecked")
+ Comparable<Object> c = (Comparable<Object>) e;
+ if(c.compareTo(queue[pos]) >= 0) {
+ // Ignore, but return true according to {@link Collection#put}
+ return true;
+ }
}
else {
- // LoggingUtil.logExpensive(Level.INFO,
- // "Keeping value: "+e+" vs. "+castQueueElement(pos));
- // Ignore, no improvement. Return success anyway.
- return true;
+ if(comparator.compare(e, queue[pos]) >= 0) {
+ // Ignore, but return true according to {@link Collection#put}
+ return true;
+ }
}
+ if(pos >= validSize) {
+ queue[pos] = e;
+ // validSize = Math.min(pos, validSize);
+ }
+ else {
+ // ensureValid();
+ heapifyUp(pos, e);
+ }
+ modCount++;
+ // We have changed - return true according to {@link Collection#put}
+ return true;
}
}
@Override
- protected void putInQueue(int pos, Object e) {
- super.putInQueue(pos, e);
- // Keep index up to date
- if(e != null) {
- O n = castQueueElement(pos);
- index.put(n, pos);
+ protected O removeAt(int pos) {
+ if(pos < 0 || pos >= size) {
+ return null;
}
- }
-
- @Override
- protected synchronized O removeAt(int pos) {
- O node = super.removeAt(pos);
+ final O ret = castQueueElement(pos);
+ // Replacement object:
+ 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);
+ }
+ }
+ 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);
+ }
+ modCount++;
// Keep index up to date
- index.remove(node);
- return node;
+ index.remove(ret);
+ return ret;
}
/**
* Remove the given object from the queue.
*
- * @param e Obejct to remove
+ * @param e Object to remove
* @return Existing entry
*/
public O removeObject(O e) {
- Integer pos = index.get(e);
- if(pos != null) {
+ int pos = index.get(e);
+ if(pos >= 0) {
return removeAt(pos);
}
else {
@@ -153,4 +216,116 @@ public class UpdatableHeap<O> extends Heap<O> {
index.remove(node);
return node;
}
+
+ /**
+ * Execute a "Heapify Upwards" aka "SiftUp". Used in insertions.
+ *
+ * @param pos insertion position
+ * @param elem Element to insert
+ */
+ @SuppressWarnings("unchecked")
+ protected void heapifyUpComparable(int pos, Object elem) {
+ final Comparable<Object> cur = (Comparable<Object>) elem; // queue[pos];
+ while(pos > 0) {
+ final int parent = (pos - 1) >>> 1;
+ Object par = queue[parent];
+
+ if(cur.compareTo(par) >= 0) {
+ break;
+ }
+ queue[pos] = par;
+ index.put(par, pos);
+ pos = parent;
+ }
+ queue[pos] = cur;
+ index.put(cur, pos);
+ }
+
+ /**
+ * Execute a "Heapify Upwards" aka "SiftUp". Used in insertions.
+ *
+ * @param pos insertion position
+ * @param cur Element to insert
+ */
+ protected void heapifyUpComparator(int pos, Object cur) {
+ while(pos > 0) {
+ final int parent = (pos - 1) >>> 1;
+ Object par = queue[parent];
+
+ if(comparator.compare(cur, par) >= 0) {
+ break;
+ }
+ queue[pos] = par;
+ index.put(par, pos);
+ pos = parent;
+ }
+ queue[pos] = cur;
+ index.put(cur, pos);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected boolean heapifyDownComparable(final int ipos, Object reinsert) {
+ Comparable<Object> cur = (Comparable<Object>) reinsert;
+ int pos = ipos;
+ final int half = size >>> 1;
+ 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) {
+ Object right = queue[rchild];
+ if(((Comparable<Object>) child).compareTo(right) > 0) {
+ cpos = rchild;
+ child = right;
+ }
+ }
+
+ if(cur.compareTo(child) <= 0) {
+ break;
+ }
+ queue[pos] = child;
+ index.put(child, pos);
+ pos = cpos;
+ }
+ queue[pos] = cur;
+ index.put(cur, pos);
+ return (pos == ipos);
+ }
+
+ @Override
+ protected boolean heapifyDownComparator(final int ipos, Object cur) {
+ int pos = ipos;
+ final int half = size >>> 1;
+ 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) {
+ min = lchild;
+ best = left;
+ }
+ final int rchild = lchild + 1;
+ if(rchild < size) {
+ Object right = queue[rchild];
+ if(comparator.compare(best, right) > 0) {
+ min = rchild;
+ best = right;
+ }
+ }
+ if(min == pos) {
+ break;
+ }
+ queue[pos] = best;
+ index.put(best, pos);
+ pos = min;
+ }
+ queue[pos] = cur;
+ index.put(cur, pos);
+ 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 45259fe7..3f193171 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) 2011
+Copyright (C) 2012
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/Hierarchical.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/Hierarchical.java
index 1bd9b430..697ac640 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/Hierarchical.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/Hierarchical.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) 2011
+ Copyright (C) 2012
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/Hierarchy.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/Hierarchy.java
index 94a6c708..3a3c4d45 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) 2011
+ Copyright (C) 2012
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/HierarchyHashmapList.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/HierarchyHashmapList.java
index 1b2dd0fa..d09e6d94 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/HierarchyHashmapList.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/HierarchyHashmapList.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -92,7 +92,7 @@ public class HierarchyHashmapList<O> implements ModifiableHierarchy<O> {
@Override
public void remove(O parent, O child) {
- // Add child to parent.
+ // Remove child from parent.
{
List<O> pchi = this.cmap.get(parent);
if(pchi != null) {
@@ -104,7 +104,7 @@ public class HierarchyHashmapList<O> implements ModifiableHierarchy<O> {
}
}
}
- // Add child to parent
+ // Remove parent from child
{
List<O> cpar = this.pmap.get(child);
if(cpar != null) {
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
index c2185dc9..f6c527ab 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/HierarchyReferenceLists.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/HierarchyReferenceLists.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) 2011
+ Copyright (C) 2012
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/ModifiableHierarchy.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/ModifiableHierarchy.java
index 9faaf189..dadc6f66 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) 2011
+ Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/hierarchy/package-info.java
index 259ab46b..0aba31be 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) 2011
+Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/datastructures/package-info.java
index 31a0f5b4..ae8308af 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) 2011
+Copyright (C) 2012
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/Observer.java b/src/de/lmu/ifi/dbs/elki/utilities/designpattern/Observer.java
index 3fab4ca2..6afec037 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/designpattern/Observer.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/designpattern/Observer.java
@@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.utilities.designpattern;
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2011
+ Copyright (C) 2012
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
index fef6b95c..dacae560 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/designpattern/Observers.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/designpattern/Observers.java
@@ -1,10 +1,12 @@
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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,30 +25,30 @@ package de.lmu.ifi.dbs.elki.utilities.designpattern;
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.
+ * 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 java.util.Vector<Observer<? super T>> {
+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.
*
@@ -64,14 +66,14 @@ public class Observers<T> extends java.util.Vector<Observer<? super T>> {
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) {
+ for(Observer<? super T> observer : this) {
observer.update(owner);
}
}
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
index e01f64e2..563470af 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/designpattern/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/designpattern/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2011
+Copyright (C) 2012
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/Description.java b/src/de/lmu/ifi/dbs/elki/utilities/documentation/Description.java
index cd9231b1..2769ff13 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) 2011
+ Copyright (C) 2012
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 05859325..1bdef265 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) 2011
+ Copyright (C) 2012
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 8b685cf3..acb3a0aa 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) 2011
+ Copyright (C) 2012
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 })
+@Target( { ElementType.TYPE, ElementType.METHOD })
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
new file mode 100644
index 00000000..8daa97ab
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/documentation/Restricted.java
@@ -0,0 +1,48 @@
+package de.lmu.ifi.dbs.elki.utilities.documentation;
+
+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 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/>.
+ */
+
+/**
+ * Indicator that the given class has distibution restrictions such as
+ * associated patents, and therefore must not be included in the release.
+ *
+ * @author Erich Schubert
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.TYPE })
+public @interface Restricted {
+ /**
+ * Restriction reason
+ *
+ * @return reason why this class must not be published
+ */
+ String value();
+} \ No newline at end of file
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 fc6199ae..2a390f19 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) 2011
+ Copyright (C) 2012
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 8a57e545..70f31ace 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) 2011
+Copyright (C) 2012
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 37fd0c6a..d332f2b0 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) 2011
+ Copyright (C) 2012
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 3025e8e7..768cb243 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) 2011
+ Copyright (C) 2012
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 e2d5fb55..1b1eed80 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/exceptions/ExceptionMessages.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/exceptions/ExceptionMessages.java
@@ -3,7 +3,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) 2011
+Copyright (C) 2012
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/ObjectNotFoundException.java b/src/de/lmu/ifi/dbs/elki/utilities/exceptions/ObjectNotFoundException.java
index 9bc9d056..c99e5394 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) 2011
+ Copyright (C) 2012
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 539af3dd..024615f8 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) 2011
+ Copyright (C) 2012
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 eb701643..f9733d18 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) 2011
+Copyright (C) 2012
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
index 8cb14df3..a56b34db 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/AbstractFilteredIterator.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/iterator/AbstractFilteredIterator.java
@@ -4,7 +4,7 @@ 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) 2011
+ Copyright (C) 2012
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/EmptyIterator.java b/src/de/lmu/ifi/dbs/elki/utilities/iterator/EmptyIterator.java
index 10fbca1c..98a3539e 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/EmptyIterator.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/iterator/EmptyIterator.java
@@ -4,7 +4,7 @@ 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) 2011
+ Copyright (C) 2012
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/IterableIterator.java b/src/de/lmu/ifi/dbs/elki/utilities/iterator/IterableIterator.java
index 7a8e0c73..d416faa6 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/IterableIterator.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/iterator/IterableIterator.java
@@ -4,7 +4,7 @@ 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) 2011
+ Copyright (C) 2012
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/IterableIteratorAdapter.java b/src/de/lmu/ifi/dbs/elki/utilities/iterator/IterableIteratorAdapter.java
index 3976319b..4a8cb512 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/IterableIteratorAdapter.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/iterator/IterableIteratorAdapter.java
@@ -4,7 +4,7 @@ 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) 2011
+ Copyright (C) 2012
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/IterableUtil.java b/src/de/lmu/ifi/dbs/elki/utilities/iterator/IterableUtil.java
index fa748248..8e4afd80 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/IterableUtil.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/iterator/IterableUtil.java
@@ -4,7 +4,7 @@ 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) 2011
+ Copyright (C) 2012
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/MergedIterator.java b/src/de/lmu/ifi/dbs/elki/utilities/iterator/MergedIterator.java
index 2676a4fb..9208ab14 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/MergedIterator.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/iterator/MergedIterator.java
@@ -4,7 +4,7 @@ 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -34,15 +34,15 @@ import java.util.Iterator;
*
* @apiviz.stereotype adapter
* @apiviz.uses Iterator oneway
- *
+ *
* @param <E> Entry type
*/
-public class MergedIterator<E> implements Iterator<E> {
+public class MergedIterator<E> implements IterableIterator<E> {
/**
* All the iterators we process
*/
final Iterator<Iterator<E>> iterators;
-
+
/**
* The iterator we are currently processing
*/
@@ -52,7 +52,7 @@ public class MergedIterator<E> implements Iterator<E> {
* The last iterator we returned an object for, for remove()
*/
Iterator<E> last = null;
-
+
/**
* Main constructor.
*
@@ -83,20 +83,22 @@ public class MergedIterator<E> implements Iterator<E> {
@Override
public boolean hasNext() {
- while((current != null && current.hasNext()) || iterators.hasNext()) {
- // Next element in current iterator?
- if (current != null && current.hasNext()) {
+ do {
+ if(current != null && current.hasNext()) {
return true;
}
+ if(!iterators.hasNext()) {
+ return false;
+ }
// advance master iterator and retry
current = iterators.next();
}
- return false;
+ while(true);
}
@Override
public E next() {
- while (!current.hasNext()) {
+ while(!current.hasNext()) {
current = iterators.next();
}
last = current;
@@ -105,9 +107,14 @@ public class MergedIterator<E> implements Iterator<E> {
@Override
public void remove() {
- if (last == null) {
+ if(last == null) {
throw new RuntimeException("Iterator.remove() called without next()");
}
last.remove();
}
+
+ @Override
+ public Iterator<E> iterator() {
+ return this;
+ }
}
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/iterator/OneItemIterator.java b/src/de/lmu/ifi/dbs/elki/utilities/iterator/OneItemIterator.java
index d67503af..a81dcc18 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/OneItemIterator.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/iterator/OneItemIterator.java
@@ -4,7 +4,7 @@ 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) 2011
+ Copyright (C) 2012
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/ReverseListIterator.java b/src/de/lmu/ifi/dbs/elki/utilities/iterator/ReverseListIterator.java
index 52cab893..c207e44c 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/ReverseListIterator.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/iterator/ReverseListIterator.java
@@ -4,7 +4,7 @@ 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) 2011
+ Copyright (C) 2012
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/TypeFilterIterator.java b/src/de/lmu/ifi/dbs/elki/utilities/iterator/TypeFilterIterator.java
index 9bf2ecfc..cd687542 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/TypeFilterIterator.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/iterator/TypeFilterIterator.java
@@ -4,7 +4,7 @@ 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -33,7 +33,7 @@ import java.util.Iterator;
* @param <IN> Input datatype
* @param <OUT> Output datatype
*/
-public class TypeFilterIterator<IN, OUT extends IN> extends AbstractFilteredIterator<IN, OUT> {
+public class TypeFilterIterator<IN, OUT extends IN> extends AbstractFilteredIterator<IN, OUT> implements IterableIterator<OUT> {
/**
* Class restriction
*/
@@ -83,4 +83,9 @@ public class TypeFilterIterator<IN, OUT extends IN> extends AbstractFilteredIter
return null;
}
}
-}
+
+ @Override
+ public Iterator<OUT> iterator() {
+ return this;
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/utilities/iterator/UnmodifiableIterator.java b/src/de/lmu/ifi/dbs/elki/utilities/iterator/UnmodifiableIterator.java
index 271ba495..03c1119c 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/UnmodifiableIterator.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/iterator/UnmodifiableIterator.java
@@ -4,7 +4,7 @@ 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) 2011
+ Copyright (C) 2012
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/UnmodifiableListIterator.java b/src/de/lmu/ifi/dbs/elki/utilities/iterator/UnmodifiableListIterator.java
index 0123216d..7b9c9d79 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/UnmodifiableListIterator.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/iterator/UnmodifiableListIterator.java
@@ -4,7 +4,7 @@ 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) 2011
+ Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/iterator/package-info.java
index 52359156..9a889d1d 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/iterator/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/iterator/package-info.java
@@ -5,7 +5,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2011
+Copyright (C) 2012
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/AbstractParameterizer.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/AbstractParameterizer.java
index 9f1a3d49..32543ace 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) 2011
+ Copyright (C) 2012
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 987497ff..4bec9193 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) 2011
+ Copyright (C) 2012
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/NoParameterValueException.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/NoParameterValueException.java
index 00fbac6b..2965f207 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) 2011
+ Copyright (C) 2012
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 8202f9d3..0d685e2b 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) 2011
+ Copyright (C) 2012
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/OptionUtil.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/OptionUtil.java
index f4ad3e48..2aa68611 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) 2011
+ Copyright (C) 2012
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 fabe9c7d..0235b4a9 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) 2011
+ Copyright (C) 2012
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 044c119c..4149658a 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) 2011
+ Copyright (C) 2012
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/Parameterizer.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/Parameterizer.java
index b434ea4e..aa5c74bd 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) 2011
+ Copyright (C) 2012
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 16828b3f..8e294ddb 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) 2011
+ Copyright (C) 2012
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 05943069..0914c0f1 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) 2011
+ Copyright (C) 2012
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 0f9c6260..219b32cd 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) 2011
+ Copyright (C) 2012
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 6b49faea..f622aba5 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) 2011
+ Copyright (C) 2012
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 59a91613..42209d87 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) 2011
+ Copyright (C) 2012
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/EqualSizeGlobalConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/EqualSizeGlobalConstraint.java
index 0e04906b..22d1ceb2 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) 2011
+ Copyright (C) 2012
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 342ffd00..ad567fa1 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) 2011
+ Copyright (C) 2012
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 8f510dc9..b30a45d9 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) 2011
+ Copyright (C) 2012
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 404da18f..b59c9493 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) 2011
+ Copyright (C) 2012
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 fe4b6520..740d9545 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) 2011
+ Copyright (C) 2012
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 1f894094..22cc50f9 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) 2011
+ Copyright (C) 2012
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 7a1d2f7a..26145620 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) 2011
+ Copyright (C) 2012
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 8a9f1bcf..f9e93a5b 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) 2011
+ Copyright (C) 2012
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.WrongParameterValueException
public class IntervalConstraint implements ParameterConstraint<Number> {
/**
* Available interval boundary types types:
- * {@link IntervalConstraint.IntervalBoundary#OPEN} denotes an opend interval,
+ * {@link IntervalConstraint.IntervalBoundary#OPEN} denotes an open interval,
* i.e. less than (or greater than) comparison
* {@link IntervalConstraint.IntervalBoundary#CLOSE} denotes a closed
* interval, i.e. an equal to or less than (or equal to or greater than)
@@ -66,7 +66,9 @@ public class IntervalConstraint implements ParameterConstraint<Number> {
private final Number lowConstraintValue;
/**
- * The interval boundary for the low constraint value (@see IntervalBoundary)
+ * The interval boundary for the low constraint value.
+ *
+ * @see IntervalBoundary
*/
private final IntervalBoundary lowBoundary;
@@ -76,7 +78,9 @@ public class IntervalConstraint implements ParameterConstraint<Number> {
private final Number highConstraintValue;
/**
- * The interval boundary for the high constraint value (@see IntervalBoundary)
+ * The interval boundary for the high constraint value.
+ *
+ * @see IntervalBoundary
*/
private final IntervalBoundary highBoundary;
@@ -88,12 +92,11 @@ public class IntervalConstraint implements ParameterConstraint<Number> {
* than (or equal to, if specified) than the specified high constraint value.
*
* @param lowConstraintValue the low constraint value (left interval boundary)
- * @param lowBoundary the interval boundary for the low constraint value (@see
- * IntervalBoundary)
+ * @param lowBoundary the interval boundary for the low constraint value (see {@link IntervalBoundary})
* @param highConstraintValue the high constraint value (right interval
* boundary)
* @param highBoundary the interval boundary for the high constraint value
- * (@see IntervalBoundary)
+ * (see {@link IntervalBoundary})
*/
public IntervalConstraint(Number lowConstraintValue, IntervalBoundary lowBoundary, Number highConstraintValue, IntervalBoundary highBoundary) {
if(lowConstraintValue.doubleValue() >= highConstraintValue.doubleValue()) {
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 a7c7cebd..0994425e 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) 2011
+ Copyright (C) 2012
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 9c180c02..712630e8 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) 2011
+ Copyright (C) 2012
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 358248cf..9855b96d 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) 2011
+ Copyright (C) 2012
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 6ea46b09..e475e92f 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) 2011
+ Copyright (C) 2012
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/ListGreaterEqualConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ListGreaterEqualConstraint.java
index fa56d021..0f33b9b2 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ListGreaterEqualConstraint.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ListGreaterEqualConstraint.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) 2011
+ Copyright (C) 2012
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/ListSizeConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ListSizeConstraint.java
index 5c6a5156..f2ef2069 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) 2011
+ Copyright (C) 2012
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 7ddd3d3b..04472fa5 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) 2011
+ Copyright (C) 2012
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/OneMustBeSetGlobalConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/OneMustBeSetGlobalConstraint.java
index 7473b6bd..1c8c6b94 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) 2011
+ Copyright (C) 2012
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/OnlyOneIsAllowedToBeSetGlobalConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/OnlyOneIsAllowedToBeSetGlobalConstraint.java
index 8f677669..74a1955b 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) 2011
+ Copyright (C) 2012
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/ParameterConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/ParameterConstraint.java
index ea57c0ea..ff66ec05 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) 2011
+ Copyright (C) 2012
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 4c5b9262..befc0788 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) 2011
+ Copyright (C) 2012
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/StringLengthConstraint.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/constraints/StringLengthConstraint.java
index ac8c48b3..84d8fa6d 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) 2011
+ Copyright (C) 2012
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 59d6534d..4b8c163a 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) 2011
+Copyright (C) 2012
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 c3196511..2756327e 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
@@ -2,7 +2,7 @@
* <p><b>Parameter handling and option descriptions.</b></p>
*
* <ol>
- * <li><b>Option ID</b>: Any parameter <em>must</em> have a {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID OptionID}.<br />
+ * <li><b>Option ID</b>: Any parameter <em>must</em> have an {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID OptionID}.<br />
* These are Singleton objects to uniquely identify the option. They should be "public static". <br />
* The OptionID specifies the parameter name and a generic description.
* <p />
@@ -253,7 +253,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2011
+Copyright (C) 2012
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 a333bffd..156dca1d 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -173,7 +173,7 @@ public abstract class AbstractParameterization implements Parameterization {
}
catch(Exception e) {
logger.exception(e);
- reportError(new InternalParameterizationErrors("Error instantiating internal class.", e));
+ reportError(new InternalParameterizationErrors("Error instantiating internal class: "+c.getName(), e));
return null;
}
}
@@ -185,7 +185,7 @@ public abstract class AbstractParameterization implements Parameterization {
}
catch(Exception e) {
logger.exception(e);
- reportError(new InternalParameterizationErrors("Error instantiating internal class.", e));
+ reportError(new InternalParameterizationErrors("Error instantiating internal class: "+c.getName(), e));
return null;
}
}
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 33aab341..f62b8128 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) 2011
+ Copyright (C) 2012
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/EmptyParameterization.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/EmptyParameterization.java
index 05a85b49..1fbd26b6 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) 2011
+ Copyright (C) 2012
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 8e751fe7..937bb966 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) 2011
+ Copyright (C) 2012
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/MergedParameterization.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/MergedParameterization.java
index 7a9ce476..8bba1c2a 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -174,7 +174,7 @@ public class MergedParameterization implements Parameterization {
return ClassGenericsUtil.tryInstantiate(r, c, this);
}
catch(Exception e) {
- reportError(new InternalParameterizationErrors("Error instantiating internal class.", e));
+ reportError(new InternalParameterizationErrors("Error instantiating internal class: "+c.getName(), e));
return null;
}
}
@@ -185,7 +185,7 @@ public class MergedParameterization implements Parameterization {
return ClassGenericsUtil.tryInstantiate(c, c, this);
}
catch(Exception e) {
- reportError(new InternalParameterizationErrors("Error instantiating internal class.", e));
+ reportError(new InternalParameterizationErrors("Error instantiating internal class: "+c.getName(), e));
return null;
}
}
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 be7c422e..f03463f8 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) 2011
+ Copyright (C) 2012
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 a4eeda1a..73abbca0 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) 2011
+ Copyright (C) 2012
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/TrackParameters.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameterization/TrackParameters.java
index 0399a5c7..157efa32 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -205,7 +205,7 @@ public class TrackParameters implements Parameterization {
return ClassGenericsUtil.tryInstantiate(r, c, this);
}
catch(Exception e) {
- reportError(new InternalParameterizationErrors("Error instantiating internal class.", e));
+ reportError(new InternalParameterizationErrors("Error instantiating internal class: "+c.getName(), e));
return null;
}
}
@@ -216,7 +216,7 @@ public class TrackParameters implements Parameterization {
return ClassGenericsUtil.tryInstantiate(c, c, this);
}
catch(Exception e) {
- reportError(new InternalParameterizationErrors("Error instantiating internal class.", e));
+ reportError(new InternalParameterizationErrors("Error instantiating internal class: "+c.getName(), e));
return null;
}
}
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 5fc930db..3a25ddd4 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -91,7 +91,7 @@ public class UnParameterization implements Parameterization {
return ClassGenericsUtil.tryInstantiate(r, c, this);
}
catch(Exception e) {
- reportError(new InternalParameterizationErrors("Error instantiating internal class.", e));
+ reportError(new InternalParameterizationErrors("Error instantiating internal class: "+c.getName(), e));
return null;
}
}
@@ -102,7 +102,7 @@ public class UnParameterization implements Parameterization {
return ClassGenericsUtil.tryInstantiate(c, c, this);
}
catch(Exception e) {
- reportError(new InternalParameterizationErrors("Error instantiating internal class.", e));
+ reportError(new InternalParameterizationErrors("Error instantiating internal class: "+c.getName(), e));
return null;
}
}
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 174c52b4..41856ad7 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) 2011
+Copyright (C) 2012
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/ClassListParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ClassListParameter.java
index 2ec3fb91..85851e5b 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,13 +26,9 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters;
import java.util.ArrayList;
import java.util.List;
-import de.lmu.ifi.dbs.elki.properties.IterateKnownImplementations;
-import de.lmu.ifi.dbs.elki.properties.Properties;
import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
import de.lmu.ifi.dbs.elki.utilities.FormatUtil;
import de.lmu.ifi.dbs.elki.utilities.InspectionUtil;
-import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
-import de.lmu.ifi.dbs.elki.utilities.iterator.IterableUtil;
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;
@@ -46,14 +42,18 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameteriz
* @author Steffi Wanka
* @author Erich Schubert
*
- * @apiviz.uses Properties
- * @apiviz.uses IterateKnownImplementations
+ * @apiviz.uses InspectionUtil
*
* @param <C> Class type
*/
// 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;
@@ -145,11 +145,11 @@ public class ClassListParameter<C> extends ListParameter<Class<? extends C>> {
try {
Class<?> c;
try {
- c = Class.forName(cl);
+ c = loader.loadClass(cl);
}
catch(ClassNotFoundException e) {
// try in package of restriction class
- c = Class.forName(restrictionClass.getPackage().getName() + "." + cl);
+ c = loader.loadClass(restrictionClass.getPackage().getName() + "." + cl);
}
// Redundant check, also in validate(), but not expensive.
if(!restrictionClass.isAssignableFrom(c)) {
@@ -192,27 +192,10 @@ public class ClassListParameter<C> extends ListParameter<Class<? extends C>> {
/**
* Get an iterator over all known implementations of the class restriction.
*
- * @return {@link java.lang.Iterable Iterable} and {@link java.util.Iterator
- * Iterator} object
- */
- public IterableIterator<Class<?>> getKnownImplementations() {
- if(InspectionUtil.NONSTATIC_CLASSPATH) {
- return IterableUtil.fromIterable(InspectionUtil.cachedFindAllImplementations(getRestrictionClass()));
- }
- return new IterateKnownImplementations(getRestrictionClass());
- }
-
- /**
- * Returns the class names allowed according to the restriction class of this
- * parameter.
- *
- * @return class names allowed according to the restriction class defined.
+ * @return List object
*/
- public String[] getRestrictionClasses() {
- if(restrictionClass != null) {
- return Properties.ELKI_PROPERTIES.getProperty(restrictionClass.getName());
- }
- return new String[] {};
+ public List<Class<?>> getKnownImplementations() {
+ return InspectionUtil.cachedFindAllImplementations(getRestrictionClass());
}
/**
@@ -277,8 +260,8 @@ public class ClassListParameter<C> extends ListParameter<Class<? extends C>> {
info.append(restrictionClass.getName());
info.append(FormatUtil.NEWLINE);
- IterableIterator<Class<?>> known = getKnownImplementations();
- if(known.hasNext()) {
+ List<Class<?>> known = getKnownImplementations();
+ if(!known.isEmpty()) {
info.append("Known classes (default package " + prefix + "):");
info.append(FormatUtil.NEWLINE);
for(Class<?> c : known) {
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 36abc0f7..6b056c03 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,15 +24,12 @@ package de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters;
*/
import java.lang.reflect.InvocationTargetException;
+import java.util.List;
import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
-import de.lmu.ifi.dbs.elki.properties.IterateKnownImplementations;
-import de.lmu.ifi.dbs.elki.properties.Properties;
import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
import de.lmu.ifi.dbs.elki.utilities.FormatUtil;
import de.lmu.ifi.dbs.elki.utilities.InspectionUtil;
-import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
-import de.lmu.ifi.dbs.elki.utilities.iterator.IterableUtil;
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;
@@ -46,14 +43,21 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameteriz
* @author Steffi Wanka
* @author Erich Schubert
*
- * @apiviz.uses Properties
- * @apiviz.uses IterateKnownImplementations
+ * @apiviz.uses InspectionUtil
*
* @param <C> Class type
*/
// TODO: add additional constructors with parameter constraints.
// TODO: turn restrictionClass into a constraint?
public class ClassParameter<C> extends Parameter<Class<?>, Class<? extends C>> {
+ /**
+ * Class loader.
+ */
+ protected static final ClassLoader loader = ClassLoader.getSystemClassLoader();
+
+ /**
+ * Factory class postfix.
+ */
public static final String FACTORY_POSTFIX = "$Factory";
/**
@@ -133,26 +137,26 @@ public class ClassParameter<C> extends Parameter<Class<?>, Class<? extends C>> {
try {
// Try exact class factory first.
try {
- return (Class<? extends C>) Class.forName(value + FACTORY_POSTFIX);
+ return (Class<? extends C>) loader.loadClass(value + FACTORY_POSTFIX);
}
catch(ClassNotFoundException e) {
// Ignore, retry
}
try {
- return (Class<? extends C>) Class.forName(value);
+ return (Class<? extends C>) loader.loadClass(value);
}
catch(ClassNotFoundException e) {
// Ignore, retry
}
// Try factory for guessed name next
try {
- return (Class<? extends C>) Class.forName(restrictionClass.getPackage().getName() + "." + value + FACTORY_POSTFIX);
+ 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>) Class.forName(restrictionClass.getPackage().getName() + "." + value);
+ return (Class<? extends C>) loader.loadClass(restrictionClass.getPackage().getName() + "." + value);
}
catch(ClassNotFoundException e) {
throw new WrongParameterValueException(this, value, "Given class \"" + value + "\" not found.", e);
@@ -269,27 +273,10 @@ public class ClassParameter<C> extends Parameter<Class<?>, Class<? extends C>> {
/**
* Get an iterator over all known implementations of the class restriction.
*
- * @return {@link java.lang.Iterable Iterable} and {@link java.util.Iterator
- * Iterator} object
- */
- public IterableIterator<Class<?>> getKnownImplementations() {
- if(InspectionUtil.NONSTATIC_CLASSPATH) {
- return IterableUtil.fromIterable(InspectionUtil.cachedFindAllImplementations(getRestrictionClass()));
- }
- return new IterateKnownImplementations(getRestrictionClass());
- }
-
- /**
- * Returns the class names allowed according to the restriction class of this
- * class parameter.
- *
- * @return class names allowed according to the restriction class defined.
+ * @return List object
*/
- public String[] getRestrictionClasses() {
- if(restrictionClass != null) {
- return Properties.ELKI_PROPERTIES.getProperty(restrictionClass.getName());
- }
- return new String[] {};
+ public List<Class<?>> getKnownImplementations() {
+ return InspectionUtil.cachedFindAllImplementations(getRestrictionClass());
}
/**
@@ -310,8 +297,8 @@ public class ClassParameter<C> extends Parameter<Class<?>, Class<? extends C>> {
info.append(restrictionClass.getName());
info.append(FormatUtil.NEWLINE);
- IterableIterator<Class<?>> known = getKnownImplementations();
- if(known.hasNext()) {
+ List<Class<?>> known = getKnownImplementations();
+ if(!known.isEmpty()) {
info.append("Known classes (default package " + restrictionClass.getPackage().getName() + "):");
info.append(FormatUtil.NEWLINE);
for(Class<?> c : known) {
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 a47f6d53..bb9dc60c 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) 2011
+ Copyright (C) 2012
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 2e255f2f..07b10b83 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) 2011
+ Copyright (C) 2012
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/DoubleParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/DoubleParameter.java
index aad0a2ee..9ebb61ee 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) 2011
+ Copyright (C) 2012
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/FileListParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/FileListParameter.java
index ec716a63..1b72df80 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) 2011
+ Copyright (C) 2012
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/FileParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/FileParameter.java
index 7c642fe8..1e04c7ae 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) 2011
+ Copyright (C) 2012
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/Flag.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/Flag.java
index fd383020..e2ce63c2 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) 2011
+ Copyright (C) 2012
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 32675d22..d7b5d570 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) 2011
+ Copyright (C) 2012
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/IntParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/IntParameter.java
index a1b22519..4e494fda 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) 2011
+ Copyright (C) 2012
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 0cc35d62..ad0ded5c 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) 2011
+ Copyright (C) 2012
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 d03d77f1..6f1a7beb 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) 2011
+ Copyright (C) 2012
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 87384e4f..3a1ab946 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) 2011
+ Copyright (C) 2012
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 f5eb2838..cfd74d9a 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) 2011
+ Copyright (C) 2012
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/ObjectParameter.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/ObjectParameter.java
index ffc668c2..0a1a6b27 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) 2011
+ Copyright (C) 2012
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 9c555359..8502bbec 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
@@ -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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -468,8 +468,8 @@ public abstract class Parameter<S, T extends S> {
/**
* Returns the value of the option.
*
- * You should use either {Parameterization#grab} or {@link #isDefined} to test
- * if getValue() will return a well-defined value.
+ * You should use either {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization#grab}
+ * or {@link #isDefined} to test if getValue() will return a well-defined value.
*
* @return the option's value.
*/
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 b988f9cb..1f54c5d2 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -61,7 +61,7 @@ public class PatternParameter extends Parameter<Pattern, Pattern> {
* @param defaultValue the default value of the parameter
*/
public PatternParameter(OptionID optionID, List<ParameterConstraint<Pattern>> constraint, String defaultValue) {
- super(optionID, constraint, Pattern.compile(defaultValue));
+ super(optionID, constraint, Pattern.compile(defaultValue, Pattern.CASE_INSENSITIVE));
}
/**
@@ -108,7 +108,7 @@ public class PatternParameter extends Parameter<Pattern, Pattern> {
* @param defaultValue the default value of the parameter
*/
public PatternParameter(OptionID optionID, ParameterConstraint<Pattern> constraint, String defaultValue) {
- super(optionID, constraint, Pattern.compile(defaultValue));
+ super(optionID, constraint, Pattern.compile(defaultValue, Pattern.CASE_INSENSITIVE));
}
/**
@@ -151,7 +151,7 @@ public class PatternParameter extends Parameter<Pattern, Pattern> {
* @param defaultValue the default value of the parameter
*/
public PatternParameter(OptionID optionID, String defaultValue) {
- super(optionID, Pattern.compile(defaultValue));
+ super(optionID, Pattern.compile(defaultValue, Pattern.CASE_INSENSITIVE));
}
/**
@@ -173,13 +173,11 @@ public class PatternParameter extends Parameter<Pattern, Pattern> {
super(optionID);
}
- /** {@inheritDoc} */
@Override
public String getValueAsString() {
return getValue().toString();
}
- /** {@inheritDoc} */
@Override
protected Pattern parseValue(Object obj) throws ParameterException {
if(obj == null) {
@@ -190,7 +188,7 @@ public class PatternParameter extends Parameter<Pattern, Pattern> {
}
if(obj instanceof String) {
try {
- return Pattern.compile((String) obj);
+ return Pattern.compile((String) obj, Pattern.CASE_INSENSITIVE);
}
catch(PatternSyntaxException e) {
throw new WrongParameterValueException("Given pattern \"" + obj + "\" for parameter \"" + getName() + "\" is no valid regular expression!");
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 43a19217..ea1c5a2c 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) 2011
+ Copyright (C) 2012
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 9fb9c6f1..0e6612b6 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) 2011
+ Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/optionhandling/parameters/package-info.java
index e13d29ee..5fcaa0c0 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
@@ -8,7 +8,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2011
+Copyright (C) 2012
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 09d0398e..a1bbc579 100644
--- a/src/de/lmu/ifi/dbs/elki/utilities/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/utilities/package-info.java
@@ -48,7 +48,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2011
+Copyright (C) 2012
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 ce7b5ded..dabc623e 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) 2011
+ Copyright (C) 2012
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 28802e3e..5a4b8cbd 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) 2011
+ Copyright (C) 2012
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/DoubleDoublePair.java b/src/de/lmu/ifi/dbs/elki/utilities/pairs/DoubleDoublePair.java
index 410f3f36..c24ee8f3 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) 2011
+ Copyright (C) 2012
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/DoubleIntPair.java b/src/de/lmu/ifi/dbs/elki/utilities/pairs/DoubleIntPair.java
index 98aba136..7bd22095 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) 2011
+ Copyright (C) 2012
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 970926bc..aa4d4b36 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) 2011
+ Copyright (C) 2012
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 00636784..6724ddfb 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) 2011
+ Copyright (C) 2012
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 2806731c..d0f356f8 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) 2011
+ Copyright (C) 2012
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 62b57709..96108239 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -154,6 +154,11 @@ public class IntIntPair implements Comparable<IntIntPair>, PairInterface<Integer
this.second = second;
}
+ @Override
+ public String toString() {
+ return "(" + first + ", " + second + ")";
+ }
+
/**
* Comparator to compare by second component only
*/
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 f034bd97..f682e06f 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) 2011
+ Copyright (C) 2012
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 8e45ce2d..5ea33971 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) 2011
+ Copyright (C) 2012
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 69e8ef3c..21917332 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) 2011
+ Copyright (C) 2012
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/SCPair.java b/src/de/lmu/ifi/dbs/elki/utilities/pairs/SCPair.java
index a2880a8f..585c7a57 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) 2011
+ Copyright (C) 2012
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 34c8713a..2f75ec5a 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) 2011
+ Copyright (C) 2012
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 cda785b3..2fdf3770 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) 2011
+Copyright (C) 2012
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 5fd4d6b4..3ec38f58 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -94,11 +94,11 @@ public class AxisBasedReferencePoints<V extends NumberVector<V, ?>> implements R
for(int d = 0; d < dim; d++) {
vec[d] = mean[d] - delta[d];
}
- result.add(factory.newInstance(vec));
+ result.add(factory.newNumberVector(vec));
for(int d = 0; d < dim; d++) {
vec[d] = mean[d] + delta[d];
}
- result.add(factory.newInstance(vec));
+ result.add(factory.newNumberVector(vec));
// Plus axis end points:
for(int i = 0; i < dim; i++) {
@@ -110,7 +110,7 @@ public class AxisBasedReferencePoints<V extends NumberVector<V, ?>> implements R
vec[d] = mean[d] + delta[d];
}
}
- result.add(factory.newInstance(vec));
+ result.add(factory.newNumberVector(vec));
}
return result;
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 62cb4c03..d427e35a 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) 2011
+ Copyright (C) 2012
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 142f9708..09d36cd8 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -117,13 +117,13 @@ public class GridBasedReferencePoints<V extends NumberVector<V, ?>> implements R
acc = acc / (gridres + 1);
vec[d] = mean[d] + (coord - halfgrid) * delta[d] * gridscale;
}
- V newp = factory.newInstance(vec);
+ V newp = factory.newNumberVector(vec);
// logger.debug("New reference point: " + FormatUtil.format(vec));
result.add(newp);
}
}
else {
- result.add(factory.newInstance(mean));
+ result.add(factory.newNumberVector(mean));
// logger.debug("New reference point: " + FormatUtil.format(mean));
}
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 ed7d74f6..6a56bfcd 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -107,7 +107,7 @@ public class RandomGeneratedReferencePoints<V extends NumberVector<V, ?>> implem
for(int d = 0; d < dim; d++) {
vec[d] = mean[d] + (Math.random() - 0.5) * scale * delta[d];
}
- V newp = factory.newInstance(vec);
+ V newp = factory.newNumberVector(vec);
// logger.debug("New reference point: " + FormatUtil.format(vec));
result.add(newp);
}
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 43c5f233..48125019 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) 2011
+ Copyright (C) 2012
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/ReferencePointsHeuristic.java b/src/de/lmu/ifi/dbs/elki/utilities/referencepoints/ReferencePointsHeuristic.java
index a7b64cc6..70114a32 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) 2011
+ Copyright (C) 2012
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 9970bf9c..819fc29e 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -118,7 +118,7 @@ public class StarBasedReferencePoints<V extends NumberVector<V, ?>> implements R
ArrayList<V> result = new ArrayList<V>(2 * dim + 1);
if(!nocenter) {
- result.add(factory.newInstance(centroid));
+ result.add(factory.newNumberVector(centroid));
}
// Plus axis end points through centroid
double[] vec = new double[dim];
@@ -129,9 +129,9 @@ public class StarBasedReferencePoints<V extends NumberVector<V, ?>> implements R
}
}
vec[i] = min[i];
- result.add(factory.newInstance(vec));
+ result.add(factory.newNumberVector(vec));
vec[i] = max[i];
- result.add(factory.newInstance(vec));
+ result.add(factory.newNumberVector(vec));
}
return result;
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 7c8ce99f..a8ce0bc5 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) 2011
+Copyright (C) 2012
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 d2f53ac2..97a43f37 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) 2011
+ Copyright (C) 2012
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 3aa539af..719a72c3 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) 2011
+ Copyright (C) 2012
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 239d51fe..a2202b92 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) 2011
+ Copyright (C) 2012
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 c4ea9e1d..87f42835 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) 2011
+ Copyright (C) 2012
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 a3c31169..b5007ad1 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) 2011
+ Copyright (C) 2012
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 3aab82ec..6bd0527f 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) 2011
+ Copyright (C) 2012
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 197f4e6c..228f5f1a 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) 2011
+ Copyright (C) 2012
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/HeDESNormalizationOutlierScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/HeDESNormalizationOutlierScaling.java
index cf880a3f..e7e6ee90 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) 2011
+ Copyright (C) 2012
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/MinusLogGammaScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MinusLogGammaScaling.java
index 4b7c7797..1485204c 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) 2011
+ Copyright (C) 2012
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.utilities.scaling.outlier;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
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.statistics.distribution.GammaDistribution;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
@@ -37,7 +37,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
*
* @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://www.dbs.ifi.lmu.de/~zimek/publications/SDM2011/SDM11-outlier-preprint.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 MinusLogGammaScaling extends OutlierGammaScaling {
/**
* Maximum value seen
@@ -88,7 +88,7 @@ public class MinusLogGammaScaling extends OutlierGammaScaling {
final double var = mv.getSampleVariance();
k = (mean * mean) / var;
theta = var / mean;
- atmean = MathUtil.regularizedGammaP(k, mean / theta);
+ atmean = GammaDistribution.regularizedGammaP(k, mean / theta);
// logger.warning("Mean:"+mean+" Var:"+var+" Theta: "+theta+" k: "+k+" valatmean"+atmean);
}
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 552de806..477fbdd2 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) 2011
+ Copyright (C) 2012
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.DBID;
import de.lmu.ifi.dbs.elki.math.MathUtil;
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.documentation.Reference;
@@ -40,7 +41,7 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
*
* @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://www.dbs.ifi.lmu.de/~zimek/publications/SDM2011/SDM11-outlier-preprint.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 MinusLogStandardDeviationScaling extends StandardDeviationScaling {
/**
* Constructor.
@@ -59,7 +60,7 @@ public class MinusLogStandardDeviationScaling extends StandardDeviationScaling {
if(mlogv < mean || Double.isNaN(mlogv)) {
return 0.0;
}
- return Math.max(0.0, MathUtil.erf((mlogv - mean) / factor));
+ return Math.max(0.0, NormalDistribution.erf((mlogv - mean) / factor));
}
@Override
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 527429c5..26abb453 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) 2011
+ Copyright (C) 2012
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/MultiplicativeInverseScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/MultiplicativeInverseScaling.java
index 3e98f49e..9602b9b6 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) 2011
+ Copyright (C) 2012
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.utilities.documentation.Reference;
*
* @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://www.dbs.ifi.lmu.de/~zimek/publications/SDM2011/SDM11-outlier-preprint.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 MultiplicativeInverseScaling implements OutlierScalingFunction {
/**
* Constructor, adhering to
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 25864872..a3eecdb0 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) 2011
+ Copyright (C) 2012
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.utilities.scaling.outlier;
*/
import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.math.MathUtil;
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.documentation.Reference;
@@ -40,7 +40,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Flag;
*
* @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://www.dbs.ifi.lmu.de/~zimek/publications/SDM2011/SDM11-outlier-preprint.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 OutlierGammaScaling implements OutlierScalingFunction {
/**
* Normalization flag.
@@ -93,7 +93,7 @@ public class OutlierGammaScaling implements OutlierScalingFunction {
if(Double.isNaN(value) || Double.isInfinite(value)) {
return 1.0;
}
- return Math.max(0, (MathUtil.regularizedGammaP(k, value / theta) - atmean) / (1 - atmean));
+ return Math.max(0, (GammaDistribution.regularizedGammaP(k, value / theta) - atmean) / (1 - atmean));
}
@Override
@@ -111,7 +111,7 @@ public class OutlierGammaScaling implements OutlierScalingFunction {
final double var = mv.getSampleVariance();
k = (mean * mean) / var;
theta = var / mean;
- atmean = MathUtil.regularizedGammaP(k, mean / theta);
+ atmean = GammaDistribution.regularizedGammaP(k, mean / theta);
// logger.warning("Mean:"+mean+" Var:"+var+" Theta: "+theta+" k: "+k+" valatmean"+atmean);
}
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 9d55048b..8f215ec3 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) 2011
+ Copyright (C) 2012
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/OutlierMinusLogScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierMinusLogScaling.java
index f1138cdf..0839f231 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) 2011
+ Copyright (C) 2012
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.utilities.documentation.Reference;
*
* @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://www.dbs.ifi.lmu.de/~zimek/publications/SDM2011/SDM11-outlier-preprint.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 OutlierMinusLogScaling implements OutlierScalingFunction {
/**
* Maximum value seen, set by {@link #prepare}
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 2aa821fe..ac774745 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) 2011
+ Copyright (C) 2012
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/OutlierSqrtScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/OutlierSqrtScaling.java
index 8ccdc8dd..d39fed97 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) 2011
+ Copyright (C) 2012
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/RankingPseudoOutlierScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/RankingPseudoOutlierScaling.java
index d6ef7f5f..47eda6aa 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) 2011
+ Copyright (C) 2012
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/SigmoidOutlierScalingFunction.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/SigmoidOutlierScalingFunction.java
index 7363f4f9..31e78ec8 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) 2011
+ Copyright (C) 2012
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/SqrtStandardDeviationScaling.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/SqrtStandardDeviationScaling.java
index 2c733332..24f9e855 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) 2011
+ Copyright (C) 2012
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.DBID;
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.statistics.distribution.NormalDistribution;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
@@ -48,7 +49,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleParameter;
*
* @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://www.dbs.ifi.lmu.de/~zimek/publications/SDM2011/SDM11-outlier-preprint.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 SqrtStandardDeviationScaling implements OutlierScalingFunction {
/**
* Parameter to specify the fixed minimum to use.
@@ -118,7 +119,7 @@ public class SqrtStandardDeviationScaling implements OutlierScalingFunction {
if(value <= mean) {
return 0;
}
- return Math.max(0, MathUtil.erf((value - mean) / factor));
+ return Math.max(0, NormalDistribution.erf((value - mean) / factor));
}
@Override
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 10db8e56..6ef5c006 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) 2011
+ Copyright (C) 2012
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.DBID;
import de.lmu.ifi.dbs.elki.math.MathUtil;
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.documentation.Reference;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
@@ -44,7 +45,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleParameter;
*
* @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://www.dbs.ifi.lmu.de/~zimek/publications/SDM2011/SDM11-outlier-preprint.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.
@@ -107,7 +108,7 @@ public class StandardDeviationScaling implements OutlierScalingFunction {
if(value <= mean) {
return 0;
}
- return Math.max(0, MathUtil.erf((value - mean) / factor));
+ return Math.max(0, NormalDistribution.erf((value - mean) / factor));
}
@Override
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 5d32dfb5..8044fce9 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) 2011
+ Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/utilities/scaling/outlier/package-info.java
index 3015661c..c2adba6b 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) 2011
+Copyright (C) 2012
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 4f781fc3..430f1bf7 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) 2011
+Copyright (C) 2012
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
new file mode 100644
index 00000000..dc3b48a8
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/utilities/xml/DOMCloner.java
@@ -0,0 +1,108 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.w3c.dom.Attr;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+/**
+ * Class for cloning XML document, with filter capabilites
+ *
+ * @author Erich Schubert
+ */
+public class DOMCloner {
+ /**
+ * Deep-clone a document.
+ *
+ * @param domImpl DOM implementation to use
+ * @param document Original document
+ * @return Cloned document
+ */
+ public Document cloneDocument(DOMImplementation domImpl, Document document) {
+ Element root = document.getDocumentElement();
+ // New document
+ Document result = domImpl.createDocument(root.getNamespaceURI(), root.getNodeName(), null);
+ Element rroot = result.getDocumentElement();
+ // Cloning the document element is a bit tricky.
+ // This is adopted from DomUtilities#deepCloneDocument
+ boolean before = true;
+ for(Node n = document.getFirstChild(); n != null; n = n.getNextSibling()) {
+ if(n == root) {
+ before = false;
+ copyAttributes(result, root, rroot);
+ for(Node c = root.getFirstChild(); c != null; c = c.getNextSibling()) {
+ final Node cl = cloneNode(result, c);
+ if(cl != null) {
+ rroot.appendChild(cl);
+ }
+ }
+ }
+ else {
+ if(n.getNodeType() != Node.DOCUMENT_TYPE_NODE) {
+ final Node cl = cloneNode(result, n);
+ if(cl != null) {
+ if(before) {
+ result.insertBefore(cl, rroot);
+ }
+ else {
+ result.appendChild(cl);
+ }
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Clone an existing node.
+ *
+ * @param doc Document
+ * @param eold Existing node
+ * @return Cloned node
+ */
+ public Node cloneNode(Document doc, Node eold) {
+ return doc.importNode(eold, true);
+ }
+
+ /**
+ * Copy the attributes from an existing node to a new node.
+ *
+ * @param doc Target document
+ * @param eold Existing node
+ * @param enew Target node
+ */
+ public void copyAttributes(Document doc, Element eold, Element enew) {
+ if(eold.hasAttributes()) {
+ NamedNodeMap attr = eold.getAttributes();
+ int len = attr.getLength();
+ for(int i = 0; i < len; i++) {
+ enew.setAttributeNode((Attr) doc.importNode(attr.item(i), true));
+ }
+ }
+ }
+} \ No newline at end of file
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 8ad2ae27..7e433525 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) 2011
+ Copyright (C) 2012
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 320f7478..e0602790 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) 2011
+ Copyright (C) 2012
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 762e9fe6..8157d4ba 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) 2011
+ Copyright (C) 2012
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 45d800b5..9b961687 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) 2011
+Copyright (C) 2012
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
new file mode 100644
index 00000000..da0a5c85
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/ExportVisualizations.java
@@ -0,0 +1,297 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.apache.batik.util.SVGConstants;
+
+import de.lmu.ifi.dbs.elki.logging.Logging;
+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.ResultHandler;
+import de.lmu.ifi.dbs.elki.result.ResultHierarchy;
+import de.lmu.ifi.dbs.elki.result.ResultUtil;
+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.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.FileParameter.FileType;
+import de.lmu.ifi.dbs.elki.visualization.gui.overview.PlotItem;
+import de.lmu.ifi.dbs.elki.visualization.projector.Projector;
+import de.lmu.ifi.dbs.elki.visualization.svg.SVGPlot;
+import de.lmu.ifi.dbs.elki.visualization.visualizers.Visualization;
+import de.lmu.ifi.dbs.elki.visualization.visualizers.VisualizerUtil;
+
+/**
+ * Class that automatically generates all visualizations and exports them into
+ * SVG files.
+ *
+ * @author Erich Schubert
+ */
+// TODO: make more parameterizable, wrt. what to skip
+public class ExportVisualizations implements ResultHandler {
+ /**
+ * Get a logger for this class.
+ */
+ protected final static Logging logger = Logging.getLogger(ExportVisualizations.class);
+
+ /**
+ * Parameter to specify the canvas ratio
+ * <p>
+ * Key: {@code -vis.ratio}
+ * </p>
+ * <p>
+ * Default value: 1.33
+ * </p>
+ */
+ public static final OptionID RATIO_ID = OptionID.getOrCreateOptionID("vis.ratio", "The width/heigh ratio of the output.");
+
+ /**
+ * Parameter to specify the output folder
+ * <p>
+ * Key: {@code -vis.output}
+ * </p>
+ */
+ public static final OptionID FOLDER_ID = OptionID.getOrCreateOptionID("vis.output", "The output folder.");
+
+ /**
+ * Output folder
+ */
+ File output;
+
+ /**
+ * Visualization manager.
+ */
+ VisualizerParameterizer manager;
+
+ /**
+ * Ratio for canvas
+ */
+ double ratio;
+
+ /**
+ * Base result
+ */
+ HierarchicalResult baseResult = null;
+
+ /**
+ * Visualizer context
+ */
+ VisualizerContext context = null;
+
+ /**
+ * Output counter
+ */
+ int counter = 0;
+
+ /**
+ * Constructor.
+ *
+ * @param output Output folder
+ * @param manager Parameterizer
+ * @param ratio Canvas ratio
+ */
+ protected ExportVisualizations(File output, VisualizerParameterizer manager, double ratio) {
+ super();
+ this.output = output;
+ this.manager = manager;
+ this.ratio = ratio;
+ }
+
+ @Override
+ public void processNewResult(HierarchicalResult baseResult, Result newResult) {
+ if(output.isFile()) {
+ throw new AbortException("Output folder cannot be an existing file.");
+ }
+ if(!output.exists()) {
+ if(!output.mkdirs()) {
+ throw new AbortException("Could not create output directory.");
+ }
+ }
+ if(this.baseResult != baseResult) {
+ this.baseResult = baseResult;
+ context = null;
+ counter = 0;
+ logger.verbose("Note: Reusing visualization exporter for more than one result is untested.");
+ }
+ if(context == null) {
+ context = manager.newContext(baseResult);
+ }
+
+ // Projected visualizations
+ ArrayList<Projector> projectors = ResultUtil.filterResults(baseResult, Projector.class);
+ for(Projector proj : projectors) {
+ // TODO: allow selecting individual projections only.
+ Collection<PlotItem> items = proj.arrange();
+ for(PlotItem item : items) {
+ processItem(item);
+ }
+ }
+ ResultHierarchy hier = baseResult.getHierarchy();
+ 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) {
+ isprojected = true;
+ break;
+ }
+ }
+ if(isprojected) {
+ continue;
+ }
+ PlotItem pi = new PlotItem(ratio, 1.0, null);
+ pi.add(task);
+ processItem(pi);
+ }
+ }
+
+ private void processItem(PlotItem item) {
+ final double height = 1;
+ final double width = ratio * height;
+ // Descend into subitems
+ for(Iterator<PlotItem> iter = item.subitems.iterator(); iter.hasNext();) {
+ PlotItem subitem = iter.next();
+ processItem(subitem);
+ }
+ if(item.taskSize() <= 0) {
+ return;
+ }
+ item.sort();
+
+ SVGPlot svgp = new SVGPlot();
+ svgp.getRoot().setAttribute(SVGConstants.SVG_WIDTH_ATTRIBUTE, "20cm");
+ 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>();
+ for(Iterator<VisualizationTask> iter = item.tasks.iterator(); iter.hasNext();) {
+ VisualizationTask task = iter.next();
+ {
+ Boolean dis = task.getGenerics(VisualizationTask.META_NODETAIL, Boolean.class);
+ if(dis != null && dis == true) {
+ continue;
+ }
+ }
+ {
+ Boolean dis = task.getGenerics(VisualizationTask.META_NOEXPORT, Boolean.class);
+ if(dis != null && dis == true) {
+ continue;
+ }
+ }
+ if(!VisualizerUtil.isVisible(task)) {
+ continue;
+ }
+ try {
+ Visualization v = task.getFactory().makeVisualization(task.clone(svgp, context, item.proj, width, height));
+ layers.add(v);
+ }
+ catch(Exception e) {
+ if(Logging.getLogger(task.getFactory().getClass()).isDebugging()) {
+ LoggingUtil.exception("Visualization failed.", e);
+ }
+ else {
+ LoggingUtil.warning("Visualizer " + task.getFactory().getClass().getName() + " failed - enable debugging to see details.");
+ }
+ }
+ }
+ if(layers.size() <= 0) {
+ return;
+ }
+ for(Visualization layer : layers) {
+ if(layer.getLayer() != null) {
+ svgp.getRoot().appendChild(layer.getLayer());
+ }
+ else {
+ LoggingUtil.warning("NULL layer seen.");
+ }
+ }
+ svgp.updateStyleElement();
+
+ // TODO: generate names...
+ File outname = new File(output, "plot-" + counter + ".svg");
+ try {
+ svgp.saveAsSVG(outname);
+ }
+ catch(Exception e) {
+ logger.warning("Export of visualization failed.", e);
+ }
+ for(Visualization layer : layers) {
+ layer.destroy();
+ }
+ counter++;
+ }
+
+ /**
+ * Parameterization class
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ /**
+ * Visualization manager.
+ */
+ VisualizerParameterizer manager;
+
+ /**
+ * Output folder
+ */
+ File output;
+
+ /**
+ * Ratio for canvas
+ */
+ double ratio;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ FileParameter outputP = new FileParameter(FOLDER_ID, FileType.OUTPUT_FILE);
+ if(config.grab(outputP)) {
+ output = outputP.getValue();
+ }
+
+ DoubleParameter ratioP = new DoubleParameter(RATIO_ID, new GreaterConstraint(0.0), 1.33);
+ if(config.grab(ratioP)) {
+ ratio = ratioP.getValue();
+ }
+
+ manager = config.tryInstantiate(VisualizerParameterizer.class);
+ }
+
+ @Override
+ protected ExportVisualizations makeInstance() {
+ return new ExportVisualizations(output, manager, ratio);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/VisualizationTask.java b/src/de/lmu/ifi/dbs/elki/visualization/VisualizationTask.java
index 3cf05e37..187b2473 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -95,6 +95,11 @@ public class VisualizationTask extends AnyMap<String> implements Cloneable, Resu
public final static String META_NOEXPORT = "no-export";
/**
+ * Flag to signal the visualizer should not be embed. Type: Boolean
+ */
+ public final static String META_NOEMBED = "no-embed";
+
+ /**
* Flag to signal default visibility of a visualizer. Type: Boolean
*/
public static final String META_VISIBLE_DEFAULT = "visible-default";
@@ -105,6 +110,11 @@ public class VisualizationTask extends AnyMap<String> implements Cloneable, Resu
public static final String META_TOOL = "tool";
/**
+ * Indicate whether this task has options.
+ */
+ public static final String META_HAS_OPTIONS = "has-options";
+
+ /**
* Background layer
*/
public final static int LEVEL_BACKGROUND = 0;
@@ -324,7 +334,7 @@ public class VisualizationTask extends AnyMap<String> implements Cloneable, Resu
Integer level1 = this.get(VisualizationTask.META_LEVEL, Integer.class);
Integer level2 = other.get(VisualizationTask.META_LEVEL, Integer.class);
if(level1 != null && level2 != null && level1 != level2) {
- return level2 - level1;
+ return level1 - level2;
}
// sort by name otherwise.
String name1 = this.getShortName();
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/VisualizerContext.java b/src/de/lmu/ifi/dbs/elki/visualization/VisualizerContext.java
index 532e7de5..663670e0 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,15 +25,20 @@ package de.lmu.ifi.dbs.elki.visualization;
import java.util.Collection;
import java.util.List;
-import java.util.regex.Pattern;
import javax.swing.event.EventListenerList;
import de.lmu.ifi.dbs.elki.algorithm.clustering.trivial.ByLabelHierarchicalClustering;
+import de.lmu.ifi.dbs.elki.algorithm.clustering.trivial.TrivialAllInOne;
import de.lmu.ifi.dbs.elki.data.Clustering;
+import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.data.model.Model;
+import de.lmu.ifi.dbs.elki.data.type.NoSupportedDataTypeException;
+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.DataStoreEvent;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreListener;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.result.DBIDSelection;
import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
@@ -42,15 +47,13 @@ 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.result.SelectionResult;
-import de.lmu.ifi.dbs.elki.utilities.datastructures.AnyMap;
-import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
import de.lmu.ifi.dbs.elki.visualization.projector.ProjectorFactory;
+import de.lmu.ifi.dbs.elki.visualization.style.ClusterStylingPolicy;
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.style.StyleResult;
import de.lmu.ifi.dbs.elki.visualization.visualizers.VisFactory;
import de.lmu.ifi.dbs.elki.visualization.visualizers.VisualizerUtil;
-import de.lmu.ifi.dbs.elki.visualization.visualizers.events.ContextChangeListener;
-import de.lmu.ifi.dbs.elki.visualization.visualizers.events.ContextChangedEvent;
/**
* Map to store context information for the visualizer. This can be any data
@@ -58,6 +61,8 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.events.ContextChangedEvent;
*
* @author Erich Schubert
*
+ * TODO: remove this class
+ *
* @apiviz.landmark
* @apiviz.uses ContextChangedEvent oneway - - «emit»
* @apiviz.composedOf StyleLibrary
@@ -65,12 +70,7 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.events.ContextChangedEvent;
* @apiviz.composedOf ResultHierarchy
* @apiviz.composedOf EventListenerList
*/
-public class VisualizerContext extends AnyMap<String> implements DataStoreListener, ResultListener, Result {
- /**
- * Serial version.
- */
- private static final long serialVersionUID = 1L;
-
+public class VisualizerContext implements DataStoreListener, Result {
/**
* Logger.
*/
@@ -102,29 +102,14 @@ public class VisualizerContext extends AnyMap<String> implements DataStoreListen
private Collection<VisFactory> factories;
/**
- * Visualizers to hide by default
+ * Selection result
*/
- private Pattern hideVisualizers;
+ private SelectionResult selection;
/**
- * Identifier for the primary clustering to use.
+ * Styling result
*/
- public static final String CLUSTERING = "clustering";
-
- /**
- * Identifier for a fallback (default) clustering.
- */
- public static final String CLUSTERING_FALLBACK = "clustering-fallback";
-
- /**
- * Identifier for the visualizer list
- */
- public static final String VISUALIZER_LIST = "visualizers";
-
- /**
- * Identifier for the selection
- */
- public static final String SELECTION = "selection";
+ private StyleResult styleresult;
/**
* Constructor. We currently require a Database and a Result.
@@ -133,35 +118,54 @@ public class VisualizerContext extends AnyMap<String> implements DataStoreListen
* @param stylelib Style library
* @param projectors Projectors to use
* @param factories Visualizer Factories to use
- * @param hideVisualizers Pattern to hide visualizers
*/
- public VisualizerContext(HierarchicalResult result, StyleLibrary stylelib, Collection<ProjectorFactory> projectors, Collection<VisFactory> factories, Pattern hideVisualizers) {
+ public VisualizerContext(HierarchicalResult result, StyleLibrary stylelib, Collection<ProjectorFactory> projectors, Collection<VisFactory> factories) {
super();
this.result = result;
this.stylelib = stylelib;
this.projectors = projectors;
this.factories = factories;
- this.hideVisualizers = hideVisualizers;
-
- List<Clustering<? extends Model>> clusterings = ResultUtil.getClusteringResults(result);
- if(clusterings.size() > 0) {
- this.put(CLUSTERING, clusterings.get(0));
- }
- List<SelectionResult> selections = ResultUtil.filterResults(result, SelectionResult.class);
- if(selections.size() > 0) {
- this.put(SELECTION, selections.get(0));
+ // Ensure that various common results needed by visualizers are
+ // automatically created
+ final Database db = ResultUtil.findDatabase(result);
+ ResultUtil.ensureClusteringResult(db, result);
+ this.selection = ResultUtil.ensureSelectionResult(db);
+ for(Relation<?> rel : ResultUtil.getRelations(result)) {
+ ResultUtil.getSamplingResult(rel);
+ // FIXME: this is a really ugly workaround. :-(
+ if(TypeUtil.NUMBER_VECTOR_FIELD.isAssignableFromType(rel.getDataTypeInformation())) {
+ @SuppressWarnings("unchecked")
+ Relation<? extends NumberVector<?, ?>> vrel = (Relation<? extends NumberVector<?, ?>>) rel;
+ ResultUtil.getScalesResult(vrel);
+ }
}
+ getStyleResult();
- result.getHierarchy().add(result, this);
+ // result.getHierarchy().add(result, this);
// Add visualizers.
processNewResult(result, result);
// For proxying events.
ResultUtil.findDatabase(result).addDataStoreListener(this);
- // Add ourselves as RL
- addResultListener(this);
+ // Add a result listener. Don't expose these methods to avoid inappropriate use.
+ addResultListener(new ResultListener() {
+ @Override
+ public void resultAdded(Result child, Result parent) {
+ processNewResult(getResult(), child);
+ }
+
+ @Override
+ public void resultChanged(Result current) {
+ // FIXME: need to do anything?
+ }
+
+ @Override
+ public void resultRemoved(Result child, Result parent) {
+ // FIXME: implement
+ }
+ });
}
/**
@@ -195,20 +199,25 @@ public class VisualizerContext extends AnyMap<String> implements DataStoreListen
}
/**
- * Convenience method to get the clustering to use, and fall back to a default
- * "clustering".
+ * Get the style result.
*
- * @return Clustering to use
+ * @return Style result
*/
- public Clustering<Model> getOrCreateDefaultClustering() {
- Clustering<Model> c = getGenerics(CLUSTERING, Clustering.class);
- if(c == null) {
- c = getGenerics(CLUSTERING_FALLBACK, Clustering.class);
- }
- if(c == null) {
- c = generateDefaultClustering();
+ public StyleResult getStyleResult() {
+ if(styleresult == null) {
+ styleresult = new StyleResult();
+ List<Clustering<? extends Model>> clusterings = ResultUtil.getClusteringResults(result);
+ if(clusterings.size() > 0) {
+ styleresult.setStylingPolicy(new ClusterStylingPolicy(clusterings.get(0), stylelib));
+ result.getHierarchy().add(result, styleresult);
+ return styleresult;
+ }
+ Clustering<Model> c = generateDefaultClustering();
+ styleresult.setStylingPolicy(new ClusterStylingPolicy(c, stylelib));
+ result.getHierarchy().add(result, styleresult);
+ return styleresult;
}
- return c;
+ return styleresult;
}
/**
@@ -217,11 +226,17 @@ public class VisualizerContext extends AnyMap<String> implements DataStoreListen
* @return generated clustering
*/
private Clustering<Model> generateDefaultClustering() {
- // Cluster by labels
- ByLabelHierarchicalClustering split = new ByLabelHierarchicalClustering();
- Clustering<Model> c = split.run(ResultUtil.findDatabase(getResult()));
- // store.
- put(CLUSTERING_FALLBACK, c);
+ final Database db = ResultUtil.findDatabase(getResult());
+ Clustering<Model> c = null;
+ try {
+ // Try to cluster by labels
+ ByLabelHierarchicalClustering split = new ByLabelHierarchicalClustering();
+ c = split.run(db);
+ }
+ catch(NoSupportedDataTypeException e) {
+ // Put everything into one
+ c = new TrivialAllInOne().run(db);
+ }
return c;
}
@@ -233,11 +248,7 @@ public class VisualizerContext extends AnyMap<String> implements DataStoreListen
* @return selection
*/
public DBIDSelection getSelection() {
- SelectionResult res = getGenerics(SELECTION, SelectionResult.class);
- if(res != null) {
- return res.getSelection();
- }
- return null;
+ return selection.getSelection();
}
/**
@@ -246,9 +257,8 @@ public class VisualizerContext extends AnyMap<String> implements DataStoreListen
* @param sel Selection
*/
public void setSelection(DBIDSelection sel) {
- SelectionResult selres = getGenerics(SELECTION, SelectionResult.class);
- selres.setSelection(sel);
- getHierarchy().resultChanged(selres);
+ selection.setSelection(sel);
+ getHierarchy().resultChanged(selection);
}
/**
@@ -258,49 +268,12 @@ public class VisualizerContext extends AnyMap<String> implements DataStoreListen
*
* @param task Visualization task
* @param visibility new visibility
- */
- public void setVisualizationVisibility(VisualizationTask task, boolean visibility) {
- // Hide other tools
- if(visibility && VisualizerUtil.isTool(task)) {
- final Iterable<VisualizationTask> visualizers = ResultUtil.filteredResults(getResult(), VisualizationTask.class);
- for(VisualizationTask other : visualizers) {
- if(other != task && VisualizerUtil.isTool(other) && VisualizerUtil.isVisible(other)) {
- other.put(VisualizationTask.META_VISIBLE, false);
- getHierarchy().resultChanged(other);
- }
- }
- }
- task.put(VisualizationTask.META_VISIBLE, visibility);
- getHierarchy().resultChanged(task);
- }
-
- /**
- * Add a context change listener.
- *
- * @param listener
- */
- public void addContextChangeListener(ContextChangeListener listener) {
- listenerList.add(ContextChangeListener.class, listener);
- }
-
- /**
- * Remove a context change listener.
- *
- * @param listener
- */
- public void removeContextChangeListener(ContextChangeListener listener) {
- listenerList.remove(ContextChangeListener.class, listener);
- }
-
- /**
- * Trigger a context change event.
*
- * @param e Event
+ * @deprecated Use {@link VisualizerUtil#setVisible}
*/
- public void fireContextChange(ContextChangedEvent e) {
- for(ContextChangeListener listener : listenerList.getListeners(ContextChangeListener.class)) {
- listener.contextChanged(e);
- }
+ @Deprecated
+ public void setVisualizationVisibility(VisualizationTask task, boolean visibility) {
+ VisualizerUtil.setVisible(this, task, visibility);
}
/**
@@ -342,9 +315,6 @@ public class VisualizerContext extends AnyMap<String> implements DataStoreListen
*/
private void processNewResult(HierarchicalResult baseResult, Result newResult) {
for(ProjectorFactory p : projectors) {
- if(hideVisualizers != null && hideVisualizers.matcher(p.getClass().getName()).find()) {
- continue;
- }
try {
p.processNewResult(baseResult, newResult);
}
@@ -354,9 +324,6 @@ public class VisualizerContext extends AnyMap<String> implements DataStoreListen
}
// Collect all visualizers.
for(VisFactory f : factories) {
- if(hideVisualizers != null && hideVisualizers.matcher(f.getClass().getName()).find()) {
- continue;
- }
try {
f.processNewResult(baseResult, newResult);
}
@@ -367,18 +334,6 @@ public class VisualizerContext extends AnyMap<String> implements DataStoreListen
}
/**
- * Get an iterator over all visualizers.
- *
- * @return Iterator
- *
- * @deprecated Odd semantics: contains duplicates!
- */
- @Deprecated
- public IterableIterator<VisualizationTask> iterVisualizers() {
- return ResultUtil.filteredResults(getResult(), VisualizationTask.class);
- }
-
- /**
* Register a result listener.
*
* @param listener Result listener.
@@ -397,21 +352,6 @@ public class VisualizerContext extends AnyMap<String> implements DataStoreListen
}
@Override
- public void resultAdded(Result child, Result parent) {
- processNewResult(getResult(), child);
- }
-
- @Override
- public void resultChanged(Result current) {
- // FIXME: need to do anything?
- }
-
- @Override
- public void resultRemoved(Result child, Result parent) {
- // FIXME: implement
- }
-
- @Override
public String getLongName() {
return "Visualizer context";
}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/VisualizerParameterizer.java b/src/de/lmu/ifi/dbs/elki/visualization/VisualizerParameterizer.java
index 7f4dc15d..8e0be062 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,16 +26,21 @@ package de.lmu.ifi.dbs.elki.visualization;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Iterator;
import java.util.List;
+import java.util.Random;
import java.util.regex.Pattern;
import de.lmu.ifi.dbs.elki.algorithm.AbstractDistanceBasedAlgorithm;
import de.lmu.ifi.dbs.elki.database.Database;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.datasource.FileBasedDatabaseConnection;
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.result.SamplingResult;
import de.lmu.ifi.dbs.elki.result.SettingsResult;
import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
import de.lmu.ifi.dbs.elki.utilities.InspectionUtil;
@@ -44,8 +49,10 @@ 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.WrongParameterValueException;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GreaterEqualConstraint;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.MergedParameterization;
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.Parameter;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.PatternParameter;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.StringParameter;
@@ -83,20 +90,29 @@ public class VisualizerParameterizer implements Parameterizable {
public final static OptionID STYLELIB_ID = OptionID.getOrCreateOptionID("visualizer.stylesheet", "Style properties file to use");
/**
- * Default pattern for visualizer disabling.
+ * Default pattern for visualizer enabling.
*/
- public final static String DEFAULT_HIDEVIS = "^experimentalcode\\..*";
+ public final static String DEFAULT_ENABLEVIS = "^" + Pattern.quote(VisualizerParameterizer.class.getPackage().getName()) + "\\..*";
/**
- * Parameter to disable visualizers
+ * Parameter to enable visualizers
*
* <p>
- * Key: -vis.hide
+ * Key: -vis.enable
*
- * Default: default properties file
+ * Default: ELKI core
* </p>
*/
- public final static OptionID HIDEVIS_ID = OptionID.getOrCreateOptionID("vis.hide", "Visualizers to not show by default. Use 'none' to not hide any by default.");
+ public final static OptionID ENABLEVIS_ID = OptionID.getOrCreateOptionID("vis.enable", "Visualizers to enable by default.");
+
+ /**
+ * Parameter to set the sampling level
+ *
+ * <p>
+ * Key: -vis.sampling
+ * </p>
+ */
+ public final static OptionID SAMPLING_ID = OptionID.getOrCreateOptionID("vis.sampling", "Maximum number of objects to visualize by default (for performance reasons).");
/**
* Style library to use.
@@ -109,29 +125,37 @@ public class VisualizerParameterizer implements Parameterizable {
private Collection<VisFactory> factories;
/**
- * Visualizer disabling pattern
+ * Projectors to use.
*/
- private Pattern hideVisualizers = null;
+ private Collection<ProjectorFactory> projectors;
/**
- * Projectors to use.
+ * Sample size
*/
- private Collection<ProjectorFactory> projectors;
+ private int samplesize = -1;
+
+ /**
+ * Random seed for sampling.
+ *
+ * FIXME: make parameterizable.
+ */
+ private long seed = new Random().nextLong();
/**
* Constructor.
*
+ * @param samplesize
* @param stylelib Style library
* @param projectors Projectors
* @param factories Factories to use
* @param hideVisualizers Visualizer hiding pattern
*/
- public VisualizerParameterizer(StyleLibrary stylelib, Collection<ProjectorFactory> projectors, Collection<VisFactory> factories, Pattern hideVisualizers) {
+ public VisualizerParameterizer(int samplesize, StyleLibrary stylelib, Collection<ProjectorFactory> projectors, Collection<VisFactory> factories, Pattern hideVisualizers) {
super();
+ this.samplesize = samplesize;
this.stylelib = stylelib;
this.projectors = projectors;
this.factories = factories;
- this.hideVisualizers = hideVisualizers;
}
/**
@@ -141,7 +165,22 @@ public class VisualizerParameterizer implements Parameterizable {
* @return New context
*/
public VisualizerContext newContext(HierarchicalResult result) {
- VisualizerContext context = new VisualizerContext(result, stylelib, projectors, factories, hideVisualizers);
+ VisualizerContext context = new VisualizerContext(result, stylelib, projectors, factories);
+ if(samplesize > 0) {
+ Iterator<Relation<?>> iter = ResultUtil.filteredResults(result, Relation.class);
+ while(iter.hasNext()) {
+ Relation<?> rel = iter.next();
+ if(ResultUtil.filteredResults(rel, SamplingResult.class).hasNext()) {
+ continue;
+ }
+ int size = rel.size();
+ if(size > samplesize) {
+ SamplingResult sample = new SamplingResult(rel);
+ sample.setSample(DBIDUtil.randomSample(sample.getSample(), samplesize, seed));
+ ResultUtil.addChildResult(rel, sample);
+ }
+ }
+ }
return context;
}
@@ -216,15 +255,21 @@ public class VisualizerParameterizer implements Parameterizable {
public static class Parameterizer extends AbstractParameterizer {
protected StyleLibrary stylelib = null;
- protected Pattern hideVisualizers = null;
+ protected Pattern enableVisualizers = null;
protected Collection<VisFactory> factories = null;
protected Collection<ProjectorFactory> projectors = null;
+ protected int samplesize = -1;
+
@Override
protected void makeOptions(Parameterization config) {
super.makeOptions(config);
+ IntParameter samplingP = new IntParameter(SAMPLING_ID, new GreaterEqualConstraint(-1), 10000);
+ if(config.grab(samplingP)) {
+ samplesize = samplingP.getValue();
+ }
StringParameter stylelibP = new StringParameter(STYLELIB_ID, PropertiesBasedStyleLibrary.DEFAULT_SCHEME_FILENAME);
if(config.grab(stylelibP)) {
String filename = stylelibP.getValue();
@@ -235,33 +280,42 @@ public class VisualizerParameterizer implements Parameterizable {
config.reportError(new WrongParameterValueException(stylelibP, filename, e));
}
}
- PatternParameter hidevisP = new PatternParameter(HIDEVIS_ID, DEFAULT_HIDEVIS);
- if(config.grab(hidevisP)) {
- if(!"none".equals(hidevisP.getValueAsString())) {
- hideVisualizers = hidevisP.getValue();
+ PatternParameter enablevisP = new PatternParameter(ENABLEVIS_ID, DEFAULT_ENABLEVIS);
+ if(config.grab(enablevisP)) {
+ if(!"all".equals(enablevisP.getValueAsString())) {
+ enableVisualizers = enablevisP.getValue();
}
}
MergedParameterization merged = new MergedParameterization(config);
- projectors = collectProjectorFactorys(merged);
- factories = collectVisFactorys(merged);
+ projectors = collectProjectorFactorys(merged, enableVisualizers);
+ factories = collectVisFactorys(merged, enableVisualizers);
}
/**
* Collect and instantiate all projector factories.
*
* @param config Parameterization
+ * @param filter Filter
* @return List of all adapters found.
*/
- private static <O> Collection<ProjectorFactory> collectProjectorFactorys(MergedParameterization config) {
+ private static <O> Collection<ProjectorFactory> collectProjectorFactorys(MergedParameterization config, Pattern filter) {
ArrayList<ProjectorFactory> factories = new ArrayList<ProjectorFactory>();
for(Class<?> c : InspectionUtil.cachedFindAllImplementations(ProjectorFactory.class)) {
+ if(filter != null && !filter.matcher(c.getCanonicalName()).find()) {
+ continue;
+ }
try {
config.rewind();
ProjectorFactory a = ClassGenericsUtil.tryInstantiate(ProjectorFactory.class, c, config);
factories.add(a);
}
catch(Throwable e) {
- logger.exception("Error instantiating visualization factory " + c.getName(), e);
+ if(logger.isDebugging()) {
+ logger.exception("Error instantiating visualization factory " + c.getName(), e.getCause());
+ }
+ else {
+ logger.warning("Error instantiating visualization factory " + c.getName() + ": " + e.getMessage());
+ }
}
}
return factories;
@@ -271,18 +325,27 @@ public class VisualizerParameterizer implements Parameterizable {
* Collect and instantiate all visualizer factories.
*
* @param config Parameterization
+ * @param filter Filter
* @return List of all adapters found.
*/
- private static <O> Collection<VisFactory> collectVisFactorys(MergedParameterization config) {
+ private static <O> Collection<VisFactory> collectVisFactorys(MergedParameterization config, Pattern filter) {
ArrayList<VisFactory> factories = new ArrayList<VisFactory>();
for(Class<?> c : InspectionUtil.cachedFindAllImplementations(VisFactory.class)) {
+ if(filter != null && !filter.matcher(c.getCanonicalName()).find()) {
+ continue;
+ }
try {
config.rewind();
VisFactory a = ClassGenericsUtil.tryInstantiate(VisFactory.class, c, config);
factories.add(a);
}
catch(Throwable e) {
- logger.exception("Error instantiating visualization factory " + c.getName(), e);
+ if(logger.isDebugging()) {
+ logger.exception("Error instantiating visualization factory " + c.getName(), e.getCause());
+ }
+ else {
+ logger.warning("Error instantiating visualization factory " + c.getName() + ": " + e.getMessage());
+ }
}
}
return factories;
@@ -290,7 +353,7 @@ public class VisualizerParameterizer implements Parameterizable {
@Override
protected VisualizerParameterizer makeInstance() {
- return new VisualizerParameterizer(stylelib, projectors, factories, hideVisualizers);
+ return new VisualizerParameterizer(samplesize, stylelib, projectors, factories, enableVisualizers);
}
}
} \ No newline at end of file
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 068b538a..0e2db37d 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) 2011
+ Copyright (C) 2012
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 f1e62754..f52951d7 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) 2011
+ Copyright (C) 2012
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 f219a0ba..4f9781e7 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) 2011
+ Copyright (C) 2012
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 d65256c0..3e9f355a 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) 2011
+ Copyright (C) 2012
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
new file mode 100644
index 00000000..a1dd3ba1
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/CloneInlineImages.java
@@ -0,0 +1,143 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.image.renderable.RenderableImage;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+
+import org.apache.batik.svggen.SVGSyntax;
+import org.apache.batik.util.Base64EncoderStream;
+import org.apache.batik.util.ParsedURL;
+import org.apache.batik.util.SVGConstants;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
+import de.lmu.ifi.dbs.elki.visualization.svg.SVGCloneVisible;
+
+/**
+ * Clone an SVG document, inlining temporary and in-memory linked images.
+ *
+ * @author Erich Schubert
+ *
+ */
+public class CloneInlineImages extends SVGCloneVisible {
+ @Override
+ public Node cloneNode(Document doc, Node eold) {
+ Node enew = null;
+ if(eold instanceof Element) {
+ Element e = (Element) eold;
+ if(e.getTagName().equals(SVGConstants.SVG_IMAGE_TAG)) {
+ String url = e.getAttributeNS(SVGConstants.XLINK_NAMESPACE_URI, SVGConstants.XLINK_HREF_ATTRIBUTE);
+ ParsedURL urldata = new ParsedURL(url);
+ if(ThumbnailRegistryEntry.isCompatibleURLStatic(urldata)) {
+ enew = inlineThumbnail(doc, urldata, eold);
+ }
+ else if("file".equals(urldata.getProtocol())) {
+ enew = inlineExternal(doc, urldata, eold);
+ }
+ }
+ }
+ if(enew != null) {
+ return enew;
+ }
+ return super.cloneNode(doc, eold);
+ }
+
+ /**
+ * Inline a referenced thumbnail.
+ *
+ * @param doc Document (element factory)
+ * @param urldata URL
+ * @param eold Existing node
+ * @return Replacement node, or {@code null}
+ */
+ protected Node inlineThumbnail(Document doc, ParsedURL urldata, Node eold) {
+ RenderableImage img = ThumbnailRegistryEntry.handleURL(urldata);
+ if(img == null) {
+ LoggingUtil.warning("Image not found in registry: " + urldata.toString());
+ return null;
+ }
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ try {
+ os.write(SVGSyntax.DATA_PROTOCOL_PNG_PREFIX.getBytes());
+ Base64EncoderStream encoder = new Base64EncoderStream(os);
+ ImageIO.write(img.createDefaultRendering(), "png", encoder);
+ encoder.close();
+ }
+ catch(IOException e) {
+ LoggingUtil.exception("Exception serializing image to png", e);
+ return null;
+ }
+ Element i = (Element) super.cloneNode(doc, eold);
+ i.setAttributeNS(SVGConstants.XLINK_NAMESPACE_URI, SVGConstants.XLINK_HREF_ATTRIBUTE, os.toString().replaceAll("\\s*[\\r\\n]+\\s*", ""));
+ return i;
+ }
+
+ /**
+ * Inline an external file (usually from temp).
+ *
+ * @param doc Document (element factory)
+ * @param urldata URL
+ * @param eold Existing node
+ * @return Replacement node, or {@code null}
+ */
+ protected Node inlineExternal(Document doc, ParsedURL urldata, Node eold) {
+ File in = new File(urldata.getPath());
+ if(!in.exists()) {
+ LoggingUtil.warning("Referencing non-existant file: " + urldata.toString());
+ return null;
+ }
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ try {
+ os.write(SVGSyntax.DATA_PROTOCOL_PNG_PREFIX.getBytes());
+ Base64EncoderStream encoder = new Base64EncoderStream(os);
+ FileInputStream instream = new FileInputStream(in);
+ byte[] buf = new byte[4096];
+ while(true) {
+ int read = instream.read(buf, 0, buf.length);
+ if(read <= 0) {
+ break;
+ }
+ encoder.write(buf, 0, read);
+ }
+ instream.close();
+ encoder.close();
+ }
+ catch(IOException e) {
+ LoggingUtil.exception("Exception serializing image to png", e);
+ return null;
+ }
+
+ Element i = (Element) super.cloneNode(doc, eold);
+ i.setAttributeNS(SVGConstants.XLINK_NAMESPACE_URI, SVGConstants.XLINK_HREF_ATTRIBUTE, os.toString().replaceAll("\\s*[\\r\\n]+\\s*", ""));
+ return i;
+ }
+} \ No newline at end of file
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 978aec29..42dab91b 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) 2011
+ Copyright (C) 2012
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/JSVGSynchronizedCanvas.java b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/JSVGSynchronizedCanvas.java
index a9e467db..7629ae1a 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) 2011
+ Copyright (C) 2012
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 0ecb6e0e..953c39da 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) 2011
+ Copyright (C) 2012
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/LazyCanvasResizer.java b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/LazyCanvasResizer.java
index d11e1b00..b0dbfd9c 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) 2011
+ Copyright (C) 2012
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 69282a5a..380d2cbf 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) 2011
+ Copyright (C) 2012
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 0b5049cb..f0fb08c5 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) 2011
+ Copyright (C) 2012
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 51b1fec8..a82025df 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) 2011
+ Copyright (C) 2012
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 9c16a2db..2f75d40e 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) 2011
+ Copyright (C) 2012
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
new file mode 100644
index 00000000..dd844165
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/ThumbnailRegistryEntry.java
@@ -0,0 +1,249 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.awt.image.RenderedImage;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.ref.SoftReference;
+import java.util.Iterator;
+
+import org.apache.batik.ext.awt.image.GraphicsUtil;
+import org.apache.batik.ext.awt.image.renderable.Filter;
+import org.apache.batik.ext.awt.image.renderable.RedRable;
+import org.apache.batik.ext.awt.image.spi.AbstractRegistryEntry;
+import org.apache.batik.ext.awt.image.spi.ImageTagRegistry;
+import org.apache.batik.ext.awt.image.spi.MagicNumberRegistryEntry;
+import org.apache.batik.ext.awt.image.spi.URLRegistryEntry;
+import org.apache.batik.svggen.ErrorConstants;
+import org.apache.batik.util.ParsedURL;
+import org.apache.batik.util.ParsedURLData;
+import org.apache.batik.util.ParsedURLProtocolHandler;
+
+import de.lmu.ifi.dbs.elki.logging.Logging;
+
+/**
+ * Access images via an internal image registry.
+ *
+ * @author Erich Schubert
+ */
+public class ThumbnailRegistryEntry extends AbstractRegistryEntry implements URLRegistryEntry, ParsedURLProtocolHandler {
+ /**
+ * ELKI internal thumbnail protocol id.
+ */
+ public static final String INTERNAL_PROTOCOL = "thumb";
+
+ /**
+ * ELKI internal thumbnail protocol prefix
+ */
+ public static final String INTERNAL_PREFIX = INTERNAL_PROTOCOL + ":";
+
+ /**
+ * Mime type
+ */
+ public static final String INTERNAL_MIME_TYPE = "internal/thumb";
+
+ /**
+ * The priority of this entry.
+ */
+ public static final float PRIORITY = 1 * MagicNumberRegistryEntry.PRIORITY;
+
+ /**
+ * The logger class.
+ */
+ private static final Logging logger = Logging.getLogger(ThumbnailRegistryEntry.class);
+
+ /**
+ * The image cache.
+ */
+ private static final TIntObjectMap<SoftReference<RenderedImage>> images = new TIntObjectHashMap<SoftReference<RenderedImage>>();
+
+ /**
+ * Object counter
+ */
+ private static int counter = 1;
+
+ /**
+ * Constructor.
+ *
+ * Note: there will usually be two instances created. One for handling the
+ * image type, one for the URL handling. This is ok.
+ */
+ public ThumbnailRegistryEntry() {
+ super("Internal", PRIORITY, new String[0], new String[] { INTERNAL_MIME_TYPE });
+ if(logger.isDebuggingFiner()) {
+ logger.debugFiner("Registry initialized.");
+ }
+ }
+
+ /**
+ * Put an image into the repository (note: the repository is only keeping a
+ * weak reference!)
+ *
+ * @param img Image to put
+ * @return Key
+ */
+ public static int registerImage(RenderedImage img) {
+ synchronized(images) {
+ int key = counter;
+ counter++;
+ assert (images.get(key) == null);
+ images.put(key, new SoftReference<RenderedImage>(img));
+ // Reorganize map, purge old entries
+ if(counter % 50 == 49) {
+ for(TIntObjectIterator<SoftReference<RenderedImage>> iter = images.iterator(); iter.hasNext();) {
+ iter.advance();
+ if(iter.value() == null || iter.value().get() == null) {
+ iter.remove();
+ }
+ }
+ }
+ if(logger.isDebuggingFiner()) {
+ logger.debugFiner("Registered image: " + key);
+ }
+ return key;
+ }
+ }
+
+ @Override
+ public boolean isCompatibleURL(ParsedURL url) {
+ // logger.warning("isCompatible " + url.toString());
+ return isCompatibleURLStatic(url);
+ }
+
+ /**
+ * Test for a compatible URL.
+ *
+ * @param url URL
+ * @return Success code
+ */
+ public static boolean isCompatibleURLStatic(ParsedURL url) {
+ return url.getProtocol().equals(INTERNAL_PROTOCOL);
+ }
+
+ @Override
+ public Filter handleURL(ParsedURL url, boolean needRawData) {
+ Filter ret = handleURL(url);
+ if(ret != null) {
+ return ret;
+ }
+ // Image not found in registry.
+ return ImageTagRegistry.getBrokenLinkImage(ThumbnailRegistryEntry.this, ErrorConstants.ERR_IMAGE_DIR_DOES_NOT_EXIST, new Object[0]);
+ }
+
+ /**
+ * Statically handle the URL access.
+ *
+ * @param url URL to access
+ * @return Image, or null
+ */
+ public static Filter handleURL(ParsedURL url) {
+ if(logger.isDebuggingFiner()) {
+ logger.debugFiner("handleURL " + url.toString());
+ }
+ if(!isCompatibleURLStatic(url)) {
+ return null;
+ }
+ int id;
+ try {
+ id = Integer.parseInt(url.getPath());
+ }
+ catch(NumberFormatException e) {
+ return null;
+ }
+ SoftReference<RenderedImage> ref = images.get(id);
+ if(ref != null) {
+ RenderedImage ri = ref.get();
+ if(ri == null) {
+ logger.warning("Referenced image has expired from the cache!");
+ }
+ else {
+ return new RedRable(GraphicsUtil.wrap(ri));
+ }
+ }
+ // Image not found in registry.
+ return null;
+ }
+
+ /**
+ * URL representation for internal URLs.
+ *
+ * @author Erich Schubert
+ */
+ class InternalParsedURLData extends ParsedURLData {
+ /**
+ * Constructor.
+ */
+ public InternalParsedURLData(String id) {
+ super();
+ this.protocol = INTERNAL_PROTOCOL;
+ this.contentType = INTERNAL_MIME_TYPE;
+ this.path = id;
+ }
+
+ @Override
+ public String getContentType(String userAgent) {
+ return INTERNAL_MIME_TYPE;
+ }
+
+ @Override
+ public boolean complete() {
+ return true;
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ public InputStream openStream(String userAgent, Iterator mimeTypes) throws IOException {
+ // Return null, since we don't want to use streams.
+ return null;
+ }
+ }
+
+ @Override
+ public ParsedURLData parseURL(String urlStr) {
+ if(logger.isDebuggingFinest()) {
+ logger.debugFinest("parseURL: " + urlStr);
+ }
+ if(urlStr.startsWith(INTERNAL_PREFIX)) {
+ InternalParsedURLData ret = new InternalParsedURLData(urlStr.substring(INTERNAL_PREFIX.length()));
+ return ret;
+ }
+ return null;
+ }
+
+ @Override
+ public ParsedURLData parseURL(ParsedURL basepurl, String urlStr) {
+ // Won't happen in a relative way anyway, and is not particularly
+ // supported (as the objects might be dropped from the cache)
+ return parseURL(urlStr);
+ }
+
+ @Override
+ public String getProtocolHandled() {
+ return INTERNAL_PROTOCOL;
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/batikutil/ThumbnailTranscoder.java b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/ThumbnailTranscoder.java
new file mode 100644
index 00000000..0b2a2080
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/batikutil/ThumbnailTranscoder.java
@@ -0,0 +1,72 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.image.BufferedImage;
+
+import org.apache.batik.transcoder.TranscoderException;
+import org.apache.batik.transcoder.TranscoderOutput;
+import org.apache.batik.transcoder.image.ImageTranscoder;
+
+/**
+ * Transcode images to in-memory thumbnails.
+ *
+ * @author Erich Schubert
+ */
+public class ThumbnailTranscoder extends ImageTranscoder {
+ /**
+ * Last image produced.
+ */
+ private BufferedImage lastimg;
+
+ /**
+ * Constructor.
+ */
+ public ThumbnailTranscoder() {
+ super();
+ hints.put(KEY_FORCE_TRANSPARENT_WHITE, Boolean.FALSE);
+ }
+
+ @Override
+ public BufferedImage createImage(int width, int height) {
+ return new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+ }
+
+ /**
+ * Output will be ignored!
+ */
+ @Override
+ public void writeImage(BufferedImage img, TranscoderOutput output) throws TranscoderException {
+ lastimg = img;
+ }
+
+ /**
+ * Get the latest image produced.
+ *
+ * @return the last image produced
+ */
+ public BufferedImage getLastImage() {
+ return lastimg;
+ }
+} \ No newline at end of file
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 80a68b29..333b8b0c 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) 2011
+Copyright (C) 2012
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 0741d9b3..2693bc6b 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) 2011
+ Copyright (C) 2012
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 4785fb87..83956102 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -54,7 +54,7 @@ public class ListBasedColorLibrary implements ColorLibrary {
@Override
public String getColor(int index) {
- return colors[index % colors.length];
+ return colors[Math.abs(index) % colors.length];
}
@Override
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 9458e458..ef4a2c64 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) 2011
+Copyright (C) 2012
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 33dfe5f4..5c89f638 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) 2011
+ Copyright (C) 2012
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/CSSClassManager.java b/src/de/lmu/ifi/dbs/elki/visualization/css/CSSClassManager.java
index de527e4e..22e53c55 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) 2011
+ Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/css/package-info.java
index bbe09653..21290f26 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) 2011
+Copyright (C) 2012
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 aa5cd2b4..2c3db308 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) 2011
+ Copyright (C) 2012
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.gui;
import javax.swing.JFrame;
-import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
import de.lmu.ifi.dbs.elki.result.Result;
@@ -34,6 +33,7 @@ import de.lmu.ifi.dbs.elki.result.ResultUtil;
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.StringParameter;
import de.lmu.ifi.dbs.elki.visualization.VisualizerContext;
import de.lmu.ifi.dbs.elki.visualization.VisualizerParameterizer;
@@ -48,8 +48,6 @@ import de.lmu.ifi.dbs.elki.visualization.VisualizerParameterizer;
* @apiviz.uses ResultWindow oneway
*/
public class ResultVisualizer implements ResultHandler {
- // TODO: move title/maxdim parameters into a layouter class.
-
/**
* Get a logger for this class.
*/
@@ -67,6 +65,15 @@ public class ResultVisualizer implements ResultHandler {
public static final OptionID WINDOW_TITLE_ID = OptionID.getOrCreateOptionID("vis.window.title", "Title to use for visualization window.");
/**
+ * Flag to set single display
+ *
+ * <p>
+ * Key: -vis.single
+ * </p>
+ */
+ public final static OptionID SINGLE_ID = OptionID.getOrCreateOptionID("vis.window.single", "Embed visualizers in a single window, not using thumbnails and detail views.");
+
+ /**
* Stores the set title.
*/
String title;
@@ -82,28 +89,31 @@ public class ResultVisualizer implements ResultHandler {
VisualizerParameterizer manager;
/**
+ * Single view mode
+ */
+ boolean single;
+
+ /**
* Constructor.
*
- * @param title
- * @param manager
+ * @param title Window title
+ * @param manager Parameterization manager for visualizers
+ * @param single Flag to indicat single-view mode.
*/
- public ResultVisualizer(String title, VisualizerParameterizer manager) {
+ public ResultVisualizer(String title, VisualizerParameterizer manager, boolean single) {
super();
this.title = title;
this.manager = manager;
+ this.single = single;
}
@Override
public void processNewResult(final HierarchicalResult top, final Result result) {
- final Database db = ResultUtil.findDatabase(top);
- ResultUtil.ensureClusteringResult(db, top);
- ResultUtil.ensureSelectionResult(db, db);
-
// FIXME: not really re-entrant to generate new contexts...
final VisualizerContext context = manager.newContext(top);
if(title == null) {
- title = VisualizerParameterizer.getTitle(db, result);
+ title = VisualizerParameterizer.getTitle(ResultUtil.findDatabase(top), result);
}
if(title == null) {
@@ -114,7 +124,7 @@ public class ResultVisualizer implements ResultHandler {
@Override
public void run() {
try {
- ResultWindow window = new ResultWindow(title, top, context);
+ ResultWindow window = new ResultWindow(title, top, context, single);
window.setVisible(true);
window.setExtendedState(window.getExtendedState() | JFrame.MAXIMIZED_BOTH);
window.showOverview();
@@ -143,6 +153,11 @@ public class ResultVisualizer implements ResultHandler {
* Visualization manager.
*/
VisualizerParameterizer manager;
+
+ /**
+ * Single view mode.
+ */
+ boolean single = false;
@Override
protected void makeOptions(Parameterization config) {
@@ -151,13 +166,16 @@ public class ResultVisualizer implements ResultHandler {
if(config.grab(titleP)) {
title = titleP.getValue();
}
-
+ Flag singleF = new Flag(SINGLE_ID);
+ if (config.grab(singleF)) {
+ single = singleF.getValue();
+ }
manager = config.tryInstantiate(VisualizerParameterizer.class);
}
@Override
protected ResultVisualizer makeInstance() {
- return new ResultVisualizer(title, manager);
+ 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 c5bdf408..38476d7d 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -63,6 +63,9 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.VisualizerUtil;
/**
* Swing window to manage a particular result visualization.
*
+ * Yes, this is very basic and ad-hoc. Feel free to contribute something more
+ * advanced to ELKI!
+ *
* @author Erich Schubert
* @author Remigius Wojdanowski
*
@@ -137,16 +140,23 @@ public class ResultWindow extends JFrame implements ResultListener {
private HierarchicalResult result;
/**
+ * Single view mode. No overview / detail view split
+ */
+ private boolean single = false;
+
+ /**
* Constructor.
*
* @param title Window title
* @param result Result to visualize
* @param context Visualizer context
+ * @param single Single visualization mode
*/
- public ResultWindow(String title, HierarchicalResult result, VisualizerContext context) {
+ public ResultWindow(String title, HierarchicalResult result, VisualizerContext context, boolean single) {
super(title);
this.context = context;
this.result = result;
+ this.single = single;
// close handler
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
@@ -158,8 +168,28 @@ public class ResultWindow extends JFrame implements ResultListener {
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 panel = new JPanel(new BorderLayout());
+
+ JMenuBar menubar = new JMenuBar();
+ JMenu filemenu = new JMenu("File");
+ filemenu.setMnemonic(KeyEvent.VK_F);
// setup buttons
+ if(!single) {
+ overviewItem = new JMenuItem("Overview");
+ overviewItem.setMnemonic(KeyEvent.VK_O);
+ overviewItem.setEnabled(false);
+ overviewItem.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent ae) {
+ showOverview();
+ }
+ });
+ filemenu.add(overviewItem);
+ }
+
exportItem = new JMenuItem("Export");
exportItem.setMnemonic(KeyEvent.VK_E);
exportItem.setEnabled(false);
@@ -169,26 +199,8 @@ public class ResultWindow extends JFrame implements ResultListener {
saveCurrentPlot();
}
});
-
- quitItem = new JMenuItem("Quit");
- quitItem.setMnemonic(KeyEvent.VK_Q);
- quitItem.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- close();
- }
- });
-
- overviewItem = new JMenuItem("Overview");
- overviewItem.setMnemonic(KeyEvent.VK_O);
- overviewItem.setEnabled(false);
- overviewItem.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent ae) {
- showOverview();
- }
- });
-
+ filemenu.add(exportItem);
+
editItem = new JMenuItem("Table View/Edit");
editItem.setMnemonic(KeyEvent.VK_T);
editItem.addActionListener(new ActionListener() {
@@ -197,17 +209,18 @@ public class ResultWindow extends JFrame implements ResultListener {
showTableView();
}
});
-
- // Create a panel and add the button, status label and the SVG canvas.
- final JPanel panel = new JPanel(new BorderLayout());
-
- JMenuBar menubar = new JMenuBar();
- JMenu filemenu = new JMenu("File");
- filemenu.setMnemonic(KeyEvent.VK_F);
- filemenu.add(overviewItem);
- filemenu.add(exportItem);
// FIXME: re-add when it is working again.
// filemenu.add(editItem);
+
+ quitItem = new JMenuItem("Quit");
+ quitItem.setMnemonic(KeyEvent.VK_Q);
+ quitItem.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ close();
+ }
+ });
+
filemenu.add(quitItem);
menubar.add(filemenu);
@@ -222,7 +235,7 @@ public class ResultWindow extends JFrame implements ResultListener {
this.getContentPane().add(panel);
- this.overview = new OverviewPlot(result, context);
+ this.overview = new OverviewPlot(result, context, single);
// when a subplot is clicked, show the selected subplot.
overview.addActionListener(new ActionListener() {
@Override
@@ -303,8 +316,10 @@ public class ResultWindow extends JFrame implements ResultListener {
* @param e
*/
protected void showSubplot(DetailViewSelectedEvent e) {
- currentSubplot = e.makeDetailView();
- showPlot(currentSubplot);
+ if(!single) {
+ currentSubplot = e.makeDetailView();
+ showPlot(currentSubplot);
+ }
}
/**
@@ -317,7 +332,9 @@ public class ResultWindow extends JFrame implements ResultListener {
((DetailView) svgCanvas.getPlot()).destroy();
}
svgCanvas.setPlot(plot);
- overviewItem.setEnabled(plot != overview);
+ if (overviewItem != null) {
+ overviewItem.setEnabled(plot != overview);
+ }
exportItem.setEnabled(plot != null);
}
@@ -384,7 +401,8 @@ public class ResultWindow extends JFrame implements ResultListener {
nochildren = false;
}
}
- // Item for a visualizer
+
+ // Item for the visualizer
JMenuItem item = makeMenuItemForVisualizer(r);
if(nochildren) {
if(item != null) {
@@ -402,12 +420,15 @@ public class ResultWindow extends JFrame implements ResultListener {
}
parent.add(submenu);
}
+
return true;
}
public JMenuItem makeMenuItemForVisualizer(Result r) {
if(VisualizationTask.class.isInstance(r)) {
final VisualizationTask v = (VisualizationTask) r;
+ JMenuItem item;
+
// Currently enabled?
final String name = v.getLongName();
boolean enabled = VisualizerUtil.isVisible(v);
@@ -421,12 +442,12 @@ public class ResultWindow extends JFrame implements ResultListener {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
- context.setVisualizationVisibility(v, visItem.getState());
+ VisualizerUtil.setVisible(context, v, visItem.getState());
}
});
}
});
- return visItem;
+ item = visItem;
}
else {
final JRadioButtonMenuItem visItem = new JRadioButtonMenuItem(name, enabled);
@@ -437,12 +458,22 @@ public class ResultWindow extends JFrame implements ResultListener {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
- context.setVisualizationVisibility(v, visItem.isSelected());
+ VisualizerUtil.setVisible(context, v, visItem.isSelected());
}
});
}
});
- return visItem;
+ item = visItem;
+ }
+ boolean hasoptions = VisualizerUtil.hasOptions(v);
+ if(hasoptions) {
+ final JMenu menu = new JMenu(name);
+ menu.add(item);
+ // TODO: build a menu for the visualizer!
+ return menu;
+ }
+ else {
+ return item;
}
}
return null;
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 6bcf5f0b..0c8e7500 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) 2011
+Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,7 +25,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
-import java.util.Collections;
import java.util.Set;
import javax.swing.ImageIcon;
@@ -202,7 +201,7 @@ public class SelectionTableWindow extends JFrame implements DataStoreListener, R
DBIDSelection sel = context.getSelection();
if(sel != null) {
this.dbids = DBIDUtil.newArray(sel.getSelectedIds());
- Collections.sort(this.dbids);
+ this.dbids.sort();
}
else {
this.dbids = DBIDUtil.newArray();
@@ -327,7 +326,7 @@ public class SelectionTableWindow extends JFrame implements DataStoreListener, R
double[] vals = new double[dimensionality];
for(int d = 0; d < dimensionality; d++) {
if(d == columnIndex - 3) {
- vals[d] = Double.valueOf((String) aValue);
+ vals[d] = Double.parseDouble((String) aValue);
}
else {
vals[d] = obj.doubleValue(d + 1);
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 a08be9b5..7c419da7 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) 2011
+ Copyright (C) 2012
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 341aa69f..8b6f4892 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) 2011
+ Copyright (C) 2012
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.visualization.gui.detail;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
@@ -35,13 +36,13 @@ import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
import de.lmu.ifi.dbs.elki.result.Result;
import de.lmu.ifi.dbs.elki.result.ResultListener;
-import de.lmu.ifi.dbs.elki.utilities.iterator.IterableUtil;
import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
import de.lmu.ifi.dbs.elki.visualization.VisualizerContext;
import de.lmu.ifi.dbs.elki.visualization.batikutil.AttributeModifier;
import de.lmu.ifi.dbs.elki.visualization.css.CSSClass;
import de.lmu.ifi.dbs.elki.visualization.gui.overview.PlotItem;
import de.lmu.ifi.dbs.elki.visualization.style.StyleLibrary;
+import de.lmu.ifi.dbs.elki.visualization.svg.SVGEffects;
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.Visualization;
@@ -105,6 +106,8 @@ public class DetailView extends SVGPlot implements ResultListener {
// TODO: only do this when there is an interactive visualizer?
setDisableInteractions(true);
addBackground(context);
+ SVGEffects.addShadowFilter(this);
+ SVGEffects.addLightGradient(this);
redraw();
context.addResultListener(this);
@@ -129,18 +132,20 @@ public class DetailView extends SVGPlot implements ResultListener {
SVGUtil.setCSSClass(bg, cls.getName());
// Note that we rely on this being called before any other drawing routines.
- getDocument().getRootElement().appendChild(bg);
+ getRoot().appendChild(bg);
}
protected void redraw() {
destroyVisualizations();
- width = getRatio();
- height = 1.0;
+ // Try to keep the area approximately 1.0
+ width = Math.sqrt(getRatio());
+ height = 1.0 / width;
ArrayList<Visualization> layers = new ArrayList<Visualization>();
// TODO: center/arrange visualizations?
- for(VisualizationTask task : IterableUtil.fromIterator(visi.visIterator())) {
+ for(Iterator<VisualizationTask> tit = visi.tasks.iterator(); tit.hasNext();) {
+ VisualizationTask task = tit.next();
if(VisualizerUtil.isVisible(task)) {
try {
Visualization v = task.getFactory().makeVisualization(task.clone(this, context, visi.proj, width, height));
@@ -152,7 +157,7 @@ public class DetailView extends SVGPlot implements ResultListener {
LoggingUtil.exception("Visualization failed.", e);
}
else {
- LoggingUtil.warning("Visualizer " + task.getFactory().getClass().getName() + " failed - enable debugging to see details.");
+ LoggingUtil.warning("Visualizer " + task.getFactory().getClass().getName() + " failed - enable debugging to see details: " + e.toString());
}
}
}
@@ -160,7 +165,7 @@ public class DetailView extends SVGPlot implements ResultListener {
// Arrange
for(Visualization layer : layers) {
if(layer.getLayer() != null) {
- this.getRoot().appendChild(layer.getLayer());
+ getRoot().appendChild(layer.getLayer());
}
else {
LoggingUtil.warning("NULL layer seen.");
@@ -216,6 +221,14 @@ public class DetailView extends SVGPlot implements ResultListener {
}
/**
+ * @return the layermap
+ */
+ // TODO: Temporary
+ public Map<VisualizationTask, Visualization> getLayermap() {
+ return layermap;
+ }
+
+ /**
* Class used to insert a new visualization layer
*
* @author Erich Schubert
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 3557a4fe..95339ac1 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) 2011
+Copyright (C) 2012
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 085fc262..4c950225 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) 2011
+ Copyright (C) 2012
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
new file mode 100644
index 00000000..c3575e43
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/gui/overview/LayerMap.java
@@ -0,0 +1,157 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.*;
+
+import org.w3c.dom.Element;
+
+import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
+import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
+import de.lmu.ifi.dbs.elki.visualization.visualizers.Visualization;
+
+/**
+ * Class to help keeping track of the materialized layers of the different visualizations.
+ *
+ * @author Erich Schubert
+ */
+public class LayerMap {
+ /**
+ * The actual map
+ */
+ private HashMap<Pair<PlotItem, VisualizationTask>, Pair<Element, Visualization>> map = new HashMap<Pair<PlotItem, VisualizationTask>, Pair<Element, Visualization>>();
+
+ /**
+ * Helper function for building a key object
+ *
+ * @param item Plot item
+ * @param task Visualization Task
+ * @return Key
+ */
+ private Pair<PlotItem, VisualizationTask> key(PlotItem item, VisualizationTask task) {
+ return new Pair<PlotItem, VisualizationTask>(item, task);
+ }
+
+ /**
+ * Helper function to build a value pair
+ *
+ * @param elem Container element
+ * @param vis Visualization
+ * @return Value object
+ */
+ private Pair<Element, Visualization> value(Element elem, Visualization vis) {
+ return new Pair<Element, Visualization>(elem, vis);
+ }
+
+ /**
+ * Get the visualization referenced by a item/key combination.
+ *
+ * @param item Plot ttem
+ * @param task Visualization task
+ * @return Visualization
+ */
+ public Visualization getVisualization(PlotItem item, VisualizationTask task) {
+ Pair<Element, Visualization> pair = map.get(key(item, task));
+ if (pair == null) {
+ return null;
+ } else {
+ return pair.second;
+ }
+ }
+
+ /**
+ * Get the container element referenced by a item/key combination.
+ *
+ * @param item Plot item
+ * @param task Visualization task
+ * @return Container element
+ */
+ public Element getContainer(PlotItem item, VisualizationTask task) {
+ Pair<Element, Visualization> pair = map.get(key(item, task));
+ if (pair == null) {
+ return null;
+ } else {
+ return pair.first;
+ }
+ }
+
+ /**
+ * Iterate over values
+ *
+ * @return Value iterable
+ */
+ public Iterable<Pair<Element, Visualization>> values() {
+ return map.values();
+ }
+
+ /**
+ * Clear a map
+ */
+ public void clear() {
+ map.clear();
+ }
+
+ /**
+ * Put a new combination into the map.
+ *
+ * @param it Plot item
+ * @param task Visualization Task
+ * @param elem Container element
+ * @param vis Visualization
+ */
+ public void put(PlotItem it, VisualizationTask task, Element elem, Visualization vis) {
+ map.put(key(it, task), value(elem, vis));
+ }
+
+ /**
+ * Remove a combination.
+ *
+ * @param it Plot item
+ * @param task Visualization task
+ * @return Previous value
+ */
+ public Pair<Element, Visualization> remove(PlotItem it, VisualizationTask task) {
+ return map.remove(key(it, task));
+ }
+
+ /**
+ * Put a new item into the visualizations
+ *
+ * @param it Plot item
+ * @param task Visualization task
+ * @param pair Pair object
+ */
+ public void put(PlotItem it, VisualizationTask task, Pair<Element, Visualization> pair) {
+ map.put(key(it, task), pair);
+ }
+
+ /**
+ * Get a pair from the map
+ *
+ * @param it Plot item
+ * @param task Visualization task
+ * @return Pair object
+ */
+ public Pair<Element, Visualization> get(PlotItem it, VisualizationTask task) {
+ return map.get(key(it, task));
+ }
+} \ No newline at end of file
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 f05719ae..56d6ce32 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,7 +27,6 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
@@ -51,6 +50,8 @@ import de.lmu.ifi.dbs.elki.visualization.batikutil.CSSHoverClass;
import de.lmu.ifi.dbs.elki.visualization.css.CSSClass;
import de.lmu.ifi.dbs.elki.visualization.gui.detail.DetailView;
import de.lmu.ifi.dbs.elki.visualization.projector.Projector;
+import de.lmu.ifi.dbs.elki.visualization.style.StyleLibrary;
+import de.lmu.ifi.dbs.elki.visualization.svg.SVGEffects;
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.Visualization;
@@ -67,8 +68,10 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.VisualizerUtil;
* @apiviz.composedOf RectangleArranger
* @apiviz.has DetailViewSelectedEvent
* @apiviz.uses DetailView
- * @apiviz.uses de.lmu.ifi.dbs.elki.visualization.projections.Projection
+ * @apiviz.uses Projector
*/
+// FIXME: there still is a synchronization issue, that causes the initialization
+// to be run twice in parallel.
public class OverviewPlot extends SVGPlot implements ResultListener {
/**
* Our logging class
@@ -81,11 +84,6 @@ public class OverviewPlot extends SVGPlot implements ResultListener {
private VisualizerContext context;
/**
- * Result we work on. Currently unused, but kept for future requirements.
- */
- private HierarchicalResult result;
-
- /**
* Map of coordinates to plots.
*/
protected RectangleArranger<PlotItem> plotmap;
@@ -96,18 +94,9 @@ public class OverviewPlot extends SVGPlot implements ResultListener {
private java.util.Vector<ActionListener> actionListeners = new java.util.Vector<ActionListener>();
/**
- * Constructor.
- *
- * @param result Result to visualize
- * @param context Visualizer context
+ * Single view mode
*/
- public OverviewPlot(HierarchicalResult result, VisualizerContext context) {
- super();
- this.result = result;
- this.context = context;
- // register context listener
- context.addResultListener(this);
- }
+ private boolean single;
/**
* Screen size (used for thumbnail sizing)
@@ -127,7 +116,7 @@ public class OverviewPlot extends SVGPlot implements ResultListener {
/**
* Lookup
*/
- private HashMap<Pair<PlotItem, VisualizationTask>, Element> vistoelem;
+ private LayerMap vistoelem = new LayerMap();
/**
* Layer for plot thumbnail
@@ -152,7 +141,7 @@ public class OverviewPlot extends SVGPlot implements ResultListener {
/**
* Pending refresh, for lazy refreshing
*/
- Runnable pendingRefresh;
+ Runnable pendingRefresh = null;
/**
* Reinitialize on refresh
@@ -160,41 +149,79 @@ public class OverviewPlot extends SVGPlot implements ResultListener {
private boolean reinitOnRefresh = true;
/**
+ * Constructor.
+ *
+ * @param result Result to visualize
+ * @param context Visualizer context
+ * @param single Single view mode
+ */
+ public OverviewPlot(HierarchicalResult result, VisualizerContext context, boolean single) {
+ super();
+ this.context = context;
+ this.single = single;
+
+ // Add a background element:
+ {
+ CSSClass cls = new CSSClass(this, "background");
+ cls.setStatement(SVGConstants.CSS_FILL_PROPERTY, context.getStyleLibrary().getBackgroundColor(StyleLibrary.PAGE));
+ addCSSClassOrLogError(cls);
+ Element background = this.svgElement(SVGConstants.SVG_RECT_TAG);
+ background.setAttribute(SVGConstants.SVG_X_ATTRIBUTE, "0");
+ background.setAttribute(SVGConstants.SVG_Y_ATTRIBUTE, "0");
+ background.setAttribute(SVGConstants.SVG_WIDTH_ATTRIBUTE, "100%");
+ background.setAttribute(SVGConstants.SVG_HEIGHT_ATTRIBUTE, "100%");
+ SVGUtil.setCSSClass(background, cls.getName());
+ getRoot().appendChild(background);
+ }
+
+ if(single) {
+ setDisableInteractions(true);
+ }
+ SVGEffects.addShadowFilter(this);
+ SVGEffects.addLightGradient(this);
+
+ // register context listener
+ context.addResultListener(this);
+ }
+
+ /**
* Recompute the layout of visualizations.
*/
private void arrangeVisualizations() {
- plotmap = new RectangleArranger<PlotItem>(ratio);
+ RectangleArranger<PlotItem> plotmap = new RectangleArranger<PlotItem>(ratio);
- ArrayList<Projector> projectors = ResultUtil.filterResults(result, Projector.class);
+ ArrayList<Projector> projectors = ResultUtil.filterResults(context.getResult(), Projector.class);
// Rectangle layout
for(Projector p : projectors) {
Collection<PlotItem> projs = p.arrange();
for(PlotItem it : projs) {
- plotmap.put(it.w, it.h, it);
+ if(it.w <= 0.0 || it.h <= 0.0) {
+ logger.warning("Plot item with improper size information: " + it);
+ }
+ else {
+ plotmap.put(it.w, it.h, it);
+ }
}
}
- ResultHierarchy hier = result.getHierarchy();
- ArrayList<VisualizationTask> tasks = ResultUtil.filterResults(result, VisualizationTask.class);
- for(VisualizationTask task : tasks) {
- boolean isprojected = false;
+ 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) {
- isprojected = true;
- break;
+ continue nextTask;
}
}
- if(!isprojected) {
- if(task.getWidth() <= 0.0 || task.getHeight() <= 0.0) {
- logger.warning("Task with improper size information: " + task);
- }
- else {
- PlotItem it = new PlotItem(task.getWidth(), task.getHeight(), null);
- it.visualizations.add(task);
- plotmap.put(it.w, it.h, it);
- }
+ if(task.getWidth() <= 0.0 || task.getHeight() <= 0.0) {
+ logger.warning("Task with improper size information: " + task);
+ }
+ else {
+ PlotItem it = new PlotItem(task.getWidth(), task.getHeight(), null);
+ it.tasks.add(task);
+ plotmap.put(it.w, it.h, it);
}
}
+ this.plotmap = plotmap;
}
/**
@@ -204,48 +231,58 @@ public class OverviewPlot extends SVGPlot implements ResultListener {
setupHoverer();
arrangeVisualizations();
recalcViewbox();
+ final int thumbsize = (int) Math.max(screenwidth / plotmap.getWidth(), screenheight / plotmap.getHeight());
// TODO: cancel pending thumbnail requests!
- // Layers.
- if(plotlayer != null) {
- if(plotlayer.getParentNode() != null) {
- plotlayer.getParentNode().removeChild(plotlayer);
- }
- plotlayer = null;
- }
- if(hoverlayer != null) {
- if(hoverlayer.getParentNode() != null) {
- hoverlayer.getParentNode().removeChild(hoverlayer);
- }
- hoverlayer = null;
+ // Detach existing elements:
+ for(Pair<Element, Visualization> pair : vistoelem.values()) {
+ SVGUtil.removeFromParent(pair.first);
}
+ // Replace the layer map
+ LayerMap oldlayers = vistoelem;
+ vistoelem = new LayerMap();
+
+ // Redo main layers
+ SVGUtil.removeFromParent(plotlayer);
+ SVGUtil.removeFromParent(hoverlayer);
plotlayer = this.svgElement(SVGConstants.SVG_G_TAG);
hoverlayer = this.svgElement(SVGConstants.SVG_G_TAG);
- vistoelem = new HashMap<Pair<PlotItem, VisualizationTask>, Element>();
-
- final int thumbsize = (int) Math.max(screenwidth / plotmap.getWidth(), screenheight / plotmap.getHeight());
- // TODO: kill all children in document root except style, defs etc?
+ // Redo the layout
for(Entry<PlotItem, double[]> e : plotmap.entrySet()) {
final double basex = e.getValue()[0];
final double basey = e.getValue()[1];
for(Iterator<PlotItem> iter = e.getKey().itemIterator(); iter.hasNext();) {
PlotItem it = iter.next();
+
boolean hasDetails = false;
+ // Container element for main plot item
Element g = this.svgElement(SVGConstants.SVG_G_TAG);
SVGUtil.setAtt(g, SVGConstants.SVG_TRANSFORM_ATTRIBUTE, "translate(" + (basex + it.x) + " " + (basey + it.y) + ")");
- for(VisualizationTask task : it.visualizations) {
- Element parent = this.svgElement(SVGConstants.SVG_G_TAG);
- g.appendChild(parent);
- makeThumbnail(thumbsize, it, task, parent);
- vistoelem.put(new Pair<PlotItem, VisualizationTask>(it, task), parent);
-
+ plotlayer.appendChild(g);
+ vistoelem.put(it, null, g, null);
+ // Add the actual tasks:
+ for(VisualizationTask task : it.tasks) {
+ if(!visibleInOverview(task)) {
+ continue;
+ }
if(VisualizerUtil.detailsEnabled(task)) {
hasDetails = true;
+ // TODO: not updatable
+ }
+ Pair<Element, Visualization> pair = oldlayers.remove(it, task);
+ if(pair == null) {
+ pair = new Pair<Element, Visualization>(null, null);
+ pair.first = svgElement(SVGConstants.SVG_G_TAG);
}
+ if(pair.second == null) {
+ pair.second = embedOrThumbnail(thumbsize, it, task, pair.first);
+ }
+ g.appendChild(pair.first);
+ vistoelem.put(it, task, pair);
}
- plotlayer.appendChild(g);
- if(hasDetails) {
+ // When needed, add a hover effect
+ if(hasDetails && !single) {
Element hover = this.svgRect(basex + it.x, basey + it.y, it.w, it.h);
SVGUtil.addCSSClass(hover, selcss.getName());
// link hoverer.
@@ -259,6 +296,11 @@ public class OverviewPlot extends SVGPlot implements ResultListener {
}
}
}
+ for(Pair<Element, Visualization> pair : oldlayers.values()) {
+ if(pair.second != null) {
+ pair.second.destroy();
+ }
+ }
getRoot().appendChild(plotlayer);
getRoot().appendChild(hoverlayer);
updateStyleElement();
@@ -272,18 +314,30 @@ public class OverviewPlot extends SVGPlot implements ResultListener {
* @param task Task
* @param parent Parent element to draw to
*/
- private void makeThumbnail(final int thumbsize, PlotItem it, VisualizationTask task, Element parent) {
- if(VisualizerUtil.isVisible(task) && VisualizerUtil.thumbnailEnabled(task)) {
+ private Visualization embedOrThumbnail(final int thumbsize, PlotItem it, VisualizationTask task, Element parent) {
+ if(single) {
+ VisualizationTask thumbtask = task.clone(this, context, it.proj, it.w, it.h);
+ final Visualization vis = thumbtask.getFactory().makeVisualization(thumbtask);
+ if(vis.getLayer() == null) {
+ LoggingUtil.warning("Visualization returned empty layer: " + vis);
+ }
+ else {
+ parent.appendChild(vis.getLayer());
+ }
+ return vis;
+ }
+ else {
VisualizationTask thumbtask = task.clone(this, context, it.proj, it.w, it.h);
thumbtask.put(VisualizationTask.THUMBNAIL, true);
thumbtask.put(VisualizationTask.THUMBNAIL_RESOLUTION, thumbsize);
- Visualization vis = thumbtask.getFactory().makeVisualizationOrThumbnail(thumbtask);
+ final Visualization vis = thumbtask.getFactory().makeVisualizationOrThumbnail(thumbtask);
if(vis.getLayer() == null) {
LoggingUtil.warning("Visualization returned empty layer: " + vis);
}
else {
parent.appendChild(vis.getLayer());
}
+ return vis;
}
}
@@ -291,39 +345,53 @@ public class OverviewPlot extends SVGPlot implements ResultListener {
* Do a refresh (when visibilities have changed).
*/
synchronized void refresh() {
- logger.debug("Refresh");
- if(vistoelem == null || plotlayer == null || hoverlayer == null || reinitOnRefresh) {
+ pendingRefresh = null;
+ if(reinitOnRefresh) {
+ logger.debug("Reinitialize");
reinitialize();
reinitOnRefresh = false;
}
else {
+ logger.debug("Incremental refresh");
boolean refreshcss = false;
final int thumbsize = (int) Math.max(screenwidth / plotmap.getWidth(), screenheight / plotmap.getHeight());
- for(Entry<PlotItem, double[]> ent : plotmap.entrySet()) {
- for(Iterator<PlotItem> iter = ent.getKey().itemIterator(); iter.hasNext();) {
+ for(PlotItem pi : plotmap.keySet()) {
+ for(Iterator<PlotItem> iter = pi.itemIterator(); iter.hasNext();) {
PlotItem it = iter.next();
- for(VisualizationTask task : it.visualizations) {
- Element parent = vistoelem.get(new Pair<PlotItem, VisualizationTask>(it, task));
- if(parent == null) {
- LoggingUtil.warning("No container element found for " + task);
- continue;
- }
- if(VisualizerUtil.thumbnailEnabled(task) && VisualizerUtil.isVisible(task)) {
- // unhide when hidden.
- if(parent.hasAttribute(SVGConstants.CSS_VISIBILITY_PROPERTY)) {
- parent.removeAttribute(SVGConstants.CSS_VISIBILITY_PROPERTY);
- }
- // if not yet rendered, add a thumbnail
- if(!parent.hasChildNodes()) {
- makeThumbnail(thumbsize, it, task, parent);
+ for(Iterator<VisualizationTask> tit = it.tasks.iterator(); tit.hasNext();) {
+ VisualizationTask task = tit.next();
+ Pair<Element, Visualization> pair = vistoelem.get(it, task);
+ // New task?
+ if(pair == null) {
+ if(visibleInOverview(task)) {
+ pair = new Pair<Element, Visualization>(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);
+ vistoelem.put(it, task, pair);
refreshcss = true;
}
}
else {
- // hide if there is anything to hide.
- if(parent != null && parent.hasChildNodes()) {
- parent.setAttribute(SVGConstants.CSS_VISIBILITY_PROPERTY, SVGConstants.CSS_HIDDEN_VALUE);
+ if(visibleInOverview(task)) {
+ // unhide if hidden.
+ 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()) {
+ logger.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()) {
+ pair.first.setAttribute(SVGConstants.CSS_VISIBILITY_PROPERTY, SVGConstants.CSS_HIDDEN_VALUE);
+ }
}
// TODO: unqueue pending thumbnails
}
@@ -337,6 +405,25 @@ public class OverviewPlot extends SVGPlot implements ResultListener {
}
/**
+ * Test whether a task should be displayed in the overview plot.
+ *
+ * @param task Task to display
+ * @return visibility
+ */
+ protected boolean visibleInOverview(VisualizationTask task) {
+ if(!VisualizerUtil.isVisible(task)) {
+ return false;
+ }
+ if(single) {
+ Boolean nothumb = task.getGenerics(VisualizationTask.META_NOEMBED, Boolean.class);
+ return (nothumb == null) || !nothumb;
+ }
+ else {
+ return VisualizerUtil.thumbnailEnabled(task);
+ }
+ }
+
+ /**
* Recompute the view box of the plot.
*/
private void recalcViewbox() {
@@ -364,6 +451,7 @@ public class OverviewPlot extends SVGPlot implements ResultListener {
addCSSClassOrLogError(hovcss);
// Hover listener.
hoverer = new CSSHoverClass(hovcss.getName(), null, true);
+ updateStyleElement();
}
/**
@@ -453,11 +541,11 @@ public class OverviewPlot extends SVGPlot implements ResultListener {
* Trigger a redraw, but avoid excessive redraws.
*/
public final void lazyRefresh() {
+ logger.debug("Scheduling refresh.");
Runnable pr = new Runnable() {
@Override
public void run() {
if(OverviewPlot.this.pendingRefresh == this) {
- OverviewPlot.this.pendingRefresh = null;
OverviewPlot.this.refresh();
}
}
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 cd8f5b3e..cbe5a4be 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -68,9 +68,9 @@ public class PlotItem {
public final Projection proj;
/**
- * The visualizations at this location
+ * The visualization tasks at this location
*/
- public List<VisualizationTask> visualizations = new LinkedList<VisualizationTask>();
+ public List<VisualizationTask> tasks = new LinkedList<VisualizationTask>();
/**
* Subitems to plot
@@ -110,73 +110,37 @@ public class PlotItem {
* Sort all visualizers for their proper drawing order
*/
public void sort() {
- Collections.sort(visualizations);
+ Collections.sort(tasks);
for(PlotItem subitem : subitems) {
subitem.sort();
}
}
/**
- * Iterate (recursively) over all visualizations.
+ * Add a task to the item.
*
- * @return Iterator
+ * @param task Task to add
*/
- public Iterator<VisualizationTask> visIterator() {
- return new VisItr();
+ public void add(VisualizationTask task) {
+ tasks.add(task);
}
/**
- * Iterate (recursively) over all plot items, including itself.
+ * Number of tasks in this item.
*
- * @return Iterator
+ * @return Number of tasks.
*/
- public Iterator<PlotItem> itemIterator() {
- return new ItmItr();
+ public int taskSize() {
+ return tasks.size();
}
/**
- * Recursive iterator
- *
- * @author Erich Schubert
+ * Iterate (recursively) over all plot items, including itself.
*
- * @apiviz.exclude
+ * @return Iterator
*/
- private class VisItr implements Iterator<VisualizationTask> {
- Iterator<VisualizationTask> cur;
-
- Iterator<PlotItem> sub;
-
- /**
- * Constructor.
- */
- public VisItr() {
- super();
- this.cur = visualizations.iterator();
- this.sub = subitems.iterator();
- }
-
- @Override
- public boolean hasNext() {
- if(cur.hasNext()) {
- return true;
- }
- if(sub.hasNext()) {
- cur = sub.next().visIterator();
- return hasNext();
- }
- return false;
- }
-
- @Override
- public VisualizationTask next() {
- hasNext();
- return cur.next();
- }
-
- @Override
- public void remove() {
- throw new UnsupportedOperationException();
- }
+ public Iterator<PlotItem> itemIterator() {
+ return new ItmItr();
}
/**
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 505e61d8..77825a5f 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -460,6 +460,15 @@ public class RectangleArranger<T> {
}
/**
+ * The item keys contained in the map.
+ *
+ * @return key set
+ */
+ public Set<T> keySet() {
+ return Collections.unmodifiableSet(map.keySet());
+ }
+
+ /**
* Test method.
*
* @param args
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 75c90809..f4690d0a 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
@@ -6,7 +6,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2011
+Copyright (C) 2012
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 e4a51f9b..0d026a1d 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) 2011
+Copyright (C) 2012
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 5fdad225..d86c1ae3 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) 2011
+ Copyright (C) 2012
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/OPTICSColorFromClustering.java b/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSColorFromClustering.java
deleted file mode 100644
index c69dabd0..00000000
--- a/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSColorFromClustering.java
+++ /dev/null
@@ -1,97 +0,0 @@
-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) 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 java.awt.Color;
-import java.util.HashMap;
-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.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.logging.Logging;
-import de.lmu.ifi.dbs.elki.result.optics.ClusterOrderEntry;
-import de.lmu.ifi.dbs.elki.visualization.colors.ColorLibrary;
-import de.lmu.ifi.dbs.elki.visualization.svg.SVGUtil;
-
-/**
- * Adapter that uses an existing clustering to colorize the OPTICS plot.
- *
- * @author Erich Schubert
- *
- * @apiviz.uses ColorLibrary
- */
-public class OPTICSColorFromClustering implements OPTICSColorAdapter {
- /**
- * Logger
- */
- private static final Logging logger = Logging.getLogger(OPTICSColorFromClustering.class);
-
- /**
- * The final mapping of object IDs to colors.
- */
- private final HashMap<DBID, Integer> idToColor;
-
- /**
- * Constructor.
- *
- * @param colors Color library to use
- * @param refc Clustering to use
- */
- public OPTICSColorFromClustering(ColorLibrary colors, Clustering<?> refc) {
- final List<?> allClusters = refc.getAllClusters();
- // Build a list of colors
- int[] cols = new int[allClusters.size()];
- for(int i = 0; i < allClusters.size(); i++) {
- Color color = SVGUtil.stringToColor(colors.getColor(i));
- if(color != null) {
- cols[i] = color.getRGB();
- }
- else {
- logger.warning("Could not parse color: " + colors.getColor(i));
- cols[i] = 0x7F7F7F7F;
- }
- }
-
- idToColor = new HashMap<DBID, Integer>();
- int cnum = 0;
- for(Cluster<?> clus : refc.getAllClusters()) {
- Color color = SVGUtil.stringToColor(colors.getColor(cnum));
- if (color == null) {
- logger.warning("Could not parse color: "+colors.getColor(cnum));
- color = Color.BLACK;
- }
- int rgb = color.getRGB();
- for(DBID id : clus.getIDs()) {
- idToColor.put(id, rgb);
- }
- cnum++;
- }
- }
-
- @Override
- public int getColorForEntry(ClusterOrderEntry<?> coe) {
- return idToColor.get(coe.getID());
- }
-} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSColorFromStylingPolicy.java b/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSColorFromStylingPolicy.java
new file mode 100644
index 00000000..53a03d3e
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSColorFromStylingPolicy.java
@@ -0,0 +1,56 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.result.optics.ClusterOrderEntry;
+import de.lmu.ifi.dbs.elki.visualization.style.StylingPolicy;
+
+/**
+ * Adapter that uses a styling policy to colorize the OPTICS plot.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.uses StylingPolicy
+ */
+public class OPTICSColorFromStylingPolicy implements OPTICSColorAdapter {
+ /**
+ * The styling policy
+ */
+ private StylingPolicy policy;
+
+ /**
+ * Constructor.
+ *
+ * @param policy Styling policy
+ */
+ public OPTICSColorFromStylingPolicy(StylingPolicy policy) {
+ super();
+ this.policy = policy;
+ }
+
+ @Override
+ public int getColorForEntry(ClusterOrderEntry<?> coe) {
+ return policy.getColorForDBID(coe.getID());
+ }
+} \ No newline at end of file
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 af28008e..920c6d27 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) 2011
+ Copyright (C) 2012
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 3e8835b1..d61c8d07 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) 2011
+ Copyright (C) 2012
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/OPTICSCut.java b/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSCut.java
index 41563087..d5a1c043 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) 2011
+ Copyright (C) 2012
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/OPTICSDistanceAdapter.java b/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSDistanceAdapter.java
index 3f36209a..16b9a323 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) 2011
+ Copyright (C) 2012
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/OPTICSNumberDistance.java b/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSNumberDistance.java
index f0b49585..697a9fa2 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) 2011
+ Copyright (C) 2012
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/OPTICSPlot.java b/src/de/lmu/ifi/dbs/elki/visualization/opticsplot/OPTICSPlot.java
index 7520d2a7..e0aac5ca 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,25 +25,20 @@ package de.lmu.ifi.dbs.elki.visualization.opticsplot;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
-import java.io.File;
-import java.io.IOException;
import java.util.List;
-import javax.imageio.ImageIO;
-
-import de.lmu.ifi.dbs.elki.data.Clustering;
import de.lmu.ifi.dbs.elki.distance.distancevalue.CorrelationDistance;
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.math.DoubleMinMax;
+import de.lmu.ifi.dbs.elki.math.scales.LinearScale;
import de.lmu.ifi.dbs.elki.result.Result;
import de.lmu.ifi.dbs.elki.result.optics.ClusterOrderEntry;
import de.lmu.ifi.dbs.elki.result.optics.ClusterOrderResult;
import de.lmu.ifi.dbs.elki.visualization.VisualizerContext;
-import de.lmu.ifi.dbs.elki.visualization.colors.ColorLibrary;
-import de.lmu.ifi.dbs.elki.visualization.scales.LinearScale;
-import de.lmu.ifi.dbs.elki.visualization.style.StyleLibrary;
+import de.lmu.ifi.dbs.elki.visualization.batikutil.ThumbnailRegistryEntry;
+import de.lmu.ifi.dbs.elki.visualization.style.StylingPolicy;
/**
* Class to produce an OPTICS plot image.
@@ -64,11 +59,6 @@ public class OPTICSPlot<D extends Distance<D>> implements Result {
protected static final Logging logger = Logging.getLogger(OPTICSPlot.class);
/**
- * Prefix for filenames
- */
- private static final String IMGFILEPREFIX = "elki-optics-";
-
- /**
* Scale to use
*/
LinearScale scale;
@@ -104,9 +94,9 @@ public class OPTICSPlot<D extends Distance<D>> implements Result {
protected RenderedImage plot;
/**
- * The plot saved to a temp file.
+ * The plot number for Batik
*/
- protected File tempFile;
+ protected int plotnum = -1;
/**
* Constructor.
@@ -234,7 +224,7 @@ public class OPTICSPlot<D extends Distance<D>> implements Result {
}
}
// Ensure we have a valid range
- if(range.isValid()) {
+ if(!range.isValid()) {
range.put(0.0);
range.put(1.0);
}
@@ -245,7 +235,7 @@ public class OPTICSPlot<D extends Distance<D>> implements Result {
* @return the scale
*/
public LinearScale getScale() {
- if(plot == null && tempFile == null) {
+ if(plot == null) {
replot();
}
return scale;
@@ -255,7 +245,7 @@ public class OPTICSPlot<D extends Distance<D>> implements Result {
* @return the width
*/
public int getWidth() {
- if(plot == null && tempFile == null) {
+ if(plot == null) {
replot();
}
return width;
@@ -265,7 +255,7 @@ public class OPTICSPlot<D extends Distance<D>> implements Result {
* @return the height
*/
public int getHeight() {
- if(plot == null && tempFile == null) {
+ if(plot == null) {
replot();
}
return height;
@@ -277,7 +267,7 @@ public class OPTICSPlot<D extends Distance<D>> implements Result {
* @return {@code width / height}
*/
public double getRatio() {
- if(plot == null && tempFile == null) {
+ if(plot == null) {
replot();
}
return ((double) width) / height;
@@ -305,25 +295,23 @@ public class OPTICSPlot<D extends Distance<D>> implements Result {
}
/**
- * Get a temporary file for the optics plot.
- *
- * @return Temp file containing the plot
- * @throws IOException
+ * Free memory used by rendered image.
*/
- public File getAsTempFile() throws IOException {
- if(tempFile == null) {
- tempFile = File.createTempFile(IMGFILEPREFIX, ".png");
- tempFile.deleteOnExit();
- ImageIO.write(getPlot(), "PNG", tempFile);
- }
- return tempFile;
+ public void forgetRenderedImage() {
+ plotnum = -1;
+ plot = null;
}
/**
- * Free memory used by rendered image.
+ * Get the SVG registered plot number
+ *
+ * @return Plot URI
*/
- public void forgetRenderedImage() {
- plot = null;
+ public String getSVGPlotURI() {
+ if(plotnum < 0) {
+ plotnum = ThumbnailRegistryEntry.registerImage(plot);
+ }
+ return ThumbnailRegistryEntry.INTERNAL_PREFIX + plotnum;
}
@Override
@@ -335,10 +323,10 @@ public class OPTICSPlot<D extends Distance<D>> implements Result {
public String getShortName() {
return "optics plot";
}
-
+
/**
- * Static method to find an optics plot for a result,
- * or to create a new one using the given context.
+ * Static method to find an optics plot for a result, or to create a new one
+ * using the given context.
*
* @param <D> Distance type
* @param co Cluster order
@@ -348,18 +336,18 @@ public class OPTICSPlot<D extends Distance<D>> implements Result {
*/
public static <D extends Distance<D>> OPTICSPlot<D> plotForClusterOrder(ClusterOrderResult<D> co, VisualizerContext context) {
// Check for an existing plot
- // ArrayList<OPTICSPlot<D>> plots = ResultUtil.filterResults(co, OPTICSPlot.class);
+ // ArrayList<OPTICSPlot<D>> plots = ResultUtil.filterResults(co,
+ // OPTICSPlot.class);
// if (plots.size() > 0) {
- // return plots.get(0);
+ // return plots.get(0);
// }
// Supported by this class?
- if (!OPTICSPlot.canPlot(co)) {
+ if(!OPTICSPlot.canPlot(co)) {
return null;
}
- final ColorLibrary colors = context.getStyleLibrary().getColorSet(StyleLibrary.PLOT);
- final Clustering<?> refc = context.getOrCreateDefaultClustering();
- final OPTICSColorAdapter opcolor = new OPTICSColorFromClustering(colors, refc);
-
+ final StylingPolicy policy = context.getStyleResult().getStylingPolicy();
+ final OPTICSColorAdapter opcolor = new OPTICSColorFromStylingPolicy(policy);
+
OPTICSPlot<D> opticsplot = new OPTICSPlot<D>(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 60529c50..39838db1 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) 2011
+Copyright (C) 2012
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 5216bbbf..b331cc0d 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/package-info.java
@@ -6,7 +6,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2011
+Copyright (C) 2012
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
new file mode 100644
index 00000000..6b08f033
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/projections/AbstractFullProjection.java
@@ -0,0 +1,239 @@
+package de.lmu.ifi.dbs.elki.visualization.projections;
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You 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 full projections.
+ *
+ * Note: the full projection API may be removed at some point, unless we find a
+ * clear use case that cannot be done by the low level fast projections.
+ *
+ * @author Erich Schubert
+ */
+public abstract class AbstractFullProjection extends AbstractProjection implements FullProjection {
+ /**
+ * Constructor.
+ *
+ * @param scales Scales
+ */
+ public AbstractFullProjection(LinearScale[] scales) {
+ super(scales);
+ }
+
+ /**
+ * Project a data vector from data space to scaled space.
+ *
+ * @param data vector in data space
+ * @return vector in scaled space
+ */
+ @Override
+ public Vector projectDataToScaledSpace(NumberVector<?, ?> data) {
+ final int dim = data.getDimensionality();
+ Vector vec = new Vector(dim);
+ double[] ds = vec.getArrayRef();
+ for(int d = 0; d < dim; d++) {
+ ds[d] = scales[d].getScaled(data.doubleValue(d + 1));
+ }
+ return vec;
+ }
+
+ /**
+ * Project a data vector from data space to scaled space.
+ *
+ * @param data vector in data space
+ * @return vector in scaled space
+ */
+ @Override
+ public Vector projectDataToScaledSpace(Vector data) {
+ double[] src = data.getArrayRef();
+ final int dim = src.length;
+ double[] dst = new double[dim];
+ for(int d = 0; d < dim; d++) {
+ dst[d] = scales[d].getScaled(src[d]);
+ }
+ return new Vector(dst);
+ }
+
+ /**
+ * Project a relative data vector from data space to scaled space.
+ *
+ * @param data relative vector in data space
+ * @return relative vector in scaled space
+ */
+ @Override
+ public Vector projectRelativeDataToScaledSpace(NumberVector<?, ?> data) {
+ final int dim = data.getDimensionality();
+ Vector vec = new Vector(dim);
+ double[] ds = vec.getArrayRef();
+ for(int d = 0; d < dim; d++) {
+ ds[d] = scales[d].getRelativeScaled(data.doubleValue(d + 1));
+ }
+ return vec;
+ }
+
+ /**
+ * Project a relative data vector from data space to scaled space.
+ *
+ * @param data relative vector in data space
+ * @return relative vector in scaled space
+ */
+ @Override
+ public Vector projectRelativeDataToScaledSpace(Vector data) {
+ double[] src = data.getArrayRef();
+ final int dim = src.length;
+ double[] dst = new double[dim];
+ for(int d = 0; d < dim; d++) {
+ dst[d] = scales[d].getRelativeScaled(src[d]);
+ }
+ return new Vector(dst);
+ }
+
+ /**
+ * Project a data vector from data space to rendering space.
+ *
+ * @param data vector in data space
+ * @return vector in rendering space
+ */
+ @Override
+ public Vector projectDataToRenderSpace(NumberVector<?, ?> data) {
+ return projectScaledToRender(projectDataToScaledSpace(data));
+ }
+
+ /**
+ * Project a data vector from data space to rendering space.
+ *
+ * @param data vector in data space
+ * @return vector in rendering space
+ */
+ @Override
+ public Vector projectDataToRenderSpace(Vector data) {
+ return projectScaledToRender(projectDataToScaledSpace(data));
+ }
+
+ /**
+ * Project a relative data vector from data space to rendering space.
+ *
+ * @param data relative vector in data space
+ * @return relative vector in rendering space
+ */
+ @Override
+ public Vector projectRelativeDataToRenderSpace(NumberVector<?, ?> data) {
+ return projectRelativeScaledToRender(projectRelativeDataToScaledSpace(data));
+ }
+
+ /**
+ * Project a relative data vector from data space to rendering space.
+ *
+ * @param data relative vector in data space
+ * @return relative vector in rendering space
+ */
+ @Override
+ public Vector projectRelativeDataToRenderSpace(Vector data) {
+ return projectRelativeScaledToRender(projectRelativeDataToScaledSpace(data));
+ }
+
+ /**
+ * Project a vector from scaled space to data space.
+ *
+ * @param <NV> Vector type
+ * @param v vector in scaled space
+ * @param factory Object factory
+ * @return vector in data space
+ */
+ @Override
+ public <NV extends NumberVector<NV, ?>> NV projectScaledToDataSpace(Vector v, NV factory) {
+ final int dim = v.getDimensionality();
+ Vector vec = v.copy();
+ double[] ds = vec.getArrayRef();
+ for(int d = 0; d < dim; d++) {
+ ds[d] = scales[d].getUnscaled(ds[d]);
+ }
+ return factory.newNumberVector(vec.getArrayRef());
+ }
+
+ /**
+ * Project a vector from rendering space to data space.
+ *
+ * @param <NV> Vector type
+ * @param v vector in rendering space
+ * @param prototype Object factory
+ * @return vector in data space
+ */
+ @Override
+ public <NV extends NumberVector<NV, ?>> NV projectRenderToDataSpace(Vector v, NV prototype) {
+ final int dim = v.getDimensionality();
+ Vector vec = projectRenderToScaled(v);
+ double[] ds = vec.getArrayRef();
+ // Not calling {@link #projectScaledToDataSpace} to avoid extra copy of
+ // vector.
+ for(int d = 0; d < dim; d++) {
+ ds[d] = scales[d].getUnscaled(ds[d]);
+ }
+ return prototype.newNumberVector(vec.getArrayRef());
+ }
+
+ /**
+ * Project a relative vector from scaled space to data space.
+ *
+ * @param <NV> Vector type
+ * @param v relative vector in scaled space
+ * @param prototype Object factory
+ * @return relative vector in data space
+ */
+ @Override
+ public <NV extends NumberVector<NV, ?>> NV projectRelativeScaledToDataSpace(Vector v, NV prototype) {
+ final int dim = v.getDimensionality();
+ Vector vec = v.copy();
+ double[] ds = vec.getArrayRef();
+ for(int d = 0; d < dim; d++) {
+ ds[d] = scales[d].getRelativeUnscaled(ds[d]);
+ }
+ return prototype.newNumberVector(vec.getArrayRef());
+ }
+
+ /**
+ * Project a relative vector from rendering space to data space.
+ *
+ * @param <NV> Vector type
+ * @param v relative vector in rendering space
+ * @param prototype Object factory
+ * @return relative vector in data space
+ */
+ @Override
+ public <NV extends NumberVector<NV, ?>> NV projectRelativeRenderToDataSpace(Vector v, NV prototype) {
+ final int dim = v.getDimensionality();
+ Vector vec = projectRelativeRenderToScaled(v);
+ double[] ds = vec.getArrayRef();
+ // Not calling {@link #projectScaledToDataSpace} to avoid extra copy of
+ // vector.
+ for(int d = 0; d < dim; d++) {
+ ds[d] = scales[d].getRelativeUnscaled(ds[d]);
+ }
+ return prototype.newNumberVector(vec.getArrayRef());
+ }
+}
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 fcd7191c..f0eeccd4 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,10 +23,8 @@ package de.lmu.ifi.dbs.elki.visualization.projections;
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.math.linearalgebra.Vector;
+import de.lmu.ifi.dbs.elki.math.scales.LinearScale;
import de.lmu.ifi.dbs.elki.result.AbstractHierarchicalResult;
-import de.lmu.ifi.dbs.elki.visualization.scales.LinearScale;
/**
* Abstract base projection class.
@@ -65,198 +63,6 @@ public abstract class AbstractProjection extends AbstractHierarchicalResult impl
return scales[d];
}
- /**
- * Project a data vector from data space to scaled space.
- *
- * @param data vector in data space
- * @return vector in scaled space
- */
- @Override
- public Vector projectDataToScaledSpace(NumberVector<?, ?> data) {
- final int dim = data.getDimensionality();
- Vector vec = new Vector(dim);
- double[] ds = vec.getArrayRef();
- for(int d = 0; d < dim; d++) {
- ds[d] = scales[d].getScaled(data.doubleValue(d + 1));
- }
- return vec;
- }
-
- /**
- * Project a data vector from data space to scaled space.
- *
- * @param data vector in data space
- * @return vector in scaled space
- */
- @Override
- public Vector projectDataToScaledSpace(Vector data) {
- double[] src = data.getArrayRef();
- final int dim = src.length;
- double[] dst = new double[dim];
- for(int d = 0; d < dim; d++) {
- dst[d] = scales[d].getScaled(src[d]);
- }
- return new Vector(dst);
- }
-
- /**
- * Project a relative data vector from data space to scaled space.
- *
- * @param data relative vector in data space
- * @return relative vector in scaled space
- */
- @Override
- public Vector projectRelativeDataToScaledSpace(NumberVector<?, ?> data) {
- final int dim = data.getDimensionality();
- Vector vec = new Vector(dim);
- double[] ds = vec.getArrayRef();
- for(int d = 0; d < dim; d++) {
- ds[d] = scales[d].getRelativeScaled(data.doubleValue(d + 1));
- }
- return vec;
- }
-
- /**
- * Project a relative data vector from data space to scaled space.
- *
- * @param data relative vector in data space
- * @return relative vector in scaled space
- */
- @Override
- public Vector projectRelativeDataToScaledSpace(Vector data) {
- double[] src = data.getArrayRef();
- final int dim = src.length;
- double[] dst = new double[dim];
- for(int d = 0; d < dim; d++) {
- dst[d] = scales[d].getRelativeScaled(src[d]);
- }
- return new Vector(dst);
- }
-
- /**
- * Project a data vector from data space to rendering space.
- *
- * @param data vector in data space
- * @return vector in rendering space
- */
- @Override
- public Vector projectDataToRenderSpace(NumberVector<?, ?> data) {
- return projectScaledToRender(projectDataToScaledSpace(data));
- }
-
- /**
- * Project a data vector from data space to rendering space.
- *
- * @param data vector in data space
- * @return vector in rendering space
- */
- @Override
- public Vector projectDataToRenderSpace(Vector data) {
- return projectScaledToRender(projectDataToScaledSpace(data));
- }
-
- /**
- * Project a relative data vector from data space to rendering space.
- *
- * @param data relative vector in data space
- * @return relative vector in rendering space
- */
- @Override
- public Vector projectRelativeDataToRenderSpace(NumberVector<?, ?> data) {
- return projectRelativeScaledToRender(projectRelativeDataToScaledSpace(data));
- }
-
- /**
- * Project a relative data vector from data space to rendering space.
- *
- * @param data relative vector in data space
- * @return relative vector in rendering space
- */
- @Override
- public Vector projectRelativeDataToRenderSpace(Vector data) {
- return projectRelativeScaledToRender(projectRelativeDataToScaledSpace(data));
- }
-
- /**
- * Project a vector from scaled space to data space.
- *
- * @param <NV> Vector type
- * @param v vector in scaled space
- * @param factory Object factory
- * @return vector in data space
- */
- @Override
- public <NV extends NumberVector<NV, ?>> NV projectScaledToDataSpace(Vector v, NV factory) {
- final int dim = v.getDimensionality();
- Vector vec = v.copy();
- double[] ds = vec.getArrayRef();
- for(int d = 0; d < dim; d++) {
- ds[d] = scales[d].getUnscaled(ds[d]);
- }
- return factory.newInstance(vec);
- }
-
- /**
- * Project a vector from rendering space to data space.
- *
- * @param <NV> Vector type
- * @param v vector in rendering space
- * @param prototype Object factory
- * @return vector in data space
- */
- @Override
- public <NV extends NumberVector<NV, ?>> NV projectRenderToDataSpace(Vector v, NV prototype) {
- final int dim = v.getDimensionality();
- Vector vec = projectRenderToScaled(v);
- double[] ds = vec.getArrayRef();
- // Not calling {@link #projectScaledToDataSpace} to avoid extra copy of
- // vector.
- for(int d = 0; d < dim; d++) {
- ds[d] = scales[d].getUnscaled(ds[d]);
- }
- return prototype.newInstance(vec);
- }
-
- /**
- * Project a relative vector from scaled space to data space.
- *
- * @param <NV> Vector type
- * @param v relative vector in scaled space
- * @param prototype Object factory
- * @return relative vector in data space
- */
- @Override
- public <NV extends NumberVector<NV, ?>> NV projectRelativeScaledToDataSpace(Vector v, NV prototype) {
- final int dim = v.getDimensionality();
- Vector vec = v.copy();
- double[] ds = vec.getArrayRef();
- for(int d = 0; d < dim; d++) {
- ds[d] = scales[d].getRelativeUnscaled(ds[d]);
- }
- return prototype.newInstance(vec);
- }
-
- /**
- * Project a relative vector from rendering space to data space.
- *
- * @param <NV> Vector type
- * @param v relative vector in rendering space
- * @param prototype Object factory
- * @return relative vector in data space
- */
- @Override
- public <NV extends NumberVector<NV, ?>> NV projectRelativeRenderToDataSpace(Vector v, NV prototype) {
- final int dim = v.getDimensionality();
- Vector vec = projectRelativeRenderToScaled(v);
- double[] ds = vec.getArrayRef();
- // Not calling {@link #projectScaledToDataSpace} to avoid extra copy of
- // vector.
- for(int d = 0; d < dim; d++) {
- ds[d] = scales[d].getRelativeUnscaled(ds[d]);
- }
- return prototype.newInstance(vec);
- }
-
@Override
public String getLongName() {
return "Projection";
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 778e0bbb..4d3aec90 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) 2011
+ Copyright (C) 2012
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.visualization.projections;
*/
import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
-import de.lmu.ifi.dbs.elki.visualization.scales.LinearScale;
+import de.lmu.ifi.dbs.elki.math.scales.LinearScale;
/**
* Abstract base class for "simple" projections.
@@ -33,7 +33,7 @@ import de.lmu.ifi.dbs.elki.visualization.scales.LinearScale;
*
* @author Erich Schubert
*/
-public abstract class AbstractSimpleProjection extends AbstractProjection {
+public abstract class AbstractSimpleProjection extends AbstractFullProjection {
/**
* Constructor.
*
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 a139cdc1..10533ee0 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) 2011
+ Copyright (C) 2012
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.visualization.projections;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import java.util.Arrays;
import java.util.BitSet;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
import de.lmu.ifi.dbs.elki.math.linearalgebra.AffineTransformation;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
-import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
-import de.lmu.ifi.dbs.elki.visualization.scales.LinearScale;
-import de.lmu.ifi.dbs.elki.visualization.svg.SVGUtil;
+import de.lmu.ifi.dbs.elki.math.scales.LinearScale;
/**
* Affine projections are the most general class. They are initialized by an
@@ -42,13 +41,18 @@ import de.lmu.ifi.dbs.elki.visualization.svg.SVGUtil;
*
* @author Erich Schubert
*/
-public class AffineProjection extends AbstractProjection implements Projection2D {
+public class AffineProjection extends AbstractFullProjection implements Projection2D {
/**
* Affine transformation used in projection
*/
private AffineTransformation proj;
/**
+ * Viewport (cache)
+ */
+ private CanvasSize viewport = null;
+
+ /**
* Constructor with a given database and axes.
*
* @param scales Scales to use
@@ -104,41 +108,36 @@ public class AffineProjection extends AbstractProjection implements Projection2D
}
@Override
- public Pair<DoubleMinMax, DoubleMinMax> estimateViewport() {
- final int dim = proj.getDimensionality();
- DoubleMinMax minmaxx = new DoubleMinMax();
- DoubleMinMax minmaxy = new DoubleMinMax();
-
- // Origin
- Vector orig = new Vector(dim);
- orig = projectScaledToRender(orig);
- minmaxx.put(orig.get(0));
- minmaxy.put(orig.get(1));
- // Diagonal point
- Vector diag = new Vector(dim);
- for(int d2 = 0; d2 < dim; d2++) {
- diag.set(d2, 1);
- }
- diag = projectScaledToRender(diag);
- minmaxx.put(diag.get(0));
- minmaxy.put(diag.get(1));
- // Axis end points
- for(int d = 0; d < dim; d++) {
- Vector v = new Vector(dim);
- v.set(d, 1);
- Vector ax = projectScaledToRender(v);
- minmaxx.put(ax.get(0));
- minmaxy.put(ax.get(1));
- }
- return new Pair<DoubleMinMax, DoubleMinMax>(minmaxx, minmaxy);
- }
+ public CanvasSize estimateViewport() {
+ if(viewport == null) {
+ final int dim = proj.getDimensionality();
+ DoubleMinMax minmaxx = new DoubleMinMax();
+ DoubleMinMax minmaxy = new DoubleMinMax();
- @Override
- public String estimateTransformString(double margin, double width, double height) {
- Pair<DoubleMinMax, DoubleMinMax> minmax = estimateViewport();
- double sizex = (minmax.first.getMax() - minmax.first.getMin());
- double sizey = (minmax.second.getMax() - minmax.second.getMin());
- return SVGUtil.makeMarginTransform(width, height, sizex, sizey, margin) + " translate(" + SVGUtil.fmt(sizex / 2) + " " + SVGUtil.fmt(sizey / 2) + ")";
+ // Origin
+ Vector orig = new Vector(dim);
+ orig = projectScaledToRender(orig);
+ minmaxx.put(orig.get(0));
+ minmaxy.put(orig.get(1));
+ // Diagonal point
+ Vector diag = new Vector(dim);
+ for(int d2 = 0; d2 < dim; d2++) {
+ diag.set(d2, 1);
+ }
+ diag = projectScaledToRender(diag);
+ minmaxx.put(diag.get(0));
+ minmaxy.put(diag.get(1));
+ // Axis end points
+ for(int d = 0; d < dim; d++) {
+ Vector v = new Vector(dim);
+ v.set(d, 1);
+ Vector ax = projectScaledToRender(v);
+ minmaxx.put(ax.get(0));
+ minmaxy.put(ax.get(1));
+ }
+ viewport = new CanvasSize(minmaxx.getMin(), minmaxx.getMax(), minmaxy.getMin(), minmaxy.getMax());
+ }
+ return viewport;
}
/**
@@ -169,18 +168,29 @@ public class AffineProjection extends AbstractProjection implements Projection2D
}
@Override
- public double[] fastProjectDataToRenderSpace(Vector data) {
- return fastProjectScaledToRender(projectDataToScaledSpace(data));
+ public double[] fastProjectDataToRenderSpace(double[] data) {
+ return fastProjectScaledToRenderSpace(fastProjectDataToScaledSpace(data));
}
@Override
public double[] fastProjectDataToRenderSpace(NumberVector<?, ?> data) {
- return fastProjectScaledToRender(projectDataToScaledSpace(data));
+ return fastProjectScaledToRenderSpace(fastProjectDataToScaledSpace(data));
}
@Override
- public double[] fastProjectScaledToRender(Vector v) {
- final double[] vr = v.getArrayRef();
+ public double[] fastProjectDataToScaledSpace(double[] data) {
+ // FIXME: implement with less objects?
+ return projectDataToScaledSpace(new Vector(data)).getArrayRef();
+ }
+
+ @Override
+ public double[] fastProjectDataToScaledSpace(NumberVector<?, ?> data) {
+ // FIXME: implement with less objects?
+ return projectDataToScaledSpace(data).getArrayRef();
+ }
+
+ @Override
+ public double[] fastProjectScaledToRenderSpace(double[] vr) {
double x = 0.0;
double y = 0.0;
double s = 0.0;
@@ -205,18 +215,19 @@ public class AffineProjection extends AbstractProjection implements Projection2D
}
@Override
- public double[] fastProjectRelativeDataToRenderSpace(Vector data) {
- return fastProjectRelativeScaledToRender(projectRelativeDataToScaledSpace(data));
+ public double[] fastProjectRelativeDataToRenderSpace(double[] data) {
+ // FIXME: implement with less objects?
+ return fastProjectRelativeScaledToRenderSpace(projectRelativeDataToScaledSpace(new Vector(data)).getArrayRef());
}
@Override
public double[] fastProjectRelativeDataToRenderSpace(NumberVector<?, ?> data) {
- return fastProjectRelativeScaledToRender(projectRelativeDataToScaledSpace(data));
+ // FIXME: implement with less objects?
+ return fastProjectRelativeScaledToRenderSpace(projectRelativeDataToScaledSpace(data).getArrayRef());
}
@Override
- public double[] fastProjectRelativeScaledToRender(Vector v) {
- final double[] vr = v.getArrayRef();
+ public double[] fastProjectRelativeScaledToRenderSpace(double[] vr) {
double x = 0.0;
double y = 0.0;
@@ -233,6 +244,27 @@ public class AffineProjection extends AbstractProjection implements Projection2D
}
@Override
+ public double[] fastProjectRenderToDataSpace(double[] data) {
+ double[] ret = fastProjectRenderToScaledSpace(data);
+ for(int d = 0; d < scales.length; d++) {
+ ret[d] = scales[d].getUnscaled(ret[d]);
+ }
+ return ret;
+ }
+
+ @Override
+ public double[] fastProjectRenderToScaledSpace(double[] v) {
+ if(v.length == scales.length) {
+ return projectRenderToScaled(new Vector(v)).getArrayRef();
+ }
+ double[] c = Arrays.copyOf(v, scales.length);
+ for(int d = v.length; d < scales.length; d++) {
+ c[d] = 0.5;
+ }
+ return projectRenderToScaled(new Vector(c)).getArrayRef();
+ }
+
+ @Override
public BitSet getVisibleDimensions2D() {
final int dim = proj.getDimensionality();
BitSet actDim = new BitSet(dim);
@@ -240,7 +272,7 @@ public class AffineProjection extends AbstractProjection implements Projection2D
for(int d = 0; d < dim; d++) {
vScale.setZero();
vScale.set(d, 1);
- double[] vRender = fastProjectScaledToRender(vScale);
+ double[] vRender = fastProjectScaledToRenderSpace(vScale.getArrayRef());
// TODO: Can't we do this by inspecting the projection matrix directly?
if(vRender[0] != 0.0 || vRender[1] != 0) {
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projections/CanvasSize.java b/src/de/lmu/ifi/dbs/elki/visualization/projections/CanvasSize.java
new file mode 100644
index 00000000..cfcec564
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/projections/CanvasSize.java
@@ -0,0 +1,139 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Size of a canvas. A 2D bounding rectangle.
+ *
+ * @author Erich Schubert
+ */
+public class CanvasSize {
+ /**
+ * Minimum X
+ */
+ public final double minx;
+
+ /**
+ * Maximum X
+ */
+ public final double maxx;
+
+ /**
+ * Minimum Y
+ */
+ public final double miny;
+
+ /**
+ * Maximum Y
+ */
+ public final double maxy;
+
+ /**
+ * Constructor.
+ *
+ * @param minx Minimum X
+ * @param maxx Maximum X
+ * @param miny Minimum Y
+ * @param maxy Maximum Y
+ */
+ public CanvasSize(double minx, double maxx, double miny, double maxy) {
+ super();
+ this.minx = minx;
+ this.maxx = maxx;
+ this.miny = miny;
+ this.maxy = maxy;
+ }
+
+ /**
+ * @return the mininum X
+ */
+ public double getMinX() {
+ return minx;
+ }
+
+ /**
+ * @return the maximum X
+ */
+ public double getMaxX() {
+ return maxx;
+ }
+
+ /**
+ * @return the minimum Y
+ */
+ public double getMinY() {
+ return miny;
+ }
+
+ /**
+ * @return the maximum Y
+ */
+ public double getMaxY() {
+ return maxy;
+ }
+
+ /**
+ * @return the length on X
+ */
+ public double getDiffX() {
+ return maxx - minx;
+ }
+
+ /**
+ * @return the length on Y
+ */
+ public double getDiffY() {
+ return maxy - miny;
+ }
+
+ /**
+ * Continue a line along a given direction to the margin.
+ *
+ * @param origin Origin point
+ * @param delta Direction vector
+ * @return scaling factor for delta vector
+ */
+ public double continueToMargin(double[] origin, double[] delta) {
+ assert (delta.length == 2 && origin.length == 2);
+ double factor = Double.POSITIVE_INFINITY;
+ if(delta[0] > 0) {
+ factor = Math.min(factor, (maxx - origin[0]) / delta[0]);
+ }
+ else if(delta[0] < 0) {
+ factor = Math.min(factor, (origin[0] - minx) / -delta[0]);
+ }
+ if(delta[1] > 0) {
+ factor = Math.min(factor, (maxy - origin[1]) / delta[1]);
+ }
+ else if(delta[1] < 0) {
+ factor = Math.min(factor, (origin[1] - miny) / -delta[1]);
+ }
+ return factor;
+ }
+
+ @Override
+ public String toString() {
+ return "CanvasSize[x=" + minx + ":" + maxx + ", y=" + miny + ":" + maxy + "]";
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projections/FullProjection.java b/src/de/lmu/ifi/dbs/elki/visualization/projections/FullProjection.java
new file mode 100644
index 00000000..cc1433aa
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/projections/FullProjection.java
@@ -0,0 +1,176 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.math.linearalgebra.Vector;
+import de.lmu.ifi.dbs.elki.visualization.projections.Projection;
+
+/**
+ * Full vector space projections.
+ *
+ * These rather portable projections offer a large choice of functions, at the
+ * cost of often being a bit slower than the low level functions.
+ *
+ * Note: this interface and methods may be removed, unless there is a clear use
+ * case for them as opposed to always using the low-level fast projections.
+ *
+ * @author Erich Schubert
+ */
+public interface FullProjection extends Projection {
+ /**
+ * Project a vector from scaled space to rendering space.
+ *
+ * @param v vector in scaled space
+ * @return vector in rendering space
+ */
+ public Vector projectScaledToRender(Vector v);
+
+ /**
+ * Project a vector from rendering space to scaled space.
+ *
+ * @param v vector in rendering space
+ * @return vector in scaled space
+ */
+ public Vector projectRenderToScaled(Vector v);
+
+ /**
+ * Project a relative vector from scaled space to rendering space.
+ *
+ * @param v relative vector in scaled space
+ * @return relative vector in rendering space
+ */
+ public Vector projectRelativeScaledToRender(Vector v);
+
+ /**
+ * Project a relative vector from rendering space to scaled space.
+ *
+ * @param v relative vector in rendering space
+ * @return relative vector in scaled space
+ */
+ public Vector projectRelativeRenderToScaled(Vector v);
+
+ /**
+ * Project a data vector from data space to scaled space.
+ *
+ * @param data vector in data space
+ * @return vector in scaled space
+ */
+ public Vector projectDataToScaledSpace(NumberVector<?, ?> data);
+
+ /**
+ * Project a data vector from data space to scaled space.
+ *
+ * @param data vector in data space
+ * @return vector in scaled space
+ */
+ public Vector projectDataToScaledSpace(Vector data);
+
+ /**
+ * Project a relative data vector from data space to scaled space.
+ *
+ * @param data relative vector in data space
+ * @return relative vector in scaled space
+ */
+ public Vector projectRelativeDataToScaledSpace(NumberVector<?, ?> data);
+
+ /**
+ * Project a relative data vector from data space to scaled space.
+ *
+ * @param data relative vector in data space
+ * @return relative vector in scaled space
+ */
+ public Vector projectRelativeDataToScaledSpace(Vector data);
+
+ /**
+ * Project a data vector from data space to rendering space.
+ *
+ * @param data vector in data space
+ * @return vector in rendering space
+ */
+ public Vector projectDataToRenderSpace(NumberVector<?, ?> data);
+
+ /**
+ * Project a data vector from data space to rendering space.
+ *
+ * @param data vector in data space
+ * @return vector in rendering space
+ */
+ public Vector projectDataToRenderSpace(Vector data);
+
+ /**
+ * Project a vector from scaled space to data space.
+ *
+ * @param <NV> Vector type
+ * @param v vector in scaled space
+ * @param factory Object factory
+ * @return vector in data space
+ */
+ public <NV extends NumberVector<NV, ?>> NV projectScaledToDataSpace(Vector v, NV factory);
+
+ /**
+ * Project a vector from rendering space to data space.
+ *
+ * @param <NV> Vector type
+ * @param v vector in rendering space
+ * @param prototype Object factory
+ * @return vector in data space
+ */
+ public <NV extends NumberVector<NV, ?>> NV projectRenderToDataSpace(Vector v, NV prototype);
+
+ /**
+ * Project a relative data vector from data space to rendering space.
+ *
+ * @param data relative vector in data space
+ * @return relative vector in rendering space
+ */
+ public Vector projectRelativeDataToRenderSpace(NumberVector<?, ?> data);
+
+ /**
+ * Project a relative data vector from data space to rendering space.
+ *
+ * @param data relative vector in data space
+ * @return relative vector in rendering space
+ */
+ public Vector projectRelativeDataToRenderSpace(Vector data);
+
+ /**
+ * Project a relative vector from scaled space to data space.
+ *
+ * @param <NV> Vector type
+ * @param v relative vector in scaled space
+ * @param prototype Object factory
+ * @return relative vector in data space
+ */
+ public <NV extends NumberVector<NV, ?>> NV projectRelativeScaledToDataSpace(Vector v, NV prototype);
+
+ /**
+ * Project a relative vector from rendering space to data space.
+ *
+ * @param <NV> Vector type
+ * @param v relative vector in rendering space
+ * @param prototype Object factory
+ * @return relative vector in data space
+ */
+ public <NV extends NumberVector<NV, ?>> NV projectRelativeRenderToDataSpace(Vector v, NV prototype);
+}
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 fcd6089d..903a5e6b 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,10 +23,8 @@ package de.lmu.ifi.dbs.elki.visualization.projections;
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.math.linearalgebra.Vector;
+import de.lmu.ifi.dbs.elki.math.scales.LinearScale;
import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
-import de.lmu.ifi.dbs.elki.visualization.scales.LinearScale;
import de.lmu.ifi.dbs.elki.visualization.style.StyleLibrary;
/**
@@ -40,8 +38,6 @@ import de.lmu.ifi.dbs.elki.visualization.style.StyleLibrary;
* @apiviz.landmark
*
* @apiviz.composedOf LinearScale
- * @apiviz.uses NumberVector
- * @apiviz.uses Vector
*/
public interface Projection extends HierarchicalResult {
/**
@@ -64,140 +60,4 @@ public interface Projection extends HierarchicalResult {
* @return Scale class
*/
public LinearScale getScale(int d);
-
- /**
- * Project a vector from scaled space to rendering space.
- *
- * @param v vector in scaled space
- * @return vector in rendering space
- */
- public Vector projectScaledToRender(Vector v);
-
- /**
- * Project a vector from rendering space to scaled space.
- *
- * @param v vector in rendering space
- * @return vector in scaled space
- */
- public Vector projectRenderToScaled(Vector v);
-
- /**
- * Project a relative vector from scaled space to rendering space.
- *
- * @param v relative vector in scaled space
- * @return relative vector in rendering space
- */
- public Vector projectRelativeScaledToRender(Vector v);
-
- /**
- * Project a relative vector from rendering space to scaled space.
- *
- * @param v relative vector in rendering space
- * @return relative vector in scaled space
- */
- public Vector projectRelativeRenderToScaled(Vector v);
-
- /**
- * Project a data vector from data space to scaled space.
- *
- * @param data vector in data space
- * @return vector in scaled space
- */
- public Vector projectDataToScaledSpace(NumberVector<?, ?> data);
-
- /**
- * Project a data vector from data space to scaled space.
- *
- * @param data vector in data space
- * @return vector in scaled space
- */
- public Vector projectDataToScaledSpace(Vector data);
-
- /**
- * Project a relative data vector from data space to scaled space.
- *
- * @param data relative vector in data space
- * @return relative vector in scaled space
- */
- public Vector projectRelativeDataToScaledSpace(NumberVector<?, ?> data);
-
- /**
- * Project a relative data vector from data space to scaled space.
- *
- * @param data relative vector in data space
- * @return relative vector in scaled space
- */
- public Vector projectRelativeDataToScaledSpace(Vector data);
-
- /**
- * Project a data vector from data space to rendering space.
- *
- * @param data vector in data space
- * @return vector in rendering space
- */
- public Vector projectDataToRenderSpace(NumberVector<?, ?> data);
-
- /**
- * Project a data vector from data space to rendering space.
- *
- * @param data vector in data space
- * @return vector in rendering space
- */
- public Vector projectDataToRenderSpace(Vector data);
-
- /**
- * Project a vector from scaled space to data space.
- *
- * @param <NV> Vector type
- * @param v vector in scaled space
- * @param factory Object factory
- * @return vector in data space
- */
- public <NV extends NumberVector<NV, ?>> NV projectScaledToDataSpace(Vector v, NV factory);
-
- /**
- * Project a vector from rendering space to data space.
- *
- * @param <NV> Vector type
- * @param v vector in rendering space
- * @param prototype Object factory
- * @return vector in data space
- */
- public <NV extends NumberVector<NV, ?>> NV projectRenderToDataSpace(Vector v, NV prototype);
-
- /**
- * Project a relative data vector from data space to rendering space.
- *
- * @param data relative vector in data space
- * @return relative vector in rendering space
- */
- public Vector projectRelativeDataToRenderSpace(NumberVector<?, ?> data);
-
- /**
- * Project a relative data vector from data space to rendering space.
- *
- * @param data relative vector in data space
- * @return relative vector in rendering space
- */
- public Vector projectRelativeDataToRenderSpace(Vector data);
-
- /**
- * Project a relative vector from scaled space to data space.
- *
- * @param <NV> Vector type
- * @param v relative vector in scaled space
- * @param prototype Object factory
- * @return relative vector in data space
- */
- public <NV extends NumberVector<NV, ?>> NV projectRelativeScaledToDataSpace(Vector v, NV prototype);
-
- /**
- * Project a relative vector from rendering space to data space.
- *
- * @param <NV> Vector type
- * @param v relative vector in rendering space
- * @param prototype Object factory
- * @return relative vector in data space
- */
- public <NV extends NumberVector<NV, ?>> NV projectRelativeRenderToDataSpace(Vector v, NV prototype);
} \ No newline at end of file
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 746b3b68..2232e0b9 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) 2011
+ Copyright (C) 2012
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 9fcb0b15..66518c8f 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -26,9 +26,6 @@ package de.lmu.ifi.dbs.elki.visualization.projections;
import java.util.BitSet;
import de.lmu.ifi.dbs.elki.data.NumberVector;
-import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
-import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
-import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
/**
* Projections that have specialized methods to only compute the first two
@@ -45,7 +42,7 @@ public interface Projection2D extends Projection {
* @param data vector in data space
* @return vector in rendering space
*/
- public double[] fastProjectDataToRenderSpace(Vector data);
+ public double[] fastProjectDataToRenderSpace(double[] data);
/**
* Project a data vector from data space to rendering space.
@@ -56,12 +53,53 @@ public interface Projection2D extends Projection {
public double[] fastProjectDataToRenderSpace(NumberVector<?, ?> data);
/**
+ * Project a data vector from data space to scaled space.
+ *
+ * @param data vector in data space
+ * @return vector in scaled space
+ */
+ public double[] fastProjectDataToScaledSpace(double[] data);
+
+ /**
+ * Project a data vector from data space to scaled space.
+ *
+ * @param data vector in data space
+ * @return vector in scaled space
+ */
+ public double[] fastProjectDataToScaledSpace(NumberVector<?, ?> data);
+
+ /**
* Project a vector from scaled space to rendering space.
*
* @param v vector in scaled space
* @return vector in rendering space
*/
- public double[] fastProjectScaledToRender(Vector v);
+ public double[] fastProjectScaledToRenderSpace(double[] v);
+
+ /**
+ * Project a data vector from rendering space to data space.
+ *
+ * @param data vector in rendering space
+ * @return vector in data space
+ */
+ public double[] fastProjectRenderToDataSpace(double[] data);
+
+ /**
+ * Project a data vector from rendering space to data space.
+ *
+ * @param data vector in rendering space
+ * @param prototype Prototype to create vector from
+ * @return vector in data space
+ */
+ // public <V extends NumberVector<V, ?>> V fastProjectRenderToDataSpace(double[] data, V prototype);
+
+ /**
+ * Project a vector from rendering space to scaled space.
+ *
+ * @param v vector in rendering space
+ * @return vector in scaled space
+ */
+ public double[] fastProjectRenderToScaledSpace(double[] v);
/**
* Project a data vector from data space to rendering space.
@@ -69,7 +107,7 @@ public interface Projection2D extends Projection {
* @param data vector in data space
* @return vector in rendering space
*/
- public double[] fastProjectRelativeDataToRenderSpace(Vector data);
+ public double[] fastProjectRelativeDataToRenderSpace(double[] data);
/**
* Project a data vector from data space to rendering space.
@@ -85,24 +123,16 @@ public interface Projection2D extends Projection {
* @param v vector in scaled space
* @return vector in rendering space
*/
- public double[] fastProjectRelativeScaledToRender(Vector v);
+ public double[] fastProjectRelativeScaledToRenderSpace(double[] v);
+ // FIXME: add missing relative projection functions
+
/**
* Estimate the viewport requirements
*
- * @return MinMax for x and y obtained from projecting scale endpoints
- */
- public Pair<DoubleMinMax, DoubleMinMax> estimateViewport();
-
- /**
- * Get a SVG transformation string to bring the contents into the unit cube.
- *
- * @param margin extra margin to add.
- * @param width Width
- * @param height Height
- * @return transformation string.
+ * @return Canvas size obtained from projecting scale endpoints
*/
- public String estimateTransformString(double margin, double width, double height);
+ public CanvasSize estimateViewport();
/**
* Get a bit set of dimensions that are visible.
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projections/ProjectionParallel.java b/src/de/lmu/ifi/dbs/elki/visualization/projections/ProjectionParallel.java
new file mode 100644
index 00000000..03e8a245
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/projections/ProjectionParallel.java
@@ -0,0 +1,196 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.math.scales.LinearScale;
+
+/**
+ * Projection to parallel coordinates that allows reordering and inversion of
+ * axes.
+ *
+ * Note: when using this projection, pay attention to the two different schemes
+ * of dimension numbering: by input dimension and by axis position.
+ *
+ * @author Robert Rödler
+ * @author Erich Schubert
+ */
+public interface ProjectionParallel extends Projection {
+ /**
+ * Get inversion flag of axis.
+ *
+ * @param axis Axis (reordered) position
+ * @return Inversion flag
+ */
+ public boolean isAxisInverted(int axis);
+
+ /**
+ * Set inversion flag of axis.
+ *
+ * @param axis Axis (reordered) position
+ * @param bool Value of inversion flag
+ */
+ public void setAxisInverted(int axis, boolean bool);
+
+ /**
+ * Toggle inverted flag of axis.
+ *
+ * @param axis Axis (reordered) position
+ */
+ public void toggleAxisInverted(int axis);
+
+ /**
+ * Get inversion flag of dimension.
+ *
+ * @param truedim Dimension in original numbering
+ * @return Inversion flag
+ */
+ public boolean isDimInverted(int truedim);
+
+ /**
+ * Set inversion flag of a dimension.
+ *
+ * @param truedim Dimension in original numbering
+ * @param bool Value of inversion flag
+ */
+ public void setDimInverted(int truedim, boolean bool);
+
+ /**
+ * Toggle inverted flag of dimension.
+ *
+ * @param truedim Dimension in original numbering
+ */
+ public void toggleDimInverted(int truedim);
+
+ /**
+ * Get scale for the given axis
+ *
+ * @param axis Axis (reordered) position
+ * @return Axis scale
+ */
+ public LinearScale getAxisScale(int axis);
+
+ /**
+ * Test whether the current axis is visible
+ *
+ * @param axis Axis (reordered) position
+ * @return Visibility of axis
+ */
+ public boolean isAxisVisible(int axis);
+
+ /**
+ * Set the visibility of the axis.
+ *
+ * @param axis Axis number
+ * @param vis Visibility status
+ */
+ public void setAxisVisible(int axis, boolean vis);
+
+ /**
+ * Toggle visibility of the axis.
+ *
+ * @param axis Axis number
+ */
+ public void toggleAxisVisible(int axis);
+
+ /**
+ * Get the number of visible dimension.
+ *
+ * @return Number of visible dimensions
+ */
+ public int getVisibleDimensions();
+
+ /**
+ * Exchange axes A and B
+ * @param a First axis
+ * @param b Second axis
+ */
+ public void swapAxes(int a, int b);
+
+ /**
+ * shift a dimension to another position
+ *
+ * @param axis axis to shift
+ * @param rn new position
+ */
+ public void moveAxis(int axis, int rn);
+
+ /**
+ * Get the dimension for the given axis number
+ *
+ * @param axis Axis number
+ * @return Dimension
+ */
+ public int getDimForAxis(int axis);
+
+ /**
+ * Get the dimension for the given visible axis
+ *
+ * @param axis Axis number (visible axes only)
+ * @return Dimension
+ */
+ public int getDimForVisibleAxis(int axis);
+
+ /**
+ * Fast project a vector from data to render space
+ *
+ * @param v Input vector
+ * @return Vector with reordering, inversions and scales applied.
+ */
+ public double[] fastProjectDataToRenderSpace(double[] v);
+
+ /**
+ * Fast project a vector from data to render space
+ *
+ * @param v Input vector
+ * @return Vector with reordering, inversions and scales applied.
+ */
+ public double[] fastProjectDataToRenderSpace(NumberVector<?, ?> v);
+
+ /**
+ * Project the value of a single axis to its display value
+ *
+ * @param value Input value
+ * @param axis Axis to use for scaling and inversion
+ * @return Transformed value
+ */
+ public double fastProjectDataToRenderSpace(double value, int axis);
+
+ /**
+ * Project a display value back to the original data space
+ *
+ * @param value transformed value
+ * @param axis Axis to use for scaling and inversion
+ * @return Original value
+ */
+ public double fastProjectRenderToDataSpace(double value, int axis);
+
+ /**
+ * Find the axis assinged to the given dimension.
+ *
+ * @param truedim Dimension
+ * @return Axis number
+ */
+ public int getAxisForDim(int truedim);
+} \ No newline at end of file
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 e208b34b..b701c934 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) 2011
+ Copyright (C) 2012
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.visualization.projections;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
-import de.lmu.ifi.dbs.elki.visualization.scales.LinearScale;
+import de.lmu.ifi.dbs.elki.math.scales.LinearScale;
/**
* Dimension-selecting 1D projection.
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 15108853..1964f12b 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) 2011
+ Copyright (C) 2012
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.visualization.projections;
import java.util.BitSet;
import de.lmu.ifi.dbs.elki.data.NumberVector;
-import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
-import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
-import de.lmu.ifi.dbs.elki.visualization.scales.LinearScale;
-import de.lmu.ifi.dbs.elki.visualization.svg.SVGUtil;
+import de.lmu.ifi.dbs.elki.math.scales.LinearScale;
/**
* Dimension-selecting 2D projection.
@@ -62,9 +59,9 @@ public class Simple2D extends AbstractSimpleProjection implements Projection2D {
}
@Override
- public double[] fastProjectDataToRenderSpace(Vector data) {
- double x = (scales[dim1].getScaled(data.get(dim1)) - 0.5) * SCALE;
- double y = (scales[dim2].getScaled(data.get(dim2)) - 0.5) * -SCALE;
+ public double[] fastProjectDataToRenderSpace(double[] data) {
+ double x = (scales[dim1].getScaled(data[dim1]) - 0.5) * SCALE;
+ double y = (scales[dim2].getScaled(data[dim2]) - 0.5) * -SCALE;
return new double[] { x, y };
}
@@ -76,16 +73,70 @@ public class Simple2D extends AbstractSimpleProjection implements Projection2D {
}
@Override
- public double[] fastProjectScaledToRender(Vector v) {
- double x = (v.get(dim1) - 0.5) * SCALE;
- double y = (v.get(dim2) - 0.5) * -SCALE;
+ public double[] fastProjectDataToScaledSpace(double[] data) {
+ final int dim = data.length;
+ double[] ds = new double[dim];
+ for(int d = 0; d < dim; d++) {
+ ds[d] = scales[d].getScaled(data[d]);
+ }
+ return ds;
+ }
+
+ @Override
+ public double[] fastProjectDataToScaledSpace(NumberVector<?, ?> data) {
+ final int dim = data.getDimensionality();
+ double[] ds = new double[dim];
+ for(int d = 0; d < dim; d++) {
+ ds[d] = scales[d].getScaled(data.doubleValue(d + 1));
+ }
+ return ds;
+ }
+
+ @Override
+ public double[] fastProjectScaledToRenderSpace(double[] v) {
+ double x = (v[dim1] - 0.5) * SCALE;
+ double y = (v[dim2] - 0.5) * -SCALE;
return new double[] { x, y };
}
@Override
- public double[] fastProjectRelativeDataToRenderSpace(Vector data) {
- double x = scales[dim1].getRelativeScaled(data.get(dim1)) * SCALE;
- double y = scales[dim2].getRelativeScaled(data.get(dim2)) * -SCALE;
+ public double[] fastProjectRenderToDataSpace(double[] v) {
+ double[] ret = new double[scales.length];
+ for(int d = 0; d < scales.length; d++) {
+ if(d == dim1) {
+ ret[d] = scales[d].getUnscaled((v[0] / SCALE) + 0.5);
+ }
+ else if(d == dim2) {
+ ret[d] = scales[d].getUnscaled((v[1] / -SCALE) + 0.5);
+ }
+ else {
+ ret[d] = scales[d].getUnscaled(0.5);
+ }
+ }
+ return ret;
+ }
+
+ @Override
+ public double[] fastProjectRenderToScaledSpace(double[] v) {
+ double[] ret = new double[scales.length];
+ for(int d = 0; d < scales.length; d++) {
+ if(d == dim1) {
+ ret[d] = (v[0] / SCALE) + 0.5;
+ }
+ else if(d == dim2) {
+ ret[d] = (v[1] / -SCALE) + 0.5;
+ }
+ else {
+ ret[d] = 0.5;
+ }
+ }
+ return ret;
+ }
+
+ @Override
+ public double[] fastProjectRelativeDataToRenderSpace(double[] data) {
+ double x = scales[dim1].getRelativeScaled(data[dim1]) * SCALE;
+ double y = scales[dim2].getRelativeScaled(data[dim2]) * -SCALE;
return new double[] { x, y };
}
@@ -97,8 +148,7 @@ public class Simple2D extends AbstractSimpleProjection implements Projection2D {
}
@Override
- public double[] fastProjectRelativeScaledToRender(Vector v) {
- final double[] vr = v.getArrayRef();
+ public double[] fastProjectRelativeScaledToRenderSpace(double[] vr) {
double x = vr[dim1] * SCALE;
double y = vr[dim2] * -SCALE;
return new double[] { x, y };
@@ -113,22 +163,8 @@ public class Simple2D extends AbstractSimpleProjection implements Projection2D {
}
@Override
- public Pair<DoubleMinMax, DoubleMinMax> estimateViewport() {
- DoubleMinMax minmaxx = new DoubleMinMax();
- DoubleMinMax minmaxy = new DoubleMinMax();
- minmaxx.put(SCALE * .5);
- minmaxx.put(-SCALE * .5);
- minmaxy.put(SCALE * .5);
- minmaxy.put(-SCALE * .5);
- return new Pair<DoubleMinMax, DoubleMinMax>(minmaxx, minmaxy);
- }
-
- @Override
- public String estimateTransformString(double margin, double width, double height) {
- Pair<DoubleMinMax, DoubleMinMax> minmax = estimateViewport();
- double sizex = (minmax.first.getMax() - minmax.first.getMin());
- double sizey = (minmax.second.getMax() - minmax.second.getMin());
- return SVGUtil.makeMarginTransform(width, height, sizex, sizey, margin) + " translate(" + SVGUtil.fmt(sizex / 2) + " " + SVGUtil.fmt(sizey / 2) + ")";
+ public CanvasSize estimateViewport() {
+ return new CanvasSize(-SCALE * .5, SCALE * .5, -SCALE * .5, SCALE * .5);
}
@Override
@@ -142,7 +178,7 @@ public class Simple2D extends AbstractSimpleProjection implements Projection2D {
if(ldim > 0) {
System.arraycopy(s, 0, r, 2, ldim);
}
- if (hdim - ldim > 1) {
+ if(hdim - ldim > 1) {
System.arraycopy(s, ldim + 1, r, ldim + 2, hdim - (ldim + 1));
}
if(hdim + 1 < s.length) {
@@ -164,7 +200,7 @@ public class Simple2D extends AbstractSimpleProjection implements Projection2D {
System.arraycopy(s, 2, r, 0, ldim);
}
// ldim = s[0 or 1]
- if (hdim - ldim > 1) {
+ if(hdim - ldim > 1) {
System.arraycopy(s, ldim + 2, r, ldim + 1, hdim - (ldim + 1));
}
// hdim = s[0 or 1]
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projections/SimpleParallel.java b/src/de/lmu/ifi/dbs/elki/visualization/projections/SimpleParallel.java
new file mode 100644
index 00000000..c843d61d
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/projections/SimpleParallel.java
@@ -0,0 +1,286 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.math.scales.LinearScale;
+import de.lmu.ifi.dbs.elki.result.BasicResult;
+import de.lmu.ifi.dbs.elki.visualization.style.StyleLibrary;
+
+/**
+ * Simple parallel projection
+ *
+ * Scaled space: reordered, scaled and inverted. Lower dimensionality! [0:1]
+ * Render space: not used here; no recentering needed.
+ *
+ * @author Robert Rödler
+ * @author Erich Schubert
+ */
+public class SimpleParallel extends BasicResult implements ProjectionParallel {
+ /**
+ * Number of visible dimensions
+ */
+ int visDims;
+
+ /**
+ * Flags for the dimensions
+ */
+ byte[] flags;
+
+ /**
+ * Ordering of dimensions
+ */
+ int[] dimOrder;
+
+ /**
+ * Scales
+ */
+ private LinearScale[] scales;
+
+ /**
+ * Flag for visibility
+ */
+ final static byte FLAG_HIDDEN = 1;
+
+ /**
+ * Flag for inverted dimensions
+ *
+ * TODO: handle inversions via scales?
+ */
+ final static byte FLAG_INVERTED = 2;
+
+ /**
+ * Constructor.
+ *
+ * @param scales Scales to use
+ */
+ public SimpleParallel(LinearScale[] scales) {
+ super("Parallel projection", "parallel-projection");
+ this.scales = scales;
+ visDims = scales.length;
+ flags = new byte[scales.length];
+ dimOrder = new int[scales.length];
+ for(int i = 0; i < dimOrder.length; i++) {
+ dimOrder[i] = i;
+ }
+ }
+
+ @Override
+ public LinearScale getScale(int dim) {
+ return scales[dim];
+ }
+
+ @Override
+ public boolean isAxisInverted(int axis) {
+ return isDimInverted(dimOrder[axis]);
+ }
+
+ @Override
+ public void setAxisInverted(int axis, boolean bool) {
+ setDimInverted(dimOrder[axis], bool);
+ }
+
+ @Override
+ public void toggleAxisInverted(int axis) {
+ toggleDimInverted(dimOrder[axis]);
+ }
+
+ @Override
+ public boolean isDimInverted(int truedim) {
+ return (flags[truedim] & FLAG_INVERTED) == FLAG_INVERTED;
+ }
+
+ @Override
+ public void setDimInverted(int truedim, boolean bool) {
+ if(bool) {
+ flags[truedim] |= FLAG_INVERTED;
+ }
+ else {
+ flags[truedim] &= ~FLAG_INVERTED;
+ }
+ }
+
+ @Override
+ public void toggleDimInverted(int truedim) {
+ flags[truedim] ^= FLAG_INVERTED;
+ }
+
+ @Override
+ public LinearScale getAxisScale(int axis) {
+ return scales[dimOrder[axis]];
+ }
+
+ protected boolean isDimHidden(int truedim) {
+ return (flags[truedim] & FLAG_HIDDEN) == FLAG_HIDDEN;
+ }
+
+ @Override
+ public boolean isAxisVisible(int dim) {
+ return !isDimHidden(dimOrder[dim]);
+ }
+
+ @Override
+ public void setAxisVisible(int dim, boolean vis) {
+ boolean prev = isAxisVisible(dim);
+ if(prev == vis) {
+ return;
+ }
+ if(vis) {
+ flags[dimOrder[dim]] &= ~FLAG_HIDDEN;
+ visDims++;
+ }
+ else {
+ flags[dimOrder[dim]] |= FLAG_HIDDEN;
+ visDims--;
+ }
+ }
+
+ @Override
+ public void toggleAxisVisible(int dim) {
+ boolean prev = isAxisVisible(dim);
+ if(!prev) {
+ flags[dimOrder[dim]] &= ~FLAG_HIDDEN;
+ visDims++;
+ }
+ else {
+ flags[dimOrder[dim]] |= FLAG_HIDDEN;
+ visDims--;
+ }
+ }
+
+ @Override
+ public int getVisibleDimensions() {
+ return visDims;
+ }
+
+ @Override
+ public int getDimForAxis(int pos) {
+ return dimOrder[pos];
+ }
+
+ @Override
+ public int getDimForVisibleAxis(int pos) {
+ for(int i = 0; i < scales.length; i++) {
+ if (isAxisVisible(i)) {
+ if (pos == 0) {
+ return dimOrder[i];
+ }
+ pos--;
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public void swapAxes(int a, int b) {
+ int temp = dimOrder[a];
+ dimOrder[a] = dimOrder[b];
+ dimOrder[b] = temp;
+ }
+
+ @Override
+ public void moveAxis(int src, int dest) {
+ if(src > dest) {
+ int temp = dimOrder[src];
+ System.arraycopy(dimOrder, dest, dimOrder, dest + 1, src - dest);
+ dimOrder[dest] = temp;
+ }
+ else if(src < dest) {
+ int temp = dimOrder[src];
+ System.arraycopy(dimOrder, src + 1, dimOrder, src, dest - src);
+ dimOrder[dest - 1] = temp;
+ }
+ }
+
+ @Override
+ public double[] fastProjectDataToRenderSpace(NumberVector<?, ?> data) {
+ double[] v = new double[visDims];
+ for(int j = 0, o = 0; j < scales.length; j++) {
+ if(isDimHidden(j)) {
+ continue;
+ }
+ int i = dimOrder[j];
+ v[o] = scales[i].getScaled(data.doubleValue(i + 1));
+ if(!isDimInverted(i)) {
+ v[o] = 1 - v[o];
+ }
+ v[o] *= StyleLibrary.SCALE;
+ o++;
+ }
+ return v;
+ }
+
+ @Override
+ public double[] fastProjectDataToRenderSpace(double[] data) {
+ double[] v = new double[visDims];
+ for(int j = 0, o = 0; j < scales.length; j++) {
+ if(isDimHidden(j)) {
+ continue;
+ }
+ int i = dimOrder[j];
+ v[o] = scales[i].getScaled(data[i]);
+ if(!isDimInverted(i)) {
+ v[o] = 1 - v[o];
+ }
+ v[o] *= StyleLibrary.SCALE;
+ o++;
+ }
+ return v;
+ }
+
+ @Override
+ public double fastProjectRenderToDataSpace(double v, int projdim) {
+ int truedim = dimOrder[projdim];
+ v /= StyleLibrary.SCALE;
+ if(!isDimInverted(truedim)) {
+ v = 1 - v;
+ }
+ return scales[truedim].getUnscaled(v);
+ }
+
+ @Override
+ public double fastProjectDataToRenderSpace(double value, int dim) {
+ double temp = scales[dimOrder[dim]].getScaled(value);
+ temp *= StyleLibrary.SCALE;
+ if(!isAxisInverted(dimOrder[dim])) {
+ return temp;
+ }
+ return 1 - temp;
+ }
+
+ @Override
+ public int getAxisForDim(int truedim) {
+ for(int i = 0; i < dimOrder.length; i++) {
+ if(dimOrder[i] == truedim) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public int getInputDimensionality() {
+ return scales.length;
+ }
+} \ No newline at end of file
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 76e5837b..7f175a43 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) 2011
+Copyright (C) 2012
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 3836379a..3f487e0e 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) 2011
+ Copyright (C) 2012
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.visualization.projector;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import java.util.ArrayList;
+
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.relation.Relation;
import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
import de.lmu.ifi.dbs.elki.result.Result;
@@ -40,7 +41,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
* Produce one-dimensional projections.
*
* @author Erich Schubert
- *
+ *
* @apiviz.has HistogramProjector
*/
public class HistogramFactory implements ProjectorFactory {
@@ -51,6 +52,7 @@ public class HistogramFactory implements ProjectorFactory {
/**
* Constructor.
+ *
* @param maxdim Maximum dimensionality
*/
public HistogramFactory(int maxdim) {
@@ -60,16 +62,14 @@ public class HistogramFactory implements ProjectorFactory {
@Override
public void processNewResult(HierarchicalResult baseResult, Result newResult) {
- Database db = ResultUtil.findDatabase(newResult);
- if(db != null) {
- for(Relation<?> rel : db.getRelations()) {
- if(TypeUtil.NUMBER_VECTOR_FIELD.isAssignableFromType(rel.getDataTypeInformation())) {
- @SuppressWarnings("unchecked")
- Relation<NumberVector<?, ?>> vrel = (Relation<NumberVector<?, ?>>) rel;
- final int dim = DatabaseUtil.dimensionality(vrel);
- HistogramProjector<NumberVector<?, ?>> proj = new HistogramProjector<NumberVector<?, ?>>(vrel, Math.min(dim, maxdim));
- baseResult.getHierarchy().add(vrel, proj);
- }
+ ArrayList<Relation<?>> rels = ResultUtil.filterResults(newResult, Relation.class);
+ for(Relation<?> rel : rels) {
+ if(TypeUtil.NUMBER_VECTOR_FIELD.isAssignableFromType(rel.getDataTypeInformation())) {
+ @SuppressWarnings("unchecked")
+ Relation<NumberVector<?, ?>> vrel = (Relation<NumberVector<?, ?>>) rel;
+ final int dim = DatabaseUtil.dimensionality(vrel);
+ HistogramProjector<NumberVector<?, ?>> proj = new HistogramProjector<NumberVector<?, ?>>(vrel, Math.min(dim, maxdim));
+ baseResult.getHierarchy().add(vrel, proj);
}
}
}
@@ -78,7 +78,7 @@ public class HistogramFactory implements ProjectorFactory {
* Parameterization class.
*
* @author Erich Schubert
- *
+ *
* @apiviz.exclude
*/
public static class Parameterizer extends AbstractParameterizer {
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 40bd55ee..95105895 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -31,13 +31,12 @@ import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.result.AbstractHierarchicalResult;
import de.lmu.ifi.dbs.elki.result.ResultUtil;
+import de.lmu.ifi.dbs.elki.result.ScalesResult;
import de.lmu.ifi.dbs.elki.utilities.DatabaseUtil;
import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
import de.lmu.ifi.dbs.elki.visualization.gui.overview.PlotItem;
import de.lmu.ifi.dbs.elki.visualization.projections.Projection1D;
import de.lmu.ifi.dbs.elki.visualization.projections.Simple1D;
-import de.lmu.ifi.dbs.elki.visualization.scales.LinearScale;
-import de.lmu.ifi.dbs.elki.visualization.scales.Scales;
import de.lmu.ifi.dbs.elki.visualization.visualizers.visunproj.LabelVisFactory;
/**
@@ -62,11 +61,6 @@ public class HistogramProjector<V extends NumberVector<?, ?>> extends AbstractHi
int dmax;
/**
- * Axis scales
- */
- LinearScale[] scales;
-
- /**
* Constructor.
*
* @param rel Relation
@@ -76,7 +70,6 @@ public class HistogramProjector<V extends NumberVector<?, ?>> extends AbstractHi
super();
this.rel = rel;
this.dmax = maxdim;
- this.scales = Scales.calcScales(rel);
assert (maxdim <= DatabaseUtil.dimensionality(rel)) : "Requested dimensionality larger than data dimensionality?!?";
}
@@ -89,10 +82,11 @@ public class HistogramProjector<V extends NumberVector<?, ?>> extends AbstractHi
final double hheight = .5;
final double lheight = .1;
PlotItem master = new PlotItem(dmax + xoff, hheight + lheight, null);
+ ScalesResult scales = ResultUtil.getScalesResult(rel);
for(int d1 = 0; d1 < dmax; d1++) {
- Projection1D proj = new Simple1D(scales, d1 + 1);
+ Projection1D proj = new Simple1D(scales.getScales(), d1 + 1);
final PlotItem it = new PlotItem(d1 + xoff, lheight, 1., hheight, proj);
- it.visualizations = tasks;
+ it.tasks = tasks;
master.subitems.add(it);
}
layout.add(master);
@@ -104,7 +98,7 @@ public class HistogramProjector<V extends NumberVector<?, ?>> extends AbstractHi
task.height = lheight;
task.width = 1;
task.put(VisualizationTask.META_NODETAIL, true);
- it.visualizations.add(task);
+ it.tasks.add(task);
master.subitems.add(it);
}
}
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 21b9c227..297b7b12 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -78,7 +78,7 @@ public class OPTICSProjector<D extends Distance<D>> extends AbstractHierarchical
List<VisualizationTask> tasks = ResultUtil.filterResults(this, VisualizationTask.class);
if (tasks.size() > 0) {
final PlotItem it = new PlotItem(4., 1., null);
- it.visualizations = tasks;
+ it.tasks = tasks;
col.add(it);
}
return col;
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 25023029..488c20e0 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) 2011
+ Copyright (C) 2012
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/ParallelPlotFactory.java b/src/de/lmu/ifi/dbs/elki/visualization/projector/ParallelPlotFactory.java
new file mode 100644
index 00000000..6dcb6271
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/projector/ParallelPlotFactory.java
@@ -0,0 +1,64 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
+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.ResultUtil;
+
+/**
+ * Produce parallel axes projections.
+ *
+ * @author Robert Rödler
+ *
+ * @apiviz.has ParallelPlotProjector
+ */
+public class ParallelPlotFactory implements ProjectorFactory {
+ /**
+ * Constructor.
+ */
+ public ParallelPlotFactory() {
+ super();
+ }
+
+ @Override
+ public void processNewResult(HierarchicalResult baseResult, Result newResult) {
+ Iterator<Relation<?>> rels = ResultUtil.filteredResults(newResult, Relation.class);
+ while (rels.hasNext()) {
+ Relation<?> rel = rels.next();
+ // TODO: multi-relational parallel plots
+ if(TypeUtil.NUMBER_VECTOR_FIELD.isAssignableFromType(rel.getDataTypeInformation())) {
+ @SuppressWarnings("unchecked")
+ Relation<NumberVector<?, ?>> vrel = (Relation<NumberVector<?, ?>>) rel;
+ ParallelPlotProjector<NumberVector<?, ?>> proj = new ParallelPlotProjector<NumberVector<?, ?>>(vrel);
+ baseResult.getHierarchy().add(vrel, proj);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/projector/ParallelPlotProjector.java b/src/de/lmu/ifi/dbs/elki/visualization/projector/ParallelPlotProjector.java
new file mode 100644
index 00000000..2076655b
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/projector/ParallelPlotProjector.java
@@ -0,0 +1,100 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.Collection;
+import java.util.List;
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+import de.lmu.ifi.dbs.elki.result.AbstractHierarchicalResult;
+import de.lmu.ifi.dbs.elki.result.ResultUtil;
+import de.lmu.ifi.dbs.elki.result.ScalesResult;
+import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
+import de.lmu.ifi.dbs.elki.visualization.gui.overview.PlotItem;
+import de.lmu.ifi.dbs.elki.visualization.projections.ProjectionParallel;
+import de.lmu.ifi.dbs.elki.visualization.projections.SimpleParallel;
+
+/**
+ * ParallelPlotProjector is responsible for producing a parallel axes
+ * visualization.
+ *
+ * @author Robert Rödler
+ *
+ * @param <V> Vector type
+ */
+// TODO: support categorical features, and multiple relations too
+public class ParallelPlotProjector<V extends NumberVector<?, ?>> extends AbstractHierarchicalResult implements Projector {
+ /**
+ * Relation we project
+ */
+ Relation<V> rel;
+
+ /**
+ * Constructor.
+ *
+ * @param rel Relation
+ */
+ public ParallelPlotProjector(Relation<V> rel) {
+ super();
+ this.rel = rel;
+ }
+
+ @Override
+ public Collection<PlotItem> arrange() {
+ List<PlotItem> col = new ArrayList<PlotItem>(1);
+ List<VisualizationTask> tasks = ResultUtil.filterResults(this, VisualizationTask.class);
+ if(tasks.size() > 0) {
+ ScalesResult scales = ResultUtil.getScalesResult(rel);
+ ProjectionParallel proj = new SimpleParallel(scales.getScales());
+
+ final double width = Math.ceil(Math.log(scales.getScales().length) / MathUtil.LOG2);
+ final PlotItem it = new PlotItem(width, 1., proj);
+ it.tasks = tasks;
+ col.add(it);
+ }
+ return col;
+ }
+
+ @Override
+ public String getLongName() {
+ return "Parallelplot";
+ }
+
+ @Override
+ public String getShortName() {
+ return "parallelplot";
+ }
+
+ /**
+ * The relation we project.
+ *
+ * @return Relation
+ */
+ public Relation<V> getRelation() {
+ return rel;
+ }
+} \ No newline at end of file
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 646adda5..6435bf60 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) 2011
+ Copyright (C) 2012
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 3dbb803f..4fb6bf9e 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) 2011
+ Copyright (C) 2012
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 5957233d..6e1a899b 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) 2011
+ Copyright (C) 2012
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.visualization.projector;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import java.util.ArrayList;
+
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.relation.Relation;
import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
import de.lmu.ifi.dbs.elki.result.Result;
@@ -69,25 +70,23 @@ public class ScatterPlotFactory implements ProjectorFactory {
@Override
public void processNewResult(HierarchicalResult baseResult, Result newResult) {
- Database db = ResultUtil.findDatabase(newResult);
- if(db != null) {
- for(Relation<?> rel : db.getRelations()) {
- if(TypeUtil.NUMBER_VECTOR_FIELD.isAssignableFromType(rel.getDataTypeInformation())) {
- @SuppressWarnings("unchecked")
- Relation<NumberVector<?, ?>> vrel = (Relation<NumberVector<?, ?>>) rel;
- final int dim = DatabaseUtil.dimensionality(vrel);
- ScatterPlotProjector<NumberVector<?, ?>> proj = new ScatterPlotProjector<NumberVector<?, ?>>(vrel, Math.min(maxdim, dim));
- baseResult.getHierarchy().add(vrel, proj);
- }
+ ArrayList<Relation<?>> rels = ResultUtil.filterResults(newResult, Relation.class);
+ for(Relation<?> rel : rels) {
+ if(TypeUtil.NUMBER_VECTOR_FIELD.isAssignableFromType(rel.getDataTypeInformation())) {
+ @SuppressWarnings("unchecked")
+ Relation<NumberVector<?, ?>> vrel = (Relation<NumberVector<?, ?>>) rel;
+ final int dim = DatabaseUtil.dimensionality(vrel);
+ ScatterPlotProjector<NumberVector<?, ?>> proj = new ScatterPlotProjector<NumberVector<?, ?>>(vrel, Math.min(maxdim, dim));
+ baseResult.getHierarchy().add(vrel, proj);
}
}
}
-
+
/**
* Parameterization class.
*
* @author Erich Schubert
- *
+ *
* @apiviz.exclude
*/
public static class Parameterizer extends AbstractParameterizer {
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 a090f523..755b6fd2 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -32,14 +32,13 @@ import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.math.linearalgebra.AffineTransformation;
import de.lmu.ifi.dbs.elki.result.AbstractHierarchicalResult;
import de.lmu.ifi.dbs.elki.result.ResultUtil;
+import de.lmu.ifi.dbs.elki.result.ScalesResult;
import de.lmu.ifi.dbs.elki.utilities.DatabaseUtil;
import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
import de.lmu.ifi.dbs.elki.visualization.gui.overview.PlotItem;
import de.lmu.ifi.dbs.elki.visualization.projections.AffineProjection;
import de.lmu.ifi.dbs.elki.visualization.projections.Projection2D;
import de.lmu.ifi.dbs.elki.visualization.projections.Simple2D;
-import de.lmu.ifi.dbs.elki.visualization.scales.LinearScale;
-import de.lmu.ifi.dbs.elki.visualization.scales.Scales;
import de.lmu.ifi.dbs.elki.visualization.visualizers.visunproj.LabelVisFactory;
/**
@@ -64,11 +63,6 @@ public class ScatterPlotProjector<V extends NumberVector<?, ?>> extends Abstract
int dmax;
/**
- * Axis scales
- */
- LinearScale[] scales;
-
- /**
* Constructor.
*
* @param rel Relation
@@ -78,7 +72,6 @@ public class ScatterPlotProjector<V extends NumberVector<?, ?>> extends Abstract
super();
this.rel = rel;
this.dmax = maxdim;
- this.scales = Scales.calcScales(rel);
assert (maxdim <= DatabaseUtil.dimensionality(rel)) : "Requested dimensionality larger than data dimensionality?!?";
}
@@ -87,14 +80,15 @@ public class ScatterPlotProjector<V extends NumberVector<?, ?>> extends Abstract
List<PlotItem> layout = new ArrayList<PlotItem>(1);
List<VisualizationTask> tasks = ResultUtil.filterResults(this, VisualizationTask.class);
if(tasks.size() > 0) {
+ ScalesResult scales = ResultUtil.getScalesResult(rel);
final PlotItem master;
if(dmax == 2) {
// In 2d, make the plot twice as big.
master = new PlotItem(2 + .1, 2 + .1, null);
{
- Projection2D proj = new Simple2D(scales, 1, 2);
+ Projection2D proj = new Simple2D(scales.getScales(), 1, 2);
PlotItem it = new PlotItem(.1, 0, 2., 2., proj);
- it.visualizations = tasks;
+ it.tasks = tasks;
master.subitems.add(it);
}
// Label at bottom
@@ -104,7 +98,7 @@ public class ScatterPlotProjector<V extends NumberVector<?, ?>> extends Abstract
task.height = .1;
task.width = 2.;
task.put(VisualizationTask.META_NODETAIL, true);
- it.visualizations.add(task);
+ it.tasks.add(task);
master.subitems.add(it);
}
// Label on left
@@ -114,7 +108,7 @@ public class ScatterPlotProjector<V extends NumberVector<?, ?>> extends Abstract
task.height = 2.;
task.width = .1;
task.put(VisualizationTask.META_NODETAIL, true);
- it.visualizations.add(task);
+ it.tasks.add(task);
master.subitems.add(it);
}
}
@@ -124,9 +118,9 @@ public class ScatterPlotProjector<V extends NumberVector<?, ?>> extends Abstract
for(int d1 = 1; d1 < dmax; d1++) {
for(int d2 = d1 + 1; d2 <= dmax; d2++) {
- Projection2D proj = new Simple2D(scales, d1, d2);
+ Projection2D proj = new Simple2D(scales.getScales(), d1, d2);
PlotItem it = new PlotItem(d1 - 1 + .1, d2 - 2, 1., 1., proj);
- it.visualizations = tasks;
+ it.tasks = tasks;
master.subitems.add(it);
}
}
@@ -137,9 +131,9 @@ public class ScatterPlotProjector<V extends NumberVector<?, ?>> extends Abstract
// Wanna try 4d? go ahead:
// p.addRotation(0, 3, Math.PI / 180 * -20.);
// p.addRotation(1, 3, Math.PI / 180 * 30.);
- Projection2D proj = new AffineProjection(scales, p);
+ Projection2D proj = new AffineProjection(scales.getScales(), p);
PlotItem it = new PlotItem(sizeh + .1, 0, sizeh, sizeh, proj);
- it.visualizations = tasks;
+ it.tasks = tasks;
master.subitems.add(it);
}
// Labels at bottom
@@ -149,7 +143,7 @@ public class ScatterPlotProjector<V extends NumberVector<?, ?>> extends Abstract
task.height = .1;
task.width = 1;
task.put(VisualizationTask.META_NODETAIL, true);
- it.visualizations.add(task);
+ it.tasks.add(task);
master.subitems.add(it);
}
// Labels on left
@@ -159,7 +153,7 @@ public class ScatterPlotProjector<V extends NumberVector<?, ?>> extends Abstract
task.height = 1;
task.width = .1;
task.put(VisualizationTask.META_NODETAIL, true);
- it.visualizations.add(task);
+ it.tasks.add(task);
master.subitems.add(it);
}
}
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 5975089c..9fbc2852 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) 2011
+Copyright (C) 2012
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 0fbf584e..f895c46e 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -36,7 +36,6 @@ import org.apache.batik.transcoder.TranscoderException;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.utilities.FileUtil;
-import de.lmu.ifi.dbs.elki.utilities.Util;
import de.lmu.ifi.dbs.elki.visualization.svg.SVGPlot;
/**
@@ -57,112 +56,142 @@ import de.lmu.ifi.dbs.elki.visualization.svg.SVGPlot;
* @apiviz.composedOf SaveOptionsPanel
*/
public class SVGSaveDialog {
- /** The default title. "Save as ...". */
- public final static String DEFAULT_TITLE = "Save as ...";
-
- /** Static logger reference */
- private final static Logging logger = Logging.getLogger(SVGSaveDialog.class);
-
- /** Automagic file format */
- final static String automagic_format = "automatic";
-
- /** Supported file format (extensions) */
- final static String[] formats = { "svg", "png", "jpeg", "jpg", "pdf", "ps", "eps" };
+ /** The default title. "Save as ...". */
+ public final static String DEFAULT_TITLE = "Save as ...";
+
+ /** Static logger reference */
+ private final static Logging logger = Logging.getLogger(SVGSaveDialog.class);
+
+ /** Automagic file format */
+ final static String automagic_format = "automatic";
+
+ /** Supported file format (extensions) */
+ final static String[] formats;
/** Visible file formats */
- final static String[] visibleformats = { automagic_format, "svg", "png", "jpeg", "pdf", "ps", "eps" };
-
- /**
- * Show a "Save as" dialog.
- *
+ final static String[] visibleformats;
+
+ static {
+ // FOP installed?
+ if(SVGPlot.hasFOPInstalled()) {
+ formats = new String[] { "svg", "png", "jpeg", "jpg", "pdf", "ps", "eps" };
+ visibleformats = new String[] { automagic_format, "svg", "png", "jpeg", "pdf", "ps", "eps" };
+ }
+ else {
+ formats = new String[] { "svg", "png", "jpeg", "jpg" };
+ visibleformats = new String[] { automagic_format, "svg", "png", "jpeg" };
+ }
+ }
+
+ /**
+ * Show a "Save as" dialog.
+ *
* @param plot The plot to be exported.
* @param width The width of the exported image (when export to JPEG/PNG).
* @param height The height of the exported image (when export to JPEG/PNG).
* @return Result from {@link JFileChooser#showSaveDialog}
- */
- public static int showSaveDialog(SVGPlot plot, int width, int height) {
- double quality = 1.0;
- int ret = -1;
-
- JFileChooser fc = new JFileChooser();
- fc.setDialogTitle(DEFAULT_TITLE);
- //fc.setFileFilter(new ImageFilter());
- SaveOptionsPanel optionsPanel = new SaveOptionsPanel(fc, width, height);
- fc.setAccessory(optionsPanel);
-
- ret = fc.showSaveDialog(null);
- fc.setDialogTitle("Saving... Please wait.");
- if (ret == JFileChooser.APPROVE_OPTION) {
+ */
+ public static int showSaveDialog(SVGPlot plot, int width, int height) {
+ double quality = 1.0;
+ int ret = -1;
+
+ JFileChooser fc = new JFileChooser();
+ fc.setDialogTitle(DEFAULT_TITLE);
+ // fc.setFileFilter(new ImageFilter());
+ SaveOptionsPanel optionsPanel = new SaveOptionsPanel(fc, width, height);
+ fc.setAccessory(optionsPanel);
+
+ ret = fc.showSaveDialog(null);
+ fc.setDialogTitle("Saving... Please wait.");
+ if(ret == JFileChooser.APPROVE_OPTION) {
File file = fc.getSelectedFile();
- String format = optionsPanel.getSelectedFormat();
- if (format == null || format == automagic_format) {
- format = guessFormat(file.getName());
- }
- try {
- if (format == null) {
+ String format = optionsPanel.getSelectedFormat();
+ if(format == null || format == automagic_format) {
+ format = guessFormat(file.getName());
+ }
+ try {
+ if(format == null) {
showError(fc, "Error saving image.", "File format not recognized.");
- } else if (format.equals("jpeg") || format.equals("jpg")) {
- quality = optionsPanel.getJPEGQuality();
- plot.saveAsJPEG(file, width, height, quality);
- } else if (format.equals("png")) {
- plot.saveAsPNG(file, width, height);
- } else if (format.equals("ps")) {
- plot.saveAsPS(file);
- } else if (format.equals("eps")) {
- plot.saveAsEPS(file);
- } else if (format.equals("pdf")) {
- plot.saveAsPDF(file);
- } else if (format.equals("svg")) {
- plot.saveAsSVG(file);
- } else {
- showError(fc, "Error saving image.", "Unsupported format: " + format);
- }
- } catch (java.lang.IncompatibleClassChangeError e) {
+ }
+ else if(format.equals("jpeg") || format.equals("jpg")) {
+ quality = optionsPanel.getJPEGQuality();
+ plot.saveAsJPEG(file, width, height, quality);
+ }
+ else if(format.equals("png")) {
+ plot.saveAsPNG(file, width, height);
+ }
+ else if(format.equals("ps")) {
+ plot.saveAsPS(file);
+ }
+ else if(format.equals("eps")) {
+ plot.saveAsEPS(file);
+ }
+ else if(format.equals("pdf")) {
+ plot.saveAsPDF(file);
+ }
+ else if(format.equals("svg")) {
+ plot.saveAsSVG(file);
+ }
+ else {
+ showError(fc, "Error saving image.", "Unsupported format: " + format);
+ }
+ }
+ catch(java.lang.IncompatibleClassChangeError e) {
showError(fc, "Error saving image.", "It seems that your Java version is incompatible with this version of Batik and Jpeg writing. Sorry.");
- } catch (IOException e) {
- logger.exception(e);
- showError(fc, "Error saving image.", e.toString());
- } catch (TranscoderException e) {
+ }
+ catch(ClassNotFoundException e) {
+ showError(fc, "Error saving image.", "A class was not found when saving this image. Maybe installing Apache FOP will help (for PDF, PS and EPS output).\n" + e.toString());
+ }
+ catch(IOException e) {
logger.exception(e);
showError(fc, "Error saving image.", e.toString());
- } catch (TransformerFactoryConfigurationError e) {
+ }
+ catch(TranscoderException e) {
logger.exception(e);
showError(fc, "Error saving image.", e.toString());
- } catch (TransformerException e) {
+ }
+ catch(TransformerFactoryConfigurationError e) {
logger.exception(e);
showError(fc, "Error saving image.", e.toString());
- } catch (Exception e) {
+ }
+ catch(TransformerException e) {
+ logger.exception(e);
+ showError(fc, "Error saving image.", e.toString());
+ }
+ catch(Exception e) {
logger.exception(e);
showError(fc, "Error saving image.", e.toString());
}
- } else if (ret == JFileChooser.ERROR_OPTION) {
- showError(fc, "Error in file dialog.", "Unknown Error.");
- } else if (ret == JFileChooser.CANCEL_OPTION) {
- // do nothing - except return result
- }
- return ret;
- }
-
- /**
- * Guess a supported format from the file name. For "auto" format handling.
- *
- * @param name File name
- * @return format or "null"
- */
- public static String guessFormat(String name) {
+ }
+ else if(ret == JFileChooser.ERROR_OPTION) {
+ showError(fc, "Error in file dialog.", "Unknown Error.");
+ }
+ else if(ret == JFileChooser.CANCEL_OPTION) {
+ // do nothing - except return result
+ }
+ return ret;
+ }
+
+ /**
+ * Guess a supported format from the file name. For "auto" format handling.
+ *
+ * @param name File name
+ * @return format or "null"
+ */
+ public static String guessFormat(String name) {
String ext = FileUtil.getFilenameExtension(name);
- int index = Util.arrayFind(formats, ext);
- if (index >= 0) {
- return ext;
- } else {
- return null;
+ for(String format : formats) {
+ if(format.equals(ext)) {
+ return ext;
+ }
}
- }
+ return null;
+ }
/**
* @return the formats
*/
- public static String[] getFormats() {
+ public static String[] getFormats() {
return formats;
}
@@ -173,14 +202,14 @@ public class SVGSaveDialog {
return visibleformats;
}
- /**
- * Helper method to show a error message as "popup".
- * Calls {@link JOptionPane#showMessageDialog(java.awt.Component, Object)}.
- *
- * @param parent The parent component for the popup.
- * @param msg The message to be displayed.
- * */
- private static void showError(Component parent, String title, String msg) {
- JOptionPane.showMessageDialog(parent, msg, title, JOptionPane.ERROR_MESSAGE);
- }
+ /**
+ * Helper method to show a error message as "popup". Calls
+ * {@link JOptionPane#showMessageDialog(java.awt.Component, Object)}.
+ *
+ * @param parent The parent component for the popup.
+ * @param msg The message to be displayed.
+ * */
+ private static void showError(Component parent, String title, String msg) {
+ JOptionPane.showMessageDialog(parent, msg, title, JOptionPane.ERROR_MESSAGE);
+ }
}
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 9c41fbab..6193310b 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -44,8 +44,6 @@ import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
-import de.lmu.ifi.dbs.elki.utilities.Util;
-
/**
* A component (JPanel) which can be displayed in the save dialog to show
* additional options when saving as JPEG or PNG.
@@ -251,7 +249,14 @@ public class SaveOptionsPanel extends JPanel {
}
protected void setFormat(String format) {
- int index = Util.arrayFind(SVGSaveDialog.getVisibleFormats(), format);
+ String[] formats = SVGSaveDialog.getVisibleFormats();
+ int index = -1;
+ for(int i = 0; i < formats.length; i++) {
+ if(formats[i].equals(format)) {
+ index = i;
+ break;
+ }
+ }
if(index != formatSelector.getSelectedIndex() && index >= 0) {
formatSelector.setSelectedIndex(index);
}
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 5a39f687..6820726b 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) 2011
+Copyright (C) 2012
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
new file mode 100644
index 00000000..5468a764
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/style/ClassStylingPolicy.java
@@ -0,0 +1,67 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.database.ids.DBID;
+
+/**
+ * Styling policy that is based on <em>classes</em>, for example clusters or
+ * labels. This allows for certain optimizations such as marker reuse, and thus
+ * is preferred when possible.
+ *
+ * @author Erich Schubert
+ */
+public interface ClassStylingPolicy extends StylingPolicy {
+ /**
+ * Get the style number for a particular object
+ *
+ * @param id Object ID
+ * @return Style number
+ */
+ public int getStyleForDBID(DBID id);
+
+ /**
+ * Get the minimum style in use.
+ *
+ * @return Style number
+ */
+ public int getMinStyle();
+
+ /**
+ * Get the maximum style in use.
+ *
+ * @return Style number
+ */
+ public int getMaxStyle();
+
+ /**
+ * Iterate over all objects from a given class.
+ *
+ * @param cnum Class number
+ * @return Iterator over object IDs
+ */
+ public Iterator<DBID> iterateClass(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
new file mode 100644
index 00000000..9680ec1f
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/style/ClusterStylingPolicy.java
@@ -0,0 +1,137 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.TIntArrayList;
+
+import java.awt.Color;
+import java.util.ArrayList;
+import java.util.Iterator;
+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.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.logging.LoggingUtil;
+import de.lmu.ifi.dbs.elki.visualization.colors.ColorLibrary;
+import de.lmu.ifi.dbs.elki.visualization.svg.SVGUtil;
+
+/**
+ * Styling policy based on cluster membership.
+ *
+ * @author Erich Schubert
+ *
+ */
+// TODO: fast enough? Some other kind of mapping we can use?
+public class ClusterStylingPolicy implements ClassStylingPolicy {
+ /**
+ * Object IDs
+ */
+ ArrayList<DBIDs> ids;
+
+ /**
+ * Colors
+ */
+ TIntArrayList colors;
+
+ /**
+ * Clustering in use.
+ */
+ Clustering<?> clustering;
+
+ /**
+ * Constructor.
+ *
+ * @param clustering Clustering to use.
+ */
+ public ClusterStylingPolicy(Clustering<?> clustering, StyleLibrary style) {
+ super();
+ this.clustering = clustering;
+ ColorLibrary colorset = style.getColorSet(StyleLibrary.PLOT);
+ List<? extends Cluster<?>> clusters = clustering.getAllClusters();
+ ids = new ArrayList<DBIDs>(clusters.size());
+ colors = new TIntArrayList(clusters.size());
+
+ Iterator<? extends Cluster<?>> ci = clusters.iterator();
+ for(int i = 0;; i++) {
+ Cluster<?> c = ci.next();
+ ids.add(DBIDUtil.ensureSet(c.getIDs()));
+ Color col = SVGUtil.stringToColor(colorset.getColor(i));
+ if (col != null) {
+ colors.add(col.getRGB());
+ } else {
+ LoggingUtil.warning("Unrecognized color name: "+colorset.getColor(i));
+ }
+ if(!ci.hasNext()) {
+ break;
+ }
+ }
+ }
+
+ @Override
+ public int getStyleForDBID(DBID id) {
+ for(int i = 0; i < ids.size(); i++) {
+ if(ids.get(i).contains(id)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public int getColorForDBID(DBID id) {
+ for(int i = 0; i < ids.size(); i++) {
+ if(ids.get(i).contains(id)) {
+ return colors.get(i);
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public int getMinStyle() {
+ return 0;
+ }
+
+ @Override
+ public int getMaxStyle() {
+ return ids.size();
+ }
+
+ @Override
+ public Iterator<DBID> iterateClass(int cnum) {
+ return ids.get(cnum).iterator();
+ }
+
+ /**
+ * Get the clustering used by this styling policy
+ *
+ * @return Clustering in use
+ */
+ public Clustering<?> getClustering() {
+ return clustering;
+ }
+} \ No newline at end of file
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 9d60a413..2bdae5e6 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -34,8 +34,8 @@ 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;
-import de.lmu.ifi.dbs.elki.visualization.style.lines.DashedLineStyleLibrary;
import de.lmu.ifi.dbs.elki.visualization.style.lines.LineStyleLibrary;
+import de.lmu.ifi.dbs.elki.visualization.style.lines.SolidLineStyleLibrary;
import de.lmu.ifi.dbs.elki.visualization.style.marker.MarkerLibrary;
import de.lmu.ifi.dbs.elki.visualization.style.marker.PrettyMarkers;
@@ -77,6 +77,16 @@ public class PropertiesBasedStyleLibrary implements StyleLibrary {
public static final String LIST_SEPARATOR = ",";
/**
+ * Property string for the line style library
+ */
+ public static final String PROP_LINES_LIBRARY = "lines-library";
+
+ /**
+ * Property string for the marker style library
+ */
+ public static final String PROP_MARKER_LIBRARY = "marker-library";
+
+ /**
* Properties file to use.
*/
private Properties properties;
@@ -301,8 +311,21 @@ public class PropertiesBasedStyleLibrary implements StyleLibrary {
@Override
public LineStyleLibrary lines() {
if(linelib == null) {
- // FIXME: make configurable
- linelib = new DashedLineStyleLibrary(this);
+ String libname = properties.getProperty(PROP_LINES_LIBRARY, SolidLineStyleLibrary.class.getName());
+ try {
+ Class<?> cls;
+ try {
+ cls = Class.forName(libname);
+ }
+ catch(ClassNotFoundException e) {
+ cls = Class.forName(LineStyleLibrary.class.getPackage().getName() + "." + libname);
+ }
+ linelib = (LineStyleLibrary) cls.getConstructor(StyleLibrary.class).newInstance(this);
+ }
+ catch(Exception e) {
+ logger.exception(e);
+ linelib = new SolidLineStyleLibrary(this);
+ }
}
return linelib;
}
@@ -310,8 +333,21 @@ public class PropertiesBasedStyleLibrary implements StyleLibrary {
@Override
public MarkerLibrary markers() {
if(markerlib == null) {
- // FIXME: make configurable
- markerlib = new PrettyMarkers(this);
+ String libname = properties.getProperty(PROP_MARKER_LIBRARY, PrettyMarkers.class.getName());
+ try {
+ Class<?> cls;
+ try {
+ cls = Class.forName(libname);
+ }
+ catch(ClassNotFoundException e) {
+ cls = Class.forName(MarkerLibrary.class.getPackage().getName() + "." + libname);
+ }
+ markerlib = (MarkerLibrary) cls.getConstructor(StyleLibrary.class).newInstance(this);
+ }
+ catch(Exception e) {
+ logger.exception(e);
+ markerlib = new PrettyMarkers(this);
+ }
}
return markerlib;
}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/style/SingleObjectsStylingPolicy.java b/src/de/lmu/ifi/dbs/elki/visualization/style/SingleObjectsStylingPolicy.java
new file mode 100644
index 00000000..f6ba0ccc
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/style/SingleObjectsStylingPolicy.java
@@ -0,0 +1,34 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Styling policy based on assigning objects individual colors.
+ *
+ * @author Erich Schubert
+ */
+public interface SingleObjectsStylingPolicy extends StylingPolicy {
+ // TODO: finish and use, e.g. for outliers and density visualization
+ // TODO: do we need anything here beyond "not a class styling policy"?
+}
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 5cd721a7..3de935a2 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -105,6 +105,11 @@ public interface StyleLibrary {
final static String DOTPLOT = "plot.dot";
/**
+ * Grayed out objects
+ */
+ final static String PLOTGREY = "plot.grey";
+
+ /**
* Reference points color and size
*/
final static String REFERENCE_POINTS = "plot.referencepoints";
@@ -126,8 +131,7 @@ public interface StyleLibrary {
/**
* Scaling constant. Keep in sync with
- * {@link de.lmu.ifi.dbs.elki.visualization.projections.AffineProjection#SCALE}
- * .
+ * {@link de.lmu.ifi.dbs.elki.visualization.projections.Projection#SCALE}
*/
public static final double SCALE = 100.0;
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/style/StyleResult.java b/src/de/lmu/ifi/dbs/elki/visualization/style/StyleResult.java
new file mode 100644
index 00000000..c617bea6
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/style/StyleResult.java
@@ -0,0 +1,66 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.result.Result;
+
+/**
+ * Result to encapsulate active styling rules.
+ *
+ * @author Erich Schubert
+ */
+// TODO: pull style library etc. from VisualizerContext here?
+public class StyleResult implements Result {
+ /**
+ * Styling policy
+ */
+ StylingPolicy policy;
+
+ /**
+ * Get the active styling policy
+ *
+ * @return Styling policy
+ */
+ public StylingPolicy getStylingPolicy() {
+ return policy;
+ }
+
+ /**
+ * Set the active styling policy
+ *
+ * @param policy new Styling policy
+ */
+ public void setStylingPolicy(StylingPolicy policy) {
+ this.policy = policy;
+ }
+
+ @Override
+ public String getLongName() {
+ return "Style policy";
+ }
+
+ @Override
+ public String getShortName() {
+ return "style-policy";
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/events/ContextChangeListener.java b/src/de/lmu/ifi/dbs/elki/visualization/style/StylingPolicy.java
index 2d7d3e91..a46d7c98 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/events/ContextChangeListener.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/style/StylingPolicy.java
@@ -1,10 +1,12 @@
-package de.lmu.ifi.dbs.elki.visualization.visualizers.events;
+package de.lmu.ifi.dbs.elki.visualization.style;
+
+import de.lmu.ifi.dbs.elki.database.ids.DBID;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,21 +25,23 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.events;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.EventListener;
-
/**
- * Listener for context changes.
+ * Styling policy.
*
- * @author Erich Schubert
+ * Implementations <em>must</em> implement either {@link ClassStylingPolicy} or
+ * {@link SingleObjectsStylingPolicy} interfaces, as most visualizers will only
+ * support these known interfaces.
*
- * @apiviz.uses de.lmu.ifi.dbs.elki.visualization.visualizers.events.ContextChangedEvent oneway - - listens
+ * @author Erich Schubert
*/
-public interface ContextChangeListener extends EventListener {
+public interface StylingPolicy {
/**
- * Method called on context changes (e.g. projection changes).
- * Usually, this should trigger a redraw!
+ * Get the color for an individual object.
+ *
+ * Note: if possible, use a class styling policy which can optimize better.
*
- * @param e Change event
+ * @param id Object ID
+ * @return Color value
*/
- public void contextChanged(ContextChangedEvent e);
-} \ No newline at end of file
+ public int getColorForDBID(DBID id);
+}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/style/classic.properties b/src/de/lmu/ifi/dbs/elki/visualization/style/classic.properties
new file mode 100644
index 00000000..ea1758e7
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/style/classic.properties
@@ -0,0 +1,79 @@
+## Libraries
+lines-library = SolidLineStyleLibrary
+marker-library = PrettyMarkers
+
+## 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.02
+## 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=grey
+## 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 the background of the key box
+key.background-color=none
+## Named color for a label in the key part
+key.label.color=black
+
+## 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.005
+## Greyed out color
+plot.grey=grey
+## Dot size
+plot.dot.size=0.002
+## Reference points
+plot.referencepoints.size=0.003
+plot.referencepoints.color=red
+## Polygons
+plot.polygons.line-width=0.001
+plot.polygons.color=grey
+
+## 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/style/default.properties b/src/de/lmu/ifi/dbs/elki/visualization/style/default.properties
index 2fdb15ed..1dd9a9c7 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/style/default.properties
+++ b/src/de/lmu/ifi/dbs/elki/visualization/style/default.properties
@@ -1,3 +1,7 @@
+## Libraries
+lines-library = SolidLineStyleLibrary
+marker-library = PrettyMarkers
+
## Default foreground color
color=black
## Default font family
@@ -21,7 +25,7 @@ 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
+axis.tick.color=grey
## Named color for a typical axis tick mark
axis.tick.minor.color=silver
## Named color for a typical axis label
@@ -39,11 +43,7 @@ key.background-color=none
key.label.color=black
## 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
+colorset=#ed420e,#fdca19,#4548a5,#7ebd3a,#a81e51,#00748b,#fa8116,#512d85,#008a7a,#fea918,#019d60,#cfde3d,#015a9c,#7b1760
## Line width scaling (for graphs)
plot.line-width=0.005
## For the cluster order
@@ -52,6 +52,8 @@ plot.clusterorder.line-width=0.002
plot.bubble.size=0.10
## Marker size (relative)
plot.marker.size=0.005
+## Greyed out color
+plot.grey=grey
## Dot size
plot.dot.size=0.002
## Reference points
@@ -59,7 +61,7 @@ plot.referencepoints.size=0.003
plot.referencepoints.color=red
## Polygons
plot.polygons.line-width=0.001
-plot.polygons.color=gray
+plot.polygons.color=grey
## Curve vis (ROC curves) labels:
curve.labels.text-size=0.04
@@ -71,3 +73,9 @@ overview.labels.text-size=0.08
plot.selection.color=darkblue
plot.selection.opacity=0.25
plot.selection.size=0.015
+
+## Circle segment colors. Will be interpolated to produce extra classes.
+segments.border.color=#FF0073
+segments.hover.color=#73ff00
+segments.cluster.first.color=#505050
+segments.cluster.second.color=#E0E0E0 \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/style/grayscale.properties b/src/de/lmu/ifi/dbs/elki/visualization/style/greyscale.properties
index dc98d41e..d31e6ec4 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/style/grayscale.properties
+++ b/src/de/lmu/ifi/dbs/elki/visualization/style/greyscale.properties
@@ -1,3 +1,7 @@
+## Libraries
+lines-library = DashedLineStyleLibrary
+marker-library = PrettyMarkers
+
## Default foreground color
color=black
## Default font family
@@ -21,7 +25,7 @@ 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
+axis.tick.color=grey
## Named color for a typical axis tick mark
axis.tick.minor.color=silver
## Named color for a typical axis label
@@ -43,7 +47,7 @@ key.label.color=black
# 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=black,gray,silver,darkgray,dimgray
+colorset=black,grey,silver,darkgrey,dimgrey
## Line width scaling (for graphs)
plot.line-width=0.005
## For the cluster order
@@ -52,6 +56,8 @@ plot.clusterorder.line-width=0.002
plot.bubble.size=0.10
## Marker size (relative)
plot.marker.size=0.005
+## Greyed out color
+plot.grey=lightgrey
## Dot size
plot.dot.size=0.002
## Reference points
@@ -59,7 +65,7 @@ plot.referencepoints.size=0.003
plot.referencepoints.color=black
## Polygons
plot.polygons.line-width=0.001
-plot.polygons.color=dimgray
+plot.polygons.color=dimgrey
## Curve vis (ROC curves) labels:
curve.labels.text-size=0.04
@@ -68,6 +74,6 @@ curve.labels.text-size=0.04
overview.labels.text-size=0.08
## Selection colors
-plot.selection.color=gray
+plot.selection.color=grey
plot.selection.opacity=0.25
plot.selection.size=0.015 \ No newline at end of file
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 0a03afce..5dbfe67a 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -37,12 +37,14 @@ import de.lmu.ifi.dbs.elki.visualization.svg.SVGUtil;
*
* {@link LineStyleLibrary#FLAG_STRONG} will result in thicker lines.
*
- * {@link LineStyleLibrary#FLAG_WEAK} will result in thinner and semi-transparent lines.
+ * {@link LineStyleLibrary#FLAG_WEAK} will result in thinner and
+ * semi-transparent lines.
*
- * {@link LineStyleLibrary#FLAG_INTERPOLATED} will result in shorter dashing patterns.
+ * {@link LineStyleLibrary#FLAG_INTERPOLATED} will result in shorter dashing
+ * patterns.
*
* @author Erich Schubert
- *
+ *
* @apiviz.composedOf ColorLibrary
*/
public class DashedLineStyleLibrary implements LineStyleLibrary {
@@ -53,21 +55,32 @@ public class DashedLineStyleLibrary implements LineStyleLibrary {
/** Dash patterns to regularly use */
private double[][] dashpatterns = {
- // solid, no dashing
+ // solid, no dashing
{},
- // half-half
+ // half-half
{ .5, .5 },
- // quarters
+ // quarters
{ .25, .25, .25, .25 },
- // alternating long-quart
+ // alternating long-quart
{ .75, .25 },
- // dash-dot
+ // dash-dot
{ .7, .1, .1, .1 }, };
+
/** Replacement for the solid pattern in 'interpolated' mode */
private double[] solidreplacement = { .1, .1 };
private int dashnum = dashpatterns.length;
-
+
+ /**
+ * Color of "uncolored" dots
+ */
+ private String dotcolor;
+
+ /**
+ * Color of "greyed out" dots
+ */
+ private String greycolor;
+
/**
* Constructor
*
@@ -76,12 +89,21 @@ public class DashedLineStyleLibrary implements LineStyleLibrary {
public DashedLineStyleLibrary(StyleLibrary style) {
super();
this.colors = style.getColorSet(StyleLibrary.PLOT);
- // TODO: Do a divisor-check to optimize colors * styles combinations?
+ this.dotcolor = style.getColor(StyleLibrary.MARKERPLOT);
+ this.greycolor = style.getColor(StyleLibrary.PLOTGREY);
}
@Override
public void formatCSSClass(CSSClass cls, int style, double width, Object... flags) {
- cls.setStatement(CSSConstants.CSS_STROKE_PROPERTY, colors.getColor(style));
+ if(style == -2) {
+ cls.setStatement(CSSConstants.CSS_STROKE_PROPERTY, greycolor);
+ }
+ else if(style == -1) {
+ cls.setStatement(CSSConstants.CSS_STROKE_PROPERTY, dotcolor);
+ }
+ else {
+ cls.setStatement(CSSConstants.CSS_STROKE_PROPERTY, colors.getColor(style));
+ }
boolean interpolated = false;
// process flavoring flags
for(Object flag : flags) {
@@ -98,7 +120,7 @@ public class DashedLineStyleLibrary implements LineStyleLibrary {
}
cls.setStatement(CSSConstants.CSS_STROKE_WIDTH_PROPERTY, SVGUtil.fmt(width));
// handle dashing
- int styleflav = style % dashnum;
+ int styleflav = (style > 0) ? (style % dashnum) : (-style % dashnum);
if(!interpolated) {
double[] pat = dashpatterns[styleflav];
assert (pat.length % 2 == 0);
@@ -109,13 +131,14 @@ public class DashedLineStyleLibrary implements LineStyleLibrary {
pattern.append(",");
}
pattern.append(SVGUtil.fmt(pat[i] * width * 30));
- //pattern.append("%");
+ // pattern.append("%");
}
cls.setStatement(CSSConstants.CSS_STROKE_DASHARRAY_PROPERTY, pattern.toString());
}
- } else {
+ }
+ else {
double[] pat = dashpatterns[styleflav];
- if (styleflav == 0) {
+ if(styleflav == 0) {
pat = solidreplacement;
}
assert (pat.length % 2 == 0);
@@ -127,10 +150,10 @@ public class DashedLineStyleLibrary implements LineStyleLibrary {
pattern.append(",");
}
pattern.append(SVGUtil.fmt(pat[i] * width));
- //pattern.append("%");
+ // pattern.append("%");
}
cls.setStatement(CSSConstants.CSS_STROKE_DASHARRAY_PROPERTY, pattern.toString());
- }
+ }
}
}
} \ No newline at end of file
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 7576967a..aff1e0fc 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) 2011
+ Copyright (C) 2012
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 2adcaa3e..051bff0a 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -31,17 +31,18 @@ import de.lmu.ifi.dbs.elki.visualization.style.StyleLibrary;
import de.lmu.ifi.dbs.elki.visualization.svg.SVGUtil;
/**
- * Line style library featuring solid lines for default styles only
- * (combine with a color library to obtain enough classes!)
+ * Line style library featuring solid lines for default styles only (combine
+ * with a color library to obtain enough classes!)
*
* {@link LineStyleLibrary#FLAG_STRONG} will result in thicker lines.
*
- * {@link LineStyleLibrary#FLAG_WEAK} will result in thinner and semi-transparent lines.
+ * {@link LineStyleLibrary#FLAG_WEAK} will result in thinner and
+ * semi-transparent lines.
*
* {@link LineStyleLibrary#FLAG_INTERPOLATED} will result in dashed lines.
*
* @author Erich Schubert
- *
+ *
* @apiviz.composedOf ColorLibrary
*/
public class SolidLineStyleLibrary implements LineStyleLibrary {
@@ -49,7 +50,17 @@ public class SolidLineStyleLibrary implements LineStyleLibrary {
* Reference to the color library.
*/
private ColorLibrary colors;
-
+
+ /**
+ * Color of "uncolored" dots
+ */
+ private String dotcolor;
+
+ /**
+ * Color of "greyed out" dots
+ */
+ private String greycolor;
+
/**
* Constructor.
*
@@ -58,11 +69,21 @@ public class SolidLineStyleLibrary implements LineStyleLibrary {
public SolidLineStyleLibrary(StyleLibrary style) {
super();
this.colors = style.getColorSet(StyleLibrary.PLOT);
+ this.dotcolor = style.getColor(StyleLibrary.MARKERPLOT);
+ this.greycolor = style.getColor(StyleLibrary.PLOTGREY);
}
@Override
public void formatCSSClass(CSSClass cls, int style, double width, Object... flags) {
- cls.setStatement(CSSConstants.CSS_STROKE_PROPERTY, colors.getColor(style));
+ if(style == -2) {
+ cls.setStatement(CSSConstants.CSS_STROKE_PROPERTY, greycolor);
+ }
+ else if(style == -1) {
+ cls.setStatement(CSSConstants.CSS_STROKE_PROPERTY, dotcolor);
+ }
+ else {
+ cls.setStatement(CSSConstants.CSS_STROKE_PROPERTY, colors.getColor(style));
+ }
boolean interpolated = false;
// process flavoring flags
for(Object flag : flags) {
@@ -79,7 +100,7 @@ public class SolidLineStyleLibrary implements LineStyleLibrary {
}
cls.setStatement(CSSConstants.CSS_STROKE_WIDTH_PROPERTY, SVGUtil.fmt(width));
if(interpolated) {
- cls.setStatement(CSSConstants.CSS_STROKE_DASHARRAY_PROPERTY, ""+SVGUtil.fmt(width/StyleLibrary.SCALE*2)+","+SVGUtil.fmt(width/StyleLibrary.SCALE*2));
+ cls.setStatement(CSSConstants.CSS_STROKE_DASHARRAY_PROPERTY, "" + SVGUtil.fmt(width / StyleLibrary.SCALE * 2) + "," + SVGUtil.fmt(width / StyleLibrary.SCALE * 2));
}
}
}
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 b524ce87..57a2ee6b 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
@@ -3,25 +3,25 @@
*
*/
/*
-This file is part of ELKI:
-Environment for Developing KDD-Applications Supported by Index-Structures
+ 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
+ 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 free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Affero General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
-You should have received a copy of the GNU Affero General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
+ You 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.visualization.style.lines; \ No newline at end of file
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
new file mode 100644
index 00000000..b847d571
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/style/marker/CircleMarkers.java
@@ -0,0 +1,90 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.apache.batik.util.SVGConstants;
+import org.w3c.dom.Element;
+
+import de.lmu.ifi.dbs.elki.visualization.colors.ColorLibrary;
+import de.lmu.ifi.dbs.elki.visualization.style.StyleLibrary;
+import de.lmu.ifi.dbs.elki.visualization.svg.SVGPlot;
+import de.lmu.ifi.dbs.elki.visualization.svg.SVGUtil;
+
+/**
+ * Simple marker library that just draws colored circles at the given
+ * coordinates.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.composedOf ColorLibrary
+ */
+public class CircleMarkers implements MarkerLibrary {
+ /**
+ * Color library
+ */
+ private ColorLibrary colors;
+
+ /**
+ * Color of "uncolored" dots
+ */
+ private String dotcolor = "black";
+
+ /**
+ * Color of "greyed out" dots
+ */
+ private String greycolor = "gray";
+
+ /**
+ * Constructor
+ *
+ * @param style Style library to use
+ */
+ public CircleMarkers(StyleLibrary style) {
+ super();
+ this.colors = style.getColorSet(StyleLibrary.MARKERPLOT);
+ this.dotcolor = style.getColor(StyleLibrary.MARKERPLOT);
+ this.greycolor = style.getColor(StyleLibrary.PLOTGREY);
+ }
+
+ /**
+ * Use a given marker on the document.
+ */
+ @Override
+ public Element useMarker(SVGPlot plot, Element parent, double x, double y, int stylenr, double size) {
+ Element marker = plot.svgCircle(x, y, size / 2);
+ final String col;
+ if(stylenr == -1) {
+ col = dotcolor;
+ }
+ else if(stylenr == -2) {
+ col = greycolor;
+ }
+ else {
+ col = colors.getColor(stylenr);
+ }
+ SVGUtil.setStyle(marker, SVGConstants.CSS_FILL_PROPERTY + ":" + col);
+ parent.appendChild(marker);
+ return marker;
+ }
+} \ No newline at end of file
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 c45b9fe4..ccddba7d 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,20 +28,21 @@ import org.w3c.dom.Element;
import de.lmu.ifi.dbs.elki.visualization.svg.SVGPlot;
/**
- * A marker library is a class that can generate and draw various styles of markers.
- * Different uses might require different marker libraries (e.g. full screen, thumbnail, print)
+ * A marker library is a class that can generate and draw various styles of
+ * markers. Different uses might require different marker libraries (e.g. full
+ * screen, thumbnail, print)
*
* @author Erich Schubert
- *
+ *
* @apiviz.uses Element oneway - - «create»
*/
public interface MarkerLibrary {
/**
- * Insert a marker at the given coordinates.
- * Markers will be defined in the defs part of the document, and then SVG-"use"d at the
- * given coordinates. This supposedly is more efficient and significantly reduces file size.
- * Symbols will be named "s0", "s1" etc.; these names must not be used by other elements in
- * the SVG document!
+ * Insert a marker at the given coordinates. Markers will be defined in the
+ * defs part of the document, and then SVG-"use"d at the given coordinates.
+ * This supposedly is more efficient and significantly reduces file size.
+ * Symbols will be named "s0", "s1" etc.; these names must not be used by
+ * other elements in the SVG document!
*
* @param plot Plot to draw on
* @param parent parent node
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 10ea2afb..2f5a8c2a 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -32,10 +32,11 @@ import de.lmu.ifi.dbs.elki.visualization.svg.SVGPlot;
import de.lmu.ifi.dbs.elki.visualization.svg.SVGUtil;
/**
- * Simple marker library that just draws colored crosses at the given coordinates.
+ * Simple marker library that just draws colored rectangles at the given
+ * coordinates.
*
* @author Erich Schubert
- *
+ *
* @apiviz.composedOf ColorLibrary
*/
public class MinimalMarkers implements MarkerLibrary {
@@ -43,15 +44,27 @@ public class MinimalMarkers implements MarkerLibrary {
* Color library
*/
private ColorLibrary colors;
-
+
+ /**
+ * Color of "uncolored" dots
+ */
+ private String dotcolor = "black";
+
+ /**
+ * Color of "greyed out" dots
+ */
+ private String greycolor = "gray";
+
/**
* Constructor
*
- * @param style Style library to use
+ * @param style Style library to use
*/
public MinimalMarkers(StyleLibrary style) {
super();
- this.colors = style.getColorSet(StyleLibrary.PLOT);
+ this.colors = style.getColorSet(StyleLibrary.MARKERPLOT);
+ this.dotcolor = style.getColor(StyleLibrary.MARKERPLOT);
+ this.greycolor = style.getColor(StyleLibrary.PLOTGREY);
}
/**
@@ -60,7 +73,17 @@ public class MinimalMarkers implements MarkerLibrary {
@Override
public Element useMarker(SVGPlot plot, Element parent, double x, double y, int stylenr, double size) {
Element marker = plot.svgRect(x - size / 2, y - size / 2, size, size);
- SVGUtil.setStyle(marker, SVGConstants.CSS_FILL_PROPERTY+":" + colors.getColor(stylenr));
+ final String col;
+ if(stylenr == -1) {
+ col = dotcolor;
+ }
+ else if(stylenr == -2) {
+ col = greycolor;
+ }
+ else {
+ col = colors.getColor(stylenr);
+ }
+ SVGUtil.setStyle(marker, SVGConstants.CSS_FILL_PROPERTY + ":" + col);
parent.appendChild(marker);
return marker;
}
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 2bab0f2c..d868bb06 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -56,6 +56,16 @@ public class PrettyMarkers implements MarkerLibrary {
private String prefix;
/**
+ * Color of "uncolored" dots
+ */
+ private String dotcolor;
+
+ /**
+ * Color of "greyed out" dots
+ */
+ private String greycolor;
+
+ /**
* Constructor
*
* @param prefix prefix to use.
@@ -63,7 +73,9 @@ public class PrettyMarkers implements MarkerLibrary {
*/
public PrettyMarkers(String prefix, StyleLibrary style) {
this.prefix = prefix;
- this.colors = style.getColorSet(StyleLibrary.PLOT);
+ this.colors = style.getColorSet(StyleLibrary.MARKERPLOT);
+ this.dotcolor = style.getColor(StyleLibrary.MARKERPLOT);
+ this.greycolor = style.getColor(StyleLibrary.PLOTGREY);
}
/**
@@ -90,6 +102,14 @@ public class PrettyMarkers implements MarkerLibrary {
*/
public void plotMarker(SVGPlot plot, Element parent, double x, double y, int style, double size) {
assert (parent != null);
+ if (style == -1) {
+ plotUncolored(plot, parent, x, y, size);
+ return;
+ }
+ if (style == -2) {
+ plotGray(plot, parent, x, y, size);
+ return;
+ }
// TODO: add more styles.
String colorstr = colors.getColor(style);
String strokestyle = SVGConstants.CSS_STROKE_PROPERTY + ":" + colorstr + ";" + SVGConstants.CSS_STROKE_WIDTH_PROPERTY + ":" + SVGUtil.fmt(size / 6);
@@ -162,6 +182,36 @@ public class PrettyMarkers implements MarkerLibrary {
}
}
+ /**
+ * Plot a replacement marker when an object is to be plotted as "disabled", usually gray.
+ *
+ * @param plot Plot to draw to
+ * @param parent Parent element
+ * @param x X position
+ * @param y Y position
+ * @param size Size
+ */
+ protected void plotGray(SVGPlot plot, Element parent, double x, double y, double size) {
+ Element marker = plot.svgCircle(x, y, size / 2);
+ SVGUtil.setStyle(marker, SVGConstants.CSS_FILL_PROPERTY + ":" + greycolor);
+ parent.appendChild(marker);
+ }
+
+ /**
+ * Plot a replacement marker when no color is set; usually black
+ *
+ * @param plot Plot to draw to
+ * @param parent Parent element
+ * @param x X position
+ * @param y Y position
+ * @param size Size
+ */
+ protected void plotUncolored(SVGPlot plot, Element parent, double x, double y, double size) {
+ Element marker = plot.svgCircle(x, y, size / 2);
+ SVGUtil.setStyle(marker, SVGConstants.CSS_FILL_PROPERTY + ":" + dotcolor);
+ parent.appendChild(marker);
+ }
+
@Override
public Element useMarker(SVGPlot plot, Element parent, double x, double y, int style, double size) {
String id = prefix + style + "_" + size;
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 294bde22..a0672ffb 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) 2011
+Copyright (C) 2012
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 859cc465..311f0884 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/style/neon.properties
+++ b/src/de/lmu/ifi/dbs/elki/visualization/style/neon.properties
@@ -1,3 +1,7 @@
+## Libraries
+lines-library = SolidLineStyleLibrary
+marker-library = PrettyMarkers
+
## Default foreground color
color=white
## Default font family
@@ -21,7 +25,7 @@ plot.background-color=none
## Named color for a typical axis
axis.color=white
## Named color for a typical axis tick mark
-axis.tick.color=gray
+axis.tick.color=grey
## Named color for a typical axis tick mark
axis.tick.minor.color=silver
## Named color for a typical axis label
@@ -52,6 +56,8 @@ plot.clusterorder.line-width=0.002
plot.bubble.size=0.10
## Marker size (relative)
plot.marker.size=0.005
+## Greyed out color
+plot.grey=darkgrey
## Dot size
plot.dot.size=0.002
## Reference points
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 4dde4067..e45cca0f 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) 2011
+Copyright (C) 2012
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 dcc35e31..31c2b569 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/style/presentation.properties
+++ b/src/de/lmu/ifi/dbs/elki/visualization/style/presentation.properties
@@ -1,13 +1,17 @@
+## Libraries
+lines-library = SolidLineStyleLibrary
+marker-library = PrettyMarkers
+
## Default foreground color
color=black
## Default font family
-font-family='Times New Roman', serif
+font-family='CompatilFact', 'Droid Sans', sans-serif
## Default background color
background-color=white
## Default line width
line-width=0.02
## Text font size scale
-text-size=0.03
+text-size=0.015
## Text color
text-color=black
## Default margin (relative)
@@ -21,7 +25,7 @@ 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
+axis.tick.color=grey
## Named color for a typical axis tick mark
axis.tick.minor.color=silver
## Named color for a typical axis label
@@ -31,7 +35,7 @@ axis.line-width=0.004
## Axis tick width
axis.tick.line-width=0.004
## Axis label font size
-axis.label.text-size=0.04
+axis.label.text-size=0.03
## Named color for the background of the key box
key.background-color=none
@@ -43,7 +47,7 @@ key.label.color=black
# 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
+colorset=#ed420e,#fdca19,#4548a5,#7ebd3a,#a81e51,#00748b,#fa8116,#512d85,#008a7a,#fea918,#019d60,#cfde3d,#015a9c,#7b1760
## Line width scaling (for graphs)
plot.line-width=0.01
## For the cluster order
@@ -51,7 +55,9 @@ plot.clusterorder.line-width=0.004
## Bubble sizes (relative)
plot.bubble.size=0.10
## Marker size (relative)
-plot.marker.size=0.005
+plot.marker.size=0.01
+## Greyed out color
+plot.grey=grey
## Dot size
plot.dot.size=0.004
## Reference points
@@ -65,9 +71,15 @@ plot.polygons.color=grey
curve.labels.text-size=0.06
# Text size in overview plot
-overview.labels.text-size=0.12
+overview.labels.text-size=0.08
## Selection colors
plot.selection.color=darkblue
plot.selection.opacity=0.4
-plot.selection.size=0.015 \ No newline at end of file
+plot.selection.size=0.015
+
+## Circle segment colors. Will be interpolated to produce extra classes.
+segments.border.color=#FF0073
+segments.hover.color=#73ff00
+segments.cluster.first.color=#404050
+segments.cluster.second.color=#D0D0F0 \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGButton.java b/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGButton.java
new file mode 100644
index 00000000..9d71c3d6
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGButton.java
@@ -0,0 +1,165 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.apache.batik.util.SVGConstants;
+import org.w3c.dom.Element;
+
+import de.lmu.ifi.dbs.elki.visualization.css.CSSClass;
+
+/**
+ * Class to draw a button as SVG.
+ *
+ * @author Erich Schubert
+ */
+public class SVGButton {
+ /**
+ * Default button color
+ */
+ public static final String DEFAULT_BUTTON_COLOR = SVGConstants.CSS_LIGHTGRAY_VALUE;
+
+ /**
+ * Default text color
+ */
+ public static final String DEFAULT_TEXT_COLOR = SVGConstants.CSS_BLACK_VALUE;
+
+ /**
+ * X position
+ */
+ private double x;
+
+ /**
+ * Y position
+ */
+ private double y;
+
+ /**
+ * Width
+ */
+ private double w;
+
+ /**
+ * Height
+ */
+ private double h;
+
+ /**
+ * Corner rounding factor. NaN = no rounding
+ */
+ private double r = Double.NaN;
+
+ /**
+ * Class for the buttons main CSS
+ */
+ private CSSClass butcss;
+
+ /**
+ * Button title, optional
+ */
+ private String title = null;
+
+ /**
+ * Title styling
+ */
+ private CSSClass titlecss = null;
+
+ /**
+ * Constructor.
+ *
+ * @param x Position X
+ * @param y Position Y
+ * @param w Width
+ * @param h Height
+ * @param r Rounded radius
+ */
+ public SVGButton(double x, double y, double w, double h, double r) {
+ super();
+ this.x = x;
+ this.y = y;
+ this.w = w;
+ this.h = h;
+ this.r = r;
+ this.butcss = new CSSClass(this, "button");
+ butcss.setStatement(SVGConstants.CSS_FILL_PROPERTY, DEFAULT_BUTTON_COLOR);
+ butcss.setStatement(SVGConstants.CSS_STROKE_PROPERTY, SVGConstants.CSS_BLACK_VALUE);
+ butcss.setStatement(SVGConstants.CSS_STROKE_WIDTH_PROPERTY, ".01");
+ }
+
+ /**
+ * Produce the actual SVG elements for the button.
+ *
+ * @param svgp Plot to draw to
+ * @return Button wrapper element
+ */
+ public Element render(SVGPlot svgp) {
+ Element tag = svgp.svgElement(SVGConstants.SVG_G_TAG);
+ Element button = svgp.svgRect(x, y, w, h);
+ if(!Double.isNaN(r)) {
+ SVGUtil.setAtt(button, SVGConstants.SVG_RX_ATTRIBUTE, r);
+ SVGUtil.setAtt(button, SVGConstants.SVG_RY_ATTRIBUTE, r);
+ }
+ SVGUtil.setAtt(button, SVGConstants.SVG_STYLE_ATTRIBUTE, butcss.inlineCSS());
+ tag.appendChild(button);
+ // Add light effect:
+ if (svgp.getIdElement(SVGEffects.LIGHT_GRADIENT_ID) != null) {
+ Element light = svgp.svgRect(x, y, w, h);
+ if(!Double.isNaN(r)) {
+ SVGUtil.setAtt(light, SVGConstants.SVG_RX_ATTRIBUTE, r);
+ SVGUtil.setAtt(light, SVGConstants.SVG_RY_ATTRIBUTE, r);
+ }
+ SVGUtil.setAtt(light, SVGConstants.SVG_STYLE_ATTRIBUTE, "fill:url(#"+SVGEffects.LIGHT_GRADIENT_ID+");fill-opacity:.5");
+ tag.appendChild(light);
+ }
+
+ // Add shadow effect:
+ if(svgp.getIdElement(SVGEffects.SHADOW_ID) != null) {
+ //Element shadow = svgp.svgRect(x + (w * .05), y + (h * .05), w, h);
+ //SVGUtil.setAtt(button, SVGConstants.SVG_STYLE_ATTRIBUTE, SVGConstants.CSS_FILL_PROPERTY + ":" + SVGConstants.CSS_BLACK_VALUE);
+ button.setAttribute(SVGConstants.SVG_FILTER_ATTRIBUTE, "url(#" + SVGEffects.SHADOW_ID + ")");
+ //tag.appendChild(shadow);
+ }
+
+ if(title != null) {
+ Element label = svgp.svgText(x + w * .5, y + h * .7, title);
+ label.setAttribute(SVGConstants.SVG_STYLE_ATTRIBUTE, titlecss.inlineCSS());
+ tag.appendChild(label);
+ }
+ return tag;
+ }
+
+ /**
+ * Set the button title
+ *
+ * @param title Button title
+ * @param textcolor Color
+ */
+ public void setTitle(String title, String textcolor) {
+ this.title = title;
+ if(titlecss == null) {
+ titlecss = new CSSClass(this, "text");
+ titlecss.setStatement(SVGConstants.CSS_TEXT_ANCHOR_PROPERTY, SVGConstants.CSS_MIDDLE_VALUE);
+ titlecss.setStatement(SVGConstants.CSS_FILL_PROPERTY, textcolor);
+ titlecss.setStatement(SVGConstants.CSS_FONT_SIZE_PROPERTY, .6 * h);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGCheckbox.java b/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGCheckbox.java
new file mode 100644
index 00000000..b6cf1165
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGCheckbox.java
@@ -0,0 +1,187 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.EventListenerList;
+
+import org.apache.batik.util.SVGConstants;
+import org.w3c.dom.Element;
+import org.w3c.dom.events.Event;
+import org.w3c.dom.events.EventListener;
+import org.w3c.dom.events.EventTarget;
+
+/**
+ * SVG checkbox.
+ *
+ * @author Sascha Goldhofer
+ */
+public class SVGCheckbox {
+ /**
+ * Status flag
+ */
+ protected boolean checked;
+
+ /**
+ * Event listeners
+ */
+ protected EventListenerList listenerList = new EventListenerList();
+
+ /**
+ * Checkbox label
+ */
+ protected String label = null;
+
+ /**
+ * Constructor, without label
+ *
+ * @param checked Checked status
+ */
+ public SVGCheckbox(boolean checked) {
+ this(checked, null);
+ }
+
+ /**
+ * Constructor, with label
+ *
+ * @param checked Checked status
+ * @param label Label
+ */
+ public SVGCheckbox(boolean checked, String label) {
+ this.checked = checked;
+ this.label = label;
+ }
+
+ /**
+ * Render the SVG checkbox to a plot
+ *
+ * @param svgp Plot to draw to
+ * @param x X offset
+ * @param y Y offset
+ * @param size Size factor
+ * @return Container element
+ */
+ public Element renderCheckBox(SVGPlot svgp, double x, double y, double size) {
+ // create check
+ final Element checkmark = SVGEffects.makeCheckmark(svgp);
+ checkmark.setAttribute(SVGConstants.SVG_TRANSFORM_ATTRIBUTE, "scale(" + (size / 11) + ") translate(" + x + " " + y + ")");
+ if(!checked) {
+ checkmark.setAttribute(SVGConstants.SVG_STYLE_ATTRIBUTE, SVGConstants.CSS_DISPLAY_PROPERTY + ":" + SVGConstants.CSS_NONE_VALUE);
+ }
+
+ // create box
+ Element checkbox_box = SVGUtil.svgRect(svgp.getDocument(), x, y, size, size);
+ checkbox_box.setAttribute(SVGConstants.SVG_FILL_ATTRIBUTE, "#d4e4f1");
+ checkbox_box.setAttribute(SVGConstants.SVG_STROKE_ATTRIBUTE, "#a0a0a0");
+ checkbox_box.setAttribute(SVGConstants.SVG_STROKE_WIDTH_ATTRIBUTE, "0.5");
+
+ // create checkbox
+ final Element checkbox = svgp.svgElement(SVGConstants.SVG_G_TAG);
+ checkbox.appendChild(checkbox_box);
+ checkbox.appendChild(checkmark);
+
+ // create Label
+ if(label != null) {
+ Element labele = svgp.svgText(x + 2 * size, y + size, label);
+ // TODO: font size!
+ checkbox.appendChild(labele);
+ }
+
+ // add click event listener
+ EventTarget targ = (EventTarget) checkbox;
+ targ.addEventListener(SVGConstants.SVG_CLICK_EVENT_TYPE, new EventListener() {
+ /**
+ * Set the checkmark, and fire the event.
+ */
+ protected void check() {
+ checkmark.removeAttribute(SVGConstants.SVG_STYLE_ATTRIBUTE);
+ checked = true;
+ fireSwitchEvent(new ChangeEvent(SVGCheckbox.this));
+ }
+
+ /**
+ * Remove the checkmark and fire the event.
+ */
+ protected void uncheck() {
+ checkmark.setAttribute(SVGConstants.SVG_STYLE_ATTRIBUTE, SVGConstants.CSS_DISPLAY_PROPERTY + ":" + SVGConstants.CSS_NONE_VALUE);
+ checked = false;
+ fireSwitchEvent(new ChangeEvent(SVGCheckbox.this));
+ }
+
+ @Override
+ public void handleEvent(Event evt) {
+ if(checked) {
+ uncheck();
+ }
+ else {
+ check();
+ }
+ }
+ }, false);
+
+ return checkbox;
+ }
+
+ /**
+ * Register a listener for this checkbox.
+ *
+ * @param listener Listener to add
+ */
+ public void addCheckBoxListener(ChangeListener listener) {
+ listenerList.add(ChangeListener.class, listener);
+ }
+
+ /**
+ * Remove a listener for this checkbox.
+ *
+ * @param listener Listener to remove
+ */
+ public void removeCheckBoxListener(ChangeListener listener) {
+ listenerList.remove(ChangeListener.class, listener);
+ }
+
+ /**
+ * Return the checkmark status.
+ *
+ * @return true, when checked
+ */
+ public boolean isChecked() {
+ return checked;
+ }
+
+ /**
+ * Fire the event to listeners
+ *
+ * @param evt Event to fire
+ */
+ protected void fireSwitchEvent(ChangeEvent evt) {
+ Object[] listeners = listenerList.getListenerList();
+ for(int i = 0; i < listeners.length; i += 2) {
+ if(listeners[i] == ChangeListener.class) {
+ ((ChangeListener) listeners[i + 1]).stateChanged(evt);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGCloneVisible.java b/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGCloneVisible.java
new file mode 100644
index 00000000..749720ee
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGCloneVisible.java
@@ -0,0 +1,60 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.apache.batik.util.SVGConstants;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import de.lmu.ifi.dbs.elki.utilities.xml.DOMCloner;
+
+/**
+ * Clone visible parts of an SVG document.
+ *
+ * @author Erich Schubert
+ */
+public class SVGCloneVisible extends DOMCloner {
+ @Override
+ public Node cloneNode(Document doc, Node eold) {
+ // Skip elements with visibility=hidden
+ if(eold instanceof Element) {
+ Element eeold = (Element) eold;
+ String vis = eeold.getAttribute(SVGConstants.CSS_VISIBILITY_PROPERTY);
+ if(SVGConstants.CSS_HIDDEN_VALUE.equals(vis)) {
+ return null;
+ }
+ }
+ // Perform clone flat
+ Node enew = doc.importNode(eold, false);
+ // Recurse:
+ for(Node n = eold.getFirstChild(); n != null; n = n.getNextSibling()) {
+ final Node clone = cloneNode(doc, n);
+ if (clone != null) {
+ enew.appendChild(clone);
+ }
+ }
+ return enew;
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGEffects.java b/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGEffects.java
new file mode 100644
index 00000000..79565902
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGEffects.java
@@ -0,0 +1,147 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.apache.batik.util.SVGConstants;
+import org.w3c.dom.Element;
+
+/**
+ * Class containing some popular SVG effects.
+ *
+ * @author Erich Schubert
+ */
+public class SVGEffects {
+ /**
+ * ID for the drop shadow effect
+ */
+ public static final String SHADOW_ID = "shadow-effect";
+
+ /**
+ * ID for the light gradient fill
+ */
+ public static final String LIGHT_GRADIENT_ID = "light-gradient";
+
+ /**
+ * Static method to prepare a SVG document for drop shadow effects.
+ *
+ * Invoke this from an appropriate update thread!
+ *
+ * @param svgp Plot to prepare
+ */
+ public static void addShadowFilter(SVGPlot svgp) {
+ Element shadow = svgp.getIdElement(SHADOW_ID);
+ if(shadow == null) {
+ shadow = svgp.svgElement(SVGConstants.SVG_FILTER_TAG);
+ shadow.setAttribute(SVGConstants.SVG_ID_ATTRIBUTE, SHADOW_ID);
+ shadow.setAttribute(SVGConstants.SVG_WIDTH_ATTRIBUTE, "140%");
+ shadow.setAttribute(SVGConstants.SVG_HEIGHT_ATTRIBUTE, "140%");
+
+ Element offset = svgp.svgElement(SVGConstants.SVG_FE_OFFSET_TAG);
+ offset.setAttribute(SVGConstants.SVG_IN_ATTRIBUTE, SVGConstants.SVG_SOURCE_ALPHA_VALUE);
+ offset.setAttribute(SVGConstants.SVG_RESULT_ATTRIBUTE, "off");
+ offset.setAttribute(SVGConstants.SVG_DX_ATTRIBUTE, "0.1");
+ offset.setAttribute(SVGConstants.SVG_DY_ATTRIBUTE, "0.1");
+ shadow.appendChild(offset);
+
+ Element gauss = svgp.svgElement(SVGConstants.SVG_FE_GAUSSIAN_BLUR_TAG);
+ gauss.setAttribute(SVGConstants.SVG_IN_ATTRIBUTE, "off");
+ gauss.setAttribute(SVGConstants.SVG_RESULT_ATTRIBUTE, "blur");
+ gauss.setAttribute(SVGConstants.SVG_STD_DEVIATION_ATTRIBUTE, "0.1");
+ shadow.appendChild(gauss);
+
+ Element blend = svgp.svgElement(SVGConstants.SVG_FE_BLEND_TAG);
+ blend.setAttribute(SVGConstants.SVG_IN_ATTRIBUTE, SVGConstants.SVG_SOURCE_GRAPHIC_VALUE);
+ blend.setAttribute(SVGConstants.SVG_IN2_ATTRIBUTE, "blur");
+ blend.setAttribute(SVGConstants.SVG_MODE_ATTRIBUTE, SVGConstants.SVG_NORMAL_VALUE);
+ shadow.appendChild(blend);
+
+ svgp.getDefs().appendChild(shadow);
+ svgp.putIdElement(SHADOW_ID, shadow);
+ }
+ }
+
+ /**
+ * Static method to prepare a SVG document for light gradient effects.
+ *
+ * Invoke this from an appropriate update thread!
+ *
+ * @param svgp Plot to prepare
+ */
+ public static void addLightGradient(SVGPlot svgp) {
+ Element gradient = svgp.getIdElement(LIGHT_GRADIENT_ID);
+ if(gradient == null) {
+ gradient = svgp.svgElement(SVGConstants.SVG_LINEAR_GRADIENT_TAG);
+ gradient.setAttribute(SVGConstants.SVG_ID_ATTRIBUTE, LIGHT_GRADIENT_ID);
+ gradient.setAttribute(SVGConstants.SVG_X1_ATTRIBUTE, "0");
+ gradient.setAttribute(SVGConstants.SVG_Y1_ATTRIBUTE, "0");
+ gradient.setAttribute(SVGConstants.SVG_X2_ATTRIBUTE, "0");
+ gradient.setAttribute(SVGConstants.SVG_Y2_ATTRIBUTE, "1");
+
+ Element stop0 = svgp.svgElement(SVGConstants.SVG_STOP_TAG);
+ stop0.setAttribute(SVGConstants.SVG_STOP_COLOR_ATTRIBUTE, "white");
+ stop0.setAttribute(SVGConstants.SVG_STOP_OPACITY_ATTRIBUTE, "1");
+ stop0.setAttribute(SVGConstants.SVG_OFFSET_ATTRIBUTE, "0");
+ gradient.appendChild(stop0);
+
+ Element stop04 = svgp.svgElement(SVGConstants.SVG_STOP_TAG);
+ stop04.setAttribute(SVGConstants.SVG_STOP_COLOR_ATTRIBUTE, "white");
+ stop04.setAttribute(SVGConstants.SVG_STOP_OPACITY_ATTRIBUTE, "0");
+ stop04.setAttribute(SVGConstants.SVG_OFFSET_ATTRIBUTE, ".4");
+ gradient.appendChild(stop04);
+
+ Element stop06 = svgp.svgElement(SVGConstants.SVG_STOP_TAG);
+ stop06.setAttribute(SVGConstants.SVG_STOP_COLOR_ATTRIBUTE, "black");
+ stop06.setAttribute(SVGConstants.SVG_STOP_OPACITY_ATTRIBUTE, "0");
+ stop06.setAttribute(SVGConstants.SVG_OFFSET_ATTRIBUTE, ".6");
+ gradient.appendChild(stop06);
+
+ Element stop1 = svgp.svgElement(SVGConstants.SVG_STOP_TAG);
+ stop1.setAttribute(SVGConstants.SVG_STOP_COLOR_ATTRIBUTE, "black");
+ stop1.setAttribute(SVGConstants.SVG_STOP_OPACITY_ATTRIBUTE, ".5");
+ stop1.setAttribute(SVGConstants.SVG_OFFSET_ATTRIBUTE, "1");
+ gradient.appendChild(stop1);
+
+ svgp.getDefs().appendChild(gradient);
+ svgp.putIdElement(LIGHT_GRADIENT_ID, gradient);
+ }
+ }
+
+ /**
+ * Checkmark path, sized approx. 15x15
+ */
+ public static final String SVG_CHECKMARK_PATH = "M0 6.458 L2.047 4.426 5.442 7.721 12.795 0 15 2.117 5.66 11.922 Z";
+
+ /**
+ * Creates a 15x15 big checkmark
+ *
+ * @param svgp Plot to create the element for
+ * @return Element
+ */
+ public static Element makeCheckmark(SVGPlot svgp) {
+ Element checkmark = svgp.svgElement(SVGConstants.SVG_PATH_TAG);
+ checkmark.setAttribute(SVGConstants.SVG_D_ATTRIBUTE, SVG_CHECKMARK_PATH);
+ checkmark.setAttribute(SVGConstants.SVG_FILL_ATTRIBUTE, SVGConstants.CSS_BLACK_VALUE);
+ checkmark.setAttribute(SVGConstants.SVG_STROKE_ATTRIBUTE, SVGConstants.CSS_NONE_VALUE);
+ return checkmark;
+ }
+} \ No newline at end of file
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 18bbeb06..723f13df 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -31,7 +31,7 @@ import org.apache.batik.util.SVGConstants;
import org.w3c.dom.Element;
import de.lmu.ifi.dbs.elki.data.NumberVector;
-import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.VMath;
import de.lmu.ifi.dbs.elki.visualization.projections.Projection2D;
/**
@@ -52,7 +52,7 @@ public class SVGHyperCube {
* @param max Opposite corner
* @return path element
*/
- public static Element drawFrame(SVGPlot svgp, Projection2D proj, Vector min, Vector max) {
+ public static Element drawFrame(SVGPlot svgp, Projection2D proj, double[] min, double[] max) {
SVGPath path = new SVGPath();
ArrayList<double[]> edges = getVisibleEdges(proj, min, max);
double[] rv_min = proj.fastProjectDataToRenderSpace(min);
@@ -72,7 +72,7 @@ public class SVGHyperCube {
*/
public static <V extends NumberVector<V, ?>> Element drawFrame(SVGPlot svgp, Projection2D proj, V min, V max) {
SVGPath path = new SVGPath();
- ArrayList<double[]> edges = getVisibleEdges(proj, min.getColumnVector(), max.getColumnVector());
+ ArrayList<double[]> edges = getVisibleEdges(proj, min.getColumnVector().getArrayRef(), max.getColumnVector().getArrayRef());
double[] rv_min = proj.fastProjectDataToRenderSpace(min);
recDrawEdges(path, rv_min, edges, 0, new BitSet());
return path.makeElement(svgp);
@@ -88,7 +88,7 @@ public class SVGHyperCube {
* @param max Opposite corner
* @return group element
*/
- public static Element drawFilled(SVGPlot svgp, String cls, Projection2D proj, Vector min, Vector max) {
+ public static Element drawFilled(SVGPlot svgp, String cls, Projection2D proj, double[] min, double[] max) {
Element group = svgp.svgElement(SVGConstants.SVG_G_TAG);
ArrayList<double[]> edges = getVisibleEdges(proj, min, max);
double[] rv_min = proj.fastProjectDataToRenderSpace(min);
@@ -109,7 +109,7 @@ public class SVGHyperCube {
*/
public static <V extends NumberVector<V, ?>> Element drawFilled(SVGPlot svgp, String cls, Projection2D proj, V min, V max) {
Element group = svgp.svgElement(SVGConstants.SVG_G_TAG);
- ArrayList<double[]> edges = getVisibleEdges(proj, min.getColumnVector(), max.getColumnVector());
+ ArrayList<double[]> edges = getVisibleEdges(proj, min.getColumnVector().getArrayRef(), max.getColumnVector().getArrayRef());
double[] rv_min = proj.fastProjectDataToRenderSpace(min);
recDrawSides(svgp, group, cls, rv_min, edges, 0, new BitSet());
return group;
@@ -123,12 +123,12 @@ public class SVGHyperCube {
* @param s_max Maximum value (in scaled space)
* @return Edge list
*/
- private static ArrayList<double[]> getVisibleEdges(Projection2D proj, Vector s_min, Vector s_max) {
- Vector s_deltas = s_max.minus(s_min);
+ 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[]>();
- for(int i = 0; i < s_min.getDimensionality(); i++) {
- Vector delta = new Vector(s_min.getDimensionality());
- delta.set(i, s_deltas.get(i));
+ for(int i = 0; i < s_min.length; i++) {
+ double[] delta = new double[s_min.length];
+ delta[i] = s_deltas[i];
double[] deltas = proj.fastProjectRelativeDataToRenderSpace(delta);
if(deltas[0] != 0 || deltas[1] != 0) {
r_edges.add(deltas);
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 169c8698..29b437f9 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,7 +29,6 @@ import org.w3c.dom.Element;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance;
-import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
import de.lmu.ifi.dbs.elki.visualization.projections.Projection2D;
/**
@@ -51,7 +50,6 @@ public class SVGHyperSphere {
/**
* Wireframe "manhattan" hypersphere
*
- * @param <V> vector type
* @param <D> radius
* @param svgp SVG Plot
* @param proj Visualization projection
@@ -59,26 +57,27 @@ public class SVGHyperSphere {
* @param rad radius
* @return path element
*/
- public static <V extends NumberVector<V, ?>, D extends NumberDistance<?, ?>> Element drawManhattan(SVGPlot svgp, Projection2D proj, V mid, D rad) {
- Vector v_mid = mid.getColumnVector();
- BitSet dims = proj.getVisibleDimensions2D();
+ public static <D extends NumberDistance<?, ?>> Element drawManhattan(SVGPlot svgp, Projection2D proj, NumberVector<?, ?> mid, D rad) {
+ final double radius = rad.doubleValue();
+ 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)) {
- Vector v1 = v_mid.copy();
- v1.set(dim, v1.get(dim) + rad.doubleValue());
- Vector v2 = v_mid.copy();
- v2.set(dim, v2.get(dim) - rad.doubleValue());
- double[] p1 = proj.fastProjectDataToRenderSpace(v1);
- double[] p2 = proj.fastProjectDataToRenderSpace(v2);
+ 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) {
- Vector v3 = v_mid.copy();
- v3.set(dim2, v3.get(dim2) + rad.doubleValue());
- Vector v4 = v_mid.copy();
- v4.set(dim2, v4.get(dim2) - rad.doubleValue());
- double[] p3 = proj.fastProjectDataToRenderSpace(v3);
- double[] p4 = proj.fastProjectDataToRenderSpace(v4);
+ v_mid[dim2] += radius;
+ double[] p3 = proj.fastProjectDataToRenderSpace(v_mid);
+ v_mid[dim2] -= radius;
+ v_mid[dim2] -= radius;
+ double[] p4 = proj.fastProjectDataToRenderSpace(v_mid);
+ v_mid[dim2] += radius;
path.moveTo(p1[0], p1[1]);
path.drawTo(p3[0], p3[1]);
@@ -98,7 +97,6 @@ public class SVGHyperSphere {
/**
* Wireframe "euclidean" hypersphere
*
- * @param <V> vector type
* @param <D> radius
* @param svgp SVG Plot
* @param proj Visualization projection
@@ -106,33 +104,34 @@ public class SVGHyperSphere {
* @param rad radius
* @return path element
*/
- public static <V extends NumberVector<V, ?>, D extends NumberDistance<?, ?>> Element drawEuclidean(SVGPlot svgp, Projection2D proj, V mid, D rad) {
- Vector v_mid = mid.getColumnVector();
+ public static <D extends NumberDistance<?, ?>> Element drawEuclidean(SVGPlot svgp, Projection2D proj, NumberVector<?, ?> mid, D rad) {
+ final double radius = rad.doubleValue();
+ 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)) {
- Vector v1 = v_mid.copy();
- v1.set(dim, v1.get(dim) + rad.doubleValue());
- Vector v2 = v_mid.copy();
- v2.set(dim, v2.get(dim) - rad.doubleValue());
- double[] p1 = proj.fastProjectDataToRenderSpace(v1);
- double[] p2 = proj.fastProjectDataToRenderSpace(v2);
+ 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;
// delta vector
- Vector dt1 = new Vector(v1.getDimensionality());
- dt1.set(dim, rad.doubleValue());
+ 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) {
- Vector v3 = v_mid.copy();
- v3.set(dim2, v3.get(dim2) + rad.doubleValue());
- Vector v4 = v_mid.copy();
- v4.set(dim2, v4.get(dim2) - rad.doubleValue());
- double[] p3 = proj.fastProjectDataToRenderSpace(v3);
- double[] p4 = proj.fastProjectDataToRenderSpace(v4);
+ v_mid[dim2] += radius;
+ double[] p3 = proj.fastProjectDataToRenderSpace(v_mid);
+ v_mid[dim2] -= radius;
+ v_mid[dim2] -= radius;
+ double[] p4 = proj.fastProjectDataToRenderSpace(v_mid);
+ v_mid[dim2] += radius;
// delta vector
- Vector dt2 = new Vector(v2.getDimensionality());
- dt2.set(dim2, rad.doubleValue());
+ double[] dt2 = new double[v_mid.length];
+ dt2[dim2] = radius;
double[] d2 = proj.fastProjectRelativeDataToRenderSpace(dt2);
path.moveTo(p1[0], p1[1]);
@@ -150,7 +149,6 @@ public class SVGHyperSphere {
/**
* Wireframe "Lp" hypersphere
*
- * @param <V> vector type
* @param <D> radius
* @param svgp SVG Plot
* @param proj Visualization projection
@@ -159,18 +157,19 @@ public class SVGHyperSphere {
* @param p L_p value
* @return path element
*/
- public static <V extends NumberVector<V, ?>, D extends NumberDistance<?, ?>> Element drawLp(SVGPlot svgp, Projection2D proj, V mid, D rad, double p) {
- Vector v_mid = mid.getColumnVector();
- BitSet dims = proj.getVisibleDimensions2D();
+ public static <D extends NumberDistance<?, ?>> Element drawLp(SVGPlot svgp, Projection2D proj, NumberVector<?, ?> mid, D rad, double p) {
+ final double radius = rad.doubleValue();
+ final double[] v_mid = mid.getColumnVector().getArrayRef();
+ final BitSet dims = proj.getVisibleDimensions2D();
final double kappax, kappay;
if(p > 1.) {
- double kappal = Math.pow(0.5, 1. / p);
+ 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.) {
- double kappal = 1 - Math.pow(0.5, 1. / p);
+ final double kappal = 1 - Math.pow(0.5, 1. / p);
kappax = 0;
kappay = Math.min(1.3, 4. * (2 * kappal - 1) / 3.);
}
@@ -182,27 +181,27 @@ public class SVGHyperSphere {
SVGPath path = new SVGPath();
for(int dim = dims.nextSetBit(0); dim >= 0; dim = dims.nextSetBit(dim + 1)) {
- Vector vp0 = v_mid.copy();
- vp0.set(dim, vp0.get(dim) + rad.doubleValue());
- Vector vm0 = v_mid.copy();
- vm0.set(dim, vm0.get(dim) - rad.doubleValue());
- double[] pvp0 = proj.fastProjectDataToRenderSpace(vp0);
- double[] pvm0 = proj.fastProjectDataToRenderSpace(vm0);
+ v_mid[dim] += radius;
+ double[] pvp0 = proj.fastProjectDataToRenderSpace(v_mid);
+ v_mid[dim] -= radius;
+ v_mid[dim] -= radius;
+ double[] pvm0 = proj.fastProjectDataToRenderSpace(v_mid);
+ v_mid[dim] += radius;
// delta vector
- Vector tvd0 = new Vector(vp0.getDimensionality());
- tvd0.set(dim, rad.doubleValue());
+ 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) {
- Vector v0p = v_mid.copy();
- v0p.set(dim2, v0p.get(dim2) + rad.doubleValue());
- Vector v0m = v_mid.copy();
- v0m.set(dim2, v0m.get(dim2) - rad.doubleValue());
- double[] pv0p = proj.fastProjectDataToRenderSpace(v0p);
- double[] pv0m = proj.fastProjectDataToRenderSpace(v0m);
+ v_mid[dim2] += radius;
+ double[] pv0p = proj.fastProjectDataToRenderSpace(v_mid);
+ v_mid[dim2] -= radius;
+ v_mid[dim2] -= radius;
+ double[] pv0m = proj.fastProjectDataToRenderSpace(v_mid);
+ v_mid[dim2] += radius;
// delta vector
- Vector tv0d = new Vector(vm0.getDimensionality());
- tv0d.set(dim2, rad.doubleValue());
+ double[] tv0d = new double[v_mid.length];
+ tv0d[dim2] = radius;
double[] v0d = proj.fastProjectRelativeDataToRenderSpace(tv0d);
if(p > 1) {
@@ -271,7 +270,6 @@ public class SVGHyperSphere {
/**
* Wireframe "cross" hypersphere
*
- * @param <V> vector type
* @param <D> radius
* @param svgp SVG Plot
* @param proj Visualization projection
@@ -279,19 +277,20 @@ public class SVGHyperSphere {
* @param rad radius
* @return path element
*/
- public static <V extends NumberVector<V, ?>, D extends NumberDistance<?, ?>> Element drawCross(SVGPlot svgp, Projection2D proj, V mid, D rad) {
- Vector v_mid = mid.getColumnVector();
- BitSet dims = proj.getVisibleDimensions2D();
+ public static <D extends NumberDistance<?, ?>> Element drawCross(SVGPlot svgp, Projection2D proj, NumberVector<?, ?> mid, D rad) {
+ final double radius = rad.doubleValue();
+ final double[] v_mid = mid.getColumnVector().getArrayRef();
+ final BitSet dims = proj.getVisibleDimensions2D();
SVGPath path = new SVGPath();
for(int dim = dims.nextSetBit(0); dim >= 0; dim = dims.nextSetBit(dim + 1)) {
- Vector v1 = v_mid.copy();
- v1.set(dim, v1.get(dim) + rad.doubleValue());
- Vector v2 = v_mid.copy();
- v2.set(dim, v2.get(dim) - rad.doubleValue());
- double[] p1 = proj.fastProjectDataToRenderSpace(v1);
- double[] p2 = proj.fastProjectDataToRenderSpace(v2);
+ v_mid[dim] += radius;
+ double[] p1 = proj.fastProjectDataToRenderSpace(v_mid);
+ v_mid[dim] -= radius;
path.moveTo(p1[0], p1[1]);
+ v_mid[dim] -= radius;
+ double[] p2 = proj.fastProjectDataToRenderSpace(v_mid);
+ v_mid[dim] += radius;
path.drawTo(p2[0], p2[1]);
path.close();
}
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 2be331ca..2b86870b 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -118,8 +118,18 @@ public class SVGPath {
}
/**
+ * Constructor with initial point.
+ *
+ * @param xy initial coordinates
+ */
+ public SVGPath(double[] xy) {
+ this();
+ this.moveTo(xy);
+ }
+
+ /**
* Constructor from a vector collection (e.g. a polygon)
- *
+ *
* @param vectors vectors
*/
public SVGPath(Iterable<Vector> vectors) {
@@ -159,6 +169,25 @@ public class SVGPath {
* @param xy new coordinates
* @return path object, for compact syntax.
*/
+ public SVGPath drawTo(double[] xy) {
+ if(!isStarted()) {
+ moveTo(xy);
+ }
+ else {
+ lineTo(xy);
+ }
+ return this;
+ }
+
+ /**
+ * Draw a line given a series of coordinates.
+ *
+ * Helper function that will use "move" for the first point, "lineto" for the
+ * remaining.
+ *
+ * @param xy new coordinates
+ * @return path object, for compact syntax.
+ */
public SVGPath drawTo(Vector xy) {
if(!isStarted()) {
moveTo(xy);
@@ -196,6 +225,17 @@ public class SVGPath {
* @param xy new coordinates
* @return path object, for compact syntax.
*/
+ public SVGPath lineTo(double[] xy) {
+ append(SVGConstants.PATH_LINE_TO, xy[0], xy[1]);
+ return this;
+ }
+
+ /**
+ * Draw a line to the given coordinates.
+ *
+ * @param xy new coordinates
+ * @return path object, for compact syntax.
+ */
public SVGPath lineTo(Vector xy) {
append(SVGConstants.PATH_LINE_TO, xy.get(0), xy.get(1));
return this;
@@ -219,6 +259,17 @@ public class SVGPath {
* @param xy new coordinates
* @return path object, for compact syntax.
*/
+ public SVGPath relativeLineTo(double[] xy) {
+ append(PATH_LINE_TO_RELATIVE, xy[0], xy[1]);
+ return this;
+ }
+
+ /**
+ * Draw a line to the given relative coordinates.
+ *
+ * @param xy new coordinates
+ * @return path object, for compact syntax.
+ */
public SVGPath relativeLineTo(Vector xy) {
append(PATH_LINE_TO_RELATIVE, xy.get(0), xy.get(1));
return this;
@@ -286,6 +337,17 @@ public class SVGPath {
* @param xy new coordinates
* @return path object, for compact syntax.
*/
+ public SVGPath moveTo(double[] xy) {
+ append(SVGConstants.PATH_MOVE, xy[0], xy[1]);
+ return this;
+ }
+
+ /**
+ * Move to the given coordinates.
+ *
+ * @param xy new coordinates
+ * @return path object, for compact syntax.
+ */
public SVGPath moveTo(Vector xy) {
append(SVGConstants.PATH_MOVE, xy.get(0), xy.get(1));
return this;
@@ -309,6 +371,17 @@ public class SVGPath {
* @param xy new coordinates
* @return path object, for compact syntax.
*/
+ public SVGPath relativeMoveTo(double[] xy) {
+ append(PATH_MOVE_RELATIVE, xy[0], xy[1]);
+ return this;
+ }
+
+ /**
+ * Move to the given relative coordinates.
+ *
+ * @param xy new coordinates
+ * @return path object, for compact syntax.
+ */
public SVGPath relativeMoveTo(Vector xy) {
append(PATH_MOVE_RELATIVE, xy.get(0), xy.get(1));
return this;
@@ -338,6 +411,19 @@ public class SVGPath {
* @param xy new coordinates
* @return path object, for compact syntax.
*/
+ public SVGPath cubicTo(double[] c1xy, double[] c2xy, double[] xy) {
+ append(SVGConstants.PATH_CUBIC_TO, c1xy[0], c1xy[1], c2xy[0], c2xy[1], xy[0], xy[1]);
+ return this;
+ }
+
+ /**
+ * Cubic Bezier line to the given coordinates.
+ *
+ * @param c1xy first control point
+ * @param c2xy second control point
+ * @param xy new coordinates
+ * @return path object, for compact syntax.
+ */
public SVGPath cubicTo(Vector c1xy, Vector c2xy, Vector xy) {
append(SVGConstants.PATH_CUBIC_TO, c1xy.get(0), c1xy.get(1), c2xy.get(0), c2xy.get(1), xy.get(0), xy.get(1));
return this;
@@ -367,6 +453,19 @@ public class SVGPath {
* @param xy new coordinates
* @return path object, for compact syntax.
*/
+ public SVGPath relativeCubicTo(double[] c1xy, double[] c2xy, double[] xy) {
+ append(PATH_CUBIC_TO_RELATIVE, c1xy[0], c1xy[1], c2xy[0], c2xy[1], xy[0], xy[1]);
+ return this;
+ }
+
+ /**
+ * Cubic Bezier line to the given relative coordinates.
+ *
+ * @param c1xy first control point
+ * @param c2xy second control point
+ * @param xy new coordinates
+ * @return path object, for compact syntax.
+ */
public SVGPath relativeCubicTo(Vector c1xy, Vector c2xy, Vector xy) {
append(PATH_CUBIC_TO_RELATIVE, c1xy.get(0), c1xy.get(1), c2xy.get(0), c2xy.get(1), xy.get(0), xy.get(1));
return this;
@@ -393,6 +492,18 @@ public class SVGPath {
* @param xy new coordinates
* @return path object, for compact syntax.
*/
+ public SVGPath smoothCubicTo(double[] c2xy, double[] xy) {
+ append(PATH_SMOOTH_CUBIC_TO, c2xy[0], c2xy[1], xy[0], xy[1]);
+ return this;
+ }
+
+ /**
+ * Smooth Cubic Bezier line to the given coordinates.
+ *
+ * @param c2xy second control point
+ * @param xy new coordinates
+ * @return path object, for compact syntax.
+ */
public SVGPath smoothCubicTo(Vector c2xy, Vector xy) {
append(PATH_SMOOTH_CUBIC_TO, c2xy.get(0), c2xy.get(1), xy.get(0), xy.get(1));
return this;
@@ -419,6 +530,18 @@ public class SVGPath {
* @param xy new coordinates
* @return path object, for compact syntax.
*/
+ public SVGPath relativeSmoothCubicTo(double[] c2xy, double[] xy) {
+ append(PATH_SMOOTH_CUBIC_TO_RELATIVE, c2xy[0], c2xy[1], xy[0], xy[1]);
+ return this;
+ }
+
+ /**
+ * Smooth Cubic Bezier line to the given relative coordinates.
+ *
+ * @param c2xy second control point
+ * @param xy new coordinates
+ * @return path object, for compact syntax.
+ */
public SVGPath relativeSmoothCubicTo(Vector c2xy, Vector xy) {
append(PATH_SMOOTH_CUBIC_TO_RELATIVE, c2xy.get(0), c2xy.get(1), xy.get(0), xy.get(1));
return this;
@@ -445,6 +568,18 @@ public class SVGPath {
* @param xy new coordinates
* @return path object, for compact syntax.
*/
+ public SVGPath quadTo(double[] c1xy, double[] xy) {
+ append(SVGConstants.PATH_QUAD_TO, c1xy[0], c1xy[1], xy[0], xy[1]);
+ return this;
+ }
+
+ /**
+ * Quadratic Bezier line to the given coordinates.
+ *
+ * @param c1xy first control point
+ * @param xy new coordinates
+ * @return path object, for compact syntax.
+ */
public SVGPath quadTo(Vector c1xy, Vector xy) {
append(SVGConstants.PATH_QUAD_TO, c1xy.get(0), c1xy.get(1), xy.get(0), xy.get(1));
return this;
@@ -471,6 +606,18 @@ public class SVGPath {
* @param xy new coordinates
* @return path object, for compact syntax.
*/
+ public SVGPath relativeQuadTo(double[] c1xy, double[] xy) {
+ append(PATH_QUAD_TO_RELATIVE, c1xy[0], c1xy[1], xy[0], xy[1]);
+ return this;
+ }
+
+ /**
+ * Quadratic Bezier line to the given relative coordinates.
+ *
+ * @param c1xy first control point
+ * @param xy new coordinates
+ * @return path object, for compact syntax.
+ */
public SVGPath relativeQuadTo(Vector c1xy, Vector xy) {
append(PATH_QUAD_TO_RELATIVE, c1xy.get(0), c1xy.get(1), xy.get(0), xy.get(1));
return this;
@@ -494,6 +641,17 @@ public class SVGPath {
* @param xy new coordinates
* @return path object, for compact syntax.
*/
+ public SVGPath smoothQuadTo(double[] xy) {
+ append(SVGConstants.PATH_SMOOTH_QUAD_TO, xy[0], xy[1]);
+ return this;
+ }
+
+ /**
+ * Smooth quadratic Bezier line to the given coordinates.
+ *
+ * @param xy new coordinates
+ * @return path object, for compact syntax.
+ */
public SVGPath smoothQuadTo(Vector xy) {
append(SVGConstants.PATH_SMOOTH_QUAD_TO, xy.get(0), xy.get(1));
return this;
@@ -517,6 +675,17 @@ public class SVGPath {
* @param xy new coordinates
* @return path object, for compact syntax.
*/
+ public SVGPath relativeSmoothQuadTo(double[] xy) {
+ append(PATH_SMOOTH_QUAD_TO_RELATIVE, xy[0], xy[1]);
+ return this;
+ }
+
+ /**
+ * Smooth quadratic Bezier line to the given relative coordinates.
+ *
+ * @param xy new coordinates
+ * @return path object, for compact syntax.
+ */
public SVGPath relativeSmoothQuadTo(Vector xy) {
append(PATH_SMOOTH_QUAD_TO_RELATIVE, xy.get(0), xy.get(1));
return this;
@@ -528,7 +697,7 @@ public class SVGPath {
* @param rx x radius
* @param ry y radius
* @param ar x-axis-rotation
- * @param la large arc flag, if angle >= 180°
+ * @param la large arc flag, if angle >= 180 deg
* @param sp sweep flag, if arc will be drawn in positive-angle direction
* @param x new coordinates
* @param y new coordinates
@@ -541,9 +710,24 @@ public class SVGPath {
/**
* Elliptical arc curve to the given coordinates.
*
+ * @param rx x radius
+ * @param ry y radius
+ * @param ar x-axis-rotation
+ * @param la large arc flag, if angle >= 180 deg
+ * @param sp sweep flag, if arc will be drawn in positive-angle direction
+ * @param xy new coordinates
+ */
+ public SVGPath ellipticalArc(double rx, double ry, double ar, double la, double sp, double[] xy) {
+ append(SVGConstants.PATH_ARC, rx, ry, ar, la, sp, xy[0], xy[1]);
+ return this;
+ }
+
+ /**
+ * Elliptical arc curve to the given coordinates.
+ *
* @param rxy radius
* @param ar x-axis-rotation
- * @param la large arc flag, if angle >= 180°
+ * @param la large arc flag, if angle >= 180 deg
* @param sp sweep flag, if arc will be drawn in positive-angle direction
* @param xy new coordinates
*/
@@ -558,7 +742,7 @@ public class SVGPath {
* @param rx x radius
* @param ry y radius
* @param ar x-axis-rotation
- * @param la large arc flag, if angle >= 180°
+ * @param la large arc flag, if angle >= 180 deg
* @param sp sweep flag, if arc will be drawn in positive-angle direction
* @param x new coordinates
* @param y new coordinates
@@ -571,9 +755,24 @@ public class SVGPath {
/**
* Elliptical arc curve to the given relative coordinates.
*
+ * @param rx x radius
+ * @param ry y radius
+ * @param ar x-axis-rotation
+ * @param la large arc flag, if angle >= 180 deg
+ * @param sp sweep flag, if arc will be drawn in positive-angle direction
+ * @param xy new coordinates
+ */
+ public SVGPath relativeEllipticalArc(double rx, double ry, double ar, double la, double sp, double[] xy) {
+ append(PATH_ARC_RELATIVE, rx, ry, ar, la, sp, xy[0], xy[1]);
+ return this;
+ }
+
+ /**
+ * Elliptical arc curve to the given relative coordinates.
+ *
* @param rxy radius
* @param ar x-axis-rotation
- * @param la large arc flag, if angle >= 180°
+ * @param la large arc flag, if angle >= 180 deg
* @param sp sweep flag, if arc will be drawn in positive-angle direction
* @param xy new coordinates
*/
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 14889fb0..81299b10 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,15 +23,12 @@ package de.lmu.ifi.dbs.elki.visualization.svg;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.io.ByteArrayOutputStream;
+import java.awt.image.BufferedImage;
import java.io.File;
-import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.ref.WeakReference;
-import java.net.URI;
-import java.net.URISyntaxException;
import java.util.Collection;
import java.util.HashMap;
@@ -44,31 +41,25 @@ import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.batik.dom.svg.SVGDOMImplementation;
-import org.apache.batik.dom.util.DOMUtilities;
-import org.apache.batik.svggen.SVGSyntax;
import org.apache.batik.transcoder.Transcoder;
import org.apache.batik.transcoder.TranscoderException;
import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;
+import org.apache.batik.transcoder.XMLAbstractTranscoder;
import org.apache.batik.transcoder.image.JPEGTranscoder;
import org.apache.batik.transcoder.image.PNGTranscoder;
-import org.apache.batik.util.Base64EncoderStream;
import org.apache.batik.util.SVGConstants;
-import org.apache.fop.render.ps.EPSTranscoder;
-import org.apache.fop.render.ps.PSTranscoder;
-import org.apache.fop.svg.PDFTranscoder;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
import org.w3c.dom.events.Event;
import org.w3c.dom.svg.SVGDocument;
import org.w3c.dom.svg.SVGPoint;
import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
import de.lmu.ifi.dbs.elki.utilities.FileUtil;
-import de.lmu.ifi.dbs.elki.utilities.xml.XMLNodeListIterator;
+import de.lmu.ifi.dbs.elki.visualization.batikutil.CloneInlineImages;
+import de.lmu.ifi.dbs.elki.visualization.batikutil.ThumbnailTranscoder;
import de.lmu.ifi.dbs.elki.visualization.css.CSSClass;
import de.lmu.ifi.dbs.elki.visualization.css.CSSClassManager;
import de.lmu.ifi.dbs.elki.visualization.css.CSSClassManager.CSSNamingConflict;
@@ -165,12 +156,12 @@ public class SVGPlot {
// create a CSS class manager.
cssman = new CSSClassManager();
}
-
+
/**
* Clean up the plot.
*/
public void dispose() {
- getUpdateRunner().clear();
+ runner.clear();
}
/**
@@ -296,6 +287,7 @@ public class SVGPlot {
/**
* Convenience method to add a CSS class or log an error.
+ *
* @param cls CSS class to add.
*/
public void addCSSClassOrLogError(CSSClass cls) {
@@ -303,7 +295,7 @@ public class SVGPlot {
cssman.addClass(cls);
}
catch(CSSNamingConflict e) {
- de.lmu.ifi.dbs.elki.logging.LoggingUtil.exception(e);
+ //de.lmu.ifi.dbs.elki.logging.LoggingUtil.exception(e);
}
}
@@ -313,8 +305,7 @@ public class SVGPlot {
*/
public void updateStyleElement() {
// TODO: this should be sufficient - why does Batik occasionally not pick up
- // the
- // changes unless we actually replace the style element itself?
+ // the changes unless we actually replace the style element itself?
// cssman.updateStyleElement(document, style);
Element newstyle = cssman.makeStyleElement(document);
style.getParentNode().replaceChild(newstyle, style);
@@ -336,40 +327,7 @@ public class SVGPlot {
OutputStream out = new FileOutputStream(file);
// TODO embed linked images.
javax.xml.transform.Result result = new StreamResult(out);
- // deep clone document
- SVGDocument doc = (SVGDocument) DOMUtilities.deepCloneDocument(getDocument(), getDocument().getImplementation());
- NodeList imgs = doc.getElementsByTagNameNS(SVGConstants.SVG_NAMESPACE_URI, SVGConstants.SVG_IMAGE_TAG);
- final String tmpurl = new File(System.getProperty("java.io.tmpdir") + File.separator).toURI().toString();
- for(Node img : new XMLNodeListIterator(imgs)) {
- if(img instanceof Element) {
- try {
- Element i = (Element) img;
- String href = i.getAttributeNS(SVGConstants.XLINK_NAMESPACE_URI, SVGConstants.XLINK_HREF_ATTRIBUTE);
- if(href.startsWith(tmpurl) && href.endsWith(".png")) {
- // need to convert the image into an inline image.
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- Base64EncoderStream encoder = new Base64EncoderStream(os);
- File in = new File(new URI(href));
- FileInputStream instream = new FileInputStream(in);
- byte[] buf = new byte[4096];
- while(true) {
- int read = instream.read(buf, 0, buf.length);
- if(read <= 0) {
- break;
- }
- encoder.write(buf, 0, read);
- }
- instream.close();
- encoder.close();
- // replace HREF with inlined image data.
- i.setAttributeNS(SVGConstants.XLINK_NAMESPACE_URI, SVGConstants.XLINK_HREF_ATTRIBUTE, SVGSyntax.DATA_PROTOCOL_PNG_PREFIX + os.toString());
- }
- }
- catch(URISyntaxException e) {
- LoggingUtil.warning("Error in embedding PNG image.");
- }
- }
- }
+ SVGDocument doc = cloneDocument();
// Use a transformer for pretty printing
Transformer xformer = TransformerFactory.newInstance().newTransformer();
xformer.setOutputProperty(OutputKeys.INDENT, "yes");
@@ -387,11 +345,9 @@ public class SVGPlot {
* @throws TranscoderException On input/parsing errors
*/
protected void transcode(File file, Transcoder transcoder) throws IOException, TranscoderException {
- // Since the Transcoder is Batik-based, it will replace the rendering tree,
- // which would then break display. Thus we need to deep clone the document
- // first.
- // -- found by Simon.
- SVGDocument doc = (SVGDocument) DOMUtilities.deepCloneDocument(getDocument(), getDocument().getImplementation());
+ // Disable validation, performance is more important here (thumbnails!)
+ transcoder.addTranscodingHint(XMLAbstractTranscoder.KEY_XML_PARSER_VALIDATING, Boolean.FALSE);
+ SVGDocument doc = cloneDocument();
TranscoderInput input = new TranscoderInput(doc);
OutputStream out = new FileOutputStream(file);
TranscoderOutput output = new TranscoderOutput(out);
@@ -401,14 +357,37 @@ public class SVGPlot {
}
/**
+ * Clone the SVGPlot document for transcoding.
+ *
+ * This will usually be necessary for exporting the SVG document if it is
+ * currently being displayed: otherwise, we break the Batik rendering trees.
+ * (Discovered by Simon).
+ *
+ * @return cloned document
+ */
+ protected SVGDocument cloneDocument() {
+ return (SVGDocument) new CloneInlineImages().cloneDocument(SVGDOMImplementation.getDOMImplementation(), document);
+ }
+
+ /**
* Transcode file to PDF.
*
* @param file Output filename
* @throws IOException On write errors
* @throws TranscoderException On input/parsing errors.
+ * @throws ClassNotFoundException PDF transcoder not installed
*/
- public void saveAsPDF(File file) throws IOException, TranscoderException {
- transcode(file, new PDFTranscoder());
+ public void saveAsPDF(File file) throws IOException, TranscoderException, ClassNotFoundException {
+ try {
+ Object t = Class.forName("org.apache.fop.svg.PDFTranscoder").newInstance();
+ transcode(file, (Transcoder) t);
+ }
+ catch(InstantiationException e) {
+ throw new ClassNotFoundException("Could not instantiate PDF transcoder - is Apache FOP installed?", e);
+ }
+ catch(IllegalAccessException e) {
+ throw new ClassNotFoundException("Could not instantiate PDF transcoder - is Apache FOP installed?", e);
+ }
}
/**
@@ -417,9 +396,19 @@ public class SVGPlot {
* @param file Output filename
* @throws IOException On write errors
* @throws TranscoderException On input/parsing errors.
+ * @throws ClassNotFoundException PS transcoder not installed
*/
- public void saveAsPS(File file) throws IOException, TranscoderException {
- transcode(file, new PSTranscoder());
+ public void saveAsPS(File file) throws IOException, TranscoderException, ClassNotFoundException {
+ try {
+ Object t = Class.forName("org.apache.fop.render.ps.PSTranscoder").newInstance();
+ transcode(file, (Transcoder) t);
+ }
+ catch(InstantiationException e) {
+ throw new ClassNotFoundException("Could not instantiate PS transcoder - is Apache FOP installed?", e);
+ }
+ catch(IllegalAccessException e) {
+ throw new ClassNotFoundException("Could not instantiate PS transcoder - is Apache FOP installed?", e);
+ }
}
/**
@@ -428,9 +417,36 @@ public class SVGPlot {
* @param file Output filename
* @throws IOException On write errors
* @throws TranscoderException On input/parsing errors.
+ * @throws ClassNotFoundException EPS transcoder not installed
*/
- public void saveAsEPS(File file) throws IOException, TranscoderException {
- transcode(file, new EPSTranscoder());
+ public void saveAsEPS(File file) throws IOException, TranscoderException, ClassNotFoundException {
+ try {
+ Object t = Class.forName("org.apache.fop.render.ps.EPSTranscoder").newInstance();
+ transcode(file, (Transcoder) t);
+ }
+ catch(InstantiationException e) {
+ throw new ClassNotFoundException("Could not instantiate EPS transcoder - is Apache FOP installed?", e);
+ }
+ catch(IllegalAccessException e) {
+ throw new ClassNotFoundException("Could not instantiate EPS transcoder - is Apache FOP installed?", e);
+ }
+ }
+
+ /**
+ * Test whether FOP were installed (for PDF, PS and EPS output support).
+ *
+ * @return true when FOP is available.
+ */
+ public static boolean hasFOPInstalled() {
+ try {
+ Class<?> c1 = Class.forName("org.apache.fop.svg.PDFTranscoder");
+ Class<?> c2 = Class.forName("org.apache.fop.render.ps.PSTranscoder");
+ Class<?> c3 = Class.forName("org.apache.fop.render.ps.EPSTranscoder");
+ return (c1 != null) && (c2 != null) && (c3 != null);
+ }
+ catch(ClassNotFoundException e) {
+ return false;
+ }
}
/**
@@ -491,8 +507,9 @@ public class SVGPlot {
* @throws TranscoderException on transcoding errors
* @throws TransformerFactoryConfigurationError on transcoding errors
* @throws TransformerException on transcoding errors
+ * @throws ClassNotFoundException when the transcoder was not installed
*/
- public void saveAsANY(File file, int width, int height, double quality) throws IOException, TranscoderException, TransformerFactoryConfigurationError, TransformerException {
+ public void saveAsANY(File file, int width, int height, double quality) throws IOException, TranscoderException, TransformerFactoryConfigurationError, TransformerException, ClassNotFoundException {
String extension = FileUtil.getFilenameExtension(file);
if(extension.equals("svg")) {
saveAsSVG(file);
@@ -518,6 +535,23 @@ public class SVGPlot {
}
/**
+ * Convert the SVG to a thumbnail image.
+ *
+ * @param width Width of thumbnail
+ * @param height Height of thumbnail
+ * @return Buffered image
+ */
+ public BufferedImage makeAWTImage(int width, int height) throws TranscoderException {
+ ThumbnailTranscoder t = new ThumbnailTranscoder();
+ t.addTranscodingHint(PNGTranscoder.KEY_WIDTH, new Float(width));
+ t.addTranscodingHint(PNGTranscoder.KEY_HEIGHT, new Float(height));
+ // Don't clone. Assume this is used safely.
+ TranscoderInput input = new TranscoderInput(document);
+ t.transcode(input, null);
+ return t.getLastImage();
+ }
+
+ /**
* Dump the SVG plot to a debug file.
*/
public void dumpDebugFile() {
@@ -563,21 +597,12 @@ public class SVGPlot {
}
/**
- * Get the plots update runner.
- *
- * @return update runner
- */
- private UpdateRunner getUpdateRunner() {
- return runner;
- }
-
- /**
* Schedule an update.
*
* @param runnable Runnable to schedule
*/
public void scheduleUpdate(Runnable runnable) {
- getUpdateRunner().invokeLater(runnable);
+ runner.invokeLater(runnable);
}
/**
@@ -586,7 +611,7 @@ public class SVGPlot {
* @param sync Update synchronizer
*/
public void synchronizeWith(UpdateSynchronizer sync) {
- getUpdateRunner().synchronizeWith(sync);
+ runner.synchronizeWith(sync);
}
/**
@@ -595,7 +620,7 @@ public class SVGPlot {
* @param sync Update synchronizer to detach from.
*/
public void unsynchronizeWith(UpdateSynchronizer sync) {
- getUpdateRunner().unsynchronizeWith(sync);
+ runner.unsynchronizeWith(sync);
}
/**
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGScoreBar.java b/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGScoreBar.java
new file mode 100644
index 00000000..185a6061
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/svg/SVGScoreBar.java
@@ -0,0 +1,118 @@
+package de.lmu.ifi.dbs.elki.visualization.svg;
+
+import java.text.NumberFormat;
+
+import org.apache.batik.util.SVGConstants;
+import org.w3c.dom.Element;
+
+import de.lmu.ifi.dbs.elki.utilities.FormatUtil;
+
+/**
+ * Draw a score bar. Essentially like a progress bar, left-to-right, displaying
+ * a relative score.
+ *
+ * @author Sascha Goldhofer
+ */
+// TODO: refactor to get a progress bar?
+public class SVGScoreBar {
+ /**
+ * Fill value
+ */
+ protected double fill = 0.0;
+
+ /**
+ * Total size
+ */
+ protected double size = 1.0;
+
+ /**
+ * Label (on the right)
+ */
+ protected String label = null;
+
+ /**
+ * Number format, set to print the actual score
+ */
+ private NumberFormat format = null;
+
+ /**
+ * Constructor.
+ */
+ public SVGScoreBar() {
+ // Nothing to do here.
+ }
+
+ /**
+ * Set the fill of the score bar.
+ *
+ * @param fill Fill value
+ * @param size Total size
+ */
+ public void setFill(double fill, double size) {
+ this.fill = fill;
+ this.size = size;
+ }
+
+ /**
+ * Set label (right of the bar)
+ *
+ * @param text Label text
+ */
+ public void addLabel(String text) {
+ this.label = text;
+ }
+
+ /**
+ * To show score values, set a number format
+ *
+ * @param format Number format
+ */
+ public void showValues(NumberFormat format) {
+ this.format = format;
+ }
+
+ /**
+ * Build the actual element
+ *
+ * @param svgp Plot to draw to
+ * @param x X coordinate
+ * @param y Y coordinate
+ * @param width Width
+ * @param height Height
+ * @return new element
+ */
+ public Element build(SVGPlot svgp, double x, double y, double width, double height) {
+ Element barchart = svgp.svgElement(SVGConstants.SVG_G_TAG);
+
+ // TODO: use style library for colors!
+ Element bar = svgp.svgRect(x, y, width, height);
+ bar.setAttribute(SVGConstants.SVG_FILL_ATTRIBUTE, "#a0a0a0");
+ bar.setAttribute(SVGConstants.SVG_STROKE_ATTRIBUTE, "#a0a0a0");
+ bar.setAttribute(SVGConstants.SVG_STROKE_WIDTH_ATTRIBUTE, "" + height * 0.01);
+
+ double fpos = (fill / size) * (width - (0.04 * height));
+ Element chart = svgp.svgRect(x + 0.02 * height, y + 0.02 * height, fpos, height - 0.04 * height);
+ chart.setAttribute(SVGConstants.SVG_FILL_ATTRIBUTE, "#d4e4f1");
+ chart.setAttribute(SVGConstants.SVG_STROKE_ATTRIBUTE, "#a0a0a0");
+ chart.setAttribute(SVGConstants.SVG_STROKE_WIDTH_ATTRIBUTE, "" + height * 0.01);
+
+ barchart = svgp.svgElement(SVGConstants.SVG_G_TAG);
+ barchart.appendChild(bar);
+ barchart.appendChild(chart);
+
+ // Draw the values:
+ if(format != null) {
+ Element lbl = svgp.svgText(x + 0.05 * width, y + 0.75 * height, FormatUtil.format(fill, format));
+ lbl.setAttribute(SVGConstants.SVG_STYLE_ATTRIBUTE, "font-size: " + 0.75 * height + "; font-weight: bold");
+ barchart.appendChild(lbl);
+ }
+
+ // Draw the label
+ if(label != null) {
+ Element lbl = svgp.svgText(x + 1.05 * width, y + 0.75 * height, label);
+ lbl.setAttribute(SVGConstants.SVG_STYLE_ATTRIBUTE, "font-size: " + 0.75 * height + "; font-weight: normal");
+ barchart.appendChild(lbl);
+ }
+ return barchart;
+ }
+} \ No newline at end of file
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 c32fef04..9a676c38 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) 2011
+ Copyright (C) 2012
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.visualization.svg;
import org.apache.batik.util.SVGConstants;
import org.w3c.dom.Element;
+import de.lmu.ifi.dbs.elki.math.scales.LinearScale;
import de.lmu.ifi.dbs.elki.visualization.css.CSSClass;
import de.lmu.ifi.dbs.elki.visualization.css.CSSClassManager;
import de.lmu.ifi.dbs.elki.visualization.css.CSSClassManager.CSSNamingConflict;
-import de.lmu.ifi.dbs.elki.visualization.scales.LinearScale;
import de.lmu.ifi.dbs.elki.visualization.style.StyleLibrary;
/**
@@ -41,6 +41,7 @@ import de.lmu.ifi.dbs.elki.visualization.style.StyleLibrary;
* @apiviz.uses CSSClassManager
* @apiviz.uses LinearScale
* @apiviz.uses StyleLibrary
+ * @apiviz.uses STYLE
* @apiviz.uses Element oneway - - «create»
*/
public class SVGSimpleLinearAxis {
@@ -55,6 +56,15 @@ public class SVGSimpleLinearAxis {
}
/**
+ * Labeling style: left-handed, right-handed, no ticks, labels at ends
+ *
+ * @author Erich Schubert
+ */
+ public enum LabelStyle {
+ LEFTHAND, RIGHTHAND, NOLABELS, NOTHING, ENDLABEL
+ }
+
+ /**
* CSS class name for the axes
*/
private final static String CSS_AXIS = "axis";
@@ -93,8 +103,6 @@ public class SVGSimpleLinearAxis {
CSSClass label = new CSSClass(owner, CSS_AXIS_LABEL);
label.setStatement(SVGConstants.CSS_FILL_PROPERTY, style.getTextColor(StyleLibrary.AXIS_LABEL));
label.setStatement(SVGConstants.CSS_FONT_FAMILY_PROPERTY, style.getFontFamily(StyleLibrary.AXIS_LABEL));
- // label.setStatement(SVGConstants.SVG_TEXT_RENDERING_ATTRIBUTE,
- // SVGConstants.SVG_OPTIMIZE_LEGIBILITY_VALUE);
label.setStatement(SVGConstants.CSS_FONT_SIZE_PROPERTY, style.getTextSize(StyleLibrary.AXIS_LABEL));
manager.addClass(label);
}
@@ -110,13 +118,11 @@ public class SVGSimpleLinearAxis {
* @param y1 starting coordinate
* @param x2 ending coordinate
* @param y2 ending coordinate
- * @param labels control whether labels are printed.
- * @param righthanded control whether to print labels on the right hand side
- * or left hand side
+ * @param labelstyle Style for placing the labels
* @param style Style library
* @throws CSSNamingConflict when a conflict occurs in CSS
*/
- public static void drawAxis(SVGPlot plot, Element parent, LinearScale scale, double x1, double y1, double x2, double y2, boolean labels, boolean righthanded, StyleLibrary style) throws CSSNamingConflict {
+ public static void drawAxis(SVGPlot plot, Element parent, LinearScale scale, double x1, double y1, double x2, double y2, LabelStyle labelstyle, StyleLibrary style) throws CSSNamingConflict {
assert (parent != null);
Element line = plot.svgLine(x1, y1, x2, y2);
SVGUtil.setCSSClass(line, CSS_AXIS);
@@ -129,75 +135,109 @@ public class SVGSimpleLinearAxis {
double th = -tx * 0.01;
// choose where to print labels.
+ final boolean labels, ticks;
+ switch(labelstyle){
+ case LEFTHAND:
+ case RIGHTHAND:
+ labels = true;
+ ticks = true;
+ break;
+ case NOLABELS:
+ labels = false;
+ ticks = true;
+ break;
+ case ENDLABEL: // end labels are handle specially
+ case NOTHING:
+ default:
+ labels = false;
+ ticks = false;
+ }
ALIGNMENT pos = ALIGNMENT.LL;
if(labels) {
double angle = Math.atan2(ty, tx);
// System.err.println(tx + " " + (-ty) + " " + angle);
if(angle > 2.6) { // pi .. 2.6 = 180 .. 150
- pos = righthanded ? ALIGNMENT.RC : ALIGNMENT.LC;
+ pos = labelstyle == LabelStyle.RIGHTHAND ? ALIGNMENT.RC : ALIGNMENT.LC;
}
else if(angle > 0.5) { // 2.3 .. 0.7 = 130 .. 40
- pos = righthanded ? ALIGNMENT.RR : ALIGNMENT.LL;
+ pos = labelstyle == LabelStyle.RIGHTHAND ? ALIGNMENT.RR : ALIGNMENT.LL;
}
else if(angle > -0.5) { // 0.5 .. -0.5 = 30 .. -30
- pos = righthanded ? ALIGNMENT.RC : ALIGNMENT.LC;
+ pos = labelstyle == LabelStyle.RIGHTHAND ? ALIGNMENT.RC : ALIGNMENT.LC;
}
else if(angle > -2.6) { // -0.5 .. -2.6 = -30 .. -150
- pos = righthanded ? ALIGNMENT.RL : ALIGNMENT.LR;
+ pos = labelstyle == LabelStyle.RIGHTHAND ? ALIGNMENT.RL : ALIGNMENT.LR;
}
else { // -2.6 .. -pi = -150 .. -180
- pos = righthanded ? ALIGNMENT.RC : ALIGNMENT.LC;
+ pos = labelstyle == LabelStyle.RIGHTHAND ? ALIGNMENT.RC : ALIGNMENT.LC;
}
}
// vertical text offset; align approximately with middle instead of
// baseline.
- double textvoff = 0.015;
+ double textvoff = style.getTextSize(StyleLibrary.AXIS_LABEL) * .35;
// draw ticks on x axis
- for(double tick = scale.getMin(); tick <= scale.getMax() + scale.getRes() / 10; tick += scale.getRes()) {
- double x = x1 + tx * scale.getScaled(tick);
- double y = y1 + ty * scale.getScaled(tick);
- // This is correct. Vectors: (vec - tvec) to (vec + tvec)
- Element tickline = plot.svgLine(x - tw, y - th, x + tw, y + th);
- SVGUtil.setAtt(tickline, SVGConstants.SVG_CLASS_ATTRIBUTE, CSS_AXIS_TICK);
- parent.appendChild(tickline);
- // draw labels
- if(labels) {
- double tex = x;
- double tey = y;
- switch(pos){
- case LL:
- case LC:
- case LR:
- tex = x + tw * 2.5;
- tey = y + th * 2.5 + textvoff;
- break;
- case RL:
- case RC:
- case RR:
- tex = x - tw * 2.5;
- tey = y - th * 2.5 + textvoff;
+ if(ticks || labels) {
+ for(double tick = scale.getMin(); tick <= scale.getMax() + scale.getRes() / 10; tick += scale.getRes()) {
+ double x = x1 + tx * scale.getScaled(tick);
+ double y = y1 + ty * scale.getScaled(tick);
+ if(ticks) {
+ // This is correct. Vectors: (vec - tvec) to (vec + tvec)
+ Element tickline = plot.svgLine(x - tw, y - th, x + tw, y + th);
+ SVGUtil.setAtt(tickline, SVGConstants.SVG_CLASS_ATTRIBUTE, CSS_AXIS_TICK);
+ parent.appendChild(tickline);
}
- Element text = plot.svgText(tex, tey, scale.formatValue(tick));
- SVGUtil.setAtt(text, SVGConstants.SVG_CLASS_ATTRIBUTE, CSS_AXIS_LABEL);
- switch(pos){
- case LL:
- case RL:
- SVGUtil.setAtt(text, SVGConstants.SVG_TEXT_ANCHOR_ATTRIBUTE, SVGConstants.SVG_START_VALUE);
- break;
- case LC:
- case RC:
- SVGUtil.setAtt(text, SVGConstants.SVG_TEXT_ANCHOR_ATTRIBUTE, SVGConstants.SVG_MIDDLE_VALUE);
- break;
- case LR:
- case RR:
- SVGUtil.setAtt(text, SVGConstants.SVG_TEXT_ANCHOR_ATTRIBUTE, SVGConstants.SVG_END_VALUE);
- break;
+ // draw labels
+ if(labels) {
+ double tex = x;
+ double tey = y;
+ switch(pos){
+ case LL:
+ case LC:
+ case LR:
+ tex = x + tw * 2.5;
+ tey = y + th * 2.5 + textvoff;
+ break;
+ case RL:
+ case RC:
+ case RR:
+ tex = x - tw * 2.5;
+ tey = y - th * 2.5 + textvoff;
+ }
+ Element text = plot.svgText(tex, tey, scale.formatValue(tick));
+ text.setAttribute(SVGConstants.SVG_CLASS_ATTRIBUTE, CSS_AXIS_LABEL);
+ switch(pos){
+ case LL:
+ case RL:
+ text.setAttribute(SVGConstants.SVG_TEXT_ANCHOR_ATTRIBUTE, SVGConstants.SVG_START_VALUE);
+ break;
+ case LC:
+ case RC:
+ text.setAttribute(SVGConstants.SVG_TEXT_ANCHOR_ATTRIBUTE, SVGConstants.SVG_MIDDLE_VALUE);
+ break;
+ case LR:
+ case RR:
+ text.setAttribute(SVGConstants.SVG_TEXT_ANCHOR_ATTRIBUTE, SVGConstants.SVG_END_VALUE);
+ break;
+ }
+ parent.appendChild(text);
}
+ }
+ }
+ if(labelstyle == LabelStyle.ENDLABEL) {
+ {
+ Element text = plot.svgText(x1 - tx * 0.02, y1 - ty * 0.02 + textvoff, scale.formatValue(scale.getMin()));
+ text.setAttribute(SVGConstants.SVG_CLASS_ATTRIBUTE, CSS_AXIS_LABEL);
+ text.setAttribute(SVGConstants.SVG_TEXT_ANCHOR_ATTRIBUTE, SVGConstants.SVG_MIDDLE_VALUE);
+ parent.appendChild(text);
+ }
+ {
+ Element text = plot.svgText(x2 + tx * 0.02, y2 + ty * 0.02 + textvoff, scale.formatValue(scale.getMax()));
+ text.setAttribute(SVGConstants.SVG_CLASS_ATTRIBUTE, CSS_AXIS_LABEL);
+ text.setAttribute(SVGConstants.SVG_TEXT_ANCHOR_ATTRIBUTE, SVGConstants.SVG_MIDDLE_VALUE);
parent.appendChild(text);
}
}
setupCSSClasses(plot, plot.getCSSClassManager(), style);
}
-
-}
+} \ No newline at end of file
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 b4e59fda..4e40d1b0 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) 2011
+ Copyright (C) 2012
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.visualization.svg;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import gnu.trove.map.hash.TObjectIntHashMap;
+
import java.awt.Color;
import java.text.NumberFormat;
-import java.util.HashMap;
import java.util.Locale;
import javax.swing.text.html.StyleSheet;
@@ -77,9 +78,16 @@ public final class SVGUtil {
/**
* SVG color names conversion.
*/
- final private static HashMap<String, Integer> SVG_COLOR_NAMES = new HashMap<String, Integer>();
+ final private static TObjectIntHashMap<String> SVG_COLOR_NAMES;
+
+ /**
+ * Key not found value. Not a reasonable color, fully transparent!
+ */
+ final private static int NO_VALUE = 0x00123456;
static {
+ // Build a reasonably sized hashmap. Use 0
+ SVG_COLOR_NAMES = new TObjectIntHashMap<String>(90, .8f, NO_VALUE);
// List taken from SVG specification:
// http://www.w3.org/TR/SVG/types.html#ColorKeywords
SVG_COLOR_NAMES.put("aliceblue", 0xFFF0F8FF);
@@ -229,6 +237,8 @@ public final class SVGUtil {
SVG_COLOR_NAMES.put("whitesmoke", 0xFFF5F5F5);
SVG_COLOR_NAMES.put("yellow", 0xFFFFFF00);
SVG_COLOR_NAMES.put("yellowgreen", 0xFF9ACD32);
+ // Nonstandard:
+ SVG_COLOR_NAMES.put("transparent", 0xFFFFFFFF);
}
/**
@@ -468,8 +478,8 @@ public final class SVGUtil {
* @return Color value
*/
public static Color stringToColor(String str) {
- Integer icol = SVG_COLOR_NAMES.get(str.toLowerCase());
- if(icol != null) {
+ int icol = SVG_COLOR_NAMES.get(str.toLowerCase());
+ if(icol != NO_VALUE) {
return new Color(icol, false);
}
return colorLookupStylesheet.stringToColor(str);
@@ -478,6 +488,8 @@ public final class SVGUtil {
/**
* Convert a color name from an AWT color object to CSS syntax
*
+ * Note: currently only RGB (from ARGB order) are supported.
+ *
* @param col Color value
* @return Color string
*/
@@ -486,6 +498,18 @@ public final class SVGUtil {
}
/**
+ * Convert a color name from an AWT color object to CSS syntax
+ *
+ * Note: currently only RGB (from ARGB order) are supported.
+ *
+ * @param col Color value
+ * @return Color string
+ */
+ public static String colorToString(int col) {
+ return String.format("#%02x%02x%02x", (col >>> 16) & 0xFF, (col >>> 8) & 0xFF, col & 0xFF);
+ }
+
+ /**
* Make a transform string to add margins
*
* @param owidth Width of outer (embedding) canvas
@@ -572,4 +596,62 @@ public final class SVGUtil {
tag.removeChild(last);
}
}
+
+ /**
+ * Remove an element from its parent, if defined.
+ *
+ * @param elem Element to remove
+ */
+ public static void removeFromParent(Element elem) {
+ if(elem != null) {
+ if(elem.getParentNode() != null) {
+ elem.getParentNode().removeChild(elem);
+ }
+ }
+ }
+
+ /**
+ * Create a circle segment.
+ *
+ * @param svgp Plot to draw to
+ * @param centerx Center X position
+ * @param centery Center Y position
+ * @param angleStart Starting angle
+ * @param angleDelta Angle delta
+ * @param innerRadius inner radius
+ * @param outerRadius outer radius
+ * @return SVG element representing this circle segment
+ */
+ 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 sin2nd = Math.sin(angleStart + angleDelta);
+ double cos2nd = Math.cos(angleStart + angleDelta);
+
+ double inner1stx = centerx + (innerRadius * sin1st);
+ double inner1sty = centery - (innerRadius * cos1st);
+ double outer1stx = centerx + (outerRadius * sin1st);
+ double outer1sty = centery - (outerRadius * cos1st);
+
+ double inner2ndx = centerx + (innerRadius * sin2nd);
+ double inner2ndy = centery - (innerRadius * cos2nd);
+ double outer2ndx = centerx + (outerRadius * sin2nd);
+ double outer2ndy = centery - (outerRadius * cos2nd);
+
+ double largeArc = 0;
+ if(angleDelta >= Math.PI) {
+ largeArc = 1;
+ }
+
+ SVGPath path = new SVGPath(inner1stx, inner1sty);
+ path.lineTo(outer1stx, outer1sty);
+ path.ellipticalArc(outerRadius, outerRadius, 0, largeArc, 1, outer2ndx, outer2ndy);
+ path.lineTo(inner2ndx, inner2ndy);
+ if (innerRadius > 0) {
+ path.ellipticalArc(innerRadius, innerRadius, 0, largeArc, 0, inner1stx, inner1sty);
+ }
+
+ return path.makeElement(svgp);
+ }
} \ No newline at end of file
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 03bc9d74..463c7c63 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) 2011
+ Copyright (C) 2012
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.visualization.svg;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.Collection;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
@@ -52,7 +51,7 @@ public class UpdateRunner {
/**
* Synchronizer that can block events from being executed right away.
*/
- private Collection<UpdateSynchronizer> synchronizer = new java.util.Vector<UpdateSynchronizer>();
+ private UpdateSynchronizer synchronizer = null;
/**
* Construct a new update handler
@@ -70,13 +69,11 @@ public class UpdateRunner {
*/
public void invokeLater(Runnable r) {
queue.add(r);
- if(synchronizer.size() > 0) {
- for(UpdateSynchronizer s : synchronizer) {
- s.activate();
- }
+ if(synchronizer == null) {
+ runQueue();
}
else {
- runQueue();
+ synchronizer.activate();
}
}
@@ -128,14 +125,18 @@ public class UpdateRunner {
* @param newsync Update synchronizer
*/
public synchronized void synchronizeWith(UpdateSynchronizer newsync) {
- //LoggingUtil.warning("Synchronizing: " + sync + " " + newsync);
- if(synchronizer.contains(newsync)) {
+ // LoggingUtil.warning("Synchronizing: " + sync + " " + newsync);
+ if(synchronizer == newsync) {
LoggingUtil.warning("Double-synced to the same plot!");
+ return;
}
- else {
- synchronizer.add(newsync);
- newsync.addUpdateRunner(this);
+ if(synchronizer != null) {
+ LoggingUtil.warning("Attempting to synchronize to more than one synchronizer.");
+ return;
}
+ synchronizer = newsync;
+ newsync.addUpdateRunner(this);
+
}
/**
@@ -144,10 +145,17 @@ public class UpdateRunner {
* @param oldsync Update synchronizer to remove
*/
public synchronized void unsynchronizeWith(UpdateSynchronizer oldsync) {
- //LoggingUtil.warning("Unsynchronizing: " + sync + " " + oldsync);
- synchronizer.remove(oldsync);
- if(synchronizer.size() == 0) {
- runQueue();
+ if(synchronizer == null) {
+ LoggingUtil.warning("Warning: was not synchronized.");
+ }
+ else {
+ if(synchronizer != oldsync) {
+ LoggingUtil.warning("Warning: was synchronized differently!");
+ return;
+ }
}
+ // LoggingUtil.warning("Unsynchronizing: " + sync + " " + oldsync);
+ synchronizer = null;
+ runQueue();
}
} \ No newline at end of file
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 c65ae719..3f249871 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) 2011
+ Copyright (C) 2012
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
new file mode 100644
index 00000000..317a44ae
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/svg/VoronoiDraw.java
@@ -0,0 +1,152 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.math.geometry.SweepHullDelaunay2D;
+import de.lmu.ifi.dbs.elki.math.geometry.SweepHullDelaunay2D.Triangle;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.VMath;
+import de.lmu.ifi.dbs.elki.visualization.projections.CanvasSize;
+import de.lmu.ifi.dbs.elki.visualization.projections.Projection2D;
+
+/**
+ * Draw the Voronoi cells
+ *
+ * @author Robert Rödler
+ * @author Erich Schubert
+ */
+public class VoronoiDraw {
+ /**
+ * Draw the Delaunay triangulation.
+ *
+ * @param proj Projection
+ * @param delaunay Triangulation
+ * @param means Means
+ * @return Path
+ */
+ public static SVGPath drawDelaunay(Projection2D proj, List<SweepHullDelaunay2D.Triangle> delaunay, List<double[]> means) {
+ final SVGPath path = new SVGPath();
+ for(SweepHullDelaunay2D.Triangle del : delaunay) {
+ path.moveTo(proj.fastProjectDataToRenderSpace(means.get(del.a)));
+ path.drawTo(proj.fastProjectDataToRenderSpace(means.get(del.b)));
+ path.drawTo(proj.fastProjectDataToRenderSpace(means.get(del.c)));
+ path.close();
+ }
+ return path;
+ }
+
+ /**
+ * Draw a Voronoi diagram
+ *
+ * @param proj Projection
+ * @param delaunay Delaunay triangulation
+ * @param means Cluster means
+ * @return SVG path
+ */
+ public static SVGPath drawVoronoi(Projection2D proj, List<SweepHullDelaunay2D.Triangle> delaunay, List<double[]> means) {
+ final SVGPath path = new SVGPath();
+ CanvasSize viewport = proj.estimateViewport();
+ for(int i = 0; i < delaunay.size(); i++) {
+ SweepHullDelaunay2D.Triangle del = delaunay.get(i);
+ final double[] projcx = proj.fastProjectDataToRenderSpace(del.m.getArrayRef());
+ if(del.ab > i) {
+ Triangle oth = delaunay.get(del.ab);
+ path.moveTo(projcx);
+ path.drawTo(proj.fastProjectDataToRenderSpace(oth.m.getArrayRef()));
+ }
+ else if(del.ab < 0) {
+ double[] dirv = VMath.minus(means.get(del.a), means.get(del.b));
+ VMath.rotate90Equals(dirv);
+ double[] dir = proj.fastProjectRelativeDataToRenderSpace(dirv);
+ final double factor = viewport.continueToMargin(projcx, dir);
+ if(factor > 0) {
+ path.moveTo(projcx);
+ path.relativeLineTo(factor * dir[0], factor * dir[1]);
+ }
+ }
+
+ if(del.bc > i) {
+ Triangle oth = delaunay.get(del.bc);
+ path.moveTo(projcx);
+ path.drawTo(proj.fastProjectDataToRenderSpace(oth.m.getArrayRef()));
+ }
+ else if(del.bc < 0) {
+ double[] dirv = VMath.minus(means.get(del.b), means.get(del.c));
+ VMath.rotate90Equals(dirv);
+ double[] dir = proj.fastProjectRelativeDataToRenderSpace(dirv);
+ final double factor = viewport.continueToMargin(projcx, dir);
+ if(factor > 0) {
+ path.moveTo(projcx);
+ path.relativeLineTo(factor * dir[0], factor * dir[1]);
+ }
+ }
+
+ if(del.ca > i) {
+ Triangle oth = delaunay.get(del.ca);
+ path.moveTo(projcx);
+ path.drawTo(proj.fastProjectDataToRenderSpace(oth.m.getArrayRef()));
+ }
+ else if(del.ca < 0) {
+ double[] dirv = VMath.minus(means.get(del.c), means.get(del.a));
+ VMath.rotate90Equals(dirv);
+ double[] dir = proj.fastProjectRelativeDataToRenderSpace(dirv);
+ final double factor = viewport.continueToMargin(projcx, dir);
+ if(factor > 0) {
+ path.moveTo(projcx);
+ path.relativeLineTo(factor * dir[0], factor * dir[1]);
+ }
+ }
+ }
+ return path;
+ }
+
+ /**
+ * Fake Voronoi diagram. For two means only
+ *
+ * @param proj Projection
+ * @param means Mean vectors
+ * @return SVG path
+ */
+ public static SVGPath drawFakeVoronoi(Projection2D proj, List<double[]> means) {
+ CanvasSize viewport = proj.estimateViewport();
+ final SVGPath path = new SVGPath();
+ // Difference
+ final double[] dirv = VMath.minus(means.get(1), means.get(0));
+ VMath.rotate90Equals(dirv);
+ double[] dir = proj.fastProjectRelativeDataToRenderSpace(dirv);
+ // Mean
+ final double[] mean = VMath.plus(means.get(0), means.get(1));
+ VMath.timesEquals(mean, 0.5);
+ double[] projmean = proj.fastProjectDataToRenderSpace(mean);
+
+ double factor = viewport.continueToMargin(projmean, dir);
+ path.moveTo(projmean[0] + factor * dir[0], projmean[1] + factor * dir[1]);
+ // Inverse direction:
+ dir[0] *= -1;
+ dir[1] *= -1;
+ factor = viewport.continueToMargin(projmean, dir);
+ path.drawTo(projmean[0] + factor * dir[0], projmean[1] + factor * dir[1]);
+ return path;
+ }
+} \ No newline at end of file
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 7c9ba1f9..7811b493 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) 2011
+Copyright (C) 2012
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 4b017fac..40ae5cdf 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -35,6 +35,11 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.thumbs.ThumbnailVisualizati
*/
public abstract class AbstractVisFactory implements VisFactory {
/**
+ * Mask for redrawing thumbnails
+ */
+ protected int thumbmask = 0;
+
+ /**
* Constructor.
*/
protected AbstractVisFactory() {
@@ -46,7 +51,7 @@ public abstract class AbstractVisFactory implements VisFactory {
// Is this a thumbnail request?
Boolean isthumb = task.get(VisualizationTask.THUMBNAIL, Boolean.class);
if (isthumb != null && isthumb.booleanValue() && allowThumbnails(task)) {
- return new ThumbnailVisualization(this, task, 0);
+ return new ThumbnailVisualization(this, task, thumbmask);
}
return makeVisualization(task);
}
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 dab1c6dd..bbff0117 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -25,21 +25,20 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers;
import org.w3c.dom.Element;
+import de.lmu.ifi.dbs.elki.database.datastore.DataStoreEvent;
+import de.lmu.ifi.dbs.elki.database.datastore.DataStoreListener;
import de.lmu.ifi.dbs.elki.result.Result;
import de.lmu.ifi.dbs.elki.result.ResultListener;
import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
import de.lmu.ifi.dbs.elki.visualization.VisualizerContext;
import de.lmu.ifi.dbs.elki.visualization.svg.SVGPlot;
-import de.lmu.ifi.dbs.elki.visualization.visualizers.events.ContextChangeListener;
-import de.lmu.ifi.dbs.elki.visualization.visualizers.events.ContextChangedEvent;
-import de.lmu.ifi.dbs.elki.visualization.visualizers.events.ResizedEvent;
/**
* Abstract base class for visualizations.
*
* @author Erich Schubert
*/
-public abstract class AbstractVisualization implements Visualization, ContextChangeListener, ResultListener {
+public abstract class AbstractVisualization implements Visualization, ResultListener {
/**
* The visualization task we do.
*/
@@ -76,12 +75,18 @@ public abstract class AbstractVisualization implements Visualization, ContextCha
this.context = task.getContext();
this.svgp = task.getPlot();
this.layer = null;
+ // Note: we do not auto-add listeners, as we don't know what kind of
+ // listeners a visualizer needs, and the visualizer might need to do some initialization first
}
@Override
public void destroy() {
- context.removeContextChangeListener(this);
+ // Always unregister listeners, as this is easy to forget otherwise
+ // TODO: remove destroy() overrides that are redundant?
context.removeResultListener(this);
+ if (this instanceof DataStoreListener) {
+ context.removeDataStoreListener((DataStoreListener) this);
+ }
}
@Override
@@ -110,26 +115,6 @@ public abstract class AbstractVisualization implements Visualization, ContextCha
return task.getHeight();
}
- @Override
- public void contextChanged(ContextChangedEvent e) {
- if(testRedraw(e)) {
- synchronizedRedraw();
- }
- }
-
- /**
- * Override this method to add additional redraw triggers!
- *
- * @param e Event
- * @return Test result
- */
- protected boolean testRedraw(ContextChangedEvent e) {
- if(e instanceof ResizedEvent) {
- return true;
- }
- return false;
- }
-
/**
* Trigger a redraw, but avoid excessive redraws.
*/
@@ -186,4 +171,16 @@ public abstract class AbstractVisualization implements Visualization, ContextCha
public void resultRemoved(Result child, Result parent) {
// Ignore by default.
}
+
+ /**
+ * Default implementation for
+ * {@link de.lmu.ifi.dbs.elki.database.datastore.DataStoreListener#contentChanged}
+ *
+ * Not enabled or used by default, but saves redundant code.
+ *
+ * @param e Data store event
+ */
+ public void contentChanged(DataStoreEvent e) {
+ synchronizedRedraw();
+ }
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/StaticVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/StaticVisualization.java
index cfc653ef..3a4be45b 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/StaticVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/StaticVisualization.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) 2011
+ Copyright (C) 2012
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 b89d1ae0..eb675951 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) 2011
+ Copyright (C) 2012
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 d2dfb687..d2d1e5fe 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) 2011
+ Copyright (C) 2012
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 14984a5d..a3b0e3f4 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) 2011
+ Copyright (C) 2012
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.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;
@@ -53,9 +54,10 @@ public final class VisualizerUtil {
*/
public static VisualizerContext getContext(HierarchicalResult baseResult) {
IterableIterator<VisualizerContext> iter = ResultUtil.filteredResults(baseResult, VisualizerContext.class);
- if (iter.hasNext()) {
+ if(iter.hasNext()) {
return iter.next();
- } else {
+ }
+ else {
return null;
}
}
@@ -79,6 +81,44 @@ public final class VisualizerUtil {
}
/**
+ * 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
+ * @param task Visualization task
+ * @param visibility Visibility value
+ */
+ public static void setVisible(VisualizerContext context, VisualizationTask task, boolean visibility) {
+ // Hide other tools
+ if(visibility && VisualizerUtil.isTool(task)) {
+ final Iterable<VisualizationTask> visualizers = ResultUtil.filteredResults(context.getResult(), VisualizationTask.class);
+ for(VisualizationTask other : visualizers) {
+ if(other != task && VisualizerUtil.isTool(other) && VisualizerUtil.isVisible(other)) {
+ other.put(VisualizationTask.META_VISIBLE, false);
+ context.getHierarchy().resultChanged(other);
+ }
+ }
+ }
+ task.put(VisualizationTask.META_VISIBLE, visibility);
+ context.getHierarchy().resultChanged(task);
+ }
+
+ /**
* Utility function to test for a visualizer being a "tool".
*
* @param vis Visualizer to test
@@ -91,34 +131,68 @@ public final class VisualizerUtil {
}
/**
+ * Utility function to test for a visualizer having options.
+ *
+ * @param vis Visualizer to test
+ * @return true when it has options
+ */
+ public static boolean hasOptions(VisualizationTask vis) {
+ // Currently enabled?
+ Boolean hasoptions = vis.getGenerics(VisualizationTask.META_HAS_OPTIONS, Boolean.class);
+ return (hasoptions != null) && hasoptions;
+ }
+
+ /**
* 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) {
- final Iterator<Relation<?>> parent = ResultUtil.filteredResults(result, Relation.class);
- return new AbstractFilteredIterator<Relation<?>, Relation<? extends NumberVector<?, ?>>>() {
- @Override
- protected Iterator<Relation<?>> getParentIterator() {
- return parent;
- }
+ public static IterableIterator<Relation<? extends NumberVector<?, ?>>> iterateVectorFieldRepresentations(final Result result) {
+ Iterator<Relation<?>> parent = ResultUtil.filteredResults(result, Relation.class);
+ return new VectorspaceIterator(parent);
+ }
+
+ /**
+ * Iterate over vectorspace
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ private static class VectorspaceIterator extends AbstractFilteredIterator<Relation<?>, Relation<? extends NumberVector<?, ?>>> implements IterableIterator<Relation<? extends NumberVector<?, ?>>> {
+ /** Parent iterator */
+ private Iterator<Relation<?>> 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;
+ 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;
+ }
+
+ @Override
+ public Iterator<Relation<? extends NumberVector<?, ?>>> iterator() {
+ return this;
+ }
+ };
/**
* Test whether a thumbnail is enabled for this visualizer.
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/events/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/events/package-info.java
deleted file mode 100644
index 6c10d496..00000000
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/events/package-info.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- * <p>Events occuring in visualization contexts</p>
- */
-/*
-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/>.
-*/
-package de.lmu.ifi.dbs.elki.visualization.visualizers.events; \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis1d/P1DVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/histogram/AbstractHistogramVisualization.java
index 721d3432..95df9533 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis1d/P1DVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/histogram/AbstractHistogramVisualization.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.visualization.visualizers.vis1d;
+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) 2011
+ Copyright (C) 2012
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.visualization.visualizers.vis1d;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+import de.lmu.ifi.dbs.elki.result.Result;
import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
import de.lmu.ifi.dbs.elki.visualization.projections.Projection1D;
import de.lmu.ifi.dbs.elki.visualization.visualizers.AbstractVisualization;
@@ -35,7 +36,7 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.AbstractVisualization;
* @apiviz.landmark
* @apiviz.has Projection1D
*/
-public abstract class P1DVisualization extends AbstractVisualization {
+public abstract class AbstractHistogramVisualization extends AbstractVisualization {
/**
* The current projection
*/
@@ -46,8 +47,16 @@ public abstract class P1DVisualization extends AbstractVisualization {
*
* @param task Visualization task
*/
- public P1DVisualization(VisualizationTask task) {
+ public AbstractHistogramVisualization(VisualizationTask task) {
super(task);
this.proj = task.getProj();
}
+
+ @Override
+ public void resultChanged(Result current) {
+ super.resultChanged(current);
+ if(current == proj) {
+ synchronizedRedraw();
+ }
+ }
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis1d/P1DHistogramVisualizer.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/histogram/ColoredHistogramVisualizer.java
index 7aee8108..d518d0cf 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis1d/P1DHistogramVisualizer.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/histogram/ColoredHistogramVisualizer.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.visualization.visualizers.vis1d;
+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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,50 +23,49 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.vis1d;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.ArrayList;
import java.util.Iterator;
-import java.util.List;
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.NumberVector;
-import de.lmu.ifi.dbs.elki.data.model.Model;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
-import de.lmu.ifi.dbs.elki.math.AggregatingHistogram;
import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
+import de.lmu.ifi.dbs.elki.math.histograms.AggregatingHistogram;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
+import de.lmu.ifi.dbs.elki.math.scales.LinearScale;
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.DatabaseUtil;
import de.lmu.ifi.dbs.elki.utilities.exceptions.ObjectNotFoundException;
-import de.lmu.ifi.dbs.elki.utilities.iterator.IterableUtil;
+import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
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.Flag;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
-import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
+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.css.CSSClassManager.CSSNamingConflict;
import de.lmu.ifi.dbs.elki.visualization.projections.Projection;
import de.lmu.ifi.dbs.elki.visualization.projector.HistogramProjector;
-import de.lmu.ifi.dbs.elki.visualization.scales.LinearScale;
+import de.lmu.ifi.dbs.elki.visualization.style.ClassStylingPolicy;
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.SVGSimpleLinearAxis;
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.thumbs.ThumbnailVisualization;
/**
* Generates a SVG-Element containing a histogram representing the distribution
@@ -80,16 +79,11 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.Visualization;
*/
// FIXME: make non-static, react to database changes!
// FIXME: cache histogram instead of recomputing it.
-public class P1DHistogramVisualizer<NV extends NumberVector<NV, ?>> extends P1DVisualization {
+public class ColoredHistogramVisualizer<NV extends NumberVector<NV, ?>> extends AbstractHistogramVisualization {
/**
* Name for this visualizer.
*/
- private static final String NAME = "Histogram";
-
- /**
- * Name for this visualizer.
- */
- private static final String CNAME = "Cluster Histograms";
+ private static final String CNAME = "Histograms";
/**
* Generic tag to indicate the type of element. Used in IDs, CSS-Classes etc.
@@ -112,9 +106,9 @@ public class P1DHistogramVisualizer<NV extends NumberVector<NV, ?>> extends P1DV
private Relation<NV> relation;
/**
- * The clustering we visualize
+ * The style policy
*/
- private Clustering<Model> clustering;
+ private StyleResult style;
/**
* Constructor.
@@ -123,12 +117,19 @@ public class P1DHistogramVisualizer<NV extends NumberVector<NV, ?>> extends P1DV
* @param curves Curves flag
* @param bins Number of bins
*/
- public P1DHistogramVisualizer(VisualizationTask task, boolean curves, int bins) {
+ public ColoredHistogramVisualizer(VisualizationTask task, boolean curves, int bins) {
super(task);
this.curves = curves;
this.bins = bins;
this.relation = task.getRelation();
- this.clustering = task.getResult();
+ this.style = task.getResult();
+ context.addResultListener(this);
+ }
+
+ @Override
+ public void destroy() {
+ context.removeResultListener(this);
+ super.destroy();
}
@Override
@@ -141,14 +142,23 @@ public class P1DHistogramVisualizer<NV extends NumberVector<NV, ?>> extends P1DV
final String transform = SVGUtil.makeMarginTransform(task.getWidth(), task.getHeight(), xsize, ysize, margin);
SVGUtil.setAtt(layer, SVGConstants.SVG_TRANSFORM_ATTRIBUTE, transform);
- final List<Cluster<Model>> allClusters = clustering != null ? clustering.getAllClusters() : null;
- final int numc = allClusters != null ? allClusters.size() : 0;
-
- setupCSS(svgp, numc);
+ // Styling policy
+ final StylingPolicy spol = style.getStylingPolicy();
+ final ClassStylingPolicy cspol;
+ if(spol instanceof ClassStylingPolicy) {
+ cspol = (ClassStylingPolicy) spol;
+ }
+ else {
+ cspol = null;
+ }
+ // TODO also use min style?
+ setupCSS(svgp, (cspol != null) ? cspol.getMaxStyle() : 0);
- // Creating histograms
+ // Create histograms
+ final int off = (cspol != null) ? cspol.getMinStyle() : 0;
+ final int numc = (cspol != null) ? (cspol.getMaxStyle() - cspol.getMinStyle()) : 0;
DoubleMinMax minmax = new DoubleMinMax();
- final double frac = 1. / relation.size();
+ final double frac = 1. / relation.size(); // TODO: sampling?
final int cols = numc + 1;
AggregatingHistogram<double[], double[]> histogram = new AggregatingHistogram<double[], double[]>(bins, -.5, .5, new AggregatingHistogram.Adapter<double[], double[]>() {
@Override
@@ -165,12 +175,13 @@ public class P1DHistogramVisualizer<NV extends NumberVector<NV, ?>> extends P1DV
}
});
- if(allClusters != null) {
- int clusterID = 0;
- for(Cluster<Model> cluster : allClusters) {
+ if(cspol != null) {
+ for(int snum = 0; snum < numc; snum++) {
double[] inc = new double[cols];
- inc[clusterID + 1] = frac;
- for(DBID id : cluster.getIDs()) {
+ inc[0] = frac;
+ inc[snum + 1] = frac;
+ for(Iterator<DBID> iter = cspol.iterateClass(snum + off); iter.hasNext();) {
+ DBID id = iter.next();
try {
double pos = proj.fastProjectDataToRenderSpace(relation.get(id)) / Projection.SCALE;
histogram.aggregate(pos, inc);
@@ -179,18 +190,19 @@ public class P1DHistogramVisualizer<NV extends NumberVector<NV, ?>> extends P1DV
// Ignore. The object was probably deleted from the database
}
}
- clusterID += 1;
}
}
- // Actual data distribution.
- double[] inc = new double[cols];
- inc[0] = frac;
- for(DBID id : relation.iterDBIDs()) {
- double pos = proj.fastProjectDataToRenderSpace(relation.get(id)) / Projection.SCALE;
- histogram.aggregate(pos, inc);
+ else {
+ // Actual data distribution.
+ double[] inc = new double[cols];
+ inc[0] = frac;
+ for(DBID id : relation.iterDBIDs()) {
+ double pos = proj.fastProjectDataToRenderSpace(relation.get(id)) / Projection.SCALE;
+ histogram.aggregate(pos, inc);
+ }
}
// for scaling, get the maximum occurring value in the bins:
- for(Pair<Double, double[]> bin : histogram) {
+ for(DoubleObjPair<double[]> bin : histogram) {
for(double val : bin.second) {
minmax.put(val);
}
@@ -199,9 +211,9 @@ public class P1DHistogramVisualizer<NV extends NumberVector<NV, ?>> extends P1DV
LinearScale yscale = new LinearScale(0, minmax.getMax());
LinearScale xscale = new LinearScale(histogram.getCoverMinimum(), histogram.getCoverMaximum());
- // Axis. TODO: Use AxisVisualizer for this?
+ // Axis. TODO: Add an AxisVisualizer for this?
try {
- SVGSimpleLinearAxis.drawAxis(svgp, layer, yscale, 0, ysize, 0, 0, true, false, context.getStyleLibrary());
+ SVGSimpleLinearAxis.drawAxis(svgp, layer, yscale, 0, ysize, 0, 0, SVGSimpleLinearAxis.LabelStyle.LEFTHAND, context.getStyleLibrary());
// draw axes that are non-trivial
final int dimensionality = DatabaseUtil.dimensionality(relation);
@@ -214,7 +226,7 @@ public class P1DHistogramVisualizer<NV extends NumberVector<NV, ?>> extends P1DV
if(ax != orig) {
final double left = (orig / Projection.SCALE + 0.5) * xsize;
final double right = (ax / Projection.SCALE + 0.5) * xsize;
- SVGSimpleLinearAxis.drawAxis(svgp, layer, proj.getScale(d), left, ysize, right, ysize, true, true, context.getStyleLibrary());
+ SVGSimpleLinearAxis.drawAxis(svgp, layer, proj.getScale(d), left, ysize, right, ysize, SVGSimpleLinearAxis.LabelStyle.RIGHTHAND, context.getStyleLibrary());
}
}
}
@@ -225,16 +237,16 @@ public class P1DHistogramVisualizer<NV extends NumberVector<NV, ?>> extends P1DV
double binwidth = histogram.getBinsize();
// Visualizing
if(!curves) {
- for(Pair<Double, double[]> bin : histogram) {
- double lpos = xscale.getScaled(bin.getFirst() - binwidth / 2);
- double rpos = xscale.getScaled(bin.getFirst() + binwidth / 2);
+ for(DoubleObjPair<double[]> bin : histogram) {
+ double lpos = xscale.getScaled(bin.first - binwidth / 2);
+ double rpos = xscale.getScaled(bin.first + binwidth / 2);
double stack = 0.0;
final int start = numc > 0 ? 1 : 0;
for(int key = start; key < cols; key++) {
double val = yscale.getScaled(bin.getSecond()[key]);
Element row = SVGUtil.svgRect(svgp.getDocument(), xsize * lpos, ysize * (1 - (val + stack)), xsize * (rpos - lpos), ysize * val);
stack = stack + val;
- SVGUtil.addCSSClass(row, BIN + (key - 1));
+ SVGUtil.addCSSClass(row, BIN + (off + key - 1));
layer.appendChild(row);
}
}
@@ -251,9 +263,9 @@ public class P1DHistogramVisualizer<NV extends NumberVector<NV, ?>> extends P1DV
}
// draw histogram lines
- for(Pair<Double, double[]> bin : histogram) {
- left = xscale.getScaled(bin.getFirst() - binwidth / 2);
- right = xscale.getScaled(bin.getFirst() + binwidth / 2);
+ for(DoubleObjPair<double[]> bin : histogram) {
+ left = xscale.getScaled(bin.first - binwidth / 2);
+ right = xscale.getScaled(bin.first + binwidth / 2);
for(int i = 0; i < cols; i++) {
double val = yscale.getScaled(bin.getSecond()[i]);
if(lasty[i] != val) {
@@ -271,7 +283,7 @@ public class P1DHistogramVisualizer<NV extends NumberVector<NV, ?>> extends P1DV
}
paths[i].lineTo(xsize * right, ysize * 1);
Element elem = paths[i].makeElement(svgp);
- SVGUtil.addCSSClass(elem, BIN + (i - 1));
+ SVGUtil.addCSSClass(elem, BIN + (off + i - 1));
layer.appendChild(elem);
}
}
@@ -368,20 +380,21 @@ public class P1DHistogramVisualizer<NV extends NumberVector<NV, ?>> extends P1DV
super();
this.curves = curves;
this.bins = bins;
+ thumbmask |= ThumbnailVisualization.ON_DATA | ThumbnailVisualization.ON_STYLE;
}
@Override
public Visualization makeVisualization(VisualizationTask task) {
- return new P1DHistogramVisualizer<NV>(task, curves, bins);
+ return new ColoredHistogramVisualizer<NV>(task, curves, bins);
}
@Override
public void processNewResult(HierarchicalResult baseResult, Result result) {
- // Cluster histograms
- ArrayList<Clustering<?>> clusterings = ResultUtil.filterResults(result, Clustering.class);
- for(Clustering<?> c : clusterings) {
- Iterator<HistogramProjector<?>> ps = ResultUtil.filteredResults(baseResult, HistogramProjector.class);
- for(HistogramProjector<?> p : IterableUtil.fromIterator(ps)) {
+ // Find a style result to visualize:
+ IterableIterator<StyleResult> styleres = ResultUtil.filteredResults(result, StyleResult.class);
+ for(StyleResult c : styleres) {
+ IterableIterator<HistogramProjector<?>> ps = ResultUtil.filteredResults(baseResult, HistogramProjector.class);
+ for(HistogramProjector<?> p : ps) {
// register self
final VisualizationTask task = new VisualizationTask(CNAME, c, p.getRelation(), this);
task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_DATA);
@@ -389,20 +402,6 @@ public class P1DHistogramVisualizer<NV extends NumberVector<NV, ?>> extends P1DV
baseResult.getHierarchy().add(p, task);
}
}
- // General data distribution
- {
- Iterator<HistogramProjector<?>> ps = ResultUtil.filteredResults(result, HistogramProjector.class);
- for(HistogramProjector<?> p : IterableUtil.fromIterator(ps)) {
- // register self
- final VisualizationTask task = new VisualizationTask(NAME, null, p.getRelation(), this);
- task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_DATA);
- if(clusterings.size() > 0) {
- task.put(VisualizationTask.META_VISIBLE_DEFAULT, false);
- }
- // baseResult.getHierarchy().add(p.getRelation(), task);
- baseResult.getHierarchy().add(p, task);
- }
- }
}
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/evaluation/paircounting/generator/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/histogram/package-info.java
index e78ebde2..4489904f 100644
--- a/src/de/lmu/ifi/dbs/elki/evaluation/paircounting/generator/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/histogram/package-info.java
@@ -1,11 +1,12 @@
/**
- * <p>Pair generation for pair counting evaluation.</p>
+ * <p>Visualizers based on 1D projected histograms.</p>
+ *
*/
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2011
+Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,4 +24,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.evaluation.paircounting.generator; \ No newline at end of file
+package de.lmu.ifi.dbs.elki.visualization.visualizers.histogram; \ No newline at end of file
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 bcf25a84..a04a4f7f 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) 2011
+ Copyright (C) 2012
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/OPTICSClusterVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSClusterVisualization.java
index 542dcea7..f69bdc59 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) 2011
+ Copyright (C) 2012
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.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.iterator.IterableUtil;
+import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
import de.lmu.ifi.dbs.elki.visualization.css.CSSClass;
import de.lmu.ifi.dbs.elki.visualization.projector.OPTICSProjector;
@@ -190,12 +190,12 @@ public class OPTICSClusterVisualization<D extends Distance<D>> extends AbstractO
@Override
public void processNewResult(HierarchicalResult baseResult, Result result) {
- Iterator<OPTICSProjector<?>> ops = ResultUtil.filteredResults(result, OPTICSProjector.class);
- for(OPTICSProjector<?> p : IterableUtil.fromIterator(ops)) {
+ IterableIterator<OPTICSProjector<?>> ops = ResultUtil.filteredResults(result, OPTICSProjector.class);
+ for(OPTICSProjector<?> p : ops) {
final Clustering<OPTICSModel> ocl = findOPTICSClustering(baseResult);
if(ocl != null) {
final VisualizationTask task = new VisualizationTask(NAME, p, null, this);
- task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_INTERACTIVE);
+ task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_DATA);
task.put(CLUSTERING, ocl);
baseResult.getHierarchy().add(p, task);
}
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 08ca7504..58cd9af3 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
@@ -23,8 +23,6 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.optics;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.Iterator;
-
import org.apache.batik.util.SVG12Constants;
import org.apache.batik.util.SVGConstants;
import org.w3c.dom.Element;
@@ -40,7 +38,7 @@ import de.lmu.ifi.dbs.elki.result.Result;
import de.lmu.ifi.dbs.elki.result.ResultUtil;
import de.lmu.ifi.dbs.elki.result.optics.ClusterOrderResult;
import de.lmu.ifi.dbs.elki.utilities.FormatUtil;
-import de.lmu.ifi.dbs.elki.utilities.iterator.IterableUtil;
+import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
import de.lmu.ifi.dbs.elki.visualization.batikutil.DragableArea;
import de.lmu.ifi.dbs.elki.visualization.css.CSSClass;
@@ -229,7 +227,7 @@ public class OPTICSPlotCutVisualization<D extends Distance<D>> extends AbstractO
Clustering<Model> cl = OPTICSCut.makeOPTICSCut(order, optics.getOPTICSPlot(context).getDistanceAdapter(), epsilon);
order.addChildResult(cl);
}
- context.resultChanged(this.task);
+ context.getHierarchy().resultChanged(this.task);
// synchronizedRedraw();
return true;
}
@@ -277,8 +275,8 @@ public class OPTICSPlotCutVisualization<D extends Distance<D>> extends AbstractO
@Override
public void processNewResult(HierarchicalResult baseResult, Result result) {
- Iterator<OPTICSProjector<?>> ops = ResultUtil.filteredResults(result, OPTICSProjector.class);
- for(OPTICSProjector<?> p : IterableUtil.fromIterator(ops)) {
+ IterableIterator<OPTICSProjector<?>> ops = ResultUtil.filteredResults(result, OPTICSProjector.class);
+ for(OPTICSProjector<?> p : ops) {
final VisualizationTask task = new VisualizationTask(NAME, p, null, this);
task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_INTERACTIVE);
baseResult.getHierarchy().add(p, task);
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSPlotSelectionVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSPlotSelectionVisualization.java
index 69bc781e..f8f30317 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSPlotSelectionVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/optics/OPTICSPlotSelectionVisualization.java
@@ -23,7 +23,6 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.optics;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.Iterator;
import java.util.List;
import org.apache.batik.dom.events.DOMMouseEvent;
@@ -45,7 +44,7 @@ import de.lmu.ifi.dbs.elki.result.Result;
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.utilities.iterator.IterableUtil;
+import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
import de.lmu.ifi.dbs.elki.visualization.batikutil.DragableArea;
import de.lmu.ifi.dbs.elki.visualization.css.CSSClass;
@@ -350,8 +349,8 @@ public class OPTICSPlotSelectionVisualization<D extends Distance<D>> extends Abs
@Override
public void processNewResult(HierarchicalResult baseResult, Result result) {
- Iterator<OPTICSProjector<?>> ops = ResultUtil.filteredResults(result, OPTICSProjector.class);
- for(OPTICSProjector<?> p : IterableUtil.fromIterator(ops)) {
+ IterableIterator<OPTICSProjector<?>> ops = ResultUtil.filteredResults(result, OPTICSProjector.class);
+ for(OPTICSProjector<?> p : ops) {
final VisualizationTask task = new VisualizationTask(NAME, p, null, this);
task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_INTERACTIVE);
baseResult.getHierarchy().add(p, task);
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 7f4e3248..da287252 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,10 +23,6 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.optics;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.io.File;
-import java.io.IOException;
-import java.util.Iterator;
-
import org.apache.batik.util.SVGConstants;
import org.w3c.dom.Element;
@@ -36,7 +32,7 @@ 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.IterableUtil;
+import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
import de.lmu.ifi.dbs.elki.visualization.css.CSSClassManager.CSSNamingConflict;
import de.lmu.ifi.dbs.elki.visualization.opticsplot.OPTICSPlot;
@@ -74,13 +70,7 @@ public class OPTICSPlotVisualizer<D extends Distance<D>> extends AbstractOPTICSV
// addCSSClasses();
OPTICSPlot<D> opticsplot = optics.getOPTICSPlot(context);
- File imgfile = null;
- try {
- imgfile = opticsplot.getAsTempFile();
- }
- catch(IOException e) {
- LoggingUtil.exception("Could not generate OPTICS plot.", e);
- }
+ String ploturi = opticsplot.getSVGPlotURI();
Element itag = svgp.svgElement(SVGConstants.SVG_IMAGE_TAG);
SVGUtil.setAtt(itag, SVGConstants.SVG_IMAGE_RENDERING_ATTRIBUTE, SVGConstants.SVG_OPTIMIZE_SPEED_VALUE);
@@ -88,13 +78,13 @@ public class OPTICSPlotVisualizer<D extends Distance<D>> extends AbstractOPTICSV
SVGUtil.setAtt(itag, SVGConstants.SVG_Y_ATTRIBUTE, 0);
SVGUtil.setAtt(itag, SVGConstants.SVG_WIDTH_ATTRIBUTE, plotwidth);
SVGUtil.setAtt(itag, SVGConstants.SVG_HEIGHT_ATTRIBUTE, plotheight);
- itag.setAttributeNS(SVGConstants.XLINK_NAMESPACE_URI, SVGConstants.XLINK_HREF_QNAME, imgfile.toURI().toString());
+ itag.setAttributeNS(SVGConstants.XLINK_NAMESPACE_URI, SVGConstants.XLINK_HREF_QNAME, ploturi);
layer.appendChild(itag);
try {
- SVGSimpleLinearAxis.drawAxis(svgp, layer, opticsplot.getScale(), 0, plotheight, 0, 0, true, false, context.getStyleLibrary());
- SVGSimpleLinearAxis.drawAxis(svgp, layer, opticsplot.getScale(), plotwidth, plotheight, plotwidth, 0, true, true, context.getStyleLibrary());
+ SVGSimpleLinearAxis.drawAxis(svgp, layer, opticsplot.getScale(), 0, plotheight, 0, 0, SVGSimpleLinearAxis.LabelStyle.LEFTHAND, context.getStyleLibrary());
+ SVGSimpleLinearAxis.drawAxis(svgp, layer, opticsplot.getScale(), plotwidth, plotheight, plotwidth, 0, SVGSimpleLinearAxis.LabelStyle.RIGHTHAND, context.getStyleLibrary());
}
catch(CSSNamingConflict e) {
LoggingUtil.exception("CSS naming conflict for axes on OPTICS plot", e);
@@ -120,11 +110,11 @@ public class OPTICSPlotVisualizer<D extends Distance<D>> extends AbstractOPTICSV
@Override
public void processNewResult(HierarchicalResult baseResult, Result result) {
- Iterator<OPTICSProjector<?>> ops = ResultUtil.filteredResults(result, OPTICSProjector.class);
- for(OPTICSProjector<?> p : IterableUtil.fromIterator(ops)) {
+ IterableIterator<OPTICSProjector<?>> ops = ResultUtil.filteredResults(result, OPTICSProjector.class);
+ for(OPTICSProjector<?> p : ops) {
// Add plots, attach visualizer
final VisualizationTask task = new VisualizationTask(NAME, p, null, this);
- task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_STATIC);
+ task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_DATA);
baseResult.getHierarchy().add(p, task);
}
}
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 b082836f..95b3d53b 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) 2011
+ Copyright (C) 2012
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.optics;
*/
import java.awt.Color;
-import java.util.Iterator;
import java.util.List;
import org.apache.batik.util.SVGConstants;
@@ -34,19 +33,19 @@ import de.lmu.ifi.dbs.elki.algorithm.clustering.OPTICSXi;
import de.lmu.ifi.dbs.elki.algorithm.clustering.OPTICSXi.SteepAreaResult;
import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
+import de.lmu.ifi.dbs.elki.math.scales.LinearScale;
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.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.iterator.IterableUtil;
+import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
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;
import de.lmu.ifi.dbs.elki.visualization.opticsplot.OPTICSPlot;
import de.lmu.ifi.dbs.elki.visualization.projector.OPTICSProjector;
-import de.lmu.ifi.dbs.elki.visualization.scales.LinearScale;
import de.lmu.ifi.dbs.elki.visualization.style.StyleLibrary;
import de.lmu.ifi.dbs.elki.visualization.svg.SVGUtil;
import de.lmu.ifi.dbs.elki.visualization.visualizers.AbstractVisFactory;
@@ -196,12 +195,12 @@ public class OPTICSSteepAreaVisualization<D extends Distance<D>> extends Abstrac
@Override
public void processNewResult(HierarchicalResult baseResult, Result result) {
- Iterator<OPTICSProjector<?>> ops = ResultUtil.filteredResults(result, OPTICSProjector.class);
- for(OPTICSProjector<?> p : IterableUtil.fromIterator(ops)) {
+ IterableIterator<OPTICSProjector<?>> ops = ResultUtil.filteredResults(result, OPTICSProjector.class);
+ for(OPTICSProjector<?> p : ops) {
final SteepAreaResult steep = findSteepAreaResult(p.getResult());
if(steep != null) {
final VisualizationTask task = new VisualizationTask(NAME, p, null, this);
- task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_INTERACTIVE);
+ task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_DATA + 1);
task.put(VisualizationTask.META_VISIBLE_DEFAULT, false);
baseResult.getHierarchy().add(p, task);
baseResult.getHierarchy().add(steep, task);
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 05b02142..642f817c 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) 2011
+Copyright (C) 2012
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 985988c6..208d8cb7 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
@@ -8,7 +8,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2011
+Copyright (C) 2012
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
new file mode 100644
index 00000000..360197ab
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/pairsegments/CircleSegmentsVisualizer.java
@@ -0,0 +1,708 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.Color;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+import org.apache.batik.util.SVGConstants;
+import org.w3c.dom.Element;
+import org.w3c.dom.events.Event;
+import org.w3c.dom.events.EventListener;
+import org.w3c.dom.events.EventTarget;
+import org.w3c.dom.events.MouseEvent;
+
+import de.lmu.ifi.dbs.elki.evaluation.clustering.pairsegments.Segment;
+import de.lmu.ifi.dbs.elki.evaluation.clustering.pairsegments.Segments;
+import de.lmu.ifi.dbs.elki.logging.Logging;
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
+import de.lmu.ifi.dbs.elki.result.Result;
+import de.lmu.ifi.dbs.elki.result.ResultListener;
+import de.lmu.ifi.dbs.elki.result.ResultUtil;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException;
+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.StyleLibrary;
+import de.lmu.ifi.dbs.elki.visualization.svg.SVGCheckbox;
+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.AbstractVisualization;
+import de.lmu.ifi.dbs.elki.visualization.visualizers.Visualization;
+
+/**
+ * Visualizer to draw circle segments of clusterings and enable interactive
+ * selection of segments. For "empty" segments, all related segments are
+ * selected instead, to visualize the differences.
+ *
+ * <p>
+ * Reference:<br />
+ * Evaluation of Clusterings – Metrics and Visual Support<br />
+ * Elke Achtert, Sascha Goldhofer, Hans-Peter Kriegel, Erich Schubert, Arthur
+ * Zimek<br />
+ * In: Proc. 28th International Conference on Data Engineering (ICDE) 2012
+ * </p>
+ *
+ * @author Sascha Goldhofer
+ * @author Erich Schubert
+ */
+@Reference(title = "Evaluation of Clusterings – Metrics and Visual Support", authors = "Elke Achtert, Sascha Goldhofer, Hans-Peter Kriegel, Erich Schubert, Arthur Zimek", booktitle = "Proc. 28th International Conference on Data Engineering (ICDE) 2012", url = "http://elki.dbs.ifi.lmu.de/wiki/PairSegments")
+public class CircleSegmentsVisualizer extends AbstractVisualization implements ResultListener {
+ /**
+ * Class logger
+ */
+ private static final Logging logger = Logging.getLogger(CircleSegmentsVisualizer.class);
+
+ /**
+ * CircleSegments visualizer name
+ */
+ private static final String NAME = "CircleSegments";
+
+ /** Minimum width (radian) of Segment */
+ private final static double SEGMENT_MIN_ANGLE = 0.01;
+
+ /** Gap (radian) between segments */
+ private final static double SEGMENT_MIN_SEP_ANGLE = 0.005;
+
+ /** Offset from center to first ring */
+ private final static double RADIUS_INNER = 0.04 * StyleLibrary.SCALE;
+
+ /** Margin between two rings */
+ private final static double RADIUS_DISTANCE = 0.01 * StyleLibrary.SCALE;
+
+ /** Radius of whole CircleSegments except selection border */
+ private final static double RADIUS_OUTER = 0.47 * StyleLibrary.SCALE;
+
+ /** Radius of highlight selection (outer ring) */
+ private final static double RADIUS_SELECTION = 0.02 * StyleLibrary.SCALE;
+
+ /**
+ * CSS class name for the clusterings.
+ */
+ private static final String CLR_CLUSTER_CLASS_PREFIX = "clusterSegment";
+
+ /**
+ * CSS border class of a cluster
+ */
+ public static final String CLR_BORDER_CLASS = "clusterBorder";
+
+ /**
+ * CSS hover class for clusters of hovered segment
+ */
+ public static final String CLR_UNPAIRED_CLASS = "clusterUnpaired";
+
+ /**
+ * CSS hover class of a segment cluster
+ */
+ public static final String CLR_HOVER_CLASS = "clusterHover";
+
+ /**
+ * CSS class of selected Segment
+ */
+ public static final String SEG_UNPAIRED_SELECTED_CLASS = "unpairedSegmentSelected";
+
+ /**
+ * Style prefix
+ */
+ public static final String STYLE = "segments";
+
+ /**
+ * Style for border lines
+ */
+ public static final String STYLE_BORDER = STYLE + ".border";
+
+ /**
+ * Style for hover effect
+ */
+ public static final String STYLE_HOVER = STYLE + ".hover";
+
+ /**
+ * First color for producing segment-cluster colors
+ */
+ public static final String STYLE_GRADIENT_FIRST = STYLE + ".cluster.first";
+
+ /**
+ * Second color for producing segment-cluster colors
+ */
+ public static final String STYLE_GRADIENT_SECOND = STYLE + ".cluster.second";
+
+ /**
+ * Segmentation of Clusterings
+ */
+ protected final Segments segments;
+
+ /**
+ * The two main layers
+ */
+ private Element visLayer, ctrlLayer;
+
+ /**
+ * Map to connect segments to their visual elements
+ */
+ public Map<Segment, List<Element>> segmentToElements = new HashMap<Segment, List<Element>>();
+
+ /**
+ * Show unclustered Pairs in CircleSegments
+ */
+ boolean showUnclusteredPairs = false;
+
+ /**
+ * Styling policy
+ */
+ protected final SegmentsStylingPolicy policy;
+
+ /**
+ * Flag to disallow an incremental redraw
+ */
+ private boolean noIncrementalRedraw = true;
+
+ /**
+ * Constructor
+ */
+ public CircleSegmentsVisualizer(VisualizationTask task) {
+ super(task);
+ segments = task.getResult();
+ policy = new SegmentsStylingPolicy(segments, context.getStyleLibrary());
+ // Listen for result changes (Selection changed)
+ context.addResultListener(this);
+ }
+
+ public void toggleUnclusteredPairs(boolean show) {
+ noIncrementalRedraw = true;
+ showUnclusteredPairs = show;
+ synchronizedRedraw();
+ }
+
+ @Override
+ public void resultChanged(Result current) {
+ super.resultChanged(current);
+ // Redraw on style result changes.
+ if(current == context.getStyleResult()) {
+ // When switching to a different policy, unhighlight segments.
+ if(context.getStyleResult().getStylingPolicy() != policy) {
+ policy.deselectAllSegments();
+ }
+ synchronizedRedraw();
+ }
+ }
+
+ @Override
+ protected void incrementalRedraw() {
+ if(noIncrementalRedraw) {
+ super.incrementalRedraw();
+ }
+ else {
+ redrawSelection();
+ }
+ }
+
+ @Override
+ public void redraw() {
+ logger.debug("Full redraw");
+ noIncrementalRedraw = false; // Done that.
+
+ // initialize css (needs clusterSize!)
+ addCSSClasses(segments.getHighestClusterCount());
+
+ layer = svgp.svgElement(SVGConstants.SVG_G_TAG);
+ visLayer = svgp.svgElement(SVGConstants.SVG_G_TAG);
+ // Setup scaling for canvas: 0 to StyleLibrary.SCALE (usually 100 to avoid a
+ // Java drawing bug!)
+ String transform = SVGUtil.makeMarginTransform(task.width, task.height, StyleLibrary.SCALE, StyleLibrary.SCALE, 0) + " translate(" + (StyleLibrary.SCALE * .5) + " " + (StyleLibrary.SCALE * .5) + ")";
+ visLayer.setAttribute(SVGConstants.SVG_TRANSFORM_ATTRIBUTE, transform);
+ ctrlLayer = svgp.svgElement(SVGConstants.SVG_G_TAG);
+
+ // and create svg elements
+ drawSegments();
+
+ //
+ // Build Interface
+ //
+ SVGCheckbox checkbox = new SVGCheckbox(showUnclusteredPairs, "Show unclustered pairs");
+ checkbox.addCheckBoxListener(new ChangeListener() {
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ toggleUnclusteredPairs(((SVGCheckbox) e.getSource()).isChecked());
+ }
+ });
+
+ // Add ring:clustering info
+ Element clrInfo = drawClusteringInfo();
+ Element c = checkbox.renderCheckBox(svgp, 1, 5 + Double.parseDouble(clrInfo.getAttribute(SVGConstants.SVG_HEIGHT_ATTRIBUTE)), 11);
+ ctrlLayer.appendChild(clrInfo);
+ ctrlLayer.appendChild(c);
+
+ ctrlLayer.setAttribute(SVGConstants.SVG_TRANSFORM_ATTRIBUTE, "scale(" + (0.25 / StyleLibrary.SCALE) + ")");
+
+ layer.appendChild(visLayer);
+ layer.appendChild(ctrlLayer);
+ }
+
+ /**
+ * Define and add required CSS classes
+ */
+ protected void addCSSClasses(int maxClusterSize) {
+ StyleLibrary style = context.getStyleLibrary();
+
+ // Cluster separation lines
+ CSSClass cssReferenceBorder = new CSSClass(this.getClass(), CLR_BORDER_CLASS);
+ cssReferenceBorder.setStatement(SVGConstants.SVG_FILL_ATTRIBUTE, style.getColor(STYLE_BORDER));
+ svgp.addCSSClassOrLogError(cssReferenceBorder);
+
+ // Hover effect for clusters
+ CSSClass cluster_hover = new CSSClass(this.getClass(), CLR_HOVER_CLASS);
+ // Note: !important is needed to override the regular color assignment
+ cluster_hover.setStatement(SVGConstants.SVG_FILL_ATTRIBUTE, style.getColor(STYLE_HOVER) + " !important");
+ cluster_hover.setStatement(SVGConstants.SVG_CURSOR_TAG, SVGConstants.SVG_POINTER_VALUE);
+ svgp.addCSSClassOrLogError(cluster_hover);
+
+ // Unpaired cluster segment
+ CSSClass cluster_unpaired = new CSSClass(this.getClass(), CLR_UNPAIRED_CLASS);
+ cluster_unpaired.setStatement(SVGConstants.SVG_FILL_ATTRIBUTE, style.getBackgroundColor(STYLE));
+ cluster_unpaired.setStatement(SVGConstants.SVG_STROKE_ATTRIBUTE, SVGConstants.CSS_NONE_VALUE);
+ svgp.addCSSClassOrLogError(cluster_unpaired);
+
+ // Selected unpaired cluster segment
+ CSSClass cluster_unpaired_s = new CSSClass(this.getClass(), SEG_UNPAIRED_SELECTED_CLASS);
+ cluster_unpaired_s.setStatement(SVGConstants.SVG_FILL_ATTRIBUTE, style.getColor(STYLE_HOVER) + " !important");
+ svgp.addCSSClassOrLogError(cluster_unpaired_s);
+
+ // create Color shades for clusters
+ String firstcol = style.getColor(STYLE_GRADIENT_FIRST);
+ String secondcol = style.getColor(STYLE_GRADIENT_SECOND);
+ String[] clusterColorShades = makeGradient(maxClusterSize, new String[] { firstcol, secondcol });
+
+ for(int i = 0; i < maxClusterSize; i++) {
+ CSSClass clusterClasses = new CSSClass(CircleSegmentsVisualizer.class, CLR_CLUSTER_CLASS_PREFIX + "_" + i);
+ clusterClasses.setStatement(SVGConstants.SVG_FILL_ATTRIBUTE, clusterColorShades[i]);
+ clusterClasses.setStatement(SVGConstants.SVG_STROKE_ATTRIBUTE, SVGConstants.SVG_NONE_VALUE);
+ svgp.addCSSClassOrLogError(clusterClasses);
+ }
+ }
+
+ /**
+ * Create the segments
+ */
+ private void drawSegments() {
+ final int clusterings = segments.getClusterings();
+
+ // Reinitialize
+ this.segmentToElements.clear();
+
+ double angle_pair = (MathUtil.TWOPI - (SEGMENT_MIN_SEP_ANGLE * segments.size())) / segments.getPairCount(showUnclusteredPairs);
+ final int pair_min_count = (int) Math.ceil(SEGMENT_MIN_ANGLE / angle_pair);
+
+ // number of segments needed to be resized
+ int cluster_min_count = 0;
+ for(Segment segment : segments) {
+ if(segment.getPairCount() <= pair_min_count) {
+ cluster_min_count++;
+ }
+ }
+
+ // update width of a pair
+ angle_pair = (MathUtil.TWOPI - (SEGMENT_MIN_SEP_ANGLE * segments.size() + cluster_min_count * SEGMENT_MIN_ANGLE)) / (segments.getPairCount(showUnclusteredPairs) - cluster_min_count);
+ double radius_delta = (RADIUS_OUTER - RADIUS_INNER - clusterings * RADIUS_DISTANCE) / clusterings;
+ double border_width = SEGMENT_MIN_SEP_ANGLE;
+
+ int refClustering = 0;
+ int refSegment = Segment.UNCLUSTERED;
+ double offsetAngle = 0.0;
+
+ for(final Segment segment : segments) {
+ long currentPairCount = segment.getPairCount();
+
+ // resize small segments if below minimum
+ double alpha = SEGMENT_MIN_ANGLE;
+ if(currentPairCount > pair_min_count) {
+ alpha = angle_pair * currentPairCount;
+ }
+
+ // ITERATE OVER ALL SEGMENT-CLUSTERS
+
+ ArrayList<Element> elems = new ArrayList<Element>(clusterings);
+ segmentToElements.put(segment, elems);
+ // draw segment for every clustering
+
+ for(int i = 0; i < clusterings; i++) {
+ double currentRadius = i * (radius_delta + RADIUS_DISTANCE) + RADIUS_INNER;
+
+ // Add border if the next segment is a different cluster in the
+ // reference clustering
+ if((refSegment != segment.get(refClustering)) && refClustering == i) {
+ Element border = SVGUtil.svgCircleSegment(svgp, 0, 0, offsetAngle - SEGMENT_MIN_SEP_ANGLE, border_width, currentRadius, RADIUS_OUTER - RADIUS_DISTANCE);
+ border.setAttribute(SVGConstants.SVG_CLASS_ATTRIBUTE, CLR_BORDER_CLASS);
+ visLayer.appendChild(border);
+
+ if(segment.get(refClustering) == Segment.UNCLUSTERED) {
+ refClustering = Math.min(refClustering + 1, clusterings - 1);
+ }
+ refSegment = segment.get(refClustering);
+ }
+
+ int cluster = segment.get(i);
+
+ // create ring segment
+ Element segelement = SVGUtil.svgCircleSegment(svgp, 0, 0, offsetAngle, alpha, currentRadius, currentRadius + radius_delta);
+ elems.add(segelement);
+
+ // MouseEvents on segment cluster
+ EventListener listener = new SegmentListenerProxy(segment, i);
+ EventTarget targ = (EventTarget) segelement;
+ targ.addEventListener(SVGConstants.SVG_MOUSEOVER_EVENT_TYPE, listener, false);
+ targ.addEventListener(SVGConstants.SVG_MOUSEOUT_EVENT_TYPE, listener, false);
+ targ.addEventListener(SVGConstants.SVG_CLICK_EVENT_TYPE, listener, false);
+
+ // Coloring based on clusterID
+ if(cluster >= 0) {
+ segelement.setAttribute(SVGConstants.SVG_CLASS_ATTRIBUTE, CLR_CLUSTER_CLASS_PREFIX + "_" + cluster);
+ }
+ // if its an unpaired cluster set color to white
+ else {
+ segelement.setAttribute(SVGConstants.SVG_CLASS_ATTRIBUTE, CLR_UNPAIRED_CLASS);
+ }
+
+ visLayer.appendChild(segelement);
+ }
+
+ //
+ // Add a extended strip for each segment to emphasis selection
+ // (easier to track thin segments and their color coding and
+ // differentiates them from cluster border lines)
+ //
+
+ double currentRadius = clusterings * (radius_delta + RADIUS_DISTANCE) + RADIUS_INNER;
+ Element extension = SVGUtil.svgCircleSegment(svgp, 0, 0, offsetAngle, alpha, currentRadius, currentRadius + RADIUS_SELECTION);
+ extension.setAttribute(SVGConstants.SVG_CLASS_ATTRIBUTE, CLR_UNPAIRED_CLASS);
+ elems.add(extension);
+
+ if(segment.isUnpaired()) {
+ if(policy.isSelected(segment)) {
+ SVGUtil.addCSSClass(extension, SEG_UNPAIRED_SELECTED_CLASS);
+ }
+ else {
+ // Remove highlight
+ SVGUtil.removeCSSClass(extension, SEG_UNPAIRED_SELECTED_CLASS);
+ }
+ }
+ else {
+ int idx = policy.indexOfSegment(segment);
+ if(idx >= 0) {
+ String color = context.getStyleLibrary().getColorSet(StyleLibrary.PLOT).getColor(idx);
+ extension.setAttribute(SVGConstants.SVG_STYLE_ATTRIBUTE, SVGConstants.CSS_FILL_PROPERTY + ":" + color);
+ }
+ else {
+ // Remove styling
+ extension.removeAttribute(SVGConstants.SVG_STYLE_ATTRIBUTE);
+ }
+ }
+
+ visLayer.appendChild(extension);
+
+ // calculate angle for next segment
+ offsetAngle += alpha + SEGMENT_MIN_SEP_ANGLE;
+ }
+ }
+
+ private void redrawSelection() {
+ logger.debug("Updating selection only.");
+ for(Entry<Segment, List<Element>> entry : segmentToElements.entrySet()) {
+ Segment segment = entry.getKey();
+ // The selection marker is the extra element in the list
+ Element extension = entry.getValue().get(segments.getClusterings());
+ if(segment.isUnpaired()) {
+ if(policy.isSelected(segment)) {
+ SVGUtil.addCSSClass(extension, SEG_UNPAIRED_SELECTED_CLASS);
+ }
+ else {
+ // Remove highlight
+ SVGUtil.removeCSSClass(extension, SEG_UNPAIRED_SELECTED_CLASS);
+ }
+ }
+ else {
+ int idx = policy.indexOfSegment(segment);
+ if(idx >= 0) {
+ String color = context.getStyleLibrary().getColorSet(StyleLibrary.PLOT).getColor(idx);
+ extension.setAttribute(SVGConstants.SVG_STYLE_ATTRIBUTE, SVGConstants.CSS_FILL_PROPERTY + ":" + color);
+ }
+ else {
+ // Remove styling
+ extension.removeAttribute(SVGConstants.SVG_STYLE_ATTRIBUTE);
+ }
+ }
+ }
+ }
+
+ /**
+ * Creates a gradient over a set of colors
+ *
+ * @param shades number of colors in the gradient
+ * @param colors colors for the gradient
+ * @return array of colors for CSS
+ */
+ protected static String[] makeGradient(int shades, String[] colors) {
+ if(shades <= colors.length) {
+ return colors;
+ }
+
+ // Convert SVG colors into AWT colors for math
+ Color[] cols = new Color[colors.length];
+ for(int i = 0; i < colors.length; i++) {
+ cols[i] = SVGUtil.stringToColor(colors[i]);
+ if(cols[i] == null) {
+ throw new AbortException("Error parsing color: " + colors[i]);
+ }
+ }
+
+ // Step size
+ double increment = (cols.length - 1.) / shades;
+
+ String[] colorShades = new String[shades];
+
+ for(int s = 0; s < shades; s++) {
+ final int ppos = Math.min((int) Math.floor(increment * s), cols.length);
+ final int npos = Math.min((int) Math.ceil(increment * s), cols.length);
+ if(ppos == npos) {
+ colorShades[s] = colors[ppos];
+ }
+ else {
+ Color prev = cols[ppos];
+ Color next = cols[npos];
+ final double mix = (increment * s - ppos) / (npos - ppos);
+ final int r = (int) ((1 - mix) * prev.getRed() + mix * next.getRed());
+ final int g = (int) ((1 - mix) * prev.getGreen() + mix * next.getGreen());
+ final int b = (int) ((1 - mix) * prev.getBlue() + mix * next.getBlue());
+ colorShades[s] = SVGUtil.colorToString(((r & 0xFF) << 16) | ((g & 0xFF) << 8) | (b & 0xFF));
+ }
+ }
+
+ return colorShades;
+ }
+
+ protected Element drawClusteringInfo() {
+ Element thumbnail = SVGUtil.svgElement(svgp.getDocument(), SVGConstants.SVG_G_TAG);
+
+ // build thumbnail
+ int startRadius = 4;
+ int singleHeight = 12;
+ int margin = 4;
+ int radius = segments.getClusterings() * (singleHeight + margin) + startRadius;
+
+ SVGUtil.setAtt(thumbnail, SVGConstants.SVG_HEIGHT_ATTRIBUTE, radius);
+
+ for(int i = 0; i < segments.getClusterings(); i++) {
+ double innerRadius = i * singleHeight + margin * i + startRadius;
+ Element clr = SVGUtil.svgCircleSegment(svgp, radius - startRadius, radius - startRadius, Math.PI * 1.5, Math.PI * 0.5, innerRadius, innerRadius + singleHeight);
+ // FIXME: Use StyleLibrary
+ clr.setAttribute(SVGConstants.SVG_FILL_ATTRIBUTE, "#d4e4f1");
+ clr.setAttribute(SVGConstants.SVG_STROKE_ATTRIBUTE, "#a0a0a0");
+ clr.setAttribute(SVGConstants.SVG_STROKE_WIDTH_ATTRIBUTE, "1.0");
+
+ String labelText = segments.getClusteringDescription(i);
+ Element label = svgp.svgText(radius + startRadius, radius - innerRadius - startRadius, labelText);
+ thumbnail.appendChild(label);
+
+ thumbnail.appendChild(clr);
+ }
+
+ return thumbnail;
+ }
+
+ protected void segmentHover(Segment segment, int ringid, boolean active) {
+ if(active) {
+ // abort if this are the unclustered pairs
+ if(segment.isNone()) {
+ return;
+ }
+ if(logger.isDebugging()) {
+ logger.debug("Hover on segment: " + segment + " unpaired: " + segment.isUnpaired());
+ }
+
+ if(!segment.isUnpaired()) {
+ //
+ // STANDARD CLUSTER SEGMENT
+ // highlight all ring segments in this clustering and this cluster
+ //
+ // highlight all corresponding ring Segments
+ for(Entry<Segment, List<Element>> entry : segmentToElements.entrySet()) {
+ Segment other = entry.getKey();
+ // Same cluster in same clustering?
+ if(other.get(ringid) != segment.get(ringid)) {
+ continue;
+ }
+ Element ringSegment = entry.getValue().get(ringid);
+ SVGUtil.addCSSClass(ringSegment, CLR_HOVER_CLASS);
+ }
+ }
+ else {
+ //
+ // UNPAIRED SEGMENT
+ // highlight all ring segments in this clustering responsible for
+ // unpaired
+ // segment
+ //
+ // get the paired segments corresponding to the unpaired segment
+ List<Segment> paired = segments.getPairedSegments(segment);
+
+ for(Segment other : paired) {
+ Element ringSegment = segmentToElements.get(other).get(ringid);
+ SVGUtil.addCSSClass(ringSegment, CLR_HOVER_CLASS);
+ }
+ }
+ }
+ else {
+ for(List<Element> elems : segmentToElements.values()) {
+ for(Element current : elems) {
+ SVGUtil.removeCSSClass(current, CLR_HOVER_CLASS);
+ }
+ }
+ }
+ }
+
+ protected void segmentClick(Segment segment, Event evt, boolean dblClick) {
+ MouseEvent mouse = (MouseEvent) evt;
+
+ // CTRL (add) pressed?
+ boolean ctrl = false;
+ if(mouse.getCtrlKey()) {
+ ctrl = true;
+ }
+
+ // Unselect others on double click
+ if(dblClick) {
+ policy.deselectAllSegments();
+ }
+ policy.select(segment, ctrl);
+ // update stylePolicy
+ context.getStyleResult().setStylingPolicy(policy);
+ // fire changed event to trigger redraw
+ context.getHierarchy().resultChanged(context.getStyleResult());
+ }
+
+ /**
+ * Proxy element to connect signals.
+ *
+ * @author Erich Schubert
+ */
+ private class SegmentListenerProxy implements EventListener {
+ /**
+ * Mouse double click time window in milliseconds
+ *
+ * TODO: does Batik have double click events?
+ */
+ public static final int EVT_DBLCLICK_DELAY = 350;
+
+ /**
+ * Segment we are attached to
+ */
+ private Segment id;
+
+ /**
+ * Segment ring we are
+ */
+ private int ringid;
+
+ /**
+ * For detecting double clicks.
+ */
+ private long lastClick = 0;
+
+ /**
+ * Constructor.
+ *
+ * @param id Segment id
+ * @param ringid Ring id
+ */
+ public SegmentListenerProxy(Segment id, int ringid) {
+ super();
+ this.id = id;
+ this.ringid = ringid;
+ }
+
+ @Override
+ public void handleEvent(Event evt) {
+ if(SVGConstants.SVG_MOUSEOVER_EVENT_TYPE.equals(evt.getType())) {
+ segmentHover(id, ringid, true);
+ }
+ if(SVGConstants.SVG_MOUSEOUT_EVENT_TYPE.equals(evt.getType())) {
+ segmentHover(id, ringid, false);
+ }
+ if(SVGConstants.SVG_CLICK_EVENT_TYPE.equals(evt.getType())) {
+ // Check Double Click
+ boolean dblClick = false;
+ long time = java.util.Calendar.getInstance().getTimeInMillis();
+ if(time - lastClick <= EVT_DBLCLICK_DELAY) {
+ dblClick = true;
+ }
+ lastClick = time;
+
+ segmentClick(id, evt, dblClick);
+ }
+ }
+ }
+
+ /**
+ * Factory for visualizers for a circle segment
+ *
+ * @author Sascha Goldhofer
+ *
+ * @apiviz.stereotype factory
+ * @apiviz.uses CircleSegmentsVisualizer oneway - - «create»
+ */
+ public static class Factory extends AbstractVisFactory {
+ /**
+ * Constructor
+ */
+ public Factory() {
+ super();
+ }
+
+ @Override
+ public Visualization makeVisualization(VisualizationTask task) {
+ return new CircleSegmentsVisualizer(task);
+ }
+
+ @Override
+ public void processNewResult(HierarchicalResult baseResult, Result result) {
+ // If no comparison result found abort
+ List<Segments> segments = ResultUtil.filterResults(result, Segments.class);
+ for(Segments segmentResult : segments) {
+ // create task for visualization
+ final VisualizationTask task = new VisualizationTask(NAME, segmentResult, null, this);
+ task.width = 2.0;
+ task.height = 2.0;
+ task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_INTERACTIVE);
+ baseResult.getHierarchy().add(segmentResult, task);
+ }
+ }
+ };
+} \ No newline at end of file
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
new file mode 100644
index 00000000..99ecf081
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/pairsegments/SegmentsStylingPolicy.java
@@ -0,0 +1,287 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.Iterator;
+import java.util.Map.Entry;
+import java.util.TreeMap;
+
+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.ModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.evaluation.clustering.pairsegments.Segment;
+import de.lmu.ifi.dbs.elki.evaluation.clustering.pairsegments.Segments;
+import de.lmu.ifi.dbs.elki.visualization.colors.ColorLibrary;
+import de.lmu.ifi.dbs.elki.visualization.style.ClassStylingPolicy;
+import de.lmu.ifi.dbs.elki.visualization.style.StyleLibrary;
+import de.lmu.ifi.dbs.elki.visualization.svg.SVGUtil;
+
+/**
+ * Styling policy to communicate the segment selection to other visualizers.
+ *
+ * @author Sascha Goldhofer
+ * @author Erich Schubert
+ */
+public class SegmentsStylingPolicy implements ClassStylingPolicy {
+ /**
+ * The segments we use for visualization
+ */
+ protected final Segments segments;
+
+ /**
+ * Selected segments
+ */
+ protected ArrayList<Segment> selectedSegments = new ArrayList<Segment>();
+
+ /**
+ * Segments indirectly selected
+ */
+ protected TreeMap<Segment, Segment> indirectSelections = new TreeMap<Segment, Segment>();
+
+ /**
+ * Not selected IDs that will be drawn in default colors.
+ */
+ protected ModifiableDBIDs unselectedObjects = DBIDUtil.newHashSet();
+
+ /**
+ * Color library (only used in compatibility mode)
+ */
+ // TODO: move to abstract super class?
+ ColorLibrary colorset;
+
+ /**
+ * Constructor.
+ *
+ * @param segments Segments
+ */
+ public SegmentsStylingPolicy(Segments segments, StyleLibrary style) {
+ super();
+ this.segments = segments;
+ this.colorset = style.getColorSet(StyleLibrary.PLOT);
+
+ // get all selectable segments
+ for(Segment segment : segments) {
+ // store segmentID
+ if(!segment.isUnpaired()) {
+ // and store their get all objects
+ if(segment.getDBIDs() != null) {
+ unselectedObjects.addDBIDs(segment.getDBIDs());
+ }
+ }
+ }
+ }
+
+ /**
+ * Test whether a segment is selected.
+ *
+ * @param segment Segment to test
+ * @return true when selected
+ */
+ public boolean isSelected(Segment segment) {
+ return selectedSegments.contains(segment) || indirectSelections.containsValue(segment);
+ }
+
+ @Override
+ public int getStyleForDBID(DBID id) {
+ Iterator<Segment> s = selectedSegments.iterator();
+ for(int i = 0; s.hasNext(); i++) {
+ Segment seg = s.next();
+ DBIDs ids = seg.getDBIDs();
+ if(ids != null && ids.contains(id)) {
+ return i;
+ }
+ }
+ return -2;
+ }
+
+ @Override
+ public int getColorForDBID(DBID id) {
+ int style = getStyleForDBID(id);
+ // FIXME: slow
+ return SVGUtil.stringToColor(colorset.getColor(style)).getRGB();
+ }
+
+ @Override
+ // -2=grau, -1=schwarz, 0+=farben
+ public int getMinStyle() {
+ return -2;
+ }
+
+ @Override
+ public int getMaxStyle() {
+ return selectedSegments.size();
+ }
+
+ @Override
+ public Iterator<DBID> iterateClass(int cnum) {
+ // unselected
+ if(cnum == -2) {
+ return unselectedObjects.iterator();
+ }
+ else if(cnum == -1) {
+ return DBIDUtil.EMPTYDBIDS.iterator();
+ }
+ // colors
+ DBIDs ids = selectedSegments.get(cnum).getDBIDs();
+ return (ids != null) ? ids.iterator() : DBIDUtil.EMPTYDBIDS.iterator();
+ }
+
+ /**
+ * Adds or removes the given segment to the selection. Depending on the
+ * clustering and cluster selected and the addToSelection option given, the
+ * current selection will be modified. This method is called by clicking on a
+ * segment and ring and the CTRL-button status.
+ *
+ * Adding selections does only work on the same clustering and cluster, else a
+ * new selection will be added.
+ *
+ * @param segment the selected element representing a segment ring (specific
+ * clustering)
+ * @param addToSelection flag for adding segment to current selection
+ */
+ public void select(Segment segment, boolean addToSelection) {
+ // abort if segment represents pairs inNone. Would select all segments...
+ if(segment.isNone()) {
+ return;
+ }
+ if(!addToSelection) {
+ deselectAllSegments();
+ }
+
+ // get selected segments
+ if(segment.isUnpaired()) {
+ // check if all segments are selected
+ if(addToSelection) {
+ boolean allSegmentsSelected = true;
+ for(Segment other : segments.getPairedSegments(segment)) {
+ if(!isSelected(other)) {
+ allSegmentsSelected = false;
+ break;
+ }
+ }
+
+ // if all are selected, deselect all
+ if(allSegmentsSelected) {
+ deselectSegment(segment);
+ return;
+ }
+ }
+ if(isSelected(segment)) {
+ deselectSegment(segment);
+ }
+ else {
+ selectSegment(segment);
+ }
+ }
+ else {
+ // an object segment was selected
+ if(isSelected(segment)) {
+ deselectSegment(segment);
+ }
+ else {
+ selectSegment(segment);
+ }
+ }
+ }
+
+ /**
+ * Deselect all currently selected segments
+ */
+ public void deselectAllSegments() {
+ while(selectedSegments.size() > 0) {
+ deselectSegment(selectedSegments.get(selectedSegments.size() - 1));
+ }
+ }
+
+ /**
+ * Deselect a segment
+ *
+ * @param segment Segment to deselect
+ */
+ protected void deselectSegment(Segment segment) {
+ if(segment.isUnpaired()) {
+ ArrayList<Segment> remove = new ArrayList<Segment>();
+ // remove all object segments associated with unpaired segment from
+ // selection list
+ for(Entry<Segment, Segment> entry : indirectSelections.entrySet()) {
+ if(entry.getValue() == segment) {
+ remove.add(entry.getKey());
+ }
+ }
+
+ for(Segment other : remove) {
+ indirectSelections.remove(other);
+ deselectSegment(other);
+ }
+ }
+ else {
+ // check if deselected object Segment has a unpaired segment highlighted
+ Segment unpaired = indirectSelections.get(segment);
+ if(unpaired != null) {
+ // remove highlight
+ deselectSegment(unpaired);
+ }
+ if(selectedSegments.remove(segment)) {
+ if(segment.getDBIDs() != null) {
+ unselectedObjects.addDBIDs(segment.getDBIDs());
+ }
+ }
+ }
+ }
+
+ /**
+ * Select a segment
+ *
+ * @param segment Segment to select
+ */
+ protected void selectSegment(Segment segment) {
+ if(segment.isUnpaired()) {
+ // remember selected unpaired segment
+ for(Segment other : segments.getPairedSegments(segment)) {
+ indirectSelections.put(other, segment);
+ selectSegment(other);
+ }
+ }
+ else {
+ if(!selectedSegments.contains(segment)) {
+ selectedSegments.add(segment);
+ if(segment.getDBIDs() != null) {
+ unselectedObjects.removeDBIDs(segment.getDBIDs());
+ }
+ }
+ }
+ }
+
+ /**
+ * Get the index of a selected segment.
+ *
+ * @param segment Segment to find
+ * @return Index, or -1
+ */
+ public int indexOfSegment(Segment segment) {
+ return selectedSegments.indexOf(segment);
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..c0c71dd3
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/pairsegments/package-info.java
@@ -0,0 +1,26 @@
+/**
+ * <p>Visualizers for inspecting cluster differences using pair counting segments.</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.visualization.visualizers.pairsegments; \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/AbstractParallelVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/AbstractParallelVisualization.java
new file mode 100644
index 00000000..babcb864
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/AbstractParallelVisualization.java
@@ -0,0 +1,163 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.apache.batik.util.SVGConstants;
+import org.w3c.dom.Element;
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.result.Result;
+import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
+import de.lmu.ifi.dbs.elki.visualization.projections.ProjectionParallel;
+import de.lmu.ifi.dbs.elki.visualization.style.StyleLibrary;
+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.AbstractVisualization;
+
+/**
+ * Abstract base class for parallel visualizations.
+ *
+ * @author Robert Rödler
+ * @author Erich Schubert
+ *
+ * @param <NV> Vector type in relation
+ */
+public abstract class AbstractParallelVisualization<NV extends NumberVector<?, ?>> extends AbstractVisualization {
+ /**
+ * The current projection
+ */
+ final protected ProjectionParallel proj;
+
+ /**
+ * The representation we visualize
+ */
+ final protected Relation<NV> relation;
+
+ /**
+ * margin
+ */
+ final double[] margins;
+
+ /**
+ * Space between two axes
+ */
+ protected double axsep;
+
+ /**
+ * viewbox size
+ */
+ final double[] size;
+
+ /**
+ * Constructor.
+ *
+ * @param task Visualization task
+ */
+ public AbstractParallelVisualization(VisualizationTask task) {
+ super(task);
+ this.proj = task.getProj();
+ this.relation = task.getRelation();
+
+ double ratio = task.width / task.height;
+
+ margins = new double[] { 0.05 * StyleLibrary.SCALE, 0.1 * StyleLibrary.SCALE, 0.05 * StyleLibrary.SCALE, 0.4 * StyleLibrary.SCALE };
+ size = new double[] { ratio * StyleLibrary.SCALE, StyleLibrary.SCALE };
+ recalcAxisPositions();
+
+ this.layer = setupCanvas(svgp, proj, task.getWidth(), task.getHeight());
+ }
+
+ /**
+ * Utility function to setup a canvas element for the visualization.
+ *
+ * @param svgp Plot element
+ * @param proj Projection to use
+ * @param width Width
+ * @param height Height
+ * @return wrapper element with appropriate view box.
+ */
+ public Element setupCanvas(SVGPlot svgp, ProjectionParallel proj, double width, double height) {
+ Element layer = SVGUtil.svgElement(svgp.getDocument(), SVGConstants.SVG_G_TAG);
+ final String transform = SVGUtil.makeMarginTransform(width, height, size[0], size[1], margins[0], margins[1], margins[2], margins[3]);
+ SVGUtil.setAtt(layer, SVGConstants.SVG_TRANSFORM_ATTRIBUTE, transform);
+ return layer;
+ }
+
+ /**
+ * Get width of main canvas.
+ *
+ * @return Width
+ */
+ protected double getSizeX() {
+ return size[0];
+ }
+
+ protected double getSizeY() {
+ return size[1];
+ }
+
+ protected double getMarginLeft() {
+ return margins[0];
+ }
+
+ protected double getMarginTop() {
+ return margins[1];
+ }
+
+ /**
+ * Distance between axes.
+ *
+ * @return Axis separation
+ */
+ protected double getAxisSep() {
+ return axsep;
+ }
+
+ /**
+ * Recalculate axis positions, in particular after projection changes.
+ */
+ private void recalcAxisPositions() {
+ axsep = size[0] / (proj.getVisibleDimensions() - 1.);
+ }
+
+ /**
+ * Get the position of visible axis d
+ *
+ * @param d Visible axis number
+ * @return Position
+ */
+ protected double getVisibleAxisX(double d) {
+ return d * axsep;
+ }
+
+ @Override
+ public void resultChanged(Result current) {
+ super.resultChanged(current);
+ if(current == proj) {
+ recalcAxisPositions();
+ synchronizedRedraw();
+ }
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/LineVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/LineVisualization.java
new file mode 100644
index 00000000..3a2c7c1d
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/LineVisualization.java
@@ -0,0 +1,218 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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 org.apache.batik.util.SVGConstants;
+import org.w3c.dom.Element;
+
+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.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.SamplingResult;
+import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
+import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
+import de.lmu.ifi.dbs.elki.visualization.css.CSSClass;
+import de.lmu.ifi.dbs.elki.visualization.projector.ParallelPlotProjector;
+import de.lmu.ifi.dbs.elki.visualization.style.ClassStylingPolicy;
+import de.lmu.ifi.dbs.elki.visualization.style.StyleLibrary;
+import de.lmu.ifi.dbs.elki.visualization.style.StylingPolicy;
+import de.lmu.ifi.dbs.elki.visualization.style.lines.LineStyleLibrary;
+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.thumbs.ThumbnailVisualization;
+
+/**
+ * Generates data lines.
+ *
+ * @author Robert Rödler
+ */
+public class LineVisualization extends AbstractParallelVisualization<NumberVector<?, ?>> implements DataStoreListener {
+ /**
+ * Generic tags to indicate the type of element. Used in IDs, CSS-Classes etc.
+ */
+ public static final String DATALINE = "Dataline";
+
+ /**
+ * Sample we visualize.
+ */
+ private SamplingResult sample;
+
+ /**
+ * Constructor.
+ *
+ * @param task VisualizationTask
+ */
+ public LineVisualization(VisualizationTask task) {
+ super(task);
+ this.sample = ResultUtil.getSamplingResult(relation);
+ context.addResultListener(this);
+ context.addDataStoreListener(this);
+ incrementalRedraw();
+ }
+
+ @Override
+ public void destroy() {
+ context.removeDataStoreListener(this);
+ context.removeResultListener(this);
+ super.destroy();
+ }
+
+ @Override
+ public void resultChanged(Result current) {
+ super.resultChanged(current);
+ if(current == sample || current == context.getStyleResult()) {
+ synchronizedRedraw();
+ }
+ }
+
+ @Override
+ protected void redraw() {
+ StylingPolicy sp = context.getStyleResult().getStylingPolicy();
+ addCSSClasses(svgp, sp);
+
+ Iterator<DBID> ids = sample.getSample().iterator();
+ if(ids == null || !ids.hasNext()) {
+ ids = relation.iterDBIDs();
+ }
+ if(sp instanceof ClassStylingPolicy) {
+ ClassStylingPolicy csp = (ClassStylingPolicy) sp;
+ for(int c = csp.getMinStyle(); c < csp.getMaxStyle(); c++) {
+ String key = DATALINE + "_" + c;
+ for(Iterator<DBID> iter = csp.iterateClass(c); iter.hasNext();) {
+ DBID id = iter.next();
+ if(!sample.getSample().contains(id)) {
+ continue; // TODO: can we test more efficiently than this?
+ }
+ SVGPath path = new SVGPath();
+ double[] yPos = proj.fastProjectDataToRenderSpace(relation.get(id));
+ for(int i = 0; i < yPos.length; i++) {
+ path.drawTo(getVisibleAxisX(i), yPos[i]);
+ }
+ Element line = path.makeElement(svgp);
+ SVGUtil.addCSSClass(line, key);
+ layer.appendChild(line);
+ }
+ }
+ }
+ else {
+ while(ids.hasNext()) {
+ DBID id = ids.next();
+ SVGPath path = new SVGPath();
+ double[] yPos = proj.fastProjectDataToRenderSpace(relation.get(id));
+ for(int i = 0; i < yPos.length; i++) {
+ path.drawTo(getVisibleAxisX(i), yPos[i]);
+ }
+ Element line = path.makeElement(svgp);
+ SVGUtil.addCSSClass(line, DATALINE);
+ // assign color
+ line.setAttribute(SVGConstants.SVG_STYLE_ATTRIBUTE, SVGConstants.CSS_STROKE_PROPERTY + ":" + SVGUtil.colorToString(sp.getColorForDBID(id)));
+ layer.appendChild(line);
+ }
+ }
+ }
+
+ /**
+ * Adds the required CSS-Classes
+ *
+ * @param svgp SVG-Plot
+ */
+ private void addCSSClasses(SVGPlot svgp, StylingPolicy sp) {
+ final StyleLibrary style = context.getStyleLibrary();
+ final LineStyleLibrary lines = style.lines();
+ final double width = .5 * style.getLineWidth(StyleLibrary.PLOT);
+ if(sp instanceof ClassStylingPolicy) {
+ ClassStylingPolicy csp = (ClassStylingPolicy) sp;
+ for(int i = csp.getMinStyle(); i < csp.getMaxStyle(); i++) {
+ String key = DATALINE + "_" + i;
+ if(!svgp.getCSSClassManager().contains(key)) {
+ CSSClass cls = new CSSClass(this, key);
+ cls.setStatement(SVGConstants.CSS_STROKE_LINECAP_PROPERTY, SVGConstants.CSS_ROUND_VALUE);
+ cls.setStatement(SVGConstants.CSS_STROKE_LINEJOIN_PROPERTY, SVGConstants.CSS_ROUND_VALUE);
+ cls.setStatement(SVGConstants.CSS_FILL_PROPERTY, SVGConstants.CSS_NONE_VALUE);
+ lines.formatCSSClass(cls, i, width);
+ svgp.addCSSClassOrLogError(cls);
+ }
+ }
+ }
+ else {
+ // Class for the distance function
+ if(!svgp.getCSSClassManager().contains(DATALINE)) {
+ CSSClass cls = new CSSClass(this, DATALINE);
+ cls.setStatement(SVGConstants.CSS_STROKE_LINECAP_PROPERTY, SVGConstants.CSS_ROUND_VALUE);
+ cls.setStatement(SVGConstants.CSS_STROKE_LINEJOIN_PROPERTY, SVGConstants.CSS_ROUND_VALUE);
+ cls.setStatement(SVGConstants.CSS_FILL_PROPERTY, SVGConstants.CSS_NONE_VALUE);
+ lines.formatCSSClass(cls, -1, width);
+ svgp.addCSSClassOrLogError(cls);
+ }
+ }
+ svgp.updateStyleElement();
+ }
+
+ /**
+ * Factory for axis visualizations
+ *
+ * @author Robert Rödler
+ *
+ * @apiviz.stereotype factory
+ * @apiviz.uses LineVisualization oneway - - «create»
+ */
+ public static class Factory extends AbstractVisFactory {
+ /**
+ * A short name characterizing this Visualizer.
+ */
+ private static final String NAME = "Data lines";
+
+ /**
+ * Constructor, adhering to
+ * {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable}
+ */
+ public Factory() {
+ super();
+ thumbmask |= ThumbnailVisualization.ON_DATA | ThumbnailVisualization.ON_STYLE;
+ }
+
+ @Override
+ public Visualization makeVisualization(VisualizationTask task) {
+ return new LineVisualization(task);
+ }
+
+ @Override
+ public void processNewResult(HierarchicalResult baseResult, Result result) {
+ IterableIterator<ParallelPlotProjector<?>> ps = ResultUtil.filteredResults(result, ParallelPlotProjector.class);
+ for(ParallelPlotProjector<?> p : ps) {
+ final VisualizationTask task = new VisualizationTask(NAME, p.getRelation(), p.getRelation(), this);
+ task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_DATA);
+ baseResult.getHierarchy().add(p, task);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/ParallelAxisVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/ParallelAxisVisualization.java
new file mode 100644
index 00000000..a47ea734
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/ParallelAxisVisualization.java
@@ -0,0 +1,196 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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 org.apache.batik.util.SVGConstants;
+import org.w3c.dom.Element;
+import org.w3c.dom.events.Event;
+import org.w3c.dom.events.EventListener;
+import org.w3c.dom.events.EventTarget;
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+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.DatabaseUtil;
+import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
+import de.lmu.ifi.dbs.elki.visualization.css.CSSClass;
+import de.lmu.ifi.dbs.elki.visualization.css.CSSClassManager.CSSNamingConflict;
+import de.lmu.ifi.dbs.elki.visualization.projector.ParallelPlotProjector;
+import de.lmu.ifi.dbs.elki.visualization.style.StyleLibrary;
+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;
+import de.lmu.ifi.dbs.elki.visualization.visualizers.AbstractVisFactory;
+import de.lmu.ifi.dbs.elki.visualization.visualizers.Visualization;
+
+/**
+ * Generates a SVG-Element containing axes, including labeling.
+ *
+ * @author Robert Rödler
+ *
+ * @apiviz.uses SVGSimpleLinearAxis
+ */
+// TODO: split into interactive / non-interactive parts?
+public class ParallelAxisVisualization extends AbstractParallelVisualization<NumberVector<?, ?>> {
+ /**
+ * Axis label class
+ */
+ public final static String AXIS_LABEL = "paxis-label";
+
+ /**
+ * Clickable area for the axis.
+ */
+ public final static String INVERTEDAXIS = "paxis-button";
+
+ /**
+ * Constructor.
+ *
+ * @param task VisualizationTask
+ */
+ public ParallelAxisVisualization(VisualizationTask task) {
+ super(task);
+ incrementalRedraw();
+ context.addResultListener(this);
+ }
+
+ @Override
+ protected void redraw() {
+ addCSSClasses(svgp);
+ final int dim = proj.getVisibleDimensions();
+ try {
+ for(int i = 0; i < dim; i++) {
+ final int truedim = proj.getDimForVisibleAxis(i);
+ final double axisX = getVisibleAxisX(i);
+ if(!proj.isAxisInverted(i)) {
+ SVGSimpleLinearAxis.drawAxis(svgp, layer, proj.getAxisScale(i), axisX, getSizeY(), axisX, 0, SVGSimpleLinearAxis.LabelStyle.ENDLABEL, context.getStyleLibrary());
+ }
+ else {
+ SVGSimpleLinearAxis.drawAxis(svgp, layer, proj.getAxisScale(i), axisX, 0, axisX, getSizeY(), SVGSimpleLinearAxis.LabelStyle.ENDLABEL, context.getStyleLibrary());
+ }
+ // Get axis label
+ final String label = DatabaseUtil.getColumnLabel(relation, truedim + 1);
+ // Add axis label
+ Element text = svgp.svgText(axisX, -.7 * getMarginTop(), label);
+ SVGUtil.setCSSClass(text, AXIS_LABEL);
+ layer.appendChild(text);
+ // TODO: Split into background + clickable layer.
+ Element button = svgp.svgRect(axisX - getAxisSep() * .475, -getMarginTop(), .95 * getAxisSep(), .5 * getMarginTop());
+ SVGUtil.setCSSClass(button, INVERTEDAXIS);
+ addEventListener(button, truedim);
+ layer.appendChild(button);
+ }
+ }
+ catch(CSSNamingConflict e) {
+ throw new RuntimeException("Conflict in CSS naming for axes.", e);
+ }
+ }
+
+ /**
+ * Add the main CSS classes.
+ *
+ * @param svgp Plot to draw to
+ */
+ private void addCSSClasses(SVGPlot svgp) {
+ final StyleLibrary style = context.getStyleLibrary();
+ if(!svgp.getCSSClassManager().contains(AXIS_LABEL)) {
+ CSSClass cls = new CSSClass(this, AXIS_LABEL);
+ cls.setStatement(SVGConstants.CSS_FILL_PROPERTY, style.getTextColor(StyleLibrary.AXIS_LABEL));
+ cls.setStatement(SVGConstants.CSS_FONT_FAMILY_PROPERTY, style.getFontFamily(StyleLibrary.AXIS_LABEL));
+ cls.setStatement(SVGConstants.CSS_FONT_SIZE_PROPERTY, style.getTextSize(StyleLibrary.AXIS_LABEL));
+ cls.setStatement(SVGConstants.CSS_TEXT_ANCHOR_PROPERTY, SVGConstants.SVG_MIDDLE_VALUE);
+ svgp.addCSSClassOrLogError(cls);
+ }
+ if(!svgp.getCSSClassManager().contains(INVERTEDAXIS)) {
+ CSSClass cls = new CSSClass(this, INVERTEDAXIS);
+ cls.setStatement(SVGConstants.CSS_OPACITY_PROPERTY, 0.1);
+ cls.setStatement(SVGConstants.CSS_FILL_PROPERTY, SVGConstants.CSS_GREY_VALUE);
+ svgp.addCSSClassOrLogError(cls);
+ }
+ }
+
+ /**
+ * Add an event listener to the Element
+ *
+ * @param tag Element to add the listener
+ * @param i Tool number for the Element
+ */
+ private void addEventListener(final Element tag, final int i) {
+ EventTarget targ = (EventTarget) tag;
+ targ.addEventListener(SVGConstants.SVG_EVENT_CLICK, new EventListener() {
+ @Override
+ public void handleEvent(Event evt) {
+ proj.toggleDimInverted(i);
+ context.getHierarchy().resultChanged(proj);
+ }
+ }, false);
+ }
+
+ /**
+ * Factory for axis visualizations
+ *
+ * @author Robert Rödler
+ *
+ * @apiviz.stereotype factory
+ * @apiviz.uses ParallelAxisVisualization oneway - - «create»
+ */
+ public static class Factory extends AbstractVisFactory {
+ /**
+ * A short name characterizing this Visualizer.
+ */
+ private static final String NAME = "Parallel Axes";
+
+ /**
+ * Constructor, adhering to
+ * {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable}
+ */
+ public Factory() {
+ super();
+ }
+
+ @Override
+ public Visualization makeVisualization(VisualizationTask task) {
+ return new ParallelAxisVisualization(task);
+ }
+
+ @Override
+ public void processNewResult(HierarchicalResult baseResult, Result result) {
+ Iterator<ParallelPlotProjector<?>> ps = ResultUtil.filteredResults(result, ParallelPlotProjector.class);
+ while(ps.hasNext()) {
+ ParallelPlotProjector<?> p = ps.next();
+ final VisualizationTask task = new VisualizationTask(NAME, p, p.getRelation(), this);
+ task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_BACKGROUND);
+ baseResult.getHierarchy().add(p, task);
+ }
+ }
+
+ @Override
+ public boolean allowThumbnails(VisualizationTask task) {
+ // Don't use thumbnails
+ return true;
+ }
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..821ca2a5
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/cluster/ClusterOutlineVisualization.java
@@ -0,0 +1,259 @@
+package de.lmu.ifi.dbs.elki.visualization.visualizers.parallel.cluster;
+
+/*
+ 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 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.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.DBID;
+import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
+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.IterableIterator;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
+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.projector.ParallelPlotProjector;
+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.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.parallel.AbstractParallelVisualization;
+
+/**
+ * Generates a SVG-Element that visualizes the area covered by a cluster.
+ *
+ * @author Robert Rödler
+ * @author Erich Schubert
+ */
+public class ClusterOutlineVisualization extends AbstractParallelVisualization<NumberVector<?, ?>> implements DataStoreListener {
+ /**
+ * Generic tags to indicate the type of element. Used in IDs, CSS-Classes etc.
+ */
+ public static final String CLUSTERAREA = "Clusteroutline";
+
+ /**
+ * The result we visualize
+ */
+ private Clustering<Model> clustering;
+
+ /**
+ * Flag for using rounded shapes
+ */
+ boolean rounded = true;
+
+ /**
+ * Constructor.
+ *
+ * @param task VisualizationTask
+ */
+ public ClusterOutlineVisualization(VisualizationTask task, boolean rounded) {
+ super(task);
+ this.clustering = task.getResult();
+ this.rounded = rounded;
+ context.addDataStoreListener(this);
+ context.addResultListener(this);
+ incrementalRedraw();
+ }
+
+ @Override
+ public void destroy() {
+ context.removeDataStoreListener(this);
+ context.removeResultListener(this);
+ super.destroy();
+ }
+
+ @Override
+ protected void redraw() {
+ addCSSClasses(svgp);
+ int dim = proj.getVisibleDimensions();
+
+ DoubleMinMax[] mms = DoubleMinMax.newArray(dim);
+ DoubleMinMax[] midmm = DoubleMinMax.newArray(dim - 1);
+
+ Iterator<Cluster<Model>> ci = clustering.getAllClusters().iterator();
+ for(int cnum = 0; cnum < clustering.getAllClusters().size(); cnum++) {
+ Cluster<?> clus = ci.next();
+ for(int i = 0; i < dim; i++) {
+ mms[i].reset();
+ if(i < dim - 1) {
+ midmm[i].reset();
+ }
+ }
+
+ // Process points
+ // TODO: do this just once, cache the result somewhere appropriately?
+ for(DBID objId : clus.getIDs()) {
+ double[] yPos = proj.fastProjectDataToRenderSpace(relation.get(objId));
+ for(int i = 0; i < dim; i++) {
+ mms[i].put(yPos[i]);
+ if(i > 0) {
+ midmm[i - 1].put((yPos[i] + yPos[i - 1]) / 2.);
+ }
+ }
+ }
+
+ SVGPath path = new SVGPath();
+ if(!rounded) {
+ // Straight lines
+ for(int i = 0; i < dim; i++) {
+ path.drawTo(getVisibleAxisX(i), mms[i].getMax());
+ if(i < dim - 1) {
+ path.drawTo(getVisibleAxisX(i + .5), midmm[i].getMax());
+ }
+ }
+ for(int i = dim - 1; i >= 0; i--) {
+ if(i < dim - 1) {
+ path.drawTo(getVisibleAxisX(i + .5), midmm[i].getMin());
+ }
+ path.drawTo(getVisibleAxisX(i), mms[i].getMin());
+ }
+ path.close();
+ }
+ else {
+ // Maxima
+ path.drawTo(getVisibleAxisX(0), mms[0].getMax());
+ for(int i = 1; i < dim; i++) {
+ path.quadTo(getVisibleAxisX(i - .5), midmm[i - 1].getMax(), getVisibleAxisX(i), mms[i].getMax());
+ }
+ // Minima
+ path.drawTo(getVisibleAxisX(dim - 1), mms[dim - 1].getMin());
+ for(int i = dim - 1; i > 0; i--) {
+ path.quadTo(getVisibleAxisX(i - .5), midmm[i - 1].getMin(), getVisibleAxisX(i - 1), mms[i - 1].getMin());
+ }
+ path.close();
+ }
+
+ Element intervals = path.makeElement(svgp);
+ SVGUtil.addCSSClass(intervals, CLUSTERAREA + cnum);
+ layer.appendChild(intervals);
+ }
+ }
+
+ /**
+ * Adds the required CSS-Classes
+ *
+ * @param svgp SVG-Plot
+ */
+ private void addCSSClasses(SVGPlot svgp) {
+ if(!svgp.getCSSClassManager().contains(CLUSTERAREA)) {
+ ColorLibrary colors = context.getStyleLibrary().getColorSet(StyleLibrary.PLOT);
+ int clusterID = 0;
+
+ for(@SuppressWarnings("unused")
+ Cluster<?> cluster : clustering.getAllClusters()) {
+ CSSClass cls = new CSSClass(this, CLUSTERAREA + clusterID);
+ // cls.setStatement(SVGConstants.CSS_STROKE_WIDTH_PROPERTY,
+ // context.getStyleLibrary().getLineWidth(StyleLibrary.PLOT) / 2.0);
+ cls.setStatement(SVGConstants.CSS_OPACITY_PROPERTY, 0.5);
+ final String color;
+ if(clustering.getAllClusters().size() == 1) {
+ color = SVGConstants.CSS_BLACK_VALUE;
+ }
+ else {
+ color = colors.getColor(clusterID);
+ }
+ // cls.setStatement(SVGConstants.CSS_STROKE_PROPERTY, color);
+ cls.setStatement(SVGConstants.CSS_FILL_PROPERTY, color);
+
+ svgp.addCSSClassOrLogError(cls);
+ clusterID++;
+ }
+ }
+ }
+
+ /**
+ * Factory for axis visualizations
+ *
+ * @author Robert Rödler
+ *
+ * @apiviz.stereotype factory
+ * @apiviz.uses ClusterOutlineVisualization oneway - - «create»
+ */
+ public static class Factory extends AbstractVisFactory {
+ /**
+ * A short name characterizing this Visualizer.
+ */
+ private static final String NAME = "Cluster Outline";
+
+ /**
+ * Currently unused option to enable/disable rounding
+ */
+ public static final OptionID ROUNDED_ID = OptionID.getOrCreateOptionID("parallel.clusteroutline.rounded", "Draw lines rounded");
+
+ /**
+ * Currently, always enabled.
+ */
+ private boolean rounded = true;
+
+ /**
+ * Constructor, adhering to
+ * {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable}
+ */
+ public Factory() {
+ super();
+ }
+
+ @Override
+ public Visualization makeVisualization(VisualizationTask task) {
+ return new ClusterOutlineVisualization(task, rounded);
+ }
+
+ @Override
+ public void processNewResult(HierarchicalResult baseResult, Result result) {
+ // Find clusterings we can visualize:
+ Iterator<Clustering<?>> clusterings = ResultUtil.filteredResults(result, Clustering.class);
+ while(clusterings.hasNext()) {
+ Clustering<?> c = clusterings.next();
+ if(c.getAllClusters().size() > 0) {
+ IterableIterator<ParallelPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ParallelPlotProjector.class);
+ for(ParallelPlotProjector<?> p : ps) {
+ final VisualizationTask task = new VisualizationTask(NAME, c, p.getRelation(), this);
+ task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_DATA - 1);
+ task.put(VisualizationTask.META_VISIBLE_DEFAULT, false);
+ baseResult.getHierarchy().add(c, task);
+ baseResult.getHierarchy().add(p, task);
+ }
+ }
+ }
+ }
+
+ @Override
+ public boolean allowThumbnails(VisualizationTask task) {
+ // Don't use thumbnails
+ return false;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/cluster/ClusterParallelMeanVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/cluster/ClusterParallelMeanVisualization.java
new file mode 100644
index 00000000..df731ac2
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/cluster/ClusterParallelMeanVisualization.java
@@ -0,0 +1,215 @@
+package de.lmu.ifi.dbs.elki.visualization.visualizers.parallel.cluster;
+
+/*
+ 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 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.NumberVector;
+import de.lmu.ifi.dbs.elki.data.model.MeanModel;
+import de.lmu.ifi.dbs.elki.database.datastore.DataStoreListener;
+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.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.projector.ParallelPlotProjector;
+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.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.parallel.AbstractParallelVisualization;
+
+/**
+ * Generates a SVG-Element that visualizes cluster means.
+ *
+ * @author Robert Rödler
+ */
+public class ClusterParallelMeanVisualization extends AbstractParallelVisualization<NumberVector<?, ?>> implements DataStoreListener {
+ /**
+ * Generic tags to indicate the type of element. Used in IDs, CSS-Classes etc.
+ */
+ public static final String CLUSTERMEAN = "Clustermean";
+
+ /**
+ * The result we visualize
+ */
+ private Clustering<MeanModel<? extends NumberVector<?, ?>>> clustering;
+
+ /**
+ * Constructor.
+ *
+ * @param task VisualizationTask
+ */
+ public ClusterParallelMeanVisualization(VisualizationTask task) {
+ super(task);
+ this.clustering = task.getResult();
+ context.addDataStoreListener(this);
+ context.addResultListener(this);
+ incrementalRedraw();
+ }
+
+ @Override
+ public void destroy() {
+ context.removeDataStoreListener(this);
+ context.removeResultListener(this);
+ super.destroy();
+ }
+
+ @Override
+ protected void redraw() {
+ addCSSClasses(svgp);
+
+ Iterator<Cluster<MeanModel<? extends NumberVector<?, ?>>>> ci = clustering.getAllClusters().iterator();
+ for(int cnum = 0; cnum < clustering.getAllClusters().size(); cnum++) {
+ Cluster<MeanModel<? extends NumberVector<?, ?>>> clus = ci.next();
+ NumberVector<?, ?> mean = clus.getModel().getMean();
+ if(mean == null) {
+ continue;
+ }
+
+ double[] pmean = proj.fastProjectDataToRenderSpace(mean);
+
+ SVGPath path = new SVGPath();
+ for(int i = 0; i < pmean.length; i++) {
+ path.drawTo(getVisibleAxisX(i), pmean[i]);
+ }
+
+ Element meanline = path.makeElement(svgp);
+ SVGUtil.addCSSClass(meanline, CLUSTERMEAN + cnum);
+ layer.appendChild(meanline);
+ }
+ }
+
+ /**
+ * Adds the required CSS-Classes
+ *
+ * @param svgp SVG-Plot
+ */
+ private void addCSSClasses(SVGPlot svgp) {
+ if(!svgp.getCSSClassManager().contains(CLUSTERMEAN)) {
+ ColorLibrary colors = context.getStyleLibrary().getColorSet(StyleLibrary.PLOT);
+ int clusterID = 0;
+
+ for(@SuppressWarnings("unused")
+ Cluster<?> cluster : clustering.getAllClusters()) {
+ CSSClass cls = new CSSClass(this, CLUSTERMEAN + clusterID);
+ cls.setStatement(SVGConstants.CSS_STROKE_WIDTH_PROPERTY, context.getStyleLibrary().getLineWidth(StyleLibrary.PLOT) * 2);
+
+ final String color;
+ if(clustering.getAllClusters().size() == 1) {
+ color = SVGConstants.CSS_BLACK_VALUE;
+ }
+ else {
+ color = colors.getColor(clusterID);
+ }
+
+ cls.setStatement(SVGConstants.CSS_STROKE_PROPERTY, color);
+ cls.setStatement(SVGConstants.CSS_FILL_PROPERTY, SVGConstants.CSS_NONE_VALUE);
+
+ svgp.addCSSClassOrLogError(cls);
+ clusterID++;
+ }
+ }
+ }
+
+ /**
+ * Factory for axis visualizations
+ *
+ * @author Robert Rödler
+ *
+ * @apiviz.stereotype factory
+ * @apiviz.uses ClusterParallelMeanVisualization oneway - - «create»
+ *
+ */
+ public static class Factory extends AbstractVisFactory {
+ /**
+ * A short name characterizing this Visualizer.
+ */
+ private static final String NAME = "Cluster Means";
+
+ /**
+ * Constructor, adhering to
+ * {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable}
+ */
+ public Factory() {
+ super();
+ }
+
+ @Override
+ public Visualization makeVisualization(VisualizationTask task) {
+ return new ClusterParallelMeanVisualization(task);
+ }
+
+ @Override
+ public void processNewResult(HierarchicalResult baseResult, Result result) {
+ // Find clusterings we can visualize:
+ Iterator<Clustering<?>> clusterings = ResultUtil.filteredResults(result, Clustering.class);
+ while(clusterings.hasNext()) {
+ Clustering<?> c = clusterings.next();
+ if(c.getAllClusters().size() > 0) {
+ // Does the cluster have a model with cluster means?
+ Clustering<MeanModel<? extends NumberVector<?, ?>>> mcls = findMeanModel(c);
+ if(mcls != null) {
+ Iterator<ParallelPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ParallelPlotProjector.class);
+ while(ps.hasNext()) {
+ ParallelPlotProjector<?> p = ps.next();
+ final VisualizationTask task = new VisualizationTask(NAME, c, p.getRelation(), this);
+ task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_DATA + 1);
+ baseResult.getHierarchy().add(c, task);
+ baseResult.getHierarchy().add(p, task);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Test if the given clustering has a mean model.
+ *
+ * @param c Clustering to inspect
+ * @return the clustering cast to return a mean model, null otherwise.
+ */
+ @SuppressWarnings("unchecked")
+ private static Clustering<MeanModel<? extends NumberVector<?, ?>>> findMeanModel(Clustering<?> c) {
+ if(c.getAllClusters().get(0).getModel() instanceof MeanModel<?>) {
+ return (Clustering<MeanModel<? extends NumberVector<?, ?>>>) c;
+ }
+ return null;
+ }
+
+ @Override
+ public boolean allowThumbnails(VisualizationTask task) {
+ // Don't use thumbnails
+ return false;
+ }
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..7977da0c
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/cluster/package-info.java
@@ -0,0 +1,26 @@
+/**
+ * <p>Visualizers for clustering results based on parallel coordinates.</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.visualization.visualizers.parallel.cluster; \ No newline at end of file
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
new file mode 100644
index 00000000..c36dff0c
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/index/RTreeParallelVisualization.java
@@ -0,0 +1,267 @@
+package de.lmu.ifi.dbs.elki.visualization.visualizers.parallel.index;
+
+/*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 org.apache.batik.util.SVGConstants;
+import org.w3c.dom.Element;
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil;
+import de.lmu.ifi.dbs.elki.database.datastore.DataStoreListener;
+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.index.tree.spatial.rstarvariants.rstar.RStarTreeNode;
+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.IterableIterator;
+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.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.ProjectionParallel;
+import de.lmu.ifi.dbs.elki.visualization.projector.ParallelPlotProjector;
+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.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.parallel.AbstractParallelVisualization;
+import de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.index.TreeMBRVisualization;
+
+/**
+ * Visualize the of an R-Tree based index.
+ *
+ * @author Robert Rödler
+ *
+ * @apiviz.has AbstractRStarTree oneway - - visualizes
+ *
+ * @param <N> Tree node type
+ * @param <E> Tree entry type
+ */
+// TODO: listen for tree changes instead of data changes?
+public class RTreeParallelVisualization<N extends AbstractRStarTreeNode<N, E>, E extends SpatialEntry> extends AbstractParallelVisualization<NumberVector<?, ?>> implements DataStoreListener {
+ /**
+ * Generic tag to indicate the type of element. Used in IDs, CSS-Classes etc.
+ */
+ public static final String INDEX = "parallelrtree";
+
+ /**
+ * A short name characterizing this Visualizer.
+ */
+ public static final String NAME = "R-Tree Index MBRs";
+
+ /**
+ * Fill parameter.
+ */
+ protected boolean fill = true;
+
+ /**
+ * The tree we visualize
+ */
+ protected AbstractRStarTree<N, E> tree;
+
+ /**
+ * Constructor.
+ *
+ * @param task Visualization task
+ * @param fill Fill flag
+ */
+ @SuppressWarnings("unchecked")
+ public RTreeParallelVisualization(VisualizationTask task, boolean fill) {
+ super(task);
+ this.tree = AbstractRStarTree.class.cast(task.getResult());
+ this.fill = fill;
+ context.addDataStoreListener(this);
+ context.addResultListener(this);
+ incrementalRedraw();
+ }
+
+ @Override
+ public void destroy() {
+ context.removeDataStoreListener(this);
+ context.removeResultListener(this);
+ super.destroy();
+ }
+
+ @Override
+ protected void redraw() {
+ if(tree != null) {
+ addCSSClasses(svgp);
+ E root = tree.getRootEntry();
+ visualizeRTreeEntry(svgp, layer, proj, tree, root, 0, 0);
+ }
+ }
+
+ /**
+ * Adds the required CSS-Classes
+ *
+ * @param svgp SVG-Plot
+ */
+ private void addCSSClasses(SVGPlot svgp) {
+ ColorLibrary colors = context.getStyleLibrary().getColorSet(StyleLibrary.PLOT);
+
+ for(int i = 0; i < tree.getHeight(); i++) {
+
+ if(!svgp.getCSSClassManager().contains(INDEX + i)) {
+ CSSClass cls = new CSSClass(this, INDEX + i);
+
+ // Relative depth of this level. 1.0 = toplevel
+ final double relDepth = 1. - (((double) i) / tree.getHeight());
+ if(fill) {
+ cls.setStatement(SVGConstants.CSS_STROKE_PROPERTY, colors.getColor(i));
+ cls.setStatement(SVGConstants.CSS_STROKE_WIDTH_PROPERTY, relDepth * context.getStyleLibrary().getLineWidth(StyleLibrary.PLOT));
+ cls.setStatement(SVGConstants.CSS_FILL_PROPERTY, colors.getColor(i));
+ cls.setStatement(SVGConstants.CSS_FILL_OPACITY_PROPERTY, 0.2);
+ }
+ else {
+ cls.setStatement(SVGConstants.CSS_STROKE_PROPERTY, colors.getColor(i));
+ cls.setStatement(SVGConstants.CSS_STROKE_WIDTH_PROPERTY, relDepth * context.getStyleLibrary().getLineWidth(StyleLibrary.PLOT));
+ cls.setStatement(SVGConstants.CSS_FILL_PROPERTY, SVGConstants.CSS_NONE_VALUE);
+ }
+ cls.setStatement(SVGConstants.CSS_STROKE_LINECAP_PROPERTY, SVGConstants.CSS_ROUND_VALUE);
+ cls.setStatement(SVGConstants.CSS_STROKE_LINEJOIN_PROPERTY, SVGConstants.CSS_ROUND_VALUE);
+ svgp.addCSSClassOrLogError(cls);
+ }
+ }
+ svgp.updateStyleElement();
+ }
+
+ /**
+ * Recursively draw the MBR rectangles.
+ *
+ * @param svgp SVG Plot
+ * @param layer Layer
+ * @param proj Projection
+ * @param rtree Rtree to visualize
+ * @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) {
+ final int dim = proj.getVisibleDimensions();
+ double[] min = proj.fastProjectDataToRenderSpace(SpatialUtil.getMin(entry));
+ double[] max = proj.fastProjectDataToRenderSpace(SpatialUtil.getMax(entry));
+ assert (min.length == dim && max.length == dim);
+ SVGPath path = new SVGPath();
+ for(int i = 0; i < dim; i++) {
+ path.drawTo(getVisibleAxisX(i), Math.max(min[i], max[i]));
+ }
+ for(int i = dim - 1; i >= 0; i--) {
+ path.drawTo(getVisibleAxisX(i), Math.min(min[i], max[i]));
+ }
+ path.close();
+
+ Element intervals = path.makeElement(svgp);
+
+ SVGUtil.addCSSClass(intervals, INDEX + depth);
+ layer.appendChild(intervals);
+
+ if(!entry.isLeafEntry()) {
+ N node = rtree.getNode(entry);
+ for(int i = 0; i < node.getNumEntries(); i++) {
+ E child = node.getEntry(i);
+ if(!child.isLeafEntry()) {
+ visualizeRTreeEntry(svgp, layer, proj, rtree, child, depth + 1, ++step);
+ }
+ }
+ }
+ }
+
+ /**
+ * Factory
+ *
+ * @author Robert Rödler
+ *
+ * @apiviz.stereotype factory
+ * @apiviz.uses RTreeParallelVisualization oneway - - «create»
+ */
+ public static class Factory extends AbstractVisFactory {
+ /**
+ * Fill parameter.
+ */
+ protected boolean fill = true;
+
+ /**
+ * Constructor.
+ *
+ * @param fill
+ */
+ public Factory(boolean fill) {
+ super();
+ this.fill = fill;
+ }
+
+ @Override
+ public Visualization makeVisualization(VisualizationTask task) {
+ return new RTreeParallelVisualization<RStarTreeNode, SpatialEntry>(task, fill);
+ }
+
+ @Override
+ public void processNewResult(HierarchicalResult baseResult, Result result) {
+ ArrayList<AbstractRStarTree<RStarTreeNode, SpatialEntry>> trees = ResultUtil.filterResults(result, AbstractRStarTree.class);
+ for(AbstractRStarTree<RStarTreeNode, SpatialEntry> tree : trees) {
+ if(tree instanceof Result) {
+ IterableIterator<ParallelPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ParallelPlotProjector.class);
+ for(ParallelPlotProjector<?> p : ps) {
+ final VisualizationTask task = new VisualizationTask(NAME, (Result) tree, p.getRelation(), this);
+ task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_BACKGROUND + 2);
+ baseResult.getHierarchy().add((Result) tree, task);
+ baseResult.getHierarchy().add(p, task);
+ }
+ }
+ }
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ protected boolean fill = true;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ Flag fillF = new Flag(TreeMBRVisualization.Factory.FILL_ID);
+ fillF.setDefaultValue(true);
+ if(config.grab(fillF)) {
+ fill = fillF.getValue();
+ }
+ }
+
+ @Override
+ protected Factory makeInstance() {
+ return new Factory(fill);
+ }
+ }
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..1cefd6f0
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/index/package-info.java
@@ -0,0 +1,26 @@
+/**
+ * <p>Visualizers for index structure based on parallel coordinates.</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.visualization.visualizers.parallel.index; \ No newline at end of file
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 f01505c7..0ab7d565 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) 2011
+Copyright (C) 2012
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/SelectionAxisRangeVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/selection/SelectionAxisRangeVisualization.java
new file mode 100644
index 00000000..cb8ee645
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/selection/SelectionAxisRangeVisualization.java
@@ -0,0 +1,184 @@
+package de.lmu.ifi.dbs.elki.visualization.visualizers.parallel.selection;
+
+/*
+ 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 java.util.ArrayList;
+
+import org.apache.batik.util.SVGConstants;
+import org.w3c.dom.Element;
+
+import de.lmu.ifi.dbs.elki.data.NumberVector;
+import de.lmu.ifi.dbs.elki.result.DBIDSelection;
+import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
+import de.lmu.ifi.dbs.elki.result.RangeSelection;
+import de.lmu.ifi.dbs.elki.result.Result;
+import de.lmu.ifi.dbs.elki.result.ResultUtil;
+import de.lmu.ifi.dbs.elki.result.SelectionResult;
+import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
+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.projector.ParallelPlotProjector;
+import de.lmu.ifi.dbs.elki.visualization.style.StyleLibrary;
+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.parallel.AbstractParallelVisualization;
+import de.lmu.ifi.dbs.elki.visualization.visualizers.thumbs.ThumbnailVisualization;
+
+/**
+ * Visualizer for generating an SVG-Element representing the selected range for
+ * each dimension
+ *
+ * @author Robert Rödler
+ *
+ * @apiviz.has SelectionResult oneway - - visualizes
+ * @apiviz.has RangeSelection oneway - - visualizes
+ */
+public class SelectionAxisRangeVisualization extends AbstractParallelVisualization<NumberVector<?, ?>> {
+ /**
+ * A short name characterizing this Visualizer.
+ */
+ private static final String NAME = "Selection Axis Range";
+
+ /**
+ * CSS Class for the range marker
+ */
+ public static final String MARKER = "selectionAxisRange";
+
+ /**
+ * Constructor.
+ *
+ * @param task Visualization task
+ */
+ public SelectionAxisRangeVisualization(VisualizationTask task) {
+ super(task);
+ addCSSClasses(svgp);
+ context.addResultListener(this);
+ incrementalRedraw();
+ }
+
+ @Override
+ public void destroy() {
+ context.removeResultListener(this);
+ super.destroy();
+ }
+
+ /**
+ * Adds the required CSS-Classes
+ *
+ * @param svgp SVG-Plot
+ */
+ private void addCSSClasses(SVGPlot svgp) {
+ final StyleLibrary style = context.getStyleLibrary();
+ // Class for the cube
+ if(!svgp.getCSSClassManager().contains(MARKER)) {
+ CSSClass cls = new CSSClass(this, MARKER);
+ cls.setStatement(SVGConstants.CSS_STROKE_VALUE, style.getColor(StyleLibrary.SELECTION));
+ cls.setStatement(SVGConstants.CSS_STROKE_OPACITY_PROPERTY, style.getOpacity(StyleLibrary.SELECTION));
+ cls.setStatement(SVGConstants.CSS_STROKE_WIDTH_PROPERTY, style.getLineWidth(StyleLibrary.PLOT));
+ cls.setStatement(SVGConstants.CSS_STROKE_LINECAP_PROPERTY, SVGConstants.CSS_ROUND_VALUE);
+ cls.setStatement(SVGConstants.CSS_STROKE_LINEJOIN_PROPERTY, SVGConstants.CSS_ROUND_VALUE);
+
+ cls.setStatement(SVGConstants.CSS_FILL_PROPERTY, style.getColor(StyleLibrary.SELECTION));
+ cls.setStatement(SVGConstants.CSS_FILL_OPACITY_PROPERTY, style.getOpacity(StyleLibrary.SELECTION));
+
+ svgp.addCSSClassOrLogError(cls);
+ }
+ }
+
+ @Override
+ protected void redraw() {
+ DBIDSelection selContext = context.getSelection();
+ if(selContext == null || !(selContext instanceof RangeSelection)) {
+ return;
+ }
+ DoubleDoublePair[] ranges = ((RangeSelection) selContext).getRanges();
+ if(ranges == null) {
+ return;
+ }
+
+ // Project:
+ double[] min = new double[ranges.length];
+ double[] max = new double[ranges.length];
+ for(int d = 0; d < ranges.length; d++) {
+ if(ranges[d] != null) {
+ min[d] = ranges[d].first;
+ max[d] = ranges[d].second;
+ }
+ }
+ min = proj.fastProjectDataToRenderSpace(min);
+ max = proj.fastProjectDataToRenderSpace(max);
+
+ int dim = proj.getVisibleDimensions();
+ for(int d = 0; d < dim; d++) {
+ if(ranges[proj.getDimForVisibleAxis(d)] != null) {
+ double amin = Math.min(min[d], max[d]);
+ double amax = Math.max(min[d], max[d]);
+ Element rect = svgp.svgRect(getVisibleAxisX(d) - (0.01 * StyleLibrary.SCALE), amin, 0.02 * StyleLibrary.SCALE, amax - amin);
+ SVGUtil.addCSSClass(rect, MARKER);
+ layer.appendChild(rect);
+ }
+ }
+ }
+
+ /**
+ * Factory for visualizers to generate an SVG-Element containing a cube as
+ * marker representing the selected range for each dimension
+ *
+ * @author Robert Rödler
+ *
+ * @apiviz.stereotype factory
+ * @apiviz.uses SelectionAxisRangeVisualization oneway - - «create»
+ */
+ public static class Factory extends AbstractVisFactory {
+ /**
+ * Constructor.
+ */
+ public Factory() {
+ super();
+ thumbmask |= ThumbnailVisualization.ON_SELECTION;
+ }
+
+ @Override
+ public Visualization makeVisualization(VisualizationTask task) {
+ return new SelectionAxisRangeVisualization(task);
+ }
+
+ @Override
+ public void processNewResult(HierarchicalResult baseResult, Result result) {
+ final ArrayList<SelectionResult> selectionResults = ResultUtil.filterResults(result, SelectionResult.class);
+ for(SelectionResult selres : selectionResults) {
+ IterableIterator<ParallelPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ParallelPlotProjector.class);
+ for(ParallelPlotProjector<?> p : ps) {
+ final VisualizationTask task = new VisualizationTask(NAME, selres, p.getRelation(), this);
+ task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_DATA - 1);
+ baseResult.getHierarchy().add(selres, task);
+ baseResult.getHierarchy().add(p, task);
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/selection/SelectionLineVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/selection/SelectionLineVisualization.java
new file mode 100644
index 00000000..f6de4133
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/selection/SelectionLineVisualization.java
@@ -0,0 +1,167 @@
+package de.lmu.ifi.dbs.elki.visualization.visualizers.parallel.selection;
+
+/*
+ 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 java.util.ArrayList;
+
+import org.apache.batik.util.SVGConstants;
+import org.w3c.dom.Element;
+
+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.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.result.DBIDSelection;
+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.SelectionResult;
+import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
+import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
+import de.lmu.ifi.dbs.elki.visualization.css.CSSClass;
+import de.lmu.ifi.dbs.elki.visualization.projector.ParallelPlotProjector;
+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.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.parallel.AbstractParallelVisualization;
+import de.lmu.ifi.dbs.elki.visualization.visualizers.thumbs.ThumbnailVisualization;
+
+/**
+ * Visualizer for generating SVG-Elements representing the selected objects
+ *
+ * @author Robert Rödler
+ *
+ * @apiviz.has SelectionResult oneway - - visualizes
+ */
+public class SelectionLineVisualization extends AbstractParallelVisualization<NumberVector<?, ?>> implements DataStoreListener {
+ /**
+ * A short name characterizing this Visualizer.
+ */
+ private static final String NAME = "Selection Line";
+
+ /**
+ * CSS Class for the range marker
+ */
+ public static final String MARKER = "SelectionLine";
+
+ /**
+ * Constructor.
+ *
+ * @param task Visualization task
+ */
+ public SelectionLineVisualization(VisualizationTask task) {
+ super(task);
+ addCSSClasses(svgp);
+ context.addDataStoreListener(this);
+ context.addResultListener(this);
+ incrementalRedraw();
+ }
+
+ @Override
+ public void destroy() {
+ context.removeDataStoreListener(this);
+ context.removeResultListener(this);
+ super.destroy();
+ }
+
+ @Override
+ protected void redraw() {
+ DBIDSelection selContext = context.getSelection();
+ if(selContext != null) {
+ DBIDs selection = selContext.getSelectedIds();
+
+ for(DBID objId : selection) {
+ double[] yPos = proj.fastProjectDataToRenderSpace(relation.get(objId));
+
+ SVGPath path = new SVGPath();
+ for(int i = 0; i < proj.getVisibleDimensions(); i++) {
+ path.drawTo(getVisibleAxisX(i), yPos[i]);
+ }
+ Element marker = path.makeElement(svgp);
+ SVGUtil.addCSSClass(marker, MARKER);
+ layer.appendChild(marker);
+ }
+ }
+ }
+
+ /**
+ * Adds the required CSS-Classes
+ *
+ * @param svgp SVG-Plot
+ */
+ private void addCSSClasses(SVGPlot svgp) {
+ final StyleLibrary style = context.getStyleLibrary();
+ // Class for the cube
+ if(!svgp.getCSSClassManager().contains(MARKER)) {
+ CSSClass cls = new CSSClass(this, MARKER);
+ cls.setStatement(SVGConstants.CSS_STROKE_VALUE, style.getColor(StyleLibrary.SELECTION));
+ cls.setStatement(SVGConstants.CSS_STROKE_OPACITY_PROPERTY, style.getOpacity(StyleLibrary.SELECTION));
+ cls.setStatement(SVGConstants.CSS_STROKE_WIDTH_PROPERTY, style.getLineWidth(StyleLibrary.PLOT) * 2.);
+ cls.setStatement(SVGConstants.CSS_STROKE_LINECAP_PROPERTY, SVGConstants.CSS_ROUND_VALUE);
+ cls.setStatement(SVGConstants.CSS_STROKE_LINEJOIN_PROPERTY, SVGConstants.CSS_ROUND_VALUE);
+ cls.setStatement(SVGConstants.CSS_FILL_PROPERTY, SVGConstants.CSS_NONE_VALUE);
+ svgp.addCSSClassOrLogError(cls);
+ }
+ }
+
+ /**
+ * Factory for visualizers to generate an SVG-Element containing a cube as
+ * marker representing the selected range for each dimension
+ *
+ * @author Robert Rödler
+ *
+ * @apiviz.stereotype factory
+ */
+ public static class Factory extends AbstractVisFactory {
+ /**
+ * Constructor.
+ */
+ public Factory() {
+ super();
+ thumbmask |= ThumbnailVisualization.ON_DATA | ThumbnailVisualization.ON_SELECTION;
+ }
+
+ @Override
+ public Visualization makeVisualization(VisualizationTask task) {
+ return new SelectionLineVisualization(task);
+ }
+
+ @Override
+ public void processNewResult(HierarchicalResult baseResult, Result result) {
+ final ArrayList<SelectionResult> selectionResults = ResultUtil.filterResults(result, SelectionResult.class);
+ for(SelectionResult selres : selectionResults) {
+ IterableIterator<ParallelPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ParallelPlotProjector.class);
+ for(ParallelPlotProjector<?> p : ps) {
+ final VisualizationTask task = new VisualizationTask(NAME, selres, p.getRelation(), this);
+ task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_DATA -1);
+ baseResult.getHierarchy().add(selres, task);
+ baseResult.getHierarchy().add(p, task);
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/selection/SelectionToolAxisRangeVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/selection/SelectionToolAxisRangeVisualization.java
new file mode 100644
index 00000000..ead8e5ce
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/selection/SelectionToolAxisRangeVisualization.java
@@ -0,0 +1,316 @@
+package de.lmu.ifi.dbs.elki.visualization.visualizers.parallel.selection;
+
+/*
+ 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 java.util.ArrayList;
+
+import org.apache.batik.util.SVGConstants;
+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.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.logging.Logging;
+import de.lmu.ifi.dbs.elki.result.DBIDSelection;
+import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
+import de.lmu.ifi.dbs.elki.result.RangeSelection;
+import de.lmu.ifi.dbs.elki.result.Result;
+import de.lmu.ifi.dbs.elki.result.ResultUtil;
+import de.lmu.ifi.dbs.elki.result.SelectionResult;
+import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
+import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleDoublePair;
+import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
+import de.lmu.ifi.dbs.elki.visualization.batikutil.DragableArea;
+import de.lmu.ifi.dbs.elki.visualization.css.CSSClass;
+import de.lmu.ifi.dbs.elki.visualization.projections.Projection;
+import de.lmu.ifi.dbs.elki.visualization.projector.ParallelPlotProjector;
+import de.lmu.ifi.dbs.elki.visualization.style.StyleLibrary;
+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.parallel.AbstractParallelVisualization;
+
+/**
+ * Tool-Visualization for the tool to select axis ranges
+ *
+ * @author Robert Rödler
+ *
+ * @apiviz.has SelectionResult oneway - - updates
+ * @apiviz.has RangeSelection oneway - - updates
+ */
+public class SelectionToolAxisRangeVisualization extends AbstractParallelVisualization<NumberVector<?, ?>> implements DragableArea.DragListener {
+ /**
+ * The logger for this class.
+ */
+ protected static final Logging logger = Logging.getLogger(SelectionToolAxisRangeVisualization.class);
+
+ /**
+ * A short name characterizing this Visualizer.
+ */
+ private static final String NAME = "Axis Range Selection";
+
+ /**
+ * Generic tag to indicate the type of element. Used in IDs, CSS-Classes etc.
+ */
+ private static final String CSS_RANGEMARKER = "selectionAxisRangeMarker";
+
+ /**
+ * Element for selection rectangle
+ */
+ private Element rtag;
+
+ /**
+ * Element for the rectangle to add listeners
+ */
+ private Element etag;
+
+ /**
+ * Constructor.
+ *
+ * @param task Task
+ */
+ public SelectionToolAxisRangeVisualization(VisualizationTask task) {
+ super(task);
+ incrementalRedraw();
+ }
+
+ @Override
+ public void destroy() {
+ super.destroy();
+ }
+
+ @Override
+ protected void redraw() {
+ addCSSClasses(svgp);
+
+ // rtag: tag for the selected rect
+ rtag = svgp.svgElement(SVGConstants.SVG_G_TAG);
+ SVGUtil.addCSSClass(rtag, CSS_RANGEMARKER);
+ layer.appendChild(rtag);
+
+ // etag: sensitive area
+ DragableArea drag = new DragableArea(svgp, -.1 * getMarginLeft(), -.1 * getMarginTop(), getSizeX() + getMarginLeft() * .2, getSizeY() + getMarginTop() * .2, this);
+ etag = drag.getElement();
+ layer.appendChild(etag);
+ }
+
+ /**
+ * Delete the children of the element
+ *
+ * @param container SVG-Element
+ */
+ private void deleteChildren(Element container) {
+ while(container.hasChildNodes()) {
+ container.removeChild(container.getLastChild());
+ }
+ }
+
+ /**
+ * Set the selected ranges and the mask for the actual dimensions in the
+ * context
+ *
+ * @param x1 min x-value
+ * @param x2 max x-value
+ * @param y1 min y-value
+ * @param y2 max y-value
+ */
+ private void updateSelectionRectKoordinates(double x1, double x2, double y1, double y2, DoubleDoublePair[] ranges) {
+ final int dim = proj.getVisibleDimensions();
+ int minaxis = dim + 1;
+ int maxaxis = -1;
+ {
+ int i = 0;
+ while(i < dim) {
+ double axx = getVisibleAxisX(i);
+ if(x1 < axx || x2 < axx) {
+ minaxis = i;
+ break;
+ }
+ i++;
+ }
+ while(i <= dim) {
+ double axx = getVisibleAxisX(i);
+ if(x2 < axx && x1 < axx) {
+ maxaxis = i;
+ break;
+ }
+ i++;
+ }
+ }
+ double z1 = Math.max(Math.min(y1, y2), 0);
+ double z2 = Math.min(Math.max(y1, y2), getSizeY());
+ for(int i = minaxis; i < maxaxis; i++) {
+ double v1 = proj.fastProjectRenderToDataSpace(z1, i);
+ double v2 = proj.fastProjectRenderToDataSpace(z2, i);
+ if (logger.isDebugging()) {
+ logger.debug("Axis "+i+" dimension "+proj.getDimForVisibleAxis(i)+" "+v1+" to "+v2);
+ }
+ ranges[proj.getDimForVisibleAxis(i)] = new DoubleDoublePair(Math.min(v1, v2), Math.max(v1, v2));
+ }
+ }
+
+ @Override
+ public boolean startDrag(SVGPoint startPoint, Event evt) {
+ return true;
+ }
+
+ @Override
+ public boolean duringDrag(SVGPoint startPoint, SVGPoint dragPoint, Event evt, boolean inside) {
+ deleteChildren(rtag);
+ double x = Math.min(startPoint.getX(), dragPoint.getX());
+ double y = Math.min(startPoint.getY(), dragPoint.getY());
+ double width = Math.abs(startPoint.getX() - dragPoint.getX());
+ double height = Math.abs(startPoint.getY() - dragPoint.getY());
+ rtag.appendChild(svgp.svgRect(x, y, width, height));
+ return true;
+ }
+
+ @Override
+ public boolean endDrag(SVGPoint startPoint, SVGPoint dragPoint, Event evt, boolean inside) {
+ deleteChildren(rtag);
+ if(startPoint.getX() != dragPoint.getX() || startPoint.getY() != dragPoint.getY()) {
+ updateSelection(proj, startPoint, dragPoint);
+ }
+ return true;
+ }
+
+ /**
+ * Update the selection in the context.
+ *
+ * @param proj The projection
+ * @param p1 First Point of the selected rectangle
+ * @param p2 Second Point of the selected rectangle
+ */
+ private void updateSelection(Projection proj, SVGPoint p1, SVGPoint p2) {
+ DBIDSelection selContext = context.getSelection();
+ ModifiableDBIDs selection;
+ if(selContext != null) {
+ selection = DBIDUtil.newHashSet(selContext.getSelectedIds());
+ }
+ else {
+ selection = DBIDUtil.newHashSet();
+ }
+ DoubleDoublePair[] ranges;
+
+ if(p1 == null || p2 == null) {
+ logger.warning("no rect selected: p1: " + p1 + " p2: " + p2);
+ }
+ else {
+ double x1 = Math.min(p1.getX(), p2.getX());
+ double x2 = Math.max(p1.getX(), p2.getX());
+ double y1 = Math.max(p1.getY(), p2.getY());
+ double y2 = Math.min(p1.getY(), p2.getY());
+
+ int dim = proj.getInputDimensionality();
+ if(selContext instanceof RangeSelection) {
+ ranges = ((RangeSelection) selContext).getRanges();
+ }
+ else {
+ ranges = new DoubleDoublePair[dim];
+ }
+ updateSelectionRectKoordinates(x1, x2, y1, y2, ranges);
+
+ selection.clear();
+ boolean idIn = true;
+ for(DBID id : relation.iterDBIDs()) {
+ NumberVector<?, ?> dbTupel = relation.get(id);
+ idIn = true;
+ for(int i = 0; i < dim; i++) {
+ if(ranges != null && ranges[i] != null) {
+ if(dbTupel.doubleValue(i + 1) < ranges[i].first || dbTupel.doubleValue(i + 1) > ranges[i].second) {
+ idIn = false;
+ break;
+ }
+ }
+ }
+ if(idIn == true) {
+ selection.add(id);
+ }
+ }
+ context.setSelection(new RangeSelection(selection, ranges));
+ }
+ }
+
+ /**
+ * Adds the required CSS-Classes
+ *
+ * @param svgp SVG-Plot
+ */
+ protected void addCSSClasses(SVGPlot svgp) {
+ // Class for the range marking
+ if(!svgp.getCSSClassManager().contains(CSS_RANGEMARKER)) {
+ final CSSClass rcls = new CSSClass(this, CSS_RANGEMARKER);
+ final StyleLibrary style = context.getStyleLibrary();
+ rcls.setStatement(SVGConstants.CSS_FILL_PROPERTY, style.getColor(StyleLibrary.SELECTION_ACTIVE));
+ rcls.setStatement(SVGConstants.CSS_OPACITY_PROPERTY, style.getOpacity(StyleLibrary.SELECTION_ACTIVE));
+ svgp.addCSSClassOrLogError(rcls);
+ }
+ }
+
+ /**
+ * Factory for tool visualizations for selecting ranges and the inclosed
+ * objects
+ *
+ * @author Robert Rödler
+ *
+ * @apiviz.stereotype factory
+ * @apiviz.uses SelectionToolAxisRangeVisualization oneway - - «create»
+ */
+ public static class Factory extends AbstractVisFactory {
+ /**
+ * Constructor, adhering to
+ * {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable}
+ */
+ public Factory() {
+ super();
+ }
+
+ @Override
+ public Visualization makeVisualization(VisualizationTask task) {
+ return new SelectionToolAxisRangeVisualization(task);
+ }
+
+ @Override
+ public void processNewResult(HierarchicalResult baseResult, Result result) {
+ final ArrayList<SelectionResult> selectionResults = ResultUtil.filterResults(result, SelectionResult.class);
+ for(SelectionResult selres : selectionResults) {
+ IterableIterator<ParallelPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ParallelPlotProjector.class);
+ for(ParallelPlotProjector<?> p : ps) {
+ final VisualizationTask task = new VisualizationTask(NAME, selres, p.getRelation(), this);
+ task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_INTERACTIVE);
+ task.put(VisualizationTask.META_TOOL, true);
+ task.put(VisualizationTask.META_NOTHUMB, true);
+ task.put(VisualizationTask.META_NOEXPORT, true);
+ task.put(VisualizationTask.META_VISIBLE_DEFAULT, false);
+ baseResult.getHierarchy().add(selres, task);
+ baseResult.getHierarchy().add(p, task);
+ }
+ }
+ }
+ }
+}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/selection/SelectionToolLineVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/selection/SelectionToolLineVisualization.java
new file mode 100644
index 00000000..966e754a
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/selection/SelectionToolLineVisualization.java
@@ -0,0 +1,331 @@
+package de.lmu.ifi.dbs.elki.visualization.visualizers.parallel.selection;
+
+/*
+ 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 java.awt.geom.Line2D;
+import java.util.ArrayList;
+
+import org.apache.batik.dom.events.DOMMouseEvent;
+import org.apache.batik.util.SVGConstants;
+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.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.HashSetModifiableDBIDs;
+import de.lmu.ifi.dbs.elki.result.DBIDSelection;
+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.SelectionResult;
+import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
+import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
+import de.lmu.ifi.dbs.elki.visualization.batikutil.DragableArea;
+import de.lmu.ifi.dbs.elki.visualization.css.CSSClass;
+import de.lmu.ifi.dbs.elki.visualization.projector.ParallelPlotProjector;
+import de.lmu.ifi.dbs.elki.visualization.style.StyleLibrary;
+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.parallel.AbstractParallelVisualization;
+
+/**
+ * Tool-Visualization for the tool to select objects
+ *
+ * @author Robert Rödler
+ *
+ * @apiviz.has SelectionResult oneway - - updates
+ * @apiviz.has DBIDSelection oneway - - updates
+ */
+public class SelectionToolLineVisualization extends AbstractParallelVisualization<NumberVector<?, ?>> implements DragableArea.DragListener {
+ /**
+ * A short name characterizing this Visualizer.
+ */
+ private static final String NAME = "Object Selection";
+
+ /**
+ * CSS class of the selection rectangle while selecting.
+ */
+ private static final String CSS_RANGEMARKER = "selectionRangeMarker";
+
+ /**
+ * Input modes
+ *
+ * @apiviz.exclude
+ */
+ private enum Mode {
+ REPLACE, ADD, INVERT
+ }
+
+ /**
+ * Element for selection rectangle
+ */
+ Element rtag;
+
+ /**
+ * Element for the rectangle to add listeners
+ */
+ Element etag;
+
+ /**
+ * Constructor.
+ *
+ * @param task Task
+ */
+ public SelectionToolLineVisualization(VisualizationTask task) {
+ super(task);
+ incrementalRedraw();
+ }
+
+ @Override
+ protected void redraw() {
+ addCSSClasses(svgp);
+
+ rtag = svgp.svgElement(SVGConstants.SVG_G_TAG);
+ SVGUtil.addCSSClass(rtag, CSS_RANGEMARKER);
+ layer.appendChild(rtag);
+
+ // etag: sensitive area
+ DragableArea drag = new DragableArea(svgp, -.1 * getMarginLeft(), -.5 * getMarginTop(), getSizeX() + .2 * getMarginLeft(), getMarginTop() * 1.5 + getSizeY(), this);
+ etag = drag.getElement();
+ layer.appendChild(etag);
+ }
+
+ /**
+ * Delete the children of the element
+ *
+ * @param container SVG-Element
+ */
+ private void deleteChildren(Element container) {
+ while(container.hasChildNodes()) {
+ container.removeChild(container.getLastChild());
+ }
+ }
+
+ @Override
+ public boolean startDrag(SVGPoint startPoint, Event evt) {
+ return true;
+ }
+
+ @Override
+ public boolean duringDrag(SVGPoint startPoint, SVGPoint dragPoint, Event evt, boolean inside) {
+ deleteChildren(rtag);
+ double x = Math.min(startPoint.getX(), dragPoint.getX());
+ double y = Math.min(startPoint.getY(), dragPoint.getY());
+ double width = Math.abs(startPoint.getX() - dragPoint.getX());
+ double height = Math.abs(startPoint.getY() - dragPoint.getY());
+ rtag.appendChild(svgp.svgRect(x, y, width, height));
+ return true;
+ }
+
+ @Override
+ public boolean endDrag(SVGPoint startPoint, SVGPoint dragPoint, Event evt, boolean inside) {
+ Mode mode = getInputMode(evt);
+ deleteChildren(rtag);
+ if(startPoint.getX() != dragPoint.getX() || startPoint.getY() != dragPoint.getY()) {
+ updateSelection(mode, startPoint, dragPoint);
+ }
+ return true;
+ }
+
+ /**
+ * Get the current input mode, on each mouse event.
+ *
+ * @param evt Mouse event.
+ * @return current input mode
+ */
+ private Mode getInputMode(Event evt) {
+ if(evt instanceof DOMMouseEvent) {
+ DOMMouseEvent domme = (DOMMouseEvent) evt;
+ // TODO: visual indication of mode possible?
+ if(domme.getShiftKey()) {
+ return Mode.ADD;
+ }
+ else if(domme.getCtrlKey()) {
+ return Mode.INVERT;
+ }
+ else {
+ return Mode.REPLACE;
+ }
+ }
+ // Default mode is replace.
+ return Mode.REPLACE;
+ }
+
+ /**
+ * Updates the selection in the context.<br>
+ *
+ * @param mode Input mode
+ * @param p1 first point of the selected rectangle
+ * @param p2 second point of the selected rectangle
+ */
+ private void updateSelection(Mode mode, SVGPoint p1, SVGPoint p2) {
+ DBIDSelection selContext = context.getSelection();
+ // Note: we rely on SET semantics below!
+ final HashSetModifiableDBIDs selection;
+ if(selContext == null || mode == Mode.REPLACE) {
+ selection = DBIDUtil.newHashSet();
+ }
+ else {
+ selection = DBIDUtil.newHashSet(selContext.getSelectedIds());
+ }
+ int[] axisrange = getAxisRange(Math.min(p1.getX(), p2.getX()), Math.max(p1.getX(), p2.getX()));
+ DBIDs objIds = ResultUtil.getSamplingResult(relation).getSample();
+ for(DBID objId : objIds){
+ double[] yPos = proj.fastProjectDataToRenderSpace(relation.get(objId));
+ if(checkSelected(axisrange, yPos, Math.max(p1.getX(), p2.getX()), Math.min(p1.getX(), p2.getX()), Math.max(p1.getY(), p2.getY()), Math.min(p1.getY(), p2.getY()))) {
+ if(mode == Mode.INVERT) {
+ if(!selection.contains(objId)) {
+ selection.add(objId);
+ }
+ else {
+ selection.remove(objId);
+ }
+ }
+ else {
+ // In REPLACE and ADD, add objects.
+ // The difference was done before by not re-using the selection.
+ // Since we are using a set, we can just add in any case.
+ selection.add(objId);
+ }
+ }
+ }
+ context.setSelection(new DBIDSelection(selection));
+ }
+
+ private int[] getAxisRange(double x1, double x2) {
+ final int dim = proj.getVisibleDimensions();
+ int minaxis = 0;
+ int maxaxis = 0;
+ boolean minx = true;
+ boolean maxx = false;
+ int count = -1;
+ for(int i = 0; i < dim; i++) {
+ if(minx && getVisibleAxisX(i) > x1) {
+ minaxis = count;
+ minx = false;
+ maxx = true;
+ }
+ if(maxx && (getVisibleAxisX(i) > x2 || i == dim - 1)) {
+ maxaxis = count + 1;
+ if(i == dim - 1 && getVisibleAxisX(i) <= x2) {
+ maxaxis++;
+ }
+ break;
+ }
+ count = i;
+ }
+ return new int[] { minaxis, maxaxis };
+ }
+
+ private boolean checkSelected(int[] ar, double[] yPos, double x1, double x2, double y1, double y2) {
+ final int dim = proj.getVisibleDimensions();
+ if (ar[0] < 0) {
+ ar[0] = 0;
+ }
+ if(ar[1] >= dim) {
+ ar[1] = dim - 1;
+ }
+ for(int i = ar[0] + 1; i <= ar[1] - 1; i++) {
+ if(yPos[i] <= y1 && yPos[i] >= y2) {
+ return true;
+ }
+ }
+ Line2D.Double idline1 = new Line2D.Double(getVisibleAxisX(ar[0]), yPos[ar[0]], getVisibleAxisX(ar[0] + 1), yPos[ar[0] + 1]);
+ Line2D.Double idline2 = new Line2D.Double(getVisibleAxisX(ar[1] - 1), yPos[ar[1] - 1], getVisibleAxisX(ar[1]), yPos[ar[1]]);
+ Line2D.Double rectline1 = new Line2D.Double(x2, y1, x1, y1);
+ Line2D.Double rectline2 = new Line2D.Double(x2, y1, x2, y2);
+ Line2D.Double rectline3 = new Line2D.Double(x2, y2, x1, y2);
+ if(idline1.intersectsLine(rectline1) || idline1.intersectsLine(rectline2) || idline1.intersectsLine(rectline3)) {
+ return true;
+ }
+ Line2D.Double rectline4 = new Line2D.Double(x1, y1, x1, y2);
+ if(idline2.intersectsLine(rectline1) || idline2.intersectsLine(rectline4) || idline2.intersectsLine(rectline3)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Adds the required CSS-Classes
+ *
+ * @param svgp SVG-Plot
+ */
+ protected void addCSSClasses(SVGPlot svgp) {
+ // Class for the range marking
+ if(!svgp.getCSSClassManager().contains(CSS_RANGEMARKER)) {
+ final CSSClass rcls = new CSSClass(this, CSS_RANGEMARKER);
+ final StyleLibrary style = context.getStyleLibrary();
+ rcls.setStatement(SVGConstants.CSS_FILL_PROPERTY, style.getColor(StyleLibrary.SELECTION_ACTIVE));
+ rcls.setStatement(SVGConstants.CSS_OPACITY_PROPERTY, style.getOpacity(StyleLibrary.SELECTION_ACTIVE));
+ svgp.addCSSClassOrLogError(rcls);
+ }
+ }
+
+ /**
+ * Factory for tool visualizations for selecting objects
+ *
+ * @author Robert Rödler
+ *
+ * @apiviz.stereotype factory
+ * @apiviz.uses SelectionToolLineVisualization - - «create»
+ *
+ */
+ public static class Factory extends AbstractVisFactory {
+ /**
+ * Constructor, adhering to
+ * {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable}
+ */
+ public Factory() {
+ super();
+ }
+
+ @Override
+ public Visualization makeVisualization(VisualizationTask task) {
+ return new SelectionToolLineVisualization(task);
+ }
+
+ @Override
+ public void processNewResult(HierarchicalResult baseResult, Result result) {
+ final ArrayList<SelectionResult> selectionResults = ResultUtil.filterResults(result, SelectionResult.class);
+ for(SelectionResult selres : selectionResults) {
+ IterableIterator<ParallelPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ParallelPlotProjector.class);
+ for(ParallelPlotProjector<?> p : ps) {
+ final VisualizationTask task = new VisualizationTask(NAME, selres, p.getRelation(), this);
+ task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_INTERACTIVE);
+ task.put(VisualizationTask.META_TOOL, true);
+ task.put(VisualizationTask.META_NOTHUMB, true);
+ task.put(VisualizationTask.META_NOEXPORT, true);
+ task.put(VisualizationTask.META_VISIBLE_DEFAULT, false);
+ baseResult.getHierarchy().add(selres, task);
+ baseResult.getHierarchy().add(p, task);
+ }
+ }
+ }
+ }
+}
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
new file mode 100644
index 00000000..e4589b05
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/parallel/selection/package-info.java
@@ -0,0 +1,26 @@
+/**
+ * <p>Visualizers for object selection based on parallel projections.</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.visualization.visualizers.parallel.selection; \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/P2DVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/AbstractScatterplotVisualization.java
index b6b4b418..cce9ea5d 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/P2DVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/AbstractScatterplotVisualization.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
+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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,7 +28,11 @@ import org.w3c.dom.Element;
import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
+import de.lmu.ifi.dbs.elki.result.Result;
+import de.lmu.ifi.dbs.elki.result.ResultUtil;
+import de.lmu.ifi.dbs.elki.result.SamplingResult;
import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
+import de.lmu.ifi.dbs.elki.visualization.projections.CanvasSize;
import de.lmu.ifi.dbs.elki.visualization.projections.Projection2D;
import de.lmu.ifi.dbs.elki.visualization.style.StyleLibrary;
import de.lmu.ifi.dbs.elki.visualization.svg.SVGPlot;
@@ -43,7 +47,7 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.AbstractVisualization;
* @apiviz.landmark
* @apiviz.has Projection2D
*/
-public abstract class P2DVisualization<NV extends NumberVector<?, ?>> extends AbstractVisualization {
+public abstract class AbstractScatterplotVisualization extends AbstractVisualization {
/**
* The current projection
*/
@@ -52,17 +56,23 @@ public abstract class P2DVisualization<NV extends NumberVector<?, ?>> extends Ab
/**
* The representation we visualize
*/
- final protected Relation<NV> rel;
+ final protected Relation<? extends NumberVector<?, ?>> rel;
+
+ /**
+ * The DBID sample
+ */
+ final protected SamplingResult sample;
/**
* Constructor.
*
* @param task Visualization task
*/
- public P2DVisualization(VisualizationTask task) {
+ public AbstractScatterplotVisualization(VisualizationTask task) {
super(task);
this.proj = task.getProj();
this.rel = task.getRelation();
+ this.sample = ResultUtil.getSamplingResult(rel);
final double margin = context.getStyleLibrary().getSize(StyleLibrary.MARGIN);
this.layer = setupCanvas(svgp, proj, margin, task.getWidth(), task.getHeight());
}
@@ -78,8 +88,21 @@ public abstract class P2DVisualization<NV extends NumberVector<?, ?>> extends Ab
* @return wrapper element with appropriate view box.
*/
public static Element setupCanvas(SVGPlot svgp, Projection2D proj, double margin, double width, double height) {
- Element layer = SVGUtil.svgElement(svgp.getDocument(), SVGConstants.SVG_G_TAG);
- SVGUtil.setAtt(layer, SVGConstants.SVG_TRANSFORM_ATTRIBUTE, proj.estimateTransformString(margin, width, height));
+ final CanvasSize canvas = proj.estimateViewport();
+ final double sizex = canvas.getDiffX();
+ final double sizey = canvas.getDiffY();
+ String transform = SVGUtil.makeMarginTransform(width, height, sizex, sizey, margin) + " translate(" + SVGUtil.fmt(sizex / 2) + " " + SVGUtil.fmt(sizey / 2) + ")";
+
+ final Element layer = SVGUtil.svgElement(svgp.getDocument(), SVGConstants.SVG_G_TAG);
+ SVGUtil.setAtt(layer, SVGConstants.SVG_TRANSFORM_ATTRIBUTE, transform);
return layer;
}
+
+ @Override
+ public void resultChanged(Result current) {
+ super.resultChanged(current);
+ if(current == proj) {
+ synchronizedRedraw();
+ }
+ }
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/AbstractTooltipVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/AbstractTooltipVisualization.java
index 4e0171ae..8ce6ad67 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/AbstractTooltipVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/AbstractTooltipVisualization.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
+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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -30,11 +30,10 @@ import org.w3c.dom.events.Event;
import org.w3c.dom.events.EventListener;
import org.w3c.dom.events.EventTarget;
-import de.lmu.ifi.dbs.elki.data.NumberVector;
-import de.lmu.ifi.dbs.elki.database.datastore.DataStoreEvent;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreListener;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
+import de.lmu.ifi.dbs.elki.result.Result;
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;
@@ -44,11 +43,9 @@ import de.lmu.ifi.dbs.elki.visualization.svg.SVGUtil;
* General base class for a tooltip visualizer.
*
* @author Erich Schubert
- *
- * @param <NV> Number Vector
*/
// TODO: can we improve performance by not adding as many hovers?
-public abstract class AbstractTooltipVisualization<NV extends NumberVector<NV, ?>> extends P2DVisualization<NV> implements DataStoreListener {
+public abstract class AbstractTooltipVisualization extends AbstractScatterplotVisualization implements DataStoreListener {
/**
* Generic tag to indicate the type of element. Used in IDs, CSS-Classes etc.
*/
@@ -69,6 +66,21 @@ public abstract class AbstractTooltipVisualization<NV extends NumberVector<NV, ?
*/
public static final String TOOLTIP_AREA = "tooltip_area";
+ /**
+ * Our event listener.
+ */
+ EventListener hoverer = new EventListener() {
+ @Override
+ public void handleEvent(Event evt) {
+ handleHoverEvent(evt);
+ }
+ };
+
+ /**
+ * Constructor.
+ *
+ * @param task Visualization task
+ */
public AbstractTooltipVisualization(VisualizationTask task) {
super(task);
context.addDataStoreListener(this);
@@ -84,22 +96,15 @@ public abstract class AbstractTooltipVisualization<NV extends NumberVector<NV, ?
public void redraw() {
setupCSS(svgp);
- double dotsize = 2 * context.getStyleLibrary().getLineWidth(StyleLibrary.PLOT);
+ double dotsize = context.getStyleLibrary().getLineWidth(StyleLibrary.PLOT);
- EventListener hoverer = new EventListener() {
- @Override
- public void handleEvent(Event evt) {
- handleHoverEvent(evt);
- }
- };
-
- for(DBID id : rel.iterDBIDs()) {
+ for(DBID id : sample.getSample()) {
double[] v = proj.fastProjectDataToRenderSpace(rel.get(id));
Element tooltip = makeTooltip(id, v[0], v[1], dotsize);
SVGUtil.addCSSClass(tooltip, TOOLTIP_HIDDEN);
// sensitive area.
- Element area = svgp.svgCircle(v[0], v[1], dotsize);
+ Element area = svgp.svgRect(v[0] - dotsize, v[1] - dotsize, 2 * dotsize, 2 * dotsize);
SVGUtil.addCSSClass(area, TOOLTIP_AREA);
EventTarget targ = (EventTarget) area;
@@ -172,7 +177,9 @@ public abstract class AbstractTooltipVisualization<NV extends NumberVector<NV, ?
abstract protected void setupCSS(SVGPlot svgp);
@Override
- public void contentChanged(DataStoreEvent e) {
- synchronizedRedraw();
+ public void resultChanged(Result current) {
+ if(sample == current) {
+ synchronizedRedraw();
+ }
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/AxisVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/AxisVisualization.java
index 4dc7e820..a8f7fdca 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/AxisVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/AxisVisualization.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
+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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,18 +23,14 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.Iterator;
-
import org.apache.batik.util.SVGConstants;
import org.w3c.dom.Element;
-import de.lmu.ifi.dbs.elki.data.NumberVector;
-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.DatabaseUtil;
-import de.lmu.ifi.dbs.elki.utilities.iterator.IterableUtil;
+import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
import de.lmu.ifi.dbs.elki.visualization.css.CSSClass;
import de.lmu.ifi.dbs.elki.visualization.css.CSSClassManager.CSSNamingConflict;
@@ -52,10 +48,8 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.Visualization;
* @author Remigius Wojdanowski
*
* @apiviz.uses SVGSimpleLinearAxis
- *
- * @param <NV> Type of the DatabaseObject being visualized.
*/
-public class AxisVisualization<NV extends NumberVector<NV, ?>> extends P2DVisualization<NV> {
+public class AxisVisualization extends AbstractScatterplotVisualization {
/**
* Constructor.
*
@@ -71,28 +65,28 @@ public class AxisVisualization<NV extends NumberVector<NV, ?>> extends P2DVisual
int dim = DatabaseUtil.dimensionality(rel);
// origin
- double[] orig = proj.fastProjectScaledToRender(new Vector(dim));
+ double[] orig = proj.fastProjectScaledToRenderSpace(new double[dim]);
// diagonal point opposite to origin
double[] diag = new double[dim];
for(int d2 = 0; d2 < dim; d2++) {
diag[d2] = 1;
}
- diag = proj.fastProjectScaledToRender(new Vector(diag));
+ diag = proj.fastProjectScaledToRenderSpace(diag);
// compute angle to diagonal line, used for axis labeling.
double diaga = Math.atan2(diag[1] - orig[1], diag[0] - orig[0]);
- double alfontsize = 1.2 * context.getStyleLibrary().getTextSize(StyleLibrary.AXIS_LABEL);
- CSSClass alcls = new CSSClass(svgp, "unmanaged");
+ double alfontsize = 1.1 * context.getStyleLibrary().getTextSize(StyleLibrary.AXIS_LABEL);
+ CSSClass alcls = new CSSClass(AxisVisualization.class, "unmanaged");
alcls.setStatement(SVGConstants.CSS_FONT_SIZE_PROPERTY, SVGUtil.fmt(alfontsize));
alcls.setStatement(SVGConstants.CSS_FILL_PROPERTY, context.getStyleLibrary().getTextColor(StyleLibrary.AXIS_LABEL));
alcls.setStatement(SVGConstants.CSS_FONT_FAMILY_PROPERTY, context.getStyleLibrary().getFontFamily(StyleLibrary.AXIS_LABEL));
// draw axes
for(int d = 0; d < dim; d++) {
- Vector v = new Vector(dim);
- v.set(d, 1);
+ double[] v = new double[dim];
+ v[d] = 1;
// projected endpoint of axis
- double[] ax = proj.fastProjectScaledToRender(v);
+ double[] ax = proj.fastProjectScaledToRenderSpace(v);
boolean righthand = false;
double axa = Math.atan2(ax[1] - orig[1], ax[0] - orig[0]);
if(axa > diaga || (diaga > 0 && axa > diaga + Math.PI)) {
@@ -102,7 +96,7 @@ public class AxisVisualization<NV extends NumberVector<NV, ?>> extends P2DVisual
// " "+(axa*180/Math.PI)+" "+(diaga*180/Math.PI));
if(ax[0] != orig[0] || ax[1] != orig[1]) {
try {
- SVGSimpleLinearAxis.drawAxis(svgp, layer, proj.getScale(d), orig[0], orig[1], ax[0], ax[1], true, righthand, context.getStyleLibrary());
+ SVGSimpleLinearAxis.drawAxis(svgp, layer, proj.getScale(d), orig[0], orig[1], ax[0], ax[1], righthand ? SVGSimpleLinearAxis.LabelStyle.RIGHTHAND : SVGSimpleLinearAxis.LabelStyle.LEFTHAND, context.getStyleLibrary());
// TODO: move axis labeling into drawAxis function.
double offx = (righthand ? 1 : -1) * 0.02 * Projection.SCALE;
double offy = (righthand ? 1 : -1) * 0.02 * Projection.SCALE;
@@ -125,10 +119,8 @@ public class AxisVisualization<NV extends NumberVector<NV, ?>> extends P2DVisual
*
* @apiviz.stereotype factory
* @apiviz.uses AxisVisualization oneway - - «create»
- *
- * @param <NV>
*/
- public static class Factory<NV extends NumberVector<NV, ?>> extends AbstractVisFactory {
+ public static class Factory extends AbstractVisFactory {
/**
* A short name characterizing this Visualizer.
*/
@@ -144,13 +136,13 @@ public class AxisVisualization<NV extends NumberVector<NV, ?>> extends P2DVisual
@Override
public Visualization makeVisualization(VisualizationTask task) {
- return new AxisVisualization<NV>(task);
+ return new AxisVisualization(task);
}
@Override
public void processNewResult(HierarchicalResult baseResult, Result result) {
- Iterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(result, ScatterPlotProjector.class);
- for(ScatterPlotProjector<?> p : IterableUtil.fromIterator(ps)) {
+ IterableIterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(result, ScatterPlotProjector.class);
+ for(ScatterPlotProjector<?> p : ps) {
final VisualizationTask task = new VisualizationTask(NAME, p, p.getRelation(), this);
task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_BACKGROUND);
baseResult.getHierarchy().add(p, task);
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
new file mode 100644
index 00000000..7672ee93
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/MarkerVisualization.java
@@ -0,0 +1,175 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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 org.apache.batik.util.SVGConstants;
+import org.w3c.dom.Element;
+
+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.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.exceptions.ObjectNotFoundException;
+import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
+import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
+import de.lmu.ifi.dbs.elki.visualization.projector.ScatterPlotProjector;
+import de.lmu.ifi.dbs.elki.visualization.style.ClassStylingPolicy;
+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.style.marker.MarkerLibrary;
+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.thumbs.ThumbnailVisualization;
+
+/**
+ * Visualize e.g. a clustering using different markers for different clusters.
+ * This visualizer is not constraint to clusters. It can in fact visualize any
+ * kind of result we have a style source for.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.uses StyleResult
+ */
+public class MarkerVisualization extends AbstractScatterplotVisualization implements DataStoreListener {
+ /**
+ * Generic tag to indicate the type of element. Used in IDs, CSS-Classes etc.
+ */
+ public static final String DOTMARKER = "dot";
+
+ /**
+ * The result we visualize
+ */
+ private StyleResult style;
+
+ /**
+ * Constructor.
+ *
+ * @param task Visualization task
+ */
+ public MarkerVisualization(VisualizationTask task) {
+ super(task);
+ this.style = task.getResult();
+ context.addDataStoreListener(this);
+ context.addResultListener(this);
+ incrementalRedraw();
+ }
+
+ @Override
+ public void destroy() {
+ super.destroy();
+ context.removeDataStoreListener(this);
+ context.removeResultListener(this);
+ }
+
+ @Override
+ public void redraw() {
+ final MarkerLibrary ml = context.getStyleLibrary().markers();
+ final double marker_size = context.getStyleLibrary().getSize(StyleLibrary.MARKERPLOT);
+ final StylingPolicy spol = style.getStylingPolicy();
+
+ if(spol instanceof ClassStylingPolicy) {
+ ClassStylingPolicy cspol = (ClassStylingPolicy) spol;
+ for(int cnum = cspol.getMinStyle(); cnum < cspol.getMaxStyle(); cnum++) {
+ for(Iterator<DBID> iter = cspol.iterateClass(cnum); iter.hasNext();) {
+ DBID cur = iter.next();
+ try {
+ final NumberVector<?, ?> vec = rel.get(cur);
+ double[] v = proj.fastProjectDataToRenderSpace(vec);
+ ml.useMarker(svgp, layer, v[0], v[1], cnum, marker_size);
+ }
+ catch(ObjectNotFoundException e) {
+ // ignore.
+ }
+ }
+ }
+ }
+ else {
+ final String FILL = SVGConstants.CSS_FILL_PROPERTY + ":";
+ // Color-based styling. Fall back to dots
+ for(DBID id : sample.getSample()) {
+ try {
+ double[] v = proj.fastProjectDataToRenderSpace(rel.get(id));
+ Element dot = svgp.svgCircle(v[0], v[1], marker_size);
+ SVGUtil.addCSSClass(dot, DOTMARKER);
+ int col = spol.getColorForDBID(id);
+ SVGUtil.setAtt(dot, SVGConstants.SVG_STYLE_ATTRIBUTE, FILL + SVGUtil.colorToString(col));
+ layer.appendChild(dot);
+ }
+ catch(ObjectNotFoundException e) {
+ // ignore.
+ }
+ }
+ }
+ }
+
+ /**
+ * Visualization factory
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.stereotype factory
+ * @apiviz.uses MarkerVisualization oneway - - «create»
+ */
+ public static class Factory extends AbstractVisFactory {
+ /**
+ * A short name characterizing this Visualizer.
+ */
+ private static final String NAME = "Markers";
+
+ /**
+ * Constructor, adhering to
+ * {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable}
+ */
+ public Factory() {
+ super();
+ thumbmask |= ThumbnailVisualization.ON_DATA | ThumbnailVisualization.ON_STYLE;
+ }
+
+ @Override
+ public Visualization makeVisualization(VisualizationTask task) {
+ return new MarkerVisualization(task);
+ }
+
+ @Override
+ public void processNewResult(HierarchicalResult baseResult, Result result) {
+ // Find a style result to visualize:
+ IterableIterator<StyleResult> styleres = ResultUtil.filteredResults(result, StyleResult.class);
+ for(StyleResult c : styleres) {
+ IterableIterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
+ for(ScatterPlotProjector<?> p : ps) {
+ final VisualizationTask task = new VisualizationTask(NAME, c, p.getRelation(), this);
+ task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_DATA);
+ baseResult.getHierarchy().add(c, task);
+ baseResult.getHierarchy().add(p, task);
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/PolygonVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/PolygonVisualization.java
index b0f18666..4dc78ecf 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/PolygonVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/PolygonVisualization.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
+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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,17 +24,13 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
*/
import java.util.ArrayList;
-import java.util.Iterator;
import org.apache.batik.util.SVGConstants;
import org.w3c.dom.Element;
-import de.lmu.ifi.dbs.elki.data.DoubleVector;
-import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.data.spatial.Polygon;
import de.lmu.ifi.dbs.elki.data.spatial.PolygonsObject;
import de.lmu.ifi.dbs.elki.data.type.TypeUtil;
-import de.lmu.ifi.dbs.elki.database.datastore.DataStoreEvent;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreListener;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
@@ -44,7 +40,7 @@ import de.lmu.ifi.dbs.elki.result.Result;
import de.lmu.ifi.dbs.elki.result.ResultUtil;
import de.lmu.ifi.dbs.elki.utilities.DatabaseUtil;
import de.lmu.ifi.dbs.elki.utilities.exceptions.ObjectNotFoundException;
-import de.lmu.ifi.dbs.elki.utilities.iterator.IterableUtil;
+import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
import de.lmu.ifi.dbs.elki.visualization.css.CSSClass;
import de.lmu.ifi.dbs.elki.visualization.projections.Projection2D;
@@ -62,7 +58,7 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.Visualization;
*
* @apiviz.has PolygonsObject - - visualizes
*/
-public class PolygonVisualization<V extends NumberVector<?, ?>> extends P2DVisualization<V> implements DataStoreListener {
+public class PolygonVisualization extends AbstractScatterplotVisualization implements DataStoreListener {
/**
* A short name characterizing this Visualizer.
*/
@@ -122,13 +118,13 @@ public class PolygonVisualization<V extends NumberVector<?, ?>> extends P2DVisua
SVGPath path = new SVGPath();
for(Polygon ppoly : poly.getPolygons()) {
Vector first = ppoly.get(0);
- double[] f = proj.fastProjectDataToRenderSpace(first);
+ double[] f = proj.fastProjectDataToRenderSpace(first.getArrayRef());
path.moveTo(f[0], f[1]);
for(Vector v : ppoly) {
if(v == first) {
continue;
}
- double[] p = proj.fastProjectDataToRenderSpace(v);
+ double[] p = proj.fastProjectDataToRenderSpace(v.getArrayRef());
path.drawTo(p[0], p[1]);
}
// close path.
@@ -144,11 +140,6 @@ public class PolygonVisualization<V extends NumberVector<?, ?>> extends P2DVisua
}
}
- @Override
- public void contentChanged(DataStoreEvent e) {
- synchronizedRedraw();
- }
-
/**
* The visualization factory
*
@@ -167,7 +158,7 @@ public class PolygonVisualization<V extends NumberVector<?, ?>> extends P2DVisua
@Override
public Visualization makeVisualization(VisualizationTask task) {
- return new PolygonVisualization<DoubleVector>(task);
+ return new PolygonVisualization(task);
}
@Override
@@ -176,8 +167,8 @@ public class PolygonVisualization<V extends NumberVector<?, ?>> extends P2DVisua
for(Relation<?> rel : results) {
if(TypeUtil.POLYGON_TYPE.isAssignableFromType(rel.getDataTypeInformation())) {
// Assume that a 2d projector is using the same coordinates as the polygons.
- Iterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
- for(ScatterPlotProjector<?> p : IterableUtil.fromIterator(ps)) {
+ IterableIterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
+ for(ScatterPlotProjector<?> p : ps) {
if(DatabaseUtil.dimensionality(p.getRelation()) == 2) {
final VisualizationTask task = new VisualizationTask(NAME, rel, p.getRelation(), this);
task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_DATA - 10);
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/ReferencePointsVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/ReferencePointsVisualization.java
index df1aac20..644fc96f 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/ReferencePointsVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/ReferencePointsVisualization.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
+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) 2011
+ Copyright (C) 2012
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.result.HierarchicalResult;
import de.lmu.ifi.dbs.elki.result.ReferencePointsResult;
import de.lmu.ifi.dbs.elki.result.Result;
import de.lmu.ifi.dbs.elki.result.ResultUtil;
-import de.lmu.ifi.dbs.elki.utilities.iterator.IterableUtil;
+import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
import de.lmu.ifi.dbs.elki.visualization.css.CSSClass;
import de.lmu.ifi.dbs.elki.visualization.projector.ScatterPlotProjector;
@@ -52,7 +52,7 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.Visualization;
* @apiviz.has ReferencePointsResult oneway - - visualizes
*/
// TODO: add a result listener for the reference points.
-public class ReferencePointsVisualization<NV extends NumberVector<NV, ?>> extends P2DVisualization<NV> {
+public class ReferencePointsVisualization extends AbstractScatterplotVisualization {
/**
* Generic tag to indicate the type of element. Used in IDs, CSS-Classes etc.
*/
@@ -66,7 +66,7 @@ public class ReferencePointsVisualization<NV extends NumberVector<NV, ?>> extend
/**
* Serves reference points.
*/
- protected ReferencePointsResult<NV> result;
+ protected ReferencePointsResult<? extends NumberVector<?, ?>> result;
/**
* Constructor.
@@ -82,11 +82,11 @@ public class ReferencePointsVisualization<NV extends NumberVector<NV, ?>> extend
@Override
public void redraw() {
setupCSS(svgp);
- Iterator<NV> iter = result.iterator();
+ Iterator<? extends NumberVector<?, ?>> iter = result.iterator();
final double dotsize = context.getStyleLibrary().getSize(StyleLibrary.REFERENCE_POINTS);
while(iter.hasNext()) {
- NV v = iter.next();
+ NumberVector<?, ?> v = iter.next();
double[] projected = proj.fastProjectDataToRenderSpace(v);
Element dot = svgp.svgCircle(projected[0], projected[1], dotsize);
SVGUtil.addCSSClass(dot, REFPOINT);
@@ -112,10 +112,8 @@ public class ReferencePointsVisualization<NV extends NumberVector<NV, ?>> extend
*
* @apiviz.stereotype factory
* @apiviz.uses ReferencePointsVisualization oneway - - «create»
- *
- * @param <NV> Type of the DatabaseObject being visualized.
*/
- public static class Factory<NV extends NumberVector<NV, ?>> extends AbstractVisFactory {
+ public static class Factory extends AbstractVisFactory {
/**
* Constructor, adhering to
* {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable}
@@ -126,10 +124,10 @@ public class ReferencePointsVisualization<NV extends NumberVector<NV, ?>> extend
@Override
public void processNewResult(HierarchicalResult baseResult, Result result) {
- Collection<ReferencePointsResult<NV>> rps = ResultUtil.filterResults(result, ReferencePointsResult.class);
- for(ReferencePointsResult<NV> rp : rps) {
- Iterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
- for(ScatterPlotProjector<?> p : IterableUtil.fromIterator(ps)) {
+ Collection<ReferencePointsResult<?>> rps = ResultUtil.filterResults(result, ReferencePointsResult.class);
+ for(ReferencePointsResult<?> rp : rps) {
+ IterableIterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
+ for(ScatterPlotProjector<?> p : ps) {
final VisualizationTask task = new VisualizationTask(NAME, rp, p.getRelation(), this);
task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_DATA);
baseResult.getHierarchy().add(rp, task);
@@ -140,7 +138,7 @@ public class ReferencePointsVisualization<NV extends NumberVector<NV, ?>> extend
@Override
public Visualization makeVisualization(VisualizationTask task) {
- return new ReferencePointsVisualization<NV>(task);
+ return new ReferencePointsVisualization(task);
}
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/ToolBox2DVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/ToolBox2DVisualization.java
index c2339fe2..7ec5f1ac 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/ToolBox2DVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/ToolBox2DVisualization.java
@@ -1,4 +1,4 @@
-package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
+package de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot;
/*
This file is part of ELKI:
@@ -24,7 +24,6 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
*/
import java.util.ArrayList;
-import java.util.Iterator;
import java.util.List;
import org.apache.batik.util.SVGConstants;
@@ -33,17 +32,15 @@ import org.w3c.dom.events.Event;
import org.w3c.dom.events.EventListener;
import org.w3c.dom.events.EventTarget;
-import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.logging.Logging;
-import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
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.iterator.IterableUtil;
-import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
+import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
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.projector.ScatterPlotProjector;
import de.lmu.ifi.dbs.elki.visualization.style.StyleLibrary;
import de.lmu.ifi.dbs.elki.visualization.svg.SVGPlot;
@@ -51,7 +48,6 @@ 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.VisualizerUtil;
-import de.lmu.ifi.dbs.elki.visualization.visualizers.events.ContextChangedEvent;
/**
* Renders a tool box on the left of the 2D visualization
@@ -59,10 +55,8 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.events.ContextChangedEvent;
* @author Heidi Kolb
*
* @apiviz.has VisualizationTask oneway - - visualizes
- *
- * @param <NV> Type of the NumberVector being visualized.
*/
-public class ToolBox2DVisualization<NV extends NumberVector<NV, ?>> extends P2DVisualization<NV> {
+public class ToolBox2DVisualization extends AbstractScatterplotVisualization {
/**
* A short name characterizing this Visualizer.
*/
@@ -101,17 +95,11 @@ public class ToolBox2DVisualization<NV extends NumberVector<NV, ?>> extends P2DV
public ToolBox2DVisualization(VisualizationTask task) {
super(task);
// TODO: which result do we best attach to?
- context.addContextChangeListener(this);
context.addResultListener(this);
incrementalRedraw();
}
@Override
- public void contextChanged(ContextChangedEvent e) {
- synchronizedRedraw();
- }
-
- @Override
protected void redraw() {
addCSSClasses(svgp);
container = svgp.svgElement(SVGConstants.SVG_G_TAG);
@@ -146,12 +134,12 @@ public class ToolBox2DVisualization<NV extends NumberVector<NV, ?>> extends P2DV
}
// calculate the position of the first tool
- Pair<DoubleMinMax, DoubleMinMax> pt = proj.estimateViewport();
- double x = pt.getFirst().getMin() - 0.17 * scale;
+ CanvasSize viewport = proj.estimateViewport();
+ double x = viewport.getMinX() - 0.17 * scale;
double width = 0.07 * scale;
double height = 0.06 * scale;
- double miny = pt.getSecond().getMin();
- double maxy = pt.getSecond().getMax();
+ double miny = viewport.getMinY();
+ double maxy = viewport.getMaxY();
double y = (miny + maxy) / 2 - (vis.size() * height * 1.4) / 2;
if(y < miny) {
logger.warning("Too many Tools");
@@ -248,7 +236,7 @@ public class ToolBox2DVisualization<NV extends NumberVector<NV, ?>> extends P2DV
if(VisualizerUtil.isVisible(tool)) {
context.setSelection(null);
}
- context.setVisualizationVisibility(tool, true);
+ VisualizerUtil.setVisible(context, tool, true);
}
@Override
@@ -288,10 +276,8 @@ public class ToolBox2DVisualization<NV extends NumberVector<NV, ?>> extends P2DV
*
* @apiviz.stereotype factory
* @apiviz.uses ToolBox2DVisualization oneway - - «create»
- *
- * @param <NV> Type of the NumberVector being visualized.
*/
- public static class Factory<NV extends NumberVector<NV, ?>> extends AbstractVisFactory {
+ public static class Factory extends AbstractVisFactory {
/**
* Constructor
*/
@@ -301,17 +287,18 @@ public class ToolBox2DVisualization<NV extends NumberVector<NV, ?>> extends P2DV
@Override
public Visualization makeVisualization(VisualizationTask task) {
- return new ToolBox2DVisualization<NV>(task);
+ return new ToolBox2DVisualization(task);
}
@Override
public void processNewResult(HierarchicalResult baseResult, Result result) {
- Iterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(result, ScatterPlotProjector.class);
- for(ScatterPlotProjector<?> p : IterableUtil.fromIterator(ps)) {
+ IterableIterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(result, ScatterPlotProjector.class);
+ for(ScatterPlotProjector<?> p : ps) {
final VisualizationTask task = new VisualizationTask(NAME, p, p.getRelation(), this);
task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_INTERACTIVE);
task.put(VisualizationTask.META_NOTHUMB, true);
task.put(VisualizationTask.META_NOEXPORT, true);
+ task.put(VisualizationTask.META_NOEMBED, true);
baseResult.getHierarchy().add(p, task);
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/TooltipScoreVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/TooltipScoreVisualization.java
index 309cc9c7..838390d0 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/TooltipScoreVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/TooltipScoreVisualization.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
+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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,21 +24,20 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
*/
import java.text.NumberFormat;
-import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import org.apache.batik.util.SVGConstants;
import org.w3c.dom.Element;
-import de.lmu.ifi.dbs.elki.data.NumberVector;
+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.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.ResultUtil;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
-import de.lmu.ifi.dbs.elki.utilities.iterator.IterableUtil;
+import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
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;
@@ -59,13 +58,18 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.Visualization;
*
* @author Remigius Wojdanowski
*/
-public class TooltipScoreVisualization<NV extends NumberVector<NV, ?>> extends AbstractTooltipVisualization<NV> {
+public class TooltipScoreVisualization extends AbstractTooltipVisualization {
/**
* A short name characterizing this Visualizer.
*/
public static final String NAME = "Outlier Score Tooltips";
/**
+ * A short name characterizing this Visualizer.
+ */
+ public static final String NAME_GEN = "Score Tooltips";
+
+ /**
* Number format.
*/
NumberFormat nf;
@@ -142,10 +146,8 @@ public class TooltipScoreVisualization<NV extends NumberVector<NV, ?>> extends A
*
* @apiviz.stereotype factory
* @apiviz.uses TooltipScoreVisualization oneway - - «create»
- *
- * @param <NV> Data type visualized.
*/
- public static class Factory<NV extends NumberVector<NV, ?>> extends AbstractVisFactory {
+ public static class Factory extends AbstractVisFactory {
/**
* Parameter for the gamma-correction.
*
@@ -178,7 +180,7 @@ public class TooltipScoreVisualization<NV extends NumberVector<NV, ?>> extends A
@Override
public Visualization makeVisualization(VisualizationTask task) {
- return new TooltipScoreVisualization<NV>(task, nf);
+ return new TooltipScoreVisualization(task, nf);
}
@Override
@@ -186,14 +188,39 @@ public class TooltipScoreVisualization<NV extends NumberVector<NV, ?>> extends A
// TODO: we can also visualize other scores!
List<OutlierResult> ors = ResultUtil.filterResults(result, OutlierResult.class);
for(OutlierResult o : ors) {
- Iterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
- for(ScatterPlotProjector<?> p : IterableUtil.fromIterator(ps)) {
+ IterableIterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
+ for(ScatterPlotProjector<?> p : ps) {
final VisualizationTask task = new VisualizationTask(NAME, o.getScores(), p.getRelation(), this);
task.put(VisualizationTask.META_TOOL, true);
+ task.put(VisualizationTask.META_VISIBLE_DEFAULT, false);
baseResult.getHierarchy().add(o.getScores(), task);
baseResult.getHierarchy().add(p, task);
}
}
+ List<Relation<?>> rrs = ResultUtil.filterResults(result, Relation.class);
+ for(Relation<?> r : rrs) {
+ if(!TypeUtil.DOUBLE.isAssignableFromType(r.getDataTypeInformation())) {
+ continue;
+ }
+ // 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 Factory) {
+ add = false;
+ break;
+ }
+ }
+ if(add) {
+ IterableIterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
+ for(ScatterPlotProjector<?> p : ps) {
+ final VisualizationTask task = new VisualizationTask(NAME_GEN, r, p.getRelation(), this);
+ task.put(VisualizationTask.META_TOOL, true);
+ task.put(VisualizationTask.META_VISIBLE_DEFAULT, false);
+ baseResult.getHierarchy().add(r, task);
+ baseResult.getHierarchy().add(p, task);
+ }
+ }
+ }
}
/**
@@ -203,7 +230,7 @@ public class TooltipScoreVisualization<NV extends NumberVector<NV, ?>> extends A
*
* @apiviz.exclude
*/
- public static class Parameterizer<NV extends NumberVector<NV, ?>> extends AbstractParameterizer {
+ public static class Parameterizer extends AbstractParameterizer {
protected int digits = 4;
@Override
@@ -217,8 +244,8 @@ public class TooltipScoreVisualization<NV extends NumberVector<NV, ?>> extends A
}
@Override
- protected Factory<NV> makeInstance() {
- return new Factory<NV>(digits);
+ protected Factory makeInstance() {
+ return new Factory(digits);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/TooltipStringVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/TooltipStringVisualization.java
index 044dc66f..9baea926 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/TooltipStringVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/TooltipStringVisualization.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
+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) 2011
+ Copyright (C) 2012
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.vis2d;
*/
import java.util.ArrayList;
-import java.util.Iterator;
import org.apache.batik.util.SVGConstants;
import org.w3c.dom.Element;
@@ -32,13 +31,12 @@ import org.w3c.dom.Element;
import de.lmu.ifi.dbs.elki.data.ClassLabel;
import de.lmu.ifi.dbs.elki.data.ExternalID;
import de.lmu.ifi.dbs.elki.data.LabelList;
-import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
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.ResultUtil;
-import de.lmu.ifi.dbs.elki.utilities.iterator.IterableUtil;
+import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
import de.lmu.ifi.dbs.elki.visualization.css.CSSClass;
import de.lmu.ifi.dbs.elki.visualization.projector.ScatterPlotProjector;
@@ -56,10 +54,8 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.Visualization;
* @author Erich Schubert
*
* @apiviz.has Relation oneway - - visualizes
- *
- * @param <NV> Data type visualized.
*/
-public class TooltipStringVisualization<NV extends NumberVector<NV, ?>> extends AbstractTooltipVisualization<NV> {
+public class TooltipStringVisualization extends AbstractTooltipVisualization {
/**
* A short name characterizing this Visualizer.
*/
@@ -161,10 +157,8 @@ public class TooltipStringVisualization<NV extends NumberVector<NV, ?>> extends
*
* @apiviz.stereotype factory
* @apiviz.uses TooltipStringVisualization oneway - - «create»
- *
- * @param <NV>
*/
- public static class Factory<NV extends NumberVector<NV, ?>> extends AbstractVisFactory {
+ public static class Factory extends AbstractVisFactory {
/**
* Constructor, adhering to
* {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable}
@@ -175,7 +169,7 @@ public class TooltipStringVisualization<NV extends NumberVector<NV, ?>> extends
@Override
public Visualization makeVisualization(VisualizationTask task) {
- return new TooltipStringVisualization<NV>(task);
+ return new TooltipStringVisualization(task);
}
@Override
@@ -183,37 +177,41 @@ public class TooltipStringVisualization<NV extends NumberVector<NV, ?>> extends
ArrayList<Relation<?>> reps = ResultUtil.filterResults(result, Relation.class);
for(Relation<?> rep : reps) {
if(DBID.class.isAssignableFrom(rep.getDataTypeInformation().getRestrictionClass())) {
- Iterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
- for(ScatterPlotProjector<?> p : IterableUtil.fromIterator(ps)) {
+ IterableIterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
+ for(ScatterPlotProjector<?> p : ps) {
final VisualizationTask task = new VisualizationTask(NAME_ID, rep, p.getRelation(), this);
task.put(VisualizationTask.META_TOOL, true);
+ task.put(VisualizationTask.META_VISIBLE_DEFAULT, false);
baseResult.getHierarchy().add(rep, task);
baseResult.getHierarchy().add(p, task);
}
}
if(ClassLabel.class.isAssignableFrom(rep.getDataTypeInformation().getRestrictionClass())) {
- Iterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
- for(ScatterPlotProjector<?> p : IterableUtil.fromIterator(ps)) {
+ IterableIterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
+ for(ScatterPlotProjector<?> p : ps) {
final VisualizationTask task = new VisualizationTask(NAME_CLASS, rep, p.getRelation(), this);
task.put(VisualizationTask.META_TOOL, true);
+ task.put(VisualizationTask.META_VISIBLE_DEFAULT, false);
baseResult.getHierarchy().add(rep, task);
baseResult.getHierarchy().add(p, task);
}
}
if(LabelList.class.isAssignableFrom(rep.getDataTypeInformation().getRestrictionClass())) {
- Iterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
- for(ScatterPlotProjector<?> p : IterableUtil.fromIterator(ps)) {
+ IterableIterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
+ for(ScatterPlotProjector<?> p : ps) {
final VisualizationTask task = new VisualizationTask(NAME_LABEL, rep, p.getRelation(), this);
task.put(VisualizationTask.META_TOOL, true);
+ task.put(VisualizationTask.META_VISIBLE_DEFAULT, false);
baseResult.getHierarchy().add(rep, task);
baseResult.getHierarchy().add(p, task);
}
}
if(ExternalID.class.isAssignableFrom(rep.getDataTypeInformation().getRestrictionClass())) {
- Iterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
- for(ScatterPlotProjector<?> p : IterableUtil.fromIterator(ps)) {
+ IterableIterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
+ for(ScatterPlotProjector<?> p : ps) {
final VisualizationTask task = new VisualizationTask(NAME_EID, rep, p.getRelation(), this);
task.put(VisualizationTask.META_TOOL, true);
+ task.put(VisualizationTask.META_VISIBLE_DEFAULT, false);
baseResult.getHierarchy().add(rep, task);
baseResult.getHierarchy().add(p, task);
}
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
new file mode 100644
index 00000000..430ab194
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/ClusterHullVisualization.java
@@ -0,0 +1,276 @@
+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) 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 java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+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.Model;
+import de.lmu.ifi.dbs.elki.data.spatial.Polygon;
+import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil;
+import de.lmu.ifi.dbs.elki.database.ids.DBID;
+import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
+import de.lmu.ifi.dbs.elki.math.geometry.AlphaShape;
+import de.lmu.ifi.dbs.elki.math.geometry.GrahamScanConvexHull2D;
+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.iterator.IterableIterator;
+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.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.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.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;
+
+/**
+ * Visualizer for generating an SVG-Element containing the convex hull / alpha
+ * shape of each cluster.
+ *
+ * @author Robert Rödler
+ * @author Erich Schubert
+ *
+ * @apiviz.has Clustering oneway - - visualizes
+ * @apiviz.uses ConvexHull2D
+ * @apiviz.uses AlphaShape
+ */
+public class ClusterHullVisualization extends AbstractScatterplotVisualization {
+ /**
+ * A short name characterizing this Visualizer.
+ */
+ private static final String NAME = "Cluster Hull Visualization";
+
+ /**
+ * Generic tags to indicate the type of element. Used in IDs, CSS-Classes etc.
+ */
+ public static final String CLUSTERHULL = "cluster-hull";
+
+ /**
+ * The result we work on
+ */
+ Clustering<Model> clustering;
+
+ /**
+ * Alpha value
+ */
+ double alpha = Double.POSITIVE_INFINITY;
+
+ /**
+ * Constructor
+ *
+ * @param task VisualizationTask
+ * @param alpha Alpha value
+ */
+ public ClusterHullVisualization(VisualizationTask task, double alpha) {
+ super(task);
+ this.clustering = task.getResult();
+ this.alpha = alpha;
+ incrementalRedraw();
+ }
+
+ @Override
+ protected void redraw() {
+ // 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();
+
+ if(alpha >= Double.POSITIVE_INFINITY) {
+ GrahamScanConvexHull2D hull = new GrahamScanConvexHull2D();
+
+ for(DBID clpnum : ids) {
+ double[] projP = proj.fastProjectDataToRenderSpace(rel.get(clpnum));
+ hull.add(new Vector(projP));
+ }
+ Polygon chres = hull.getHull();
+
+ // Plot the convex hull:
+ if(chres != null && chres.size() > 1) {
+ SVGPath path = new SVGPath(chres);
+ // 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);
+
+ Element hulls = path.makeElement(svgp);
+ addCSSClasses(svgp, cnum, opacity);
+ SVGUtil.addCSSClass(hulls, CLUSTERHULL + cnum);
+ layer.appendChild(hulls);
+ }
+ }
+ else {
+ ArrayList<Vector> ps = new ArrayList<Vector>(ids.size());
+ for(DBID clpnum : ids) {
+ double[] projP = proj.fastProjectDataToRenderSpace(rel.get(clpnum));
+ ps.add(new Vector(projP));
+ }
+ List<Polygon> polys = (new AlphaShape(ps, alpha * Projection.SCALE)).compute();
+ for(Polygon p : polys) {
+ SVGPath path = new SVGPath(p);
+ Element hulls = path.makeElement(svgp);
+ addCSSClasses(svgp, cnum, 0.5);
+ SVGUtil.addCSSClass(hulls, CLUSTERHULL + cnum);
+ layer.appendChild(hulls);
+ }
+ }
+ }
+ }
+
+ /**
+ * Adds the required CSS-Classes
+ *
+ * @param svgp SVG-Plot
+ */
+ private void addCSSClasses(SVGPlot svgp, int clusterID, double opac) {
+ ColorLibrary colors = context.getStyleLibrary().getColorSet(StyleLibrary.PLOT);
+
+ CSSClass cls = new CSSClass(this, CLUSTERHULL + clusterID);
+ cls.setStatement(SVGConstants.CSS_STROKE_WIDTH_PROPERTY, context.getStyleLibrary().getLineWidth(StyleLibrary.PLOT));
+
+ final String color;
+ if(clustering.getAllClusters().size() == 1) {
+ color = "black";
+ }
+ else {
+ 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);
+
+ svgp.addCSSClassOrLogError(cls);
+ }
+
+ /**
+ * Factory for visualizers to generate an SVG-Element containing the convex
+ * hull or alpha shape of a cluster.
+ *
+ * @author Robert Rödler
+ * @author Erich Schubert
+ *
+ * @apiviz.stereotype factory
+ * @apiviz.uses ClusterHullVisualization oneway - - «create»
+ */
+ public static class Factory extends AbstractVisFactory {
+ /**
+ * Alpha value
+ */
+ double alpha = Double.POSITIVE_INFINITY;
+
+ /**
+ * Constructor.
+ *
+ * @param alpha Alpha value
+ */
+ public Factory(double alpha) {
+ super();
+ this.alpha = alpha;
+ }
+
+ @Override
+ public Visualization makeVisualization(VisualizationTask task) {
+ return new ClusterHullVisualization(task, alpha);
+ }
+
+ @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) {
+ IterableIterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
+ for(ScatterPlotProjector<?> p : ps) {
+ final VisualizationTask task = new VisualizationTask(NAME, c, p.getRelation(), this);
+ task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_DATA - 1);
+ task.put(VisualizationTask.META_VISIBLE_DEFAULT, false);
+ baseResult.getHierarchy().add(c, task);
+ baseResult.getHierarchy().add(p, task);
+ }
+ }
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ /**
+ * Alpha-Value for alpha-shapes
+ *
+ * <p>
+ * Key: {@code -hull.alpha}
+ * </p>
+ */
+ public static final OptionID ALPHA_ID = OptionID.getOrCreateOptionID("hull.alpha", "Alpha value for hull drawing (in projected space!).");
+
+ /**
+ * Alpha value
+ */
+ double alpha = Double.POSITIVE_INFINITY;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ DoubleParameter alphaP = new DoubleParameter(ALPHA_ID, Double.POSITIVE_INFINITY);
+ if(config.grab(alphaP)) {
+ alpha = alphaP.getValue();
+ }
+ }
+
+ @Override
+ protected Factory makeInstance() {
+ return new Factory(alpha);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/ClusterMeanVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/ClusterMeanVisualization.java
index d1f1712d..c9443a9f 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/ClusterMeanVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/ClusterMeanVisualization.java
@@ -1,4 +1,4 @@
-package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
+package de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.cluster;
/*
This file is part of ELKI:
@@ -23,7 +23,6 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.Collection;
import java.util.Iterator;
import org.apache.batik.util.SVGConstants;
@@ -33,19 +32,26 @@ 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.DBID;
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.IterableUtil;
+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.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.projector.ScatterPlotProjector;
import de.lmu.ifi.dbs.elki.visualization.style.StyleLibrary;
import de.lmu.ifi.dbs.elki.visualization.style.marker.MarkerLibrary;
+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;
/**
* Visualize the mean of a KMeans-Clustering
@@ -53,10 +59,8 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.Visualization;
* @author Heidi Kolb
*
* @apiviz.has MeanModel oneway - - visualizes
- *
- * @param <NV> Type of the DatabaseObject being visualized.
*/
-public class ClusterMeanVisualization<NV extends NumberVector<NV, ?>> extends P2DVisualization<NV> {
+public class ClusterMeanVisualization extends AbstractScatterplotVisualization {
/**
* A short name characterizing this Visualizer.
*/
@@ -73,14 +77,30 @@ public class ClusterMeanVisualization<NV extends NumberVector<NV, ?>> extends P2
private final static String CSS_MEAN = "mean-marker";
/**
+ * CSS class name for center of the means
+ */
+ private final static String CSS_MEAN_STAR = "mean-star";
+
+ /**
* Clustering to visualize.
*/
- Clustering<MeanModel<NV>> clustering;
+ Clustering<MeanModel<? extends NumberVector<?, ?>>> clustering;
- public ClusterMeanVisualization(VisualizationTask task) {
+ /**
+ * Draw stars
+ */
+ boolean stars;
+
+ /**
+ * Constructor.
+ *
+ * @param task Visualization task
+ * @param stars Draw stars
+ */
+ public ClusterMeanVisualization(VisualizationTask task, boolean stars) {
super(task);
this.clustering = task.getResult();
- context.addContextChangeListener(this);
+ this.stars = stars;
incrementalRedraw();
}
@@ -91,9 +111,9 @@ public class ClusterMeanVisualization<NV extends NumberVector<NV, ?>> extends P2
MarkerLibrary ml = context.getStyleLibrary().markers();
double marker_size = context.getStyleLibrary().getSize(StyleLibrary.MARKERPLOT);
- Iterator<Cluster<MeanModel<NV>>> ci = clustering.getAllClusters().iterator();
- for(int cnum = 0; cnum < clustering.getAllClusters().size(); cnum++) {
- Cluster<MeanModel<NV>> clus = ci.next();
+ Iterator<Cluster<MeanModel<? extends NumberVector<?, ?>>>> ci = clustering.getAllClusters().iterator();
+ for(int cnum = 0; ci.hasNext(); cnum++) {
+ Cluster<MeanModel<? extends NumberVector<?, ?>>> clus = ci.next();
double[] mean = proj.fastProjectDataToRenderSpace(clus.getModel().getMean());
// add a greater Marker for the mean
@@ -108,6 +128,18 @@ public class ClusterMeanVisualization<NV extends NumberVector<NV, ?>> extends P2
layer.appendChild(meanMarkerCenter);
layer.appendChild(meanMarkerCenter2);
+
+ if(stars) {
+ SVGPath star = new SVGPath();
+ for(DBID id : clus.getIDs()) {
+ double[] obj = proj.fastProjectDataToRenderSpace(rel.get(id));
+ star.moveTo(mean);
+ star.drawTo(obj);
+ }
+ Element stare = star.makeElement(svgp);
+ SVGUtil.setCSSClass(stare, CSS_MEAN_STAR + "_" + cnum);
+ layer.appendChild(stare);
+ }
}
}
@@ -118,16 +150,31 @@ public class ClusterMeanVisualization<NV extends NumberVector<NV, ?>> extends P2
*/
private void addCSSClasses(SVGPlot svgp) {
if(!svgp.getCSSClassManager().contains(CSS_MEAN_CENTER)) {
- CSSClass center = new CSSClass(svgp, CSS_MEAN_CENTER);
+ CSSClass center = new CSSClass(this, CSS_MEAN_CENTER);
center.setStatement(SVGConstants.CSS_STROKE_PROPERTY, context.getStyleLibrary().getTextColor(StyleLibrary.DEFAULT));
center.setStatement(SVGConstants.CSS_STROKE_WIDTH_PROPERTY, context.getStyleLibrary().getLineWidth(StyleLibrary.AXIS_TICK) / 2);
svgp.addCSSClassOrLogError(center);
}
if(!svgp.getCSSClassManager().contains(CSS_MEAN)) {
- CSSClass center = new CSSClass(svgp, CSS_MEAN);
+ CSSClass center = new CSSClass(this, CSS_MEAN);
center.setStatement(SVGConstants.CSS_OPACITY_PROPERTY, "0.7");
svgp.addCSSClassOrLogError(center);
}
+ if(stars) {
+ ColorLibrary colors = context.getStyleLibrary().getColorSet(StyleLibrary.PLOT);
+
+ Iterator<Cluster<MeanModel<? extends NumberVector<?, ?>>>> ci = clustering.getAllClusters().iterator();
+ for(int cnum = 0; ci.hasNext(); cnum++) {
+ ci.next();
+ if(!svgp.getCSSClassManager().contains(CSS_MEAN_STAR + "_" + cnum)) {
+ CSSClass center = new CSSClass(this, CSS_MEAN_STAR + "_" + cnum);
+ center.setStatement(SVGConstants.CSS_STROKE_PROPERTY, colors.getColor(cnum));
+ center.setStatement(SVGConstants.CSS_STROKE_WIDTH_PROPERTY, context.getStyleLibrary().getLineWidth(StyleLibrary.PLOT));
+ center.setStatement(SVGConstants.CSS_OPACITY_PROPERTY, "0.7");
+ svgp.addCSSClassOrLogError(center);
+ }
+ }
+ }
}
/**
@@ -138,33 +185,50 @@ public class ClusterMeanVisualization<NV extends NumberVector<NV, ?>> extends P2
*
* @apiviz.stereotype factory
* @apiviz.uses ClusterMeanVisualization oneway - - «create»
- *
- * @param <NV> Type of the NumberVector being visualized.
*/
- public static class Factory<NV extends NumberVector<NV, ?>> extends AbstractVisFactory {
+ public static class Factory extends AbstractVisFactory {
/**
- * Constructor
+ * Option ID for visualization of cluster means.
+ *
+ * <pre>
+ * -cluster.stars
+ * </pre>
+ */
+ public static final OptionID STARS_ID = OptionID.getOrCreateOptionID("cluster.stars", "Visualize mean-based clusters using stars.");
+
+ /**
+ * Draw stars
+ */
+ private boolean stars;
+
+ /**
+ * Constructor.
+ *
+ * @param stars Draw stars
*/
- public Factory() {
+ public Factory(boolean stars) {
super();
+ this.stars = stars;
}
@Override
public Visualization makeVisualization(VisualizationTask task) {
- return new ClusterMeanVisualization<NV>(task);
+ return new ClusterMeanVisualization(task, stars);
}
@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) {
+ Iterator<Clustering<?>> clusterings = ResultUtil.filteredResults(result, Clustering.class);
+ while(clusterings.hasNext()) {
+ Clustering<?> c = clusterings.next();
if(c.getAllClusters().size() > 0) {
// Does the cluster have a model with cluster means?
- Clustering<MeanModel<NV>> mcls = findMeanModel(c);
+ Clustering<MeanModel<? extends NumberVector<?, ?>>> mcls = findMeanModel(c);
if(mcls != null) {
Iterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
- for(ScatterPlotProjector<?> p : IterableUtil.fromIterator(ps)) {
+ while(ps.hasNext()) {
+ ScatterPlotProjector<?> p = ps.next();
final VisualizationTask task = new VisualizationTask(NAME, c, p.getRelation(), this);
task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_DATA + 1);
baseResult.getHierarchy().add(c, task);
@@ -178,16 +242,40 @@ public class ClusterMeanVisualization<NV extends NumberVector<NV, ?>> extends P2
/**
* Test if the given clustering has a mean model.
*
- * @param <NV> Vector type
* @param c Clustering to inspect
* @return the clustering cast to return a mean model, null otherwise.
*/
@SuppressWarnings("unchecked")
- private static <NV extends NumberVector<NV, ?>> Clustering<MeanModel<NV>> findMeanModel(Clustering<?> c) {
+ private static Clustering<MeanModel<? extends NumberVector<?, ?>>> findMeanModel(Clustering<?> c) {
if(c.getAllClusters().get(0).getModel() instanceof MeanModel<?>) {
- return (Clustering<MeanModel<NV>>) c;
+ return (Clustering<MeanModel<? extends NumberVector<?, ?>>>) c;
}
return null;
}
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ protected boolean stars = false;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ Flag starsF = new Flag(STARS_ID);
+ if(config.grab(starsF)) {
+ stars = starsF.getValue();
+ }
+ }
+
+ @Override
+ protected Factory makeInstance() {
+ return new Factory(stars);
+ }
+ }
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/ClusterOrderVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/ClusterOrderVisualization.java
index f758ff99..1ac55851 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/ClusterOrderVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/ClusterOrderVisualization.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
+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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,12 +24,9 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
*/
import java.util.Collection;
-import java.util.Iterator;
import org.w3c.dom.Element;
-import de.lmu.ifi.dbs.elki.data.NumberVector;
-import de.lmu.ifi.dbs.elki.database.datastore.DataStoreEvent;
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.distancevalue.DoubleDistance;
@@ -38,7 +35,7 @@ import de.lmu.ifi.dbs.elki.result.Result;
import de.lmu.ifi.dbs.elki.result.ResultUtil;
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.iterator.IterableUtil;
+import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
import de.lmu.ifi.dbs.elki.visualization.css.CSSClass;
import de.lmu.ifi.dbs.elki.visualization.projector.ScatterPlotProjector;
@@ -46,6 +43,7 @@ import de.lmu.ifi.dbs.elki.visualization.style.StyleLibrary;
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;
/**
* Cluster order visualizer.
@@ -55,7 +53,7 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.Visualization;
* @apiviz.has ClusterOrderResult oneway - - visualizes
*/
// TODO: listen for CLUSTER ORDER changes.
-public class ClusterOrderVisualization<NV extends NumberVector<NV, ?>> extends P2DVisualization<NV> implements DataStoreListener {
+public class ClusterOrderVisualization extends AbstractScatterplotVisualization implements DataStoreListener {
/**
* A short name characterizing this Visualizer.
*/
@@ -99,6 +97,10 @@ public class ClusterOrderVisualization<NV extends NumberVector<NV, ?>> extends P
}
double[] thisVec = proj.fastProjectDataToRenderSpace(rel.get(thisId));
double[] prevVec = proj.fastProjectDataToRenderSpace(rel.get(prevId));
+
+ // FIXME: DO NOT COMMIT
+ thisVec[0] = thisVec[0] * 0.95 + prevVec[0] * 0.05;
+ thisVec[1] = thisVec[1] * 0.95 + prevVec[1] * 0.05;
Element arrow = svgp.svgLine(prevVec[0], prevVec[1], thisVec[0], thisVec[1]);
SVGUtil.setCSSClass(arrow, cls.getName());
@@ -107,11 +109,6 @@ public class ClusterOrderVisualization<NV extends NumberVector<NV, ?>> extends P
}
}
- @Override
- public void contentChanged(DataStoreEvent e) {
- synchronizedRedraw();
- }
-
/**
* Visualize an OPTICS cluster order by drawing connection lines.
*
@@ -119,10 +116,8 @@ public class ClusterOrderVisualization<NV extends NumberVector<NV, ?>> extends P
*
* @apiviz.stereotype factory
* @apiviz.uses ClusterOrderVisualization oneway - - «create»
- *
- * @param <NV> object type
*/
- public static class Factory<NV extends NumberVector<NV, ?>> extends AbstractVisFactory {
+ public static class Factory extends AbstractVisFactory {
/**
* Constructor, adhering to
* {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable}
@@ -133,15 +128,15 @@ public class ClusterOrderVisualization<NV extends NumberVector<NV, ?>> extends P
@Override
public Visualization makeVisualization(VisualizationTask task) {
- return new ClusterOrderVisualization<NV>(task);
+ return new ClusterOrderVisualization(task);
}
@Override
public void processNewResult(HierarchicalResult baseResult, Result result) {
Collection<ClusterOrderResult<DoubleDistance>> cos = ResultUtil.filterResults(result, ClusterOrderResult.class);
for(ClusterOrderResult<DoubleDistance> co : cos) {
- Iterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
- for(ScatterPlotProjector<?> p : IterableUtil.fromIterator(ps)) {
+ IterableIterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
+ for(ScatterPlotProjector<?> p : ps) {
final VisualizationTask task = new VisualizationTask(NAME, co, p.getRelation(), this);
task.put(VisualizationTask.META_VISIBLE_DEFAULT, false);
task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_DATA - 1);
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/EMClusterVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/EMClusterVisualization.java
index f62ff1a6..6b2f43a3 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/EMClusterVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/EMClusterVisualization.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
+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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -39,8 +39,8 @@ import de.lmu.ifi.dbs.elki.data.model.Model;
import de.lmu.ifi.dbs.elki.data.spatial.Polygon;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
-import de.lmu.ifi.dbs.elki.math.ConvexHull2D;
import de.lmu.ifi.dbs.elki.math.MathUtil;
+import de.lmu.ifi.dbs.elki.math.geometry.GrahamScanConvexHull2D;
import de.lmu.ifi.dbs.elki.math.linearalgebra.EigenPair;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Matrix;
import de.lmu.ifi.dbs.elki.math.linearalgebra.SortedEigenPairs;
@@ -50,7 +50,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.ClassGenericsUtil;
-import de.lmu.ifi.dbs.elki.utilities.iterator.IterableUtil;
+import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.EmptyParameterization;
import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
import de.lmu.ifi.dbs.elki.visualization.colors.ColorLibrary;
@@ -62,6 +62,7 @@ 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.scatterplot.AbstractScatterplotVisualization;
/**
* Visualizer for generating SVG-Elements containing ellipses for first, second
@@ -76,7 +77,7 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.AbstractVisFactory;
*/
// TODO: nicer stacking of n-fold hulls
// TODO: can we find a proper sphere for 3+ dimensions?
-public class EMClusterVisualization<NV extends NumberVector<NV, ?>> extends P2DVisualization<NV> {
+public class EMClusterVisualization<NV extends NumberVector<NV, ?>> extends AbstractScatterplotVisualization {
/**
* A short name characterizing this Visualizer.
*/
@@ -115,7 +116,6 @@ public class EMClusterVisualization<NV extends NumberVector<NV, ?>> extends P2DV
public EMClusterVisualization(VisualizationTask task) {
super(task);
this.clustering = task.getResult();
- context.addContextChangeListener(this);
incrementalRedraw();
}
@@ -144,7 +144,7 @@ public class EMClusterVisualization<NV extends NumberVector<NV, ?>> extends P2DV
for(int i = 0; i < eps.size(); i++) {
EigenPair ep = eps.getEigenPair(i);
Vector sev = ep.getEigenvector().times(Math.sqrt(ep.getEigenvalue()));
- pc[i] = new Vector(proj.fastProjectRelativeDataToRenderSpace(sev));
+ pc[i] = new Vector(proj.fastProjectRelativeDataToRenderSpace(sev.getArrayRef()));
}
if(drawStyle != 0 || eps.size() == 2) {
drawSphere2D(cnum, cent, pc);
@@ -193,27 +193,29 @@ public class EMClusterVisualization<NV extends NumberVector<NV, ?>> extends P2DV
}
protected void drawHullLines(int cnum, Vector cent, Polygon chres) {
- for(int i = 1; i <= times; i++) {
- SVGPath path = new SVGPath();
- for(int p = 0; p < chres.size(); p++) {
- Vector cur = cent.plusTimes(chres.get(p), i);
- path.drawTo(cur);
- }
- path.close();
- Element ellipse = path.makeElement(svgp);
- SVGUtil.addCSSClass(ellipse, EMBORDER + cnum);
- if(opacStyle == 1) {
- CSSClass cls = new CSSClass(null, "temp");
- double s = (i >= 1 && i <= sigma.length) ? sigma[i - 1] : 0.0;
- cls.setStatement(SVGConstants.CSS_FILL_OPACITY_PROPERTY, s);
- SVGUtil.setAtt(ellipse, SVGConstants.SVG_STYLE_ATTRIBUTE, cls.inlineCSS());
+ if(chres.size() > 1) {
+ for(int i = 1; i <= times; i++) {
+ SVGPath path = new SVGPath();
+ for(int p = 0; p < chres.size(); p++) {
+ Vector cur = cent.plusTimes(chres.get(p), i);
+ path.drawTo(cur);
+ }
+ path.close();
+ Element ellipse = path.makeElement(svgp);
+ SVGUtil.addCSSClass(ellipse, EMBORDER + cnum);
+ if(opacStyle == 1) {
+ CSSClass cls = new CSSClass(null, "temp");
+ double s = (i >= 1 && i <= sigma.length) ? sigma[i - 1] : 0.0;
+ cls.setStatement(SVGConstants.CSS_FILL_OPACITY_PROPERTY, s);
+ SVGUtil.setAtt(ellipse, SVGConstants.SVG_STYLE_ATTRIBUTE, cls.inlineCSS());
+ }
+ layer.appendChild(ellipse);
}
- layer.appendChild(ellipse);
}
}
protected Polygon makeHull(Vector[] pc) {
- ConvexHull2D hull = new ConvexHull2D();
+ GrahamScanConvexHull2D hull = new GrahamScanConvexHull2D();
Vector diag = new Vector(0, 0);
for(int j = 0; j < pc.length; j++) {
@@ -239,7 +241,7 @@ public class EMClusterVisualization<NV extends NumberVector<NV, ?>> extends P2DV
}
protected Polygon makeHullComplex(Vector[] pc) {
- ConvexHull2D hull = new ConvexHull2D();
+ GrahamScanConvexHull2D hull = new GrahamScanConvexHull2D();
Vector diag = new Vector(0, 0);
for(int j = 0; j < pc.length; j++) {
@@ -440,8 +442,8 @@ public class EMClusterVisualization<NV extends NumberVector<NV, ?>> extends P2DV
// Does the cluster have a model with cluster means?
Clustering<MeanModel<NV>> mcls = findMeanModel(c);
if(mcls != null) {
- Iterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
- for(ScatterPlotProjector<?> p : IterableUtil.fromIterator(ps)) {
+ IterableIterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
+ for(ScatterPlotProjector<?> p : ps) {
final VisualizationTask task = new VisualizationTask(NAME, c, p.getRelation(), this);
task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_DATA + 3);
baseResult.getHierarchy().add(c, task);
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
new file mode 100644
index 00000000..37f125d4
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/VoronoiVisualization.java
@@ -0,0 +1,298 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.Collection;
+import java.util.List;
+
+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.NumberVector;
+import de.lmu.ifi.dbs.elki.data.model.EMModel;
+import de.lmu.ifi.dbs.elki.data.model.MeanModel;
+import de.lmu.ifi.dbs.elki.data.model.Model;
+import de.lmu.ifi.dbs.elki.math.geometry.SweepHullDelaunay2D;
+import de.lmu.ifi.dbs.elki.math.geometry.SweepHullDelaunay2D.Triangle;
+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.DatabaseUtil;
+import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
+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.EnumParameter;
+import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
+import de.lmu.ifi.dbs.elki.visualization.css.CSSClass;
+import de.lmu.ifi.dbs.elki.visualization.projector.ScatterPlotProjector;
+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.SVGUtil;
+import de.lmu.ifi.dbs.elki.visualization.svg.VoronoiDraw;
+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;
+
+/**
+ * Visualizer drawing Voronoi cells for k-means clusterings.
+ *
+ * See also: {@link de.lmu.ifi.dbs.elki.algorithm.clustering.kmeans.KMeansLloyd KMeans
+ * clustering}
+ *
+ * @author Robert Rödler
+ * @author Erich Schubert
+ *
+ * @apiviz.has MeanModel oneway - - visualizes
+ */
+public class VoronoiVisualization extends AbstractScatterplotVisualization {
+ /**
+ * A short name characterizing this Visualizer.
+ */
+ private static final String NAME = "k-means Voronoi cells";
+
+ /**
+ * Generic tags to indicate the type of element. Used in IDs, CSS-Classes etc.
+ */
+ private static final String KMEANSBORDER = "kmeans-border";
+
+ /**
+ * Visualization mode.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static enum Mode {
+ VORONOI, DELAUNAY, V_AND_D
+ }
+
+ /**
+ * The result we work on
+ */
+ Clustering<MeanModel<? extends NumberVector<?, ?>>> clustering;
+
+ /**
+ * The Voronoi diagram
+ */
+ Element voronoi;
+
+ /**
+ * Active drawing mode.
+ */
+ private Mode mode;
+
+ /**
+ * Constructor
+ *
+ * @param task VisualizationTask
+ * @param mode Drawing mode
+ */
+ public VoronoiVisualization(VisualizationTask task, Mode mode) {
+ super(task);
+ this.clustering = task.getResult();
+ this.mode = mode;
+ incrementalRedraw();
+ }
+
+ @Override
+ protected void redraw() {
+ addCSSClasses(svgp);
+ final List<Cluster<MeanModel<? extends NumberVector<?, ?>>>> clusters = clustering.getAllClusters();
+
+ if(clusters.size() < 2) {
+ return;
+ }
+
+ // Collect cluster means
+ if(clusters.size() == 2) {
+ ArrayList<double[]> means = new ArrayList<double[]>(clusters.size());
+ {
+ for(Cluster<MeanModel<? extends NumberVector<?, ?>>> clus : clusters) {
+ means.add(clus.getModel().getMean().getColumnVector().getArrayRef());
+ }
+ }
+ if(mode == Mode.VORONOI || mode == Mode.V_AND_D) {
+ Element path = VoronoiDraw.drawFakeVoronoi(proj, means).makeElement(svgp);
+ SVGUtil.addCSSClass(path, KMEANSBORDER);
+ layer.appendChild(path);
+ }
+ if(mode == Mode.DELAUNAY || mode == Mode.V_AND_D) {
+ Element path = new SVGPath(proj.fastProjectDataToRenderSpace(means.get(0))).drawTo(proj.fastProjectDataToRenderSpace(means.get(1))).makeElement(svgp);
+ SVGUtil.addCSSClass(path, KMEANSBORDER);
+ layer.appendChild(path);
+ }
+ }
+ else {
+ ArrayList<Vector> vmeans = new ArrayList<Vector>(clusters.size());
+ ArrayList<double[]> means = new ArrayList<double[]>(clusters.size());
+ {
+ for(Cluster<MeanModel<? extends NumberVector<?, ?>>> clus : clusters) {
+ Vector v = clus.getModel().getMean().getColumnVector();
+ vmeans.add(v);
+ means.add(v.getArrayRef());
+ }
+ }
+ // Compute Delaunay Triangulation
+ ArrayList<Triangle> delaunay = new SweepHullDelaunay2D(vmeans).getDelaunay();
+ if(mode == Mode.VORONOI || mode == Mode.V_AND_D) {
+ Element path = VoronoiDraw.drawVoronoi(proj, delaunay, means).makeElement(svgp);
+ SVGUtil.addCSSClass(path, KMEANSBORDER);
+ layer.appendChild(path);
+ }
+ if(mode == Mode.DELAUNAY || mode == Mode.V_AND_D) {
+ Element path = VoronoiDraw.drawDelaunay(proj, delaunay, means).makeElement(svgp);
+ SVGUtil.addCSSClass(path, KMEANSBORDER);
+ layer.appendChild(path);
+ }
+ }
+ }
+
+ /**
+ * Adds the required CSS-Classes
+ *
+ * @param svgp SVG-Plot
+ */
+ private void addCSSClasses(SVGPlot svgp) {
+ // Class for the distance markers
+ if(!svgp.getCSSClassManager().contains(KMEANSBORDER)) {
+ CSSClass cls = new CSSClass(this, KMEANSBORDER);
+ cls = new CSSClass(this, KMEANSBORDER);
+ cls.setStatement(SVGConstants.CSS_STROKE_PROPERTY, SVGConstants.CSS_BLACK_VALUE);
+ cls.setStatement(SVGConstants.CSS_STROKE_WIDTH_PROPERTY, context.getStyleLibrary().getLineWidth(StyleLibrary.PLOT) * .5);
+ cls.setStatement(SVGConstants.CSS_FILL_PROPERTY, SVGConstants.CSS_NONE_VALUE);
+ cls.setStatement(SVGConstants.CSS_STROKE_LINECAP_PROPERTY, SVGConstants.CSS_ROUND_VALUE);
+ cls.setStatement(SVGConstants.CSS_STROKE_LINEJOIN_PROPERTY, SVGConstants.CSS_ROUND_VALUE);
+ svgp.addCSSClassOrLogError(cls);
+ }
+ }
+
+ /**
+ * Factory for visualizers to generate an SVG-Element containing the lines
+ * between kMeans clusters
+ *
+ * @author Robert Rödler
+ * @author Erich Schubert
+ *
+ * @apiviz.stereotype factory
+ * @apiviz.uses VoronoiVisualisation oneway - - «create»
+ */
+ public static class Factory extends AbstractVisFactory {
+ /**
+ * Mode for drawing: Voronoi, Delaunay, both
+ *
+ * <p>
+ * Key: {@code -voronoi.mode}
+ * </p>
+ */
+ public static final OptionID MODE_ID = OptionID.getOrCreateOptionID("voronoi.mode", "Mode for drawing the voronoi cells (and/or delaunay triangulation)");
+
+ /**
+ * Drawing mode
+ */
+ private Mode mode;
+
+ /**
+ * Constructor
+ *
+ * @param mode Drawing mode
+ */
+ public Factory(Mode mode) {
+ super();
+ this.mode = mode;
+ }
+
+ @Override
+ public Visualization makeVisualization(VisualizationTask task) {
+ return new VoronoiVisualization(task, mode);
+ }
+
+ @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) {
+ if(c.getAllClusters().size() > 0) {
+ // Does the cluster have a model with cluster means?
+ Clustering<MeanModel<? extends NumberVector<?, ?>>> mcls = findMeanModel(c);
+ if(mcls != null) {
+ IterableIterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
+ for(ScatterPlotProjector<?> p : ps) {
+ if(DatabaseUtil.dimensionality(p.getRelation()) == 2) {
+ final VisualizationTask task = new VisualizationTask(NAME, c, p.getRelation(), this);
+ task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_DATA + 3);
+ baseResult.getHierarchy().add(p, task);
+ baseResult.getHierarchy().add(c, task);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Test if the given clustering has a mean model.
+ *
+ * @param c Clustering to inspect
+ * @return the clustering cast to return a mean model, null otherwise.
+ */
+ @SuppressWarnings("unchecked")
+ private static Clustering<MeanModel<? extends NumberVector<?, ?>>> findMeanModel(Clustering<?> c) {
+ final Model firstModel = c.getAllClusters().get(0).getModel();
+ if(firstModel instanceof MeanModel<?> && !(firstModel instanceof EMModel<?>)) {
+ return (Clustering<MeanModel<? extends NumberVector<?, ?>>>) c;
+ }
+ return null;
+ }
+
+ /**
+ * Parameterization class.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.exclude
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ protected Mode mode;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ EnumParameter<Mode> modeP = new EnumParameter<Mode>(MODE_ID, Mode.class, Mode.VORONOI);
+ if(config.grab(modeP)) {
+ mode = modeP.getValue();
+ }
+ }
+
+ @Override
+ protected Factory makeInstance() {
+ return new Factory(mode);
+ }
+ }
+ }
+} \ No newline at end of file
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
new file mode 100644
index 00000000..0f232498
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/cluster/package-info.java
@@ -0,0 +1,26 @@
+/**
+ * <p>Visualizers for clustering results based on 2D projections.</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.visualization.visualizers.scatterplot.cluster; \ No newline at end of file
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
new file mode 100644
index 00000000..28e4da32
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/density/DensityEstimationOverlay.java
@@ -0,0 +1,236 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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.image.BufferedImage;
+import java.util.Arrays;
+import java.util.Comparator;
+
+import org.apache.batik.util.SVGConstants;
+import org.w3c.dom.Element;
+
+import de.lmu.ifi.dbs.elki.database.ids.DBID;
+import de.lmu.ifi.dbs.elki.math.MathUtil;
+import de.lmu.ifi.dbs.elki.math.MeanVariance;
+import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
+import de.lmu.ifi.dbs.elki.result.KMLOutputHandler;
+import de.lmu.ifi.dbs.elki.result.Result;
+import de.lmu.ifi.dbs.elki.result.ResultUtil;
+import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
+import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
+import de.lmu.ifi.dbs.elki.visualization.batikutil.ThumbnailRegistryEntry;
+import de.lmu.ifi.dbs.elki.visualization.projections.CanvasSize;
+import de.lmu.ifi.dbs.elki.visualization.projector.ScatterPlotProjector;
+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;
+
+/**
+ * A simple density estimation visualization, based on a simple kernel-density
+ * <em>in the projection, not the actual data!</em>
+ *
+ * @author Erich Schubert
+ */
+// TODO: make parameterizable, in particular color map, kernel bandwidth and
+// kernel function
+public class DensityEstimationOverlay extends AbstractScatterplotVisualization {
+ /**
+ * A short name characterizing this Visualizer.
+ */
+ private static final String NAME = "Density estimation overlay";
+
+ /**
+ * Density map resolution
+ */
+ private int resolution = 500;
+
+ /**
+ * The actual image
+ */
+ private BufferedImage img = null;
+
+ /**
+ * Constructor.
+ *
+ * @param task Task
+ */
+ public DensityEstimationOverlay(VisualizationTask task) {
+ super(task);
+ incrementalRedraw();
+ }
+
+ @Override
+ protected void redraw() {
+ if(img == null) {
+ renderImage();
+ }
+
+ CanvasSize canvas = proj.estimateViewport();
+ String imguri = ThumbnailRegistryEntry.INTERNAL_PREFIX + ThumbnailRegistryEntry.registerImage(img);
+ Element itag = svgp.svgElement(SVGConstants.SVG_IMAGE_TAG);
+ SVGUtil.setAtt(itag, SVGConstants.SVG_IMAGE_RENDERING_ATTRIBUTE, SVGConstants.SVG_OPTIMIZE_SPEED_VALUE);
+ SVGUtil.setAtt(itag, SVGConstants.SVG_X_ATTRIBUTE, canvas.minx);
+ SVGUtil.setAtt(itag, SVGConstants.SVG_Y_ATTRIBUTE, canvas.miny);
+ SVGUtil.setAtt(itag, SVGConstants.SVG_WIDTH_ATTRIBUTE, canvas.maxx - canvas.minx);
+ SVGUtil.setAtt(itag, SVGConstants.SVG_HEIGHT_ATTRIBUTE, canvas.maxy - canvas.miny);
+ SVGUtil.setAtt(itag, SVGConstants.SVG_STYLE_ATTRIBUTE, SVGConstants.CSS_OPACITY_PROPERTY + ": .5");
+ itag.setAttributeNS(SVGConstants.XLINK_NAMESPACE_URI, SVGConstants.XLINK_HREF_QNAME, imguri);
+
+ layer.appendChild(itag);
+ }
+
+ @Reference(authors = "D. W. Scott", title = "Multivariate density estimation", booktitle = "Multivariate Density Estimation: Theory, Practice, and Visualization", url = "http://dx.doi.org/10.1002/9780470316849.fmatter")
+ private double[] initializeBandwidth(double[][] data) {
+ MeanVariance mv0 = new MeanVariance();
+ MeanVariance mv1 = new MeanVariance();
+ // For Kernel bandwidth.
+ for(double[] projected : data) {
+ mv0.put(projected[0]);
+ mv1.put(projected[1]);
+ }
+ // Set bandwidths according to Scott's rule:
+ // Note: in projected space, d=2.
+ double[] bandwidth = new double[2];
+ bandwidth[0] = MathUtil.SQRT5 * mv0.getSampleStddev() * Math.pow(rel.size(), -1 / 6.);
+ bandwidth[1] = MathUtil.SQRT5 * mv1.getSampleStddev() * Math.pow(rel.size(), -1 / 6.);
+ return bandwidth;
+ }
+
+ private void renderImage() {
+ // TODO: SAMPLE? Do region queries?
+ // Project the data just once, keep a copy.
+ double[][] data = new double[rel.size()][];
+ {
+ int i = 0;
+ for(DBID id : rel.iterDBIDs()) {
+ data[i] = proj.fastProjectDataToRenderSpace(rel.get(id));
+ i++;
+ }
+ }
+ double[] bandwidth = initializeBandwidth(data);
+ // Compare by first component
+ Comparator<double[]> comp0 = new Comparator<double[]>() {
+ @Override
+ public int compare(double[] o1, double[] o2) {
+ return Double.compare(o1[0], o2[0]);
+ }
+ };
+ // Compare by second component
+ Comparator<double[]> comp1 = new Comparator<double[]>() {
+ @Override
+ public int compare(double[] o1, double[] o2) {
+ return Double.compare(o1[1], o2[1]);
+ }
+ };
+ // TODO: choose comparator order based on smaller bandwidth?
+ Arrays.sort(data, comp0);
+
+ CanvasSize canvas = proj.estimateViewport();
+ double min0 = canvas.minx, max0 = canvas.maxx, ste0 = (max0 - min0) / resolution;
+ double min1 = canvas.miny, max1 = canvas.maxy, ste1 = (max1 - min1) / resolution;
+
+ double kernf = 9. / (16 * bandwidth[0] * bandwidth[1]);
+ double maxdens = 0.0;
+ double[][] dens = new double[resolution][resolution];
+ {
+ // TODO: incrementally update the loff/roff values?
+ for(int x = 0; x < resolution; x++) {
+ double xlow = min0 + ste0 * x, xhig = xlow + ste0;
+ int loff = unflip(Arrays.binarySearch(data, new double[] { xlow - bandwidth[0] }, comp0));
+ int roff = unflip(Arrays.binarySearch(data, new double[] { xhig + bandwidth[0] }, comp0));
+ // Resort by second component
+ Arrays.sort(data, loff, roff, comp1);
+ for(int y = 0; y < resolution; y++) {
+ double ylow = min1 + ste1 * y, yhig = ylow + ste1;
+ int boff = unflip(Arrays.binarySearch(data, loff, roff, new double[] { 0, ylow - bandwidth[1] }, comp1));
+ int toff = unflip(Arrays.binarySearch(data, loff, roff, new double[] { 0, yhig + bandwidth[1] }, comp1));
+ for(int pos = boff; pos < toff; pos++) {
+ double[] val = data[pos];
+ double d0 = (val[0] < xlow) ? (xlow - val[0]) : (val[0] > xhig) ? (val[0] - xhig) : 0;
+ double d1 = (val[1] < ylow) ? (ylow - val[1]) : (val[1] > yhig) ? (val[1] - yhig) : 0;
+ d0 = d0 / bandwidth[0];
+ d1 = d1 / bandwidth[1];
+ dens[x][y] += kernf * (1 - d0 * d0) * (1 - d1 * d1);
+ }
+ maxdens = Math.max(maxdens, dens[x][y]);
+ }
+ // Restore original sorting, as the intervals overlap
+ Arrays.sort(data, loff, roff, comp0);
+ }
+ }
+ img = new BufferedImage(resolution, resolution, BufferedImage.TYPE_INT_ARGB);
+ {
+ for(int x = 0; x < resolution; x++) {
+ for(int y = 0; y < resolution; y++) {
+ int rgb = KMLOutputHandler.getColorForValue(dens[x][y] / maxdens).getRGB();
+ img.setRGB(x, y, rgb);
+ }
+ }
+ }
+ }
+
+ private int unflip(int binarySearch) {
+ if(binarySearch < 0) {
+ return (-binarySearch) - 1;
+ }
+ else {
+ return binarySearch;
+ }
+ }
+
+ /**
+ * The visualization factory
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.stereotype factory
+ * @apiviz.uses DensityEstimation2DVisualization oneway - - «create»
+ */
+ public static class Factory extends AbstractVisFactory {
+ /**
+ * Constructor, adhering to
+ * {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable}
+ */
+ public Factory() {
+ super();
+ }
+
+ @Override
+ public Visualization makeVisualization(VisualizationTask task) {
+ return new DensityEstimationOverlay(task);
+ }
+
+ @Override
+ public void processNewResult(HierarchicalResult baseResult, Result result) {
+ IterableIterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(result, ScatterPlotProjector.class);
+ for(ScatterPlotProjector<?> p : ps) {
+ final VisualizationTask task = new VisualizationTask(NAME, p.getRelation(), p.getRelation(), this);
+ task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_DATA + 1);
+ task.put(VisualizationTask.META_VISIBLE_DEFAULT, false);
+ baseResult.getHierarchy().add(p, task);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/distribution/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/density/package-info.java
index 6aab20ab..b9771aed 100644
--- a/src/de/lmu/ifi/dbs/elki/data/synthetic/bymodel/distribution/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/density/package-info.java
@@ -1,12 +1,11 @@
/**
- * <p>Data generators used by the model-based generator.</p>
- *
+ * <p>Visualizers for data set density in a scatterplot projection.</p>
*/
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2011
+Copyright (C) 2012
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.data.synthetic.bymodel.distribution; \ No newline at end of file
+package de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.density; \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/TreeMBRVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/index/TreeMBRVisualization.java
index cc3dfbe8..0b4bee2f 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/TreeMBRVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/index/TreeMBRVisualization.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
+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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,25 +24,21 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
*/
import java.util.ArrayList;
-import java.util.Iterator;
import org.apache.batik.util.SVGConstants;
import org.w3c.dom.Element;
-import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable;
import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil;
-import de.lmu.ifi.dbs.elki.database.datastore.DataStoreEvent;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreListener;
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.index.tree.spatial.rstarvariants.rstar.RStarTreeNode;
-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.iterator.IterableUtil;
+import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
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;
@@ -58,6 +54,7 @@ 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;
/**
* Visualize the bounding rectangles of an R-Tree based index.
@@ -67,12 +64,11 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.Visualization;
* @apiviz.has AbstractRStarTree oneway - - visualizes
* @apiviz.uses SVGHyperCube
*
- * @param <NV> Type of the DatabaseObject being visualized.
* @param <N> Tree node type
* @param <E> Tree entry type
*/
// TODO: listen for tree changes instead of data changes?
-public class TreeMBRVisualization<NV extends NumberVector<NV, ?>, N extends AbstractRStarTreeNode<N, E>, E extends SpatialEntry> extends P2DVisualization<NV> implements DataStoreListener {
+public class TreeMBRVisualization<N extends AbstractRStarTreeNode<N, E>, E extends SpatialEntry> extends AbstractScatterplotVisualization implements DataStoreListener {
/**
* Generic tag to indicate the type of element. Used in IDs, CSS-Classes etc.
*/
@@ -152,11 +148,11 @@ public class TreeMBRVisualization<NV extends NumberVector<NV, ?>, N extends Abst
SpatialComparable mbr = entry;
if(fill) {
- Element r = SVGHyperCube.drawFilled(svgp, INDEX + depth, proj, new Vector(SpatialUtil.getMin(mbr)), new Vector(SpatialUtil.getMax(mbr)));
+ Element r = SVGHyperCube.drawFilled(svgp, INDEX + depth, proj, SpatialUtil.getMin(mbr), SpatialUtil.getMax(mbr));
layer.appendChild(r);
}
else {
- Element r = SVGHyperCube.drawFrame(svgp, proj, new Vector(SpatialUtil.getMin(mbr)), new Vector(SpatialUtil.getMax(mbr)));
+ Element r = SVGHyperCube.drawFrame(svgp, proj, SpatialUtil.getMin(mbr), SpatialUtil.getMax(mbr));
SVGUtil.setCSSClass(r, INDEX + depth);
layer.appendChild(r);
}
@@ -178,11 +174,6 @@ public class TreeMBRVisualization<NV extends NumberVector<NV, ?>, N extends Abst
context.removeDataStoreListener(this);
}
- @Override
- public void contentChanged(DataStoreEvent e) {
- synchronizedRedraw();
- }
-
/**
* Factory
*
@@ -190,10 +181,8 @@ public class TreeMBRVisualization<NV extends NumberVector<NV, ?>, N extends Abst
*
* @apiviz.stereotype factory
* @apiviz.uses TreeMBRVisualization oneway - - «create»
- *
- * @param <NV> vector type
*/
- public static class Factory<NV extends NumberVector<NV, ?>> extends AbstractVisFactory {
+ public static class Factory extends AbstractVisFactory {
/**
* Flag for half-transparent filling of bubbles.
*
@@ -220,7 +209,7 @@ public class TreeMBRVisualization<NV extends NumberVector<NV, ?>, N extends Abst
@Override
public Visualization makeVisualization(VisualizationTask task) {
- return new TreeMBRVisualization<NV, RStarTreeNode, SpatialEntry>(task, fill);
+ return new TreeMBRVisualization<RStarTreeNode, SpatialEntry>(task, fill);
}
@Override
@@ -228,8 +217,8 @@ public class TreeMBRVisualization<NV extends NumberVector<NV, ?>, N extends Abst
ArrayList<AbstractRStarTree<RStarTreeNode, SpatialEntry>> trees = ResultUtil.filterResults(result, AbstractRStarTree.class);
for(AbstractRStarTree<RStarTreeNode, SpatialEntry> tree : trees) {
if(tree instanceof Result) {
- Iterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
- for(ScatterPlotProjector<?> p : IterableUtil.fromIterator(ps)) {
+ IterableIterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
+ for(ScatterPlotProjector<?> p : ps) {
final VisualizationTask task = new VisualizationTask(NAME, (Result) tree, p.getRelation(), this);
task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_BACKGROUND + 1);
baseResult.getHierarchy().add((Result) tree, task);
@@ -246,7 +235,7 @@ public class TreeMBRVisualization<NV extends NumberVector<NV, ?>, N extends Abst
*
* @apiviz.exclude
*/
- public static class Parameterizer<NV extends NumberVector<NV, ?>> extends AbstractParameterizer {
+ public static class Parameterizer extends AbstractParameterizer {
protected boolean fill = false;
@Override
@@ -259,8 +248,8 @@ public class TreeMBRVisualization<NV extends NumberVector<NV, ?>, N extends Abst
}
@Override
- protected Factory<NV> makeInstance() {
- return new Factory<NV>(fill);
+ protected Factory makeInstance() {
+ return new Factory(fill);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/TreeSphereVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/index/TreeSphereVisualization.java
index 73a02ddb..85429eb1 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/TreeSphereVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/index/TreeSphereVisualization.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
+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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,13 +24,11 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
*/
import java.util.ArrayList;
-import java.util.Iterator;
import org.apache.batik.util.SVGConstants;
import org.w3c.dom.Element;
import de.lmu.ifi.dbs.elki.data.NumberVector;
-import de.lmu.ifi.dbs.elki.database.datastore.DataStoreEvent;
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;
@@ -46,7 +44,7 @@ import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mtree.MTreeNode;
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.IterableUtil;
+import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
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;
@@ -61,6 +59,7 @@ 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;
/**
* Visualize the bounding sphere of a metric index.
@@ -70,12 +69,11 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.Visualization;
* @apiviz.has AbstractMTree oneway - - visualizes
* @apiviz.uses SVGHyperSphere
*
- * @param <NV> Type of the DatabaseObject being visualized.
* @param <N> Tree node type
* @param <E> Tree entry type
*/
// TODO: listen for tree changes!
-public class TreeSphereVisualization<NV extends NumberVector<NV, ?>, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<NV, D, N, E>, E extends MTreeEntry<D>> extends P2DVisualization<NV> implements DataStoreListener {
+public class TreeSphereVisualization<D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<?, D, N, E>, E extends MTreeEntry<D>> extends AbstractScatterplotVisualization implements DataStoreListener {
/**
* Generic tag to indicate the type of element. Used in IDs, CSS-Classes etc.
*/
@@ -105,7 +103,7 @@ public class TreeSphereVisualization<NV extends NumberVector<NV, ?>, D extends N
/**
* The tree we visualize
*/
- protected AbstractMTree<NV, D, N, E> tree;
+ protected AbstractMTree<?, D, N, E> tree;
/**
* Fill parameter.
@@ -208,10 +206,10 @@ public class TreeSphereVisualization<NV extends NumberVector<NV, ?>, D extends N
* @param entry Current entry
* @param depth Current depth
*/
- private void visualizeMTreeEntry(SVGPlot svgp, Element layer, Projection2D proj, AbstractMTree<NV, 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) {
- NV ro = rel.get(roid);
+ NumberVector<?, ?> ro = rel.get(roid);
D rad = entry.getCoveringRadius();
final Element r;
@@ -247,11 +245,6 @@ public class TreeSphereVisualization<NV extends NumberVector<NV, ?>, D extends N
context.removeDataStoreListener(this);
}
- @Override
- public void contentChanged(DataStoreEvent e) {
- synchronizedRedraw();
- }
-
/**
* Factory
*
@@ -259,10 +252,8 @@ public class TreeSphereVisualization<NV extends NumberVector<NV, ?>, D extends N
*
* @apiviz.stereotype factory
* @apiviz.uses TreeSphereVisualization oneway - - «create»
- *
- * @param <NV>
*/
- public static class Factory<NV extends NumberVector<NV, ?>> extends AbstractVisFactory {
+ public static class Factory extends AbstractVisFactory {
/**
* Fill parameter.
*/
@@ -280,10 +271,10 @@ public class TreeSphereVisualization<NV extends NumberVector<NV, ?>, D extends N
@Override
public void processNewResult(HierarchicalResult baseResult, Result result) {
- Iterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
- for(ScatterPlotProjector<?> p : IterableUtil.fromIterator(ps)) {
- ArrayList<AbstractMTree<NV, DoubleDistance, ?, ?>> trees = ResultUtil.filterResults(result, AbstractMTree.class);
- for(AbstractMTree<NV, DoubleDistance, ?, ?> tree : trees) {
+ IterableIterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
+ for(ScatterPlotProjector<?> p : ps) {
+ ArrayList<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.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_BACKGROUND + 1);
@@ -296,7 +287,7 @@ public class TreeSphereVisualization<NV extends NumberVector<NV, ?>, D extends N
@Override
public Visualization makeVisualization(VisualizationTask task) {
- return new TreeSphereVisualization<NV, DoubleDistance, MTreeNode<NV, DoubleDistance>, MTreeEntry<DoubleDistance>>(task, fill);
+ return new TreeSphereVisualization<DoubleDistance, MTreeNode<Object, DoubleDistance>, MTreeEntry<DoubleDistance>>(task, fill);
}
/**
@@ -306,7 +297,7 @@ public class TreeSphereVisualization<NV extends NumberVector<NV, ?>, D extends N
*
* @apiviz.exclude
*/
- public static class Parameterizer<NV extends NumberVector<NV, ?>> extends AbstractParameterizer {
+ public static class Parameterizer extends AbstractParameterizer {
protected boolean fill = false;
@Override
@@ -319,8 +310,8 @@ public class TreeSphereVisualization<NV extends NumberVector<NV, ?>, D extends N
}
@Override
- protected Factory<NV> makeInstance() {
- return new Factory<NV>(fill);
+ protected Factory makeInstance() {
+ return new Factory(fill);
}
}
}
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
new file mode 100644
index 00000000..a4b3c0c9
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/index/package-info.java
@@ -0,0 +1,26 @@
+/**
+ * <p>Visualizers for index structures based on 2D projections.</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.visualization.visualizers.scatterplot.index; \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/BubbleVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/outlier/BubbleVisualization.java
index 3d183a88..7c40c1cb 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/BubbleVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/outlier/BubbleVisualization.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
+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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,17 +23,12 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.util.Iterator;
import java.util.List;
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.NumberVector;
-import de.lmu.ifi.dbs.elki.data.model.Model;
-import de.lmu.ifi.dbs.elki.database.datastore.DataStoreEvent;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreListener;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
@@ -41,7 +36,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.utilities.documentation.Reference;
-import de.lmu.ifi.dbs.elki.utilities.iterator.IterableUtil;
+import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
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;
@@ -53,11 +48,14 @@ 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.projector.ScatterPlotProjector;
+import de.lmu.ifi.dbs.elki.visualization.style.ClassStylingPolicy;
import de.lmu.ifi.dbs.elki.visualization.style.StyleLibrary;
+import de.lmu.ifi.dbs.elki.visualization.style.StylingPolicy;
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;
/**
* Generates a SVG-Element containing bubbles. A Bubble is a circle visualizing
@@ -68,11 +66,9 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.Visualization;
* @author Erich Schubert
*
* @apiviz.has OutlierResult oneway - - visualizes
- *
- * @param <NV> Type of the DatabaseObject being visualized.
*/
-@Reference(authors = "E. Achtert, H.-P. Kriegel, L. Reichert, E. Schubert, R. Wojdanowski, A. Zimek", title = "Visual Evaluation of Outlier Detection Models", booktitle = "Proceedings of the 15th International Conference on Database Systems for Advanced Applications (DASFAA), Tsukuba, Japan, 2010", url = "http://dx.doi.org/10.1007%2F978-3-642-12098-5_34")
-public class BubbleVisualization<NV extends NumberVector<NV, ?>> extends P2DVisualization<NV> implements DataStoreListener {
+@Reference(authors = "E. Achtert, H.-P. Kriegel, L. Reichert, E. Schubert, R. Wojdanowski, A. Zimek", title = "Visual Evaluation of Outlier Detection Models", booktitle = "Proceedings of the 15th International Conference on Database Systems for Advanced Applications (DASFAA), Tsukuba, Japan, 2010", url = "http://dx.doi.org/10.1007/978-3-642-12098-5_34")
+public class BubbleVisualization extends AbstractScatterplotVisualization implements DataStoreListener {
/**
* Generic tag to indicate the type of element. Used in IDs, CSS-Classes etc.
*/
@@ -120,22 +116,46 @@ public class BubbleVisualization<NV extends NumberVector<NV, ?>> extends P2DVisu
@Override
public void redraw() {
- Clustering<Model> clustering = context.getOrCreateDefaultClustering();
- setupCSS(svgp, clustering);
+ StylingPolicy stylepolicy = context.getStyleResult().getStylingPolicy();
// bubble size
- double bubble_size = context.getStyleLibrary().getSize(StyleLibrary.BUBBLEPLOT);
- // draw data
- Iterator<Cluster<Model>> ci = clustering.getAllClusters().iterator();
- for(int cnum = 0; cnum < clustering.getAllClusters().size(); cnum++) {
- Cluster<?> clus = ci.next();
- for(DBID objId : clus.getIDs()) {
+ final double bubble_size = context.getStyleLibrary().getSize(StyleLibrary.BUBBLEPLOT);
+ if(stylepolicy instanceof ClassStylingPolicy) {
+ ClassStylingPolicy colors = (ClassStylingPolicy) stylepolicy;
+ setupCSS(svgp, colors);
+ // draw data
+ for(DBID objId : sample.getSample()) {
+ final Double radius = getScaledForId(objId);
+ if(radius > 0.01 && !Double.isInfinite(radius)) {
+ final NumberVector<?, ?> vec = rel.get(objId);
+ 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));
+ layer.appendChild(circle);
+ }
+ }
+ }
+ }
+ else {
+ // draw data
+ for(DBID objId : sample.getSample()) {
final Double radius = getScaledForId(objId);
- if(radius > 0.01) {
- final NV vec = rel.get(objId);
+ if(radius > 0.01 && !Double.isInfinite(radius)) {
+ final NumberVector<?, ?> vec = rel.get(objId);
if(vec != null) {
double[] v = proj.fastProjectDataToRenderSpace(vec);
Element circle = svgp.svgCircle(v[0], v[1], radius * bubble_size);
- SVGUtil.addCSSClass(circle, BUBBLE + cnum);
+ int color = stylepolicy.getColorForDBID(objId);
+ final StringBuffer style = new StringBuffer();
+ if(fill) {
+ style.append(SVGConstants.CSS_FILL_PROPERTY + ":").append(SVGUtil.colorToString(color));
+ style.append(SVGConstants.CSS_FILL_OPACITY_PROPERTY + ":0.5");
+ }
+ else {
+ style.append(SVGConstants.CSS_STROKE_VALUE + ":").append(SVGUtil.colorToString(color));
+ style.append(SVGConstants.CSS_FILL_PROPERTY + ":" + SVGConstants.CSS_NONE_VALUE);
+ }
+ SVGUtil.setAtt(circle, SVGConstants.SVG_STYLE_ATTRIBUTE, style.toString());
layer.appendChild(circle);
}
}
@@ -144,35 +164,27 @@ public class BubbleVisualization<NV extends NumberVector<NV, ?>> extends P2DVisu
}
@Override
- public void contentChanged(DataStoreEvent e) {
- synchronizedRedraw();
+ public void resultChanged(Result current) {
+ if(sample == current) {
+ synchronizedRedraw();
+ }
}
/**
* Registers the Bubble-CSS-Class at a SVGPlot.
*
* @param svgp the SVGPlot to register the Tooltip-CSS-Class.
- * @param clustering Clustering to use
+ * @param policy Clustering to use
*/
- private void setupCSS(SVGPlot svgp, Clustering<? extends Model> clustering) {
+ private void setupCSS(SVGPlot svgp, ClassStylingPolicy policy) {
ColorLibrary colors = context.getStyleLibrary().getColorSet(StyleLibrary.PLOT);
// creating IDs manually because cluster often return a null-ID.
- int clusterID = 0;
-
- for(@SuppressWarnings("unused")
- Cluster<?> cluster : clustering.getAllClusters()) {
+ for(int clusterID = policy.getMinStyle(); clusterID < policy.getMaxStyle(); clusterID++) {
CSSClass bubble = new CSSClass(svgp, BUBBLE + clusterID);
bubble.setStatement(SVGConstants.CSS_STROKE_WIDTH_PROPERTY, context.getStyleLibrary().getLineWidth(StyleLibrary.PLOT));
- String color;
-
- if(clustering.getAllClusters().size() == 1) {
- color = "black";
- }
- else {
- color = colors.getColor(clusterID);
- }
+ String color = colors.getColor(clusterID);
if(fill) {
bubble.setStatement(SVGConstants.CSS_FILL_PROPERTY, color);
@@ -185,7 +197,6 @@ public class BubbleVisualization<NV extends NumberVector<NV, ?>> extends P2DVisu
}
svgp.addCSSClassOrLogError(bubble);
- clusterID += 1;
}
}
@@ -196,9 +207,9 @@ public class BubbleVisualization<NV extends NumberVector<NV, ?>> extends P2DVisu
* @return a Double representing a outlierness-score, after it has modified by
* the given scales.
*/
- protected Double getScaledForId(DBID id) {
- Double d = result.getScores().get(id).doubleValue();
- if(d == null) {
+ protected double getScaledForId(DBID id) {
+ double d = result.getScores().get(id).doubleValue();
+ if(Double.isNaN(d) || Double.isInfinite(d)) {
return 0.0;
}
if(scaling == null) {
@@ -216,10 +227,8 @@ public class BubbleVisualization<NV extends NumberVector<NV, ?>> extends P2DVisu
*
* @apiviz.stereotype factory
* @apiviz.uses BubbleVisualization oneway - - «create»
- *
- * @param <NV> Type of the DatabaseObject being visualized.
*/
- public static class Factory<NV extends NumberVector<NV, ?>> extends AbstractVisFactory {
+ public static class Factory extends AbstractVisFactory {
/**
* Flag for half-transparent filling of bubbles.
*
@@ -266,14 +275,14 @@ public class BubbleVisualization<NV extends NumberVector<NV, ?>> extends P2DVisu
final OutlierResult outlierResult = task.getResult();
((OutlierScalingFunction) this.scaling).prepare(outlierResult);
}
- return new BubbleVisualization<NV>(task, scaling);
+ return new BubbleVisualization(task, scaling);
}
@Override
public void processNewResult(HierarchicalResult baseResult, Result result) {
List<OutlierResult> ors = ResultUtil.filterResults(result, OutlierResult.class);
for(OutlierResult o : ors) {
- Iterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
+ IterableIterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(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.
@@ -283,7 +292,7 @@ public class BubbleVisualization<NV extends NumberVector<NV, ?>> extends P2DVisu
break;
}
}
- for(ScatterPlotProjector<?> p : IterableUtil.fromIterator(ps)) {
+ for(ScatterPlotProjector<?> p : ps) {
final VisualizationTask task = new VisualizationTask(NAME, o, p.getRelation(), this);
task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_DATA);
if(!vis) {
@@ -302,7 +311,7 @@ public class BubbleVisualization<NV extends NumberVector<NV, ?>> extends P2DVisu
*
* @apiviz.exclude
*/
- public static class Parameterizer<NV extends NumberVector<NV, ?>> extends AbstractParameterizer {
+ public static class Parameterizer extends AbstractParameterizer {
/**
* Fill parameter.
*/
@@ -328,8 +337,8 @@ public class BubbleVisualization<NV extends NumberVector<NV, ?>> extends P2DVisu
}
@Override
- protected Factory<NV> makeInstance() {
- return new Factory<NV>(fill, scaling);
+ protected Factory makeInstance() {
+ return new Factory(fill, scaling);
}
}
}
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
new file mode 100644
index 00000000..7332fcb0
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/outlier/package-info.java
@@ -0,0 +1,26 @@
+/**
+ * <p>Visualizers for outlier scores based on 2D projections.</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.visualization.visualizers.scatterplot.outlier; \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/package-info.java
index 6a0fa750..805379d7 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/package-info.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/package-info.java
@@ -1,9 +1,8 @@
/**
- * <p>Visualizers based on 2D projections.</p>
+ * <p>Visualizers based on scatterplots.</p>
*
* @apiviz.exclude de.lmu.ifi.dbs.elki.visualization.batikutil.*
* @apiviz.exclude de.lmu.ifi.dbs.elki.visualization.svg.*
- * @apiviz.exclude de.lmu.ifi.dbs.elki.visualization.visualizers.events.*
* @apiviz.exclude de.lmu.ifi.dbs.elki.result.*
* @apiviz.exclude de.lmu.ifi.dbs.elki.index.*
* @apiviz.exclude de.lmu.ifi.dbs.elki.data.*
@@ -13,7 +12,7 @@
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
-Copyright (C) 2011
+Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -31,4 +30,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.visualization.visualizers.vis2d; \ No newline at end of file
+package de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot; \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/MoveObjectsToolVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/selection/MoveObjectsToolVisualization.java
index 6d798247..fb9de7d5 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/MoveObjectsToolVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/selection/MoveObjectsToolVisualization.java
@@ -1,4 +1,4 @@
-package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
+package de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.selection;
/*
This file is part of ELKI:
@@ -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;
@@ -38,7 +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.utilities.exceptions.AbortException;
-import de.lmu.ifi.dbs.elki.utilities.iterator.IterableUtil;
+import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
import de.lmu.ifi.dbs.elki.visualization.batikutil.DragableArea;
import de.lmu.ifi.dbs.elki.visualization.batikutil.DragableArea.DragListener;
@@ -49,7 +48,7 @@ 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.events.ContextChangedEvent;
+import de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.AbstractScatterplotVisualization;
/**
* Tool to move the currently selected objects.
@@ -58,10 +57,8 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.events.ContextChangedEvent;
* @author Erich Schubert
*
* @apiviz.has NumberVector oneway - - edits
- *
- * @param <NV> Type of the NumberVector being visualized.
*/
-public class MoveObjectsToolVisualization<NV extends NumberVector<NV, ?>> extends P2DVisualization<NV> implements DragListener {
+public class MoveObjectsToolVisualization extends AbstractScatterplotVisualization implements DragListener {
/**
* A short name characterizing this Visualizer.
*/
@@ -84,19 +81,14 @@ public class MoveObjectsToolVisualization<NV extends NumberVector<NV, ?>> extend
public MoveObjectsToolVisualization(VisualizationTask task) {
super(task);
- context.addContextChangeListener(this);
incrementalRedraw();
}
@Override
- public void destroy() {
- super.destroy();
- context.removeContextChangeListener(this);
- }
-
- @Override
- public void contextChanged(ContextChangedEvent e) {
- synchronizedRedraw();
+ public void resultChanged(Result current) {
+ if(sample == current) {
+ synchronizedRedraw();
+ }
}
@Override
@@ -200,10 +192,8 @@ public class MoveObjectsToolVisualization<NV extends NumberVector<NV, ?>> extend
*
* @apiviz.stereotype factory
* @apiviz.uses MoveObjectsToolVisualization oneway - - «create»
- *
- * @param <NV> Type of the NumberVector being visualized.
*/
- public static class Factory<NV extends NumberVector<NV, ?>> extends AbstractVisFactory {
+ public static class Factory extends AbstractVisFactory {
/**
* Constructor
*/
@@ -213,7 +203,7 @@ public class MoveObjectsToolVisualization<NV extends NumberVector<NV, ?>> extend
@Override
public Visualization makeVisualization(VisualizationTask task) {
- return new MoveObjectsToolVisualization<NV>(task);
+ return new MoveObjectsToolVisualization(task);
}
@Override
@@ -222,13 +212,14 @@ public class MoveObjectsToolVisualization<NV extends NumberVector<NV, ?>> extend
if(!dbs.hasNext()) {
return;
}
- Iterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
- for(ScatterPlotProjector<?> p : IterableUtil.fromIterator(ps)) {
+ IterableIterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
+ for(ScatterPlotProjector<?> p : ps) {
final VisualizationTask task = new VisualizationTask(NAME, p.getRelation(), p.getRelation(), this);
task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_INTERACTIVE);
task.put(VisualizationTask.META_TOOL, true);
task.put(VisualizationTask.META_NOTHUMB, true);
task.put(VisualizationTask.META_NOEXPORT, true);
+ task.put(VisualizationTask.META_VISIBLE_DEFAULT, false);
// baseResult.getHierarchy().add(p.getRelation(), task);
baseResult.getHierarchy().add(p, task);
}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/SelectionConvexHullVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/selection/SelectionConvexHullVisualization.java
index fde2c00d..5702800d 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/SelectionConvexHullVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/selection/SelectionConvexHullVisualization.java
@@ -1,4 +1,4 @@
-package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
+package de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.selection;
/*
This file is part of ELKI:
@@ -24,18 +24,15 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
*/
import java.util.ArrayList;
-import java.util.Iterator;
import org.apache.batik.util.SVGConstants;
import org.w3c.dom.Element;
-import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.data.spatial.Polygon;
-import de.lmu.ifi.dbs.elki.database.datastore.DataStoreEvent;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreListener;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
-import de.lmu.ifi.dbs.elki.math.ConvexHull2D;
+import de.lmu.ifi.dbs.elki.math.geometry.GrahamScanConvexHull2D;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
import de.lmu.ifi.dbs.elki.result.DBIDSelection;
import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
@@ -43,7 +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.SelectionResult;
import de.lmu.ifi.dbs.elki.utilities.exceptions.ObjectNotFoundException;
-import de.lmu.ifi.dbs.elki.utilities.iterator.IterableUtil;
+import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
import de.lmu.ifi.dbs.elki.visualization.css.CSSClass;
import de.lmu.ifi.dbs.elki.visualization.projector.ScatterPlotProjector;
@@ -53,7 +50,7 @@ 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.events.ContextChangeListener;
+import de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.AbstractScatterplotVisualization;
import de.lmu.ifi.dbs.elki.visualization.visualizers.thumbs.ThumbnailVisualization;
/**
@@ -65,10 +62,8 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.thumbs.ThumbnailVisualizati
* @apiviz.has SelectionResult oneway - - visualizes
* @apiviz.has DBIDSelection oneway - - visualizes
* @apiviz.uses ConvexHull2D
- *
- * @param <NV> Type of the NumberVector being visualized.
*/
-public class SelectionConvexHullVisualization<NV extends NumberVector<NV, ?>> extends P2DVisualization<NV> implements ContextChangeListener, DataStoreListener {
+public class SelectionConvexHullVisualization extends AbstractScatterplotVisualization implements DataStoreListener {
/**
* A short name characterizing this Visualizer.
*/
@@ -86,7 +81,6 @@ public class SelectionConvexHullVisualization<NV extends NumberVector<NV, ?>> ex
*/
public SelectionConvexHullVisualization(VisualizationTask task) {
super(task);
- context.addContextChangeListener(this);
context.addResultListener(this);
context.addDataStoreListener(this);
incrementalRedraw();
@@ -98,7 +92,7 @@ public class SelectionConvexHullVisualization<NV extends NumberVector<NV, ?>> ex
DBIDSelection selContext = context.getSelection();
if(selContext != null) {
DBIDs selection = selContext.getSelectedIds();
- ConvexHull2D hull = new ConvexHull2D();
+ GrahamScanConvexHull2D hull = new GrahamScanConvexHull2D();
for(DBID i : selection) {
try {
hull.add(new Vector(proj.fastProjectDataToRenderSpace(rel.get(i))));
@@ -139,11 +133,6 @@ public class SelectionConvexHullVisualization<NV extends NumberVector<NV, ?>> ex
}
}
- @Override
- public void contentChanged(DataStoreEvent e) {
- synchronizedRedraw();
- }
-
/**
* Factory for visualizers to generate an SVG-Element containing the convex
* hull of the selected points
@@ -152,33 +141,27 @@ public class SelectionConvexHullVisualization<NV extends NumberVector<NV, ?>> ex
*
* @apiviz.stereotype factory
* @apiviz.uses SelectionConvexHullVisualization oneway - - «create»
- *
- * @param <NV> Type of the NumberVector being visualized.
*/
- public static class Factory<NV extends NumberVector<NV, ?>> extends AbstractVisFactory {
+ public static class Factory extends AbstractVisFactory {
/**
* Constructor
*/
public Factory() {
super();
+ thumbmask |= ThumbnailVisualization.ON_DATA | ThumbnailVisualization.ON_SELECTION;
}
@Override
public Visualization makeVisualization(VisualizationTask task) {
- return new SelectionConvexHullVisualization<NV>(task);
- }
-
- @Override
- public Visualization makeVisualizationOrThumbnail(VisualizationTask task) {
- return new ThumbnailVisualization(this, task, ThumbnailVisualization.ON_DATA | ThumbnailVisualization.ON_SELECTION);
+ return new SelectionConvexHullVisualization(task);
}
@Override
public void processNewResult(HierarchicalResult baseResult, Result result) {
final ArrayList<SelectionResult> selectionResults = ResultUtil.filterResults(result, SelectionResult.class);
for(SelectionResult selres : selectionResults) {
- Iterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
- for(ScatterPlotProjector<?> p : IterableUtil.fromIterator(ps)) {
+ IterableIterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
+ for(ScatterPlotProjector<?> p : ps) {
final VisualizationTask task = new VisualizationTask(NAME, selres, p.getRelation(), this);
task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_DATA - 2);
baseResult.getHierarchy().add(selres, task);
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/SelectionCubeVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/selection/SelectionCubeVisualization.java
index 087ec6af..9fd24b43 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/SelectionCubeVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/selection/SelectionCubeVisualization.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
+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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,13 +24,10 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
*/
import java.util.ArrayList;
-import java.util.Iterator;
import org.apache.batik.util.SVGConstants;
import org.w3c.dom.Element;
-import de.lmu.ifi.dbs.elki.data.NumberVector;
-import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
import de.lmu.ifi.dbs.elki.result.DBIDSelection;
import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
import de.lmu.ifi.dbs.elki.result.RangeSelection;
@@ -38,7 +35,7 @@ import de.lmu.ifi.dbs.elki.result.Result;
import de.lmu.ifi.dbs.elki.result.ResultUtil;
import de.lmu.ifi.dbs.elki.result.SelectionResult;
import de.lmu.ifi.dbs.elki.utilities.DatabaseUtil;
-import de.lmu.ifi.dbs.elki.utilities.iterator.IterableUtil;
+import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
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;
@@ -54,7 +51,7 @@ 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.events.ContextChangeListener;
+import de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.AbstractScatterplotVisualization;
import de.lmu.ifi.dbs.elki.visualization.visualizers.thumbs.ThumbnailVisualization;
/**
@@ -66,10 +63,8 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.thumbs.ThumbnailVisualizati
* @apiviz.has SelectionResult oneway - - visualizes
* @apiviz.has RangeSelection oneway - - visualizes
* @apiviz.uses SVGHyperCube
- *
- * @param <NV> Type of the NumberVector being visualized.
*/
-public class SelectionCubeVisualization<NV extends NumberVector<NV, ?>> extends P2DVisualization<NV> implements ContextChangeListener {
+public class SelectionCubeVisualization extends AbstractScatterplotVisualization {
/**
* A short name characterizing this Visualizer.
*/
@@ -99,11 +94,16 @@ public class SelectionCubeVisualization<NV extends NumberVector<NV, ?>> extends
super(task);
this.nofill = nofill;
addCSSClasses(svgp);
- context.addContextChangeListener(this);
context.addResultListener(this);
incrementalRedraw();
}
+ @Override
+ public void destroy() {
+ context.removeResultListener(this);
+ super.destroy();
+ }
+
/**
* Adds the required CSS-Classes
*
@@ -165,12 +165,12 @@ public class SelectionCubeVisualization<NV extends NumberVector<NV, ?>> extends
}
}
if(nofill) {
- Element r = SVGHyperCube.drawFrame(svgp, proj, new Vector(min), new Vector(max));
+ Element r = SVGHyperCube.drawFrame(svgp, proj, min, max);
SVGUtil.setCSSClass(r, CSS_CUBEFRAME);
layer.appendChild(r);
}
else {
- Element r = SVGHyperCube.drawFilled(svgp, CSS_CUBE, proj, new Vector(min), new Vector(max));
+ Element r = SVGHyperCube.drawFilled(svgp, CSS_CUBE, proj, min, max);
layer.appendChild(r);
}
@@ -193,10 +193,8 @@ public class SelectionCubeVisualization<NV extends NumberVector<NV, ?>> extends
*
* @apiviz.stereotype factory
* @apiviz.uses SelectionCubeVisualization oneway - - «create»
- *
- * @param <NV> vector type
*/
- public static class Factory<NV extends NumberVector<NV, ?>> extends AbstractVisFactory {
+ public static class Factory extends AbstractVisFactory {
/**
* Flag for half-transparent filling of selection cubes.
*
@@ -219,19 +217,20 @@ public class SelectionCubeVisualization<NV extends NumberVector<NV, ?>> extends
public Factory(boolean nofill) {
super();
this.nofill = nofill;
+ thumbmask |= ThumbnailVisualization.ON_DATA | ThumbnailVisualization.ON_SELECTION;
}
@Override
public Visualization makeVisualization(VisualizationTask task) {
- return new SelectionCubeVisualization<NV>(task, nofill);
+ return new SelectionCubeVisualization(task, nofill);
}
@Override
public void processNewResult(HierarchicalResult baseResult, Result result) {
final ArrayList<SelectionResult> selectionResults = ResultUtil.filterResults(result, SelectionResult.class);
for(SelectionResult selres : selectionResults) {
- Iterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
- for(ScatterPlotProjector<?> p : IterableUtil.fromIterator(ps)) {
+ IterableIterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
+ for(ScatterPlotProjector<?> p : ps) {
final VisualizationTask task = new VisualizationTask(NAME, selres, p.getRelation(), this);
task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_DATA - 2);
baseResult.getHierarchy().add(selres, task);
@@ -240,11 +239,6 @@ public class SelectionCubeVisualization<NV extends NumberVector<NV, ?>> extends
}
}
- @Override
- public Visualization makeVisualizationOrThumbnail(VisualizationTask task) {
- return new ThumbnailVisualization(this, task, ThumbnailVisualization.ON_DATA | ThumbnailVisualization.ON_SELECTION);
- }
-
/**
* Parameterization class.
*
@@ -252,7 +246,7 @@ public class SelectionCubeVisualization<NV extends NumberVector<NV, ?>> extends
*
* @apiviz.exclude
*/
- public static class Parameterizer<NV extends NumberVector<NV, ?>> extends AbstractParameterizer {
+ public static class Parameterizer extends AbstractParameterizer {
protected boolean nofill;
@Override
@@ -265,8 +259,8 @@ public class SelectionCubeVisualization<NV extends NumberVector<NV, ?>> extends
}
@Override
- protected Factory<NV> makeInstance() {
- return new Factory<NV>(nofill);
+ protected Factory makeInstance() {
+ return new Factory(nofill);
}
}
}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/SelectionDotVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/selection/SelectionDotVisualization.java
index 06167532..79d1afe5 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/SelectionDotVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/selection/SelectionDotVisualization.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
+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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,13 +24,10 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
*/
import java.util.ArrayList;
-import java.util.Iterator;
import org.apache.batik.util.SVGConstants;
import org.w3c.dom.Element;
-import de.lmu.ifi.dbs.elki.data.NumberVector;
-import de.lmu.ifi.dbs.elki.database.datastore.DataStoreEvent;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreListener;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
@@ -40,7 +37,7 @@ import de.lmu.ifi.dbs.elki.result.Result;
import de.lmu.ifi.dbs.elki.result.ResultUtil;
import de.lmu.ifi.dbs.elki.result.SelectionResult;
import de.lmu.ifi.dbs.elki.utilities.exceptions.ObjectNotFoundException;
-import de.lmu.ifi.dbs.elki.utilities.iterator.IterableUtil;
+import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
import de.lmu.ifi.dbs.elki.visualization.css.CSSClass;
import de.lmu.ifi.dbs.elki.visualization.projector.ScatterPlotProjector;
@@ -49,7 +46,7 @@ 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.events.ContextChangeListener;
+import de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.AbstractScatterplotVisualization;
import de.lmu.ifi.dbs.elki.visualization.visualizers.thumbs.ThumbnailVisualization;
/**
@@ -60,10 +57,8 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.thumbs.ThumbnailVisualizati
*
* @apiviz.has SelectionResult oneway - - visualizes
* @apiviz.has DBIDSelection oneway - - visualizes
- *
- * @param <NV> Type of the NumberVector being visualized.
*/
-public class SelectionDotVisualization<NV extends NumberVector<NV, ?>> extends P2DVisualization<NV> implements ContextChangeListener, DataStoreListener {
+public class SelectionDotVisualization extends AbstractScatterplotVisualization implements DataStoreListener {
/**
* A short name characterizing this Visualizer.
*/
@@ -81,13 +76,18 @@ public class SelectionDotVisualization<NV extends NumberVector<NV, ?>> extends P
*/
public SelectionDotVisualization(VisualizationTask task) {
super(task);
- context.addContextChangeListener(this);
context.addResultListener(this);
context.addDataStoreListener(this);
incrementalRedraw();
}
@Override
+ public void destroy() {
+ context.removeResultListener(this);
+ super.destroy();
+ }
+
+ @Override
protected void redraw() {
addCSSClasses(svgp);
final double size = context.getStyleLibrary().getSize(StyleLibrary.SELECTION);
@@ -124,11 +124,6 @@ public class SelectionDotVisualization<NV extends NumberVector<NV, ?>> extends P
}
}
- @Override
- public void contentChanged(DataStoreEvent e) {
- synchronizedRedraw();
- }
-
/**
* Factory for visualizers to generate an SVG-Element containing dots as
* markers representing the selected Database's objects.
@@ -137,33 +132,27 @@ public class SelectionDotVisualization<NV extends NumberVector<NV, ?>> extends P
*
* @apiviz.stereotype factory
* @apiviz.uses SelectionDotVisualization oneway - - «create»
- *
- * @param <NV> Type of the NumberVector being visualized.
*/
- public static class Factory<NV extends NumberVector<NV, ?>> extends AbstractVisFactory {
+ public static class Factory extends AbstractVisFactory {
/**
* Constructor
*/
public Factory() {
super();
+ thumbmask |= ThumbnailVisualization.ON_DATA | ThumbnailVisualization.ON_SELECTION;
}
@Override
public Visualization makeVisualization(VisualizationTask task) {
- return new SelectionDotVisualization<NV>(task);
- }
-
- @Override
- public Visualization makeVisualizationOrThumbnail(VisualizationTask task) {
- return new ThumbnailVisualization(this, task, ThumbnailVisualization.ON_DATA | ThumbnailVisualization.ON_SELECTION);
+ return new SelectionDotVisualization(task);
}
@Override
public void processNewResult(HierarchicalResult baseResult, Result result) {
final ArrayList<SelectionResult> selectionResults = ResultUtil.filterResults(result, SelectionResult.class);
for(SelectionResult selres : selectionResults) {
- Iterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
- for(ScatterPlotProjector<?> p : IterableUtil.fromIterator(ps)) {
+ IterableIterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
+ for(ScatterPlotProjector<?> p : ps) {
final VisualizationTask task = new VisualizationTask(NAME, selres, p.getRelation(), this);
task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_DATA - 1);
baseResult.getHierarchy().add(selres, task);
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/SelectionToolCubeVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/selection/SelectionToolCubeVisualization.java
index ed0b456d..8e86f920 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/SelectionToolCubeVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/selection/SelectionToolCubeVisualization.java
@@ -1,4 +1,4 @@
-package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
+package de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.selection;
/*
This file is part of ELKI:
@@ -25,7 +25,6 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
import java.util.ArrayList;
import java.util.BitSet;
-import java.util.Iterator;
import org.apache.batik.util.SVGConstants;
import org.w3c.dom.Element;
@@ -37,7 +36,6 @@ 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.logging.Logging;
-import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
import de.lmu.ifi.dbs.elki.result.DBIDSelection;
import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
import de.lmu.ifi.dbs.elki.result.RangeSelection;
@@ -45,7 +43,7 @@ import de.lmu.ifi.dbs.elki.result.Result;
import de.lmu.ifi.dbs.elki.result.ResultUtil;
import de.lmu.ifi.dbs.elki.result.SelectionResult;
import de.lmu.ifi.dbs.elki.utilities.DatabaseUtil;
-import de.lmu.ifi.dbs.elki.utilities.iterator.IterableUtil;
+import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleDoublePair;
import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
import de.lmu.ifi.dbs.elki.visualization.batikutil.DragableArea;
@@ -57,7 +55,7 @@ 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.events.ContextChangedEvent;
+import de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.AbstractScatterplotVisualization;
/**
* Tool-Visualization for the tool to select ranges
@@ -66,10 +64,8 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.events.ContextChangedEvent;
*
* @apiviz.has SelectionResult oneway - - updates
* @apiviz.has RangeSelection oneway - - updates
- *
- * @param <NV> Type of the NumberVector being visualized.
*/
-public class SelectionToolCubeVisualization<NV extends NumberVector<NV, ?>> extends P2DVisualization<NV> implements DragableArea.DragListener {
+public class SelectionToolCubeVisualization extends AbstractScatterplotVisualization implements DragableArea.DragListener {
/**
* The logger for this class.
*/
@@ -108,22 +104,10 @@ public class SelectionToolCubeVisualization<NV extends NumberVector<NV, ?>> exte
public SelectionToolCubeVisualization(VisualizationTask task) {
super(task);
this.dim = DatabaseUtil.dimensionality(rel);
- context.addContextChangeListener(this);
incrementalRedraw();
}
@Override
- public void destroy() {
- super.destroy();
- context.removeContextChangeListener(this);
- }
-
- @Override
- public void contextChanged(ContextChangedEvent e) {
- synchronizedRedraw();
- }
-
- @Override
protected void redraw() {
addCSSClasses(svgp);
@@ -160,20 +144,18 @@ public class SelectionToolCubeVisualization<NV extends NumberVector<NV, ?>> exte
*/
private void updateSelectionRectKoordinates(double x1, double x2, double y1, double y2, DoubleDoublePair[] ranges) {
BitSet actDim = proj.getVisibleDimensions2D();
- Vector v1 = new Vector(dim);
- Vector v2 = new Vector(dim);
- v1.set(0, x1);
- v1.set(1, y1);
- v2.set(0, x2);
- v2.set(1, y2);
+ double[] v1 = new double[dim];
+ double[] v2 = new double[dim];
+ v1[0] = x1;
+ v1[1] = y1;
+ v2[0] = x2;
+ v2[1] = y2;
- NV factory = DatabaseUtil.assumeVectorField(rel).getFactory();
-
- NV nv1 = proj.projectRenderToDataSpace(v1, factory);
- NV nv2 = proj.projectRenderToDataSpace(v2, factory);
+ double[] nv1 = proj.fastProjectRenderToDataSpace(v1);
+ double[] nv2 = proj.fastProjectRenderToDataSpace(v2);
for(int d = actDim.nextSetBit(0); d >= 0; d = actDim.nextSetBit(d + 1)) {
- ranges[d] = new DoubleDoublePair(Math.min(nv1.doubleValue(d + 1), nv2.doubleValue(d + 1)), Math.max(nv1.doubleValue(d + 1), nv2.doubleValue(d + 1)));
+ ranges[d] = new DoubleDoublePair(Math.min(nv1[d], nv2[d]), Math.max(nv1[d], nv2[d]));
}
}
@@ -240,7 +222,7 @@ public class SelectionToolCubeVisualization<NV extends NumberVector<NV, ?>> exte
selection.clear();
boolean idIn = true;
for(DBID id : rel.iterDBIDs()) {
- NV dbTupel = rel.get(id);
+ NumberVector<?, ?> dbTupel = rel.get(id);
idIn = true;
for(int i = 0; i < dim; i++) {
if(ranges != null && ranges[i] != null) {
@@ -282,10 +264,8 @@ public class SelectionToolCubeVisualization<NV extends NumberVector<NV, ?>> exte
*
* @apiviz.stereotype factory
* @apiviz.uses SelectionToolCubeVisualization oneway - - «create»
- *
- * @param <NV> Type of the NumberVector being visualized.
*/
- public static class Factory<NV extends NumberVector<NV, ?>> extends AbstractVisFactory {
+ public static class Factory extends AbstractVisFactory {
/**
* Constructor, adhering to
* {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable}
@@ -296,20 +276,21 @@ public class SelectionToolCubeVisualization<NV extends NumberVector<NV, ?>> exte
@Override
public Visualization makeVisualization(VisualizationTask task) {
- return new SelectionToolCubeVisualization<NV>(task);
+ return new SelectionToolCubeVisualization(task);
}
@Override
public void processNewResult(HierarchicalResult baseResult, Result result) {
final ArrayList<SelectionResult> selectionResults = ResultUtil.filterResults(result, SelectionResult.class);
for(SelectionResult selres : selectionResults) {
- Iterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
- for(ScatterPlotProjector<?> p : IterableUtil.fromIterator(ps)) {
+ IterableIterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
+ for(ScatterPlotProjector<?> p : ps) {
final VisualizationTask task = new VisualizationTask(NAME, selres, p.getRelation(), this);
task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_INTERACTIVE);
task.put(VisualizationTask.META_TOOL, true);
task.put(VisualizationTask.META_NOTHUMB, true);
task.put(VisualizationTask.META_NOEXPORT, true);
+ task.put(VisualizationTask.META_VISIBLE_DEFAULT, false);
baseResult.getHierarchy().add(selres, task);
baseResult.getHierarchy().add(p, task);
}
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/SelectionToolDotVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/selection/SelectionToolDotVisualization.java
index 7593dac5..877833f7 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/SelectionToolDotVisualization.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/selection/SelectionToolDotVisualization.java
@@ -1,4 +1,4 @@
-package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
+package de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.selection;
/*
This file is part of ELKI:
@@ -24,7 +24,6 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
*/
import java.util.ArrayList;
-import java.util.Iterator;
import org.apache.batik.dom.events.DOMMouseEvent;
import org.apache.batik.util.SVGConstants;
@@ -32,7 +31,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.ids.DBID;
import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
import de.lmu.ifi.dbs.elki.database.ids.HashSetModifiableDBIDs;
@@ -41,7 +39,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.SelectionResult;
-import de.lmu.ifi.dbs.elki.utilities.iterator.IterableUtil;
+import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator;
import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
import de.lmu.ifi.dbs.elki.visualization.batikutil.DragableArea;
import de.lmu.ifi.dbs.elki.visualization.css.CSSClass;
@@ -52,7 +50,7 @@ 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.events.ContextChangedEvent;
+import de.lmu.ifi.dbs.elki.visualization.visualizers.scatterplot.AbstractScatterplotVisualization;
/**
* Tool-Visualization for the tool to select objects
@@ -61,10 +59,8 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.events.ContextChangedEvent;
*
* @apiviz.has SelectionResult oneway - - updates
* @apiviz.has DBIDSelection oneway - - updates
- *
- * @param <NV> vector type
*/
-public class SelectionToolDotVisualization<NV extends NumberVector<NV, ?>> extends P2DVisualization<NV> implements DragableArea.DragListener {
+public class SelectionToolDotVisualization extends AbstractScatterplotVisualization implements DragableArea.DragListener {
/**
* A short name characterizing this Visualizer.
*/
@@ -101,22 +97,10 @@ public class SelectionToolDotVisualization<NV extends NumberVector<NV, ?>> exten
*/
public SelectionToolDotVisualization(VisualizationTask task) {
super(task);
- context.addContextChangeListener(this);
incrementalRedraw();
}
@Override
- public void destroy() {
- super.destroy();
- context.removeContextChangeListener(this);
- }
-
- @Override
- public void contextChanged(ContextChangedEvent e) {
- synchronizedRedraw();
- }
-
- @Override
protected void redraw() {
addCSSClasses(svgp);
@@ -255,10 +239,8 @@ public class SelectionToolDotVisualization<NV extends NumberVector<NV, ?>> exten
*
* @apiviz.stereotype factory
* @apiviz.uses SelectionToolDotVisualization - - «create»
- *
- * @param <NV> Type of the NumberVector being visualized.
*/
- public static class Factory<NV extends NumberVector<NV, ?>> extends AbstractVisFactory {
+ public static class Factory extends AbstractVisFactory {
/**
* Constructor, adhering to
* {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable}
@@ -269,20 +251,21 @@ public class SelectionToolDotVisualization<NV extends NumberVector<NV, ?>> exten
@Override
public Visualization makeVisualization(VisualizationTask task) {
- return new SelectionToolDotVisualization<NV>(task);
+ return new SelectionToolDotVisualization(task);
}
@Override
public void processNewResult(HierarchicalResult baseResult, Result result) {
final ArrayList<SelectionResult> selectionResults = ResultUtil.filterResults(result, SelectionResult.class);
for(SelectionResult selres : selectionResults) {
- Iterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
- for(ScatterPlotProjector<?> p : IterableUtil.fromIterator(ps)) {
+ IterableIterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
+ for(ScatterPlotProjector<?> p : ps) {
final VisualizationTask task = new VisualizationTask(NAME, selres, p.getRelation(), this);
task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_INTERACTIVE);
task.put(VisualizationTask.META_TOOL, true);
task.put(VisualizationTask.META_NOTHUMB, true);
task.put(VisualizationTask.META_NOEXPORT, true);
+ task.put(VisualizationTask.META_VISIBLE_DEFAULT, false);
baseResult.getHierarchy().add(selres, task);
baseResult.getHierarchy().add(p, task);
}
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
new file mode 100644
index 00000000..3710de5c
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/scatterplot/selection/package-info.java
@@ -0,0 +1,26 @@
+/**
+ * <p>Visualizers for object selection based on 2D projections.</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.visualization.visualizers.scatterplot.selection; \ No newline at end of file
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 5d79a986..2c9425de 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) 2011
+ Copyright (C) 2012
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.visualization.visualizers.thumbs;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
-
/**
* Thread to render thumbnails in the background.
*
@@ -47,11 +46,6 @@ public class ThumbnailThread extends Thread {
private boolean shutdown = false;
/**
- * Thumbnailer to use.
- */
- private Thumbnailer t = new Thumbnailer();
-
- /**
* The static thumbnail thread.
*/
private static ThumbnailThread THREAD = null;
@@ -113,7 +107,7 @@ public class ThumbnailThread extends Thread {
* @param ti Visualization task
*/
private void generateThumbnail(Task ti) {
- ti.callback.doThumbnail(t);
+ ti.callback.doThumbnail();
}
@Override
@@ -163,9 +157,7 @@ public class ThumbnailThread extends Thread {
public interface Listener {
/**
* Callback when to (re-)compute the thumbnail.
- *
- * @param t Thumbnailer to use
*/
- public void doThumbnail(Thumbnailer t);
+ public void doThumbnail();
}
} \ No newline at end of file
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 25f55d41..9ea016a5 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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -23,32 +23,30 @@ package de.lmu.ifi.dbs.elki.visualization.visualizers.thumbs;
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.io.File;
+import java.awt.image.BufferedImage;
import org.apache.batik.util.SVGConstants;
import org.w3c.dom.Element;
-import de.lmu.ifi.dbs.elki.database.datastore.DataStoreEvent;
import de.lmu.ifi.dbs.elki.database.datastore.DataStoreListener;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
import de.lmu.ifi.dbs.elki.result.Result;
import de.lmu.ifi.dbs.elki.result.SelectionResult;
import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
+import de.lmu.ifi.dbs.elki.visualization.batikutil.ThumbnailRegistryEntry;
+import de.lmu.ifi.dbs.elki.visualization.style.StyleResult;
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.AbstractVisualization;
import de.lmu.ifi.dbs.elki.visualization.visualizers.VisFactory;
import de.lmu.ifi.dbs.elki.visualization.visualizers.Visualization;
-import de.lmu.ifi.dbs.elki.visualization.visualizers.events.ContextChangedEvent;
-import de.lmu.ifi.dbs.elki.visualization.visualizers.events.ResizedEvent;
/**
* Thumbnail visualization.
*
* @author Erich Schubert
*
- * @apiviz.uses Thumbnailer
* @apiviz.uses ThumbnailThread
*/
public class ThumbnailVisualization extends AbstractVisualization implements ThumbnailThread.Listener, DataStoreListener {
@@ -63,14 +61,24 @@ public class ThumbnailVisualization extends AbstractVisualization implements Thu
public static final int ON_SELECTION = 2;
/**
+ * Constant to listen for style result changes
+ */
+ public static final int ON_STYLE = 4;
+
+ /**
+ * Constant to <em>not</em> listen for projection changes
+ */
+ public static final int NO_PROJECTION = 8;
+
+ /**
* Visualizer factory
*/
protected final VisFactory visFactory;
/**
- * The thumbnail file.
+ * The thumbnail id.
*/
- protected File thumb = null;
+ protected int thumbid = -1;
/**
* Pending redraw
@@ -83,11 +91,16 @@ public class ThumbnailVisualization extends AbstractVisualization implements Thu
protected int tresolution;
/**
- * The event mask. See {@link #ON_DATA}, {@link #ON_SELECTION}
+ * The event mask. See {@link #ON_DATA}, {@link #ON_SELECTION}, {@link #ON_STYLE}, {@link #NO_PROJECTION}
*/
private int mask;
/**
+ * Our thumbnail (keep a reference to prevent garbage collection!)
+ */
+ private BufferedImage thumb;
+
+ /**
* Constructor.
*
* @param visFactory Visualizer Factory to use
@@ -100,14 +113,13 @@ public class ThumbnailVisualization extends AbstractVisualization implements Thu
Integer tres = task.getGenerics(VisualizationTask.THUMBNAIL_RESOLUTION, Integer.class);
this.tresolution = tres;
this.layer = task.getPlot().svgElement(SVGConstants.SVG_G_TAG);
+ this.thumbid = -1;
this.thumb = null;
this.mask = mask;
// Listen for database events only when needed.
if((mask & ON_DATA) == ON_DATA) {
context.addDataStoreListener(this);
}
- // Always listen for context changes, in particular resize.
- context.addContextChangeListener(this);
// Listen for result changes, including the one we monitor
context.addResultListener(this);
}
@@ -117,45 +129,19 @@ public class ThumbnailVisualization extends AbstractVisualization implements Thu
if(pendingThumbnail != null) {
ThumbnailThread.UNQUEUE(pendingThumbnail);
}
+ // TODO: remove image from registry?
context.removeResultListener(this);
- context.removeContextChangeListener(this);
context.removeDataStoreListener(this);
}
@Override
public Element getLayer() {
- if(thumb == null) {
+ if(thumbid < 0) {
synchronizedRedraw();
}
return layer;
}
- @Override
- public void contextChanged(ContextChangedEvent e) {
- if(testRedraw(e)) {
- refreshThumbnail();
- }
- }
-
- /**
- * Override this method to add additional redraw triggers!
- *
- * @param e Event
- * @return Test result
- */
- @Override
- protected boolean testRedraw(ContextChangedEvent e) {
- if(e instanceof ResizedEvent) {
- return true;
- }
- return false;
- }
-
- @Override
- public void contentChanged(DataStoreEvent e) {
- refreshThumbnail();
- }
-
/**
* Redraw the visualization (maybe incremental).
*
@@ -182,7 +168,7 @@ public class ThumbnailVisualization extends AbstractVisualization implements Thu
*/
@Override
protected void redraw() {
- if(thumb == null) {
+ if(thumbid < 0) {
// LoggingUtil.warning("Generating new thumbnail " + this);
layer.appendChild(SVGUtil.svgWaitIcon(task.getPlot().getDocument(), 0, 0, task.getWidth(), task.getHeight()));
if(pendingThumbnail == null) {
@@ -196,13 +182,13 @@ public class ThumbnailVisualization extends AbstractVisualization implements Thu
SVGUtil.setAtt(i, SVGConstants.SVG_Y_ATTRIBUTE, 0);
SVGUtil.setAtt(i, SVGConstants.SVG_WIDTH_ATTRIBUTE, task.getWidth());
SVGUtil.setAtt(i, SVGConstants.SVG_HEIGHT_ATTRIBUTE, task.getHeight());
- i.setAttributeNS(SVGConstants.XLINK_NAMESPACE_URI, SVGConstants.XLINK_HREF_QNAME, thumb.toURI().toString());
+ i.setAttributeNS(SVGConstants.XLINK_NAMESPACE_URI, SVGConstants.XLINK_HREF_QNAME, ThumbnailRegistryEntry.INTERNAL_PROTOCOL + ":" + thumbid);
layer.appendChild(i);
}
}
@Override
- public synchronized void doThumbnail(Thumbnailer t) {
+ public synchronized void doThumbnail() {
pendingThumbnail = null;
try {
SVGPlot plot = new SVGPlot();
@@ -217,7 +203,8 @@ public class ThumbnailVisualization extends AbstractVisualization implements Thu
plot.updateStyleElement();
final int tw = (int) (task.getWidth() * tresolution);
final int th = (int) (task.getHeight() * tresolution);
- thumb = t.thumbnail(plot, tw, th);
+ thumb = plot.makeAWTImage(tw, th);
+ thumbid = ThumbnailRegistryEntry.registerImage(thumb);
// The visualization will not be used anymore.
vis.destroy();
synchronizedRedraw();
@@ -236,7 +223,9 @@ public class ThumbnailVisualization extends AbstractVisualization implements Thu
protected void refreshThumbnail() {
// Discard an existing thumbnail
+ thumbid = -1;
thumb = null;
+ // TODO: also purge from ThumbnailRegistryEntry?
synchronizedRedraw();
}
@@ -246,6 +235,14 @@ public class ThumbnailVisualization extends AbstractVisualization implements Thu
refreshThumbnail();
return;
}
+ if((mask & ON_STYLE) == ON_STYLE && current instanceof StyleResult) {
+ refreshThumbnail();
+ return;
+ }
+ if (task.getProj() != null && (mask & NO_PROJECTION) != NO_PROJECTION && current == task.getProj()) {
+ refreshThumbnail();
+ return;
+ }
super.resultChanged(current);
}
} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/thumbs/Thumbnailer.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/thumbs/Thumbnailer.java
deleted file mode 100644
index 1909821a..00000000
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/thumbs/Thumbnailer.java
+++ /dev/null
@@ -1,96 +0,0 @@
-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) 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 java.io.File;
-import java.io.IOException;
-
-import de.lmu.ifi.dbs.elki.logging.LoggingUtil;
-import de.lmu.ifi.dbs.elki.visualization.svg.SVGPlot;
-
-/**
- * Class that will render a {@link SVGPlot} into a {@link File} as thumbnail.
- *
- * Note: this does not happen in the background - call it from your own Thread if you need that!
- *
- * @author Erich Schubert
- *
- * @apiviz.uses SVGPlot oneway - - renders
- * @apiviz.has File oneway - - «create»
- */
-public class Thumbnailer {
- /**
- * Default prefix
- */
- private static final String DEFAULT_PREFIX = "elki-";
-
- /**
- * Prefix storage.
- */
- private String prefix;
-
- /**
- * Constructor
- * @param prefix Filename prefix to avoid collisions (e.g "elki-")
- */
- public Thumbnailer(String prefix) {
- this.prefix = prefix;
- }
-
- /**
- * Constructor
- */
- public Thumbnailer() {
- this(DEFAULT_PREFIX);
- }
-
- /**
- * Generate a thumbnail for a given plot.
- *
- * @param plot Plot to use
- * @param thumbwidth Width of the thumbnail
- * @param thumbheight height of the thumbnail
- * @return File object of the thumbnail, which has deleteOnExit set.
- */
- public synchronized File thumbnail(SVGPlot plot, int thumbwidth, int thumbheight) {
- File temp = null;
- try {
- temp = File.createTempFile(prefix, ".png");
- temp.deleteOnExit();
- plot.saveAsPNG(temp, thumbwidth, thumbheight);
- }
- catch(org.apache.batik.bridge.BridgeException e) {
- plot.dumpDebugFile();
- LoggingUtil.exception("Exception rendering thumbnail: ", e);
- }
- catch(org.apache.batik.transcoder.TranscoderException e) {
- plot.dumpDebugFile();
- LoggingUtil.exception("Exception rendering thumbnail: ", e);
- }
- catch(IOException e) {
- LoggingUtil.exception(e);
- }
- return temp;
- }
-} \ No newline at end of file
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 3006f52b..64676bb3 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) 2011
+Copyright (C) 2012
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/vis2d/ClusterConvexHullVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/ClusterConvexHullVisualization.java
deleted file mode 100644
index 0b97986b..00000000
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/ClusterConvexHullVisualization.java
+++ /dev/null
@@ -1,207 +0,0 @@
-package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
-
-/*
- 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 java.util.Collection;
-import java.util.Iterator;
-
-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.NumberVector;
-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;
-import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
-import de.lmu.ifi.dbs.elki.math.ConvexHull2D;
-import de.lmu.ifi.dbs.elki.math.DoubleMinMax;
-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.iterator.IterableUtil;
-import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
-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.projector.ScatterPlotProjector;
-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.SVGUtil;
-import de.lmu.ifi.dbs.elki.visualization.visualizers.AbstractVisFactory;
-import de.lmu.ifi.dbs.elki.visualization.visualizers.Visualization;
-
-/**
- * Visualizer for generating an SVG-Element containing the convex hull of each
- * cluster.
- *
- * @author Robert Rödler
- *
- * @apiviz.has Clustering oneway - - visualizes
- * @apiviz.uses ConvexHull2D
- *
- * @param <NV> Type of the NumberVector being visualized.
- */
-public class ClusterConvexHullVisualization<NV extends NumberVector<NV, ?>> extends P2DVisualization<NV> {
- /**
- * A short name characterizing this Visualizer.
- */
- private static final String NAME = "Cluster Convex Hull Visualization";
-
- /**
- * Generic tags to indicate the type of element. Used in IDs, CSS-Classes etc.
- */
- public static final String CONVEXHULL = "convexHull";
-
- /**
- * The result we work on
- */
- Clustering<Model> clustering;
-
- /**
- * The hulls
- */
- Element hulls;
-
- /**
- * Constructor
- *
- * @param task VisualizationTask
- */
- public ClusterConvexHullVisualization(VisualizationTask task) {
- super(task);
- this.clustering = task.getResult();
- context.addContextChangeListener(this);
- incrementalRedraw();
- }
-
- @Override
- protected void redraw() {
- // Viewport size, for "relative size" computations
- final Pair<DoubleMinMax, DoubleMinMax> viewp = proj.estimateViewport();
- double projarea = (viewp.getFirst().getDiff()) * (viewp.getSecond().getDiff());
-
- 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();
- ConvexHull2D hull = new ConvexHull2D();
-
- for(DBID clpnum : ids) {
- double[] projP = proj.fastProjectDataToRenderSpace(rel.get(clpnum).getColumnVector());
- hull.add(new Vector(projP));
- }
- Polygon chres = hull.getHull();
-
- // Plot the convex hull:
- if(chres != null) {
- SVGPath path = new SVGPath(chres);
- // 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);
-
- hulls = path.makeElement(svgp);
- addCSSClasses(svgp, cnum, opacity);
- SVGUtil.addCSSClass(hulls, CONVEXHULL + cnum);
- layer.appendChild(hulls);
- }
- }
- }
-
- /**
- * Adds the required CSS-Classes
- *
- * @param svgp SVG-Plot
- */
- private void addCSSClasses(SVGPlot svgp, int clusterID, double opac) {
- ColorLibrary colors = context.getStyleLibrary().getColorSet(StyleLibrary.PLOT);
-
- CSSClass cls = new CSSClass(this, CONVEXHULL + clusterID);
- cls.setStatement(SVGConstants.CSS_STROKE_WIDTH_PROPERTY, context.getStyleLibrary().getLineWidth(StyleLibrary.PLOT));
-
- final String color;
- if(clustering.getAllClusters().size() == 1) {
- color = "black";
- }
- else {
- 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);
-
- svgp.addCSSClassOrLogError(cls);
- }
-
- /**
- * Factory for visualizers to generate an SVG-Element containing the convex
- * hull of a cluster.
- *
- * @author Robert Rödler
- *
- * @apiviz.stereotype factory
- * @apiviz.uses ClusterConvexHullVisualization oneway - - «create»
- *
- * @param <NV> Type of the NumberVector being visualized.
- */
- public static class Factory<NV extends NumberVector<NV, ?>> extends AbstractVisFactory {
- /**
- * Constructor
- */
- public Factory() {
- super();
- }
-
- @Override
- public Visualization makeVisualization(VisualizationTask task) {
- return new ClusterConvexHullVisualization<NV>(task);
- }
-
- @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) {
- Iterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
- for(ScatterPlotProjector<?> p : IterableUtil.fromIterator(ps)) {
- final VisualizationTask task = new VisualizationTask(NAME, c, p.getRelation(), this);
- task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_DATA - 1);
- task.put(VisualizationTask.META_VISIBLE_DEFAULT, false);
- baseResult.getHierarchy().add(c, task);
- baseResult.getHierarchy().add(p, task);
- }
- }
- }
- }
-} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/ClusteringVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/ClusteringVisualization.java
deleted file mode 100644
index 4bef6e11..00000000
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/ClusteringVisualization.java
+++ /dev/null
@@ -1,154 +0,0 @@
-package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
-
-/*
- 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 java.util.Collection;
-import java.util.Iterator;
-
-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.Model;
-import de.lmu.ifi.dbs.elki.database.datastore.DataStoreEvent;
-import de.lmu.ifi.dbs.elki.database.datastore.DataStoreListener;
-import de.lmu.ifi.dbs.elki.database.ids.DBID;
-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.exceptions.ObjectNotFoundException;
-import de.lmu.ifi.dbs.elki.utilities.iterator.IterableUtil;
-import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
-import de.lmu.ifi.dbs.elki.visualization.projector.ScatterPlotProjector;
-import de.lmu.ifi.dbs.elki.visualization.style.StyleLibrary;
-import de.lmu.ifi.dbs.elki.visualization.style.marker.MarkerLibrary;
-import de.lmu.ifi.dbs.elki.visualization.visualizers.AbstractVisFactory;
-import de.lmu.ifi.dbs.elki.visualization.visualizers.Visualization;
-
-/**
- * Visualize a clustering using different markers for different clusters.
- *
- * @author Erich Schubert
- *
- * @apiviz.has Clustering oneway - - visualizes
- *
- * @param <NV> Type of the DatabaseObject being visualized.
- */
-// TODO: ensure we have the right database for this
-public class ClusteringVisualization<NV extends NumberVector<NV, ?>> extends P2DVisualization<NV> implements DataStoreListener {
- /**
- * The result we visualize
- */
- private Clustering<Model> clustering;
-
- /**
- * Constructor.
- *
- * @param task Visualization task
- */
- public ClusteringVisualization(VisualizationTask task) {
- super(task);
- this.clustering = task.getResult();
- context.addDataStoreListener(this);
- incrementalRedraw();
- }
-
- @Override
- public void destroy() {
- super.destroy();
- context.removeDataStoreListener(this);
- }
-
- @Override
- public void redraw() {
- MarkerLibrary ml = context.getStyleLibrary().markers();
- double marker_size = context.getStyleLibrary().getSize(StyleLibrary.MARKERPLOT);
- // draw data
- Iterator<Cluster<Model>> ci = clustering.getAllClusters().iterator();
- for(int cnum = 0; cnum < clustering.getAllClusters().size(); cnum++) {
- Cluster<?> clus = ci.next();
- for(DBID objId : clus.getIDs()) {
- try {
- final NV vec = rel.get(objId);
- double[] v = proj.fastProjectDataToRenderSpace(vec);
- ml.useMarker(svgp, layer, v[0], v[1], cnum, marker_size);
- }
- catch(ObjectNotFoundException e) {
- // ignore.
- }
- }
- }
- }
-
- @Override
- public void contentChanged(DataStoreEvent e) {
- synchronizedRedraw();
- }
-
- /**
- * Visualization factory
- *
- * @author Erich Schubert
- *
- * @apiviz.stereotype factory
- * @apiviz.uses ClusteringVisualization oneway - - «create»
- *
- * @param <NV> Type of the DatabaseObject being visualized.
- */
- public static class Factory<NV extends NumberVector<NV, ?>> extends AbstractVisFactory {
- /**
- * A short name characterizing this Visualizer.
- */
- private static final String NAME = "Cluster Markers";
-
- /**
- * Constructor, adhering to
- * {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable}
- */
- public Factory() {
- super();
- }
-
- @Override
- public Visualization makeVisualization(VisualizationTask task) {
- return new ClusteringVisualization<NV>(task);
- }
-
- @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) {
- if(c.getAllClusters().size() > 0) {
- Iterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(baseResult, ScatterPlotProjector.class);
- for(ScatterPlotProjector<?> p : IterableUtil.fromIterator(ps)) {
- final VisualizationTask task = new VisualizationTask(NAME, c, p.getRelation(), this);
- task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_DATA);
- baseResult.getHierarchy().add(c, task);
- baseResult.getHierarchy().add(p, task);
- }
- }
- }
- }
- }
-} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/DotVisualization.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/DotVisualization.java
deleted file mode 100644
index 3cfd5a48..00000000
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/vis2d/DotVisualization.java
+++ /dev/null
@@ -1,150 +0,0 @@
-package de.lmu.ifi.dbs.elki.visualization.visualizers.vis2d;
-
-/*
- 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 java.util.ArrayList;
-import java.util.Iterator;
-
-import org.w3c.dom.Element;
-
-import de.lmu.ifi.dbs.elki.data.Clustering;
-import de.lmu.ifi.dbs.elki.data.NumberVector;
-import de.lmu.ifi.dbs.elki.database.datastore.DataStoreEvent;
-import de.lmu.ifi.dbs.elki.database.datastore.DataStoreListener;
-import de.lmu.ifi.dbs.elki.database.ids.DBID;
-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.exceptions.ObjectNotFoundException;
-import de.lmu.ifi.dbs.elki.utilities.iterator.IterableUtil;
-import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
-import de.lmu.ifi.dbs.elki.visualization.projector.ScatterPlotProjector;
-import de.lmu.ifi.dbs.elki.visualization.style.StyleLibrary;
-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;
-
-/**
- * Generates a SVG-Element containing "dots" as markers representing the
- * Database's objects.
- *
- * @author Remigius Wojdanowski
- *
- * @apiviz.has NumberVector - - visualizes
- *
- * @param <NV> Type of the NumberVector being visualized.
- */
-public class DotVisualization<NV extends NumberVector<NV, ?>> extends P2DVisualization<NV> implements DataStoreListener {
- /**
- * A short name characterizing this Visualizer.
- */
- private static final String NAME = "Data Dots";
-
- /**
- * Generic tag to indicate the type of element. Used in IDs, CSS-Classes etc.
- */
- public static final String MARKER = "marker";
-
- /**
- * Constructor.
- *
- * @param task Task to visualize
- */
- public DotVisualization(VisualizationTask task) {
- super(task);
- context.addDataStoreListener(this);
- incrementalRedraw();
- }
-
- @Override
- public void destroy() {
- super.destroy();
- context.removeDataStoreListener(this);
- }
-
- @Override
- public void redraw() {
- // draw data
- double dot_size = context.getStyleLibrary().getSize(StyleLibrary.DOTPLOT);
- for(DBID id : rel.iterDBIDs()) {
- try {
- double[] v = proj.fastProjectDataToRenderSpace(rel.get(id));
- Element dot = svgp.svgCircle(v[0], v[1], dot_size);
- SVGUtil.addCSSClass(dot, MARKER);
- layer.appendChild(dot);
- }
- catch(ObjectNotFoundException e) {
- // ignore.
- }
-
- }
- }
-
- @Override
- public void contentChanged(DataStoreEvent e) {
- synchronizedRedraw();
- }
-
- /**
- * The visualization factory
- *
- * @author Erich Schubert
- *
- * @apiviz.stereotype factory
- * @apiviz.uses DotVisualization oneway - - «create»
- *
- * @param <NV> Type of the NumberVector being visualized.
- */
- public static class Factory<NV extends NumberVector<NV, ?>> extends AbstractVisFactory {
- /**
- * Constructor, adhering to
- * {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable}
- */
- public Factory() {
- super();
- }
-
- @Override
- public Visualization makeVisualization(VisualizationTask task) {
- return new DotVisualization<NV>(task);
- }
-
- @Override
- public void processNewResult(HierarchicalResult baseResult, Result result) {
- ArrayList<Clustering<?>> cs = ResultUtil.filterResults(result, Clustering.class);
- boolean hasClustering = (cs.size() > 0);
-
- Iterator<ScatterPlotProjector<?>> ps = ResultUtil.filteredResults(result, ScatterPlotProjector.class);
- for(ScatterPlotProjector<?> p : IterableUtil.fromIterator(ps)) {
- final VisualizationTask task = new VisualizationTask(NAME, p.getRelation(), p.getRelation(), this);
- task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_DATA + 1);
- if(hasClustering) {
- task.put(VisualizationTask.META_VISIBLE_DEFAULT, false);
- }
- // baseResult.getHierarchy().add(p.getRelation(), task);
- baseResult.getHierarchy().add(p, task);
- }
- }
- }
-} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/ClusterEvaluationVisFactory.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/ClusterEvaluationVisFactory.java
index 405ba673..05d9038c 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/ClusterEvaluationVisFactory.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/ClusterEvaluationVisFactory.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -24,12 +24,20 @@ 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;
-import de.lmu.ifi.dbs.elki.evaluation.paircounting.EvaluatePairCountingFMeasure;
-import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
+import de.lmu.ifi.dbs.elki.data.Clustering;
+import de.lmu.ifi.dbs.elki.evaluation.clustering.BCubed;
+import de.lmu.ifi.dbs.elki.evaluation.clustering.ClusterContingencyTable;
+import de.lmu.ifi.dbs.elki.evaluation.clustering.EditDistance;
+import de.lmu.ifi.dbs.elki.evaluation.clustering.Entropy;
+import de.lmu.ifi.dbs.elki.evaluation.clustering.EvaluateClustering;
+import de.lmu.ifi.dbs.elki.evaluation.clustering.PairCounting;
+import de.lmu.ifi.dbs.elki.evaluation.clustering.SetMatchingPurity;
+import de.lmu.ifi.dbs.elki.math.MeanVariance;
import de.lmu.ifi.dbs.elki.result.HierarchicalResult;
import de.lmu.ifi.dbs.elki.result.Result;
import de.lmu.ifi.dbs.elki.result.ResultUtil;
@@ -37,6 +45,7 @@ import de.lmu.ifi.dbs.elki.utilities.FormatUtil;
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;
+import de.lmu.ifi.dbs.elki.visualization.svg.SVGScoreBar;
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.StaticVisualization;
@@ -46,10 +55,11 @@ import de.lmu.ifi.dbs.elki.visualization.visualizers.Visualization;
* Pseudo-Visualizer, that lists the cluster evaluation results found.
*
* @author Erich Schubert
+ * @author Sascha Goldhofer
*
* @apiviz.stereotype factory
* @apiviz.uses StaticVisualization oneway - - «create»
- * @apiviz.has de.lmu.ifi.dbs.elki.evaluation.paircounting.EvaluatePairCountingFMeasure.ScoreResult oneway - - visualizes
+ * @apiviz.has EvaluateClustering.ScoreResult oneway - - visualizes
*/
public class ClusterEvaluationVisFactory extends AbstractVisFactory {
/**
@@ -58,68 +68,124 @@ public class ClusterEvaluationVisFactory extends AbstractVisFactory {
private static final String NAME = "Cluster Evaluation";
/**
+ * Constant: width of score bars
+ */
+ private static final double BARLENGTH = 5;
+
+ /**
+ * Constant: height of score bars
+ */
+ private static final double BARHEIGHT = 0.7;
+
+ /**
* Constructor.
*/
public ClusterEvaluationVisFactory() {
super();
}
-
+
@Override
public void processNewResult(HierarchicalResult baseResult, Result newResult) {
- final ArrayList<EvaluatePairCountingFMeasure.ScoreResult> srs = ResultUtil.filterResults(newResult, EvaluatePairCountingFMeasure.ScoreResult.class);
- for(EvaluatePairCountingFMeasure.ScoreResult sr : srs) {
+ final ArrayList<EvaluateClustering.ScoreResult> srs = ResultUtil.filterResults(newResult, EvaluateClustering.ScoreResult.class);
+ for(EvaluateClustering.ScoreResult sr : srs) {
final VisualizationTask task = new VisualizationTask(NAME, sr, null, this);
- task.width = 1.0;
- task.height = 0.5;
+ task.width = .5;
+ task.height = 2.0;
task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_STATIC);
baseResult.getHierarchy().add(sr, task);
}
}
+ private double addBarChart(SVGPlot svgp, Element parent, double ypos, String label, double maxValue, double value) {
+ SVGScoreBar barchart = new SVGScoreBar();
+ barchart.setFill(value, maxValue);
+ barchart.showValues(FormatUtil.NF4);
+ barchart.addLabel(label);
+ parent.appendChild(barchart.build(svgp, 0.0, ypos, BARLENGTH, BARHEIGHT));
+ ypos += 1;
+ return ypos;
+ }
+
+ private double addHeader(SVGPlot svgp, Element parent, double ypos, String text) {
+ ypos += .5;
+ Element object = svgp.svgText(0, ypos + BARHEIGHT * 0.5, text);
+ object.setAttribute(SVGConstants.SVG_STYLE_ATTRIBUTE, "font-size: 0.6; font-weight: bold");
+ parent.appendChild(object);
+ ypos += 1;
+ return ypos;
+ }
+
@Override
public Visualization makeVisualization(VisualizationTask task) {
- SVGPlot svgp = task.getPlot();
- Element layer = svgp.svgElement(SVGConstants.SVG_G_TAG);
- EvaluatePairCountingFMeasure.ScoreResult sr = task.getResult();
+ // TODO: make a utility class to wrap SVGPlot + parent layer + ypos.
- // TODO: use CSSClass and StyleLibrary
- int i = 0;
- {
- Element object = svgp.svgText(0, i + 0.7, "Same-cluster object pairs");
- object.setAttribute(SVGConstants.SVG_STYLE_ATTRIBUTE, "font-size: 0.6; font-weight: bold");
- layer.appendChild(object);
- i++;
- }
- {
- Element object = svgp.svgText(0, i + 0.7, "F1-Measure, Precision and Recall:");
- object.setAttribute(SVGConstants.SVG_STYLE_ATTRIBUTE, "font-size: 0.6; font-weight: bold");
- layer.appendChild(object);
- i++;
- }
- for(Vector vec : sr) {
- StringBuffer buf = new StringBuffer();
- double fmeasure = vec.get(0);
- double inboth = vec.get(1);
- double infirst = vec.get(2);
- double insecond = vec.get(3);
- buf.append(FormatUtil.format(fmeasure, FormatUtil.NF6));
- buf.append(" / ");
- buf.append(FormatUtil.format(inboth / (inboth + infirst), FormatUtil.NF6));
- buf.append(" / ");
- buf.append(FormatUtil.format(inboth / (inboth + insecond), FormatUtil.NF6));
- Element object = svgp.svgText(0, i + 0.7, buf.toString());
- object.setAttribute(SVGConstants.SVG_STYLE_ATTRIBUTE, "font-size: 0.6");
- layer.appendChild(object);
- i++;
+ 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) {
+ ypos = addHeader(svgp, parent, ypos, r.getLongName());
+ }
}
+ // TODO: use CSSClass and StyleLibrary
+
+ ypos = addHeader(svgp, parent, ypos, "Pair counting measures");
+
+ PairCounting paircount = cont.getPaircount();
+ ypos = addBarChart(svgp, parent, ypos, "Jaccard", 1, paircount.jaccard());
+ ypos = addBarChart(svgp, parent, ypos, "F1-Measure", 1, paircount.f1Measure());
+ ypos = addBarChart(svgp, parent, ypos, "Precision", 1, paircount.precision());
+ ypos = addBarChart(svgp, parent, ypos, "Recall", 1, paircount.recall());
+ ypos = addBarChart(svgp, parent, ypos, "Rand", 1, paircount.randIndex());
+ ypos = addBarChart(svgp, parent, ypos, "ARI", 1, paircount.adjustedRandIndex());
+ ypos = addBarChart(svgp, parent, ypos, "FowlkesMallows", 1, paircount.fowlkesMallows());
+
+ ypos = addHeader(svgp, parent, ypos, "Entropy based measures");
+
+ Entropy entropy = cont.getEntropy();
+ ypos = addBarChart(svgp, parent, ypos, "NMI Joint", 1, entropy.entropyNMIJoint());
+ ypos = addBarChart(svgp, parent, ypos, "NMI Sqrt", 1, entropy.entropyNMISqrt());
+
+ ypos = addHeader(svgp, parent, ypos, "BCubed-based measures");
+
+ BCubed bcubed = cont.getBCubed();
+ ypos = addBarChart(svgp, parent, ypos, "F1-Measure", 1, bcubed.f1Measure());
+ ypos = addBarChart(svgp, parent, ypos, "Recall", 1, bcubed.recall());
+ ypos = addBarChart(svgp, parent, ypos, "Precision", 1, bcubed.precision());
+
+ ypos = addHeader(svgp, parent, ypos, "Set-Matching-based measures");
+
+ SetMatchingPurity setm = cont.getSetMatching();
+ ypos = addBarChart(svgp, parent, ypos, "F1-Measure", 1, setm.f1Measure());
+ ypos = addBarChart(svgp, parent, ypos, "Purity", 1, setm.purity());
+ ypos = addBarChart(svgp, parent, ypos, "Inverse Purity", 1, setm.inversePurity());
+
+ ypos = addHeader(svgp, parent, ypos, "Editing-distance measures");
+
+ EditDistance edit = cont.getEdit();
+ ypos = addBarChart(svgp, parent, ypos, "F1-Measure", 1, edit.f1Measure());
+ ypos = addBarChart(svgp, parent, ypos, "Precision", 1, edit.editDistanceFirst());
+ ypos = addBarChart(svgp, parent, ypos, "Recall", 1, edit.editDistanceSecond());
+
+ ypos = addHeader(svgp, parent, ypos, "Gini measures");
+
+ final MeanVariance gini = cont.averageSymmetricGini();
+ ypos = addBarChart(svgp, parent, ypos, "Mean +-" + FormatUtil.format(gini.getSampleStddev(), FormatUtil.NF4), 1, gini.getMean());
- int cols = Math.max(10, (int) (i * task.getHeight() / task.getWidth()));
- int rows = i;
+ // scale vis
+ double cols = 10; // Math.max(10, (int) (i * task.getHeight() /
+ // task.getWidth()));
+ double rows = ypos;
final double margin = task.getContext().getStyleLibrary().getSize(StyleLibrary.MARGIN);
final String transform = SVGUtil.makeMarginTransform(task.getWidth(), task.getHeight(), cols, rows, margin / StyleLibrary.SCALE);
- SVGUtil.setAtt(layer, SVGConstants.SVG_TRANSFORM_ATTRIBUTE, transform);
+ SVGUtil.setAtt(parent, SVGConstants.SVG_TRANSFORM_ATTRIBUTE, transform);
- return new StaticVisualization(task, layer);
+ return new StaticVisualization(task, parent);
}
@Override
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/CurveVisFactory.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/CurveVisFactory.java
index 4d0e3dc0..e12a392a 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/CurveVisFactory.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/CurveVisFactory.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) 2011
+ Copyright (C) 2012
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.evaluation.roc.ComputeROCCurve;
import de.lmu.ifi.dbs.elki.evaluation.roc.ComputeROCCurve.ROCResult;
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.result.HierarchicalResult;
import de.lmu.ifi.dbs.elki.result.IterableResult;
import de.lmu.ifi.dbs.elki.result.Result;
@@ -45,7 +46,6 @@ import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
import de.lmu.ifi.dbs.elki.visualization.VisualizerContext;
import de.lmu.ifi.dbs.elki.visualization.css.CSSClass;
import de.lmu.ifi.dbs.elki.visualization.css.CSSClassManager.CSSNamingConflict;
-import de.lmu.ifi.dbs.elki.visualization.scales.LinearScale;
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;
@@ -118,8 +118,8 @@ public class CurveVisFactory extends AbstractVisFactory {
// add axes
try {
- SVGSimpleLinearAxis.drawAxis(svgp, layer, scalex, 0, sizey, sizex, sizey, true, true, context.getStyleLibrary());
- SVGSimpleLinearAxis.drawAxis(svgp, layer, scaley, 0, sizey, 0, 0, true, false, context.getStyleLibrary());
+ SVGSimpleLinearAxis.drawAxis(svgp, layer, scaley, 0, sizey, 0, 0, SVGSimpleLinearAxis.LabelStyle.LEFTHAND, context.getStyleLibrary());
+ SVGSimpleLinearAxis.drawAxis(svgp, layer, scalex, 0, sizey, sizex, sizey, SVGSimpleLinearAxis.LabelStyle.RIGHTHAND, context.getStyleLibrary());
}
catch(CSSNamingConflict e) {
LoggingUtil.exception(e);
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/HistogramVisFactory.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/HistogramVisFactory.java
index 81a77c13..117c3c2c 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/HistogramVisFactory.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/HistogramVisFactory.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -31,6 +31,7 @@ import org.w3c.dom.Element;
import de.lmu.ifi.dbs.elki.data.NumberVector;
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.result.HierarchicalResult;
import de.lmu.ifi.dbs.elki.result.HistogramResult;
import de.lmu.ifi.dbs.elki.result.Result;
@@ -40,7 +41,6 @@ import de.lmu.ifi.dbs.elki.visualization.VisualizerContext;
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.css.CSSClassManager.CSSNamingConflict;
-import de.lmu.ifi.dbs.elki.visualization.scales.LinearScale;
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;
@@ -141,8 +141,8 @@ public class HistogramVisFactory extends AbstractVisFactory {
// add axes
try {
- SVGSimpleLinearAxis.drawAxis(svgp, layer, xscale, 0, sizey, sizex, sizey, true, true, context.getStyleLibrary());
- SVGSimpleLinearAxis.drawAxis(svgp, layer, yscale, 0, sizey, 0, 0, true, false, context.getStyleLibrary());
+ SVGSimpleLinearAxis.drawAxis(svgp, layer, yscale, 0, sizey, 0, 0, SVGSimpleLinearAxis.LabelStyle.LEFTHAND, context.getStyleLibrary());
+ SVGSimpleLinearAxis.drawAxis(svgp, layer, xscale, 0, sizey, sizex, sizey, SVGSimpleLinearAxis.LabelStyle.RIGHTHAND, context.getStyleLibrary());
}
catch(CSSNamingConflict e) {
LoggingUtil.exception(e);
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/KeyVisFactory.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/KeyVisFactory.java
deleted file mode 100644
index e3a5dfd4..00000000
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/KeyVisFactory.java
+++ /dev/null
@@ -1,122 +0,0 @@
-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) 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 java.util.Collection;
-import java.util.List;
-
-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.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.visualization.VisualizationTask;
-import de.lmu.ifi.dbs.elki.visualization.VisualizerContext;
-import de.lmu.ifi.dbs.elki.visualization.style.StyleLibrary;
-import de.lmu.ifi.dbs.elki.visualization.style.marker.MarkerLibrary;
-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.StaticVisualization;
-import de.lmu.ifi.dbs.elki.visualization.visualizers.Visualization;
-
-/**
- * Pseudo-Visualizer, that gives the key for a clustering.
- *
- * @author Erich Schubert
- *
- * @apiviz.stereotype factory
- * @apiviz.uses StaticVisualization oneway - - «create»
- * @apiviz.has Clustering oneway - - visualizes
- */
-public class KeyVisFactory extends AbstractVisFactory {
- /**
- * Name for this visualizer.
- */
- private static final String NAME = "Cluster Key";
-
- /**
- * Constructor, adhering to
- * {@link de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable}
- */
- public KeyVisFactory() {
- super();
- }
-
- @Override
- public Visualization makeVisualization(VisualizationTask task) {
- Clustering<Model> clustering = task.getResult();
- SVGPlot svgp = task.getPlot();
- VisualizerContext context = task.getContext();
- final List<Cluster<Model>> allcs = clustering.getAllClusters();
- int numc = allcs.size();
-
- // FIXME: Use CSS and style library.
-
- Element layer = svgp.svgElement(SVGConstants.SVG_G_TAG);
-
- MarkerLibrary ml = context.getStyleLibrary().markers();
-
- int i = 0;
- for(Cluster<Model> c : allcs) {
- ml.useMarker(svgp, layer, 0.3, i + 0.5, i, 0.3);
- Element label = svgp.svgText(0.7, i + 0.7, c.getNameAutomatic());
- label.setAttribute(SVGConstants.SVG_STYLE_ATTRIBUTE, "font-size: 0.6");
- layer.appendChild(label);
- i++;
- }
-
- int cols = Math.max(6, (int) (numc * task.getHeight() / task.getWidth()));
- int rows = numc;
- final double margin = context.getStyleLibrary().getSize(StyleLibrary.MARGIN);
- final String transform = SVGUtil.makeMarginTransform(task.getWidth(), task.getHeight(), cols, rows, margin / StyleLibrary.SCALE);
- SVGUtil.setAtt(layer, SVGConstants.SVG_TRANSFORM_ATTRIBUTE, transform);
-
- return new StaticVisualization(task, layer);
- }
-
- @Override
- public void processNewResult(HierarchicalResult baseResult, Result newResult) {
- // Find clusterings we can visualize:
- Collection<Clustering<?>> clusterings = ResultUtil.filterResults(newResult, Clustering.class);
- for(Clustering<?> c : clusterings) {
- if(c.getAllClusters().size() > 0) {
- final VisualizationTask task = new VisualizationTask(NAME, c, null, this);
- task.width = 1.0;
- task.height = 1.0;
- task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_STATIC);
- baseResult.getHierarchy().add(c, task);
- }
- }
- }
-
- @Override
- public boolean allowThumbnails(VisualizationTask task) {
- return false;
- }
-} \ No newline at end of file
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
new file mode 100644
index 00000000..15c50a39
--- /dev/null
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/KeyVisualization.java
@@ -0,0 +1,198 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should 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 org.apache.batik.util.SVGConstants;
+import org.w3c.dom.Element;
+import org.w3c.dom.events.Event;
+import org.w3c.dom.events.EventListener;
+import org.w3c.dom.events.EventTarget;
+
+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.result.HierarchicalResult;
+import de.lmu.ifi.dbs.elki.result.Result;
+import de.lmu.ifi.dbs.elki.result.ResultUtil;
+import de.lmu.ifi.dbs.elki.visualization.VisualizationTask;
+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;
+import de.lmu.ifi.dbs.elki.visualization.style.marker.MarkerLibrary;
+import de.lmu.ifi.dbs.elki.visualization.svg.SVGButton;
+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.AbstractVisualization;
+import de.lmu.ifi.dbs.elki.visualization.visualizers.Visualization;
+
+/**
+ * Visualizer, displaying the key for a clustering.
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.has Clustering oneway - - visualizes
+ */
+public class KeyVisualization extends AbstractVisualization {
+ /**
+ * Name for this visualizer.
+ */
+ private static final String NAME = "Cluster Key";
+
+ /**
+ * Clustering to display
+ */
+ private Clustering<Model> clustering;
+
+ /**
+ * Constructor.
+ *
+ * @param task Visualization task
+ */
+ public KeyVisualization(VisualizationTask task) {
+ super(task);
+ this.clustering = task.getResult();
+ context.addResultListener(this);
+ }
+
+ @Override
+ public void destroy() {
+ context.removeResultListener(this);
+ super.destroy();
+ }
+
+ @Override
+ public void resultChanged(Result current) {
+ super.resultChanged(current);
+ if(current == context.getStyleResult()) {
+ incrementalRedraw();
+ }
+ }
+
+ @Override
+ protected void redraw() {
+ SVGPlot svgp = task.getPlot();
+ final List<Cluster<Model>> allcs = clustering.getAllClusters();
+
+ MarkerLibrary ml = context.getStyleLibrary().markers();
+ 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");
+ layer.appendChild(label);
+ }
+
+ // TODO: multi-column layout!
+ int i = 0;
+ for(Cluster<Model> c : allcs) {
+ ml.useMarker(svgp, layer, 0.3, i + 1.5, i, 0.3);
+ Element label = svgp.svgText(0.7, i + 1.7, c.getNameAutomatic());
+ label.setAttribute(SVGConstants.SVG_STYLE_ATTRIBUTE, "font-size: 0.6");
+ layer.appendChild(label);
+ i++;
+ }
+
+ // Add a button to set style policy
+ {
+ StylingPolicy sp = context.getStyleResult().getStylingPolicy();
+ 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, i + 1.1, 3.8, .7, .2);
+ // button.setTitle("Active style", "darkgray");
+ // layer.appendChild(button.render(svgp));
+ }
+ else {
+ SVGButton button = new SVGButton(.1, i + 1.1, 3.8, .7, .2);
+ button.setTitle("Set style", "black");
+ Element elem = button.render(svgp);
+ // Attach listener
+ EventTarget etr = (EventTarget) elem;
+ etr.addEventListener(SVGConstants.SVG_CLICK_EVENT_TYPE, new EventListener() {
+ @Override
+ public void handleEvent(Event evt) {
+ setStylePolicy();
+ }
+ }, false);
+ layer.appendChild(elem);
+ }
+ }
+
+ int rows = i + 2;
+ int cols = Math.max(6, (int) (rows * task.getHeight() / task.getWidth()));
+ final double margin = context.getStyleLibrary().getSize(StyleLibrary.MARGIN);
+ final String transform = SVGUtil.makeMarginTransform(task.getWidth(), task.getHeight(), cols, rows, margin / StyleLibrary.SCALE);
+ SVGUtil.setAtt(layer, SVGConstants.SVG_TRANSFORM_ATTRIBUTE, transform);
+ }
+
+ /**
+ * Trigger a style change.
+ */
+ protected void setStylePolicy() {
+ context.getStyleResult().setStylingPolicy(new ClusterStylingPolicy(clustering, context.getStyleLibrary()));
+ context.getHierarchy().resultChanged(context.getStyleResult());
+ }
+
+ /**
+ * Visualization factory
+ *
+ * @author Erich Schubert
+ *
+ * @apiviz.stereotype factory
+ * @apiviz.uses KeyVisualization oneway - - «create»
+ */
+ public static class Factory extends AbstractVisFactory {
+ @Override
+ public void processNewResult(HierarchicalResult baseResult, Result newResult) {
+ // Find clusterings we can visualize:
+ Iterator<Clustering<?>> clusterings = ResultUtil.filteredResults(newResult, Clustering.class);
+ while(clusterings.hasNext()) {
+ Clustering<?> c = clusterings.next();
+ if(c.getAllClusters().size() > 0) {
+ final VisualizationTask task = new VisualizationTask(NAME, c, null, this);
+ task.width = 1.0;
+ task.height = 1.0;
+ task.put(VisualizationTask.META_LEVEL, VisualizationTask.LEVEL_STATIC);
+ task.put(VisualizationTask.META_NODETAIL, true);
+ baseResult.getHierarchy().add(c, task);
+ }
+ }
+ }
+
+ @Override
+ public Visualization makeVisualization(VisualizationTask task) {
+ return new KeyVisualization(task);
+ }
+
+ @Override
+ public boolean allowThumbnails(VisualizationTask task) {
+ return false;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/LabelVisFactory.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/LabelVisFactory.java
index 6145b7a8..b6eb4549 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/LabelVisFactory.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/LabelVisFactory.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) 2011
+ Copyright (C) 2012
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 825d64b6..9269f404 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) 2011
+ Copyright (C) 2012
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/SettingsVisFactory.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/SettingsVisFactory.java
index 5d33fede..5bbc698c 100644
--- a/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/SettingsVisFactory.java
+++ b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/SettingsVisFactory.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) 2011
+ Copyright (C) 2012
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/SimilarityMatrixVisualizer.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/SimilarityMatrixVisualizer.java
index 17424519..c53a722a 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) 2011
+ Copyright (C) 2012
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/package-info.java b/src/de/lmu/ifi/dbs/elki/visualization/visualizers/visunproj/package-info.java
index 252bffc5..30042923 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) 2011
+Copyright (C) 2012
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 f212d818..807f2684 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) 2011
+ Copyright (C) 2012
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/EvaluationStep.java b/src/de/lmu/ifi/dbs/elki/workflow/EvaluationStep.java
index 70a7478c..65ac83a6 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) 2011
+ Copyright (C) 2012
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/InputStep.java b/src/de/lmu/ifi/dbs/elki/workflow/InputStep.java
index bdd60126..95a58f60 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) 2011
+ Copyright (C) 2012
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/LoggingStep.java b/src/de/lmu/ifi/dbs/elki/workflow/LoggingStep.java
index 5e1b1327..1e1a144f 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) 2011
+ Copyright (C) 2012
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/OutputStep.java b/src/de/lmu/ifi/dbs/elki/workflow/OutputStep.java
index a910245b..b7289f95 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) 2011
+ Copyright (C) 2012
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/WorkflowStep.java b/src/de/lmu/ifi/dbs/elki/workflow/WorkflowStep.java
index f27f5b5b..6117e3d6 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) 2011
+ Copyright (C) 2012
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 e81a0676..17cefb27 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) 2011
+Copyright (C) 2012
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
new file mode 100644
index 00000000..6909d2ff
--- /dev/null
+++ b/src/tutorial/distancefunction/MultiLPNorm.java
@@ -0,0 +1,126 @@
+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;
+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.parameterization.Parameterization;
+import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleListParameter;
+
+/*
+ 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/>.
+ */
+
+/**
+ * Tutorial example for ELKI.
+ *
+ * See <a
+ * href="http://elki.dbs.ifi.lmu.de/wiki/Tutorial/DistanceFunctions">Distance
+ * function tutorial</a>
+ *
+ * @author Erich Schubert
+ */
+public class MultiLPNorm extends AbstractVectorDoubleDistanceFunction {
+ /**
+ * The exponents
+ */
+ double[] ps;
+
+ /**
+ * Normalization factor (count(ps)/sum(ps))
+ */
+ double pinv;
+
+ /**
+ * Constructor.
+ *
+ * @param ps The exponents
+ */
+ public MultiLPNorm(double[] ps) {
+ super();
+ double sum = 0.0;
+ for(int dim = 0; dim < ps.length; dim++) {
+ assert (ps[dim] >= 0) : "Negative exponents are not allowed.";
+ sum += ps[dim];
+ }
+ assert (sum > 0) : "At least one exponent should be different from 0!";
+
+ this.ps = ps;
+ this.pinv = ps.length / sum;
+ }
+
+ @Override
+ public double doubleDistance(NumberVector<?, ?> o1, NumberVector<?, ?> o2) {
+ assert o1.getDimensionality() == ps.length : "Inappropriate dimensionality!";
+ assert o2.getDimensionality() == ps.length : "Inappropriate dimensionality!";
+
+ double sum = 0.0;
+ for(int dim = 0; dim < ps.length; dim++) {
+ if(ps[dim] > 0) {
+ final double delta = Math.abs(o1.doubleValue(dim + 1) - o2.doubleValue(dim + 1));
+ sum += Math.pow(delta, ps[dim]);
+ }
+ }
+ return Math.pow(sum, pinv);
+ }
+
+ @Override
+ public SimpleTypeInformation<? super NumberVector<?, ?>> getInputTypeRestriction() {
+ return new VectorFieldTypeInformation<NumberVector<?, ?>>(NumberVector.class, ps.length);
+ }
+
+ /**
+ * Parameterization class example
+ *
+ * @author Erich Schubert
+ */
+ public static class Parameterizer extends AbstractParameterizer {
+ /**
+ * Option ID for the exponents <code>
+ * -multinorm.ps
+ * </code>
+ */
+ public static final OptionID EXPONENTS_ID = OptionID.getOrCreateOptionID("multinorm.ps", "The exponents to use for this distance function");
+
+ /**
+ * P exponents
+ */
+ double[] ps;
+
+ @Override
+ protected void makeOptions(Parameterization config) {
+ super.makeOptions(config);
+ DoubleListParameter ps_param = new DoubleListParameter(EXPONENTS_ID);
+ if(config.grab(ps_param)) {
+ ps = ArrayLikeUtil.toPrimitiveDoubleArray(ps_param.getValue());
+ }
+ }
+
+ @Override
+ protected MultiLPNorm makeInstance() {
+ return new MultiLPNorm(ps);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/tutorial/distancefunction/TutorialDistanceFunction.java b/src/tutorial/distancefunction/TutorialDistanceFunction.java
new file mode 100644
index 00000000..0b225c61
--- /dev/null
+++ b/src/tutorial/distancefunction/TutorialDistanceFunction.java
@@ -0,0 +1,50 @@
+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
+ Ludwig-Maximilians-Universität München
+ Lehr- und Forschungseinheit für Datenbanksysteme
+ ELKI Development Team
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * Tutorial example for ELKI.
+ *
+ * See <a href="http://elki.dbs.ifi.lmu.de/wiki/Tutorial/DistanceFunctions">Distance function tutorial</a>
+ *
+ * @author Erich Schubert
+ */
+public class TutorialDistanceFunction extends AbstractVectorDoubleDistanceFunction {
+ @Override
+ public double doubleDistance(NumberVector<?, ?> o1, NumberVector<?, ?> o2) {
+ double dx = (o1.doubleValue(1) - o2.doubleValue(1));
+ double dy = (o1.doubleValue(2) - o2.doubleValue(2));
+ return dx * dx + Math.abs(dy);
+ }
+
+ @Override
+ public SimpleTypeInformation<? super NumberVector<?, ?>> getInputTypeRestriction() {
+ return new VectorFieldTypeInformation<NumberVector<?, ?>>(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
new file mode 100644
index 00000000..eec5b38c
--- /dev/null
+++ b/src/tutorial/distancefunction/package-info.java
@@ -0,0 +1,26 @@
+/**
+ * <p>Classes from the tutorial on implementing distance functions.</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 tutorial.distancefunction; \ No newline at end of file
diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/TreeSetDBIDs.java b/src/tutorial/package-info.java
index 43fff9ef..ede5b3a2 100644
--- a/src/de/lmu/ifi/dbs/elki/database/ids/TreeSetDBIDs.java
+++ b/src/tutorial/package-info.java
@@ -1,10 +1,11 @@
-package de.lmu.ifi.dbs.elki.database.ids;
-
+/**
+ * <p>Classes for ELKI tutorials.</p>
+ */
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -22,13 +23,5 @@ 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/>.
*/
+package tutorial;
-
-/**
- * Marker for sorted, tree-organized DBIDs
- *
- * @author Erich Schubert
- */
-public interface TreeSetDBIDs extends SetDBIDs {
- // Empty
-}
diff --git a/test/de/lmu/ifi/dbs/elki/AllTests.java b/test/de/lmu/ifi/dbs/elki/AllTests.java
index cc0e1af6..84f8e407 100644
--- a/test/de/lmu/ifi/dbs/elki/AllTests.java
+++ b/test/de/lmu/ifi/dbs/elki/AllTests.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/test/de/lmu/ifi/dbs/elki/JUnit4Test.java b/test/de/lmu/ifi/dbs/elki/JUnit4Test.java
index 023d0905..fc44d409 100644
--- a/test/de/lmu/ifi/dbs/elki/JUnit4Test.java
+++ b/test/de/lmu/ifi/dbs/elki/JUnit4Test.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) 2011
+ Copyright (C) 2012
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 894a314f..7b6fbbfa 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/AbstractSimpleAlgorithmTest.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/AbstractSimpleAlgorithmTest.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -34,7 +34,6 @@ import java.util.Iterator;
import java.util.List;
import de.lmu.ifi.dbs.elki.algorithm.clustering.trivial.ByLabelClustering;
-import de.lmu.ifi.dbs.elki.algorithm.clustering.trivial.ByLabelHierarchicalClustering;
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;
@@ -46,7 +45,7 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil;
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.evaluation.paircounting.PairCountingFMeasure;
+import de.lmu.ifi.dbs.elki.evaluation.clustering.ClusterContingencyTable;
import de.lmu.ifi.dbs.elki.evaluation.roc.ComputeROCCurve;
import de.lmu.ifi.dbs.elki.logging.Logging;
import de.lmu.ifi.dbs.elki.result.Result;
@@ -155,26 +154,9 @@ public abstract class AbstractSimpleAlgorithmTest {
ByLabelClustering bylabel = new ByLabelClustering();
Clustering<Model> rbl = bylabel.run(database);
- double score = PairCountingFMeasure.compareClusterings(clustering, rbl, 1.0);
- 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);
- }
-
- /**
- * Test the clustering result by comparing the score with an expected value.
- *
- * @param database Database to test
- * @param clustering Clustering result
- * @param expected Expected score
- */
- protected <O> void testFMeasureHierarchical(Database database, Clustering<?> clustering, double expected) {
- // Run by-label as reference
- ByLabelHierarchicalClustering bylabel = new ByLabelHierarchicalClustering();
- Clustering<Model> rbl = bylabel.run(database);
-
- double score = PairCountingFMeasure.compareClusterings(clustering, rbl, 1.0, false, true);
+ ClusterContingencyTable ct = new ClusterContingencyTable(true, false);
+ ct.process(clustering, rbl);
+ double score = ct.getPaircount().f1Measure();
if(logger.isVerbose()) {
logger.verbose(this.getClass().getSimpleName() + " score: " + score + " expect: " + expected);
}
diff --git a/test/de/lmu/ifi/dbs/elki/algorithm/TestKNNJoin.java b/test/de/lmu/ifi/dbs/elki/algorithm/TestKNNJoin.java
index fa5dbc14..c846aa6b 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/TestKNNJoin.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/TestKNNJoin.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -37,9 +37,9 @@ 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.DBID;
-import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
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.KNNResult;
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;
@@ -102,7 +102,7 @@ public class TestKNNJoin implements JUnit4Test {
MeanVariance meansize = new MeanVariance();
for(DBID id : relation.iterDBIDs()) {
- List<DistanceResultPair<DoubleDistance>> knnlist = knnq.getKNNForDBID(id, 2);
+ KNNResult<DoubleDistance> knnlist = knnq.getKNNForDBID(id, 2);
meansize.put(knnlist.size());
}
org.junit.Assert.assertEquals("Euclidean mean 2NN", mean2nnEuclid, meansize.getMean(), 0.00001);
@@ -115,7 +115,7 @@ public class TestKNNJoin implements JUnit4Test {
MeanVariance meansize = new MeanVariance();
for(DBID id : relation.iterDBIDs()) {
- List<DistanceResultPair<DoubleDistance>> knnlist = knnq.getKNNForDBID(id, 2);
+ KNNResult<DoubleDistance> knnlist = knnq.getKNNForDBID(id, 2);
meansize.put(knnlist.size());
}
org.junit.Assert.assertEquals("Manhattan mean 2NN", mean2nnManhattan, meansize.getMean(), 0.00001);
@@ -213,4 +213,4 @@ public class TestKNNJoin implements JUnit4Test {
org.junit.Assert.assertEquals("Manhattan variance 2NN", var2nnManhattan, meansize.getSampleVariance(), 0.00001);
}
}
-}
+} \ No newline at end of file
diff --git a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestDBSCANResults.java b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestDBSCANResults.java
index 025a6f4f..1e95165a 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestDBSCANResults.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestDBSCANResults.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) 2011
+ Copyright (C) 2012
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/clustering/TestDeLiCluResults.java b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestDeLiCluResults.java
index 9fc898f6..7b62b913 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestDeLiCluResults.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestDeLiCluResults.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,10 +27,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.algorithm.clustering.trivial.ByLabelClustering;
import de.lmu.ifi.dbs.elki.data.Clustering;
+import de.lmu.ifi.dbs.elki.data.model.Model;
import de.lmu.ifi.dbs.elki.database.Database;
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.utilities.ClassGenericsUtil;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.ParameterException;
@@ -70,7 +73,15 @@ public class TestDeLiCluResults extends AbstractSimpleAlgorithmTest implements J
// run DeLiClu on database
Clustering<?> clustering = opticsxi.run(db);
- testFMeasure(db, clustering, 0.8765283);
- testClusterSizes(clustering, new int[] { 108, 121, 210, 271 });
+
+ // Test F-Measure
+ ByLabelClustering bylabel = new ByLabelClustering();
+ Clustering<Model> rbl = bylabel.run(db);
+ ClusterContingencyTable ct = new ClusterContingencyTable(true, false);
+ ct.process(clustering, rbl);
+ double score = ct.getPaircount().f1Measure();
+ // We cannot test exactly - due to Hashing, DeLiClu sequence is not
+ // identical each time, the results will vary slightly.
+ org.junit.Assert.assertTrue(this.getClass().getSimpleName() + ": Score does not match: " + score, score > 0.85);
}
} \ No newline at end of file
diff --git a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestEMResults.java b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestEMResults.java
index 16edcf94..d9f6e7e6 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestEMResults.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestEMResults.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -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.clustering.kmeans.AbstractKMeans;
import de.lmu.ifi.dbs.elki.data.Clustering;
import de.lmu.ifi.dbs.elki.data.DoubleVector;
import de.lmu.ifi.dbs.elki.data.model.EMModel;
@@ -56,7 +57,7 @@ public class TestEMResults extends AbstractSimpleAlgorithmTest implements JUnit4
// Setup algorithm
ListParameterization params = new ListParameterization();
- params.addParameter(EM.SEED_ID, 1);
+ params.addParameter(AbstractKMeans.SEED_ID, 1);
params.addParameter(EM.K_ID, 5);
EM<DoubleVector> em = ClassGenericsUtil.parameterizeOrAbort(EM.class, params);
testParameterizationOk(params);
diff --git a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestOPTICSResults.java b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestOPTICSResults.java
index d91c1060..dde81a0f 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestOPTICSResults.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestOPTICSResults.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) 2011
+ Copyright (C) 2012
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/clustering/TestSLINKResults.java b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestSLINKResults.java
index b1a89360..18a16e0e 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestSLINKResults.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestSLINKResults.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) 2011
+ Copyright (C) 2012
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/clustering/TestSNNClusteringResults.java b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestSNNClusteringResults.java
index 43ae1a60..ba13af08 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestSNNClusteringResults.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestSNNClusteringResults.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) 2011
+ Copyright (C) 2012
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/clustering/correlation/TestCASHResults.java b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/TestCASHResults.java
index 33ba56c5..f6d4aba5 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
@@ -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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -73,11 +73,8 @@ public class TestCASHResults extends AbstractSimpleAlgorithmTest implements JUni
// run CASH on database
Clustering<Model> result = cash.run(db);
- testFMeasureHierarchical(db, result, 0.64102);
+ testFMeasure(db, result, 0.49055); // with hierarchical pairs: 0.64102
testClusterSizes(result, new int[] { 37, 71, 76, 442 });
- // Old heap scored worse?
- // testFMeasureHierarchical(db, result, 0.638727);
- // testClusterSizes(result, new int[] { 13, 65, 74, 75, 442 });
}
/**
diff --git a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/TestCOPACResults.java b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/TestCOPACResults.java
index 2fbe8401..8af036bf 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/TestCOPACResults.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/TestCOPACResults.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) 2011
+ Copyright (C) 2012
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/clustering/correlation/TestERiCResults.java b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/TestERiCResults.java
index ec030ec1..92a61e5e 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/TestERiCResults.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/TestERiCResults.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -87,7 +87,7 @@ public class TestERiCResults extends AbstractSimpleAlgorithmTest implements JUni
// run ERiC on database
Clustering<CorrelationModel<DoubleVector>> result = eric.run(db);
- testFMeasureHierarchical(db, result, 0.9204825);
+ testFMeasure(db, result, 0.714207); // Hierarchical pairs scored: 0.9204825
testClusterSizes(result, new int[] { 109, 184, 307 });
}
diff --git a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/TestFourCResults.java b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/TestFourCResults.java
index bfbddd64..8604a5f0 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/TestFourCResults.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/TestFourCResults.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -67,7 +67,7 @@ public class TestFourCResults extends AbstractSimpleAlgorithmTest implements JUn
// run 4C on database
Clustering<Model> result = fourc.run(db);
- testFMeasureHierarchical(db, result, 0.79467);
+ testFMeasure(db, result, 0.498048); // Hierarchical pairs scored: 0.79467
testClusterSizes(result, new int[] { 5, 595 });
}
diff --git a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/TestORCLUSResults.java b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/TestORCLUSResults.java
index 48b84d04..2660c586 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/TestORCLUSResults.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/correlation/TestORCLUSResults.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -68,7 +68,7 @@ public class TestORCLUSResults extends AbstractSimpleAlgorithmTest implements JU
// run ORCLUS on database
Clustering<Model> result = orclus.run(db);
- testFMeasureHierarchical(db, result, 0.789113);
+ testFMeasure(db, result, 0.640306); // Hierarchical pairs scored: 0.789113
testClusterSizes(result, new int[] { 22, 27, 401 });
}
diff --git a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestKMeansResults.java b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/TestKMeansResults.java
index d4557e8f..c35a7194 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/TestKMeansResults.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/TestKMeansResults.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.algorithm.clustering;
+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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -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.clustering.kmeans.KMeansLloyd;
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;
@@ -53,14 +54,37 @@ public class TestKMeansResults extends AbstractSimpleAlgorithmTest implements JU
* @throws ParameterException
*/
@Test
- public void testKMeansResults() {
+ public void testKMeansLloyd() {
Database db = makeSimpleDatabase(UNITTEST + "different-densities-2d-no-noise.ascii", 1000);
// Setup algorithm
ListParameterization params = new ListParameterization();
- params.addParameter(KMeans.K_ID, 5);
- params.addParameter(KMeans.SEED_ID, 3);
- KMeans<DoubleVector, DoubleDistance> kmeans = ClassGenericsUtil.parameterizeOrAbort(KMeans.class, params);
+ params.addParameter(AbstractKMeans.K_ID, 5);
+ params.addParameter(AbstractKMeans.SEED_ID, 3);
+ AbstractKMeans<DoubleVector, DoubleDistance> kmeans = ClassGenericsUtil.parameterizeOrAbort(KMeansLloyd.class, params);
+ testParameterizationOk(params);
+
+ // run KMeans on database
+ Clustering<MeanModel<DoubleVector>> result = kmeans.run(db);
+ testFMeasure(db, result, 0.998005);
+ testClusterSizes(result, new int[] { 199, 200, 200, 200, 201 });
+ }
+
+ /**
+ * Run KMeans with fixed parameters and compare the result to a golden
+ * standard.
+ *
+ * @throws ParameterException
+ */
+ @Test
+ public void testKMeansMacQueen() {
+ Database db = makeSimpleDatabase(UNITTEST + "different-densities-2d-no-noise.ascii", 1000);
+
+ // Setup algorithm
+ ListParameterization params = new ListParameterization();
+ params.addParameter(AbstractKMeans.K_ID, 5);
+ params.addParameter(AbstractKMeans.SEED_ID, 3);
+ AbstractKMeans<DoubleVector, DoubleDistance> kmeans = ClassGenericsUtil.parameterizeOrAbort(KMeansMacQueen.class, params);
testParameterizationOk(params);
// run KMeans on database
diff --git a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/TestCLIQUEResults.java b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/TestCLIQUEResults.java
index d2cacf1b..726efd76 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/TestCLIQUEResults.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/TestCLIQUEResults.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -27,13 +27,10 @@ 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.trivial.ByLabelClustering;
import de.lmu.ifi.dbs.elki.data.Clustering;
import de.lmu.ifi.dbs.elki.data.DoubleVector;
-import de.lmu.ifi.dbs.elki.data.model.Model;
import de.lmu.ifi.dbs.elki.data.model.SubspaceModel;
import de.lmu.ifi.dbs.elki.database.Database;
-import de.lmu.ifi.dbs.elki.evaluation.paircounting.PairCountingFMeasure;
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;
@@ -69,12 +66,9 @@ public class TestCLIQUEResults extends AbstractSimpleAlgorithmTest implements JU
// run CLIQUE on database
Clustering<SubspaceModel<DoubleVector>> result = clique.run(db);
- // Run by-label as reference
- ByLabelClustering bylabel = new ByLabelClustering(true, null);
- Clustering<Model> rbl = bylabel.run(db);
- double score = PairCountingFMeasure.compareClusterings(result, rbl, 1.0);
- org.junit.Assert.assertEquals(this.getClass().getSimpleName() + ": Score does not match.", 0.9882, score, 0.0001);
+ // PairCounting is not appropriate here: overlapping clusterings!
+ // testFMeasure(db, result, 0.9882);
testClusterSizes(result, new int[] { 200, 200, 216, 400 });
}
@@ -97,7 +91,8 @@ public class TestCLIQUEResults extends AbstractSimpleAlgorithmTest implements JU
// run CLIQUE on database
Clustering<SubspaceModel<DoubleVector>> result = clique.run(db);
- testFMeasure(db, result, 0.433661);
+ // PairCounting is not appropriate here: overlapping clusterings!
+ // testFMeasure(db, result, 0.433661);
testClusterSizes(result, new int[] { 255, 409, 458, 458, 480 });
}
} \ No newline at end of file
diff --git a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/TestDiSHResults.java b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/TestDiSHResults.java
index ca8f55b4..c7be9747 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/TestDiSHResults.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/TestDiSHResults.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -66,7 +66,7 @@ public class TestDiSHResults extends AbstractSimpleAlgorithmTest implements JUni
// run DiSH on database
Clustering<SubspaceModel<DoubleVector>> result = dish.run(db);
- testFMeasureHierarchical(db, result, 0.9991258);
+ testFMeasure(db, result, 0.996976); // Hierarchical pairs scored: 0.9991258
testClusterSizes(result, new int[] { 51, 199, 200 });
}
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 48dbe9c3..c5f37c88 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
@@ -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) 2011
+ Copyright (C) 2012
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/clustering/subspace/TestPreDeConResults.java b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/TestPreDeConResults.java
index 9e04d6d3..4d2bf7d0 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/TestPreDeConResults.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/TestPreDeConResults.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) 2011
+ Copyright (C) 2012
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/clustering/subspace/TestSUBCLUResults.java b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/TestSUBCLUResults.java
index 9f0e1550..817687c5 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/TestSUBCLUResults.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/clustering/subspace/TestSUBCLUResults.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -67,7 +67,8 @@ public class TestSUBCLUResults extends AbstractSimpleAlgorithmTest implements JU
// run SUBCLU on database
Clustering<SubspaceModel<DoubleVector>> result = subclu.run(db);
- testFMeasure(db, result, 0.9090);
+ // PairCounting is not appropriate here: overlapping clusterings!
+ // testFMeasure(db, result, 0.9090);
testClusterSizes(result, new int[] { 191, 194, 395 });
}
@@ -90,7 +91,8 @@ public class TestSUBCLUResults extends AbstractSimpleAlgorithmTest implements JU
// run SUBCLU on database
Clustering<SubspaceModel<DoubleVector>> result = subclu.run(db);
- testFMeasure(db, result, 0.49279033);
+ // PairCounting is not appropriate here: overlapping clusterings!
+ // testFMeasure(db, result, 0.49279033);
testClusterSizes(result, new int[] { 99, 247, 303, 323, 437, 459 });
}
} \ No newline at end of file
diff --git a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestABOD.java b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestABOD.java
index 022c448c..3490ce9a 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestABOD.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestABOD.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) 2011
+ Copyright (C) 2012
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/outlier/TestAggarwalYuEvolutionary.java b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestAggarwalYuEvolutionary.java
index c2f8c016..1eb0c713 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestAggarwalYuEvolutionary.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestAggarwalYuEvolutionary.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) 2011
+ Copyright (C) 2012
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/outlier/TestAggarwalYuNaive.java b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestAggarwalYuNaive.java
index 92c74f3c..937977f2 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestAggarwalYuNaive.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestAggarwalYuNaive.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) 2011
+ Copyright (C) 2012
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/outlier/TestDBOutlierDetection.java b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestDBOutlierDetection.java
index 79c596ff..0d6fc7f6 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestDBOutlierDetection.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestDBOutlierDetection.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) 2011
+ Copyright (C) 2012
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/outlier/TestDBOutlierScore.java b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestDBOutlierScore.java
index 875eceb3..b34c071e 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestDBOutlierScore.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestDBOutlierScore.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) 2011
+ Copyright (C) 2012
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/outlier/TestGaussianModel.java b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestGaussianModel.java
index 52c20bbe..e18c2f46 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestGaussianModel.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestGaussianModel.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) 2011
+ Copyright (C) 2012
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/outlier/TestGaussianUniformMixture.java b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestGaussianUniformMixture.java
index e0c54380..c02da8a5 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestGaussianUniformMixture.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestGaussianUniformMixture.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) 2011
+ Copyright (C) 2012
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/outlier/TestINFLO.java b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestINFLO.java
index 2323e512..39dd9bc0 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestINFLO.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestINFLO.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) 2011
+ Copyright (C) 2012
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/outlier/TestKNNOutlier.java b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestKNNOutlier.java
index a6708171..7d0457df 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestKNNOutlier.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestKNNOutlier.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) 2011
+ Copyright (C) 2012
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/outlier/TestKNNWeightOutlier.java b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestKNNWeightOutlier.java
index be5e2704..bbb1bdfb 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestKNNWeightOutlier.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestKNNWeightOutlier.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) 2011
+ Copyright (C) 2012
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/outlier/TestLDOF.java b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestLDOF.java
index 210a9e71..70a5b170 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestLDOF.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestLDOF.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -55,7 +55,7 @@ public class TestLDOF extends AbstractSimpleAlgorithmTest implements JUnit4Test
// run LDOF on database
OutlierResult result = ldof.run(db);
- testSingleScore(result, 1025, 0.8976268846182947);
testAUC(db, "Noise", result, 0.9637948717948718);
+ testSingleScore(result, 1025, 0.8976268846182947);
}
} \ No newline at end of file
diff --git a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestLOCI.java b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestLOCI.java
index 3d2cd32e..d95b362c 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestLOCI.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestLOCI.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -55,7 +55,7 @@ public class TestLOCI extends AbstractSimpleAlgorithmTest implements JUnit4Test
// run LOCI on database
OutlierResult result = loci.run(db);
- testAUC(db, "Noise", result, 0.954444);
- testSingleScore(result, 146, 4.14314916);
+ testAUC(db, "Noise", result, 0.96222222);
+ testSingleScore(result, 146, 3.8054382);
}
} \ No newline at end of file
diff --git a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestLOF.java b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestLOF.java
index e4d71111..a1ef967b 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestLOF.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestLOF.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) 2011
+ Copyright (C) 2012
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/outlier/TestLoOP.java b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestLoOP.java
index 18d759c5..653f4a29 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestLoOP.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestLoOP.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -55,7 +55,7 @@ public class TestLoOP extends AbstractSimpleAlgorithmTest implements JUnit4Test
// run LoOP on database
OutlierResult result = loop.run(db);
- testSingleScore(result, 945, 0.39805457858293325);
testAUC(db, "Noise", result, 0.9443796296296296);
+ testSingleScore(result, 945, 0.39805457858293325);
}
} \ No newline at end of file
diff --git a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestOPTICSOF.java b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestOPTICSOF.java
index be6779ff..ed9e1533 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestOPTICSOF.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestOPTICSOF.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) 2011
+ Copyright (C) 2012
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/outlier/TestOnlineLOF.java b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestOnlineLOF.java
index 4c875917..10cff737 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestOnlineLOF.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestOnlineLOF.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) 2011
+ Copyright (C) 2012
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/outlier/TestReferenceBasedOutlierDetection.java b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestReferenceBasedOutlierDetection.java
index 901f5a3e..5b6d3bde 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestReferenceBasedOutlierDetection.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestReferenceBasedOutlierDetection.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) 2011
+ Copyright (C) 2012
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/outlier/TestSOD.java b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestSOD.java
index cab95aff..de637957 100644
--- a/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestSOD.java
+++ b/test/de/lmu/ifi/dbs/elki/algorithm/outlier/TestSOD.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) 2011
+ Copyright (C) 2012
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.JUnit4Test;
import de.lmu.ifi.dbs.elki.algorithm.AbstractSimpleAlgorithmTest;
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.index.preprocessed.snn.SharedNearestNeighborPreprocessor;
import de.lmu.ifi.dbs.elki.result.outlier.OutlierResult;
import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil;
@@ -50,7 +51,7 @@ public class TestSOD extends AbstractSimpleAlgorithmTest implements JUnit4Test {
params.addParameter(SharedNearestNeighborPreprocessor.Factory.NUMBER_OF_NEIGHBORS_ID, 19);
// setup Algorithm
- SOD<DoubleVector> sod = ClassGenericsUtil.parameterizeOrAbort(SOD.class, params);
+ SOD<DoubleVector, DoubleDistance> sod = ClassGenericsUtil.parameterizeOrAbort(SOD.class, params);
testParameterizationOk(params);
// run SOD on database
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 0c568578..18e5c6ac 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
@@ -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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -79,6 +79,6 @@ public class TestFeatureBagging extends AbstractSimpleAlgorithmTest implements J
OutlierResult result = fb.run(db);
testSingleScore(result, 1293, 1.321709879);
- testAUC(db, "Noise", result, 0.88466106);
+ testAUC(db, "Noise", result, 0.884212);
}
} \ 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 1294c91a..60d7f678 100644
--- a/test/de/lmu/ifi/dbs/elki/data/spatial/TestPolygon.java
+++ b/test/de/lmu/ifi/dbs/elki/data/spatial/TestPolygon.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/test/de/lmu/ifi/dbs/elki/distance/distancefunction/SpatialPrimitiveDistanceFunctionTest.java b/test/de/lmu/ifi/dbs/elki/distance/distancefunction/SpatialPrimitiveDistanceFunctionTest.java
new file mode 100644
index 00000000..1c459717
--- /dev/null
+++ b/test/de/lmu/ifi/dbs/elki/distance/distancefunction/SpatialPrimitiveDistanceFunctionTest.java
@@ -0,0 +1,148 @@
+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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import org.junit.Test;
+
+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.distancevalue.Distance;
+import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
+
+/**
+ * Validate spatial distance functions by ensuring that mindist <= distance for
+ * random objects.
+ *
+ * @author Erich Schubert
+ *
+ */
+public class SpatialPrimitiveDistanceFunctionTest implements JUnit4Test {
+ @Test
+ public void testSpatialDistanceConsistency() {
+ final Random rnd = new Random(0);
+ final int dim = 7;
+ final int iters = 10000;
+
+ List<SpatialPrimitiveDistanceFunction<? super NumberVector<?, ?>, ?>> dists = new ArrayList<SpatialPrimitiveDistanceFunction<? super NumberVector<?, ?>, ?>>();
+ dists.add(EuclideanDistanceFunction.STATIC);
+ dists.add(ManhattanDistanceFunction.STATIC);
+ dists.add(MaximumDistanceFunction.STATIC);
+ dists.add(MinimumDistanceFunction.STATIC);
+ dists.add(new LPNormDistanceFunction(3));
+ dists.add(new LPNormDistanceFunction(.5));
+ dists.add(CanberraDistanceFunction.STATIC);
+ // Histogram intersection distance isn't proper for negative values
+ // dists.add(HistogramIntersectionDistanceFunction.STATIC);
+ dists.add(SquaredEuclideanDistanceFunction.STATIC);
+ dists.add(ArcCosineDistanceFunction.STATIC);
+ dists.add(CosineDistanceFunction.STATIC);
+
+ double[] d1 = new double[dim];
+ double[] d2 = new double[dim];
+ double[] d3 = new double[dim];
+ double[] d4 = new double[dim];
+ Vector v1 = new Vector(d1);
+ ModifiableHyperBoundingBox mbr = new ModifiableHyperBoundingBox(d2, d3);
+ Vector v2 = new Vector(d4);
+ for(int i = 0; i < iters; i++) {
+ for(int d = 0; d < dim; d++) {
+ d1[d] = (rnd.nextDouble() - .5) * 2E4;
+ d2[d] = (rnd.nextDouble() - .5) * 2E4;
+ d3[d] = (rnd.nextDouble() - .5) * 2E4;
+ if(d2[d] > d3[d]) {
+ double t = d2[d];
+ d2[d] = d3[d];
+ d3[d] = t;
+ }
+ double m = rnd.nextDouble();
+ d4[d] = m * d2[d] + (1 - m) * d3[d];
+ }
+ for(SpatialPrimitiveDistanceFunction<? super NumberVector<?, ?>, ?> dis : dists) {
+ compareDistances(v1, mbr, v2, dis);
+ }
+ }
+ }
+
+ @Test
+ public void testSpatialDistanceConsistencyPositive() {
+ final Random rnd = new Random(1);
+ final int dim = 7;
+ final int iters = 10000;
+
+ List<SpatialPrimitiveDistanceFunction<? super NumberVector<?, ?>, ?>> dists = new ArrayList<SpatialPrimitiveDistanceFunction<? super NumberVector<?, ?>, ?>>();
+ dists.add(EuclideanDistanceFunction.STATIC);
+ dists.add(ManhattanDistanceFunction.STATIC);
+ dists.add(MaximumDistanceFunction.STATIC);
+ dists.add(MinimumDistanceFunction.STATIC);
+ dists.add(new LPNormDistanceFunction(3));
+ dists.add(new LPNormDistanceFunction(.5));
+ dists.add(CanberraDistanceFunction.STATIC);
+ dists.add(HistogramIntersectionDistanceFunction.STATIC);
+ dists.add(SquaredEuclideanDistanceFunction.STATIC);
+ dists.add(ArcCosineDistanceFunction.STATIC);
+ dists.add(CosineDistanceFunction.STATIC);
+
+ double[] d1 = new double[dim];
+ double[] d2 = new double[dim];
+ double[] d3 = new double[dim];
+ double[] d4 = new double[dim];
+ Vector v1 = new Vector(d1);
+ ModifiableHyperBoundingBox mbr = new ModifiableHyperBoundingBox(d2, d3);
+ Vector v2 = new Vector(d4);
+ for(int i = 0; i < iters; i++) {
+ for(int d = 0; d < dim; d++) {
+ d1[d] = rnd.nextDouble() * 2E4;
+ d2[d] = rnd.nextDouble() * 2E4;
+ d3[d] = rnd.nextDouble() * 2E4;
+ if(d2[d] > d3[d]) {
+ double t = d2[d];
+ d2[d] = d3[d];
+ d3[d] = t;
+ }
+ double m = rnd.nextDouble();
+ d4[d] = m * d2[d] + (1 - m) * d3[d];
+ }
+ for(SpatialPrimitiveDistanceFunction<? super NumberVector<?, ?>, ?> dis : dists) {
+ compareDistances(v1, mbr, v2, dis);
+ }
+ }
+ }
+
+ protected <D extends Distance<D>> void compareDistances(Vector v1, ModifiableHyperBoundingBox mbr, Vector v2, SpatialPrimitiveDistanceFunction<? super NumberVector<?, ?>, D> dist) {
+ D exact = dist.distance(v1, v2);
+ D mind = dist.minDist(v1, v2);
+ D mbrd = dist.minDist(v1, mbr);
+ assertEquals("Not same: " + dist.toString(), exact, mind);
+ assertTrue("Not smaller:" + dist.toString() + " " + mbrd + " > " + exact + " " + mbr + " " + v1, mbrd.compareTo(exact) <= 0);
+ }
+} \ No newline at end of file
diff --git a/test/de/lmu/ifi/dbs/elki/evaluation/TestPairCountingFMeasure.java b/test/de/lmu/ifi/dbs/elki/evaluation/paircounting/TestClusterContingencyTable.java
index 123e2e4f..42188f56 100644
--- a/test/de/lmu/ifi/dbs/elki/evaluation/TestPairCountingFMeasure.java
+++ b/test/de/lmu/ifi/dbs/elki/evaluation/paircounting/TestClusterContingencyTable.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.evaluation;
+package de.lmu.ifi.dbs.elki.evaluation.paircounting;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -39,18 +39,18 @@ import de.lmu.ifi.dbs.elki.database.Database;
import de.lmu.ifi.dbs.elki.database.StaticArrayDatabase;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
import de.lmu.ifi.dbs.elki.datasource.FileBasedDatabaseConnection;
-import de.lmu.ifi.dbs.elki.evaluation.paircounting.PairCountingFMeasure;
+import de.lmu.ifi.dbs.elki.evaluation.clustering.ClusterContingencyTable;
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;
/**
- * Validate {@link PairCountingFMeasure} with respect to its ability to compare
+ * Validate {@link ClusterContingencyTable} with respect to its ability to compare
* data clusterings.
*
* @author Erich Schubert
*/
-public class TestPairCountingFMeasure implements JUnit4Test {
+public class TestClusterContingencyTable implements JUnit4Test {
// the following values depend on the data set used!
String dataset = "data/testdata/unittests/hierarchical-3d2d1d.csv";
@@ -58,7 +58,7 @@ public class TestPairCountingFMeasure implements JUnit4Test {
int shoulds = 600;
/**
- * Validate {@link PairCountingFMeasure} with respect to its ability to
+ * Validate {@link ClusterContingencyTable} with respect to its ability to
* compare data clusterings.
*
* @throws ParameterException on errors.
@@ -89,13 +89,19 @@ public class TestPairCountingFMeasure implements JUnit4Test {
ByLabelClustering bylabel = new ByLabelClustering();
Clustering<?> rbl = bylabel.run(db);
- assertEquals(1.0, PairCountingFMeasure.compareClusterings(rai, rai), Double.MIN_VALUE);
- assertEquals(1.0, PairCountingFMeasure.compareClusterings(ran, ran), Double.MIN_VALUE);
- assertEquals(1.0, PairCountingFMeasure.compareClusterings(rbl, rbl), Double.MIN_VALUE);
+ assertEquals(1.0, computeFMeasure(rai, rai, false), Double.MIN_VALUE);
+ assertEquals(1.0, computeFMeasure(ran, ran, false), Double.MIN_VALUE);
+ assertEquals(1.0, computeFMeasure(rbl, rbl, false), Double.MIN_VALUE);
- assertEquals(0.009950248756218905, PairCountingFMeasure.compareClusterings(ran, rbl, true, false), Double.MIN_VALUE);
- assertEquals(0.0033277870216306157, PairCountingFMeasure.compareClusterings(rai, ran, true, false), Double.MIN_VALUE);
+ assertEquals(0.009950248756218905, computeFMeasure(ran, rbl, true), Double.MIN_VALUE);
+ assertEquals(0.0033277870216306157, computeFMeasure(rai, ran, true), Double.MIN_VALUE);
- assertEquals(0.5 /* 0.3834296724470135 */, PairCountingFMeasure.compareClusterings(rai, rbl), Double.MIN_VALUE);
+ assertEquals(0.5 /* 0.3834296724470135 */, computeFMeasure(rai, rbl, false), Double.MIN_VALUE);
+ }
+
+ private double computeFMeasure(Clustering<?> c1, Clustering<?> c2, boolean noise) {
+ ClusterContingencyTable ct = new ClusterContingencyTable(true, noise);
+ ct.process(c1, c2);
+ return ct.getPaircount().f1Measure();
}
} \ No newline at end of file
diff --git a/test/de/lmu/ifi/dbs/elki/evaluation/TestComputeROC.java b/test/de/lmu/ifi/dbs/elki/evaluation/roc/TestComputeROC.java
index 2ad7c11f..206fbcfd 100644
--- a/test/de/lmu/ifi/dbs/elki/evaluation/TestComputeROC.java
+++ b/test/de/lmu/ifi/dbs/elki/evaluation/roc/TestComputeROC.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.evaluation;
+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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -42,7 +42,6 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
* Test to validate ROC curve computation.
*
* @author Erich Schubert
- *
*/
public class TestComputeROC implements JUnit4Test {
/**
diff --git a/test/de/lmu/ifi/dbs/elki/index/TestIndexStructures.java b/test/de/lmu/ifi/dbs/elki/index/TestIndexStructures.java
index 53801e09..4ce9dc6e 100644
--- a/test/de/lmu/ifi/dbs/elki/index/TestIndexStructures.java
+++ b/test/de/lmu/ifi/dbs/elki/index/TestIndexStructures.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) 2011
+ Copyright (C) 2012
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.database.ids.DBID;
import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
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.KNNResult;
import de.lmu.ifi.dbs.elki.database.query.knn.LinearScanKNNQuery;
import de.lmu.ifi.dbs.elki.database.query.range.LinearScanRangeQuery;
import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery;
@@ -56,7 +57,7 @@ import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.query.DoubleDistance
import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.query.DoubleDistanceRStarTreeRangeQuery;
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.util.ApproximateLeastOverlapInsertionStrategy;
+import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert.ApproximativeLeastOverlapInsertionStrategy;
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;
@@ -140,8 +141,8 @@ 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, ApproximateLeastOverlapInsertionStrategy.class);
- spatparams.addParameter(ApproximateLeastOverlapInsertionStrategy.Parameterizer.INSERTION_CANDIDATES_ID, 1);
+ spatparams.addParameter(AbstractRStarTreeFactory.INSERTION_STRATEGY_ID, ApproximativeLeastOverlapInsertionStrategy.class);
+ spatparams.addParameter(ApproximativeLeastOverlapInsertionStrategy.Parameterizer.INSERTION_CANDIDATES_ID, 1);
spatparams.addParameter(TreeIndexFactory.PAGE_SIZE_ID, 300);
testFileBasedDatabaseConnection(spatparams, DoubleDistanceRStarTreeKNNQuery.class, DoubleDistanceRStarTreeRangeQuery.class);
}
@@ -185,7 +186,7 @@ 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()));
- List<DistanceResultPair<DoubleDistance>> ids = knnq.getKNNForObject(dv, k);
+ KNNResult<DoubleDistance> ids = knnq.getKNNForObject(dv, k);
assertEquals("Result size does not match expectation!", shouldd.length, ids.size());
// verify that the neighbors match.
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 e3948fef..f2372d7a 100644
--- a/test/de/lmu/ifi/dbs/elki/index/preprocessed/TestMaterializedKNNAndRKNNPreprocessor.java
+++ b/test/de/lmu/ifi/dbs/elki/index/preprocessed/TestMaterializedKNNAndRKNNPreprocessor.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -44,6 +44,7 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDs;
import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair;
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.KNNResult;
import de.lmu.ifi.dbs.elki.database.query.knn.LinearScanKNNQuery;
import de.lmu.ifi.dbs.elki.database.query.rknn.LinearScanRKNNQuery;
import de.lmu.ifi.dbs.elki.database.query.rknn.RKNNQuery;
@@ -155,11 +156,11 @@ 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<List<DistanceResultPair<DoubleDistance>>> lin_knn_ids = lin_knn_query.getKNNForBulkDBIDs(sample, k);
- List<List<DistanceResultPair<DoubleDistance>>> preproc_knn_ids = preproc_knn_query.getKNNForBulkDBIDs(sample, k);
+ List<KNNResult<DoubleDistance>> lin_knn_ids = lin_knn_query.getKNNForBulkDBIDs(sample, k);
+ List<KNNResult<DoubleDistance>> preproc_knn_ids = preproc_knn_query.getKNNForBulkDBIDs(sample, k);
for(int i = 0; i < rep.size(); i++) {
- List<DistanceResultPair<DoubleDistance>> lin_knn = lin_knn_ids.get(i);
- List<DistanceResultPair<DoubleDistance>> pre_knn = preproc_knn_ids.get(i);
+ KNNResult<DoubleDistance> lin_knn = lin_knn_ids.get(i);
+ KNNResult<DoubleDistance> pre_knn = preproc_knn_ids.get(i);
if(!lin_knn.equals(pre_knn)) {
System.out.println("LIN kNN " + lin_knn);
System.out.println("PRE kNN " + pre_knn);
diff --git a/test/de/lmu/ifi/dbs/elki/logging/TestOutputStreamLogger.java b/test/de/lmu/ifi/dbs/elki/logging/TestOutputStreamLogger.java
index 7d0a9317..1ae0e71d 100644
--- a/test/de/lmu/ifi/dbs/elki/logging/TestOutputStreamLogger.java
+++ b/test/de/lmu/ifi/dbs/elki/logging/TestOutputStreamLogger.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/test/de/lmu/ifi/dbs/elki/math/TestAffineTransformation.java b/test/de/lmu/ifi/dbs/elki/math/TestAffineTransformation.java
index 0ac6b1a6..926c111c 100644
--- a/test/de/lmu/ifi/dbs/elki/math/TestAffineTransformation.java
+++ b/test/de/lmu/ifi/dbs/elki/math/TestAffineTransformation.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/test/de/lmu/ifi/dbs/elki/math/TestKernelDensityFitting.java b/test/de/lmu/ifi/dbs/elki/math/TestKernelDensityFitting.java
index 7533a235..c7ebfec2 100644
--- a/test/de/lmu/ifi/dbs/elki/math/TestKernelDensityFitting.java
+++ b/test/de/lmu/ifi/dbs/elki/math/TestKernelDensityFitting.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) 2011
+ Copyright (C) 2012
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.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.utilities.ClassGenericsUtil;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.ParameterException;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.ListParameterization;
@@ -138,8 +139,8 @@ public class TestKernelDensityFitting implements JUnit4Test {
params[0] = mv.getMean();
params[1] = mv.getSampleStddev();
// guess initial amplitude for an gaussian distribution.
- double c1 = MathUtil.erf(Math.abs(data[0] - params[0]) / (params[1] * Math.sqrt(2)));
- double c2 = MathUtil.erf(Math.abs(data[data.length - 1] - params[0]) / (params[1] * Math.sqrt(2)));
+ double c1 = NormalDistribution.erf(Math.abs(data[0] - params[0]) / (params[1] * Math.sqrt(2)));
+ double c2 = NormalDistribution.erf(Math.abs(data[data.length - 1] - params[0]) / (params[1] * Math.sqrt(2)));
params[2] = 1.0 / Math.min(c1, c2);
// System.out.println("Mean: " + params[0] + " Stddev: " + params[1] +
// " Amp: " + params[2]);
diff --git a/test/de/lmu/ifi/dbs/elki/math/TestLevenbergMarquardtGaussianFitting.java b/test/de/lmu/ifi/dbs/elki/math/TestLevenbergMarquardtGaussianFitting.java
index 46676c9b..54376c52 100644
--- a/test/de/lmu/ifi/dbs/elki/math/TestLevenbergMarquardtGaussianFitting.java
+++ b/test/de/lmu/ifi/dbs/elki/math/TestLevenbergMarquardtGaussianFitting.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/test/de/lmu/ifi/dbs/elki/math/TestMathUtil.java b/test/de/lmu/ifi/dbs/elki/math/TestMathUtil.java
index 16dfe77c..d8211741 100644
--- a/test/de/lmu/ifi/dbs/elki/math/TestMathUtil.java
+++ b/test/de/lmu/ifi/dbs/elki/math/TestMathUtil.java
@@ -1,17 +1,19 @@
package de.lmu.ifi.dbs.elki.math;
-import static org.junit.Assert.*;
+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
- Copyright (C) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -42,17 +44,57 @@ public class TestMathUtil implements JUnit4Test {
double[] weight2 = new double[size];
Random r = new Random(seed);
- for (int i = 0; i < size; i++) {
+ for(int i = 0; i < size; i++) {
data1[i] = r.nextDouble();
data2[i] = r.nextDouble();
weight1[i] = 1.0;
weight2[i] = 0.1;
}
-
+
double pear = MathUtil.pearsonCorrelationCoefficient(data1, data2);
double wpear1 = MathUtil.weightedPearsonCorrelationCoefficient(data1, data2, weight1);
double wpear2 = MathUtil.weightedPearsonCorrelationCoefficient(data1, data2, weight2);
assertEquals("Pearson and weighted pearson should be the same with constant weights.", pear, wpear1, 1E-10);
assertEquals("Weighted pearsons should be the same with constant weights.", wpear1, wpear2, 1E-10);
}
-}
+
+ @Test
+ public void testBitMath() {
+ assertEquals("Bit math issues", 1024, MathUtil.nextPow2Int(912));
+ assertEquals("Bit math issues", 8, MathUtil.nextPow2Int(5));
+ assertEquals("Bit math issues", 4, MathUtil.nextPow2Int(4));
+ assertEquals("Bit math issues", 4, MathUtil.nextPow2Int(3));
+ assertEquals("Bit math issues", 2, MathUtil.nextPow2Int(2));
+ assertEquals("Bit math issues", 1, MathUtil.nextPow2Int(1));
+ assertEquals("Bit math issues", 0, MathUtil.nextPow2Int(0));
+ assertEquals("Bit math issues", 1024L, MathUtil.nextPow2Long(912L));
+ assertEquals("Bit math issues", 0, MathUtil.nextPow2Int(-1));
+ assertEquals("Bit math issues", 0, MathUtil.nextPow2Int(-2));
+ assertEquals("Bit math issues", 0, MathUtil.nextPow2Int(-99));
+ assertEquals("Bit math issues", 15, MathUtil.nextAllOnesInt(8));
+ assertEquals("Bit math issues", 7, MathUtil.nextAllOnesInt(4));
+ assertEquals("Bit math issues", 3, MathUtil.nextAllOnesInt(3));
+ assertEquals("Bit math issues", 3, MathUtil.nextAllOnesInt(2));
+ assertEquals("Bit math issues", 1, MathUtil.nextAllOnesInt(1));
+ assertEquals("Bit math issues", 0, MathUtil.nextAllOnesInt(0));
+ assertEquals("Bit math issues", -1, MathUtil.nextAllOnesInt(-1));
+ assertEquals("Bit math issues", 0, 0 >>> 1);
+ }
+
+ @Test
+ public void testFloatToDouble() {
+ Random r = new Random(1l);
+ for(int i = 0; i < 10000; i++) {
+ final double dbl = Double.longBitsToDouble(r.nextLong());
+ final float flt = (float) dbl;
+ final double uppd = MathUtil.floatToDoubleUpper(flt);
+ final float uppf = (float) uppd;
+ final double lowd = MathUtil.floatToDoubleLower(flt);
+ final float lowf = (float) lowd;
+ assertTrue("Expected value to become larger, but " + uppd + " < " + dbl, uppd >= dbl || Double.isNaN(dbl));
+ assertTrue("Expected value to round to the same float.", flt == uppf || Double.isNaN(flt));
+ assertTrue("Expected value to become smaller, but " + lowd + " > " + dbl, lowd <= dbl || Double.isNaN(dbl));
+ assertTrue("Expected value to round to the same float.", flt == lowf || Double.isNaN(flt));
+ }
+ }
+} \ No newline at end of file
diff --git a/test/de/lmu/ifi/dbs/elki/math/TestMatrix.java b/test/de/lmu/ifi/dbs/elki/math/TestMatrix.java
index 0d22d19a..55c266d8 100644
--- a/test/de/lmu/ifi/dbs/elki/math/TestMatrix.java
+++ b/test/de/lmu/ifi/dbs/elki/math/TestMatrix.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/test/de/lmu/ifi/dbs/elki/math/TestWeightFunctions.java b/test/de/lmu/ifi/dbs/elki/math/TestWeightFunctions.java
index f07be82a..c24bab2e 100644
--- a/test/de/lmu/ifi/dbs/elki/math/TestWeightFunctions.java
+++ b/test/de/lmu/ifi/dbs/elki/math/TestWeightFunctions.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/test/de/lmu/ifi/dbs/elki/math/TestFlexiHistogram.java b/test/de/lmu/ifi/dbs/elki/math/histograms/TestFlexiHistogram.java
index b3db5b85..bcc7f330 100644
--- a/test/de/lmu/ifi/dbs/elki/math/TestFlexiHistogram.java
+++ b/test/de/lmu/ifi/dbs/elki/math/histograms/TestFlexiHistogram.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.math;
+package de.lmu.ifi.dbs.elki.math.histograms;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -30,7 +30,7 @@ import org.junit.Test;
import de.lmu.ifi.dbs.elki.JUnit4Test;
import de.lmu.ifi.dbs.elki.utilities.iterator.IterableUtil;
-import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
+import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleObjPair;
/**
* JUnit test to test the {@link ReplacingHistogram} class.
@@ -68,15 +68,15 @@ public class TestFlexiHistogram implements JUnit4Test {
// compare results via Iterator.
int off = 0;
- for(Pair<Double, Double> pair : hist) {
- assertEquals("Array iterator bin position", -0.1 + 0.2 * off, pair.getFirst(), 0.00001);
+ for(DoubleObjPair<Double> pair : hist) {
+ assertEquals("Array iterator bin position", -0.1 + 0.2 * off, pair.first, 0.00001);
assertEquals("Array iterator bin contents", resized[off], pair.getSecond(), 0.00001);
off++;
}
// backwards...
off--;
- for(Pair<Double, Double> pair : IterableUtil.fromIterator(hist.reverseIterator())) {
- assertEquals("Array iterator bin position", -0.1 + 0.2 * off, pair.getFirst(), 0.00001);
+ for(DoubleObjPair<Double> pair : IterableUtil.fromIterator(hist.reverseIterator())) {
+ assertEquals("Array iterator bin position", -0.1 + 0.2 * off, pair.first, 0.00001);
assertEquals("Array iterator bin contents", resized[off], pair.getSecond(), 0.00001);
off--;
}
diff --git a/test/de/lmu/ifi/dbs/elki/math/TestReplacingHistogram.java b/test/de/lmu/ifi/dbs/elki/math/histograms/TestReplacingHistogram.java
index 266a437f..455a880a 100644
--- a/test/de/lmu/ifi/dbs/elki/math/TestReplacingHistogram.java
+++ b/test/de/lmu/ifi/dbs/elki/math/histograms/TestReplacingHistogram.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.math;
+package de.lmu.ifi.dbs.elki.math.histograms;
/*
This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures
- Copyright (C) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -29,7 +29,7 @@ import static org.junit.Assert.assertEquals;
import org.junit.Test;
import de.lmu.ifi.dbs.elki.JUnit4Test;
-import de.lmu.ifi.dbs.elki.utilities.pairs.Pair;
+import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleObjPair;
/**
* JUnit test to test the {@link ReplacingHistogram} class.
@@ -66,8 +66,8 @@ public class TestReplacingHistogram implements JUnit4Test {
// compare results via Iterator.
int off = 0;
- for(Pair<Double, Double> pair : hist) {
- assertEquals("Array iterator bin position", -0.15 + 0.1 * off, pair.getFirst(), 0.00001);
+ for(DoubleObjPair<Double> pair : hist) {
+ assertEquals("Array iterator bin position", -0.15 + 0.1 * off, pair.first, 0.00001);
assertEquals("Array iterator bin contents", resized[off], pair.getSecond(), 0.00001);
off++;
}
diff --git a/test/de/lmu/ifi/dbs/elki/visualization/TestLinearScale.java b/test/de/lmu/ifi/dbs/elki/math/scales/TestLinearScale.java
index e4ca972b..f593902c 100644
--- a/test/de/lmu/ifi/dbs/elki/visualization/TestLinearScale.java
+++ b/test/de/lmu/ifi/dbs/elki/math/scales/TestLinearScale.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.visualization;
+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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -28,7 +28,7 @@ import static org.junit.Assert.assertEquals;
import org.junit.Test;
import de.lmu.ifi.dbs.elki.JUnit4Test;
-import de.lmu.ifi.dbs.elki.visualization.scales.LinearScale;
+import de.lmu.ifi.dbs.elki.math.scales.LinearScale;
/**
* Test class to test rounding of the linear scale.
diff --git a/test/de/lmu/ifi/dbs/elki/persistent/TestByteArrayUtil.java b/test/de/lmu/ifi/dbs/elki/persistent/TestByteArrayUtil.java
index 769b3fe2..21848a04 100644
--- a/test/de/lmu/ifi/dbs/elki/persistent/TestByteArrayUtil.java
+++ b/test/de/lmu/ifi/dbs/elki/persistent/TestByteArrayUtil.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/test/de/lmu/ifi/dbs/elki/persistent/TestOnDiskArray.java b/test/de/lmu/ifi/dbs/elki/persistent/TestOnDiskArray.java
index 910e4898..4483a29e 100644
--- a/test/de/lmu/ifi/dbs/elki/persistent/TestOnDiskArray.java
+++ b/test/de/lmu/ifi/dbs/elki/persistent/TestOnDiskArray.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/test/de/lmu/ifi/dbs/elki/persistent/TestOnDiskUpperTriangleMatrix.java b/test/de/lmu/ifi/dbs/elki/persistent/TestOnDiskUpperTriangleMatrix.java
index 2690a651..c5997615 100644
--- a/test/de/lmu/ifi/dbs/elki/persistent/TestOnDiskUpperTriangleMatrix.java
+++ b/test/de/lmu/ifi/dbs/elki/persistent/TestOnDiskUpperTriangleMatrix.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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
diff --git a/test/de/lmu/ifi/dbs/elki/utilities/TestBitsUtil.java b/test/de/lmu/ifi/dbs/elki/utilities/TestBitsUtil.java
new file mode 100644
index 00000000..504e5764
--- /dev/null
+++ b/test/de/lmu/ifi/dbs/elki/utilities/TestBitsUtil.java
@@ -0,0 +1,186 @@
+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/>.
+ */
+
+import static org.junit.Assert.*;
+
+import java.math.BigInteger;
+import java.util.BitSet;
+import java.util.Random;
+
+import org.junit.Test;
+
+import de.lmu.ifi.dbs.elki.JUnit4Test;
+import de.lmu.ifi.dbs.elki.utilities.BitsUtil;
+
+public class TestBitsUtil implements JUnit4Test {
+ @Test
+ public void testAgainstBigInteger() {
+ BigInteger bigint = new BigInteger("123");
+ long[] bituti = BitsUtil.make(Long.SIZE, 123);
+ assertEquals("Bit strings do not agree.", bigint.toString(2), BitsUtil.toString(bituti));
+
+ bigint = bigint.shiftLeft(13);
+ BitsUtil.shiftLeftI(bituti, 13);
+ assertEquals("Bit strings do not agree.", bigint.toString(2), BitsUtil.toString(bituti));
+
+ bigint = bigint.shiftRight(15);
+ BitsUtil.shiftRightI(bituti, 15);
+ assertEquals("Bit strings do not agree.", bigint.toString(2), BitsUtil.toString(bituti));
+ }
+
+ @Test
+ public void testSimpleOperations() {
+ long[] test = BitsUtil.zero(128);
+ BitsUtil.setI(test, 5);
+ BitsUtil.setI(test, 7);
+ assertEquals(BitsUtil.toString(test), "10100000");
+ assertEquals(BitsUtil.numberOfTrailingZerosSigned(test), 5);
+ BitsUtil.truncateI(test, 7);
+ assertEquals(BitsUtil.toString(test), "100000");
+ assertEquals(BitsUtil.numberOfTrailingZerosSigned(test), 5);
+ BitsUtil.setI(test, 7);
+ assertEquals(BitsUtil.toString(test), "10100000");
+ assertEquals(BitsUtil.numberOfTrailingZerosSigned(test), 5);
+ BitsUtil.cycleRightI(test, 6, 8);
+ assertEquals(BitsUtil.toString(test), "10000010");
+ assertEquals(BitsUtil.numberOfTrailingZerosSigned(test), 1);
+
+ BitsUtil.zeroI(test);
+ BitsUtil.setI(test, 125);
+ BitsUtil.setI(test, 60);
+ BitsUtil.cycleRightI(test, 70, 128);
+ assertTrue(BitsUtil.get(test, 55));
+ assertTrue(BitsUtil.get(test, 118));
+ assertEquals(BitsUtil.cardinality(test), 2);
+ BitsUtil.cycleLeftI(test, 70, 128);
+ assertTrue(BitsUtil.get(test, 125));
+ assertTrue(BitsUtil.get(test, 60));
+ assertEquals(BitsUtil.cardinality(test), 2);
+ }
+
+ @Test
+ public void testSorting() {
+ final Random r = new Random(0);
+ final int cnt = 100;
+ long[] rnds = new long[cnt];
+ long[][] bits = new long[cnt][];
+ for(int i = 0; i < cnt; i++) {
+ rnds[i] = Math.abs(r.nextLong());
+ bits[i] = BitsUtil.make(Long.SIZE, rnds[i]);
+ }
+
+ for(int i = 0; i < cnt; i++) {
+ for(int j = 0; j < cnt; j++) {
+ assertEquals(compare(rnds[i], rnds[j]), BitsUtil.compare(bits[i], bits[j]));
+ }
+ }
+
+ for(int i = 0; i < cnt; i++) {
+ long[] btmp = BitsUtil.copy(bits[i], 64 + r.nextInt(500));
+ assertEquals(BitsUtil.compare(btmp, bits[i]), 0);
+ for(int j = 0; j < cnt; j++) {
+ assertEquals(compare(rnds[i], rnds[j]), BitsUtil.compare(btmp, bits[j]));
+ }
+ }
+
+ for(int i = 0; i < cnt; i++) {
+ long[] btmp = BitsUtil.truncateI(BitsUtil.copy(bits[i]), 47);
+ for(int j = 0; j < cnt; j++) {
+ assertEquals(compare(rnds[i] & ((1 << 48) - 1), rnds[j]), BitsUtil.compare(btmp, bits[j]));
+ }
+ }
+
+ for(int i = 0; i < cnt; i++) {
+ long[] btmp = BitsUtil.cycleRightI(BitsUtil.copy(bits[i]), 13, Long.SIZE - 32);
+ long ltmp = BitsUtil.cycleRightC(rnds[i], 13, Long.SIZE - 32);
+ for(int j = 0; j < cnt; j++) {
+ assertEquals(compare(ltmp, rnds[j]), BitsUtil.compare(btmp, bits[j]));
+ }
+ }
+ }
+
+ /**
+ * Not jet in Java 6. To come in JDK7 as Long.copmare
+ *
+ * @param x
+ * @param y
+ * @return
+ */
+ public static int compare(long x, long y) {
+ return (x < y) ? -1 : ((x == y) ? 0 : 1);
+ }
+
+ @Test
+ public void testAgainstBitSet() {
+ BitSet bitset = new BitSet();
+ long[] bituti = BitsUtil.zero(Long.SIZE);
+ for (int i = 0; i >= 0;) {
+ assertEquals("Bit strings do not agree.", bitset.nextSetBit(i), BitsUtil.nextSetBit(bituti, i));
+ i = bitset.nextSetBit(i + 1);
+ }
+ // Java 7:
+ // assertEquals("Bit strings do not agree.", BitsUtil.toString(bitset.toLongArray()), BitsUtil.toString(bituti));
+
+ bitset.set(4);
+ BitsUtil.setI(bituti, 4);
+ for (int i = 0; i >= 0;) {
+ assertEquals("Bit strings do not agree.", bitset.nextSetBit(i), BitsUtil.nextSetBit(bituti, i));
+ i = bitset.nextSetBit(i + 1);
+ }
+ // Java 7:
+ // assertEquals("Bit strings do not agree.", BitsUtil.toString(bitset.toLongArray()), BitsUtil.toString(bituti));
+
+ bitset.set(15);
+ BitsUtil.setI(bituti, 15);
+ for (int i = 0; i >= 0;) {
+ assertEquals("Bit strings do not agree.", bitset.nextSetBit(i), BitsUtil.nextSetBit(bituti, i));
+ i = bitset.nextSetBit(i + 1);
+ }
+ // Java 7:
+ // assertEquals("Bit strings do not agree.", BitsUtil.toString(bitset.toLongArray()), BitsUtil.toString(bituti));
+
+ assertEquals(bitset.nextSetBit(0), BitsUtil.nextSetBit(bituti, 0));
+ assertEquals(bitset.nextSetBit(4), BitsUtil.nextSetBit(bituti, 4));
+ assertEquals(bitset.nextSetBit(5), BitsUtil.nextSetBit(bituti, 5));
+ // previousSetBit is not in JDK6.
+ // assertEquals(bitset.previousSetBit(64), BitsUtil.previousSetBit(bituti, 64));
+ // assertEquals(bitset.previousSetBit(15), BitsUtil.previousSetBit(bituti, 15));
+ // assertEquals(bitset.previousSetBit(14), BitsUtil.previousSetBit(bituti, 14));
+ }
+
+ @Test
+ public void testGrayCoding() {
+ long[] bits = BitsUtil.zero(123);
+ long[] ones = BitsUtil.ones(123);
+ BitsUtil.flipI(bits, 122);
+ BitsUtil.invgrayI(bits);
+ BitsUtil.xorI(bits, ones);
+ assertTrue(BitsUtil.isZero(bits));
+ BitsUtil.xorI(bits, ones);
+ BitsUtil.grayI(bits);
+ assertTrue(BitsUtil.get(bits, 122));
+ assertEquals(1, BitsUtil.cardinality(bits));
+ }
+} \ No newline at end of file
diff --git a/test/de/lmu/ifi/dbs/elki/utilities/datastructures/TestHeap.java b/test/de/lmu/ifi/dbs/elki/utilities/datastructures/TestHeap.java
deleted file mode 100644
index fcdc28d2..00000000
--- a/test/de/lmu/ifi/dbs/elki/utilities/datastructures/TestHeap.java
+++ /dev/null
@@ -1,64 +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) 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 static org.junit.Assert.assertEquals;
-
-import java.util.Collections;
-
-import org.junit.Test;
-
-import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.Heap;
-
-/**
- * Test the in-memory heap class.
- *
- * @author Erich Schubert
- */
-public class TestHeap {
- /**
- * Puts 10 integers into both an ascending and a descending heap and verifies
- * they come out in sequence.
- */
- @Test
- public void 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>();
- Heap<Integer> hdesc = new Heap<Integer>(Collections.reverseOrder());
- for(Integer i : data) {
- hasc.add(i);
- hdesc.add(i);
- }
- for(int i = 0; i < asc.length; i++) {
- final Integer gota = hasc.poll();
- assertEquals("Objects sorted incorrectly at ascending position " + i, asc[i], gota);
- }
- for(int i = 0; i < desc.length; i++) {
- final Integer gotd = hdesc.poll();
- assertEquals("Objects sorted incorrectly at descending position " + i, desc[i], gotd);
- }
- }
-}
diff --git a/test/de/lmu/ifi/dbs/elki/math/TestQuickSelect.java b/test/de/lmu/ifi/dbs/elki/utilities/datastructures/TestQuickSelect.java
index 132be182..b9030d59 100644
--- a/test/de/lmu/ifi/dbs/elki/math/TestQuickSelect.java
+++ b/test/de/lmu/ifi/dbs/elki/utilities/datastructures/TestQuickSelect.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.math;
+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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
@@ -31,7 +31,7 @@ import java.util.Random;
import org.junit.Test;
import de.lmu.ifi.dbs.elki.JUnit4Test;
-import de.lmu.ifi.dbs.elki.math.statistics.QuickSelect;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.QuickSelect;
/**
* Test the QuickSelect math class.
@@ -96,10 +96,10 @@ public class TestQuickSelect implements JUnit4Test {
@Test
public void testPartialArray() {
double data[] = new double[] { 0.1, 0.2, 1, 2, 3, 0.9, 0.95 };
- assertEquals("Partial median incorrect.", 1, QuickSelect.median(data, 2, 2), Double.MIN_VALUE);
- assertEquals("Partial median incorrect.", 3, QuickSelect.median(data, 4, 4), Double.MIN_VALUE);
+ assertEquals("Partial median incorrect.", 1, QuickSelect.median(data, 2, 3), Double.MIN_VALUE);
+ assertEquals("Partial median incorrect.", 3, QuickSelect.median(data, 4, 5), Double.MIN_VALUE);
// Note: do not change the order, since this modifies the array.
- assertEquals("Partial median incorrect.", 2, QuickSelect.median(data, 2, 4), Double.MIN_VALUE);
+ assertEquals("Partial median incorrect.", 2, QuickSelect.median(data, 2, 5), Double.MIN_VALUE);
// Note: do not change the order, since this modifies the array.
assertEquals("Full median incorrect.", 0.95, QuickSelect.median(data), Double.MIN_VALUE);
}
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
new file mode 100644
index 00000000..33ebdfae
--- /dev/null
+++ b/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestHeap.java
@@ -0,0 +1,235 @@
+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.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.
+ *
+ * @author Erich Schubert
+ */
+public class TestHeap {
+ /**
+ * 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;
+ 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());
+ 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 Integer gota = hasc.poll();
+ assertEquals("Objects sorted incorrectly at ascending position " + i, asc[i], gota);
+ final Integer gotd = hdesc.poll();
+ assertEquals("Objects sorted incorrectly at descending position " + i, desc[i], gotd);
+ }
+ }
+ // Refill
+ for(Integer 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 Integer gota = hasc.poll();
+ assertEquals("Objects sorted incorrectly at ascending position " + i, asc[i], gota);
+ final Integer 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 Integer gota = hasc.poll();
+ assertEquals("Objects sorted incorrectly at ascending position " + i, asc[i], gota);
+ final Integer 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 Integer gota = hasc.poll();
+ assertEquals("Objects sorted incorrectly at ascending position " + i, asc[i], gota);
+ final Integer 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 Integer gota = hasc.poll();
+ assertEquals("Objects sorted incorrectly at ascending position " + i, asc[i], gota);
+ final Integer 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 Integer gota = hasc.poll();
+ assertEquals("Objects sorted incorrectly at ascending position " + i, asc[i], gota);
+ final Integer 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 Integer gota = hasc.poll();
+ //System.err.println(hasc.toString() + " " + hasc.validSize);
+ assertEquals("Objects sorted incorrectly at ascending position " + i, asc[i], gota);
+ final Integer 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);
+ Heap<Integer> hasc = new Heap<Integer>();
+ Heap<Integer> hdesc = new Heap<Integer>(Collections.reverseOrder());
+ 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/TestHeapPerformance.java b/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestHeapPerformance.java
new file mode 100644
index 00000000..2f990e30
--- /dev/null
+++ b/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestHeapPerformance.java
@@ -0,0 +1,113 @@
+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;
+
+import de.lmu.ifi.dbs.elki.JUnit4Test;
+import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.Heap;
+
+/**
+ * Unit test to ensure that our heap is not significantly worse than SUN javas
+ * regular PriorityQueue.
+ *
+ * @author Erich Schubert
+ */
+public class TestHeapPerformance implements JUnit4Test {
+ 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<Integer>(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++) {
+ Heap<Integer> pq = new Heap<Integer>();
+ testQueue(elements, pq);
+ }
+ for(int j = 0; j < iterations; j++) {
+ PriorityQueue<Integer> pq = new PriorityQueue<Integer>(); // 11,
+ testQueue(elements, pq);
+ }
+ }
+
+ long hstart = System.nanoTime();
+ {
+ for(int j = 0; j < iterations; j++) {
+ Heap<Integer> pq = new Heap<Integer>();
+ testQueue(elements, pq);
+ }
+ }
+ long htime = System.nanoTime() - hstart;
+
+ long pqstart = System.nanoTime();
+ {
+ for(int j = 0; j < iterations; j++) {
+ PriorityQueue<Integer> pq = new PriorityQueue<Integer>(); // 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 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/TestTiedTopBoundedHeap.java b/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestTiedTopBoundedHeap.java
index cb4492b8..8059a873 100644
--- a/test/de/lmu/ifi/dbs/elki/utilities/datastructures/TestTiedTopBoundedHeap.java
+++ b/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestTiedTopBoundedHeap.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.utilities.datastructures;
+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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
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
new file mode 100644
index 00000000..b5ad9b2c
--- /dev/null
+++ b/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestTiedTopBoundedUpdatableHeap.java
@@ -0,0 +1,114 @@
+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.Random;
+
+import org.junit.Test;
+
+import de.lmu.ifi.dbs.elki.JUnit4Test;
+
+public class TestTiedTopBoundedUpdatableHeap implements JUnit4Test {
+ @Test
+ public void testTiedTopBoundedUpdatableHeap() {
+ final int iters = 100;
+ final int maxid = 5000;
+ 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);
+ 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);
+ // Update heap
+ heap.offer(nobj);
+ // Enabling the followig assertion *hides* certain problems!
+ // assertTrue("Heap not valid at i="+i, heap.checkHeap());
+ // Update simulation
+ boolean found = false;
+ for(IntegerPriorityObject<Integer> ent : simulate) {
+ if(ent.getObject().equals(id)) {
+ if(score > ent.priority) {
+ ent.priority = score;
+ }
+ found = true;
+ break;
+ }
+ }
+ if(!found) {
+ simulate.add(nobj);
+ }
+ Collections.sort(simulate, Collections.reverseOrder());
+ while(simulate.size() > limit) {
+ int max = simulate.get(limit - 1).priority;
+ if(simulate.get(simulate.size() - 1).priority == max) {
+ break;
+ }
+ else {
+ assertTrue(simulate.get(simulate.size() - 1).priority > max);
+ simulate.remove(simulate.size() - 1);
+ }
+ }
+ if(simulate.size() != heap.size()) {
+ System.err.println("Lost synchronization " + i + "/" + j + ": " + id + " to " + score + "(" + found + ") sizes: " + simulate.size() + " " + heap.size());
+ System.err.println("Sim: " + simulate.get(simulate.size() - 1) + " <=> Heap: " + heap.peek());
+ }
+ assertEquals("Sizes don't match!", simulate.size(), heap.size());
+ }
+ assertEquals("Heap not valid at i=" + i, null, heap.checkHeap());
+
+ // System.err.println("Sim: " + simulate.get(simulate.size() - 1) +
+ // " <=> Heap: " + heap.peek());
+ // System.err.println(simulate.size() + " <=> " + heap.size());
+ int remove = r.nextInt(simulate.size());
+ for(int j = 0; j < remove; j++) {
+ // System.out.println(heap.toString());
+ IntegerPriorityObject<Integer> fromheap = heap.poll();
+ IntegerPriorityObject<Integer> fromsim = simulate.remove(simulate.size() - 1);
+ assertEquals("Priority doesn't agree.", fromheap.priority, fromsim.priority);
+ if(j + 1 == remove) {
+ while(heap.size() > 0) {
+ assertEquals("Priority doesn't agree.", heap.peek().priority, simulate.get(simulate.size() - 1).priority);
+ if(heap.peek().priority == fromheap.priority) {
+ fromheap = heap.poll();
+ fromsim = simulate.remove(simulate.size() - 1);
+ }
+ else {
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/test/de/lmu/ifi/dbs/elki/utilities/datastructures/TestTopBoundedHeap.java b/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestTopBoundedHeap.java
index f0160d5e..7586556c 100644
--- a/test/de/lmu/ifi/dbs/elki/utilities/datastructures/TestTopBoundedHeap.java
+++ b/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestTopBoundedHeap.java
@@ -1,10 +1,10 @@
-package de.lmu.ifi.dbs.elki.utilities.datastructures;
+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) 2011
+ Copyright (C) 2012
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team
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
new file mode 100644
index 00000000..7e0e8650
--- /dev/null
+++ b/test/de/lmu/ifi/dbs/elki/utilities/datastructures/heap/TestUpdatableHeap.java
@@ -0,0 +1,88 @@
+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.*;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Random;
+
+import org.junit.Test;
+
+import de.lmu.ifi.dbs.elki.JUnit4Test;
+
+public class TestUpdatableHeap implements JUnit4Test {
+ @Test
+ public void testUpdatableHeap() {
+ final int iters = 100;
+ 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>>();
+ 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));
+ // Update simulation
+ boolean found = false;
+ for(IntegerPriorityObject<Integer> ent : simulate) {
+ if(ent.getObject().equals(id)) {
+ if(score > ent.priority) {
+ // System.err.println("Updating in ArrayList: " + ent + " to " + score);
+ ent.priority = score;
+ }
+ found = true;
+ break;
+ }
+ }
+ if(!found) {
+ simulate.add(new IntegerPriorityObject<Integer>(score, id));
+ }
+ }
+ // Keeping the simulation list reverse is a bit faster for removal
+ Collections.sort(simulate, Collections.reverseOrder());
+ // System.err.println(simulate.size() + " <=> " + heap.size());
+ assertEquals("Sizes don't match!", simulate.size(), heap.size());
+ int remove = r.nextInt(simulate.size());
+ for(int j = 0; j < remove; j++) {
+ // System.out.println(heap.toString());
+ IntegerPriorityObject<Integer> fromheap = heap.poll();
+ IntegerPriorityObject<Integer> fromsim = simulate.remove(simulate.size() - 1);
+ //System.out.println(fromheap+" <=> "+fromsim);
+ assertEquals("Priority doesn't agree.", fromheap.priority, fromsim.priority);
+ if(fromheap.getObject() != fromsim.getObject()) {
+ // Ties
+ if(j + 1 == remove && heap.size() > 0) {
+ j++;
+ }
+ }
+ }
+ }
+ }
+}