diff options
Diffstat (limited to 'src/de/lmu/ifi/dbs/elki/index/tree')
153 files changed, 3594 insertions, 1392 deletions
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 |