use of de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.deliclu.DeLiCluEntry in project elki by elki-project.
the class DeLiClu method expandDirNodes.
/**
* Expands the specified directory nodes.
*
* @param distFunction the spatial distance function of this algorithm
* @param node1 the first node
* @param node2 the second node
*/
private void expandDirNodes(SpatialPrimitiveDistanceFunction<NV> distFunction, DeLiCluNode node1, DeLiCluNode node2) {
if (LOG.isDebuggingFinest()) {
LOG.debugFinest("ExpandDirNodes: " + node1.getPageID() + " + " + node2.getPageID());
}
int numEntries_1 = node1.getNumEntries();
int numEntries_2 = node2.getNumEntries();
// node1-node2 into pq
for (int i = 0; i < numEntries_1; i++) {
DeLiCluEntry entry1 = node1.getEntry(i);
if (!entry1.hasUnhandled()) {
continue;
}
for (int j = 0; j < numEntries_2; j++) {
DeLiCluEntry entry2 = node2.getEntry(j);
if (!entry2.hasHandled()) {
continue;
}
double distance = distFunction.minDist(entry1, entry2);
SpatialObjectPair nodePair = new SpatialObjectPair(distance, entry1, entry2, true);
heap.add(nodePair);
}
}
}
use of de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.deliclu.DeLiCluEntry in project elki by elki-project.
the class DeLiClu method run.
public ClusterOrder run(Database database, Relation<NV> relation) {
Collection<DeLiCluTreeIndex<NV>> indexes = ResultUtil.filterResults(database.getHierarchy(), relation, DeLiCluTreeIndex.class);
if (indexes.size() != 1) {
throw new MissingPrerequisitesException("DeLiClu found " + indexes.size() + " DeLiCluTree indexes. DeLiClu needs a special index to operate, therefore you need to add this index to your database.");
}
DeLiCluTreeIndex<NV> index = indexes.iterator().next();
if (!(getDistanceFunction() instanceof SpatialPrimitiveDistanceFunction<?>)) {
throw new IllegalArgumentException("Distance Function must be an instance of " + SpatialPrimitiveDistanceFunction.class.getName());
}
@SuppressWarnings("unchecked") SpatialPrimitiveDistanceFunction<NV> distFunction = (SpatialPrimitiveDistanceFunction<NV>) getDistanceFunction();
// first do the knn-Join
if (LOG.isVerbose()) {
LOG.verbose("knnJoin...");
}
Relation<KNNList> knns = knnJoin.run(relation);
DBIDs ids = relation.getDBIDs();
final int size = ids.size();
FiniteProgress progress = LOG.isVerbose() ? new FiniteProgress("DeLiClu", size, LOG) : null;
ClusterOrder clusterOrder = new ClusterOrder(ids, "DeLiClu Clustering", "deliclu-clustering");
heap = new UpdatableHeap<>();
// add start object to cluster order and (root, root) to priority queue
DBID startID = DBIDUtil.deref(ids.iter());
clusterOrder.add(startID, Double.POSITIVE_INFINITY, null);
int numHandled = 1;
index.setHandled(startID, relation.get(startID));
SpatialDirectoryEntry rootEntry = (SpatialDirectoryEntry) index.getRootEntry();
SpatialObjectPair spatialObjectPair = new SpatialObjectPair(0., rootEntry, rootEntry, true);
heap.add(spatialObjectPair);
while (numHandled < size) {
if (heap.isEmpty()) {
throw new AbortException("DeLiClu heap was empty when it shouldn't have been.");
}
SpatialObjectPair dataPair = heap.poll();
// pair of nodes
if (dataPair.isExpandable) {
expandNodes(index, distFunction, dataPair, knns);
} else // pair of objects
{
// set handled
LeafEntry e1 = (LeafEntry) dataPair.entry1;
LeafEntry e2 = (LeafEntry) dataPair.entry2;
final DBID e1id = e1.getDBID();
IndexTreePath<DeLiCluEntry> path = index.setHandled(e1id, relation.get(e1id));
if (path == null) {
throw new RuntimeException("snh: parent(" + e1id + ") = null!!!");
}
// add to cluster order
clusterOrder.add(e1id, dataPair.distance, e2.getDBID());
numHandled++;
// reinsert expanded leafs
reinsertExpanded(distFunction, index, path, knns);
if (progress != null) {
progress.setProcessed(numHandled, LOG);
}
}
}
LOG.ensureCompleted(progress);
return clusterOrder;
}
use of de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.deliclu.DeLiCluEntry in project elki by elki-project.
the class DeLiClu method reinsertExpanded.
/**
* Reinserts the objects of the already expanded nodes.
*
* @param distFunction the spatial distance function of this algorithm
* @param index the index storing the objects
* @param path the path of the object inserted last
* @param knns the knn list
*/
private void reinsertExpanded(SpatialPrimitiveDistanceFunction<NV> distFunction, DeLiCluTree index, IndexTreePath<DeLiCluEntry> path, Relation<KNNList> knns) {
// Count the number of components.
int l = 0;
for (IndexTreePath<DeLiCluEntry> it = path; it != null; it = it.getParentPath()) {
l++;
}
ArrayList<IndexTreePath<DeLiCluEntry>> p = new ArrayList<>(l - 1);
// All except the last (= root).
IndexTreePath<DeLiCluEntry> it = path;
for (; it.getParentPath() != null; it = it.getParentPath()) {
p.add(it);
}
assert (p.size() == l - 1);
DeLiCluEntry rootEntry = it.getEntry();
reinsertExpanded(distFunction, index, p, l - 2, rootEntry, knns);
}
use of de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.deliclu.DeLiCluEntry in project elki by elki-project.
the class DeLiClu method expandLeafNodes.
/**
* Expands the specified leaf nodes.
*
* @param distFunction the spatial distance function of this algorithm
* @param node1 the first node
* @param node2 the second node
* @param knns the knn list
*/
private void expandLeafNodes(SpatialPrimitiveDistanceFunction<NV> distFunction, DeLiCluNode node1, DeLiCluNode node2, Relation<KNNList> knns) {
if (LOG.isDebuggingFinest()) {
LOG.debugFinest("ExpandLeafNodes: " + node1.getPageID() + " + " + node2.getPageID());
}
int numEntries_1 = node1.getNumEntries();
int numEntries_2 = node2.getNumEntries();
// node1-node2 into pq
for (int i = 0; i < numEntries_1; i++) {
DeLiCluEntry entry1 = node1.getEntry(i);
if (!entry1.hasUnhandled()) {
continue;
}
for (int j = 0; j < numEntries_2; j++) {
DeLiCluEntry entry2 = node2.getEntry(j);
if (!entry2.hasHandled()) {
continue;
}
double distance = distFunction.minDist(entry1, entry2);
double reach = MathUtil.max(distance, knns.get(((LeafEntry) entry2).getDBID()).getKNNDistance());
SpatialObjectPair dataPair = new SpatialObjectPair(reach, entry1, entry2, false);
heap.add(dataPair);
}
}
}
use of de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.deliclu.DeLiCluEntry in project elki by elki-project.
the class DeLiClu method reinsertExpanded.
private void reinsertExpanded(SpatialPrimitiveDistanceFunction<NV> distFunction, DeLiCluTree index, List<IndexTreePath<DeLiCluEntry>> path, int pos, DeLiCluEntry parentEntry, Relation<KNNList> knns) {
DeLiCluNode parentNode = index.getNode(parentEntry);
SpatialEntry entry2 = path.get(pos).getEntry();
if (entry2 instanceof LeafEntry) {
assert (pos == 0);
for (int i = 0; i < parentNode.getNumEntries(); i++) {
DeLiCluEntry entry1 = parentNode.getEntry(i);
if (entry1.hasHandled()) {
continue;
}
double distance = distFunction.minDist(entry1, entry2);
double reach = MathUtil.max(distance, knns.get(((LeafEntry) entry2).getDBID()).getKNNDistance());
SpatialObjectPair dataPair = new SpatialObjectPair(reach, entry1, entry2, false);
heap.add(dataPair);
}
return;
}
IntSet expanded = index.getExpanded(entry2);
for (int i = 0; i < parentNode.getNumEntries(); i++) {
DeLiCluDirectoryEntry entry1 = (DeLiCluDirectoryEntry) parentNode.getEntry(i);
// not yet expanded
if (!expanded.contains(entry1.getPageID())) {
double distance = distFunction.minDist(entry1, entry2);
SpatialObjectPair nodePair = new SpatialObjectPair(distance, entry1, entry2, true);
heap.add(nodePair);
} else // already expanded
{
reinsertExpanded(distFunction, index, path, pos - 1, entry1, knns);
}
}
}
Aggregations