use of de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDListIter in project elki by elki-project.
the class DWOF method clusterData.
/**
* This method applies a density based clustering algorithm.
*
* It looks for an unclustered object and builds a new cluster for it, then
* adds all the points within its radius to that cluster.
*
* nChain represents the points to be added to the cluster and its
* radius-neighbors
*
* @param ids Database IDs to process
* @param rnnQuery Data to process
* @param radii Radii to cluster accordingly
* @param labels Label storage.
*/
private void clusterData(DBIDs ids, RangeQuery<O> rnnQuery, WritableDoubleDataStore radii, WritableDataStore<ModifiableDBIDs> labels) {
FiniteProgress clustProg = LOG.isVerbose() ? new FiniteProgress("Density-Based Clustering", ids.size(), LOG) : null;
// Iterate over all objects
for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
if (labels.get(iter) != null) {
continue;
}
ModifiableDBIDs newCluster = DBIDUtil.newArray();
newCluster.add(iter);
labels.put(iter, newCluster);
LOG.incrementProcessed(clustProg);
// container of the points to be added and their radii neighbors to the
// cluster
ModifiableDBIDs nChain = DBIDUtil.newArray();
nChain.add(iter);
// iterate over nChain
for (DBIDIter toGetNeighbors = nChain.iter(); toGetNeighbors.valid(); toGetNeighbors.advance()) {
double range = radii.doubleValue(toGetNeighbors);
DoubleDBIDList nNeighbors = rnnQuery.getRangeForDBID(toGetNeighbors, range);
for (DoubleDBIDListIter iter2 = nNeighbors.iter(); iter2.valid(); iter2.advance()) {
if (DBIDUtil.equal(toGetNeighbors, iter2)) {
continue;
}
if (labels.get(iter2) == null) {
newCluster.add(iter2);
labels.put(iter2, newCluster);
nChain.add(iter2);
LOG.incrementProcessed(clustProg);
} else if (labels.get(iter2) != newCluster) {
ModifiableDBIDs toBeDeleted = labels.get(iter2);
newCluster.addDBIDs(toBeDeleted);
for (DBIDIter iter3 = toBeDeleted.iter(); iter3.valid(); iter3.advance()) {
labels.put(iter3, newCluster);
}
toBeDeleted.clear();
}
}
}
}
LOG.ensureCompleted(clustProg);
}
use of de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDListIter in project elki by elki-project.
the class MaterializeKNNAndRKNNPreprocessor method materializeKNNAndRKNNs.
/**
* Materializes the kNNs and RkNNs of the specified object IDs.
*
* @param ids the IDs of the objects
*/
private void materializeKNNAndRKNNs(ArrayDBIDs ids, FiniteProgress progress) {
// add an empty list to each rknn
for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
if (materialized_RkNN.get(iter) == null) {
materialized_RkNN.put(iter, new TreeSet<DoubleDBIDPair>());
}
}
// knn query
List<? extends KNNList> kNNList = knnQuery.getKNNForBulkDBIDs(ids, k);
int i = 0;
for (DBIDIter id = ids.iter(); id.valid(); id.advance(), i++) {
KNNList kNNs = kNNList.get(i);
storage.put(id, kNNs);
for (DoubleDBIDListIter iter = kNNs.iter(); iter.valid(); iter.advance()) {
TreeSet<DoubleDBIDPair> rknns = materialized_RkNN.get(iter);
rknns.add(makePair(iter, id));
}
getLogger().incrementProcessed(progress);
}
getLogger().ensureCompleted(progress);
}
use of de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDListIter in project elki by elki-project.
the class MaterializeKNNAndRKNNPreprocessor method updateKNNsAndRkNNs.
/**
* Updates the kNNs and RkNNs after insertion of the specified ids.
*
* @param ids the ids of newly inserted objects causing a change of
* 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 (DBIDIter id = oldids.iter(); id.valid(); id.advance()) {
KNNList oldkNNs = storage.get(id);
double knnDist = oldkNNs.getKNNDistance();
// look for new kNNs
KNNHeap heap = null;
for (DBIDIter newid = ids.iter(); newid.valid(); newid.advance()) {
double dist = distanceQuery.distance(id, newid);
if (dist <= knnDist) {
// New id changes the kNNs of oldid.
if (heap == null) {
heap = DBIDUtil.newHeap(oldkNNs);
}
heap.insert(dist, newid);
}
}
// kNNs for oldid have changed:
if (heap != null) {
KNNList newkNNs = heap.toKNNList();
storage.put(id, newkNNs);
// get the difference
int i = 0;
int j = 0;
ModifiableDoubleDBIDList added = DBIDUtil.newDistanceDBIDList();
ModifiableDoubleDBIDList removed = DBIDUtil.newDistanceDBIDList();
// TODO: use iterators.
while (i < oldkNNs.size() && j < newkNNs.size()) {
DoubleDBIDPair drp1 = oldkNNs.get(i);
DoubleDBIDPair drp2 = newkNNs.get(j);
// NOTE: we assume that on ties they are ordered the same way!
if (!DBIDUtil.equal(drp1, drp2)) {
added.add(drp2);
j++;
} else {
i++;
j++;
}
}
if (i != j) {
for (; i < oldkNNs.size(); i++) {
removed.add(oldkNNs.get(i));
}
for (; j < newkNNs.size(); i++) {
added.add(newkNNs.get(i));
}
}
// add new RkNN
for (DoubleDBIDListIter newnn = added.iter(); newnn.valid(); newnn.advance()) {
TreeSet<DoubleDBIDPair> rknns = materialized_RkNN.get(newnn);
rknns.add(makePair(newnn, id));
}
// remove old RkNN
for (DoubleDBIDListIter oldnn = removed.iter(); oldnn.valid(); oldnn.advance()) {
TreeSet<DoubleDBIDPair> rknns = materialized_RkNN.get(oldnn);
rknns.remove(makePair(oldnn, id));
}
rkNN_ids.add(id);
}
}
return rkNN_ids;
}
use of de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDListIter in project elki by elki-project.
the class NNDescentTest method testKNNQueries.
private void testKNNQueries(Relation<DoubleVector> rep, KNNQuery<DoubleVector> lin_knn_query, KNNQuery<DoubleVector> preproc_knn_query, int k) {
ArrayDBIDs sample = DBIDUtil.ensureArray(rep.getDBIDs());
List<? extends KNNList> lin_knn_ids = lin_knn_query.getKNNForBulkDBIDs(sample, k);
List<? extends KNNList> preproc_knn_ids = preproc_knn_query.getKNNForBulkDBIDs(sample, k);
for (int i = 0; i < rep.size(); i++) {
KNNList lin_knn = lin_knn_ids.get(i);
KNNList pre_knn = preproc_knn_ids.get(i);
DoubleDBIDListIter lin = lin_knn.iter(), pre = pre_knn.iter();
for (; lin.valid() && pre.valid(); lin.advance(), pre.advance(), i++) {
if (DBIDUtil.equal(lin, pre) || lin.doubleValue() == pre.doubleValue()) {
continue;
}
fail(//
new StringBuilder(1000).append("Neighbor distances do not agree: ").append(lin_knn.toString()).append(" got: ").append(pre_knn.toString()).toString());
}
assertEquals("kNN sizes do not agree.", lin_knn.size(), pre_knn.size());
for (int j = 0; j < lin_knn.size(); j++) {
assertTrue("kNNs of linear scan and preprocessor do not match!", DBIDUtil.equal(lin_knn.get(j), pre_knn.get(j)));
assertEquals("kNNs of linear scan and preprocessor do not match!", lin_knn.get(j).doubleValue(), pre_knn.get(j).doubleValue(), 0.);
}
}
}
use of de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDListIter in project elki by elki-project.
the class MkMaxTree method reverseKNNQuery.
/**
* Performs a reverse k-nearest neighbor query for the given object ID. In the
* first step the candidates are chosen by performing a reverse k-nearest
* neighbor query with k = {@link #getKmax()}. Then these candidates are refined
* in a second step.
*/
@Override
public DoubleDBIDList reverseKNNQuery(DBIDRef id, int k) {
if (k > this.getKmax()) {
throw new IllegalArgumentException("Parameter k has to be equal or less than " + "parameter k of the MkMax-Tree!");
}
// get the candidates
ModifiableDoubleDBIDList candidates = DBIDUtil.newDistanceDBIDList();
doReverseKNNQuery(id, getRoot(), null, candidates);
if (k == this.getKmax()) {
candidates.sort();
// rkNNStatistics.addResults(candidates.size());
return candidates;
}
// refinement of candidates
ModifiableDBIDs candidateIDs = DBIDUtil.newArray(candidates.size());
for (DBIDIter candidate = candidates.iter(); candidate.valid(); candidate.advance()) {
candidateIDs.add(candidate);
}
Map<DBID, KNNList> knnLists = batchNN(getRoot(), candidateIDs, k);
ModifiableDoubleDBIDList result = DBIDUtil.newDistanceDBIDList();
for (DBIDIter iter = candidateIDs.iter(); iter.valid(); iter.advance()) {
DBID cid = DBIDUtil.deref(iter);
KNNList cands = knnLists.get(cid);
for (DoubleDBIDListIter iter2 = cands.iter(); iter2.valid(); iter2.advance()) {
if (DBIDUtil.equal(id, iter2)) {
result.add(iter2.doubleValue(), cid);
break;
}
}
}
// FIXME: re-add statistics.
// rkNNStatistics.addResults(result.size());
// rkNNStatistics.addCandidates(candidates.size());
result.sort();
return result;
}
Aggregations