use of de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query.MTreeSearchCandidate in project elki by elki-project.
the class MkAppTree method reverseKNNQuery.
/**
* Performs a reverse k-nearest neighbor query for the given object ID. The
* query result is in ascending order to the distance to the query object.
*
* @param id the query object id
* @param k the number of nearest neighbors to be returned
* @return a List of the query results
*/
@Override
public DoubleDBIDList reverseKNNQuery(DBIDRef id, int k) {
ModifiableDoubleDBIDList result = DBIDUtil.newDistanceDBIDList();
final Heap<MTreeSearchCandidate> pq = new UpdatableHeap<>();
// push root
pq.add(new MTreeSearchCandidate(0., getRootID(), null, Double.NaN));
// search in tree
while (!pq.isEmpty()) {
MTreeSearchCandidate pqNode = pq.poll();
// FIXME: cache the distance to the routing object in the queue node!
MkAppTreeNode<O> node = getNode(pqNode.nodeID);
// directory node
if (!node.isLeaf()) {
for (int i = 0; i < node.getNumEntries(); i++) {
MkAppEntry entry = node.getEntry(i);
double distance = distance(entry.getRoutingObjectID(), id);
double minDist = (entry.getCoveringRadius() > distance) ? 0. : distance - entry.getCoveringRadius();
double approxValue = settings.log ? FastMath.exp(entry.approximatedValueAt(k)) : entry.approximatedValueAt(k);
if (approxValue < 0) {
approxValue = 0;
}
if (minDist <= approxValue) {
pq.add(new MTreeSearchCandidate(minDist, getPageID(entry), entry.getRoutingObjectID(), Double.NaN));
}
}
} else // data node
{
for (int i = 0; i < node.getNumEntries(); i++) {
MkAppLeafEntry entry = (MkAppLeafEntry) node.getEntry(i);
double distance = distance(entry.getRoutingObjectID(), id);
double approxValue = settings.log ? FastMath.exp(entry.approximatedValueAt(k)) : entry.approximatedValueAt(k);
if (approxValue < 0) {
approxValue = 0;
}
if (distance <= approxValue) {
result.add(distance, entry.getRoutingObjectID());
}
}
}
}
return result;
}
use of de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query.MTreeSearchCandidate in project elki by elki-project.
the class MkCoPTree method doReverseKNNQuery.
/**
* Performs a reverse knn query.
*
* @param k the parameter k of the rknn query
* @param q the id of the query object
* @param result holds the true results (they need not to be refined)
* @param candidates holds possible candidates for the result (they need a
* refinement)
*/
private void doReverseKNNQuery(int k, DBIDRef q, ModifiableDoubleDBIDList result, ModifiableDBIDs candidates) {
final ComparableMinHeap<MTreeSearchCandidate> pq = new ComparableMinHeap<>();
// push root
pq.add(new MTreeSearchCandidate(0., getRootID(), null, Double.NaN));
// search in tree
while (!pq.isEmpty()) {
MTreeSearchCandidate pqNode = pq.poll();
// FIXME: cache the distance to the routing object in the queue node!
MkCoPTreeNode<O> node = getNode(pqNode.nodeID);
// directory node
if (!node.isLeaf()) {
for (int i = 0; i < node.getNumEntries(); i++) {
MkCoPEntry entry = node.getEntry(i);
double distance = distance(entry.getRoutingObjectID(), q);
double minDist = entry.getCoveringRadius() > distance ? 0. : distance - entry.getCoveringRadius();
double approximatedKnnDist_cons = entry.approximateConservativeKnnDistance(k);
if (minDist <= approximatedKnnDist_cons) {
pq.add(new MTreeSearchCandidate(minDist, getPageID(entry), entry.getRoutingObjectID(), Double.NaN));
}
}
} else // data node
{
for (int i = 0; i < node.getNumEntries(); i++) {
MkCoPLeafEntry entry = (MkCoPLeafEntry) node.getEntry(i);
double distance = distance(entry.getRoutingObjectID(), q);
double approximatedKnnDist_prog = entry.approximateProgressiveKnnDistance(k);
if (distance <= approximatedKnnDist_prog) {
result.add(distance, entry.getRoutingObjectID());
} else {
double approximatedKnnDist_cons = entry.approximateConservativeKnnDistance(k);
double diff = distance - approximatedKnnDist_cons;
if (diff <= 1E-10) {
candidates.add(entry.getRoutingObjectID());
}
}
}
}
}
}
Aggregations