diff options
Diffstat (limited to 'src/de/lmu/ifi/dbs/elki/database')
174 files changed, 4952 insertions, 916 deletions
diff --git a/src/de/lmu/ifi/dbs/elki/database/AbstractDatabase.java b/src/de/lmu/ifi/dbs/elki/database/AbstractDatabase.java index b62db142..8b3a64eb 100644 --- a/src/de/lmu/ifi/dbs/elki/database/AbstractDatabase.java +++ b/src/de/lmu/ifi/dbs/elki/database/AbstractDatabase.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -82,17 +82,17 @@ public abstract class AbstractDatabase extends AbstractHierarchicalResult implem /** * The relations we manage. */ - protected final List<Relation<?>> relations = new java.util.Vector<Relation<?>>(); + protected final List<Relation<?>> relations = new ArrayList<>(); /** * Indexes. */ - protected final List<Index> indexes = new java.util.Vector<Index>(); + protected final List<Index> indexes = new ArrayList<>(); /** * Index factories. */ - protected final Collection<IndexFactory<?, ?>> indexFactories = new java.util.Vector<IndexFactory<?, ?>>(); + protected final Collection<IndexFactory<?, ?>> indexFactories = new ArrayList<>(); /** * Constructor. @@ -154,7 +154,7 @@ public abstract class AbstractDatabase extends AbstractHierarchicalResult implem return (Relation<O>) relation; } } - List<TypeInformation> types = new ArrayList<TypeInformation>(relations.size()); + List<TypeInformation> types = new ArrayList<>(relations.size()); for(Relation<?> relation : relations) { types.add(relation.getDataTypeInformation()); } @@ -269,7 +269,7 @@ public abstract class AbstractDatabase extends AbstractHierarchicalResult implem } } KNNQuery<O, D> knnQuery = getKNNQuery(distanceQuery, DatabaseQuery.HINT_BULK, maxk); - return new LinearScanRKNNQuery<O, D>(distanceQuery, knnQuery, maxk); + return new LinearScanRKNNQuery<>(distanceQuery, knnQuery, maxk); } @Override diff --git a/src/de/lmu/ifi/dbs/elki/database/Database.java b/src/de/lmu/ifi/dbs/elki/database/Database.java index e5b9f7ff..da4cc827 100644 --- a/src/de/lmu/ifi/dbs/elki/database/Database.java +++ b/src/de/lmu/ifi/dbs/elki/database/Database.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -42,7 +42,7 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; import de.lmu.ifi.dbs.elki.distance.similarityfunction.SimilarityFunction; import de.lmu.ifi.dbs.elki.index.Index; import de.lmu.ifi.dbs.elki.result.HierarchicalResult; -import de.lmu.ifi.dbs.elki.utilities.InspectionUtilFrequentlyScanned; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID; /** * Database specifies the requirements for any database implementation. Note @@ -60,7 +60,17 @@ import de.lmu.ifi.dbs.elki.utilities.InspectionUtilFrequentlyScanned; * @apiviz.has Index oneway - - manages * @apiviz.has DataStoreListener oneway - - invokes */ -public interface Database extends HierarchicalResult, InspectionUtilFrequentlyScanned { +public interface Database extends HierarchicalResult { + /** + * Option to specify the data source for the database. + * + * Key: + * <p> + * {@code -dbc} + * </p> + */ + public static final OptionID DATABASE_CONNECTION_ID = new OptionID("dbc", "Database connection class."); + /** * Initialize the database, for example by loading the input data. (Since this * should NOT be done on construction time!) diff --git a/src/de/lmu/ifi/dbs/elki/database/DatabaseEventManager.java b/src/de/lmu/ifi/dbs/elki/database/DatabaseEventManager.java index ce6e4d9a..4b9c9d94 100644 --- a/src/de/lmu/ifi/dbs/elki/database/DatabaseEventManager.java +++ b/src/de/lmu/ifi/dbs/elki/database/DatabaseEventManager.java @@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.database; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2012 +Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -88,7 +88,7 @@ public class DatabaseEventManager { public void flushDataStoreEvents() {
// inform listeners
Object[] listeners = listenerList.getListenerList();
- Map<Type, DBIDs> objects = new HashMap<Type, DBIDs>();
+ Map<Type, DBIDs> objects = new HashMap<>();
objects.put(currentDataStoreEventType, DBIDUtil.makeUnmodifiable(dataStoreObjects));
DataStoreEvent e = new DataStoreEvent(this, objects);
diff --git a/src/de/lmu/ifi/dbs/elki/database/HashmapDatabase.java b/src/de/lmu/ifi/dbs/elki/database/HashmapDatabase.java index 069de73e..e7106927 100644 --- a/src/de/lmu/ifi/dbs/elki/database/HashmapDatabase.java +++ b/src/de/lmu/ifi/dbs/elki/database/HashmapDatabase.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -44,13 +44,13 @@ import de.lmu.ifi.dbs.elki.datasource.FileBasedDatabaseConnection; import de.lmu.ifi.dbs.elki.datasource.bundle.MultipleObjectsBundle; import de.lmu.ifi.dbs.elki.datasource.bundle.ObjectBundle; import de.lmu.ifi.dbs.elki.datasource.bundle.SingleObjectBundle; +import de.lmu.ifi.dbs.elki.index.DynamicIndex; import de.lmu.ifi.dbs.elki.index.Index; import de.lmu.ifi.dbs.elki.index.IndexFactory; import de.lmu.ifi.dbs.elki.logging.Logging; import de.lmu.ifi.dbs.elki.utilities.documentation.Description; import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException; import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID; import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectListParameter; @@ -172,7 +172,11 @@ public class HashmapDatabase extends AbstractDatabase implements UpdatableDataba // Notify indexes of insertions for (Index index : indexes) { - index.insertAll(newids); + if (index instanceof DynamicIndex) { + ((DynamicIndex) index).insertAll(newids); + } else { + LOG.warning("Non-dynamic indexes have been added to the database. Updates are not possible!"); + } } // fire insertion event @@ -222,7 +226,7 @@ public class HashmapDatabase extends AbstractDatabase implements UpdatableDataba private Relation<?> addNewRelation(SimpleTypeInformation<?> meta) { @SuppressWarnings("unchecked") SimpleTypeInformation<Object> ometa = (SimpleTypeInformation<Object>) meta; - Relation<?> relation = new MaterializedRelation<Object>(this, ometa, ids); + Relation<?> relation = new MaterializedRelation<>(this, ometa, ids); relations.add(relation); getHierarchy().add(this, relation); // Try to add indexes where appropriate @@ -232,24 +236,27 @@ public class HashmapDatabase extends AbstractDatabase implements UpdatableDataba final IndexFactory<Object, ?> ofact = (IndexFactory<Object, ?>) factory; @SuppressWarnings("unchecked") final Relation<Object> orep = (Relation<Object>) relation; - addIndex(ofact.instantiate(orep)); + Index index = ofact.instantiate(orep); + addIndex(index); + index.initialize(); } } return relation; } /** - * Removes the objects from the database (by calling {@link #doDelete(DBIDRef)} - * for each object) and indexes and fires a deletion event. + * Removes the objects from the database (by calling + * {@link #doDelete(DBIDRef)} for each object) and indexes and fires a + * deletion event. * - * {@inheritDoc} + * {@inheritDoc} */ @Override public MultipleObjectsBundle delete(DBIDs ids) { // Prepare bundle to return MultipleObjectsBundle bundle = new MultipleObjectsBundle(); for (Relation<?> relation : relations) { - ArrayList<Object> data = new ArrayList<Object>(ids.size()); + ArrayList<Object> data = new ArrayList<>(ids.size()); for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { data.add(relation.get(iter)); } @@ -261,7 +268,12 @@ public class HashmapDatabase extends AbstractDatabase implements UpdatableDataba } // Remove from indexes for (Index index : indexes) { - index.deleteAll(ids); + if (index instanceof DynamicIndex) { + ((DynamicIndex) index).deleteAll(ids); + } else { + LOG.warning("Non-dynamic indexes have been added to the database. Updates are not possible!"); + } + } // fire deletion event eventManager.fireObjectsRemoved(ids); @@ -270,10 +282,10 @@ public class HashmapDatabase extends AbstractDatabase implements UpdatableDataba } /** - * Removes the object from the database (by calling {@link #doDelete(DBIDRef)}) - * and indexes and fires a deletion event. - * - * {@inheritDoc} + * Removes the object from the database (by calling {@link #doDelete(DBIDRef)} + * ) and indexes and fires a deletion event. + * + * {@inheritDoc} */ @Override public SingleObjectBundle delete(DBIDRef id) { @@ -285,7 +297,11 @@ public class HashmapDatabase extends AbstractDatabase implements UpdatableDataba doDelete(id); // Remove from indexes for (Index index : indexes) { - index.delete(id); + if (index instanceof DynamicIndex) { + ((DynamicIndex) index).delete(id); + } else { + LOG.warning("Non-dynamic indexes have been added to the database. Updates are not possible!"); + } } // fire deletion event eventManager.fireObjectRemoved(id); @@ -338,12 +354,12 @@ public class HashmapDatabase extends AbstractDatabase implements UpdatableDataba protected void makeOptions(Parameterization config) { super.makeOptions(config); // Get database connection. - final ObjectParameter<DatabaseConnection> dbcP = new ObjectParameter<DatabaseConnection>(OptionID.DATABASE_CONNECTION, DatabaseConnection.class, FileBasedDatabaseConnection.class); + final ObjectParameter<DatabaseConnection> dbcP = new ObjectParameter<>(Database.DATABASE_CONNECTION_ID, DatabaseConnection.class, FileBasedDatabaseConnection.class); if (config.grab(dbcP)) { databaseConnection = dbcP.instantiateClass(config); } // Get indexes. - final ObjectListParameter<IndexFactory<?, ?>> indexFactoryP = new ObjectListParameter<IndexFactory<?, ?>>(INDEX_ID, IndexFactory.class, true); + final ObjectListParameter<IndexFactory<?, ?>> indexFactoryP = new ObjectListParameter<>(INDEX_ID, IndexFactory.class, true); if (config.grab(indexFactoryP)) { indexFactories = indexFactoryP.instantiateClasses(config); } diff --git a/src/de/lmu/ifi/dbs/elki/database/ProxyDatabase.java b/src/de/lmu/ifi/dbs/elki/database/ProxyDatabase.java index 3f41326a..a06b7a12 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ProxyDatabase.java +++ b/src/de/lmu/ifi/dbs/elki/database/ProxyDatabase.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -43,14 +43,9 @@ public class ProxyDatabase extends AbstractDatabase { private static final Logging LOG = Logging.getLogger(ProxyDatabase.class); /** - * Our DBIDs - */ - final protected DBIDs ids; - - /** * Our DBID representation */ - final protected DBIDView idrep; + protected DBIDView idrep; /** * Constructor. @@ -59,8 +54,7 @@ public class ProxyDatabase extends AbstractDatabase { */ public ProxyDatabase(DBIDs ids) { super(); - this.ids = ids; - this.idrep = new DBIDView(this, this.ids); + this.idrep = new DBIDView(this, ids); this.relations.add(idrep); this.addChildResult(idrep); } @@ -73,11 +67,10 @@ public class ProxyDatabase extends AbstractDatabase { */ public ProxyDatabase(DBIDs ids, Iterable<Relation<?>> relations) { super(); - this.ids = ids; - this.idrep = new DBIDView(this, this.ids); + this.idrep = new DBIDView(this, ids); this.relations.add(idrep); this.addChildResult(idrep); - for(Relation<?> orel : relations) { + for (Relation<?> orel : relations) { Relation<?> relation = ProxyView.wrap(this, ids, orel); this.relations.add(relation); this.addChildResult(relation); @@ -122,4 +115,19 @@ public class ProxyDatabase extends AbstractDatabase { protected Logging getLogger() { return LOG; } -}
\ No newline at end of file + + /** + * Set the DBIDs to use. + * + * @param ids DBIDs to use + */ + public void setDBIDs(DBIDs ids) { + this.idrep.setDBIDs(ids); + // Update relations. + for (Relation<?> orel : this.relations) { + if (orel instanceof ProxyView) { + ((ProxyView<?>) orel).setDBIDs(this.idrep.getDBIDs()); + } + } + } +} diff --git a/src/de/lmu/ifi/dbs/elki/database/QueryUtil.java b/src/de/lmu/ifi/dbs/elki/database/QueryUtil.java index f65b3cba..73259b5d 100644 --- a/src/de/lmu/ifi/dbs/elki/database/QueryUtil.java +++ b/src/de/lmu/ifi/dbs/elki/database/QueryUtil.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -28,10 +28,10 @@ import de.lmu.ifi.dbs.elki.database.query.distance.PrimitiveDistanceQuery; import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery; import de.lmu.ifi.dbs.elki.database.query.knn.LinearScanKNNQuery; import de.lmu.ifi.dbs.elki.database.query.knn.LinearScanPrimitiveDistanceKNNQuery; -import de.lmu.ifi.dbs.elki.database.query.knn.LinearScanRawDoubleDistanceKNNQuery; +import de.lmu.ifi.dbs.elki.database.query.knn.DoubleOptimizedKNNQuery; import de.lmu.ifi.dbs.elki.database.query.range.LinearScanPrimitiveDistanceRangeQuery; import de.lmu.ifi.dbs.elki.database.query.range.LinearScanRangeQuery; -import de.lmu.ifi.dbs.elki.database.query.range.LinearScanRawDoubleDistanceRangeQuery; +import de.lmu.ifi.dbs.elki.database.query.range.DoubleOptimizedRangeQuery; import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery; import de.lmu.ifi.dbs.elki.database.query.rknn.RKNNQuery; import de.lmu.ifi.dbs.elki.database.query.similarity.SimilarityQuery; @@ -233,17 +233,17 @@ public final class QueryUtil { if(distanceQuery.getDistanceFunction() instanceof PrimitiveDoubleDistanceFunction) { final PrimitiveDistanceQuery<O, ?> pdq = (PrimitiveDistanceQuery<O, ?>) distanceQuery; @SuppressWarnings("unchecked") - final KNNQuery<O, ?> knnQuery = new LinearScanRawDoubleDistanceKNNQuery<O>((PrimitiveDistanceQuery<O, DoubleDistance>) pdq); + final KNNQuery<O, ?> knnQuery = new DoubleOptimizedKNNQuery<>((PrimitiveDistanceQuery<O, DoubleDistance>) pdq); @SuppressWarnings("unchecked") final KNNQuery<O, D> castQuery = (KNNQuery<O, D>) knnQuery; return castQuery; } else { final PrimitiveDistanceQuery<O, D> pdq = (PrimitiveDistanceQuery<O, D>) distanceQuery; - return new LinearScanPrimitiveDistanceKNNQuery<O, D>(pdq); + return new LinearScanPrimitiveDistanceKNNQuery<>(pdq); } } - return new LinearScanKNNQuery<O, D>(distanceQuery); + return new LinearScanKNNQuery<>(distanceQuery); } /** @@ -260,16 +260,16 @@ public final class QueryUtil { if(distanceQuery.getDistanceFunction() instanceof PrimitiveDoubleDistanceFunction) { final PrimitiveDistanceQuery<O, ?> pdq = (PrimitiveDistanceQuery<O, ?>) distanceQuery; @SuppressWarnings("unchecked") - final RangeQuery<O, ?> knnQuery = new LinearScanRawDoubleDistanceRangeQuery<O>((PrimitiveDistanceQuery<O, DoubleDistance>) pdq); + final RangeQuery<O, ?> knnQuery = new DoubleOptimizedRangeQuery<>((PrimitiveDistanceQuery<O, DoubleDistance>) pdq); @SuppressWarnings("unchecked") final RangeQuery<O, D> castQuery = (RangeQuery<O, D>) knnQuery; return castQuery; } else { final PrimitiveDistanceQuery<O, D> pdq = (PrimitiveDistanceQuery<O, D>) distanceQuery; - return new LinearScanPrimitiveDistanceRangeQuery<O, D>(pdq); + return new LinearScanPrimitiveDistanceRangeQuery<>(pdq); } } - return new LinearScanRangeQuery<O, D>(distanceQuery); + return new LinearScanRangeQuery<>(distanceQuery); } }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/database/StaticArrayDatabase.java b/src/de/lmu/ifi/dbs/elki/database/StaticArrayDatabase.java index c2d66f5c..7916c75f 100644 --- a/src/de/lmu/ifi/dbs/elki/database/StaticArrayDatabase.java +++ b/src/de/lmu/ifi/dbs/elki/database/StaticArrayDatabase.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -43,9 +43,9 @@ import de.lmu.ifi.dbs.elki.datasource.bundle.ObjectBundle; import de.lmu.ifi.dbs.elki.index.Index; import de.lmu.ifi.dbs.elki.index.IndexFactory; import de.lmu.ifi.dbs.elki.logging.Logging; +import de.lmu.ifi.dbs.elki.logging.statistics.Duration; import de.lmu.ifi.dbs.elki.utilities.documentation.Description; import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID; import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectListParameter; @@ -98,7 +98,7 @@ public class StaticArrayDatabase extends AbstractDatabase implements Parameteriz this.idrep = null; // Add indexes. - if(indexFactories != null) { + if (indexFactories != null) { this.indexFactories.addAll(indexFactories); } } @@ -116,8 +116,8 @@ public class StaticArrayDatabase extends AbstractDatabase implements Parameteriz */ @Override public void initialize() { - if(databaseConnection != null) { - if(LOG.isDebugging()) { + if (databaseConnection != null) { + if (LOG.isDebugging()) { LOG.debugFine("Loading data from database connection."); } MultipleObjectsBundle objpackages = databaseConnection.loadData(); @@ -127,12 +127,11 @@ public class StaticArrayDatabase extends AbstractDatabase implements Parameteriz // Find DBID column int idrepnr = findDBIDColumn(objpackages); // Build DBID array - if(idrepnr == -1) { + if (idrepnr == -1) { this.ids = DBIDUtil.generateStaticDBIDRange(objpackages.dataLength()); - } - else { + } else { final ArrayModifiableDBIDs newids = DBIDUtil.newArray(objpackages.dataLength()); - for(int j = 0; j < objpackages.dataLength(); j++) { + for (int j = 0; j < objpackages.dataLength(); j++) { DBID newid = (DBID) objpackages.data(j, idrepnr); newids.add(newid); } @@ -148,11 +147,11 @@ public class StaticArrayDatabase extends AbstractDatabase implements Parameteriz Relation<?>[] targets = alignColumns(objpackages); DBIDIter newid = ids.iter(); - for(int j = 0; j < objpackages.dataLength(); j++, newid.advance()) { + for (int j = 0; j < objpackages.dataLength(); j++, newid.advance()) { // insert object - for(int i = 0; i < targets.length; i++) { + for (int i = 0; i < targets.length; i++) { // DBIDs were handled above. - if(i == idrepnr) { + if (i == idrepnr) { continue; } @SuppressWarnings("unchecked") @@ -161,18 +160,26 @@ public class StaticArrayDatabase extends AbstractDatabase implements Parameteriz } } - for(Relation<?> relation : relations) { + for (Relation<?> relation : relations) { SimpleTypeInformation<?> meta = relation.getDataTypeInformation(); // Try to add indexes where appropriate - for(IndexFactory<?, ?> factory : indexFactories) { - if(factory.getInputTypeRestriction().isAssignableFromType(meta)) { + for (IndexFactory<?, ?> factory : indexFactories) { + if (factory.getInputTypeRestriction().isAssignableFromType(meta)) { @SuppressWarnings("unchecked") final IndexFactory<Object, ?> ofact = (IndexFactory<Object, ?>) factory; @SuppressWarnings("unchecked") final Relation<Object> orep = (Relation<Object>) relation; final Index index = ofact.instantiate(orep); + Duration duration = LOG.isStatistics() ? LOG.newDuration(index.getClass().getName() + ".construction") : null; + if (duration != null) { + duration.begin(); + } + index.initialize(); + if (duration != null) { + duration.end(); + LOG.statistics(duration); + } addIndex(index); - index.insertAll(ids); } } } @@ -184,7 +191,7 @@ public class StaticArrayDatabase extends AbstractDatabase implements Parameteriz @Override public void addIndex(Index index) { - if(LOG.isDebuggingFiner()) { + if (LOG.isDebuggingFiner()) { LOG.debugFine("Adding index: " + index); } this.indexes.add(index); @@ -192,7 +199,6 @@ public class StaticArrayDatabase extends AbstractDatabase implements Parameteriz this.addChildResult(index); } - /** * Find an DBID column. * @@ -200,9 +206,9 @@ public class StaticArrayDatabase extends AbstractDatabase implements Parameteriz * @return DBID column */ protected int findDBIDColumn(ObjectBundle pack) { - for(int i = 0; i < pack.metaLength(); i++) { + for (int i = 0; i < pack.metaLength(); i++) { SimpleTypeInformation<?> meta = pack.meta(i); - if(TypeUtil.DBID.isAssignableFromType(meta)) { + if (TypeUtil.DBID.isAssignableFromType(meta)) { return i; } } @@ -220,19 +226,19 @@ public class StaticArrayDatabase extends AbstractDatabase implements Parameteriz // align representations. Relation<?>[] targets = new Relation<?>[pack.metaLength()]; BitSet used = new BitSet(relations.size()); - for(int i = 0; i < targets.length; i++) { + for (int i = 0; i < targets.length; i++) { SimpleTypeInformation<?> meta = pack.meta(i); // TODO: aggressively try to match exact metas first? // Try to match unused representations only - for(int j = used.nextClearBit(0); j >= 0 && j < relations.size(); j = used.nextClearBit(j + 1)) { + for (int j = used.nextClearBit(0); j >= 0 && j < relations.size(); j = used.nextClearBit(j + 1)) { Relation<?> relation = relations.get(j); - if(relation.getDataTypeInformation().isAssignableFromType(meta)) { + if (relation.getDataTypeInformation().isAssignableFromType(meta)) { targets[i] = relation; used.set(j); break; } } - if(targets[i] == null) { + if (targets[i] == null) { targets[i] = addNewRelation(meta); used.set(relations.size() - 1); } @@ -249,7 +255,7 @@ public class StaticArrayDatabase extends AbstractDatabase implements Parameteriz private Relation<?> addNewRelation(SimpleTypeInformation<?> meta) { @SuppressWarnings("unchecked") SimpleTypeInformation<Object> ometa = (SimpleTypeInformation<Object>) meta; - Relation<?> relation = new MaterializedRelation<Object>(this, ometa, ids); + Relation<?> relation = new MaterializedRelation<>(this, ometa, ids); relations.add(relation); getHierarchy().add(this, relation); return relation; @@ -282,13 +288,13 @@ public class StaticArrayDatabase extends AbstractDatabase implements Parameteriz protected void makeOptions(Parameterization config) { super.makeOptions(config); // Get database connection. - final ObjectParameter<DatabaseConnection> dbcP = new ObjectParameter<DatabaseConnection>(OptionID.DATABASE_CONNECTION, DatabaseConnection.class, FileBasedDatabaseConnection.class); - if(config.grab(dbcP)) { + final ObjectParameter<DatabaseConnection> dbcP = new ObjectParameter<>(Database.DATABASE_CONNECTION_ID, DatabaseConnection.class, FileBasedDatabaseConnection.class); + if (config.grab(dbcP)) { databaseConnection = dbcP.instantiateClass(config); } // Get indexes. - final ObjectListParameter<IndexFactory<?, ?>> indexFactoryP = new ObjectListParameter<IndexFactory<?, ?>>(INDEX_ID, IndexFactory.class, true); - if(config.grab(indexFactoryP)) { + final ObjectListParameter<IndexFactory<?, ?>> indexFactoryP = new ObjectListParameter<>(INDEX_ID, IndexFactory.class, true); + if (config.grab(indexFactoryP)) { indexFactories = indexFactoryP.instantiateClasses(config); } } @@ -298,4 +304,4 @@ public class StaticArrayDatabase extends AbstractDatabase implements Parameteriz return new StaticArrayDatabase(databaseConnection, indexFactories); } } -}
\ No newline at end of file +} diff --git a/src/de/lmu/ifi/dbs/elki/database/UpdatableDatabase.java b/src/de/lmu/ifi/dbs/elki/database/UpdatableDatabase.java index 86555a86..f22dd799 100644 --- a/src/de/lmu/ifi/dbs/elki/database/UpdatableDatabase.java +++ b/src/de/lmu/ifi/dbs/elki/database/UpdatableDatabase.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/DBIDDataStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/DBIDDataStore.java index 7941219f..8c0eb2cb 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/DBIDDataStore.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/DBIDDataStore.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/DataStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/DataStore.java index a6d5a704..384680c6 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/DataStore.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/DataStore.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreEvent.java b/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreEvent.java index 5c0a6836..7942fb9b 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreEvent.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreEvent.java @@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.database.datastore; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2012 +Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreFactory.java b/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreFactory.java index aca5b86f..7b3cd0e7 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreFactory.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreFactory.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreIDMap.java b/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreIDMap.java index cba8e4c9..adfd1354 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreIDMap.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreIDMap.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreListener.java b/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreListener.java index 609fe67d..a3f1319d 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreListener.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreListener.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreUtil.java b/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreUtil.java index a9052f87..6d0c2d0f 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreUtil.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreUtil.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -24,6 +24,7 @@ package de.lmu.ifi.dbs.elki.database.datastore; */ import de.lmu.ifi.dbs.elki.database.ids.DBIDs; +import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; /** * Storage utility class. Mostly a shorthand for @@ -123,4 +124,17 @@ public final class DataStoreUtil { public static WritableRecordStore makeRecordStorage(DBIDs ids, int hints, Class<?>... dataclasses) { return DataStoreFactory.FACTORY.makeRecordStorage(ids, hints, dataclasses); } + + /** + * Make a new storage, to associate the given ids with an double valued + * distance. + * + * @param ids DBIDs to store data for + * @param hints Hints for the storage manager + * @return new data store + */ + public static WritableDoubleDistanceDataStore makeDoubleDistanceStorage(DBIDs ids, int hints) { + // FIXME: this is an ugly work-around. + return (WritableDoubleDistanceDataStore) DataStoreFactory.FACTORY.makeStorage(ids, hints, DoubleDistance.class); + } } diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/DoubleDataStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/DoubleDataStore.java index 3348a246..b121d195 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/DoubleDataStore.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/DoubleDataStore.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/DoubleDistanceDataStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/DoubleDistanceDataStore.java index f74b681a..88b9d4dc 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/DoubleDistanceDataStore.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/DoubleDistanceDataStore.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/IntegerDataStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/IntegerDataStore.java index e450c11b..969e2228 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/IntegerDataStore.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/IntegerDataStore.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/RecordStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/RecordStore.java index 508dae8e..07bf2dcf 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/RecordStore.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/RecordStore.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDBIDDataStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDBIDDataStore.java index 960b79ac..bae55a57 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDBIDDataStore.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDBIDDataStore.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDataStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDataStore.java index 93176445..c62fc721 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDataStore.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDataStore.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDoubleDataStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDoubleDataStore.java index 19cc54c7..a40f0ef4 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDoubleDataStore.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDoubleDataStore.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDoubleDistanceDataStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDoubleDistanceDataStore.java index 03a3e75e..f929d5d7 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDoubleDistanceDataStore.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDoubleDistanceDataStore.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/WritableIntegerDataStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/WritableIntegerDataStore.java index b8bf1348..fb323b02 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/WritableIntegerDataStore.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/WritableIntegerDataStore.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/WritableRecordStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/WritableRecordStore.java index 0799fdfe..c4c182e9 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/WritableRecordStore.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/WritableRecordStore.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayDBIDStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayDBIDStore.java index c9bc6438..2d5033ab 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayDBIDStore.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayDBIDStore.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -78,7 +78,7 @@ public class ArrayDBIDStore implements WritableDBIDDataStore { @Override public void assignVar(DBIDRef id, DBIDVar var) { - data.assign(idmap.mapDBIDToOffset(id), var); + data.assignVar(idmap.mapDBIDToOffset(id), var); } @Override diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayDoubleDistanceStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayDoubleDistanceStore.java index 99ec1382..2bf8161d 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayDoubleDistanceStore.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayDoubleDistanceStore.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayDoubleStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayDoubleStore.java index 1d8920bf..501d5369 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayDoubleStore.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayDoubleStore.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayIntegerStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayIntegerStore.java index bb250164..d5b5cfb9 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayIntegerStore.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayIntegerStore.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayRecordStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayRecordStore.java index 4dd9a684..2767b180 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayRecordStore.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayRecordStore.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -62,7 +62,7 @@ public class ArrayRecordStore implements WritableRecordStore { @Override public <T> WritableDataStore<T> getStorage(int col, Class<? super T> datatype) { // TODO: add type checking safety? - return new StorageAccessor<T>(col); + return new StorageAccessor<>(col); } /** diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayStore.java index 29658818..367b634f 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayStore.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayStore.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDDBIDStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDDBIDStore.java index 565d0848..9b8a4be8 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDDBIDStore.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDDBIDStore.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDDoubleDistanceStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDDoubleDistanceStore.java index 82570639..be12b54c 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDDoubleDistanceStore.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDDoubleDistanceStore.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDDoubleStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDDoubleStore.java index 944f9710..8d73b672 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDDoubleStore.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDDoubleStore.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDIntegerStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDIntegerStore.java index f31c97f9..935f23f4 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDIntegerStore.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDIntegerStore.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDRecordStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDRecordStore.java index 2926f14c..c9004a0f 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDRecordStore.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDRecordStore.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -83,7 +83,7 @@ public class MapIntegerDBIDRecordStore implements WritableRecordStore { @Override public <T> WritableDataStore<T> getStorage(int col, Class<? super T> datatype) { // TODO: add type checking? - return new StorageAccessor<T>(col); + return new StorageAccessor<>(col); } /** diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDStore.java index 236389e4..ede82f15 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDStore.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDStore.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -58,7 +58,7 @@ public class MapIntegerDBIDStore<T> implements WritableDataStore<T> { */ public MapIntegerDBIDStore() { super(); - this.data = new TIntObjectHashMap<T>(); + this.data = new TIntObjectHashMap<>(); } /** @@ -67,7 +67,7 @@ public class MapIntegerDBIDStore<T> implements WritableDataStore<T> { * @param size Expected size */ public MapIntegerDBIDStore(int size) { - this.data = new TIntObjectHashMap<T>(size); + this.data = new TIntObjectHashMap<>(size); } @Override diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapRecordStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapRecordStore.java index 20778327..8c8c4bc9 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapRecordStore.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapRecordStore.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -76,7 +76,7 @@ public class MapRecordStore implements WritableRecordStore { @Override public <T> WritableDataStore<T> getStorage(int col, Class<? super T> datatype) { // TODO: add type checking? - return new StorageAccessor<T>(col); + return new StorageAccessor<>(col); } /** diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapStore.java index 9818afd2..c40e0a72 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapStore.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapStore.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -60,7 +60,7 @@ public class MapStore<T> implements WritableDataStore<T> { */ public MapStore() { super(); - this.data = new HashMap<DBID, T>(); + this.data = new HashMap<>(); } @Override diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MemoryDataStoreFactory.java b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MemoryDataStoreFactory.java index 06a80fd7..2a6cd1cb 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MemoryDataStoreFactory.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MemoryDataStoreFactory.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -65,10 +65,10 @@ public class MemoryDataStoreFactory implements DataStoreFactory { if(ids instanceof DBIDRange) { DBIDRange range = (DBIDRange) ids; Object[] data = new Object[range.size()]; - return new ArrayStore<T>(data, range); + return new ArrayStore<>(data, range); } else { - return new MapIntegerDBIDStore<T>(ids.size()); + return new MapIntegerDBIDStore<>(ids.size()); } } diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/package-info.java b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/package-info.java index 6200bb46..5ea46015 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/memory/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2012 +Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/package-info.java b/src/de/lmu/ifi/dbs/elki/database/datastore/package-info.java index e5b4a259..f213019d 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/package-info.java @@ -24,7 +24,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2012 +Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/ArrayDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/ArrayDBIDs.java index 7e9c55c0..865e0bb7 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/ArrayDBIDs.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/ArrayDBIDs.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -47,7 +47,7 @@ public interface ArrayDBIDs extends DBIDs { * @param index Position * @param var Variable to assign the value to. */ - public void assign(int index, DBIDVar var); + public void assignVar(int index, DBIDVar var); /** * Iterable diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/ArrayModifiableDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/ArrayModifiableDBIDs.java index ffac393b..3db40630 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/ArrayModifiableDBIDs.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/ArrayModifiableDBIDs.java @@ -6,7 +6,7 @@ import java.util.Comparator; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/ArrayStaticDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/ArrayStaticDBIDs.java index a14eac0c..47cf295f 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/ArrayStaticDBIDs.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/ArrayStaticDBIDs.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/DBID.java b/src/de/lmu/ifi/dbs/elki/database/ids/DBID.java index 5abf4377..a773ee27 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/DBID.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/DBID.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDArrayIter.java b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDArrayIter.java index fefe5ad1..ef1132b3 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDArrayIter.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDArrayIter.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -22,7 +22,7 @@ package de.lmu.ifi.dbs.elki.database.ids; You should have received a copy of the GNU Affero General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import de.lmu.ifi.dbs.elki.utilities.iterator.ArrayIter; +import de.lmu.ifi.dbs.elki.utilities.datastructures.iterator.ArrayIter; /** * Array iterators that can also go backwards and seek. diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDArrayMIter.java b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDArrayMIter.java index 1de202a2..1aaefc8e 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDArrayMIter.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDArrayMIter.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDFactory.java b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDFactory.java index 646e6e4d..4c6472a7 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDFactory.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDFactory.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,6 +23,10 @@ package de.lmu.ifi.dbs.elki.database.ids; along with this program. If not, see <http://www.gnu.org/licenses/>. */ +import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDPair; +import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPair; +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.ids.integer.TrivialDBIDFactory; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; import de.lmu.ifi.dbs.elki.persistent.ByteBufferSerializer; @@ -192,6 +196,27 @@ public interface DBIDFactory { HashSetModifiableDBIDs newHashSet(DBIDs existing); /** + * Create an appropriate heap for the distance function. + * + * This will use a double heap if appropriate. + * + * @param factory distance prototype + * @param k K value + * @param <D> distance type + * @return New heap of size k, appropriate for this distance type. + */ + <D extends Distance<D>> KNNHeap<D> newHeap(D factory, int k); + + /** + * Build a new heap from a given list. + * + * @param exist Existing result + * @param <D> Distance type + * @return New heap + */ + <D extends Distance<D>> KNNHeap<D> newHeap(KNNList<D> exist); + + /** * Get a serializer for DBIDs. * * @return DBID serializer diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDIter.java b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDIter.java index 268f4441..f051d51c 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDIter.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDIter.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,7 +23,7 @@ package de.lmu.ifi.dbs.elki.database.ids; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import de.lmu.ifi.dbs.elki.utilities.iterator.Iter; +import de.lmu.ifi.dbs.elki.utilities.datastructures.iterator.Iter; /** * Iterator for DBIDs. diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDMIter.java b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDMIter.java index 9f42c5a0..0fbed7e0 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDMIter.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDMIter.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,7 +23,7 @@ package de.lmu.ifi.dbs.elki.database.ids; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import de.lmu.ifi.dbs.elki.utilities.iterator.MIter; +import de.lmu.ifi.dbs.elki.utilities.datastructures.iterator.MIter; /** * Modifiable DBID iterator. diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDPair.java b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDPair.java index 8f03e279..bdbbe2da 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDPair.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDPair.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDRange.java b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDRange.java index 8f7e428d..588cfe6a 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDRange.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDRange.java @@ -6,7 +6,7 @@ import de.lmu.ifi.dbs.elki.database.datastore.DataStoreIDMap; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDRef.java b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDRef.java index fce87c31..77cc621e 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDRef.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDRef.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDUtil.java b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDUtil.java index 9cb4082a..78dba268 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDUtil.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDUtil.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -25,10 +25,17 @@ package de.lmu.ifi.dbs.elki.database.ids; import java.util.Random; +import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDPair; +import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPair; +import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNList; +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.ids.generic.DoubleDistanceKNNSubList; +import de.lmu.ifi.dbs.elki.database.ids.generic.KNNSubList; import de.lmu.ifi.dbs.elki.database.ids.generic.UnmodifiableArrayDBIDs; import de.lmu.ifi.dbs.elki.database.ids.generic.UnmodifiableDBIDs; +import de.lmu.ifi.dbs.elki.database.ids.integer.IntegerArrayDBIDs; import de.lmu.ifi.dbs.elki.database.ids.integer.IntegerDBIDs; -import de.lmu.ifi.dbs.elki.database.ids.integer.TroveArrayDBIDs; import de.lmu.ifi.dbs.elki.database.ids.integer.UnmodifiableIntegerArrayDBIDs; import de.lmu.ifi.dbs.elki.database.ids.integer.UnmodifiableIntegerDBIDs; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; @@ -319,9 +326,33 @@ public final class DBIDUtil { * @return size */ public static int intersectionSize(DBIDs first, DBIDs second) { - if (first.size() > second.size()) { - return intersectionSize(second, first); + // If exactly one is a Set, use it as second parameter. + if (second instanceof SetDBIDs) { + if (!(first instanceof SetDBIDs)) { + return internalIntersectionSize(first, second); + } + } else { + if (first instanceof SetDBIDs) { + return internalIntersectionSize(second, first); + } } + // Both are the same type: both set or both non set. + // Smaller goes first. + if (first.size() <= second.size()) { + return internalIntersectionSize(first, second); + } else { + return internalIntersectionSize(second, first); + } + } + + /** + * Compute the set intersection size of two sets. + * + * @param first First set + * @param second Second set + * @return size + */ + private static int internalIntersectionSize(DBIDs first, DBIDs second) { int c = 0; for (DBIDIter it = first.iter(); it.valid(); it.advance()) { if (second.contains(it)) { @@ -398,8 +429,8 @@ public final class DBIDUtil { if (existing instanceof StaticDBIDs) { return (StaticDBIDs) existing; } - if (existing instanceof TroveArrayDBIDs) { - return new UnmodifiableIntegerArrayDBIDs((TroveArrayDBIDs) existing); + if (existing instanceof IntegerArrayDBIDs) { + return new UnmodifiableIntegerArrayDBIDs((IntegerArrayDBIDs) existing); } if (existing instanceof IntegerDBIDs) { return new UnmodifiableIntegerDBIDs((IntegerDBIDs) existing); @@ -504,6 +535,31 @@ public final class DBIDUtil { } /** + * Create an appropriate heap for the distance type. + * + * This will use a double heap if appropriate. + * + * @param distancetype distance prototype + * @param k K value + * @param <D> distance type + * @return New heap of size k, appropriate for this distance type. + */ + public static <D extends Distance<D>> KNNHeap<D> newHeap(D distancetype, int k) { + return DBIDFactory.FACTORY.newHeap(distancetype, k); + } + + /** + * Build a new heap from a given list. + * + * @param exist Existing result + * @param <D> Distance type + * @return New heap + */ + public static <D extends Distance<D>> KNNHeap<D> newHeap(KNNList<D> exist) { + return DBIDFactory.FACTORY.newHeap(exist); + } + + /** * Produce a random sample of the given DBIDs. * * @param source Original DBIDs @@ -614,4 +670,23 @@ public final class DBIDUtil { return sample; } } + + /** + * Get a subset of the KNN result. + * + * @param list Existing list + * @param k k + * @param <D> distance type + * @return Subset + */ + @SuppressWarnings("unchecked") + public static <D extends Distance<D>> KNNList<D> subList(KNNList<D> list, int k) { + if (k >= list.size()) { + return list; + } + if (list instanceof DoubleDistanceKNNList) { + return (KNNList<D>) new DoubleDistanceKNNSubList((DoubleDistanceKNNList) list, k); + } + return new KNNSubList<>(list, k); + } } diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDVar.java b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDVar.java index b66ae5f5..94480fe9 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDVar.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDVar.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDs.java index 0b9db136..2bf2b28d 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDs.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDs.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/DoubleDBIDPair.java b/src/de/lmu/ifi/dbs/elki/database/ids/DoubleDBIDPair.java index 06210076..970092b0 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/DoubleDBIDPair.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/DoubleDBIDPair.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/EmptyDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/EmptyDBIDs.java index 995f917c..8a7b2e28 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/EmptyDBIDs.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/EmptyDBIDs.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -68,7 +68,7 @@ public class EmptyDBIDs implements ArrayStaticDBIDs, SetDBIDs { } @Override - public void assign(int index, DBIDVar var) { + public void assignVar(int index, DBIDVar var) { throw new ArrayIndexOutOfBoundsException(); } diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/HashSetDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/HashSetDBIDs.java index 5ff0bc97..cabe9898 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/HashSetDBIDs.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/HashSetDBIDs.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/HashSetModifiableDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/HashSetModifiableDBIDs.java index efb39bc8..6a57f5f0 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/HashSetModifiableDBIDs.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/HashSetModifiableDBIDs.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/ModifiableDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/ModifiableDBIDs.java index 547f3297..1cd8c4e7 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/ModifiableDBIDs.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/ModifiableDBIDs.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/SetDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/SetDBIDs.java index 7fd28326..3a92593e 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/SetDBIDs.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/SetDBIDs.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/StaticDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/StaticDBIDs.java index ce616da3..2ba30d4b 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/StaticDBIDs.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/StaticDBIDs.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/distance/DistanceDBIDList.java b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DistanceDBIDList.java new file mode 100644 index 00000000..360dda12 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DistanceDBIDList.java @@ -0,0 +1,87 @@ +package de.lmu.ifi.dbs.elki.database.ids.distance; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import de.lmu.ifi.dbs.elki.database.ids.DBIDs; +import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; + +/** + * Collection of objects and their distances. + * + * To iterate over the results, use the following code: + * + * <pre> + * {@code + * for (DistanceDBIDResultIter<D> iter = result.iter(); iter.valid(); iter.advance()) { + * // You can get the distance via: iter.getDistance(); + * // Or use iter just like any other DBIDRef + * } + * } + * </pre> + * + * If you are only interested in the IDs of the objects, the following is also + * sufficient: + * + * <pre> + * {@code + * for (DBIDIter<D> iter = result.iter(); iter.valid(); iter.advance()) { + * // Use iter just like any other DBIDRef + * } + * } + * </pre> + * + * @author Erich Schubert + * + * @apiviz.landmark + * + * @apiviz.composedOf DistanceDBIDPair + * @apiviz.has DistanceDBIDListIter + * + * @param <D> Distance type + */ +public interface DistanceDBIDList<D extends Distance<D>> extends DBIDs { + /** + * Size of list. + * + * @return Size + */ + @Override + int size(); + + /** + * Access a single pair. + * + * @param off Offset + * @return Pair + */ + DistanceDBIDPair<D> get(int off); + + /** + * Get an iterator + * + * @return New iterator + */ + @Override + DistanceDBIDListIter<D> iter(); +} diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/distance/DistanceDBIDListIter.java b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DistanceDBIDListIter.java new file mode 100644 index 00000000..914f3676 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DistanceDBIDListIter.java @@ -0,0 +1,55 @@ +package de.lmu.ifi.dbs.elki.database.ids.distance; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import de.lmu.ifi.dbs.elki.database.ids.DBIDArrayIter; +import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; + +/** + * Iterator over distance-based query results. + * + * There is no getter for the DBID, as this implements + * {@link de.lmu.ifi.dbs.elki.database.ids.DBIDRef}. + * + * @author Erich Schubert + * + * @apiviz.landmark + * + * @apiviz.has DistanceDBIDPair - - iterator for + */ +public interface DistanceDBIDListIter<D extends Distance<D>> extends DBIDArrayIter { + /** + * Get the distance + * + * @return distance + */ + public D getDistance(); + + /** + * Get an object pair. + * + * @return object pair + */ + public DistanceDBIDPair<D> getDistancePair(); +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/DistanceDBIDPair.java b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DistanceDBIDPair.java index 01a1f407..a9d879d9 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/DistanceDBIDPair.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DistanceDBIDPair.java @@ -1,10 +1,10 @@ -package de.lmu.ifi.dbs.elki.database.ids; +package de.lmu.ifi.dbs.elki.database.ids.distance; /* This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,6 +23,7 @@ package de.lmu.ifi.dbs.elki.database.ids; along with this program. If not, see <http://www.gnu.org/licenses/>. */ +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; /** diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceDBIDList.java b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceDBIDList.java new file mode 100644 index 00000000..85182313 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceDBIDList.java @@ -0,0 +1,39 @@ +package de.lmu.ifi.dbs.elki.database.ids.distance; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; + +/** + * An object containing Double-DBID-Pairs. + * + * @author Erich Schubert + */ +public interface DoubleDistanceDBIDList extends DistanceDBIDList<DoubleDistance> { + @Override + DoubleDistanceDBIDListIter iter(); + + @Override + DoubleDistanceDBIDPair get(int off); +} diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceDBIDListIter.java b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceDBIDListIter.java new file mode 100644 index 00000000..68b2de1e --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceDBIDListIter.java @@ -0,0 +1,60 @@ +package de.lmu.ifi.dbs.elki.database.ids.distance; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; + +/** + * Iterator for double valued distance-based query results. + * + * @author Erich Schubert + */ +public interface DoubleDistanceDBIDListIter extends DistanceDBIDListIter<DoubleDistance> { + /** + * Get the distance + * + * @return distance + */ + public double doubleDistance(); + + /** + * Get an object pair. + * + * @return object pair + */ + @Override + public DoubleDistanceDBIDPair getDistancePair(); + + /** + * Get the distance + * + * @deprecated Use {@link #doubleDistance} to avoid creating unnecessary + * objects. + * + * @return distance + */ + @Deprecated + @Override + public DoubleDistance getDistance(); +} diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/DoubleDistanceDBIDPair.java b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceDBIDPair.java index 72a9cfef..5286029b 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/DoubleDistanceDBIDPair.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceDBIDPair.java @@ -1,10 +1,10 @@ -package de.lmu.ifi.dbs.elki.database.ids; +package de.lmu.ifi.dbs.elki.database.ids.distance; /* This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,6 +23,7 @@ package de.lmu.ifi.dbs.elki.database.ids; along with this program. If not, see <http://www.gnu.org/licenses/>. */ +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; /** diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceDBIDPairList.java b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceDBIDPairList.java new file mode 100644 index 00000000..f9bfc20a --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceDBIDPairList.java @@ -0,0 +1,212 @@ +package de.lmu.ifi.dbs.elki.database.ids.distance; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import java.util.ArrayList; +import java.util.Collections; + +import de.lmu.ifi.dbs.elki.database.ids.DBIDFactory; +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.distance.distanceresultlist.DistanceDBIDResultUtil; +import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; + +/** + * Default class to keep a list of distance-object pairs. + * + * @author Erich Schubert + * + * @apiviz.composedOf DoubleDistanceDBIDPair + * @apiviz.has DoubleDistanceDBIDListIter + */ +public class DoubleDistanceDBIDPairList implements ModifiableDoubleDistanceDBIDList { + /** + * Actual storage. + */ + final ArrayList<DoubleDistanceDBIDPair> storage; + + /** + * Constructor. + */ + public DoubleDistanceDBIDPairList() { + super(); + storage = new ArrayList<>(); + } + + /** + * Constructor. + * + * @param initialCapacity Capacity + */ + public DoubleDistanceDBIDPairList(int initialCapacity) { + super(); + storage = new ArrayList<>(initialCapacity); + } + + /** + * Add an element. + * + * @deprecated Pass a double value instead. + * + * @param dist Distance + * @param id ID + */ + @Override + @Deprecated + public void add(DoubleDistance dist, DBIDRef id) { + storage.add(DBIDFactory.FACTORY.newDistancePair(dist.doubleValue(), id)); + } + + /** + * Add an element. + * + * @param dist Distance + * @param id ID + */ + @Override + public void add(double dist, DBIDRef id) { + storage.add(DBIDFactory.FACTORY.newDistancePair(dist, id)); + } + + /** + * Add an element. + * + * @param pair Pair to add + */ + @Override + public void add(DoubleDistanceDBIDPair pair) { + storage.add(pair); + } + + @Override + public void sort() { + Collections.sort(storage, DistanceDBIDResultUtil.distanceComparator()); + } + + @Override + public int size() { + return storage.size(); + } + + @Override + public DoubleDistanceDBIDPair get(int off) { + return storage.get(off); + } + + @Override + public DoubleDistanceDBIDListIter iter() { + return new Itr(); + } + + @Override + public boolean contains(DBIDRef o) { + for(DBIDIter iter = iter(); iter.valid(); iter.advance()) { + if(DBIDUtil.equal(iter, o)) { + return true; + } + } + return false; + } + + @Override + public boolean isEmpty() { + return size() == 0; + } + + @Override + public String toString() { + return DistanceDBIDResultUtil.toString(this); + } + + /** + * Iterator class. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + protected class Itr implements DoubleDistanceDBIDListIter { + /** + * Iterator position. + */ + int pos = 0; + + @Override + public int internalGetIndex() { + return get(pos).internalGetIndex(); + } + + @Override + public boolean valid() { + return pos < size(); + } + + @Override + public void advance() { + pos++; + } + + @Override + @Deprecated + public DoubleDistance getDistance() { + return get(pos).getDistance(); + } + + @Override + public double doubleDistance() { + return get(pos).doubleDistance(); + } + + @Override + public DoubleDistanceDBIDPair getDistancePair() { + return get(pos); + } + + @Override + public String toString() { + return valid() ? getDistancePair().toString() : "null"; + } + + @Override + public int getOffset() { + return pos; + } + + @Override + public void advance(int count) { + pos += count; + } + + @Override + public void retract() { + --pos; + } + + @Override + public void seek(int off) { + pos = off; + } + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceKNNHeap.java b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceKNNHeap.java new file mode 100644 index 00000000..1e75f120 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceKNNHeap.java @@ -0,0 +1,100 @@ +package de.lmu.ifi.dbs.elki.database.ids.distance; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; +import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; + +/** + * Interface for kNN heaps storing double distances and DBIDs. + * + * @author Erich Schubert + */ +public interface DoubleDistanceKNNHeap extends KNNHeap<DoubleDistance> { + /** + * Add a distance-id pair to the heap unless the distance is too large. + * + * Compared to the super.add() method, this often saves the pair construction. + * + * @param distance Distance value + * @param id ID number + */ + void add(double distance, DBIDRef id); + + /** + * Add a distance-id pair to the heap unless the distance is too large. + * + * Compared to the super.add() method, this often saves the pair construction. + * + * @param distance Distance value + * @param id ID number + */ + @Deprecated + void add(Double distance, DBIDRef id); + + /** + * Add a distance-id pair to the heap unless the distance is too large. + * + * Use for existing pairs. + * + * @param e Existing distance pair + */ + void add(DoubleDistanceDBIDPair e); + + /** + * {@inheritDoc} + * + * @deprecated if you know your distances are double-valued, you should be + * using the primitive type. + */ + @Override + @Deprecated + void add(DoubleDistance dist, DBIDRef id); + + /** + * Get the distance to the k nearest neighbor, or maxdist otherwise. + * + * @return Maximum distance + */ + double doubleKNNDistance(); + + /** + * {@inheritDoc} + * + * @deprecated if you know your distances are double-valued, you should be + * using the primitive type. + */ + @Override + @Deprecated + DoubleDistance getKNNDistance(); + + @Override + DoubleDistanceDBIDPair poll(); + + @Override + DoubleDistanceDBIDPair peek(); + + @Override + DoubleDistanceKNNList toKNNList(); +} diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceKNNList.java b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceKNNList.java new file mode 100644 index 00000000..c54110ab --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/ids/distance/DoubleDistanceKNNList.java @@ -0,0 +1,55 @@ +package de.lmu.ifi.dbs.elki.database.ids.distance; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; + +/** + * Double-valued KNN result. + * + * @author Erich Schubert + */ +public interface DoubleDistanceKNNList extends KNNList<DoubleDistance> { + /** + * {@inheritDoc} + * + * @deprecated use doubleKNNDistance()! + */ + @Override + @Deprecated + DoubleDistance getKNNDistance(); + + /** + * Get the kNN distance as double value. + * + * @return Distance + */ + double doubleKNNDistance(); + + @Override + DoubleDistanceDBIDListIter iter(); + + @Override + DoubleDistanceDBIDPair get(int off); +} diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/distance/KNNHeap.java b/src/de/lmu/ifi/dbs/elki/database/ids/distance/KNNHeap.java new file mode 100644 index 00000000..c02071e7 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/ids/distance/KNNHeap.java @@ -0,0 +1,111 @@ +package de.lmu.ifi.dbs.elki.database.ids.distance; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; +import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; + +/** + * Interface for kNN heaps. + * + * To instantiate, use: {@link de.lmu.ifi.dbs.elki.database.ids.DBIDUtil#newHeap}! + * + * @author Erich Schubert + * + * @apiviz.landmark + * + * @apiviz.uses KNNList - - «serializes to» + * @apiviz.composedOf DistanceDBIDPair + * + * @param <D> Distance function + */ +public interface KNNHeap<D extends Distance<D>> { + /** + * Serialize to a {@link KNNList}. This empties the heap! + * + * @return KNNList with the heaps contents. + */ + KNNList<D> toKNNList(); + + /** + * Get the K parameter ("maxsize" internally). + * + * @return K + */ + int getK(); + + /** + * Get the distance to the k nearest neighbor, or maxdist otherwise. + * + * @return Maximum distance + */ + D getKNNDistance(); + + /** + * Add a distance-id pair to the heap unless the distance is too large. + * + * Compared to the super.add() method, this often saves the pair construction. + * + * @param distance Distance value + * @param id ID number + */ + void add(D distance, DBIDRef id); + + /** + * Current size of heap. + * + * @return Heap size + */ + int size(); + + /** + * Test if the heap is empty. + * + * @return true when empty. + */ + boolean isEmpty(); + + /** + * Clear the heap. + */ + void clear(); + + /** + * Poll the <em>largest</em> element from the heap. + * + * This is in descending order because of the heap structure. For a convenient + * way to serialize the heap into a list that you can iterate in ascending + * order, see {@link #toKNNList()}. + * + * @return largest element + */ + DistanceDBIDPair<D> poll(); + + /** + * Peek at the <em>largest</em> element in the heap. + * + * @return The current largest element. + */ + DistanceDBIDPair<D> peek(); +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/distance/KNNList.java b/src/de/lmu/ifi/dbs/elki/database/ids/distance/KNNList.java new file mode 100644 index 00000000..61b75ba8 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/ids/distance/KNNList.java @@ -0,0 +1,89 @@ +package de.lmu.ifi.dbs.elki.database.ids.distance; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; + +/** + * Interface for kNN results. + * + * To iterate over the results, use the following code: + * + * <pre> + * {@code + * for (DistanceDBIDResultIter<D> iter = result.iter(); iter.valid(); iter.advance()) { + * // You can get the distance via: iter.getDistance(); + * // Or use iter just like any other DBIDRef + * } + * } + * </pre> + * + * If you are only interested in the IDs of the objects, the following is also + * sufficient: + * + * <pre> + * {@code + * for (DBIDIter<D> iter = result.iter(); iter.valid(); iter.advance()) { + * // Use iter just like any other DBIDRef + * } + * } + * </pre> + * + * @author Erich Schubert + * + * @apiviz.landmark + * + * @apiviz.composedOf DistanceDBIDPair + * + * @param <D> Distance type + */ +public interface KNNList<D extends Distance<D>> extends DistanceDBIDList<D> { + /** + * Size + */ + @Override + public int size(); + + /** + * Get the K parameter (note: this may be less than the size of the list!) + * + * @return K + */ + public int getK(); + + /** + * Direct object access. + * + * @param index + */ + @Override + public DistanceDBIDPair<D> get(int index); + + /** + * Get the distance to the k nearest neighbor, or maxdist otherwise. + * + * @return Maximum distance + */ + public D getKNNDistance(); +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/distance/ModifiableDistanceDBIDList.java b/src/de/lmu/ifi/dbs/elki/database/ids/distance/ModifiableDistanceDBIDList.java new file mode 100644 index 00000000..afb15f93 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/ids/distance/ModifiableDistanceDBIDList.java @@ -0,0 +1,48 @@ +package de.lmu.ifi.dbs.elki.database.ids.distance; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; +import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; +/** + * Modifiable API for Distance-DBID results + * + * @author Erich Schubert + * + * @param <D> Distance type + */ +public interface ModifiableDistanceDBIDList<D extends Distance<D>> extends DistanceDBIDList<D> { + /** + * Add an object to this result. + * + * @param distance Distance to add + * @param id DBID to add + */ + public void add(D distance, DBIDRef id); + + /** + * Sort the result in ascending order + */ + public void sort(); +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/distance/ModifiableDoubleDistanceDBIDList.java b/src/de/lmu/ifi/dbs/elki/database/ids/distance/ModifiableDoubleDistanceDBIDList.java new file mode 100644 index 00000000..12cdaf69 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/ids/distance/ModifiableDoubleDistanceDBIDList.java @@ -0,0 +1,63 @@ +package de.lmu.ifi.dbs.elki.database.ids.distance; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; +import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDList; +import de.lmu.ifi.dbs.elki.database.ids.distance.ModifiableDistanceDBIDList; +import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; + +/** + * An object containing Double-DBID-Pairs. + * + * @author Erich Schubert + */ +public interface ModifiableDoubleDistanceDBIDList extends DoubleDistanceDBIDList, ModifiableDistanceDBIDList<DoubleDistance> { + /** + * Add an element. + * + * @deprecated Pass a double value instead. + * + * @param dist Distance + * @param id ID + */ + @Override + @Deprecated + void add(DoubleDistance dist, DBIDRef id); + + /** + * Add an element. + * + * @param dist Distance + * @param id ID + */ + void add(double dist, DBIDRef id); + + /** + * Add an element. + * + * @param pair Pair to add + */ + void add(DoubleDistanceDBIDPair pair); +} diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/distance/package-info.java b/src/de/lmu/ifi/dbs/elki/database/ids/distance/package-info.java new file mode 100644 index 00000000..7fefbedd --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/ids/distance/package-info.java @@ -0,0 +1,26 @@ +/** + * Distance-DBID pairs, lists and heaps. + */ +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package de.lmu.ifi.dbs.elki.database.ids.distance; diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/generic/AbstractKNNHeap.java b/src/de/lmu/ifi/dbs/elki/database/ids/generic/AbstractKNNHeap.java new file mode 100644 index 00000000..2c2e60b0 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/ids/generic/AbstractKNNHeap.java @@ -0,0 +1,93 @@ +package de.lmu.ifi.dbs.elki.database.ids.generic; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDPair; +import de.lmu.ifi.dbs.elki.database.ids.distance.KNNHeap; +import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultUtil; +import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; +import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.TiedTopBoundedHeap; + +/** + * Heap used for KNN management. + * + * @author Erich Schubert + * + * @param <P> pair type + * @param <D> distance type + */ +abstract class AbstractKNNHeap<P extends DistanceDBIDPair<D>, D extends Distance<D>> implements KNNHeap<D> { + /** + * The actual heap. + */ + protected final TiedTopBoundedHeap<P> heap; + + /** + * Constructor. + * + * @param k Maximum heap size (unless tied) + */ + public AbstractKNNHeap(int k) { + super(); + heap = new TiedTopBoundedHeap<>(k, DistanceDBIDResultUtil.BY_REVERSE_DISTANCE); + } + + /** + * Add a pair to the heap. + * + * @param pair Pair to add. + */ + public abstract void add(P pair); + + @Override + public final int getK() { + return heap.getMaxSize(); + } + + @Override + public int size() { + return heap.size(); + } + + @Override + public P peek() { + return heap.peek(); + } + + @Override + public boolean isEmpty() { + return heap.isEmpty(); + } + + @Override + public void clear() { + heap.clear(); + } + + @Override + public P poll() { + return heap.poll(); + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/generic/DBIDIterAdapter.java b/src/de/lmu/ifi/dbs/elki/database/ids/generic/DBIDIterAdapter.java index 124d1b28..85fdcffd 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/generic/DBIDIterAdapter.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/generic/DBIDIterAdapter.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.generic; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/generic/DistanceDBIDPairKNNHeap.java b/src/de/lmu/ifi/dbs/elki/database/ids/generic/DistanceDBIDPairKNNHeap.java new file mode 100644 index 00000000..88459077 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/ids/generic/DistanceDBIDPairKNNHeap.java @@ -0,0 +1,106 @@ +package de.lmu.ifi.dbs.elki.database.ids.generic; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import de.lmu.ifi.dbs.elki.database.ids.DBIDFactory; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; +import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDPair; +import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; + +/** + * Heap for collecting kNN candidates with arbitrary distance types. + * + * For double distances, see {@link DoubleDistanceDBIDPairKNNHeap} + * + * <b>To instantiate, use {@link de.lmu.ifi.dbs.elki.database.ids.DBIDUtil#newHeap} instead!</b> + * + * @author Erich Schubert + * + * @param <D> Distance type + */ +public class DistanceDBIDPairKNNHeap<D extends Distance<D>> extends AbstractKNNHeap<DistanceDBIDPair<D>, D> { + /** + * Cached distance to k nearest neighbor (to avoid going through {@link #peek} + * each time). + */ + protected D knndistance = null; + + /** + * Constructor. + * + * <b>To instantiate, use {@link de.lmu.ifi.dbs.elki.database.ids.DBIDUtil#newHeap} instead!</b> + * + * @param k Heap size + */ + public DistanceDBIDPairKNNHeap(int k) { + super(k); + } + + /** + * Serialize to a {@link DistanceDBIDPairKNNList}. This empties the heap! + * + * @return KNNList with the heaps contents. + */ + @Override + public DistanceDBIDPairKNNList<D> toKNNList() { + return new DistanceDBIDPairKNNList<>(this); + } + + @Override + public void add(D distance, DBIDRef id) { + if (size() < getK()) { + heap.add(DBIDFactory.FACTORY.newDistancePair(distance, id)); + heapModified(); + return; + } + // size >= maxsize. Insert only when necessary. + if (knndistance.compareTo(distance) >= 0) { + // Replace worst element. + heap.add(DBIDFactory.FACTORY.newDistancePair(distance, id)); + heapModified(); + } + } + + @Override + public void add(DistanceDBIDPair<D> pair) { + if (size() < getK() || knndistance.compareTo(pair.getDistance()) >= 0) { + heap.add(pair); + heapModified(); + } + } + + // @Override + protected void heapModified() { + // super.heapModified(); + // Update threshold. + if (size() >= getK()) { + knndistance = heap.peek().getDistance(); + } + } + + @Override + public D getKNNDistance() { + return knndistance; + } +} diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/generic/DistanceDBIDPairKNNList.java b/src/de/lmu/ifi/dbs/elki/database/ids/generic/DistanceDBIDPairKNNList.java new file mode 100644 index 00000000..bc5392d6 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/ids/generic/DistanceDBIDPairKNNList.java @@ -0,0 +1,211 @@ +package de.lmu.ifi.dbs.elki.database.ids.generic; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +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.distance.DistanceDBIDPair; +import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter; +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.distance.distancevalue.Distance; +import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.Heap; + +/** + * Finalized KNN List. + * + * @author Erich Schubert + * + * @param <D> Distance type + */ +public class DistanceDBIDPairKNNList<D extends Distance<D>> implements KNNList<D> { + /** + * The value of k this was materialized for. + */ + private final int k; + + /** + * The actual data array. + */ + private final Object[] data; + + /** + * Constructor, to be called from KNNHeap only. Use {@link KNNHeap#toKNNList} + * instead! + * + * @param heap Calling heap + */ + protected DistanceDBIDPairKNNList(KNNHeap<D> heap) { + super(); + this.data = new Object[heap.size()]; + this.k = heap.getK(); + // Get sorted data from heap; but in reverse. + int i = heap.size(); + while (heap.size() > 0) { + i--; + assert (i >= 0); + data[i] = heap.poll(); + } + assert (data.length == 0 || data[0] != null); + assert (heap.size() == 0); + } + + /** + * Constructor. With a KNNHeap, use {@link KNNHeap#toKNNList} instead! + * + * @param heap Calling heap + * @param k K value + */ + public DistanceDBIDPairKNNList(Heap<? extends DistanceDBIDPair<D>> heap, int k) { + super(); + this.data = new Object[heap.size()]; + this.k = k; + assert (heap.size() >= this.k) : "Heap doesn't contain enough objects!"; + // Get sorted data from heap; but in reverse. + int i = heap.size(); + while (!heap.isEmpty()) { + i--; + assert (i >= 0); + data[i] = heap.poll(); + } + assert (data.length == 0 || data[0] != null); + assert (heap.size() == 0); + } + + @Override + public int getK() { + return k; + } + + @Override + public D getKNNDistance() { + return get(getK() - 1).getDistance(); + } + + @Override + public String toString() { + StringBuilder buf = new StringBuilder(); + buf.append("kNNList["); + for (DistanceDBIDListIter<D> iter = this.iter(); iter.valid();) { + buf.append(iter.getDistance()).append(':').append(DBIDUtil.toString(iter)); + iter.advance(); + if (iter.valid()) { + buf.append(','); + } + } + buf.append(']'); + return buf.toString(); + } + + @SuppressWarnings("unchecked") + @Override + public DistanceDBIDPair<D> get(int index) { + return (DistanceDBIDPair<D>) data[index]; + } + + @Override + public DistanceDBIDListIter<D> iter() { + return new Itr(); + } + + @Override + public int size() { + return data.length; + } + + @Override + public boolean contains(DBIDRef o) { + for (DBIDIter iter = iter(); iter.valid(); iter.advance()) { + if (DBIDUtil.equal(iter, o)) { + return true; + } + } + return false; + } + + @Override + public boolean isEmpty() { + return size() == 0; + } + + /** + * Iterator. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + private class Itr implements DistanceDBIDListIter<D> { + /** + * Cursor position. + */ + private int pos = 0; + + @Override + public int internalGetIndex() { + return get(pos).internalGetIndex(); + } + + @Override + public boolean valid() { + return pos < data.length; + } + + @Override + public void advance() { + pos++; + } + + @Override + public D getDistance() { + return get(pos).getDistance(); + } + + @Override + public DistanceDBIDPair<D> getDistancePair() { + return get(pos); + } + + @Override + public int getOffset() { + return pos; + } + + @Override + public void advance(int count) { + pos += count; + } + + @Override + public void retract() { + --pos; + } + + @Override + public void seek(int off) { + pos += off; + } + } +} diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/generic/DoubleDistanceDBIDPairKNNHeap.java b/src/de/lmu/ifi/dbs/elki/database/ids/generic/DoubleDistanceDBIDPairKNNHeap.java new file mode 100644 index 00000000..829bb00c --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/ids/generic/DoubleDistanceDBIDPairKNNHeap.java @@ -0,0 +1,196 @@ +package de.lmu.ifi.dbs.elki.database.ids.generic; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import java.util.Comparator; + +import de.lmu.ifi.dbs.elki.database.ids.DBIDFactory; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; +import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPair; +import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNHeap; +import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; + +/** + * Heap for collecting double-valued KNN instances. + * + * See also: {@link de.lmu.ifi.dbs.elki.database.ids.DBIDUtil#newHeap}! + * + * Experiments have shown that it <em>can</em> be much more performant to track the + * knndistance <em>outside</em> of the heap, and do comparisons on the stack: + * <blockquote> + * + * <pre> + * {@code + * double knndist = Double.POSITIVE_INFINITY; + * DoubleDistanceDBIDPairKNNHeap heap = new DoubleDistanceDBIDPairKNNHeap(k); + * for (DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) { + * double dist = computeDistance(iditer, ...); + * if (dist < knndist) { + * heap.add(dist, iditer); + * if (heap.size() >= k) { + * max = heap.doubleKNNDistance(); + * } + * } + * } + * } + * </pre> + * + * </blockquote> + * + * The reason probably is that {@code knndist} resides on the stack and can be + * better optimized by the hotspot compiler. + * + * @author Erich Schubert + */ +public class DoubleDistanceDBIDPairKNNHeap extends AbstractKNNHeap<DoubleDistanceDBIDPair, DoubleDistance> implements DoubleDistanceKNNHeap { + /** + * Comparator class. + */ + public static final Comparator<DoubleDistanceDBIDPair> COMPARATOR = new Comp(); + + /** + * Cached distance to k nearest neighbor (to avoid going through {@link #peek} + * too often). + */ + protected double knndistance = Double.POSITIVE_INFINITY; + + /** + * Constructor. + * + * See also: {@link de.lmu.ifi.dbs.elki.database.ids.DBIDUtil#newHeap}! + * + * @param k Heap size + */ + public DoubleDistanceDBIDPairKNNHeap(int k) { + super(k); + } + + /** + * Serialize to a {@link DoubleDistanceDBIDPairKNNList}. This empties the heap! + * + * @return KNNList with the heaps contents. + */ + @Override + public DoubleDistanceDBIDPairKNNList toKNNList() { + return new DoubleDistanceDBIDPairKNNList(this); + } + + /** + * Add a distance-id pair to the heap unless the distance is too large. + * + * Compared to the super.add() method, this often saves the pair construction. + * + * @param distance Distance value + * @param id ID number + */ + @Override + public final void add(final double distance, final DBIDRef id) { + if (size() < getK() || knndistance >= distance) { + heap.add(DBIDFactory.FACTORY.newDistancePair(distance, id)); + heapModified(); + } + } + + /** + * Add a distance-id pair to the heap unless the distance is too large. + * + * Compared to the super.add() method, this often saves the pair construction. + * + * @param distance Distance value + * @param id ID number + */ + @Override + @Deprecated + public final void add(final Double distance, final DBIDRef id) { + if (size() < getK() || knndistance >= distance) { + heap.add(DBIDFactory.FACTORY.newDistancePair(distance, id)); + heapModified(); + } + } + + // @Override + protected void heapModified() { + // super.heapModified(); + if (size() >= getK()) { + knndistance = heap.peek().doubleDistance(); + } + } + + @Override + public void add(final DoubleDistanceDBIDPair e) { + if (size() < getK() || knndistance >= e.doubleDistance()) { + heap.add(e); + heapModified(); + } + } + + /** + * {@inheritDoc} + * + * @deprecated if you know your distances are double-valued, you should be + * using the primitive type. + * + */ + @Override + @Deprecated + public void add(DoubleDistance dist, DBIDRef id) { + add(dist.doubleValue(), id); + } + + /** + * Get the distance to the k nearest neighbor, or maxdist otherwise. + * + * @return Maximum distance + */ + @Override + public double doubleKNNDistance() { + return knndistance; + } + + /** + * {@inheritDoc} + * + * @deprecated if you know your distances are double-valued, you should be + * using the primitive type. + */ + @Override + @Deprecated + public DoubleDistance getKNNDistance() { + return new DoubleDistance(knndistance); + } + + /** + * Comparator to use. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + protected static class Comp implements Comparator<DoubleDistanceDBIDPair> { + @Override + public int compare(DoubleDistanceDBIDPair o1, DoubleDistanceDBIDPair o2) { + return -Double.compare(o1.doubleDistance(), o2.doubleDistance()); + } + } +} diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/generic/DoubleDistanceDBIDPairKNNList.java b/src/de/lmu/ifi/dbs/elki/database/ids/generic/DoubleDistanceDBIDPairKNNList.java new file mode 100644 index 00000000..c72529ad --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/ids/generic/DoubleDistanceDBIDPairKNNList.java @@ -0,0 +1,257 @@ +package de.lmu.ifi.dbs.elki.database.ids.generic; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import java.util.Collection; +import java.util.Iterator; + +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.distance.DoubleDistanceDBIDPair; +import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDListIter; +import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNList; +import de.lmu.ifi.dbs.elki.database.ids.distance.KNNHeap; +import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; +import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.Heap; + +/** + * Finalized KNN List. + * + * @author Erich Schubert + * + * @apiviz.composedOf DoubleDistanceDBIDPair + * @apiviz.has DoubleDistanceDBIDListIter + */ +public class DoubleDistanceDBIDPairKNNList implements DoubleDistanceKNNList { + /** + * The value of k this was materialized for. + */ + private final int k; + + /** + * The actual data array. + */ + private final DoubleDistanceDBIDPair[] data; + + /** + * Constructor. This will <em>clone</em> the given collection! + * + * @param col Existing collection + * @param k K parameter + */ + public DoubleDistanceDBIDPairKNNList(Collection<DoubleDistanceDBIDPair> col, int k) { + super(); + this.data = new DoubleDistanceDBIDPair[col.size()]; + this.k = k; + assert (col.size() >= this.k) : "Collection doesn't contain enough objects!"; + // Get sorted data from heap; but in reverse. + Iterator<DoubleDistanceDBIDPair> it = col.iterator(); + for (int i = 0; it.hasNext(); i++) { + data[i] = it.next(); + } + assert (data.length == 0 || data[0] != null); + } + + /** + * Constructor, to be called from KNNHeap only. Use {@link KNNHeap#toKNNList} + * instead! + * + * @param heap Calling heap + */ + protected DoubleDistanceDBIDPairKNNList(DoubleDistanceDBIDPairKNNHeap heap) { + super(); + this.data = new DoubleDistanceDBIDPair[heap.size()]; + this.k = heap.getK(); + // Get sorted data from heap; but in reverse. + int i = heap.size(); + while (heap.size() > 0) { + i--; + assert (i >= 0); + data[i] = heap.poll(); + } + assert (data.length == 0 || data[0] != null); + assert (heap.size() == 0); + } + + /** + * Constructor, to be called from KNNHeap only. Use {@link KNNHeap#toKNNList} + * instead! + * + * @param heap Calling heap + * @param k Target number of neighbors (before ties) + */ + public DoubleDistanceDBIDPairKNNList(Heap<DoubleDistanceDBIDPair> heap, int k) { + super(); + this.data = new DoubleDistanceDBIDPair[heap.size()]; + this.k = k; + assert (heap.size() >= this.k) : "Heap doesn't contain enough objects!"; + // Get sorted data from heap; but in reverse. + int i = heap.size(); + while (heap.size() > 0) { + i--; + assert (i >= 0); + data[i] = heap.poll(); + } + assert (data.length == 0 || data[0] != null); + assert (heap.size() == 0); + } + + @Override + public int getK() { + return k; + } + + @Override + @Deprecated + public DoubleDistance getKNNDistance() { + if (size() < k) { + return DoubleDistance.INFINITE_DISTANCE; + } + return get(k - 1).getDistance(); + } + + @Override + public double doubleKNNDistance() { + if (size() < k) { + return Double.POSITIVE_INFINITY; + } + return get(k - 1).doubleDistance(); + } + + @Override + public String toString() { + StringBuilder buf = new StringBuilder(); + buf.append("kNNList["); + for (DoubleDistanceDBIDListIter iter = this.iter(); iter.valid();) { + buf.append(iter.doubleDistance()).append(':').append(DBIDUtil.toString(iter)); + iter.advance(); + if (iter.valid()) { + buf.append(','); + } + } + buf.append(']'); + return buf.toString(); + } + + @Override + public DoubleDistanceDBIDPair get(int index) { + return data[index]; + } + + @Override + public DoubleDistanceDBIDListIter iter() { + return new Itr(); + } + + @Override + public int size() { + return data.length; + } + + @Override + public boolean contains(DBIDRef o) { + for (DBIDIter iter = iter(); iter.valid(); iter.advance()) { + if (DBIDUtil.equal(iter, o)) { + return true; + } + } + return false; + } + + @Override + public boolean isEmpty() { + return size() == 0; + } + + /** + * Iterator. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + private class Itr implements DoubleDistanceDBIDListIter { + /** + * Cursor position. + */ + private int pos = 0; + + @Override + public int internalGetIndex() { + return get(pos).internalGetIndex(); + } + + @Override + public boolean valid() { + return pos < data.length; + } + + @Override + public void advance() { + pos++; + } + + /** + * {@inheritDoc} + * + * @deprecated use {@link #doubleDistance}! + */ + @Override + @Deprecated + public DoubleDistance getDistance() { + return get(pos).getDistance(); + } + + @Override + public double doubleDistance() { + return get(pos).doubleDistance(); + } + + @Override + public DoubleDistanceDBIDPair getDistancePair() { + return get(pos); + } + + @Override + public int getOffset() { + return pos; + } + + @Override + public void advance(int count) { + pos += count; + } + + @Override + public void retract() { + --pos; + } + + @Override + public void seek(int off) { + pos = off; + } + } +} diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/generic/DoubleDistanceKNNSubList.java b/src/de/lmu/ifi/dbs/elki/database/ids/generic/DoubleDistanceKNNSubList.java new file mode 100644 index 00000000..c2854a54 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/ids/generic/DoubleDistanceKNNSubList.java @@ -0,0 +1,190 @@ +package de.lmu.ifi.dbs.elki.database.ids.generic; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +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.distance.DoubleDistanceDBIDPair; +import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDListIter; +import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNList; +import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; + +/** + * Sublist of an existing result to contain only the first k elements. + * + * TOOD: can be optimized slightly better. + * + * @author Erich Schubert + */ +public class DoubleDistanceKNNSubList implements DoubleDistanceKNNList { + /** + * Parameter k. + */ + private final int k; + + /** + * Actual size, including ties. + */ + private final int size; + + /** + * Wrapped inner result. + */ + private final DoubleDistanceKNNList inner; + + /** + * Constructor. + * + * @param inner Inner instance + * @param k k value + */ + public DoubleDistanceKNNSubList(DoubleDistanceKNNList inner, int k) { + this.inner = inner; + this.k = k; + // Compute list size + { + DoubleDistanceDBIDPair dist = inner.get(k); + int i = k; + while (i + 1 < inner.size()) { + if (dist.compareByDistance(inner.get(i + 1)) < 0) { + break; + } + i++; + } + size = i; + } + } + + @Override + public int getK() { + return k; + } + + @Override + public DoubleDistanceDBIDPair get(int index) { + assert (index < size) : "Access beyond design size of list."; + return inner.get(index); + } + + @Override + @Deprecated + public DoubleDistance getKNNDistance() { + return inner.get(k).getDistance(); + } + + @Override + public double doubleKNNDistance() { + return inner.get(k).doubleDistance(); + } + + @Override + public DoubleDistanceDBIDListIter iter() { + return new Itr(); + } + + @Override + public boolean contains(DBIDRef o) { + for (DBIDIter iter = iter(); iter.valid(); iter.advance()) { + if (DBIDUtil.equal(iter, o)) { + return true; + } + } + return false; + } + + @Override + public boolean isEmpty() { + return size == 0; + } + + @Override + public int size() { + return size; + } + + /** + * Iterator for the sublist. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + private class Itr implements DoubleDistanceDBIDListIter { + /** + * Current position. + */ + private int pos = 0; + + @Override + public boolean valid() { + return pos < size; + } + + @Override + public void advance() { + pos++; + } + + @Override + @Deprecated + public DoubleDistance getDistance() { + return inner.get(pos).getDistance(); + } + + @Override + public double doubleDistance() { + return inner.get(pos).doubleDistance(); + } + + @Override + public DoubleDistanceDBIDPair getDistancePair() { + return inner.get(pos); + } + + @Override + public int internalGetIndex() { + return inner.get(pos).internalGetIndex(); + } + + @Override + public int getOffset() { + return pos; + } + + @Override + public void advance(int count) { + pos += count; + } + + @Override + public void retract() { + --pos; + } + + @Override + public void seek(int off) { + pos = off; + } + } +} diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/generic/GenericDistanceDBIDList.java b/src/de/lmu/ifi/dbs/elki/database/ids/generic/GenericDistanceDBIDList.java new file mode 100644 index 00000000..9b6c188b --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/ids/generic/GenericDistanceDBIDList.java @@ -0,0 +1,186 @@ +package de.lmu.ifi.dbs.elki.database.ids.generic; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import java.util.ArrayList; + +import de.lmu.ifi.dbs.elki.database.ids.DBIDFactory; +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.distance.DistanceDBIDListIter; +import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDPair; +import de.lmu.ifi.dbs.elki.database.ids.distance.ModifiableDistanceDBIDList; +import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultUtil; +import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; + +/** + * Default class to keep a list of distance-object pairs. + * + * @author Erich Schubert + * + * @param <D> Distance type + */ +public class GenericDistanceDBIDList<D extends Distance<D>> implements ModifiableDistanceDBIDList<D> { + /** + * Actual storage. + */ + final ArrayList<DistanceDBIDPair<D>> storage; + + /** + * Constructor. + */ + public GenericDistanceDBIDList() { + super(); + storage = new ArrayList<>(); + } + + /** + * Constructor. + * + * @param initialCapacity Capacity + */ + public GenericDistanceDBIDList(int initialCapacity) { + super(); + storage = new ArrayList<>(initialCapacity); + } + + @Override + public void add(D dist, DBIDRef id) { + storage.add(DBIDFactory.FACTORY.newDistancePair(dist, id)); + } + + /** + * Add a prepared pair. + * + * @param pair Pair to add + */ + public void add(DistanceDBIDPair<D> pair) { + storage.add(pair); + } + + @Override + public void sort() { + DistanceDBIDResultUtil.sortByDistance(storage); + } + + @Override + public int size() { + return storage.size(); + } + + @Override + public DistanceDBIDPair<D> get(int off) { + return storage.get(off); + } + + @Override + public DistanceDBIDListIter<D> iter() { + return new Itr(); + } + + @Override + public boolean contains(DBIDRef o) { + for(DBIDIter iter = iter(); iter.valid(); iter.advance()) { + if(DBIDUtil.equal(iter, o)) { + return true; + } + } + return false; + } + + @Override + public boolean isEmpty() { + return size() == 0; + } + + @Override + public String toString() { + return DistanceDBIDResultUtil.toString(this); + } + + /** + * Iterator class. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + protected class Itr implements DistanceDBIDListIter<D> { + /** + * Iterator position. + */ + int pos = 0; + + @Override + public int internalGetIndex() { + return get(pos).internalGetIndex(); + } + + @Override + public boolean valid() { + return pos < size(); + } + + @Override + public void advance() { + pos++; + } + + @Override + public D getDistance() { + return get(pos).getDistance(); + } + + @Override + public DistanceDBIDPair<D> getDistancePair() { + return get(pos); + } + + @Override + public String toString() { + return valid() ? getDistancePair().toString() : "null"; + } + + @Override + public int getOffset() { + return pos; + } + + @Override + public void advance(int count) { + pos += count; + } + + @Override + public void retract() { + --pos; + } + + @Override + public void seek(int off) { + pos = off; + } + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/generic/KNNSubList.java b/src/de/lmu/ifi/dbs/elki/database/ids/generic/KNNSubList.java new file mode 100644 index 00000000..3d7863fd --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/ids/generic/KNNSubList.java @@ -0,0 +1,180 @@ +package de.lmu.ifi.dbs.elki.database.ids.generic; + +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.distance.DistanceDBIDListIter; +import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDPair; +import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList; +import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * Sublist of an existing result to contain only the first k elements. + * + * @author Erich Schubert + * + * @param <D> Distance + */ +public class KNNSubList<D extends Distance<D>> implements KNNList<D> { + /** + * Parameter k. + */ + private final int k; + + /** + * Actual size, including ties. + */ + private final int size; + + /** + * Wrapped inner result. + */ + private final KNNList<D> inner; + + /** + * Constructor. + * + * @param inner Inner instance + * @param k k value + */ + public KNNSubList(KNNList<D> inner, int k) { + this.inner = inner; + this.k = k; + // Compute list size + // TODO: optimize for double distances. + { + DistanceDBIDPair<D> dist = inner.get(k); + int i = k; + while (i + 1 < inner.size()) { + if (dist.compareByDistance(inner.get(i + 1)) < 0) { + break; + } + i++; + } + size = i; + } + } + + @Override + public int getK() { + return k; + } + + @Override + public DistanceDBIDPair<D> get(int index) { + assert (index < size) : "Access beyond design size of list."; + return inner.get(index); + } + + @Override + public D getKNNDistance() { + return inner.get(k).getDistance(); + } + + @Override + public DistanceDBIDListIter<D> iter() { + return new Itr(); + } + + @Override + public boolean contains(DBIDRef o) { + for (DBIDIter iter = iter(); iter.valid(); iter.advance()) { + if (DBIDUtil.equal(iter, o)) { + return true; + } + } + return false; + } + + @Override + public boolean isEmpty() { + return size == 0; + } + + @Override + public int size() { + return size; + } + + /** + * Iterator for the sublist. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + private class Itr implements DistanceDBIDListIter<D> { + /** + * Current position. + */ + private int pos = 0; + + @Override + public boolean valid() { + return pos < size; + } + + @Override + public void advance() { + pos++; + } + + @Override + public D getDistance() { + return inner.get(pos).getDistance(); + } + + @Override + public DistanceDBIDPair<D> getDistancePair() { + return inner.get(pos); + } + + @Override + public int internalGetIndex() { + return inner.get(pos).internalGetIndex(); + } + + @Override + public int getOffset() { + return pos; + } + + @Override + public void advance(int count) { + pos -= count; + } + + @Override + public void retract() { + --pos; + } + + @Override + public void seek(int off) { + pos = off; + } + } +} diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/generic/MaskedDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/generic/MaskedDBIDs.java index 668ac0d8..2b481fca 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/generic/MaskedDBIDs.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/generic/MaskedDBIDs.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.generic; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/generic/MergedDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/generic/MergedDBIDs.java index 9d2583e3..7df6975c 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/generic/MergedDBIDs.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/generic/MergedDBIDs.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.generic; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/generic/UnmodifiableArrayDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/generic/UnmodifiableArrayDBIDs.java index abcdef54..318e4e79 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/generic/UnmodifiableArrayDBIDs.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/generic/UnmodifiableArrayDBIDs.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.generic; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -90,8 +90,8 @@ public class UnmodifiableArrayDBIDs implements ArrayStaticDBIDs { } @Override - public void assign(int index, DBIDVar var) { - inner.assign(index, var); + public void assignVar(int index, DBIDVar var) { + inner.assignVar(index, var); } @Override diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/generic/UnmodifiableDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/generic/UnmodifiableDBIDs.java index fea35692..458dab3f 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/generic/UnmodifiableDBIDs.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/generic/UnmodifiableDBIDs.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.generic; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/generic/package-info.java b/src/de/lmu/ifi/dbs/elki/database/ids/generic/package-info.java index 890b9c0a..9920cac7 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/generic/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/generic/package-info.java @@ -7,7 +7,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2012 +Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/AbstractIntegerDBIDFactory.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/AbstractIntegerDBIDFactory.java new file mode 100644 index 00000000..061deb08 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/AbstractIntegerDBIDFactory.java @@ -0,0 +1,201 @@ +package de.lmu.ifi.dbs.elki.database.ids.integer; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs; +import de.lmu.ifi.dbs.elki.database.ids.DBID; +import de.lmu.ifi.dbs.elki.database.ids.DBIDFactory; +import de.lmu.ifi.dbs.elki.database.ids.DBIDPair; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; +import de.lmu.ifi.dbs.elki.database.ids.DBIDVar; +import de.lmu.ifi.dbs.elki.database.ids.DBIDs; +import de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDPair; +import de.lmu.ifi.dbs.elki.database.ids.HashSetModifiableDBIDs; +import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDPair; +import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPair; +import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNHeap; +import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNList; +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.ids.generic.DistanceDBIDPairKNNHeap; +import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; +import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; +import de.lmu.ifi.dbs.elki.persistent.ByteBufferSerializer; +import de.lmu.ifi.dbs.elki.persistent.FixedSizeByteBufferSerializer; + +/** + * Abstract base class for DBID factories. + * + * @author Erich Schubert + * + * @apiviz.uses IntegerDBID oneway - - «create» + * @apiviz.uses IntegerDBIDPair oneway - - «create» + * @apiviz.uses IntegerDBIDRange oneway - - «create» + * @apiviz.uses TroveArrayModifiableDBIDs oneway - - «create» + * @apiviz.uses TroveHashSetModifiableDBIDs oneway - - «create» + */ +abstract class AbstractIntegerDBIDFactory implements DBIDFactory { + /** + * Invalid ID. + */ + DBID invalid = new IntegerDBID(Integer.MIN_VALUE); + + @Override + public DBID importInteger(int id) { + return new IntegerDBID(id); + } + + @Override + public void assignVar(DBIDVar var, int val) { + if (var instanceof IntegerDBIDVar) { + ((IntegerDBIDVar)var).internalSetIndex(val); + } else { + var.set(new IntegerDBID(val)); + } + } + + @Override + public int compare(DBIDRef a, DBIDRef b) { + final int inta = a.internalGetIndex(); + final int intb = b.internalGetIndex(); + return (inta < intb ? -1 : (inta == intb ? 0 : 1)); + } + + @Override + public boolean equal(DBIDRef a, DBIDRef b) { + return a.internalGetIndex() == b.internalGetIndex(); + } + + @Override + public String toString(DBIDRef id) { + return Integer.toString(id.internalGetIndex()); + } + + @Override + public DBIDVar newVar(DBIDRef val) { + return new IntegerDBIDVar(val); + } + + @Override + public ArrayModifiableDBIDs newArray() { + return new ArrayModifiableIntegerDBIDs(); + } + + @Override + public HashSetModifiableDBIDs newHashSet() { + return new TroveHashSetModifiableDBIDs(); + } + + @Override + public ArrayModifiableDBIDs newArray(int size) { + return new ArrayModifiableIntegerDBIDs(size); + } + + @Override + public HashSetModifiableDBIDs newHashSet(int size) { + return new TroveHashSetModifiableDBIDs(size); + } + + @Override + public ArrayModifiableDBIDs newArray(DBIDs existing) { + return new ArrayModifiableIntegerDBIDs(existing); + } + + @Override + public HashSetModifiableDBIDs newHashSet(DBIDs existing) { + return new TroveHashSetModifiableDBIDs(existing); + } + + @Override + public DBIDPair newPair(DBIDRef first, DBIDRef second) { + return new IntegerDBIDPair(first.internalGetIndex(), second.internalGetIndex()); + } + + @Override + public DoubleDBIDPair newPair(double val, DBIDRef id) { + return new IntegerDoubleDBIDPair(val, id.internalGetIndex()); + } + + @SuppressWarnings("unchecked") + @Override + public <D extends Distance<D>> DistanceDBIDPair<D> newDistancePair(D val, DBIDRef id) { + if (val instanceof DoubleDistance) { + return (DistanceDBIDPair<D>) new DoubleDistanceIntegerDBIDPair(((DoubleDistance) val).doubleValue(), id.internalGetIndex()); + } + return new DistanceIntegerDBIDPair<>(val, id.internalGetIndex()); + } + + @Override + public DoubleDistanceDBIDPair newDistancePair(double val, DBIDRef id) { + return new DoubleDistanceIntegerDBIDPair(val, id.internalGetIndex()); + } + + @SuppressWarnings("unchecked") + @Override + public <D extends Distance<D>> KNNHeap<D> newHeap(D factory, int k) { + if (factory instanceof DoubleDistance) { + return (KNNHeap<D>) new DoubleDistanceIntegerDBIDKNNListHeap(k); + } + return new DistanceDBIDPairKNNHeap<>(k); + } + + @SuppressWarnings("unchecked") + @Override + public <D extends Distance<D>> KNNHeap<D> newHeap(KNNList<D> exist) { + if (exist instanceof DoubleDistanceKNNList) { + DoubleDistanceKNNHeap heap = new DoubleDistanceIntegerDBIDKNNListHeap(exist.getK()); + // Insert backwards, as this will produce a proper heap + for (int i = exist.size() - 1; i >= 0; i--) { + heap.add((DoubleDistanceDBIDPair) exist.get(i)); + } + return (KNNHeap<D>) heap; + } else { + DistanceDBIDPairKNNHeap<D> heap = new DistanceDBIDPairKNNHeap<>(exist.getK()); + // Insert backwards, as this will produce a proper heap + for (int i = exist.size() - 1; i >= 0; i--) { + heap.add(exist.get(i)); + } + return heap; + } + } + + @Override + public ByteBufferSerializer<DBID> getDBIDSerializer() { + return IntegerDBID.DYNAMIC_SERIALIZER; + } + + @Override + public FixedSizeByteBufferSerializer<DBID> getDBIDSerializerStatic() { + return IntegerDBID.STATIC_SERIALIZER; + } + + @Override + public Class<? extends DBID> getTypeRestriction() { + return IntegerDBID.class; + } + + @Override + public DBIDRef invalid() { + return invalid; + } +} diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/ArrayModifiableIntegerDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/ArrayModifiableIntegerDBIDs.java new file mode 100644 index 00000000..dfff45b4 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/ArrayModifiableIntegerDBIDs.java @@ -0,0 +1,306 @@ +package de.lmu.ifi.dbs.elki.database.ids.integer; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import java.util.Arrays; +import java.util.Comparator; + +import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs; +import de.lmu.ifi.dbs.elki.database.ids.DBID; +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.DBIDVar; +import de.lmu.ifi.dbs.elki.database.ids.DBIDs; + +/** + * Class using a primitive int[] array as storage. + * + * @author Erich Schubert + */ +public class ArrayModifiableIntegerDBIDs implements ArrayModifiableDBIDs, IntegerArrayDBIDs { + /** + * The actual Trove array list. + */ + private int[] store; + + /** + * Occupied size. + */ + private int size = 0; + + /** + * Initial size. + */ + public static final int INITIAL_SIZE = 21; + + /** + * Constructor. + * + * @param size Initial size + */ + protected ArrayModifiableIntegerDBIDs(int size) { + super(); + this.store = new int[size]; + } + + /** + * Constructor. + */ + protected ArrayModifiableIntegerDBIDs() { + super(); + this.store = new int[INITIAL_SIZE]; + } + + /** + * Constructor. + * + * @param existing Existing ids + */ + protected ArrayModifiableIntegerDBIDs(DBIDs existing) { + this(existing.size()); + this.addDBIDs(existing); + } + + @Override + public int size() { + return size; + } + + @Override + public boolean isEmpty() { + return size == 0; + } + + @Override + public DBID get(int i) { + return new IntegerDBID(store[i]); + } + + @Override + public void assignVar(int index, DBIDVar var) { + if(var instanceof IntegerDBIDVar) { + ((IntegerDBIDVar) var).internalSetIndex(store[index]); + } + else { + // less efficient, involves object creation. + var.set(get(index)); + } + } + + /** + * Resize as desired. + * + * @param minsize Desired size + */ + private void ensureSize(int minsize) { + int asize = store.length; + // Ensure a minimum size, to not run into an infinite loop below! + if (asize < 2) { + asize = 2; + } + while(asize < minsize) { + asize = (asize >> 1) + asize; + } + if(asize > store.length) { + store = Arrays.copyOf(store, asize); + } + } + + @Override + public boolean addDBIDs(DBIDs ids) { + ensureSize(size + ids.size()); + for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { + store[size] = iter.internalGetIndex(); + ++size; + } + return true; + } + + @Override + public boolean removeDBIDs(DBIDs ids) { + boolean success = false; + for(DBIDIter id = ids.iter(); id.valid(); id.advance()) { + int rm = id.internalGetIndex(); + // TODO: when sorted, use binary search! + for(int i = 0; i < size; i++) { + if(store[i] == rm) { + --size; + store[i] = store[size]; + success = true; + break; + } + } + } + return success; + } + + @Override + public boolean add(DBIDRef e) { + if(size == store.length) { + ensureSize(size + 1); + } + store[size] = e.internalGetIndex(); + ++size; + return true; + } + + @Override + public boolean remove(DBIDRef o) { + int rm = o.internalGetIndex(); + // TODO: when sorted, use binary search! + for(int i = 0; i < size; i++) { + if(store[i] == rm) { + --size; + store[i] = store[size]; + return true; + } + } + return false; + } + + @Override + public DBID set(int index, DBIDRef element) { + int prev = store[index]; + store[index] = element.internalGetIndex(); + return new IntegerDBID(prev); + } + + @Override + public DBID remove(int index) { + DBID ret = new IntegerDBID(store[index]); + --size; + if(size > 0) { + store[index] = store[size]; + } + return ret; + } + + @Override + public void clear() { + size = 0; + } + + @Override + public int binarySearch(DBIDRef key) { + return Arrays.binarySearch(store, 0, size, key.internalGetIndex()); + } + + @Override + public boolean contains(DBIDRef o) { + // TODO: recognize sorted arrays, then use binary search? + int oid = o.internalGetIndex(); + for(int i = 0; i < size; i++) { + if(store[i] == oid) { + return true; + } + } + return false; + } + + @Override + public void sort() { + Arrays.sort(store, 0, size); + } + + @Override + public void sort(Comparator<? super DBIDRef> comparator) { + IntegerDBIDArrayQuickSort.sort(store, 0, size, comparator); + } + + @Override + public void sort(int start, int end, Comparator<? super DBIDRef> comparator) { + IntegerDBIDArrayQuickSort.sort(store, start, end, comparator); + } + + @Override + public void swap(int a, int b) { + int tmp = store[b]; + store[b] = store[a]; + store[a] = tmp; + } + + @Override + public IntegerDBIDArrayMIter iter() { + return new Itr(); + } + + /** + * Iterator class. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + private class Itr implements IntegerDBIDArrayMIter { + /** + * Iterator position. + */ + int pos = 0; + + @Override + public int internalGetIndex() { + return store[pos]; + } + + @Override + public boolean valid() { + return pos < size && pos >= 0; + } + + @Override + public void advance() { + ++pos; + } + + @Override + public int getOffset() { + return pos; + } + + @Override + public void advance(int count) { + pos += count; + } + + @Override + public void retract() { + --pos; + } + + @Override + public void seek(int off) { + pos = off; + } + + @Override + public void remove() { + ArrayModifiableIntegerDBIDs.this.remove(pos); + } + + @Override + public String toString() { + return Integer.toString(internalGetIndex()) + "@" + pos; + } + } +} diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntArrayStaticDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/ArrayStaticIntegerDBIDs.java index aa3b3cc0..4b4b5a42 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntArrayStaticDBIDs.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/ArrayStaticIntegerDBIDs.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -39,7 +39,7 @@ import de.lmu.ifi.dbs.elki.logging.LoggingUtil; * * @apiviz.has IntegerDBID */ -public class IntArrayStaticDBIDs implements IntegerArrayStaticDBIDs { +public class ArrayStaticIntegerDBIDs implements IntegerArrayStaticDBIDs { /** * The actual storage. */ @@ -50,7 +50,7 @@ public class IntArrayStaticDBIDs implements IntegerArrayStaticDBIDs { * * @param ids Array of ids. */ - public IntArrayStaticDBIDs(int... ids) { + public ArrayStaticIntegerDBIDs(int... ids) { super(); this.ids = ids; } @@ -118,7 +118,7 @@ public class IntArrayStaticDBIDs implements IntegerArrayStaticDBIDs { @Override public String toString() { - return Integer.toString(internalGetIndex()); + return Integer.toString(internalGetIndex()) + "@" + pos; } } @@ -149,7 +149,7 @@ public class IntArrayStaticDBIDs implements IntegerArrayStaticDBIDs { } @Override - public void assign(int i, DBIDVar var) { + public void assignVar(int i, DBIDVar var) { if (var instanceof IntegerDBIDVar) { ((IntegerDBIDVar)var).internalSetIndex(ids[i]); } else { diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/DistanceIntegerDBIDPair.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/DistanceIntegerDBIDPair.java index 01eec02e..a8930b87 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/DistanceIntegerDBIDPair.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/DistanceIntegerDBIDPair.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,9 +23,10 @@ package de.lmu.ifi.dbs.elki.database.ids.integer; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import de.lmu.ifi.dbs.elki.database.ids.DistanceDBIDPair; +import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDPair; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; +import de.lmu.ifi.dbs.elki.utilities.Util; /** * Class storing a double distance a DBID. @@ -88,8 +89,13 @@ class DistanceIntegerDBIDPair<D extends Distance<D>> implements DistanceDBIDPair } if (o instanceof DoubleDistanceIntegerDBIDPair && distance instanceof DoubleDistance) { DoubleDistanceIntegerDBIDPair p = (DoubleDistanceIntegerDBIDPair) o; - return (this.id == p.id) && (((DoubleDistance) this.distance).doubleValue() == p.distance); + return (this.id == p.id) && (Double.compare(((DoubleDistance) this.distance).doubleValue(), p.distance) == 0); } return false; } + + @Override + public int hashCode() { + return Util.mixHashCodes(distance.hashCode(), id); + } } diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDKNNHeap.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDKNNHeap.java new file mode 100644 index 00000000..6c88c2d8 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDKNNHeap.java @@ -0,0 +1,252 @@ +package de.lmu.ifi.dbs.elki.database.ids.integer; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import java.util.Arrays; + +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; +import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPair; +import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNHeap; +import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; +import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.DoubleIntegerMaxHeap; + +/** + * Class to efficiently manage a kNN heap. + * + * @author Erich Schubert + * + * @apiviz.has DoubleDistanceIntegerDBIDKNNList + * @apiviz.composedOf DoubleIntegerMaxHeap + */ +public class DoubleDistanceIntegerDBIDKNNHeap implements DoubleDistanceKNNHeap { + /** + * k for this heap. + */ + private final int k; + + /** + * The main heap. + */ + private final DoubleIntegerMaxHeap heap; + + /** + * List to track ties. + */ + private int[] ties; + + /** + * Number of element in ties list. + */ + private int numties = 0; + + /** + * Current maximum value. + */ + private double kdist = Double.POSITIVE_INFINITY; + + /** + * Initial size of ties array. + */ + private static final int INITIAL_TIES_SIZE = 11; + + /** + * Constructor. + * + * @param k Size of knn. + */ + public DoubleDistanceIntegerDBIDKNNHeap(int k) { + super(); + this.k = k; + this.heap = new DoubleIntegerMaxHeap(k); + this.ties = new int[INITIAL_TIES_SIZE]; + } + + @Override + public int getK() { + return k; + } + + @Override + @Deprecated + public DoubleDistance getKNNDistance() { + if (heap.size() < k) { + return DoubleDistance.INFINITE_DISTANCE; + } + return new DoubleDistance(kdist); + } + + @Override + public double doubleKNNDistance() { + return kdist; + } + + @Override + @Deprecated + public void add(DoubleDistance distance, DBIDRef id) { + add(distance.doubleValue(), id); + } + + @Override + @Deprecated + public void add(Double distance, DBIDRef id) { + add(distance.doubleValue(), id); + } + + @Override + public final void add(final double distance, final DBIDRef id) { + if (distance > kdist) { + return; + } + final int iid = id.internalGetIndex(); + if (heap.size() < k) { + heap.add(distance, iid); + if (heap.size() >= k) { + kdist = heap.peekKey(); + } + return; + } + // Tied with top: + if (distance >= kdist) { + addToTies(iid); + return; + } + // Old top element: (kdist, previd) + updateHeap(distance, iid); + } + + @Override + public void add(DoubleDistanceDBIDPair e) { + add(e.doubleDistance(), e); + } + + /** + * Do a full update for the heap. + * + * @param distance Distance + * @param iid Object id + */ + private final void updateHeap(final double distance, final int iid) { + final double prevdist = kdist; + final int previd = heap.peekValue(); + heap.replaceTopElement(distance, iid); + kdist = heap.peekKey(); + // If the kdist improved, zap ties. + if (kdist < prevdist) { + numties = 0; + } else { + addToTies(previd); + } + } + + /** + * Ensure the ties array has capacity for at least one more element. + * + * @param id Id to add + */ + private final void addToTies(int id) { + if (ties.length == numties) { + ties = Arrays.copyOf(ties, (ties.length << 1) + 1); // grow. + } + ties[numties] = id; + ++numties; + } + + @Override + public DoubleDistanceIntegerDBIDPair poll() { + final DoubleDistanceIntegerDBIDPair ret; + if (numties > 0) { + ret = new DoubleDistanceIntegerDBIDPair(kdist, ties[numties - 1]); + --numties; + } else { + ret = new DoubleDistanceIntegerDBIDPair(heap.peekKey(), heap.peekValue()); + heap.poll(); + } + return ret; + } + + /** + * Pop the topmost element. + */ + protected void pop() { + if (numties > 0) { + --numties; + } else { + heap.poll(); + } + } + + @Override + public DoubleDistanceIntegerDBIDPair peek() { + if (numties > 0) { + return new DoubleDistanceIntegerDBIDPair(kdist, ties[numties - 1]); + } + return new DoubleDistanceIntegerDBIDPair(heap.peekKey(), heap.peekValue()); + } + + @Override + public int size() { + return heap.size() + numties; + } + + @Override + public boolean isEmpty() { + return heap.size() == 0; + } + + @Override + public void clear() { + heap.clear(); + numties = 0; + } + + @Override + public DoubleDistanceIntegerDBIDKNNList toKNNList() { + return new DoubleDistanceIntegerDBIDKNNList(this); + } + + /** + * Peek the topmost distance. + * + * @return distance + */ + protected double peekDistance() { + if (numties > 0) { + return kdist; + } else { + return heap.peekKey(); + } + } + + /** + * Peek the topmost internal ID. + * + * @return internal id + */ + protected int peekInternalDBID() { + if (numties > 0) { + return ties[numties - 1]; + } + return heap.peekValue(); + } +} diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDKNNList.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDKNNList.java new file mode 100644 index 00000000..a74497e8 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDKNNList.java @@ -0,0 +1,298 @@ +package de.lmu.ifi.dbs.elki.database.ids.integer; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +import java.util.Arrays; + +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; +import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPair; +import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDListIter; +import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNList; +import de.lmu.ifi.dbs.elki.database.ids.distance.ModifiableDoubleDistanceDBIDList; +import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; + +/** + * Class to store double distance, integer DBID results. + * + * @author Erich Schubert + * + * @apiviz.uses DoubleIntegerArrayQuickSort + */ +public class DoubleDistanceIntegerDBIDKNNList implements ModifiableDoubleDistanceDBIDList, DoubleDistanceKNNList, IntegerDBIDs { + /** + * Initial size allocation. + */ + private static final int INITIAL_SIZE = 21; + + /** + * The k value this list was generated for. + */ + int k; + + /** + * The size + */ + int size; + + /** + * Distance values + */ + double[] dists; + + /** + * DBIDs + */ + int[] ids; + + /** + * Constructor. + */ + public DoubleDistanceIntegerDBIDKNNList() { + super(); + this.k = -1; + this.dists = new double[INITIAL_SIZE]; + this.ids = new int[INITIAL_SIZE]; + } + + /** + * Constructor. + * + * @param k K parameter + * @param size Actual size + */ + public DoubleDistanceIntegerDBIDKNNList(int k, int size) { + super(); + this.k = k; + if (size > 0) { + this.dists = new double[size]; + this.ids = new int[size]; + } else { + this.dists = new double[INITIAL_SIZE]; + this.ids = new int[INITIAL_SIZE]; + } + } + + /** + * Constructor from heap. + * + * @param heap KNN heap. + */ + public DoubleDistanceIntegerDBIDKNNList(DoubleDistanceIntegerDBIDKNNHeap heap) { + super(); + this.k = heap.getK(); + this.size = heap.size(); + this.dists = new double[size]; + this.ids = new int[size]; + for (int i = size - 1; i >= 0; i--) { + dists[i] = heap.peekDistance(); + ids[i] = heap.peekInternalDBID(); + heap.pop(); + } + } + + @Override + public DoubleDistanceIntegerDBIDListIter iter() { + return new Itr(); + } + + @Override + public boolean contains(DBIDRef o) { + final int q = o.internalGetIndex(); + for (int i = 0; i < size; i++) { + if (q == ids[i]) { + return true; + } + } + return false; + } + + @Override + public boolean isEmpty() { + return size == 0; + } + + @Override + public int size() { + return size; + } + + @Override + public int getK() { + if (k <= 0) { + return size - 1; + } + return k; + } + + @Override + public DoubleDistanceIntegerDBIDPair get(int index) { + return new DoubleDistanceIntegerDBIDPair(dists[index], ids[index]); + } + + @Override + @Deprecated + public DoubleDistance getKNNDistance() { + return new DoubleDistance(doubleKNNDistance()); + } + + @Override + public double doubleKNNDistance() { + if (k <= 0) { + return dists[size - 1]; + } + if (size < k) { + return Double.POSITIVE_INFINITY; + } + return dists[k - 1]; + } + + /** + * Add an entry, consisting of distance and internal index. + * + * @param dist Distance + * @param id Internal index + */ + protected void add(double dist, int id) { + if (size == dists.length) { + final int newlength = (dists.length << 1) + 1; + dists = Arrays.copyOf(dists, newlength); + ids = Arrays.copyOf(ids, newlength); + } + dists[size] = dist; + ids[size] = id; + ++size; + } + + @Override + @Deprecated + public void add(DoubleDistance dist, DBIDRef id) { + add(dist.doubleValue(), id); + } + + @Override + public void add(double dist, DBIDRef id) { + add(dist, id.internalGetIndex()); + } + + @Override + public void add(DoubleDistanceDBIDPair pair) { + add(pair.doubleDistance(), pair.internalGetIndex()); + } + + @Override + public void sort() { + DoubleIntegerArrayQuickSort.sort(dists, ids, 0, size); + } + + /** + * Reverse the list. + */ + protected void reverse() { + for (int i = 0, j = size - 1; i < j; i++, j--) { + double tmpd = dists[j]; + dists[j] = dists[i]; + dists[i] = tmpd; + int tmpi = ids[j]; + ids[j] = ids[i]; + ids[i] = tmpi; + } + } + + @Override + public String toString() { + StringBuilder buf = new StringBuilder(); + buf.append("kNNList["); + for (DoubleDistanceDBIDListIter iter = this.iter(); iter.valid();) { + buf.append(iter.doubleDistance()).append(':').append(iter.internalGetIndex()); + iter.advance(); + if (iter.valid()) { + buf.append(','); + } + } + buf.append(']'); + return buf.toString(); + } + + /** + * List iterator. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + private class Itr implements DoubleDistanceIntegerDBIDListIter { + int offset = 0; + + @Override + public boolean valid() { + return offset < size; + } + + @Override + public void advance() { + ++offset; + } + + @Override + public int getOffset() { + return offset; + } + + @Override + public void advance(int count) { + offset += count; + } + + @Override + public void retract() { + offset--; + } + + @Override + public void seek(int off) { + offset = off; + } + + @Override + public int internalGetIndex() { + return ids[offset]; + } + + @Override + public double doubleDistance() { + return dists[offset]; + } + + @Override + public DoubleDistanceDBIDPair getDistancePair() { + return new DoubleDistanceIntegerDBIDPair(dists[offset], ids[offset]); + } + + @Override + @Deprecated + public DoubleDistance getDistance() { + return new DoubleDistance(dists[offset]); + } + + } +} diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDKNNListHeap.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDKNNListHeap.java new file mode 100644 index 00000000..ffc2266e --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDKNNListHeap.java @@ -0,0 +1,315 @@ +package de.lmu.ifi.dbs.elki.database.ids.integer; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +import java.util.Arrays; + +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; +import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDListIter; +import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPair; +import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNHeap; +import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNList; +import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; + +/** + * Class to store double distance, integer DBID results. + * + * @author Erich Schubert + * + * @apiviz.uses DoubleIntegerArrayQuickSort + */ +public class DoubleDistanceIntegerDBIDKNNListHeap implements DoubleDistanceKNNHeap, DoubleDistanceKNNList, IntegerDBIDs { + /** + * The k value this list was generated for. + */ + int k; + + /** + * The size + */ + int size; + + /** + * Distance values + */ + double[] dists; + + /** + * DBIDs + */ + int[] ids; + + /** + * Constructor. + * + * @param k K parameter + */ + public DoubleDistanceIntegerDBIDKNNListHeap(int k) { + super(); + this.k = k; + this.size = 0; + this.dists = new double[k + 1]; + this.ids = new int[k + 1]; + } + + @Override + public DoubleDistanceIntegerDBIDListIter iter() { + return new Itr(); + } + + @Override + public boolean contains(DBIDRef o) { + final int q = o.internalGetIndex(); + for(int i = 0; i < size; i++) { + if(q == ids[i]) { + return true; + } + } + return false; + } + + @Override + public boolean isEmpty() { + return size == 0; + } + + @Override + public int size() { + return size; + } + + @Override + public int getK() { + return k; + } + + @Override + public DoubleDistanceIntegerDBIDPair get(int index) { + return new DoubleDistanceIntegerDBIDPair(dists[index], ids[index]); + } + + @Override + @Deprecated + public DoubleDistance getKNNDistance() { + return new DoubleDistance(doubleKNNDistance()); + } + + @Override + public double doubleKNNDistance() { + if(size < k) { + return Double.POSITIVE_INFINITY; + } + return dists[k - 1]; + } + + /** + * Add an entry, consisting of distance and internal index. + * + * @param dist Distance + * @param id Internal index + */ + protected void append(double dist, int id) { + ensureSize(size + 1); + dists[size] = dist; + ids[size] = id; + ++size; + } + + /** + * Add a new element to the heap/list. + * + * @param dist Distance + * @param id Object ID + */ + protected void add(double dist, int id) { + if(size < k) { + dists[size] = dist; + ids[size] = id; + ++size; + if(size == k) { + sort(); + } + return; + } + if (dist > dists[size - 1]) { + return; + } + // Ensure we have enough space. + ensureSize(size + 1); + // Insertion sort: + int pos = size; + while(pos > 0 && dists[pos - 1] > dist) { + dists[pos] = dists[pos - 1]; + ids[pos] = ids[pos - 1]; + --pos; + } + dists[pos] = dist; + ids[pos] = id; + ++size; + // Truncate if necessary: + if(dists[k] > dists[k - 1]) { + size = k; + } + } + + /** + * Ensure we have enough space. + * + * @param size Desired size + */ + private void ensureSize(int size) { + if(size > dists.length) { + final int newlength = Math.max(size, (dists.length << 1) + 1); + dists = Arrays.copyOf(dists, newlength); + ids = Arrays.copyOf(ids, newlength); + } + } + + @Override + @Deprecated + public void add(DoubleDistance dist, DBIDRef id) { + add(dist.doubleValue(), id); + } + + @Override + @Deprecated + public void add(Double dist, DBIDRef id) { + add(dist.doubleValue(), id); + } + + @Override + public void add(double dist, DBIDRef id) { + add(dist, id.internalGetIndex()); + } + + @Override + public void add(DoubleDistanceDBIDPair pair) { + add(pair.doubleDistance(), pair.internalGetIndex()); + } + + /** + * Sort the current contents of the list. + */ + protected void sort() { + DoubleIntegerArrayQuickSort.sort(dists, ids, 0, size); + } + + @Override + public void clear() { + size = 0; + Arrays.fill(dists, Double.NaN); + Arrays.fill(ids, -1); + } + + @Override + public DoubleDistanceIntegerDBIDPair poll() { + return new DoubleDistanceIntegerDBIDPair(dists[k], ids[k]); + } + + @Override + public DoubleDistanceIntegerDBIDPair peek() { + return new DoubleDistanceIntegerDBIDPair(dists[k], ids[k]); + } + + @Override + public DoubleDistanceKNNList toKNNList() { + return this; + } + + @Override + public String toString() { + StringBuilder buf = new StringBuilder(); + buf.append("kNNListHeap["); + for(DoubleDistanceDBIDListIter iter = this.iter(); iter.valid();) { + buf.append(iter.doubleDistance()).append(':').append(iter.internalGetIndex()); + iter.advance(); + if(iter.valid()) { + buf.append(','); + } + } + buf.append(']'); + return buf.toString(); + } + + /** + * List iterator. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + private class Itr implements DoubleDistanceIntegerDBIDListIter { + int offset = 0; + + @Override + public boolean valid() { + return offset < size; + } + + @Override + public void advance() { + ++offset; + } + + @Override + public int getOffset() { + return offset; + } + + @Override + public void advance(int count) { + offset += count; + } + + @Override + public void retract() { + offset--; + } + + @Override + public void seek(int off) { + offset = off; + } + + @Override + public int internalGetIndex() { + return ids[offset]; + } + + @Override + public double doubleDistance() { + return dists[offset]; + } + + @Override + public DoubleDistanceDBIDPair getDistancePair() { + return new DoubleDistanceIntegerDBIDPair(dists[offset], ids[offset]); + } + + @Override + @Deprecated + public DoubleDistance getDistance() { + return new DoubleDistance(dists[offset]); + } + } +} diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDListIter.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDListIter.java new file mode 100644 index 00000000..0df81929 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDListIter.java @@ -0,0 +1,34 @@ +package de.lmu.ifi.dbs.elki.database.ids.integer; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDListIter; + +/** + * Combination interface. + * + * @author Erich Schubert + */ +public interface DoubleDistanceIntegerDBIDListIter extends DoubleDistanceDBIDListIter, IntegerDBIDArrayIter { + // Yet another painful combination interface. +} diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDPair.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDPair.java index 8334d2e3..1f3b2a45 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDPair.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleDistanceIntegerDBIDPair.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -22,9 +22,10 @@ package de.lmu.ifi.dbs.elki.database.ids.integer; You should have received a copy of the GNU Affero General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import de.lmu.ifi.dbs.elki.database.ids.DistanceDBIDPair; -import de.lmu.ifi.dbs.elki.database.ids.DoubleDistanceDBIDPair; +import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDPair; +import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPair; import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; +import de.lmu.ifi.dbs.elki.utilities.Util; /** * Class storing a double distance a DBID. @@ -90,14 +91,20 @@ class DoubleDistanceIntegerDBIDPair implements DoubleDistanceDBIDPair, IntegerDB } if (o instanceof DoubleDistanceIntegerDBIDPair) { DoubleDistanceIntegerDBIDPair p = (DoubleDistanceIntegerDBIDPair) o; - return (this.id == p.id) && (this.distance == p.distance); + return (this.id == p.id) && (Double.compare(this.distance, p.distance) == 0); } if (o instanceof DistanceIntegerDBIDPair) { DistanceIntegerDBIDPair<?> p = (DistanceIntegerDBIDPair<?>) o; if (p.distance instanceof DoubleDistance) { - return (this.id == p.id) && (this.distance == ((DoubleDistance) p.distance).doubleValue()); + return (this.id == p.id) && (Double.compare(this.distance, ((DoubleDistance) p.distance).doubleValue()) == 0); } } return false; } + + @Override + public int hashCode() { + long bits = Double.doubleToLongBits(distance); + return Util.mixHashCodes((int) (bits ^ (bits >>> 32)), id); + } } diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleIntegerArrayQuickSort.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleIntegerArrayQuickSort.java new file mode 100644 index 00000000..8f1c58d6 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/DoubleIntegerArrayQuickSort.java @@ -0,0 +1,181 @@ +package de.lmu.ifi.dbs.elki.database.ids.integer; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * Class to sort a double and an integer DBID array, using a quicksort with a + * best of 5 heuristic. + * + * @author Erich Schubert + */ +class DoubleIntegerArrayQuickSort { + /** + * Threshold for using insertion sort. + */ + private static final int INSERTION_THRESHOLD = 22; + + /** + * Sort the full array using the given comparator. + * + * @param keys Keys for sorting + * @param values Values for sorting + * @param len Length to sort. + */ + public static void sort(double[] keys, int[] values, int len) { + sort(keys, values, 0, len); + } + + /** + * Sort the array using the given comparator. + * + * @param keys Keys for sorting + * @param values Values for sorting + * @param start First index + * @param end Last index (exclusive) + */ + public static void sort(double[] keys, int[] values, int start, int end) { + quickSort(keys, values, start, end); + } + + /** + * Actual recursive sort function. + * + * @param keys Keys for sorting + * @param vals Values for sorting + * @param start First index + * @param end Last index (exclusive!) + */ + private static void quickSort(double[] keys, int[] vals, final int start, final int end) { + final int len = end - start; + if (len < INSERTION_THRESHOLD) { + // Classic insertion sort. + for (int i = start + 1; i < end; i++) { + for (int j = i; j > start; j--) { + if (keys[j] < keys[j - 1]) { + swap(keys, vals, j, j - 1); + } else { + break; + } + } + } + return; + } + + // Choose pivots by looking at five candidates. + final int seventh = (len >> 3) + (len >> 6) + 1; + final int m3 = (start + end) >> 1; // middle + final int m2 = m3 - seventh; + final int m1 = m2 - seventh; + final int m4 = m3 + seventh; + final int m5 = m4 + seventh; + + // Mixture of insertion and merge sort: + if (keys[m1] > keys[m2]) { + swap(keys, vals, m1, m2); + } + if (keys[m3] > keys[m4]) { + swap(keys, vals, m3, m4); + } + // Merge 1+2 and 3+4 + if (keys[m2] > keys[m4]) { + swap(keys, vals, m2, m4); + } + if (keys[m1] > keys[m3]) { + swap(keys, vals, m1, m3); + } + if (keys[m2] > keys[m3]) { + swap(keys, vals, m2, m3); + } + // Insertion sort m5: + if (keys[m4] > keys[m5]) { + swap(keys, vals, m4, m5); + if (keys[m3] > keys[m4]) { + swap(keys, vals, m3, m4); + if (keys[m2] > keys[m3]) { + swap(keys, vals, m2, m3); + if (keys[m1] > keys[m1]) { + swap(keys, vals, m1, m2); + } + } + } + } + + // Move pivot to the front. + double pivotkey = keys[m3]; + int pivotval = vals[m3]; + keys[m3] = keys[start]; + vals[m3] = vals[start]; + + // The interval to pivotize + int left = start + 1; + int right = end - 1; + + // This is the classic QuickSort loop: + while (true) { + while (left <= right && keys[left] <= pivotkey) { + left++; + } + while (left <= right && pivotkey <= keys[right]) { + right--; + } + if (right <= left) { + break; + } + swap(keys, vals, left, right); + left++; + right--; + } + + // Move pivot back into the appropriate place + keys[start] = keys[right]; + vals[start] = vals[right]; + keys[right] = pivotkey; + vals[right] = pivotval; + + // Recursion: + if (start + 1 < right) { + quickSort(keys, vals, start, right); + } + if (right + 2 < end) { + quickSort(keys, vals, right + 1, end); + } + } + + /** + * Swap two entries. + * + * @param keys Keys + * @param vals Values + * @param j First index + * @param i Second index + */ + private static void swap(double[] keys, int[] vals, int j, int i) { + double td = keys[j]; + keys[j] = keys[i]; + keys[i] = td; + int ti = vals[j]; + vals[j] = vals[i]; + vals[i] = ti; + } +} diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveArrayStaticDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerArrayDBIDs.java index 60dd50eb..61a12b3f 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveArrayStaticDBIDs.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerArrayDBIDs.java @@ -1,9 +1,10 @@ package de.lmu.ifi.dbs.elki.database.ids.integer; + /* This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -22,31 +23,14 @@ package de.lmu.ifi.dbs.elki.database.ids.integer; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import gnu.trove.list.TIntList; +import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs; /** - * Class accessing a trove int array. + * Trivial combination interface. * * @author Erich Schubert */ -class TroveArrayStaticDBIDs extends TroveArrayDBIDs implements IntegerArrayStaticDBIDs { - /** - * Actual trove store. - */ - private final TIntList store; - - /** - * Constructor. - * - * @param store Actual trove store. - */ - protected TroveArrayStaticDBIDs(TIntList store) { - super(); - this.store = store; - } - +public interface IntegerArrayDBIDs extends IntegerDBIDs, ArrayDBIDs { @Override - protected TIntList getStore() { - return store; - } + IntegerDBIDArrayIter iter(); } diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerArrayStaticDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerArrayStaticDBIDs.java index 4bafd343..9e18631b 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerArrayStaticDBIDs.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerArrayStaticDBIDs.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -29,9 +29,8 @@ import de.lmu.ifi.dbs.elki.database.ids.ArrayStaticDBIDs; * Combination of {@link ArrayStaticDBIDs} and {@link IntegerDBIDs}. * * @author Erich Schubert - * */ -public interface IntegerArrayStaticDBIDs extends ArrayStaticDBIDs, IntegerDBIDs { +public interface IntegerArrayStaticDBIDs extends ArrayStaticDBIDs, IntegerArrayDBIDs { @Override IntegerDBIDArrayIter iter(); }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBID.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBID.java index 91c00939..40243695 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBID.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBID.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -133,7 +133,7 @@ final class IntegerDBID implements DBID, IntegerDBIDRef { } @Override - public void assign(int index, DBIDVar var) { + public void assignVar(int index, DBIDVar var) { if (index != 0) { throw new ArrayIndexOutOfBoundsException(); } diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDArrayIter.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDArrayIter.java index b0e2d339..c604ac71 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDArrayIter.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDArrayIter.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDArrayMIter.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDArrayMIter.java index 21616f75..dcead6bd 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDArrayMIter.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDArrayMIter.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDArrayQuickSort.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDArrayQuickSort.java index 2c096ab9..90a97609 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDArrayQuickSort.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDArrayQuickSort.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDIter.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDIter.java index 9b50d544..cc241475 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDIter.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDIter.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDMIter.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDMIter.java index 2e339dbc..c0291d5b 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDMIter.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDMIter.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDPair.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDPair.java index e716f5b5..1b1ab154 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDPair.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDPair.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDRange.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDRange.java index 85c47f43..3ceb163d 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDRange.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDRange.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -189,7 +189,7 @@ class IntegerDBIDRange implements DBIDRange { } @Override - public void assign(int index, DBIDVar var) { + public void assignVar(int index, DBIDVar var) { if (var instanceof IntegerDBIDVar) { ((IntegerDBIDVar)var).internalSetIndex(start + index); } else { diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDRef.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDRef.java index 45854440..dc63b117 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDRef.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDRef.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDVar.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDVar.java index 73d164e0..57d400df 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDVar.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDVar.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -24,7 +24,6 @@ package de.lmu.ifi.dbs.elki.database.ids.integer; */ import de.lmu.ifi.dbs.elki.database.ids.DBID; -import de.lmu.ifi.dbs.elki.database.ids.DBIDArrayIter; import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; import de.lmu.ifi.dbs.elki.database.ids.DBIDVar; import de.lmu.ifi.dbs.elki.logging.LoggingUtil; @@ -38,7 +37,7 @@ import de.lmu.ifi.dbs.elki.logging.LoggingUtil; * * @author Erich Schubert */ -class IntegerDBIDVar implements DBIDVar { +class IntegerDBIDVar implements DBIDVar, IntegerDBIDs { /** * The actual value. */ @@ -88,7 +87,7 @@ class IntegerDBIDVar implements DBIDVar { } @Override - public DBIDArrayIter iter() { + public IntegerDBIDArrayIter iter() { return new DBIDItr(); } @@ -115,7 +114,7 @@ class IntegerDBIDVar implements DBIDVar { * * @apiviz.exclude */ - protected class DBIDItr implements DBIDArrayIter, IntegerDBIDRef { + protected class DBIDItr implements IntegerDBIDArrayIter, IntegerDBIDRef { /** * Iterator position: We use an integer so we can support retract(). */ @@ -182,15 +181,15 @@ class IntegerDBIDVar implements DBIDVar { } @Override - public void assign(int i, DBIDVar var) { + public void assignVar(int i, DBIDVar var) { if (var instanceof IntegerDBIDVar) { - ((IntegerDBIDVar)var).internalSetIndex(i); + ((IntegerDBIDVar) var).internalSetIndex(i); } else { // Much less efficient: var.set(get(i)); } } - + @Override public String toString() { return Integer.toString(id); diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDs.java index 8ffb9c6b..4acf91e6 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDs.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDBIDs.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDoubleDBIDPair.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDoubleDBIDPair.java index fe8c6a60..b522ffb2 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDoubleDBIDPair.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/IntegerDoubleDBIDPair.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/ReusingDBIDFactory.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/ReusingDBIDFactory.java index f6df2e0d..ebb36f22 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/ReusingDBIDFactory.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/ReusingDBIDFactory.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -33,14 +33,15 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; import de.lmu.ifi.dbs.elki.logging.Logging; /** - * Slightly more advanced DBID management, that allows reuse of DBIDs. + * Slightly more complex DBID management, that allows reuse of DBIDs. + * + * NOT tested a lot yet. Not reusing is much simpler! + * + * TODO: manage fragmentation of ranges? * * @author Erich Schubert * * @apiviz.stereotype factory - * @apiviz.uses IntegerDBID oneway - - «create» - * @apiviz.uses IntegerDBIDPair oneway - - «create» - * @apiviz.uses IntegerDBIDRange oneway - - «create» */ public class ReusingDBIDFactory extends SimpleDBIDFactory { /** @@ -64,7 +65,7 @@ public class ReusingDBIDFactory extends SimpleDBIDFactory { /** * Returned range allocations */ - ArrayList<IntegerDBIDRange> returnedAllocations = new ArrayList<IntegerDBIDRange>(); + ArrayList<IntegerDBIDRange> returnedAllocations = new ArrayList<>(); /** * Constructor @@ -115,7 +116,6 @@ public class ReusingDBIDFactory extends SimpleDBIDFactory { @Override public synchronized void deallocateDBIDRange(DBIDRange range) { - // TODO: catch an eventual cast exception? returnedAllocations.add((IntegerDBIDRange) range); } } diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/SimpleDBIDFactory.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/SimpleDBIDFactory.java index 77c1a91b..c3abd43a 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/SimpleDBIDFactory.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/SimpleDBIDFactory.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,22 +23,9 @@ package de.lmu.ifi.dbs.elki.database.ids.integer; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs; import de.lmu.ifi.dbs.elki.database.ids.DBID; -import de.lmu.ifi.dbs.elki.database.ids.DBIDFactory; -import de.lmu.ifi.dbs.elki.database.ids.DBIDPair; import de.lmu.ifi.dbs.elki.database.ids.DBIDRange; import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; -import de.lmu.ifi.dbs.elki.database.ids.DBIDVar; -import de.lmu.ifi.dbs.elki.database.ids.DBIDs; -import de.lmu.ifi.dbs.elki.database.ids.DistanceDBIDPair; -import de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDPair; -import de.lmu.ifi.dbs.elki.database.ids.DoubleDistanceDBIDPair; -import de.lmu.ifi.dbs.elki.database.ids.HashSetModifiableDBIDs; -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; -import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; -import de.lmu.ifi.dbs.elki.persistent.ByteBufferSerializer; -import de.lmu.ifi.dbs.elki.persistent.FixedSizeByteBufferSerializer; import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException; /** @@ -50,13 +37,8 @@ import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException; * * @apiviz.landmark * @apiviz.stereotype factory - * @apiviz.uses IntegerDBID oneway - - «create» - * @apiviz.uses IntegerDBIDPair oneway - - «create» - * @apiviz.uses IntegerDBIDRange oneway - - «create» - * @apiviz.uses TroveArrayModifiableDBIDs oneway - - «create» - * @apiviz.uses TroveHashSetModifiableDBIDs oneway - - «create» */ -public class SimpleDBIDFactory implements DBIDFactory { +public class SimpleDBIDFactory extends AbstractIntegerDBIDFactory { /** * Keep track of the smallest dynamic DBID offset not used. */ @@ -68,11 +50,6 @@ public class SimpleDBIDFactory implements DBIDFactory { int rangestart = 0; /** - * Invalid ID. - */ - DBID invalid = new IntegerDBID(Integer.MIN_VALUE); - - /** * Constructor. */ public SimpleDBIDFactory() { @@ -81,10 +58,10 @@ public class SimpleDBIDFactory implements DBIDFactory { @Override public synchronized DBID generateSingleDBID() { + dynamicids--; if(dynamicids == Integer.MIN_VALUE) { throw new AbortException("DBID range allocation error - too many objects allocated!"); } - dynamicids--; return new IntegerDBID(dynamicids); } @@ -107,114 +84,4 @@ public class SimpleDBIDFactory implements DBIDFactory { public void deallocateDBIDRange(DBIDRange range) { // ignore. } - - @Override - public DBID importInteger(int id) { - return new IntegerDBID(id); - } - - @Override - public void assignVar(DBIDVar var, int val) { - if (var instanceof IntegerDBIDVar) { - ((IntegerDBIDVar)var).internalSetIndex(val); - } else { - var.set(new IntegerDBID(val)); - } - } - - @Override - public int compare(DBIDRef a, DBIDRef b) { - final int inta = a.internalGetIndex(); - final int intb = b.internalGetIndex(); - return (inta < intb ? -1 : (inta == intb ? 0 : 1)); - } - - @Override - public boolean equal(DBIDRef a, DBIDRef b) { - return a.internalGetIndex() == b.internalGetIndex(); - } - - @Override - public String toString(DBIDRef id) { - return Integer.toString(id.internalGetIndex()); - } - - @Override - public DBIDVar newVar(DBIDRef val) { - return new IntegerDBIDVar(val); - } - - @Override - public ArrayModifiableDBIDs newArray() { - return new TroveArrayModifiableDBIDs(); - } - - @Override - public HashSetModifiableDBIDs newHashSet() { - return new TroveHashSetModifiableDBIDs(); - } - - @Override - public ArrayModifiableDBIDs newArray(int size) { - return new TroveArrayModifiableDBIDs(size); - } - - @Override - public HashSetModifiableDBIDs newHashSet(int size) { - return new TroveHashSetModifiableDBIDs(size); - } - - @Override - public ArrayModifiableDBIDs newArray(DBIDs existing) { - return new TroveArrayModifiableDBIDs(existing); - } - - @Override - public HashSetModifiableDBIDs newHashSet(DBIDs existing) { - return new TroveHashSetModifiableDBIDs(existing); - } - - @Override - public DBIDPair newPair(DBIDRef first, DBIDRef second) { - return new IntegerDBIDPair(first.internalGetIndex(), second.internalGetIndex()); - } - - @Override - public DoubleDBIDPair newPair(double val, DBIDRef id) { - return new IntegerDoubleDBIDPair(val, id.internalGetIndex()); - } - - @SuppressWarnings("unchecked") - @Override - public <D extends Distance<D>> DistanceDBIDPair<D> newDistancePair(D val, DBIDRef id) { - if (val instanceof DoubleDistance) { - return (DistanceDBIDPair<D>) new DoubleDistanceIntegerDBIDPair(((DoubleDistance) val).doubleValue(), id.internalGetIndex()); - } - return new DistanceIntegerDBIDPair<D>(val, id.internalGetIndex()); - } - - @Override - public DoubleDistanceDBIDPair newDistancePair(double val, DBIDRef id) { - return new DoubleDistanceIntegerDBIDPair(val, id.internalGetIndex()); - } - - @Override - public ByteBufferSerializer<DBID> getDBIDSerializer() { - return IntegerDBID.DYNAMIC_SERIALIZER; - } - - @Override - public FixedSizeByteBufferSerializer<DBID> getDBIDSerializerStatic() { - return IntegerDBID.STATIC_SERIALIZER; - } - - @Override - public Class<? extends DBID> getTypeRestriction() { - return IntegerDBID.class; - } - - @Override - public DBIDRef invalid() { - return invalid; - } }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/TrivialDBIDFactory.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/TrivialDBIDFactory.java index a9d8aa90..577c29ac 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/TrivialDBIDFactory.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/TrivialDBIDFactory.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -25,51 +25,27 @@ package de.lmu.ifi.dbs.elki.database.ids.integer; import java.util.concurrent.atomic.AtomicInteger; -import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs; import de.lmu.ifi.dbs.elki.database.ids.DBID; -import de.lmu.ifi.dbs.elki.database.ids.DBIDFactory; -import de.lmu.ifi.dbs.elki.database.ids.DBIDPair; import de.lmu.ifi.dbs.elki.database.ids.DBIDRange; import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; -import de.lmu.ifi.dbs.elki.database.ids.DBIDVar; -import de.lmu.ifi.dbs.elki.database.ids.DBIDs; -import de.lmu.ifi.dbs.elki.database.ids.DistanceDBIDPair; -import de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDPair; -import de.lmu.ifi.dbs.elki.database.ids.DoubleDistanceDBIDPair; -import de.lmu.ifi.dbs.elki.database.ids.HashSetModifiableDBIDs; -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; -import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; -import de.lmu.ifi.dbs.elki.persistent.ByteBufferSerializer; -import de.lmu.ifi.dbs.elki.persistent.FixedSizeByteBufferSerializer; import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException; /** * Trivial DBID management, that never reuses IDs and just gives them out in - * sequence. Statically allocated DBID ranges are given positive values, - * Dynamically allocated DBIDs are given negative values. + * sequence. All IDs will be positive. * * @author Erich Schubert * * @apiviz.landmark * @apiviz.stereotype factory - * @apiviz.uses IntegerDBID oneway - - «create» - * @apiviz.uses IntegerDBIDPair oneway - - «create» - * @apiviz.uses IntegerDBIDRange oneway - - «create» - * @apiviz.uses TroveArrayModifiableDBIDs oneway - - «create» - * @apiviz.uses TroveHashSetModifiableDBIDs oneway - - «create» */ -final public class TrivialDBIDFactory implements DBIDFactory { +final public class TrivialDBIDFactory extends AbstractIntegerDBIDFactory { /** * Keep track of the smallest dynamic DBID offset not used. */ AtomicInteger next = new AtomicInteger(1); /** - * Invalid ID. - */ - DBID invalid = new IntegerDBID(Integer.MIN_VALUE); - - /** * Constructor. */ public TrivialDBIDFactory() { @@ -105,114 +81,4 @@ final public class TrivialDBIDFactory implements DBIDFactory { public void deallocateDBIDRange(DBIDRange range) { // ignore. } - - @Override - public DBID importInteger(int id) { - return new IntegerDBID(id); - } - - @Override - public void assignVar(DBIDVar var, int val) { - if (var instanceof IntegerDBIDVar) { - ((IntegerDBIDVar)var).internalSetIndex(val); - } else { - var.set(new IntegerDBID(val)); - } - } - - @Override - public int compare(DBIDRef a, DBIDRef b) { - final int inta = a.internalGetIndex(); - final int intb = b.internalGetIndex(); - return (inta < intb ? -1 : (inta == intb ? 0 : 1)); - } - - @Override - public boolean equal(DBIDRef a, DBIDRef b) { - return a.internalGetIndex() == b.internalGetIndex(); - } - - @Override - public String toString(DBIDRef id) { - return Integer.toString(id.internalGetIndex()); - } - - @Override - public DBIDVar newVar(DBIDRef val) { - return new IntegerDBIDVar(val); - } - - @Override - public ArrayModifiableDBIDs newArray() { - return new TroveArrayModifiableDBIDs(); - } - - @Override - public HashSetModifiableDBIDs newHashSet() { - return new TroveHashSetModifiableDBIDs(); - } - - @Override - public ArrayModifiableDBIDs newArray(int size) { - return new TroveArrayModifiableDBIDs(size); - } - - @Override - public HashSetModifiableDBIDs newHashSet(int size) { - return new TroveHashSetModifiableDBIDs(size); - } - - @Override - public ArrayModifiableDBIDs newArray(DBIDs existing) { - return new TroveArrayModifiableDBIDs(existing); - } - - @Override - public HashSetModifiableDBIDs newHashSet(DBIDs existing) { - return new TroveHashSetModifiableDBIDs(existing); - } - - @Override - public DBIDPair newPair(DBIDRef first, DBIDRef second) { - return new IntegerDBIDPair(first.internalGetIndex(), second.internalGetIndex()); - } - - @Override - public DoubleDBIDPair newPair(double val, DBIDRef id) { - return new IntegerDoubleDBIDPair(val, id.internalGetIndex()); - } - - @SuppressWarnings("unchecked") - @Override - public <D extends Distance<D>> DistanceDBIDPair<D> newDistancePair(D val, DBIDRef id) { - if (val instanceof DoubleDistance) { - return (DistanceDBIDPair<D>) new DoubleDistanceIntegerDBIDPair(((DoubleDistance) val).doubleValue(), id.internalGetIndex()); - } - return new DistanceIntegerDBIDPair<D>(val, id.internalGetIndex()); - } - - @Override - public DoubleDistanceDBIDPair newDistancePair(double val, DBIDRef id) { - return new DoubleDistanceIntegerDBIDPair(val, id.internalGetIndex()); - } - - @Override - public ByteBufferSerializer<DBID> getDBIDSerializer() { - return IntegerDBID.DYNAMIC_SERIALIZER; - } - - @Override - public FixedSizeByteBufferSerializer<DBID> getDBIDSerializerStatic() { - return IntegerDBID.STATIC_SERIALIZER; - } - - @Override - public Class<? extends DBID> getTypeRestriction() { - return IntegerDBID.class; - } - - @Override - public DBIDRef invalid() { - return invalid; - } } diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveArrayDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveArrayDBIDs.java index 313a0f3b..6980176a 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveArrayDBIDs.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveArrayDBIDs.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -24,7 +24,6 @@ package de.lmu.ifi.dbs.elki.database.ids.integer; */ import gnu.trove.list.TIntList; -import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs; import de.lmu.ifi.dbs.elki.database.ids.DBID; import de.lmu.ifi.dbs.elki.database.ids.DBIDIter; import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; @@ -40,7 +39,7 @@ import de.lmu.ifi.dbs.elki.logging.LoggingUtil; * @apiviz.has IntegerDBID * @apiviz.has DBIDItr */ -public abstract class TroveArrayDBIDs implements ArrayDBIDs, IntegerDBIDs { +public abstract class TroveArrayDBIDs implements IntegerArrayDBIDs { /** * Get the array store. * @@ -59,7 +58,7 @@ public abstract class TroveArrayDBIDs implements ArrayDBIDs, IntegerDBIDs { } @Override - public void assign(int index, DBIDVar var) { + public void assignVar(int index, DBIDVar var) { if (var instanceof IntegerDBIDVar) { ((IntegerDBIDVar)var).internalSetIndex(getStore().get(index)); } else { diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveArrayModifiableDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveArrayModifiableDBIDs.java index 7e84eb56..41191b10 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveArrayModifiableDBIDs.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveArrayModifiableDBIDs.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -81,6 +81,7 @@ class TroveArrayModifiableDBIDs extends TroveArrayDBIDs implements ArrayModifiab @Override public boolean addDBIDs(DBIDs ids) { boolean success = false; + store.ensureCapacity(ids.size()); for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { success |= store.add(DBIDUtil.asInteger(iter)); } diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveHashSetModifiableDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveHashSetModifiableDBIDs.java index 9e65b3ae..9ebdccea 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveHashSetModifiableDBIDs.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/TroveHashSetModifiableDBIDs.java @@ -9,13 +9,13 @@ 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.HashSetModifiableDBIDs; -import de.lmu.ifi.dbs.elki.utilities.iterator.Iter; +import de.lmu.ifi.dbs.elki.utilities.datastructures.iterator.Iter; /* This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -83,6 +83,7 @@ class TroveHashSetModifiableDBIDs implements HashSetModifiableDBIDs, IntegerDBID @Override public boolean addDBIDs(DBIDs ids) { + store.ensureCapacity(ids.size()); boolean success = false; for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { success |= store.add(DBIDUtil.asInteger(iter)); diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/UnmodifiableIntegerArrayDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/UnmodifiableIntegerArrayDBIDs.java index 14e26748..ba30f54f 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/UnmodifiableIntegerArrayDBIDs.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/UnmodifiableIntegerArrayDBIDs.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -40,14 +40,14 @@ public class UnmodifiableIntegerArrayDBIDs implements IntegerArrayStaticDBIDs { /** * The DBIDs we wrap. */ - private final TroveArrayDBIDs inner; + private final IntegerArrayDBIDs inner; /** * Constructor. * * @param inner Inner DBID collection. */ - public UnmodifiableIntegerArrayDBIDs(TroveArrayDBIDs inner) { + public UnmodifiableIntegerArrayDBIDs(IntegerArrayDBIDs inner) { super(); this.inner = inner; } @@ -87,8 +87,8 @@ public class UnmodifiableIntegerArrayDBIDs implements IntegerArrayStaticDBIDs { } @Override - public void assign(int index, DBIDVar var) { - inner.assign(index, var); + public void assignVar(int index, DBIDVar var) { + inner.assignVar(index, var); } @Override diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/UnmodifiableIntegerDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/UnmodifiableIntegerDBIDs.java index 1d27f530..a3f03bd9 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/UnmodifiableIntegerDBIDs.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/UnmodifiableIntegerDBIDs.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.ids.integer; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/integer/package-info.java b/src/de/lmu/ifi/dbs/elki/database/ids/integer/package-info.java index 2508c930..74a39fb9 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/integer/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/integer/package-info.java @@ -10,7 +10,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2012 +Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/package-info.java b/src/de/lmu/ifi/dbs/elki/database/ids/package-info.java index 71af955c..eb0a6733 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/package-info.java @@ -83,7 +83,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/package-info.java b/src/de/lmu/ifi/dbs/elki/database/package-info.java index 73cf0596..0b5d16ea 100644 --- a/src/de/lmu/ifi/dbs/elki/database/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/database/package-info.java @@ -9,7 +9,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2012 +Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/query/AbstractDataBasedQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/AbstractDataBasedQuery.java index d9accf4f..5d0e8444 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/AbstractDataBasedQuery.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/AbstractDataBasedQuery.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/query/DatabaseQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/DatabaseQuery.java index 28c89ee3..caba81e3 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/DatabaseQuery.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/DatabaseQuery.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/query/DistanceSimilarityQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/DistanceSimilarityQuery.java index 9b9367fb..8906e07c 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/DistanceSimilarityQuery.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/DistanceSimilarityQuery.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/query/LinearScanQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/LinearScanQuery.java index 4cace1cf..6cb35025 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/LinearScanQuery.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/LinearScanQuery.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/query/distance/AbstractDatabaseDistanceQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/distance/AbstractDatabaseDistanceQuery.java index ed1ee50c..f530b72a 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/distance/AbstractDatabaseDistanceQuery.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/distance/AbstractDatabaseDistanceQuery.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.distance; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/query/distance/AbstractDistanceQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/distance/AbstractDistanceQuery.java index b85ddef0..933bd0d3 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/distance/AbstractDistanceQuery.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/distance/AbstractDistanceQuery.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.distance; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/query/distance/DBIDDistanceQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/distance/DBIDDistanceQuery.java index 28ca9b16..e619bc57 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/distance/DBIDDistanceQuery.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/distance/DBIDDistanceQuery.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.distance; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/query/distance/DistanceQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/distance/DistanceQuery.java index c026162d..12e76ace 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/distance/DistanceQuery.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/distance/DistanceQuery.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.distance; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/query/distance/PrimitiveDistanceQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/distance/PrimitiveDistanceQuery.java index 75bd9e39..ab3046ed 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/distance/PrimitiveDistanceQuery.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/distance/PrimitiveDistanceQuery.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.distance; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/query/distance/PrimitiveDistanceSimilarityQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/distance/PrimitiveDistanceSimilarityQuery.java index 930d195c..5ca62a73 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/distance/PrimitiveDistanceSimilarityQuery.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/distance/PrimitiveDistanceSimilarityQuery.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.distance; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/query/distance/SpatialDistanceQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/distance/SpatialDistanceQuery.java index 59f6534b..14839dd7 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/distance/SpatialDistanceQuery.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/distance/SpatialDistanceQuery.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.distance; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/query/distance/SpatialPrimitiveDistanceQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/distance/SpatialPrimitiveDistanceQuery.java index 550c2c5c..c5a601bd 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/distance/SpatialPrimitiveDistanceQuery.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/distance/SpatialPrimitiveDistanceQuery.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.distance; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/query/distance/package-info.java b/src/de/lmu/ifi/dbs/elki/database/query/distance/package-info.java index fdd116b7..97bc471d 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/distance/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/distance/package-info.java @@ -7,7 +7,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2012 +Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/query/knn/AbstractDistanceKNNQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/knn/AbstractDistanceKNNQuery.java index 0ac2e8ee..f9f7d018 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/knn/AbstractDistanceKNNQuery.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/knn/AbstractDistanceKNNQuery.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.knn; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,10 +23,15 @@ package de.lmu.ifi.dbs.elki.database.query.knn; along with this program. If not, see <http://www.gnu.org/licenses/>. */ +import java.util.ArrayList; +import java.util.List; + +import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs; +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.distance.KNNList; import de.lmu.ifi.dbs.elki.database.query.AbstractDataBasedQuery; import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; -import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; /** @@ -51,8 +56,22 @@ public abstract class AbstractDistanceKNNQuery<O, D extends Distance<D>> extends } @Override - abstract public KNNResult<D> getKNNForDBID(DBIDRef id, int k); + public List<? extends KNNList<D>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) { + // throw new + // UnsupportedOperationException(ExceptionMessages.UNSUPPORTED_NOT_YET); + // TODO: optimize + List<KNNList<D>> ret = new ArrayList<>(ids.size()); + for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { + ret.add(getKNNForDBID(iter, k)); + } + return ret; + } + + @Override + public KNNList<D> getKNNForDBID(DBIDRef id, int k) { + return getKNNForObject(relation.get(id), k); + } @Override - abstract public KNNResult<D> getKNNForObject(O obj, int k); -}
\ No newline at end of file + abstract public KNNList<D> getKNNForObject(O obj, int k); +} diff --git a/src/de/lmu/ifi/dbs/elki/database/query/knn/DoubleOptimizedKNNQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/knn/DoubleOptimizedKNNQuery.java new file mode 100644 index 00000000..b18db8f0 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/query/knn/DoubleOptimizedKNNQuery.java @@ -0,0 +1,309 @@ +package de.lmu.ifi.dbs.elki.database.query.knn; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import java.util.ArrayList; + +import de.lmu.ifi.dbs.elki.database.ids.DBIDFactory; +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.distance.DistanceDBIDPair; +import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPair; +import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNHeap; +import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList; +import de.lmu.ifi.dbs.elki.database.ids.generic.DistanceDBIDPairKNNList; +import de.lmu.ifi.dbs.elki.database.ids.generic.DoubleDistanceDBIDPairKNNHeap; +import de.lmu.ifi.dbs.elki.database.ids.generic.DoubleDistanceDBIDPairKNNList; +import de.lmu.ifi.dbs.elki.database.ids.integer.DoubleDistanceIntegerDBIDKNNList; +import de.lmu.ifi.dbs.elki.database.ids.integer.DoubleDistanceIntegerDBIDKNNListHeap; +import de.lmu.ifi.dbs.elki.database.query.distance.PrimitiveDistanceQuery; +import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction; +import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultUtil; +import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; +import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.Heap; +import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.TiedTopBoundedHeap; + +/** + * Optimized linear scan query for {@link PrimitiveDoubleDistanceFunction}s. + * + * @author Erich Schubert + * + * @apiviz.uses PrimitiveDoubleDistanceFunction + * + * @param <O> Object type + */ +public class DoubleOptimizedKNNQuery<O> extends LinearScanKNNQuery<O, DoubleDistance> { + /** + * Raw distance function. + */ + PrimitiveDoubleDistanceFunction<O> rawdist; + + /** + * Constructor. + * + * @param distanceQuery Distance function to use + */ + @SuppressWarnings("unchecked") + public DoubleOptimizedKNNQuery(PrimitiveDistanceQuery<O, DoubleDistance> distanceQuery) { + super(distanceQuery); + if(!(distanceQuery.getDistanceFunction() instanceof PrimitiveDoubleDistanceFunction)) { + throw new UnsupportedOperationException("DoubleOptimizedKNNQuery instantiated for non-PrimitiveDoubleDistanceFunction!"); + } + rawdist = (PrimitiveDoubleDistanceFunction<O>) distanceQuery.getDistanceFunction(); + } + + @Override + public KNNList<DoubleDistance> getKNNForDBID(DBIDRef id, int k) { + return getKNNForObject(relation.get(id), k); + } + + @Override + public KNNList<DoubleDistance> getKNNForObject(O obj, int k) { + return getKNNForObjectBenchmarked(obj, k); + } + + /** + * This is the straightforward implementation using the optimized heap. + * + * @param obj Query object + * @param k Desired number of neighbors + * @return kNN result + */ + KNNList<DoubleDistance> getKNNForObjectKNNHeap(O obj, int k) { + // Optimization for double distances. + final DoubleDistanceKNNHeap heap = (DoubleDistanceKNNHeap) DBIDUtil.newHeap(DoubleDistance.FACTORY, k); + for(DBIDIter iter = relation.iterDBIDs(); iter.valid(); iter.advance()) { + heap.add(rawdist.doubleDistance(obj, relation.get(iter)), iter); + } + return heap.toKNNList(); + } + + /** + * This is the cleaner, supposedly faster implementation. + * + * @param obj Query object + * @param k Desired number of neighbors + * @return kNN result + */ + KNNList<DoubleDistance> getKNNForObjectClean(O obj, int k) { + // Optimization for double distances. + final TiedTopBoundedHeap<DoubleDistanceDBIDPair> heap = new TiedTopBoundedHeap<>(k, DoubleDistanceDBIDPairKNNHeap.COMPARATOR); + final DBIDIter iter = relation.iterDBIDs(); + + // First k elements don't need checking. + double max = 0.; + for(int i = 0; i < k && iter.valid(); i++, iter.advance()) { + final double doubleDistance = rawdist.doubleDistance(obj, relation.get(iter)); + heap.add(DBIDFactory.FACTORY.newDistancePair(doubleDistance, iter)); + max = Math.max(max, doubleDistance); + } + // Remaining elements + for(; iter.valid(); iter.advance()) { + final double doubleDistance = rawdist.doubleDistance(obj, relation.get(iter)); + if(doubleDistance <= max) { + heap.add(DBIDFactory.FACTORY.newDistancePair(doubleDistance, iter)); + } + if(doubleDistance < max) { + max = heap.peek().doubleDistance(); + } + } + return new DoubleDistanceDBIDPairKNNList(heap, k); + } + + /** + * It does not make sense, but this version is faster in our larger + * benchmarks. Apparently, some JIT optimization kicks in better. + * + * @param obj Query object + * @param k Desired number of neighbors + * @return kNN result + */ + KNNList<DoubleDistance> getKNNForObjectBenchmarked(O obj, int k) { + // THIS SHOULD BE SLOWER THAN THE VERSION ABOVE, BUT ISN'T! + final TiedTopBoundedHeap<DistanceDBIDPair<DoubleDistance>> heap = new TiedTopBoundedHeap<>(k, DistanceDBIDResultUtil.BY_REVERSE_DISTANCE); + final DBIDIter iter = relation.iterDBIDs(); + // First k elements don't need checking. + double max = 0.; + for(int i = 0; i < k && iter.valid(); i++, iter.advance()) { + final double doubleDistance = rawdist.doubleDistance(obj, relation.get(iter)); + heap.add(DBIDFactory.FACTORY.newDistancePair(new DoubleDistance(doubleDistance), iter)); + max = Math.max(max, doubleDistance); + } + // Remaining elements + for(; iter.valid(); iter.advance()) { + final double doubleDistance = rawdist.doubleDistance(obj, relation.get(iter)); + if(doubleDistance <= max) { + heap.add(DBIDFactory.FACTORY.newDistancePair(new DoubleDistance(doubleDistance), iter)); + } + if(doubleDistance < max) { + max = heap.peek().getDistance().doubleValue(); + } + } + return new DistanceDBIDPairKNNList<>(heap, k); + } + + /** + * Another attempt at getting a faster knn heap. + * + * @param obj Query object + * @param k Desired number of neighbors + * @return kNN result + */ + KNNList<DoubleDistance> getKNNForObjectBenchmarked2(O obj, int k) { + final Heap<DoubleDistanceDBIDPair> heap = new Heap<>(k, DistanceDBIDResultUtil.BY_REVERSE_DISTANCE); + final ArrayList<DoubleDistanceDBIDPair> ties = new ArrayList<>(); + final DBIDIter iter = relation.iterDBIDs(); + // First k elements don't need checking. + double max = 0.; + for(int i = 0; i < k && iter.valid(); i++, iter.advance()) { + final double doubleDistance = rawdist.distance(obj, relation.get(iter)).doubleValue(); + heap.add(DBIDFactory.FACTORY.newDistancePair(doubleDistance, iter)); + max = Math.max(max, doubleDistance); + } + // Remaining elements + for(; iter.valid(); iter.advance()) { + final double doubleDistance = rawdist.distance(obj, relation.get(iter)).doubleValue(); + if(doubleDistance <= max) { + if(doubleDistance < max) { + DoubleDistanceDBIDPair prev = heap.replaceTopElement(DBIDFactory.FACTORY.newDistancePair(doubleDistance, iter)); + double newkdist = heap.peek().doubleDistance(); + if(newkdist < max) { + max = newkdist; + ties.clear(); + } + else { + ties.add(prev); + } + } + else { + ties.add(DBIDFactory.FACTORY.newDistancePair(doubleDistance, iter)); + } + } + } + + DoubleDistanceIntegerDBIDKNNList ret = new DoubleDistanceIntegerDBIDKNNList(k, k + ties.size()); + for(DoubleDistanceDBIDPair pair : ties) { + ret.add(pair); + } + while(!heap.isEmpty()) { + ret.add(heap.poll()); + } + ret.sort(); // Actually, reverse. + return ret; + } + + /** + * Next attempt at exploiting the JIT fully. + * + * @param obj Query object + * @param k Desired number of neighbors + * @return kNN result + */ + KNNList<DoubleDistance> getKNNForObjectBenchmarked3(O obj, int k) { + DoubleDistanceKNNHeap heap = new DoubleDistanceIntegerDBIDKNNListHeap(k); + final DBIDIter iter = relation.iterDBIDs(); + // First k elements don't need checking. + double max = 0.; + for(int i = 0; i < k && iter.valid(); i++, iter.advance()) { + final double doubleDistance = rawdist.doubleDistance(obj, relation.get(iter)); + heap.add(doubleDistance, iter); + max = Math.max(max, doubleDistance); + } + // Remaining elements + for(; iter.valid(); iter.advance()) { + final double doubleDistance = rawdist.doubleDistance(obj, relation.get(iter)); + if(doubleDistance <= max) { + heap.add(doubleDistance, iter); + } + if(doubleDistance < max) { + max = heap.peek().doubleDistance(); + } + } + return heap.toKNNList(); + } + + /** + * Next attempt at exploiting the JIT fully. + * + * @param obj Query object + * @param k Desired number of neighbors + * @return kNN result + */ + KNNList<DoubleDistance> getKNNForObjectBenchmarked4(O obj, int k) { + DoubleDistanceKNNHeap heap = new DoubleDistanceIntegerDBIDKNNListHeap(k); + final DBIDIter iter = relation.iterDBIDs(); + // First k elements don't need checking. + for(int i = 0; i < k && iter.valid(); i++, iter.advance()) { + final double doubleDistance = rawdist.doubleDistance(obj, relation.get(iter)); + heap.add(doubleDistance, iter); + } + double max = heap.doubleKNNDistance(); + // Remaining elements + for(; iter.valid(); iter.advance()) { + final double doubleDistance = rawdist.doubleDistance(obj, relation.get(iter)); + if(doubleDistance <= max) { + heap.add(doubleDistance, iter); + max = heap.doubleKNNDistance(); + } + } + return heap.toKNNList(); + } + + /** + * Next attempt at exploiting the JIT fully. + * + * @param obj Query object + * @param k Desired number of neighbors + * @return kNN result + */ + KNNList<DoubleDistance> getKNNForObjectBenchmarked5(O obj, int k) { + DoubleDistanceKNNHeap heap = new DoubleDistanceIntegerDBIDKNNListHeap(k); + double max = Double.POSITIVE_INFINITY; + for(DBIDIter iter = relation.iterDBIDs(); iter.valid(); iter.advance()) { + final double distance = rawdist.doubleDistance(obj, relation.get(iter)); + if(distance <= max) { + heap.add(distance, iter); + max = heap.doubleKNNDistance(); + } + } + return heap.toKNNList(); + } + + /** + * Next attempt at exploiting the JIT fully. + * + * @param obj Query object + * @param k Desired number of neighbors + * @return kNN result + */ + KNNList<DoubleDistance> getKNNForObjectBenchmarked6(O obj, int k) { + DoubleDistanceKNNHeap heap = new DoubleDistanceIntegerDBIDKNNListHeap(k); + for(DBIDIter iter = relation.iterDBIDs(); iter.valid(); iter.advance()) { + final double distance = rawdist.doubleDistance(obj, relation.get(iter)); + heap.add(distance, iter); + } + return heap.toKNNList(); + } +} diff --git a/src/de/lmu/ifi/dbs/elki/database/query/knn/KNNQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/knn/KNNQuery.java index 5b517509..c94f3d42 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/knn/KNNQuery.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/knn/KNNQuery.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.knn; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -27,8 +27,8 @@ import java.util.List; import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs; import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; +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.distance.distanceresultlist.KNNResult; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; /** @@ -37,7 +37,7 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; * @author Erich Schubert * * @apiviz.landmark - * @apiviz.has KNNResult oneway - - «create» + * @apiviz.has KNNList oneway - - «create» * * @param <O> Object type * @param <D> Distance type @@ -50,7 +50,7 @@ public interface KNNQuery<O, D extends Distance<D>> extends DatabaseQuery { * @param k Number of neighbors requested * @return neighbors */ - public KNNResult<D> getKNNForDBID(DBIDRef id, int k); + public KNNList<D> getKNNForDBID(DBIDRef id, int k); /** * Bulk query method @@ -59,7 +59,7 @@ public interface KNNQuery<O, D extends Distance<D>> extends DatabaseQuery { * @param k Number of neighbors requested * @return neighbors */ - public List<? extends KNNResult<D>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k); + public List<? extends KNNList<D>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k); /** * Get the k nearest neighbors for a particular id. @@ -68,5 +68,5 @@ public interface KNNQuery<O, D extends Distance<D>> extends DatabaseQuery { * @param k Number of neighbors requested * @return neighbors */ - public KNNResult<D> getKNNForObject(O obj, int k); + public KNNList<D> getKNNForObject(O obj, int k); }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/database/query/knn/LinearScanKNNQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/knn/LinearScanKNNQuery.java index 29fa9931..485330ea 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/knn/LinearScanKNNQuery.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/knn/LinearScanKNNQuery.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.knn; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -29,12 +29,12 @@ import java.util.List; import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs; 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.distance.KNNHeap; +import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList; import de.lmu.ifi.dbs.elki.database.query.LinearScanQuery; import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; import de.lmu.ifi.dbs.elki.database.query.distance.PrimitiveDistanceQuery; -import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNHeap; -import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult; -import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNUtil; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; /** @@ -63,9 +63,9 @@ public class LinearScanKNNQuery<O, D extends Distance<D>> extends AbstractDistan */ private void linearScanBatchKNN(ArrayDBIDs ids, List<KNNHeap<D>> heaps) { // The distance is computed on database IDs - for(DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) { + for (DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) { int index = 0; - for(DBIDIter iter2 = ids.iter(); iter2.valid(); iter2.advance()) { + for (DBIDIter iter2 = ids.iter(); iter2.valid(); iter2.advance()) { KNNHeap<D> heap = heaps.get(index); heap.add(distanceQuery.distance(iter2, iter), iter); index++; @@ -74,27 +74,26 @@ public class LinearScanKNNQuery<O, D extends Distance<D>> extends AbstractDistan } @Override - public KNNResult<D> getKNNForDBID(DBIDRef id, int k) { - KNNHeap<D> heap = KNNUtil.newHeap(distanceQuery.getDistanceFactory(), k); + public KNNList<D> getKNNForDBID(DBIDRef id, int k) { + KNNHeap<D> heap = DBIDUtil.newHeap(distanceQuery.getDistanceFactory(), k); D max = distanceQuery.getDistanceFactory().infiniteDistance(); - if(PrimitiveDistanceQuery.class.isInstance(distanceQuery)) { + if (PrimitiveDistanceQuery.class.isInstance(distanceQuery)) { O obj = relation.get(id); - for(DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) { + for (DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) { final D dist = distanceQuery.distance(obj, relation.get(iter)); - if(max.compareTo(dist) > 0) { + if (max.compareTo(dist) > 0) { heap.add(dist, iter); - if(heap.size() >= k) { + if (heap.size() >= k) { max = heap.getKNNDistance(); } } } - } - else { - for(DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) { + } else { + for (DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) { final D dist = distanceQuery.distance(id, iter); - if(max.compareTo(dist) > 0) { + if (max.compareTo(dist) > 0) { heap.add(dist, iter); - if(heap.size() >= k) { + if (heap.size() >= k) { max = heap.getKNNDistance(); } } @@ -104,27 +103,27 @@ public class LinearScanKNNQuery<O, D extends Distance<D>> extends AbstractDistan } @Override - public List<KNNResult<D>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) { + public List<KNNList<D>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) { final int size = ids.size(); - final List<KNNHeap<D>> heaps = new ArrayList<KNNHeap<D>>(size); - for(int i = 0; i < size; i++) { - heaps.add(KNNUtil.newHeap(distanceQuery.getDistanceFactory(), k)); + final List<KNNHeap<D>> heaps = new ArrayList<>(size); + for (int i = 0; i < size; i++) { + heaps.add(DBIDUtil.newHeap(distanceQuery.getDistanceFactory(), k)); } linearScanBatchKNN(ids, heaps); // Serialize heaps - List<KNNResult<D>> result = new ArrayList<KNNResult<D>>(size); - for(KNNHeap<D> heap : heaps) { + List<KNNList<D>> result = new ArrayList<>(size); + for (KNNHeap<D> heap : heaps) { result.add(heap.toKNNList()); } return result; } @Override - public KNNResult<D> getKNNForObject(O obj, int k) { - KNNHeap<D> heap = KNNUtil.newHeap(distanceQuery.getDistanceFactory(), k); - for(DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) { + public KNNList<D> getKNNForObject(O obj, int k) { + KNNHeap<D> heap = DBIDUtil.newHeap(distanceQuery.getDistanceFactory(), k); + for (DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) { heap.add(distanceQuery.distance(obj, iter), iter); } return heap.toKNNList(); } -}
\ No newline at end of file +} diff --git a/src/de/lmu/ifi/dbs/elki/database/query/knn/LinearScanPrimitiveDistanceKNNQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/knn/LinearScanPrimitiveDistanceKNNQuery.java index c4f09744..3f3fbc3f 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/knn/LinearScanPrimitiveDistanceKNNQuery.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/knn/LinearScanPrimitiveDistanceKNNQuery.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.knn; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -29,10 +29,10 @@ import java.util.List; import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs; 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.distance.KNNHeap; +import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList; import de.lmu.ifi.dbs.elki.database.query.distance.PrimitiveDistanceQuery; -import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNHeap; -import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult; -import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNUtil; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; /** @@ -74,22 +74,22 @@ public class LinearScanPrimitiveDistanceKNNQuery<O, D extends Distance<D>> exten } @Override - public KNNResult<D> getKNNForDBID(DBIDRef id, int k) { + public KNNList<D> getKNNForDBID(DBIDRef id, int k) { return getKNNForObject(relation.get(id), k); } @Override - public List<KNNResult<D>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) { + public List<KNNList<D>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) { final int size = ids.size(); - final List<KNNHeap<D>> heaps = new ArrayList<KNNHeap<D>>(size); - List<O> objs = new ArrayList<O>(size); + final List<KNNHeap<D>> heaps = new ArrayList<>(size); + List<O> objs = new ArrayList<>(size); for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { - heaps.add(KNNUtil.newHeap(distanceQuery.getDistanceFactory(), k)); + heaps.add(DBIDUtil.newHeap(distanceQuery.getDistanceFactory(), k)); objs.add(relation.get(iter)); } linearScanBatchKNN(objs, heaps); - List<KNNResult<D>> result = new ArrayList<KNNResult<D>>(heaps.size()); + List<KNNList<D>> result = new ArrayList<>(heaps.size()); for(KNNHeap<D> heap : heaps) { result.add(heap.toKNNList()); } diff --git a/src/de/lmu/ifi/dbs/elki/database/query/knn/LinearScanRawDoubleDistanceKNNQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/knn/LinearScanRawDoubleDistanceKNNQuery.java deleted file mode 100644 index 5e5eae2f..00000000 --- a/src/de/lmu/ifi/dbs/elki/database/query/knn/LinearScanRawDoubleDistanceKNNQuery.java +++ /dev/null @@ -1,143 +0,0 @@ -package de.lmu.ifi.dbs.elki.database.query.knn; - -/* - This file is part of ELKI: - Environment for Developing KDD-Applications Supported by Index-Structures - - Copyright (C) 2012 - Ludwig-Maximilians-Universität München - Lehr- und Forschungseinheit für Datenbanksysteme - ELKI Development Team - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -import de.lmu.ifi.dbs.elki.database.ids.DBIDFactory; -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.DistanceDBIDPair; -import de.lmu.ifi.dbs.elki.database.ids.DoubleDistanceDBIDPair; -import de.lmu.ifi.dbs.elki.database.query.distance.PrimitiveDistanceQuery; -import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distanceresultlist.AbstractKNNHeap; -import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceKNNHeap; -import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceKNNList; -import de.lmu.ifi.dbs.elki.distance.distanceresultlist.GenericKNNList; -import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult; -import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; -import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.TiedTopBoundedHeap; - -/** - * Optimized linear scan query for {@link PrimitiveDoubleDistanceFunction}s. - * - * @author Erich Schubert - * - * @apiviz.uses PrimitiveDoubleDistanceFunction - * - * @param <O> Object type - */ -public class LinearScanRawDoubleDistanceKNNQuery<O> extends LinearScanPrimitiveDistanceKNNQuery<O, DoubleDistance> { - /** - * Raw distance function. - */ - PrimitiveDoubleDistanceFunction<O> rawdist; - - /** - * Constructor. - * - * @param distanceQuery Distance function to use - */ - @SuppressWarnings("unchecked") - public LinearScanRawDoubleDistanceKNNQuery(PrimitiveDistanceQuery<O, DoubleDistance> distanceQuery) { - super(distanceQuery); - if (!(distanceQuery.getDistanceFunction() instanceof PrimitiveDoubleDistanceFunction)) { - throw new UnsupportedOperationException("LinearScanRawDoubleDistance instantiated for non-RawDoubleDistance!"); - } - rawdist = (PrimitiveDoubleDistanceFunction<O>) distanceQuery.getDistanceFunction(); - } - - @Override - public KNNResult<DoubleDistance> getKNNForDBID(DBIDRef id, int k) { - return getKNNForObject(relation.get(id), k); - } - - @Override - public KNNResult<DoubleDistance> getKNNForObject(O obj, int k) { - return getKNNForObjectBenchmarked(obj, k); - } - - /** - * This is the cleaner, supposedly faster implementation. - * - * @param obj Query object - * @param k Desired number of neighbors - * @return kNN result - */ - KNNResult<DoubleDistance> getKNNForObjectClean(O obj, int k) { - // Optimization for double distances. - final TiedTopBoundedHeap<DoubleDistanceDBIDPair> heap = new TiedTopBoundedHeap<DoubleDistanceDBIDPair>(k, DoubleDistanceKNNHeap.COMPARATOR); - final DBIDIter iter = relation.iterDBIDs(); - - // First k elements don't need checking. - double max = 0.; - for (int i = 0; i < k && iter.valid(); i++, iter.advance()) { - final double doubleDistance = rawdist.doubleDistance(obj, relation.get(iter)); - heap.add(DBIDFactory.FACTORY.newDistancePair(doubleDistance, iter)); - max = Math.max(max, doubleDistance); - } - // Remaining elements - for (; iter.valid(); iter.advance()) { - final double doubleDistance = rawdist.doubleDistance(obj, relation.get(iter)); - if (doubleDistance <= max) { - heap.add(DBIDFactory.FACTORY.newDistancePair(doubleDistance, iter)); - } - if (doubleDistance < max) { - max = heap.peek().doubleDistance(); - } - } - return new DoubleDistanceKNNList(heap, k); - } - - /** - * It does not make sense, but this version is faster in our larger - * benchmarks. Apparently, some JIT optimization kicks in better. - * - * @param obj Query object - * @param k Desired number of neighbors - * @return kNN result - */ - KNNResult<DoubleDistance> getKNNForObjectBenchmarked(O obj, int k) { - // THIS SHOULD BE SLOWER THAN THE VERSION ABOVE, BUT ISN'T! - final TiedTopBoundedHeap<DistanceDBIDPair<DoubleDistance>> heap = new TiedTopBoundedHeap<DistanceDBIDPair<DoubleDistance>>(k, AbstractKNNHeap.COMPARATOR); - final DBIDIter iter = relation.iterDBIDs(); - // First k elements don't need checking. - double max = 0.; - for (int i = 0; i < k && iter.valid(); i++, iter.advance()) { - final double doubleDistance = rawdist.doubleDistance(obj, relation.get(iter)); - heap.add(DBIDFactory.FACTORY.newDistancePair(new DoubleDistance(doubleDistance), iter)); - max = Math.max(max, doubleDistance); - } - // Remaining elements - for (; iter.valid(); iter.advance()) { - final double doubleDistance = rawdist.doubleDistance(obj, relation.get(iter)); - if (doubleDistance <= max) { - heap.add(DBIDFactory.FACTORY.newDistancePair(new DoubleDistance(doubleDistance), iter)); - } - if (doubleDistance < max) { - max = heap.peek().getDistance().doubleValue(); - } - } - return new GenericKNNList<DoubleDistance>(heap, k); - } -} diff --git a/src/de/lmu/ifi/dbs/elki/database/query/knn/PreprocessorKNNQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/knn/PreprocessorKNNQuery.java index a1e12fc3..0f555c79 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/knn/PreprocessorKNNQuery.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/knn/PreprocessorKNNQuery.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.knn; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -29,10 +29,10 @@ import java.util.List; import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs; 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.distance.KNNList; import de.lmu.ifi.dbs.elki.database.query.AbstractDataBasedQuery; import de.lmu.ifi.dbs.elki.database.relation.Relation; -import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult; -import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNUtil; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; import de.lmu.ifi.dbs.elki.index.preprocessed.knn.AbstractMaterializeKNNPreprocessor; import de.lmu.ifi.dbs.elki.logging.LoggingUtil; @@ -43,7 +43,7 @@ import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException; * * @author Erich Schubert */ -public class PreprocessorKNNQuery<O, D extends Distance<D>, T extends KNNResult<D>> extends AbstractDataBasedQuery<O> implements KNNQuery<O, D> { +public class PreprocessorKNNQuery<O, D extends Distance<D>, T extends KNNList<D>> extends AbstractDataBasedQuery<O> implements KNNQuery<O, D> { /** * The last preprocessor result */ @@ -76,12 +76,12 @@ public class PreprocessorKNNQuery<O, D extends Distance<D>, T extends KNNResult< } @Override - public KNNResult<D> getKNNForDBID(DBIDRef id, int k) { + public KNNList<D> getKNNForDBID(DBIDRef id, int k) { if(!warned && k > preprocessor.getK()) { LoggingUtil.warning("Requested more neighbors than preprocessed!"); } if(!warned && k < preprocessor.getK()) { - KNNResult<D> dr = preprocessor.get(id); + KNNList<D> dr = preprocessor.get(id); int subk = k; D kdist = dr.get(subk - 1).getDistance(); while(subk < dr.size()) { @@ -95,7 +95,7 @@ public class PreprocessorKNNQuery<O, D extends Distance<D>, T extends KNNResult< } } if(subk < dr.size()) { - return KNNUtil.subList(dr, subk); + return DBIDUtil.subList(dr, subk); } else { return dr; @@ -105,14 +105,14 @@ public class PreprocessorKNNQuery<O, D extends Distance<D>, T extends KNNResult< } @Override - public List<KNNResult<D>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) { + public List<KNNList<D>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) { if(!warned && k > preprocessor.getK()) { LoggingUtil.warning("Requested more neighbors than preprocessed!"); } - List<KNNResult<D>> result = new ArrayList<KNNResult<D>>(ids.size()); + List<KNNList<D>> result = new ArrayList<>(ids.size()); if(k < preprocessor.getK()) { for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { - KNNResult<D> dr = preprocessor.get(iter); + KNNList<D> dr = preprocessor.get(iter); int subk = k; D kdist = dr.get(subk - 1).getDistance(); while(subk < dr.size()) { @@ -126,7 +126,7 @@ public class PreprocessorKNNQuery<O, D extends Distance<D>, T extends KNNResult< } } if(subk < dr.size()) { - result.add(KNNUtil.subList(dr, subk)); + result.add(DBIDUtil.subList(dr, subk)); } else { result.add(dr); @@ -142,7 +142,7 @@ public class PreprocessorKNNQuery<O, D extends Distance<D>, T extends KNNResult< } @Override - public KNNResult<D> getKNNForObject(O obj, int k) { + public KNNList<D> getKNNForObject(O obj, int k) { throw new AbortException("Preprocessor KNN query only supports ID queries."); } diff --git a/src/de/lmu/ifi/dbs/elki/database/query/knn/package-info.java b/src/de/lmu/ifi/dbs/elki/database/query/knn/package-info.java index 63c3aa16..17d8e4b0 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/knn/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/knn/package-info.java @@ -8,7 +8,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2012 +Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/query/package-info.java b/src/de/lmu/ifi/dbs/elki/database/query/package-info.java index 386ce6f3..fb3539bc 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/package-info.java @@ -81,7 +81,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2012 +Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/query/range/AbstractDistanceRangeQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/range/AbstractDistanceRangeQuery.java index 9997f3d6..c348653b 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/range/AbstractDistanceRangeQuery.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/range/AbstractDistanceRangeQuery.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.range; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -24,9 +24,9 @@ package de.lmu.ifi.dbs.elki.database.query.range; */ import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; +import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList; import de.lmu.ifi.dbs.elki.database.query.AbstractDataBasedQuery; import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; -import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; /** @@ -55,8 +55,10 @@ public abstract class AbstractDistanceRangeQuery<O, D extends Distance<D>> exten } @Override - abstract public DistanceDBIDResult<D> getRangeForDBID(DBIDRef id, D range); + public DistanceDBIDList<D> getRangeForDBID(DBIDRef id, D range) { + return getRangeForObject(relation.get(id), range); + } @Override - abstract public DistanceDBIDResult<D> getRangeForObject(O obj, D range); -}
\ No newline at end of file + abstract public DistanceDBIDList<D> getRangeForObject(O obj, D range); +} diff --git a/src/de/lmu/ifi/dbs/elki/database/query/range/DoubleOptimizedRangeQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/range/DoubleOptimizedRangeQuery.java new file mode 100644 index 00000000..209e8950 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/query/range/DoubleOptimizedRangeQuery.java @@ -0,0 +1,95 @@ +package de.lmu.ifi.dbs.elki.database.query.range; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2013 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +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.distance.DistanceDBIDList; +import de.lmu.ifi.dbs.elki.database.ids.distance.ModifiableDoubleDistanceDBIDList; +import de.lmu.ifi.dbs.elki.database.ids.integer.DoubleDistanceIntegerDBIDKNNList; +import de.lmu.ifi.dbs.elki.database.query.LinearScanQuery; +import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; +import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction; +import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; + +/** + * Default linear scan range query class. + * + * @author Erich Schubert + * + * @apiviz.uses PrimitiveDoubleDistanceFunction + * + * @param <O> Database object type + */ +public class DoubleOptimizedRangeQuery<O> extends LinearScanRangeQuery<O, DoubleDistance> implements LinearScanQuery { + /** + * Raw distance function. + */ + PrimitiveDoubleDistanceFunction<O> rawdist; + + /** + * Constructor. + * + * @param distanceQuery Distance function to use + */ + @SuppressWarnings("unchecked") + public DoubleOptimizedRangeQuery(DistanceQuery<O, DoubleDistance> distanceQuery) { + super(distanceQuery); + if (!(distanceQuery.getDistanceFunction() instanceof PrimitiveDoubleDistanceFunction)) { + throw new UnsupportedOperationException("DoubleOptimizedRangeQuery instantiated for non-PrimitiveDoubleDistanceFunction!"); + } + rawdist = (PrimitiveDoubleDistanceFunction<O>) distanceQuery.getDistanceFunction(); + } + + @Override + public DistanceDBIDList<DoubleDistance> getRangeForDBID(DBIDRef id, DoubleDistance range) { + double epsilon = range.doubleValue(); + + O qo = relation.get(id); + ModifiableDoubleDistanceDBIDList result = new DoubleDistanceIntegerDBIDKNNList(); + for (DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) { + double doubleDistance = rawdist.doubleDistance(qo, relation.get(iter)); + if (doubleDistance <= epsilon) { + result.add(doubleDistance, iter); + } + } + result.sort(); + return result; + } + + @Override + public DistanceDBIDList<DoubleDistance> getRangeForObject(O obj, DoubleDistance range) { + double epsilon = range.doubleValue(); + + ModifiableDoubleDistanceDBIDList result = new DoubleDistanceIntegerDBIDKNNList(); + for (DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) { + double doubleDistance = rawdist.doubleDistance(obj, relation.get(iter)); + if (doubleDistance <= epsilon) { + result.add(doubleDistance, iter); + } + } + result.sort(); + return result; + } +} diff --git a/src/de/lmu/ifi/dbs/elki/database/query/range/LinearScanPrimitiveDistanceRangeQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/range/LinearScanPrimitiveDistanceRangeQuery.java index 57fa2338..3b18c282 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/range/LinearScanPrimitiveDistanceRangeQuery.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/range/LinearScanPrimitiveDistanceRangeQuery.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.range; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -24,8 +24,8 @@ package de.lmu.ifi.dbs.elki.database.query.range; */ import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; +import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList; import de.lmu.ifi.dbs.elki.database.query.distance.PrimitiveDistanceQuery; -import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; /** @@ -52,7 +52,7 @@ public class LinearScanPrimitiveDistanceRangeQuery<O, D extends Distance<D>> ext } @Override - public DistanceDBIDResult<D> getRangeForDBID(DBIDRef id, D range) { + public DistanceDBIDList<D> getRangeForDBID(DBIDRef id, D range) { // Note: subtle optimization. Get "id" only once! return getRangeForObject(relation.get(id), range); } diff --git a/src/de/lmu/ifi/dbs/elki/database/query/range/LinearScanRangeQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/range/LinearScanRangeQuery.java index 13e13a5c..c886c537 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/range/LinearScanRangeQuery.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/range/LinearScanRangeQuery.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.range; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -25,10 +25,10 @@ package de.lmu.ifi.dbs.elki.database.query.range; 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.distance.DistanceDBIDList; +import de.lmu.ifi.dbs.elki.database.ids.generic.GenericDistanceDBIDList; import de.lmu.ifi.dbs.elki.database.query.LinearScanQuery; import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; -import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult; -import de.lmu.ifi.dbs.elki.distance.distanceresultlist.GenericDistanceDBIDList; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; /** @@ -53,8 +53,8 @@ public class LinearScanRangeQuery<O, D extends Distance<D>> extends AbstractDist } @Override - public DistanceDBIDResult<D> getRangeForDBID(DBIDRef id, D range) { - GenericDistanceDBIDList<D> result = new GenericDistanceDBIDList<D>(); + public DistanceDBIDList<D> getRangeForDBID(DBIDRef id, D range) { + GenericDistanceDBIDList<D> result = new GenericDistanceDBIDList<>(); for(DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) { D currentDistance = distanceQuery.distance(id, iter); if(currentDistance.compareTo(range) <= 0) { @@ -66,8 +66,8 @@ public class LinearScanRangeQuery<O, D extends Distance<D>> extends AbstractDist } @Override - public DistanceDBIDResult<D> getRangeForObject(O obj, D range) { - GenericDistanceDBIDList<D> result = new GenericDistanceDBIDList<D>(); + public DistanceDBIDList<D> getRangeForObject(O obj, D range) { + GenericDistanceDBIDList<D> result = new GenericDistanceDBIDList<>(); for(DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) { D currentDistance = distanceQuery.distance(obj, iter); if(currentDistance.compareTo(range) <= 0) { diff --git a/src/de/lmu/ifi/dbs/elki/database/query/range/LinearScanRawDoubleDistanceRangeQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/range/LinearScanRawDoubleDistanceRangeQuery.java deleted file mode 100644 index 18863b2d..00000000 --- a/src/de/lmu/ifi/dbs/elki/database/query/range/LinearScanRawDoubleDistanceRangeQuery.java +++ /dev/null @@ -1,99 +0,0 @@ -package de.lmu.ifi.dbs.elki.database.query.range; - -/* - This file is part of ELKI: - Environment for Developing KDD-Applications Supported by Index-Structures - - Copyright (C) 2012 - Ludwig-Maximilians-Universität München - Lehr- und Forschungseinheit für Datenbanksysteme - ELKI Development Team - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -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.query.LinearScanQuery; -import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; -import de.lmu.ifi.dbs.elki.database.query.distance.PrimitiveDistanceQuery; -import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult; -import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DoubleDistanceDBIDList; -import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; - -/** - * Default linear scan range query class. - * - * @author Erich Schubert - * - * @apiviz.uses PrimitiveDoubleDistanceFunction - * - * @param <O> Database object type - */ -public class LinearScanRawDoubleDistanceRangeQuery<O> extends LinearScanRangeQuery<O, DoubleDistance> implements LinearScanQuery { - /** - * Constructor. - * - * @param distanceQuery Distance function to use - */ - public LinearScanRawDoubleDistanceRangeQuery(DistanceQuery<O, DoubleDistance> distanceQuery) { - super(distanceQuery); - } - - @Override - public DistanceDBIDResult<DoubleDistance> getRangeForDBID(DBIDRef id, DoubleDistance range) { - if(distanceQuery instanceof PrimitiveDistanceQuery && distanceQuery.getDistanceFunction() instanceof PrimitiveDoubleDistanceFunction) { - @SuppressWarnings("unchecked") - PrimitiveDoubleDistanceFunction<O> rawdist = (PrimitiveDoubleDistanceFunction<O>) distanceQuery.getDistanceFunction(); - double epsilon = range.doubleValue(); - - O qo = relation.get(id); - DoubleDistanceDBIDList result = new DoubleDistanceDBIDList(); - for(DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) { - double doubleDistance = rawdist.doubleDistance(qo, relation.get(iter)); - if(doubleDistance <= epsilon) { - result.add(doubleDistance, iter); - } - } - result.sort(); - return result; - } - else { - return super.getRangeForDBID(id, range); - } - } - - @Override - public DistanceDBIDResult<DoubleDistance> getRangeForObject(O obj, DoubleDistance range) { - if(distanceQuery instanceof PrimitiveDistanceQuery && distanceQuery.getDistanceFunction() instanceof PrimitiveDoubleDistanceFunction) { - @SuppressWarnings("unchecked") - PrimitiveDoubleDistanceFunction<O> rawdist = (PrimitiveDoubleDistanceFunction<O>) distanceQuery.getDistanceFunction(); - double epsilon = range.doubleValue(); - - DoubleDistanceDBIDList result = new DoubleDistanceDBIDList(); - for(DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) { - double doubleDistance = rawdist.doubleDistance(obj, relation.get(iter)); - if(doubleDistance <= epsilon) { - result.add(doubleDistance, iter); - } - } - result.sort(); - return result; - } - else { - return super.getRangeForObject(obj, range); - } - } -}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/database/query/range/RangeQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/range/RangeQuery.java index 9574cda7..0ec40dde 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/range/RangeQuery.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/range/RangeQuery.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.range; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -24,8 +24,8 @@ package de.lmu.ifi.dbs.elki.database.query.range; */ import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; +import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList; import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery; -import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; /** @@ -47,7 +47,7 @@ public interface RangeQuery<O, D extends Distance<D>> extends DatabaseQuery { * @param range Query range * @return neighbors */ - public DistanceDBIDResult<D> getRangeForDBID(DBIDRef id, D range); + public DistanceDBIDList<D> getRangeForDBID(DBIDRef id, D range); /** * Get the nearest neighbors for a particular object in a given query range @@ -56,5 +56,5 @@ public interface RangeQuery<O, D extends Distance<D>> extends DatabaseQuery { * @param range Query range * @return neighbors */ - public DistanceDBIDResult<D> getRangeForObject(O obj, D range); + public DistanceDBIDList<D> getRangeForObject(O obj, D range); }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/database/query/range/package-info.java b/src/de/lmu/ifi/dbs/elki/database/query/range/package-info.java index a176e43d..b2e3427d 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/range/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/range/package-info.java @@ -7,7 +7,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2012 +Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/query/rknn/AbstractRKNNQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/rknn/AbstractRKNNQuery.java index a090b466..8a88bf0f 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/rknn/AbstractRKNNQuery.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/rknn/AbstractRKNNQuery.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.rknn; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -24,9 +24,9 @@ package de.lmu.ifi.dbs.elki.database.query.rknn; */ import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; +import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList; import de.lmu.ifi.dbs.elki.database.query.AbstractDataBasedQuery; import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; -import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; /** @@ -51,5 +51,5 @@ public abstract class AbstractRKNNQuery<O, D extends Distance<D>> extends Abstra } @Override - abstract public DistanceDBIDResult<D> getRKNNForDBID(DBIDRef id, int k); + abstract public DistanceDBIDList<D> getRKNNForDBID(DBIDRef id, int k); }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/database/query/rknn/LinearScanRKNNQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/rknn/LinearScanRKNNQuery.java index f0e33777..71cf0619 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/rknn/LinearScanRKNNQuery.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/rknn/LinearScanRKNNQuery.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.rknn; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -30,13 +30,13 @@ import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs; 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.distance.DistanceDBIDList; +import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter; +import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList; +import de.lmu.ifi.dbs.elki.database.ids.generic.GenericDistanceDBIDList; import de.lmu.ifi.dbs.elki.database.query.LinearScanQuery; import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery; -import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult; -import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultIter; -import de.lmu.ifi.dbs.elki.distance.distanceresultlist.GenericDistanceDBIDList; -import de.lmu.ifi.dbs.elki.distance.distanceresultlist.KNNResult; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; /** @@ -70,15 +70,15 @@ public class LinearScanRKNNQuery<O, D extends Distance<D>> extends AbstractRKNNQ } @Override - public DistanceDBIDResult<D> getRKNNForObject(O obj, int k) { - GenericDistanceDBIDList<D> rNNlist = new GenericDistanceDBIDList<D>(); + public DistanceDBIDList<D> getRKNNForObject(O obj, int k) { + GenericDistanceDBIDList<D> rNNlist = new GenericDistanceDBIDList<>(); ArrayDBIDs allIDs = DBIDUtil.ensureArray(relation.getDBIDs()); - List<? extends KNNResult<D>> kNNLists = knnQuery.getKNNForBulkDBIDs(allIDs, k); + List<? extends KNNList<D>> kNNLists = knnQuery.getKNNForBulkDBIDs(allIDs, k); int i = 0; for (DBIDIter iter = allIDs.iter(); iter.valid(); iter.advance()) { - KNNResult<D> knn = kNNLists.get(i); + KNNList<D> knn = kNNLists.get(i); int last = Math.min(k - 1, knn.size() - 1); D dist = distanceQuery.distance(obj, iter); if(last < k - 1 || dist.compareTo(knn.get(last).getDistance()) < 1) { @@ -91,16 +91,16 @@ public class LinearScanRKNNQuery<O, D extends Distance<D>> extends AbstractRKNNQ } @Override - public DistanceDBIDResult<D> getRKNNForDBID(DBIDRef id, int k) { - GenericDistanceDBIDList<D> rNNList = new GenericDistanceDBIDList<D>(); + public DistanceDBIDList<D> getRKNNForDBID(DBIDRef id, int k) { + GenericDistanceDBIDList<D> rNNList = new GenericDistanceDBIDList<>(); ArrayDBIDs allIDs = DBIDUtil.ensureArray(relation.getDBIDs()); - List<? extends KNNResult<D>> kNNList = knnQuery.getKNNForBulkDBIDs(allIDs, k); + List<? extends KNNList<D>> kNNList = knnQuery.getKNNForBulkDBIDs(allIDs, k); int i = 0; for (DBIDIter iter = allIDs.iter(); iter.valid(); iter.advance()) { - KNNResult<D> knn = kNNList.get(i); - for(DistanceDBIDResultIter<D> n = knn.iter(); n.valid(); n.advance()) { + KNNList<D> knn = kNNList.get(i); + for(DistanceDBIDListIter<D> n = knn.iter(); n.valid(); n.advance()) { if(DBIDUtil.equal(n, id)) { rNNList.add(n.getDistance(), iter); } @@ -113,18 +113,18 @@ public class LinearScanRKNNQuery<O, D extends Distance<D>> extends AbstractRKNNQ @Override public List<GenericDistanceDBIDList<D>> getRKNNForBulkDBIDs(ArrayDBIDs ids, int k) { - List<GenericDistanceDBIDList<D>> rNNList = new ArrayList<GenericDistanceDBIDList<D>>(ids.size()); + List<GenericDistanceDBIDList<D>> rNNList = new ArrayList<>(ids.size()); for(int i = 0; i < ids.size(); i++) { rNNList.add(new GenericDistanceDBIDList<D>()); } ArrayDBIDs allIDs = DBIDUtil.ensureArray(relation.getDBIDs()); - List<? extends KNNResult<D>> kNNList = knnQuery.getKNNForBulkDBIDs(allIDs, k); + List<? extends KNNList<D>> kNNList = knnQuery.getKNNForBulkDBIDs(allIDs, k); int i = 0; for (DBIDIter iter = allIDs.iter(); iter.valid(); iter.advance()) { - KNNResult<D> knn = kNNList.get(i); - for(DistanceDBIDResultIter<D> n = knn.iter(); n.valid(); n.advance()) { + KNNList<D> knn = kNNList.get(i); + for(DistanceDBIDListIter<D> n = knn.iter(); n.valid(); n.advance()) { int j = 0; for (DBIDIter iter2 = ids.iter(); iter2.valid(); iter2.advance()) { if(DBIDUtil.equal(n, iter2)) { diff --git a/src/de/lmu/ifi/dbs/elki/database/query/rknn/PreprocessorRKNNQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/rknn/PreprocessorRKNNQuery.java index 8256ffad..9f8f9c71 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/rknn/PreprocessorRKNNQuery.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/rknn/PreprocessorRKNNQuery.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.rknn; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -29,9 +29,9 @@ import java.util.List; import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs; 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.distance.DistanceDBIDList; import de.lmu.ifi.dbs.elki.database.query.AbstractDataBasedQuery; import de.lmu.ifi.dbs.elki.database.relation.Relation; -import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; import de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNAndRKNNPreprocessor; import de.lmu.ifi.dbs.elki.logging.LoggingUtil; @@ -75,7 +75,7 @@ public class PreprocessorRKNNQuery<O, D extends Distance<D>> extends AbstractDat } @Override - public DistanceDBIDResult<D> getRKNNForDBID(DBIDRef id, int k) { + public DistanceDBIDList<D> getRKNNForDBID(DBIDRef id, int k) { if(!warned && k != preprocessor.getK()) { LoggingUtil.warning("Requested more neighbors than preprocessed!"); } @@ -83,16 +83,16 @@ public class PreprocessorRKNNQuery<O, D extends Distance<D>> extends AbstractDat } @Override - public DistanceDBIDResult<D> getRKNNForObject(O obj, int k) { + public DistanceDBIDList<D> getRKNNForObject(O obj, int k) { throw new AbortException("Preprocessor KNN query only supports ID queries."); } @Override - public List<? extends DistanceDBIDResult<D>> getRKNNForBulkDBIDs(ArrayDBIDs ids, int k) { + public List<? extends DistanceDBIDList<D>> getRKNNForBulkDBIDs(ArrayDBIDs ids, int k) { if(!warned && k != preprocessor.getK()) { LoggingUtil.warning("Requested more neighbors than preprocessed!"); } - List<DistanceDBIDResult<D>> result = new ArrayList<DistanceDBIDResult<D>>(ids.size()); + List<DistanceDBIDList<D>> result = new ArrayList<>(ids.size()); for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { result.add(preprocessor.getRKNN(iter)); } diff --git a/src/de/lmu/ifi/dbs/elki/database/query/rknn/RKNNQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/rknn/RKNNQuery.java index dc21948e..0a05d797 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/rknn/RKNNQuery.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/rknn/RKNNQuery.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.rknn; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -27,8 +27,8 @@ import java.util.List; import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs; import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; +import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList; import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery; -import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResult; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; /** @@ -36,7 +36,7 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; * * @author Erich Schubert * - * @apiviz.uses DistanceDBIDResult oneway - - «create» + * @apiviz.uses DistanceDBIDList oneway - - «create» * * @param <O> Object type * @param <D> Distance type @@ -49,7 +49,7 @@ public interface RKNNQuery<O, D extends Distance<D>> extends DatabaseQuery { * @param k number of neighbors requested * @return reverse k nearest neighbors */ - public DistanceDBIDResult<D> getRKNNForDBID(DBIDRef id, int k); + public DistanceDBIDList<D> getRKNNForDBID(DBIDRef id, int k); /** * Get the reverse k nearest neighbors for a particular object. @@ -58,7 +58,7 @@ public interface RKNNQuery<O, D extends Distance<D>> extends DatabaseQuery { * @param k number of neighbors requested * @return reverse k nearest neighbors */ - public DistanceDBIDResult<D> getRKNNForObject(O obj, int k); + public DistanceDBIDList<D> getRKNNForObject(O obj, int k); /** * Bulk query method for reverse k nearest neighbors for ids. @@ -67,5 +67,5 @@ public interface RKNNQuery<O, D extends Distance<D>> extends DatabaseQuery { * @param k number of neighbors requested * @return reverse k nearest neighbors */ - public List<? extends DistanceDBIDResult<D>> getRKNNForBulkDBIDs(ArrayDBIDs ids, int k); + public List<? extends DistanceDBIDList<D>> getRKNNForBulkDBIDs(ArrayDBIDs ids, int k); }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/database/query/rknn/package-info.java b/src/de/lmu/ifi/dbs/elki/database/query/rknn/package-info.java index a7e2bf37..8c0501b6 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/rknn/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/rknn/package-info.java @@ -7,7 +7,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2012 +Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/query/similarity/AbstractDBIDSimilarityQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/similarity/AbstractDBIDSimilarityQuery.java index 3d5ff71f..8dc6dd61 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/similarity/AbstractDBIDSimilarityQuery.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/similarity/AbstractDBIDSimilarityQuery.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.similarity; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/query/similarity/AbstractSimilarityQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/similarity/AbstractSimilarityQuery.java index 21abe219..fbcf76a7 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/similarity/AbstractSimilarityQuery.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/similarity/AbstractSimilarityQuery.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.similarity; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/query/similarity/PrimitiveSimilarityQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/similarity/PrimitiveSimilarityQuery.java index 5a604d0c..b98482a8 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/similarity/PrimitiveSimilarityQuery.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/similarity/PrimitiveSimilarityQuery.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.similarity; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/query/similarity/SimilarityQuery.java b/src/de/lmu/ifi/dbs/elki/database/query/similarity/SimilarityQuery.java index b25d13fc..3e02edc1 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/similarity/SimilarityQuery.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/similarity/SimilarityQuery.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.query.similarity; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/query/similarity/package-info.java b/src/de/lmu/ifi/dbs/elki/database/query/similarity/package-info.java index d601d0a4..dde6909b 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/similarity/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/similarity/package-info.java @@ -6,7 +6,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2012 +Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/relation/ConvertToStringView.java b/src/de/lmu/ifi/dbs/elki/database/relation/ConvertToStringView.java index 4c25405b..3ce4d935 100644 --- a/src/de/lmu/ifi/dbs/elki/database/relation/ConvertToStringView.java +++ b/src/de/lmu/ifi/dbs/elki/database/relation/ConvertToStringView.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.relation; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/relation/DBIDView.java b/src/de/lmu/ifi/dbs/elki/database/relation/DBIDView.java index b8974ac2..7eb14983 100644 --- a/src/de/lmu/ifi/dbs/elki/database/relation/DBIDView.java +++ b/src/de/lmu/ifi/dbs/elki/database/relation/DBIDView.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.relation; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -48,7 +48,7 @@ public class DBIDView extends AbstractHierarchicalResult implements Relation<DBI /** * The ids object */ - private final DBIDs ids; + private DBIDs ids; /** * Constructor. @@ -80,10 +80,9 @@ public class DBIDView extends AbstractHierarchicalResult implements Relation<DBI @Override public void delete(DBIDRef id) { - if(database instanceof UpdatableDatabase) { + if (database instanceof UpdatableDatabase) { ((UpdatableDatabase) database).delete(id); - } - else { + } else { throw new UnsupportedOperationException("Deletions are not supported."); } } @@ -103,6 +102,15 @@ public class DBIDView extends AbstractHierarchicalResult implements Relation<DBI return ids.iter(); } + /** + * Set the DBIDs of the view. + * + * @param ids IDs to use + */ + public void setDBIDs(DBIDs ids) { + this.ids = DBIDUtil.makeUnmodifiable(ids); + } + @Override public int size() { return ids.size(); @@ -117,4 +125,4 @@ public class DBIDView extends AbstractHierarchicalResult implements Relation<DBI public String getShortName() { return "DBID"; } -}
\ No newline at end of file +} diff --git a/src/de/lmu/ifi/dbs/elki/database/relation/MaterializedRelation.java b/src/de/lmu/ifi/dbs/elki/database/relation/MaterializedRelation.java index 2d090e99..8df4a42b 100644 --- a/src/de/lmu/ifi/dbs/elki/database/relation/MaterializedRelation.java +++ b/src/de/lmu/ifi/dbs/elki/database/relation/MaterializedRelation.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.relation; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/relation/ProjectedView.java b/src/de/lmu/ifi/dbs/elki/database/relation/ProjectedView.java index 8f2b8c92..252b651b 100644 --- a/src/de/lmu/ifi/dbs/elki/database/relation/ProjectedView.java +++ b/src/de/lmu/ifi/dbs/elki/database/relation/ProjectedView.java @@ -12,7 +12,7 @@ import de.lmu.ifi.dbs.elki.result.AbstractHierarchicalResult; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -60,6 +60,7 @@ public class ProjectedView<IN, OUT> extends AbstractHierarchicalResult implement super(); this.inner = inner; this.projection = projection; + projection.initialize(inner.getDataTypeInformation()); } @Override diff --git a/src/de/lmu/ifi/dbs/elki/database/relation/ProxyView.java b/src/de/lmu/ifi/dbs/elki/database/relation/ProxyView.java index 9937c8ee..d6e12d60 100644 --- a/src/de/lmu/ifi/dbs/elki/database/relation/ProxyView.java +++ b/src/de/lmu/ifi/dbs/elki/database/relation/ProxyView.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.relation; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -48,7 +48,7 @@ public class ProxyView<O> extends AbstractHierarchicalResult implements Relation /** * The DBIDs we contain */ - private final DBIDs idview; + private DBIDs idview; /** * The wrapped representation where we get the IDs from. @@ -82,7 +82,7 @@ public class ProxyView<O> extends AbstractHierarchicalResult implements Relation * @return Instance */ public static <O> ProxyView<O> wrap(Database database, DBIDs idview, Relation<O> inner) { - return new ProxyView<O>(database, idview, inner); + return new ProxyView<>(database, idview, inner); } @Override @@ -90,7 +90,7 @@ public class ProxyView<O> extends AbstractHierarchicalResult implements Relation assert (idview.contains(id)) : "Accessing object not included in view."; return inner.get(id); } - + @Override public void set(DBIDRef id, O val) { assert (idview.contains(id)) : "Accessing object not included in view."; @@ -131,4 +131,13 @@ public class ProxyView<O> extends AbstractHierarchicalResult implements Relation public String getShortName() { return "partition"; } -}
\ No newline at end of file + + /** + * Set the DBIDs to use. + * + * @param ids DBIDs + */ + public void setDBIDs(DBIDs ids) { + this.idview = ids; + } +} diff --git a/src/de/lmu/ifi/dbs/elki/database/relation/Relation.java b/src/de/lmu/ifi/dbs/elki/database/relation/Relation.java index 4969ad50..9ac4e408 100644 --- a/src/de/lmu/ifi/dbs/elki/database/relation/Relation.java +++ b/src/de/lmu/ifi/dbs/elki/database/relation/Relation.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.relation; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/relation/RelationUtil.java b/src/de/lmu/ifi/dbs/elki/database/relation/RelationUtil.java index 77f98f60..b6549d6c 100644 --- a/src/de/lmu/ifi/dbs/elki/database/relation/RelationUtil.java +++ b/src/de/lmu/ifi/dbs/elki/database/relation/RelationUtil.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.database.relation; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2012 + Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/database/relation/package-info.java b/src/de/lmu/ifi/dbs/elki/database/relation/package-info.java index 12ecf968..133d6574 100644 --- a/src/de/lmu/ifi/dbs/elki/database/relation/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/database/relation/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2012 +Copyright (C) 2013 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team |