diff options
Diffstat (limited to 'src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/MaterializeKNNPreprocessor.java')
-rw-r--r-- | src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/MaterializeKNNPreprocessor.java | 147 |
1 files changed, 60 insertions, 87 deletions
diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/MaterializeKNNPreprocessor.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/MaterializeKNNPreprocessor.java index 50ef21ed..ef48e4cb 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/MaterializeKNNPreprocessor.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/MaterializeKNNPreprocessor.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.knn; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -33,14 +33,13 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDIter; import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; 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.KNNHeap; +import de.lmu.ifi.dbs.elki.database.ids.KNNList; import de.lmu.ifi.dbs.elki.database.ids.SetDBIDs; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNHeap; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList; import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery; import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; import de.lmu.ifi.dbs.elki.index.DynamicIndex; import de.lmu.ifi.dbs.elki.logging.Logging; import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress; @@ -63,11 +62,10 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Title; * @apiviz.has KNNListener * * @param <O> the type of database objects the preprocessor can be applied to - * @param <D> the type of distance the used distance function will return */ @Title("Materialize kNN Neighborhood preprocessor") @Description("Materializes the k nearest neighbors of objects of a database.") -public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor<O, D, KNNList<D>> implements DynamicIndex { +public class MaterializeKNNPreprocessor<O> extends AbstractMaterializeKNNPreprocessor<O> implements DynamicIndex { /** * Logger to use. */ @@ -83,7 +81,7 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra /** * KNNQuery instance to use. */ - protected final KNNQuery<O, D> knnQuery; + protected final KNNQuery<O> knnQuery; /** * Holds the listener. @@ -97,7 +95,7 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra * @param distanceFunction the distance function to use * @param k query k */ - public MaterializeKNNPreprocessor(Relation<O> relation, DistanceFunction<? super O, D> distanceFunction, int k) { + public MaterializeKNNPreprocessor(Relation<O> relation, DistanceFunction<? super O> distanceFunction, int k) { super(relation, distanceFunction, k); this.knnQuery = relation.getDatabase().getKNNQuery(distanceQuery, k, DatabaseQuery.HINT_BULK, DatabaseQuery.HINT_HEAVY_USE, DatabaseQuery.HINT_NO_CACHE); } @@ -111,42 +109,33 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra ArrayDBIDs ids = DBIDUtil.ensureArray(relation.getDBIDs()); - if (LOG.isStatistics()) { + if(LOG.isStatistics()) { LOG.statistics(new LongStatistic(this.getClass().getName() + ".k", k)); } - Duration duration = LOG.isStatistics() ? LOG.newDuration(this.getClass().getName() + ".precomputation-time") : null; - if (duration != null) { - duration.begin(); - } + Duration duration = LOG.isStatistics() ? LOG.newDuration(this.getClass().getName() + ".precomputation-time").begin() : null; FiniteProgress progress = getLogger().isVerbose() ? new FiniteProgress("Materializing k nearest neighbors (k=" + k + ")", ids.size(), getLogger()) : null; // Try bulk - List<? extends KNNList<D>> kNNList = null; - if (usebulk) { + List<? extends KNNList> kNNList = null; + if(usebulk) { kNNList = knnQuery.getKNNForBulkDBIDs(ids, k); - if (kNNList != null) { + if(kNNList != null) { int i = 0; - for (DBIDIter id = ids.iter(); id.valid(); id.advance(), i++) { + for(DBIDIter id = ids.iter(); id.valid(); id.advance(), i++) { storage.put(id, kNNList.get(i)); - if (progress != null) { - progress.incrementProcessed(getLogger()); - } + getLogger().incrementProcessed(progress); } } - } else { - for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { - KNNList<D> knn = knnQuery.getKNNForDBID(iter, k); + } + else { + for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { + KNNList knn = knnQuery.getKNNForDBID(iter, k); storage.put(iter, knn); - if (progress != null) { - progress.incrementProcessed(getLogger()); - } + getLogger().incrementProcessed(progress); } } - if (progress != null) { - progress.ensureCompleted(getLogger()); - } - if (duration != null) { - duration.end(); - LOG.statistics(duration); + getLogger().ensureCompleted(progress); + if(duration != null) { + LOG.statistics(duration.end()); } } @@ -157,9 +146,10 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra @Override public void insertAll(DBIDs ids) { - if (storage == null && ids.size() > 0) { + if(storage == null && ids.size() > 0) { preprocess(); - } else { + } + else { objectsInserted(ids); } } @@ -186,32 +176,24 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra ArrayDBIDs aids = DBIDUtil.ensureArray(ids); // materialize the new kNNs - if (stepprog != null) { - stepprog.beginStep(1, "New insertions ocurred, materialize their new kNNs.", getLogger()); - } + getLogger().beginStep(stepprog, 1, "New insertions ocurred, materialize their new kNNs."); // Bulk-query kNNs - List<? extends KNNList<D>> kNNList = knnQuery.getKNNForBulkDBIDs(aids, k); + List<? extends KNNList> kNNList = knnQuery.getKNNForBulkDBIDs(aids, k); // Store in storage DBIDIter iter = aids.iter(); - for (int i = 0; i < aids.size(); i++, iter.advance()) { + for(int i = 0; i < aids.size(); i++, iter.advance()) { storage.put(iter, kNNList.get(i)); } // update the affected kNNs - if (stepprog != null) { - stepprog.beginStep(2, "New insertions ocurred, update the affected kNNs.", getLogger()); - } + getLogger().beginStep(stepprog, 2, "New insertions ocurred, update the affected kNNs."); ArrayDBIDs rkNN_ids = updateKNNsAfterInsertion(ids); // inform listener - if (stepprog != null) { - stepprog.beginStep(3, "New insertions ocurred, inform listeners.", getLogger()); - } + getLogger().beginStep(stepprog, 3, "New insertions ocurred, inform listeners."); fireKNNsInserted(ids, rkNN_ids); - if (stepprog != null) { - stepprog.setCompleted(getLogger()); - } + getLogger().setCompleted(stepprog); } /** @@ -225,21 +207,21 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra private ArrayDBIDs updateKNNsAfterInsertion(DBIDs ids) { ArrayModifiableDBIDs rkNN_ids = DBIDUtil.newArray(); DBIDs oldids = DBIDUtil.difference(relation.getDBIDs(), ids); - for (DBIDIter iter = oldids.iter(); iter.valid(); iter.advance()) { - KNNList<D> kNNs = storage.get(iter); - D knnDist = kNNs.get(kNNs.size() - 1).getDistance(); + for(DBIDIter iter = oldids.iter(); iter.valid(); iter.advance()) { + KNNList kNNs = storage.get(iter); + double knnDist = kNNs.getKNNDistance(); // look for new kNNs - KNNHeap<D> heap = null; - for (DBIDIter iter2 = ids.iter(); iter2.valid(); iter2.advance()) { - D dist = distanceQuery.distance(iter, iter2); - if (dist.compareTo(knnDist) <= 0) { - if (heap == null) { + KNNHeap heap = null; + for(DBIDIter iter2 = ids.iter(); iter2.valid(); iter2.advance()) { + double dist = distanceQuery.distance(iter, iter2); + if(dist <= knnDist) { + if(heap == null) { heap = DBIDUtil.newHeap(kNNs); } heap.insert(dist, iter2); } } - if (heap != null) { + if(heap != null) { kNNs = heap.toKNNList(); storage.put(iter, kNNs); rkNN_ids.add(iter); @@ -258,10 +240,10 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra private ArrayDBIDs updateKNNsAfterDeletion(DBIDs ids) { SetDBIDs idsSet = DBIDUtil.ensureSet(ids); ArrayModifiableDBIDs rkNN_ids = DBIDUtil.newArray(); - for (DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) { - KNNList<D> kNNs = storage.get(iditer); - for (DBIDIter it = kNNs.iter(); it.valid(); it.advance()) { - if (idsSet.contains(it)) { + for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) { + KNNList kNNs = storage.get(iditer); + for(DBIDIter it = kNNs.iter(); it.valid(); it.advance()) { + if(idsSet.contains(it)) { rkNN_ids.add(iditer); break; } @@ -269,9 +251,9 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra } // update the kNNs of the RkNNs - List<? extends KNNList<D>> kNNList = knnQuery.getKNNForBulkDBIDs(rkNN_ids, k); + List<? extends KNNList> kNNList = knnQuery.getKNNForBulkDBIDs(rkNN_ids, k); DBIDIter iter = rkNN_ids.iter(); - for (int i = 0; i < rkNN_ids.size(); i++, iter.advance()) { + for(int i = 0; i < rkNN_ids.size(); i++, iter.advance()) { storage.put(iter, kNNList.get(i)); } @@ -288,28 +270,20 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra StepProgress stepprog = getLogger().isVerbose() ? new StepProgress(3) : null; // delete the materialized (old) kNNs - if (stepprog != null) { - stepprog.beginStep(1, "New deletions ocurred, remove their materialized kNNs.", getLogger()); - } - for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { + getLogger().beginStep(stepprog, 1, "New deletions ocurred, remove their materialized kNNs."); + for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { storage.delete(iter); } // update the affected kNNs - if (stepprog != null) { - stepprog.beginStep(2, "New deletions ocurred, update the affected kNNs.", getLogger()); - } + getLogger().beginStep(stepprog, 2, "New deletions ocurred, update the affected kNNs."); ArrayDBIDs rkNN_ids = updateKNNsAfterDeletion(ids); // inform listener - if (stepprog != null) { - stepprog.beginStep(3, "New deletions ocurred, inform listeners.", getLogger()); - } + getLogger().beginStep(stepprog, 3, "New deletions ocurred, inform listeners."); fireKNNsRemoved(ids, rkNN_ids); - if (stepprog != null) { - stepprog.ensureCompleted(getLogger()); - } + getLogger().ensureCompleted(stepprog); } /** @@ -324,8 +298,8 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra protected void fireKNNsInserted(DBIDs insertions, DBIDs updates) { KNNChangeEvent e = new KNNChangeEvent(this, KNNChangeEvent.Type.INSERT, insertions, updates); Object[] listeners = listenerList.getListenerList(); - for (int i = listeners.length - 2; i >= 0; i -= 2) { - if (listeners[i] == KNNListener.class) { + for(int i = listeners.length - 2; i >= 0; i -= 2) { + if(listeners[i] == KNNListener.class) { ((KNNListener) listeners[i + 1]).kNNsChanged(e); } } @@ -342,8 +316,8 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra protected void fireKNNsRemoved(DBIDs removals, DBIDs updates) { KNNChangeEvent e = new KNNChangeEvent(this, KNNChangeEvent.Type.DELETE, removals, updates); Object[] listeners = listenerList.getListenerList(); - for (int i = listeners.length - 2; i >= 0; i -= 2) { - if (listeners[i] == KNNListener.class) { + for(int i = listeners.length - 2; i >= 0; i -= 2) { + if(listeners[i] == KNNListener.class) { ((KNNListener) listeners[i + 1]).kNNsChanged(e); } } @@ -403,22 +377,21 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra * @apiviz.uses MaterializeKNNPreprocessor oneway - - «create» * * @param <O> The object type - * @param <D> The distance type */ - public static class Factory<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor.Factory<O, D, KNNList<D>> { + public static class Factory<O> extends AbstractMaterializeKNNPreprocessor.Factory<O> { /** * Index factory. * * @param k k parameter * @param distanceFunction distance function */ - public Factory(int k, DistanceFunction<? super O, D> distanceFunction) { + public Factory(int k, DistanceFunction<? super O> distanceFunction) { super(k, distanceFunction); } @Override - public MaterializeKNNPreprocessor<O, D> instantiate(Relation<O> relation) { - MaterializeKNNPreprocessor<O, D> instance = new MaterializeKNNPreprocessor<>(relation, distanceFunction, k); + public MaterializeKNNPreprocessor<O> instantiate(Relation<O> relation) { + MaterializeKNNPreprocessor<O> instance = new MaterializeKNNPreprocessor<>(relation, distanceFunction, k); return instance; } @@ -429,9 +402,9 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra * * @apiviz.exclude */ - public static class Parameterizer<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor.Factory.Parameterizer<O, D> { + public static class Parameterizer<O> extends AbstractMaterializeKNNPreprocessor.Factory.Parameterizer<O> { @Override - protected Factory<O, D> makeInstance() { + protected Factory<O> makeInstance() { return new Factory<>(k, distanceFunction); } } |