* materialized kNNs and RkNNs
* @return the RkNNs of the specified ids, i.e. the kNNs which have been
* updated
*/
private ArrayDBIDs updateKNNsAndRkNNs(DBIDs ids) {
ArrayModifiableDBIDs rkNN_ids = DBIDUtil.newArray();
DBIDs oldids = DBIDUtil.difference(relation.getDBIDs(), ids);
for(DBID id1 : oldids) {
KNNResult<D> kNNs = storage.get(id1);
D knnDist = kNNs.getKNNDistance();
// look for new kNNs
KNNHeap<D> heap = null;
for(DBID id2 : ids) {
D dist = distanceQuery.distance(id1, id2);
if(dist.compareTo(knnDist) <= 0) {
if(heap == null) {
heap = new KNNHeap<D>(k);
heap.addAll(kNNs);
}
heap.add(dist, id2);
}
}
if(heap != null) {
KNNList<D> newKNNs = heap.toKNNList();
storage.put(id1, newKNNs);
// get the difference
int i = 0;
int j = 0;
List<DistanceResultPair<D>> added = new ArrayList<DistanceResultPair<D>>();
List<DistanceResultPair<D>> removed = new ArrayList<DistanceResultPair<D>>();
while(i < kNNs.size() && j < newKNNs.size()) {
DistanceResultPair<D> drp1 = kNNs.get(i);
DistanceResultPair<D> drp2 = newKNNs.get(j);
if(!drp1.equals(drp2)) {
added.add(drp2);
j++;
}
else {
i++;
j++;
}
}
if(i != j) {
for(; i < kNNs.size(); i++)
removed.add(kNNs.get(i));
}
// add new RkNN
for(DistanceResultPair<D> drp : added) {
Set<DistanceResultPair<D>> rknns = materialized_RkNN.get(drp.getDBID());
rknns.add(new GenericDistanceResultPair<D>(drp.getDistance(), id1));
}
// remove old RkNN
for(DistanceResultPair<D> drp : removed) {
Set<DistanceResultPair<D>> rknns = materialized_RkNN.get(drp.getDBID());
rknns.remove(new GenericDistanceResultPair<D>(drp.getDistance(), id1));
}
rkNN_ids.add(id1);
}
}
return rkNN_ids;
}