diff options
Diffstat (limited to 'src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/GeneralizedDBSCAN.java')
-rw-r--r-- | src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/GeneralizedDBSCAN.java | 81 |
1 files changed, 40 insertions, 41 deletions
diff --git a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/GeneralizedDBSCAN.java b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/GeneralizedDBSCAN.java index 1e0a8642..9c8d0e48 100644 --- a/src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/GeneralizedDBSCAN.java +++ b/src/de/lmu/ifi/dbs/elki/algorithm/clustering/gdbscan/GeneralizedDBSCAN.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.algorithm.clustering.gdbscan; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -76,7 +76,10 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter; * @apiviz.composedOf CorePredicate * @apiviz.composedOf NeighborPredicate */ -@Reference(authors = "Jörg Sander, Martin Ester, Hans-Peter Kriegel, Xiaowei Xu", title = "Density-Based Clustering in Spatial Databases: The Algorithm GDBSCAN and Its Applications", booktitle = "Data Mining and Knowledge Discovery", url = "http://dx.doi.org/10.1023/A:1009745219419") +@Reference(authors = "Jörg Sander, Martin Ester, Hans-Peter Kriegel, Xiaowei Xu", // +title = "Density-Based Clustering in Spatial Databases: The Algorithm GDBSCAN and Its Applications", // +booktitle = "Data Mining and Knowledge Discovery", // +url = "http://dx.doi.org/10.1023/A:1009745219419") public class GeneralizedDBSCAN extends AbstractAlgorithm<Clustering<Model>> implements ClusteringAlgorithm<Clustering<Model>> { /** * Get a logger for this algorithm @@ -114,8 +117,8 @@ public class GeneralizedDBSCAN extends AbstractAlgorithm<Clustering<Model>> impl @Override public Clustering<Model> run(Database database) { - for (SimpleTypeInformation<?> t : npred.getOutputType()) { - if (corepred.acceptsType(t)) { + for(SimpleTypeInformation<?> t : npred.getOutputType()) { + if(corepred.acceptsType(t)) { return new Instance<>(npred.instantiate(database, t), corepred.instantiate(database, t), coremodel).run(); } } @@ -140,16 +143,16 @@ public class GeneralizedDBSCAN extends AbstractAlgorithm<Clustering<Model>> impl * @apiviz.composedOf CorePredicate.Instance * @apiviz.composedOf NeighborPredicate.Instance */ - public class Instance<T> { + public static class Instance<T> { /** * Unprocessed IDs */ - private static final int UNPROCESSED = 0; + protected static final int UNPROCESSED = 0; /** * Noise IDs */ - private static final int NOISE = 1; + protected static final int NOISE = 1; /** * The neighborhood predicate @@ -159,7 +162,7 @@ public class GeneralizedDBSCAN extends AbstractAlgorithm<Clustering<Model>> impl /** * The core object property */ - final CorePredicate.Instance<T> corepred; + final CorePredicate.Instance<? super T> corepred; /** * Track which objects are "core" objects. @@ -173,7 +176,7 @@ public class GeneralizedDBSCAN extends AbstractAlgorithm<Clustering<Model>> impl * @param corepred Core object predicate * @param coremodel Keep track of core points. */ - public Instance(NeighborPredicate.Instance<T> npred, CorePredicate.Instance<T> corepred, boolean coremodel) { + public Instance(NeighborPredicate.Instance<T> npred, CorePredicate.Instance<? super T> corepred, boolean coremodel) { super(); this.npred = npred; this.corepred = corepred; @@ -201,69 +204,65 @@ public class GeneralizedDBSCAN extends AbstractAlgorithm<Clustering<Model>> impl // reduced memory use in the HashMap! int clusterid = NOISE + 1; // Iterate over all objects in the database. - for (DBIDIter id = ids.iter(); id.valid(); id.advance()) { + for(DBIDIter id = ids.iter(); id.valid(); id.advance()) { // Skip already processed ids. - if (clusterids.intValue(id) != UNPROCESSED) { + if(clusterids.intValue(id) != UNPROCESSED) { continue; } // Evaluate Neighborhood predicate final T neighbors = npred.getNeighbors(id); // Evaluate Core-Point predicate: - if (corepred.isCorePoint(id, neighbors)) { + if(corepred.isCorePoint(id, neighbors)) { clusterids.putInt(id, clusterid); clustersizes.add(expandCluster(clusterid, clusterids, neighbors, progress)); // start next cluster on next iteration. ++clusterid; - if (clusprogress != null) { + if(clusprogress != null) { clusprogress.setProcessed(clusterid, LOG); } - } else { + } + else { // otherwise, it's a noise point clusterids.putInt(id, NOISE); clustersizes.set(NOISE, clustersizes.get(NOISE) + 1); } // We've completed this element - if (progress != null) { - progress.incrementProcessed(LOG); - } + LOG.incrementProcessed(progress); } // Finish progress logging. - if (progress != null) { - progress.ensureCompleted(LOG); - } - if (clusprogress != null) { - clusprogress.setCompleted(LOG); - } + LOG.ensureCompleted(progress); + LOG.setCompleted(clusprogress); // Transform cluster ID mapping into a clustering result: ArrayList<ArrayModifiableDBIDs> clusterlists = new ArrayList<>(clusterid); ArrayList<ArrayModifiableDBIDs> corelists = coremodel ? new ArrayList<ArrayModifiableDBIDs>(clusterid) : null; // add storage containers for clusters - for (int i = 0; i < clustersizes.size(); i++) { + for(int i = 0; i < clustersizes.size(); i++) { clusterlists.add(DBIDUtil.newArray(clustersizes.get(i))); - if (corelists != null) { + if(corelists != null) { corelists.add(DBIDUtil.newArray(clustersizes.get(i))); } } // do the actual inversion - for (DBIDIter id = ids.iter(); id.valid(); id.advance()) { + for(DBIDIter id = ids.iter(); id.valid(); id.advance()) { // Negative values are non-core points: int cid = clusterids.intValue(id); int cluster = Math.abs(cid); clusterlists.get(cluster).add(id); - if (corelists != null && cid > NOISE) { + if(corelists != null && cid > NOISE) { corelists.get(cluster).add(id); } } clusterids.destroy(); Clustering<Model> result = new Clustering<>("GDBSCAN", "gdbscan-clustering"); - for (int cid = NOISE; cid < clusterlists.size(); cid++) { + for(int cid = NOISE; cid < clusterlists.size(); cid++) { boolean isNoise = (cid == NOISE); Cluster<Model> c; - if (corelists != null) { + if(corelists != null) { c = new Cluster<Model>(clusterlists.get(cid), isNoise, new CoreObjectsModel(corelists.get(cid))); - } else { + } + else { c = new Cluster<Model>(clusterlists.get(cid), isNoise, ClusterModel.CLUSTER); } result.addToplevelCluster(c); @@ -287,32 +286,32 @@ public class GeneralizedDBSCAN extends AbstractAlgorithm<Clustering<Model>> impl npred.addDBIDs(activeSet, neighbors); // run expandCluster as long as this set is non-empty (non-recursive // implementation) - while (!activeSet.isEmpty()) { + while(!activeSet.isEmpty()) { final DBID id = activeSet.remove(activeSet.size() - 1); // Assign object to cluster final int oldclus = clusterids.intValue(id); - if (oldclus == NOISE) { + if(oldclus == NOISE) { clustersize += 1; // Non core point cluster member: clusterids.putInt(id, -clusterid); - } else if (oldclus == UNPROCESSED) { + } + else if(oldclus == UNPROCESSED) { clustersize += 1; // expandCluster again: // Evaluate Neighborhood predicate final T newneighbors = npred.getNeighbors(id); // Evaluate Core-Point predicate - if (corepred.isCorePoint(id, newneighbors)) { + if(corepred.isCorePoint(id, newneighbors)) { // Note: the recursion is unrolled into iteration over the active // set. npred.addDBIDs(activeSet, newneighbors); clusterids.putInt(id, clusterid); - } else { + } + else { // Non core point cluster member: clusterids.putInt(id, -clusterid); } - if (progress != null) { - progress.incrementProcessed(LOG); - } + LOG.incrementProcessed(progress); } } return clustersize; @@ -361,18 +360,18 @@ public class GeneralizedDBSCAN extends AbstractAlgorithm<Clustering<Model>> impl protected void makeOptions(Parameterization config) { // Neighborhood predicate ObjectParameter<NeighborPredicate> npredOpt = new ObjectParameter<>(NEIGHBORHOODPRED_ID, NeighborPredicate.class, EpsilonNeighborPredicate.class); - if (config.grab(npredOpt)) { + if(config.grab(npredOpt)) { npred = npredOpt.instantiateClass(config); } // Core point predicate ObjectParameter<CorePredicate> corepredOpt = new ObjectParameter<>(COREPRED_ID, CorePredicate.class, MinPtsCorePredicate.class); - if (config.grab(corepredOpt)) { + if(config.grab(corepredOpt)) { corepred = corepredOpt.instantiateClass(config); } Flag coremodelOpt = new Flag(COREMODEL_ID); - if (config.grab(coremodelOpt)) { + if(config.grab(coremodelOpt)) { coremodel = coremodelOpt.isTrue(); } } |