diff options
Diffstat (limited to 'src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/DoubleDistanceRStarTreeKNNQuery.java')
-rw-r--r-- | src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/DoubleDistanceRStarTreeKNNQuery.java | 89 |
1 files changed, 52 insertions, 37 deletions
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 |