diff options
Diffstat (limited to 'src/de/lmu/ifi/dbs/elki/database')
89 files changed, 1658 insertions, 401 deletions
diff --git a/src/de/lmu/ifi/dbs/elki/database/AbstractDatabase.java b/src/de/lmu/ifi/dbs/elki/database/AbstractDatabase.java index f9582039..e0fc6bf2 100644 --- a/src/de/lmu/ifi/dbs/elki/database/AbstractDatabase.java +++ b/src/de/lmu/ifi/dbs/elki/database/AbstractDatabase.java @@ -23,6 +23,7 @@ package de.lmu.ifi.dbs.elki.database; along with this program. If not, see <http://www.gnu.org/licenses/>. */ +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -56,7 +57,8 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID; /** * Abstract base class for database API implementations. Provides default - * management of relations, indexes and events as well as default query matching. + * management of relations, indexes and events as well as default query + * matching. * * @author Erich Schubert * @@ -137,7 +139,7 @@ public abstract class AbstractDatabase extends AbstractHierarchicalResult implem throw e; } } - + @Override public Collection<Relation<?>> getRelations() { return Collections.unmodifiableCollection(relations); @@ -152,15 +154,11 @@ public abstract class AbstractDatabase extends AbstractHierarchicalResult implem return (Relation<O>) relation; } } - if (getLogger().isDebugging()) { - StringBuffer buf = new StringBuffer(); - buf.append("No matching relation for type ").append(restriction.toString()).append(":\n"); - for(Relation<?> relation : relations) { - buf.append(relation.getDataTypeInformation().toString()).append(","); - } - getLogger().debug(buf); + List<TypeInformation> types = new ArrayList<TypeInformation>(relations.size()); + for(Relation<?> relation : relations) { + types.add(relation.getDataTypeInformation()); } - throw new NoSupportedDataTypeException(restriction); + throw new NoSupportedDataTypeException(restriction, types); } @Override diff --git a/src/de/lmu/ifi/dbs/elki/database/HashmapDatabase.java b/src/de/lmu/ifi/dbs/elki/database/HashmapDatabase.java index e94bcfb1..a92c4427 100644 --- a/src/de/lmu/ifi/dbs/elki/database/HashmapDatabase.java +++ b/src/de/lmu/ifi/dbs/elki/database/HashmapDatabase.java @@ -31,6 +31,7 @@ import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation; 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.DBIDIter; 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; @@ -62,7 +63,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter; * @author Erich Schubert * * @apiviz.landmark - * @apiviz.composedOf TreeSetModifiableDBIDs + * @apiviz.composedOf HashSetModifiableDBIDs */ @Description("Database using an in-memory hashtable and at least providing linear scans.") public class HashmapDatabase extends AbstractDatabase implements UpdatableDatabase, Parameterizable { @@ -246,13 +247,14 @@ public class HashmapDatabase extends AbstractDatabase implements UpdatableDataba MultipleObjectsBundle bundle = new MultipleObjectsBundle(); for(Relation<?> relation : relations) { ArrayList<Object> data = new ArrayList<Object>(ids.size()); - for(DBID id : ids) { - data.add(relation.get(id)); + for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { + data.add(relation.get(iter)); } bundle.appendColumn(relation.getDataTypeInformation(), data); } // remove from db - for(DBID id : ids) { + for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { + DBID id = iter.getDBID(); doDelete(id); } // Remove from indexes 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 8d7f73ce..a6d5a704 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/DataStore.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/DataStore.java @@ -24,6 +24,7 @@ package de.lmu.ifi.dbs.elki.database.datastore; */ import de.lmu.ifi.dbs.elki.database.ids.DBID; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; import de.lmu.ifi.dbs.elki.result.Result; /** @@ -40,5 +41,5 @@ public interface DataStore<T> extends Result { * @param id Database ID. * @return Object or {@code null} */ - public T get(DBID id); -} + public T get(DBIDRef id); +}
\ No newline at end of file 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 65a1265d..2ed9f536 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreFactory.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreFactory.java @@ -91,6 +91,38 @@ public interface DataStoreFactory { public WritableDoubleDataStore makeDoubleStorage(DBIDs ids, int hints); /** + * Make a new storage, to associate the given ids with an object of class + * dataclass. + * + * @param ids DBIDs to store data for + * @param hints Hints for the storage manager + * @param def Default value + * @return new data store + */ + public WritableDoubleDataStore makeDoubleStorage(DBIDs ids, int hints, double def); + + /** + * Make a new storage, to associate the given ids with an object of class + * dataclass. + * + * @param ids DBIDs to store data for + * @param hints Hints for the storage manager + * @return new data store + */ + public WritableIntegerDataStore makeIntegerStorage(DBIDs ids, int hints); + + /** + * Make a new storage, to associate the given ids with an object of class + * dataclass. + * + * @param ids DBIDs to store data for + * @param hints Hints for the storage manager + * @param def Default value + * @return new data store + */ + public WritableIntegerDataStore makeIntegerStorage(DBIDs ids, int hints, int def); + + /** * Make a new record storage, to associate the given ids with an object of * class dataclass. * 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 ead75709..dada881a 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreIDMap.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreIDMap.java @@ -23,7 +23,7 @@ package de.lmu.ifi.dbs.elki.database.datastore; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import de.lmu.ifi.dbs.elki.database.ids.DBID; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; /** * Interface to map DBIDs to integer record ids for use in storage. @@ -37,5 +37,5 @@ public interface DataStoreIDMap { * @param dbid DBID * @return record id {@code id >= 0} */ - public int map(DBID dbid); + public int map(DBIDRef dbid); } 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 f299c1e8..a8afeaec 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreUtil.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/DataStoreUtil.java @@ -59,6 +59,41 @@ public final class DataStoreUtil { } /** + * Make a new storage, to associate the given ids with an object of class dataclass. + * + * @param ids DBIDs to store data for + * @param hints Hints for the storage manager + * @param def Default value + * @return new data store + */ + public static WritableDoubleDataStore makeDoubleStorage(DBIDs ids, int hints, double def) { + return DataStoreFactory.FACTORY.makeDoubleStorage(ids, hints, def); + } + + /** + * Make a new storage, to associate the given ids with an object of class dataclass. + * + * @param ids DBIDs to store data for + * @param hints Hints for the storage manager + * @return new data store + */ + public static WritableIntegerDataStore makeIntegerStorage(DBIDs ids, int hints) { + return DataStoreFactory.FACTORY.makeIntegerStorage(ids, hints); + } + + /** + * Make a new storage, to associate the given ids with an object of class dataclass. + * + * @param ids DBIDs to store data for + * @param hints Hints for the storage manager + * @param def Default value + * @return new data store + */ + public static WritableIntegerDataStore makeIntegerStorage(DBIDs ids, int hints, int def) { + return DataStoreFactory.FACTORY.makeIntegerStorage(ids, hints, def); + } + + /** * Make a new record storage, to associate the given ids with an object of class dataclass. * * @param ids DBIDs to store data for 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 ee315a0c..3348a246 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/DoubleDataStore.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/DoubleDataStore.java @@ -1,7 +1,5 @@ package de.lmu.ifi.dbs.elki.database.datastore; -import de.lmu.ifi.dbs.elki.database.ids.DBID; - /* This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures @@ -25,14 +23,22 @@ import de.lmu.ifi.dbs.elki.database.ids.DBID; along with this program. If not, see <http://www.gnu.org/licenses/>. */ +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; + /** * Double-valued data store (avoids boxing/unboxing). * * @author Erich Schubert */ public interface DoubleDataStore extends DataStore<Double> { + /** + * Getter, but using objects. + * + * @deprecated Use {@link #doubleValue} instead, to avoid boxing/unboxing cost. + */ + @Override @Deprecated - public Double get(DBID id); + public Double get(DBIDRef id); /** * Retrieves an object from the storage. @@ -40,5 +46,5 @@ public interface DoubleDataStore extends DataStore<Double> { * @param id Database ID. * @return Double value */ - public double doubleValue(DBID id); + public double doubleValue(DBIDRef id); }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/IntegerDataStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/IntegerDataStore.java new file mode 100644 index 00000000..e450c11b --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/IntegerDataStore.java @@ -0,0 +1,50 @@ +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 + 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; + +/** + * Integer-valued data store (avoids boxing/unboxing). + * + * @author Erich Schubert + */ +public interface IntegerDataStore extends DataStore<Integer> { + /** + * Getter, but using objects. + * + * @deprecated Use {@link #intValue} instead, to avoid boxing/unboxing cost. + */ + @Override + @Deprecated + public Integer get(DBIDRef id); + + /** + * Retrieves an object from the storage. + * + * @param id Database ID. + * @return Double value + */ + public int intValue(DBIDRef id); +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/RangeIDMap.java b/src/de/lmu/ifi/dbs/elki/database/datastore/RangeIDMap.java index 7fc0ed7f..e00f9ff8 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/RangeIDMap.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/RangeIDMap.java @@ -23,8 +23,8 @@ package de.lmu.ifi.dbs.elki.database.datastore; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import de.lmu.ifi.dbs.elki.database.ids.DBID; import de.lmu.ifi.dbs.elki.database.ids.DBIDRange; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; /** * Mapping a static DBID range to storage IDs. @@ -47,7 +47,7 @@ public class RangeIDMap implements DataStoreIDMap { } @Override - public int map(DBID dbid) { + public int map(DBIDRef dbid) { return range.getOffset(dbid); } } 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 7f1fbf52..93176445 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDataStore.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDataStore.java @@ -23,7 +23,7 @@ package de.lmu.ifi.dbs.elki.database.datastore; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import de.lmu.ifi.dbs.elki.database.ids.DBID; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; /** * Writable data store. @@ -32,7 +32,7 @@ import de.lmu.ifi.dbs.elki.database.ids.DBID; * * @apiviz.landmark * - * @param <T> + * @param <T> Data type */ public interface WritableDataStore<T> extends DataStore<T> { /** @@ -44,7 +44,7 @@ public interface WritableDataStore<T> extends DataStore<T> { * @param value Value to store. * @return previous value */ - public T put(DBID id, T value); + public T put(DBIDRef id, T value); /** * Deallocate the storage, freeing the memory and notifies the registered @@ -58,5 +58,5 @@ public interface WritableDataStore<T> extends DataStore<T> { * * @param id Database ID. */ - public void delete(DBID id); + public void delete(DBIDRef id); } 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 313e4adc..19cc54c7 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDoubleDataStore.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/WritableDoubleDataStore.java @@ -1,7 +1,5 @@ package de.lmu.ifi.dbs.elki.database.datastore; -import de.lmu.ifi.dbs.elki.database.ids.DBID; - /* This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures @@ -25,15 +23,22 @@ import de.lmu.ifi.dbs.elki.database.ids.DBID; along with this program. If not, see <http://www.gnu.org/licenses/>. */ +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; + /** * Data store specialized for doubles. Avoids boxing/unboxing. * * @author Erich Schubert */ public interface WritableDoubleDataStore extends DoubleDataStore, WritableDataStore<Double> { + /** + * Setter, but using objects. + * + * @deprecated Use {@link #putDouble} instead, to avoid boxing/unboxing cost. + */ @Override @Deprecated - public Double put(DBID id, Double value); + public Double put(DBIDRef id, Double value); /** * Associates the specified value with the specified id in this storage. If @@ -44,7 +49,7 @@ public interface WritableDoubleDataStore extends DoubleDataStore, WritableDataSt * @param value Value to store. * @return previous value */ - public double putDouble(DBID id, double value); + public double putDouble(DBIDRef id, double value); /** * Associates the specified value with the specified id in this storage. If @@ -55,5 +60,5 @@ public interface WritableDoubleDataStore extends DoubleDataStore, WritableDataSt * @param value Value to store. * @return previous value */ - public double put(DBID id, double value); + public double put(DBIDRef id, double value); }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/database/datastore/WritableIntegerDataStore.java b/src/de/lmu/ifi/dbs/elki/database/datastore/WritableIntegerDataStore.java new file mode 100644 index 00000000..b8bf1348 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/WritableIntegerDataStore.java @@ -0,0 +1,64 @@ +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 + 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; + +/** + * Data store specialized for doubles. Avoids boxing/unboxing. + * + * @author Erich Schubert + */ +public interface WritableIntegerDataStore extends IntegerDataStore, WritableDataStore<Integer> { + /** + * Setter, but using objects. + * + * @deprecated Use {@link #putInt} instead, to avoid boxing/unboxing cost. + */ + @Override + @Deprecated + public Integer put(DBIDRef id, Integer value); + + /** + * Associates the specified value with the specified id in this storage. If + * the storage previously contained a value for the id, the previous value is + * replaced by the specified value. + * + * @param id Database ID. + * @param value Value to store. + * @return previous value + */ + public int putInt(DBIDRef id, int value); + + /** + * Associates the specified value with the specified id in this storage. If + * the storage previously contained a value for the id, the previous value is + * replaced by the specified value. + * + * @param id Database ID. + * @param value Value to store. + * @return previous value + */ + public int put(DBIDRef id, int value); +}
\ No newline at end of file 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 775d201b..0799fdfe 100644 --- a/src/de/lmu/ifi/dbs/elki/database/datastore/WritableRecordStore.java +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/WritableRecordStore.java @@ -23,7 +23,7 @@ package de.lmu.ifi.dbs.elki.database.datastore; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import de.lmu.ifi.dbs.elki.database.ids.DBID; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; /** * Represents a storage which stores multiple values per object in a record fashion. @@ -52,5 +52,5 @@ public interface WritableRecordStore extends RecordStore { * @param id object ID to remove * @return success code */ - public boolean remove(DBID id); + public boolean remove(DBIDRef id); } 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 433547a5..de22a6b3 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 @@ -23,9 +23,11 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory; along with this program. If not, see <http://www.gnu.org/licenses/>. */ +import java.util.Arrays; + import de.lmu.ifi.dbs.elki.database.datastore.DataStoreIDMap; import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore; -import de.lmu.ifi.dbs.elki.database.ids.DBID; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; /** * A class to answer representation queries using the stored Array. @@ -52,14 +54,28 @@ public class ArrayDoubleStore implements WritableDoubleDataStore { * @param idmap ID map */ public ArrayDoubleStore(int size, DataStoreIDMap idmap) { + this(size, idmap, Double.NaN); + } + + /** + * Constructor. + * + * @param size Size + * @param idmap ID map + * @param def Default value + */ + public ArrayDoubleStore(int size, DataStoreIDMap idmap, double def) { super(); this.data = new double[size]; + if(def != 0) { + Arrays.fill(this.data, def); + } this.idmap = idmap; } @Override @Deprecated - public Double get(DBID id) { + public Double get(DBIDRef id) { try { return data[idmap.map(id)]; } @@ -70,20 +86,20 @@ public class ArrayDoubleStore implements WritableDoubleDataStore { @Override @Deprecated - public Double put(DBID id, Double value) { + public Double put(DBIDRef id, Double value) { final int off = idmap.map(id); double ret = data[off]; data[off] = value; return ret; } - + @Override - public double doubleValue(DBID id) { + public double doubleValue(DBIDRef id) { return data[idmap.map(id)]; } @Override - public double putDouble(DBID id, double value) { + public double putDouble(DBIDRef id, double value) { final int off = idmap.map(id); final double ret = data[off]; data[off] = value; @@ -91,7 +107,7 @@ public class ArrayDoubleStore implements WritableDoubleDataStore { } @Override - public double put(DBID id, double value) { + public double put(DBIDRef id, double value) { final int off = idmap.map(id); final double ret = data[off]; data[off] = value; @@ -105,7 +121,7 @@ public class ArrayDoubleStore implements WritableDoubleDataStore { } @Override - public void delete(DBID id) { + public void delete(DBIDRef id) { throw new UnsupportedOperationException("Can't delete from a static array storage."); } 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 new file mode 100644 index 00000000..8caa7ec3 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/ArrayIntegerStore.java @@ -0,0 +1,137 @@ +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 + 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.datastore.DataStoreIDMap; +import de.lmu.ifi.dbs.elki.database.datastore.WritableIntegerDataStore; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; + +/** + * A class to answer representation queries using the stored Array. + * + * @author Erich Schubert + * + * @apiviz.composedOf de.lmu.ifi.dbs.elki.database.datastore.DataStoreIDMap + */ +public class ArrayIntegerStore implements WritableIntegerDataStore { + /** + * Data array + */ + private int[] data; + + /** + * DBID to index map + */ + private DataStoreIDMap idmap; + + /** + * Constructor. + * + * @param size Size + * @param idmap ID map + */ + public ArrayIntegerStore(int size, DataStoreIDMap idmap) { + this(size, idmap, 0); + } + + /** + * Constructor. + * + * @param size Size + * @param idmap ID map + * @param def Default value + */ + public ArrayIntegerStore(int size, DataStoreIDMap idmap, int def) { + super(); + this.data = new int[size]; + if (def != 0) { + Arrays.fill(this.data, def); + } + this.idmap = idmap; + } + + @Override + @Deprecated + public Integer get(DBIDRef id) { + try { + return data[idmap.map(id)]; + } + catch(ArrayIndexOutOfBoundsException e) { + return null; + } + } + + @Override + @Deprecated + public Integer put(DBIDRef id, Integer value) { + final int off = idmap.map(id); + int ret = data[off]; + data[off] = value; + return ret; + } + + @Override + public int intValue(DBIDRef id) { + return data[idmap.map(id)]; + } + + @Override + public int putInt(DBIDRef id, int value) { + final int off = idmap.map(id); + final int ret = data[off]; + data[off] = value; + return ret; + } + + @Override + public int put(DBIDRef id, int value) { + final int off = idmap.map(id); + final int ret = data[off]; + data[off] = value; + return ret; + } + + @Override + public void destroy() { + data = null; + idmap = null; + } + + @Override + public void delete(DBIDRef id) { + throw new UnsupportedOperationException("Can't delete from a static array storage."); + } + + @Override + public String getLongName() { + return "raw"; + } + + @Override + public String getShortName() { + return "raw"; + } +}
\ No newline at end of file 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 7be68c97..6e578b61 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 @@ -26,7 +26,7 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory; import de.lmu.ifi.dbs.elki.database.datastore.DataStoreIDMap; import de.lmu.ifi.dbs.elki.database.datastore.WritableDataStore; import de.lmu.ifi.dbs.elki.database.datastore.WritableRecordStore; -import de.lmu.ifi.dbs.elki.database.ids.DBID; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; /** * A class to answer representation queries using the stored Array. @@ -73,7 +73,7 @@ public class ArrayRecordStore implements WritableRecordStore { * @return current value */ @SuppressWarnings("unchecked") - protected <T> T get(DBID id, int index) { + protected <T> T get(DBIDRef id, int index) { try { return (T) data[idmap.map(id)][index]; } @@ -97,7 +97,7 @@ public class ArrayRecordStore implements WritableRecordStore { * @return old value */ @SuppressWarnings("unchecked") - protected <T> T set(DBID id, int index, T value) { + protected <T> T set(DBIDRef id, int index, T value) { T ret = (T) data[idmap.map(id)][index]; data[idmap.map(id)][index] = value; return ret; @@ -128,12 +128,12 @@ public class ArrayRecordStore implements WritableRecordStore { @SuppressWarnings("unchecked") @Override - public T get(DBID id) { + public T get(DBIDRef id) { return (T) ArrayRecordStore.this.get(id, index); } @Override - public T put(DBID id, T value) { + public T put(DBIDRef id, T value) { return ArrayRecordStore.this.set(id, index, value); } @@ -143,7 +143,7 @@ public class ArrayRecordStore implements WritableRecordStore { } @Override - public void delete(DBID id) { + public void delete(DBIDRef id) { throw new UnsupportedOperationException("ArrayStore record values cannot be deleted."); } @@ -159,7 +159,7 @@ public class ArrayRecordStore implements WritableRecordStore { } @Override - public boolean remove(DBID id) { + public boolean remove(DBIDRef id) { throw new UnsupportedOperationException("ArrayStore records cannot be removed."); } }
\ No newline at end of file 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 a41a444d..a7ce310b 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 @@ -25,7 +25,7 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory; import de.lmu.ifi.dbs.elki.database.datastore.DataStoreIDMap; import de.lmu.ifi.dbs.elki.database.datastore.WritableDataStore; -import de.lmu.ifi.dbs.elki.database.ids.DBID; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; /** * A class to answer representation queries using the stored Array. @@ -58,7 +58,7 @@ public class ArrayStore<T> implements WritableDataStore<T> { @SuppressWarnings("unchecked") @Override - public T get(DBID id) { + public T get(DBIDRef id) { try { return (T) data[idmap.map(id)]; } @@ -74,7 +74,7 @@ public class ArrayStore<T> implements WritableDataStore<T> { } @Override - public T put(DBID id, T value) { + public T put(DBIDRef id, T value) { T ret = get(id); data[idmap.map(id)] = value; return ret; @@ -87,7 +87,7 @@ public class ArrayStore<T> implements WritableDataStore<T> { } @Override - public void delete(DBID id) { + public void delete(DBIDRef id) { throw new UnsupportedOperationException("Can't delete from a static array storage."); } 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 ae06dc00..f9f8d48a 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 @@ -1,4 +1,5 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory; + /* This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures @@ -25,7 +26,7 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory; import gnu.trove.map.TIntDoubleMap; import gnu.trove.map.hash.TIntDoubleHashMap; import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore; -import de.lmu.ifi.dbs.elki.database.ids.DBID; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; /** * Writable data store for double values. @@ -37,25 +38,35 @@ public class MapIntegerDBIDDoubleStore implements WritableDoubleDataStore { * Data storage */ private TIntDoubleMap map; - + /** * Constructor. - * + * * @param size Expected size */ public MapIntegerDBIDDoubleStore(int size) { + this(size, Double.NaN); + } + + /** + * Constructor. + * + * @param size Expected size + * @param def Default value + */ + public MapIntegerDBIDDoubleStore(int size, double def) { super(); - map = new TIntDoubleHashMap(size, 0.5f, Integer.MIN_VALUE, Double.NaN); + map = new TIntDoubleHashMap(size, 0.5f, Integer.MIN_VALUE, def); } @Override @Deprecated - public Double get(DBID id) { + public Double get(DBIDRef id) { return map.get(id.getIntegerID()); } @Override - public double doubleValue(DBID id) { + public double doubleValue(DBIDRef id) { return map.get(id.getIntegerID()); } @@ -71,7 +82,7 @@ public class MapIntegerDBIDDoubleStore implements WritableDoubleDataStore { @Override @Deprecated - public Double put(DBID id, Double value) { + public Double put(DBIDRef id, Double value) { return map.put(id.getIntegerID(), value); } @@ -82,17 +93,17 @@ public class MapIntegerDBIDDoubleStore implements WritableDoubleDataStore { } @Override - public void delete(DBID id) { + public void delete(DBIDRef id) { map.remove(id.getIntegerID()); } @Override - public double putDouble(DBID id, double value) { + public double putDouble(DBIDRef id, double value) { return map.put(id.getIntegerID(), value); } @Override - public double put(DBID id, double value) { + public double put(DBIDRef id, double value) { return map.put(id.getIntegerID(), value); } } 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 new file mode 100644 index 00000000..f7aea633 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/datastore/memory/MapIntegerDBIDIntegerStore.java @@ -0,0 +1,109 @@ +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 + 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 gnu.trove.map.TIntIntMap; +import gnu.trove.map.hash.TIntIntHashMap; +import de.lmu.ifi.dbs.elki.database.datastore.WritableIntegerDataStore; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; + +/** + * Writable data store for double values. + * + * @author Erich Schubert + */ +public class MapIntegerDBIDIntegerStore implements WritableIntegerDataStore { + /** + * Data storage + */ + private TIntIntMap map; + + /** + * Constructor. + * + * @param size Expected size + */ + public MapIntegerDBIDIntegerStore(int size) { + this(size, 0); + } + + /** + * Constructor. + * + * @param size Expected size + * @param def Default value + */ + public MapIntegerDBIDIntegerStore(int size, int def) { + super(); + map = new TIntIntHashMap(size, 0.5f, Integer.MIN_VALUE, def); + } + + @Override + @Deprecated + public Integer get(DBIDRef id) { + return map.get(id.getIntegerID()); + } + + @Override + public int intValue(DBIDRef id) { + return map.get(id.getIntegerID()); + } + + @Override + public String getLongName() { + return "raw"; + } + + @Override + public String getShortName() { + return "raw"; + } + + @Override + @Deprecated + public Integer put(DBIDRef id, Integer value) { + return map.put(id.getIntegerID(), value); + } + + @Override + public void destroy() { + map.clear(); + map = null; + } + + @Override + public void delete(DBIDRef id) { + map.remove(id.getIntegerID()); + } + + @Override + public int putInt(DBIDRef id, int value) { + return map.put(id.getIntegerID(), value); + } + + @Override + public int put(DBIDRef id, int value) { + return map.put(id.getIntegerID(), value); + } +} 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 8272fb2e..805c6de3 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 @@ -27,7 +27,7 @@ import gnu.trove.map.TIntObjectMap; import gnu.trove.map.hash.TIntObjectHashMap; import de.lmu.ifi.dbs.elki.database.datastore.WritableDataStore; import de.lmu.ifi.dbs.elki.database.datastore.WritableRecordStore; -import de.lmu.ifi.dbs.elki.database.ids.DBID; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; /** * A class to answer representation queries using a map and an index within the @@ -93,7 +93,7 @@ public class MapIntegerDBIDRecordStore implements WritableRecordStore { * @return current value */ @SuppressWarnings("unchecked") - protected <T> T get(DBID id, int index) { + protected <T> T get(DBIDRef id, int index) { Object[] d = data.get(id.getIntegerID()); if(d == null) { return null; @@ -118,7 +118,7 @@ public class MapIntegerDBIDRecordStore implements WritableRecordStore { * @return previous value */ @SuppressWarnings("unchecked") - protected <T> T set(DBID id, int index, T value) { + protected <T> T set(DBIDRef id, int index, T value) { Object[] d = data.get(id.getIntegerID()); if(d == null) { d = new Object[rlen]; @@ -154,12 +154,12 @@ public class MapIntegerDBIDRecordStore implements WritableRecordStore { @SuppressWarnings("unchecked") @Override - public T get(DBID id) { + public T get(DBIDRef id) { return (T) MapIntegerDBIDRecordStore.this.get(id, index); } @Override - public T put(DBID id, T value) { + public T put(DBIDRef id, T value) { return MapIntegerDBIDRecordStore.this.set(id, index, value); } @@ -169,7 +169,7 @@ public class MapIntegerDBIDRecordStore implements WritableRecordStore { } @Override - public void delete(DBID id) { + public void delete(DBIDRef id) { throw new UnsupportedOperationException("Record storage values cannot be deleted."); } @@ -185,7 +185,7 @@ public class MapIntegerDBIDRecordStore implements WritableRecordStore { } @Override - public boolean remove(DBID id) { + public boolean remove(DBIDRef id) { return data.remove(id.getIntegerID()) != null; } }
\ No newline at end of file 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 4deb929d..e04027d0 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 @@ -26,7 +26,7 @@ package de.lmu.ifi.dbs.elki.database.datastore.memory; import gnu.trove.map.TIntObjectMap; import gnu.trove.map.hash.TIntObjectHashMap; import de.lmu.ifi.dbs.elki.database.datastore.WritableDataStore; -import de.lmu.ifi.dbs.elki.database.ids.DBID; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; /** * A class to answer representation queries using a map. Basically, it is just a @@ -70,12 +70,12 @@ public class MapIntegerDBIDStore<T> implements WritableDataStore<T> { } @Override - public T get(DBID id) { + public T get(DBIDRef id) { return data.get(id.getIntegerID()); } @Override - public T put(DBID id, T value) { + public T put(DBIDRef id, T value) { if(value == null) { return data.remove(id.getIntegerID()); } @@ -88,7 +88,7 @@ public class MapIntegerDBIDStore<T> implements WritableDataStore<T> { } @Override - public void delete(DBID id) { + public void delete(DBIDRef id) { data.remove(id.getIntegerID()); } 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 5a98966f..05cf3697 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 @@ -29,6 +29,7 @@ import java.util.concurrent.ConcurrentHashMap; import de.lmu.ifi.dbs.elki.database.datastore.WritableDataStore; import de.lmu.ifi.dbs.elki.database.datastore.WritableRecordStore; import de.lmu.ifi.dbs.elki.database.ids.DBID; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; /** * A class to answer representation queries using a map and an index within the @@ -47,6 +48,7 @@ public class MapRecordStore implements WritableRecordStore { /** * Storage Map */ + // TODO: Use trove maps? private final Map<DBID, Object[]> data; /** @@ -84,8 +86,8 @@ public class MapRecordStore implements WritableRecordStore { * @return current value */ @SuppressWarnings("unchecked") - protected <T> T get(DBID id, int index) { - Object[] d = data.get(id); + protected <T> T get(DBIDRef id, int index) { + Object[] d = data.get(id.getDBID()); if(d == null) { return null; } @@ -109,11 +111,11 @@ public class MapRecordStore implements WritableRecordStore { * @return previous value */ @SuppressWarnings("unchecked") - protected <T> T set(DBID id, int index, T value) { - Object[] d = data.get(id); + protected <T> T set(DBIDRef id, int index, T value) { + Object[] d = data.get(id.getDBID()); if(d == null) { d = new Object[rlen]; - data.put(id, d); + data.put(id.getDBID(), d); } T ret = (T) d[index]; d[index] = value; @@ -145,12 +147,12 @@ public class MapRecordStore implements WritableRecordStore { @SuppressWarnings("unchecked") @Override - public T get(DBID id) { + public T get(DBIDRef id) { return (T) MapRecordStore.this.get(id, index); } @Override - public T put(DBID id, T value) { + public T put(DBIDRef id, T value) { return MapRecordStore.this.set(id, index, value); } @@ -160,7 +162,7 @@ public class MapRecordStore implements WritableRecordStore { } @Override - public void delete(DBID id) { + public void delete(DBIDRef id) { throw new UnsupportedOperationException("Record storage values cannot be deleted."); } @@ -176,7 +178,7 @@ public class MapRecordStore implements WritableRecordStore { } @Override - public boolean remove(DBID id) { + public boolean remove(DBIDRef id) { return data.remove(id) != null; } 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 27cd9f63..90742993 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 @@ -28,6 +28,7 @@ import java.util.Map; import de.lmu.ifi.dbs.elki.database.datastore.WritableDataStore; import de.lmu.ifi.dbs.elki.database.ids.DBID; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; /** * A class to answer representation queries using a map. Basically, it is just a @@ -41,6 +42,7 @@ public class MapStore<T> implements WritableDataStore<T> { /** * Storage Map */ + // TODO: use trove maps? private Map<DBID, T> data; /** @@ -62,16 +64,16 @@ public class MapStore<T> implements WritableDataStore<T> { } @Override - public T get(DBID id) { - return data.get(id); + public T get(DBIDRef id) { + return data.get(id.getDBID()); } @Override - public T put(DBID id, T value) { + public T put(DBIDRef id, T value) { if(value == null) { - return data.remove(id); + return data.remove(id.getDBID()); } - return data.put(id, value); + return data.put(id.getDBID(), value); } @Override @@ -80,7 +82,7 @@ public class MapStore<T> implements WritableDataStore<T> { } @Override - public void delete(DBID id) { + public void delete(DBIDRef id) { data.remove(id); } 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 3e3ce017..683e4c5d 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 @@ -27,6 +27,7 @@ import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory; import de.lmu.ifi.dbs.elki.database.datastore.RangeIDMap; import de.lmu.ifi.dbs.elki.database.datastore.WritableDataStore; import de.lmu.ifi.dbs.elki.database.datastore.WritableDoubleDataStore; +import de.lmu.ifi.dbs.elki.database.datastore.WritableIntegerDataStore; import de.lmu.ifi.dbs.elki.database.datastore.WritableRecordStore; import de.lmu.ifi.dbs.elki.database.ids.DBIDRange; import de.lmu.ifi.dbs.elki.database.ids.DBIDs; @@ -47,8 +48,15 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDs; * @apiviz.uses MapRecordStore oneway - - «create» */ public class MemoryDataStoreFactory implements DataStoreFactory { + @SuppressWarnings("unchecked") @Override public <T> WritableDataStore<T> makeStorage(DBIDs ids, int hints, Class<? super T> dataclass) { + if (Double.class.equals(dataclass)) { + return (WritableDataStore<T>) makeDoubleStorage(ids, hints); + } + if (Integer.class.equals(dataclass)) { + return (WritableDataStore<T>) makeIntegerStorage(ids, hints); + } if(ids instanceof DBIDRange) { DBIDRange range = (DBIDRange) ids; Object[] data = new Object[range.size()]; @@ -71,6 +79,39 @@ public class MemoryDataStoreFactory implements DataStoreFactory { } @Override + public WritableDoubleDataStore makeDoubleStorage(DBIDs ids, int hints, double def) { + if(ids instanceof DBIDRange) { + DBIDRange range = (DBIDRange) ids; + return new ArrayDoubleStore(range.size(), new RangeIDMap(range), def); + } + else { + return new MapIntegerDBIDDoubleStore(ids.size(), def); + } + } + + @Override + public WritableIntegerDataStore makeIntegerStorage(DBIDs ids, int hints) { + if(ids instanceof DBIDRange) { + DBIDRange range = (DBIDRange) ids; + return new ArrayIntegerStore(range.size(), new RangeIDMap(range)); + } + else { + return new MapIntegerDBIDIntegerStore(ids.size()); + } + } + + @Override + public WritableIntegerDataStore makeIntegerStorage(DBIDs ids, int hints, int def) { + if(ids instanceof DBIDRange) { + DBIDRange range = (DBIDRange) ids; + return new ArrayIntegerStore(range.size(), new RangeIDMap(range), def); + } + else { + return new MapIntegerDBIDIntegerStore(ids.size(), def); + } + } + + @Override public WritableRecordStore makeRecordStorage(DBIDs ids, int hints, Class<?>... dataclasses) { if(ids instanceof DBIDRange) { DBIDRange range = (DBIDRange) ids; 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 13d6ea58..68bbb83d 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/ArrayDBIDs.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/ArrayDBIDs.java @@ -42,6 +42,7 @@ public interface ArrayDBIDs extends DBIDs { * * @return Iterator */ + @Override public DBIDIter iter(); /** @@ -49,6 +50,7 @@ public interface ArrayDBIDs extends DBIDs { * * @return size */ + @Override public int size(); /** @@ -61,5 +63,5 @@ public interface ArrayDBIDs extends DBIDs { * @param key Key to search for * @return Offset of key */ - public int binarySearch(DBID key); + public int binarySearch(DBIDRef key); } 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 e9a6c8e0..95bcc2f7 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/ArrayModifiableDBIDs.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/ArrayModifiableDBIDs.java @@ -59,4 +59,12 @@ public interface ArrayModifiableDBIDs extends ModifiableDBIDs, ArrayDBIDs { * @return previous value */ public DBID set(int i, DBID newval); + + /** + * Swap DBIDs add positions a and b. + * + * @param a First position + * @param b Second position + */ + public void swap(int a, int b); }
\ No newline at end of file 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 1391b75b..8d98893d 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/DBID.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/DBID.java @@ -37,11 +37,67 @@ package de.lmu.ifi.dbs.elki.database.ids; * * @apiviz.landmark */ -public interface DBID extends Comparable<DBID>, ArrayDBIDs { +public interface DBID extends DBIDRef, Comparable<DBIDRef>, ArrayDBIDs { /** - * Return the integer value of the object ID, if possible. + * Compare the <em>current</em> value of two referenced DBIDs. * - * @return integer id + * @param other Other DBID reference (or DBID) + * @return {@code true} when the references <em>currently</em> refer to the same. */ - public int getIntegerID(); + @Override + public boolean sameDBID(DBIDRef other); + + /** + * Compare two objects by the value of the referenced DBID. + * + * @param other Other DBID or object + * @return -1, 0 or +1 + */ + @Override + public int compareDBID(DBIDRef other); + + /** + * In contrast to {@link DBIDRef}, the DBID interface is supposed to have a + * stable hash code. However, it is generally preferred to use optimized + * storage classes instead of Java collections! + * + * @return hash code + */ + @Override + public int hashCode(); + + /** + * In contrast to {@link DBIDRef}, the DBID interface is supposed to have a + * stable equals for other DBIDs. + * + * Yet, {@link #sameDBID} is more type safe and explicit. + * + * @return true when the object is the same DBID. + */ + @Override + public boolean equals(Object obj); + + /** + * Part of the DBIDRef API, this <em>must</em> return {@code this} for an + * actual DBID. + * + * @return {@code this} + * @deprecated When the object is known to be a DBID, the usage of this method + * is pointless, therefore it is marked as deprecated to cause a + * warning. + */ + @Deprecated + @Override + public DBID getDBID(); + + /** + * Compare two DBIDs for ordering. + * + * Consider using {@link #compareDBID}, which is more explicit. + * + * @param other Other DBID object + * @return Comparison result + */ + @Override + public int compareTo(DBIDRef other); }
\ No newline at end of file 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 f35f390b..6063508b 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDFactory.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDFactory.java @@ -40,7 +40,7 @@ import de.lmu.ifi.dbs.elki.persistent.FixedSizeByteBufferSerializer; * @apiviz.uses DBIDRange oneway - - «create» * @apiviz.uses ArrayModifiableDBIDs oneway - - «create» * @apiviz.uses HashSetModifiableDBIDs oneway - - «create» - * @apiviz.uses TreeSetModifiableDBIDs oneway - - «create» + * @apiviz.uses HashSetModifiableDBIDs oneway - - «create» * @apiviz.has ByteBufferSerializer oneway - - provides */ public interface DBIDFactory { @@ -89,12 +89,12 @@ public interface DBIDFactory { /** * Make a DBID pair from two existing DBIDs. * - * @param first first DBID - * @param second second DBID + * @param id1 first DBID + * @param id2 second DBID * * @return new pair. */ - public DBIDPair makePair(DBID first, DBID second); + public DBIDPair makePair(DBIDRef id1, DBIDRef id2); /** * Make a new (modifiable) array of DBIDs. 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 a41284f4..f2d0ae91 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDIter.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDIter.java @@ -22,6 +22,9 @@ 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.Iter; + /** * Iterator for DBIDs. * @@ -30,11 +33,15 @@ package de.lmu.ifi.dbs.elki.database.ids; * with Java, but at the same time, the syntax is much more compatible with for * loops. * - * Usage example: <blockquote><code>{@code + * Usage example: + * + * <pre> + * {@code * for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { * iter.getDBID(); * } - * }</code></blockquote> + * } + * </pre> * * We list some fundamental differences. * <ul> @@ -47,33 +54,15 @@ package de.lmu.ifi.dbs.elki.database.ids; * * @author Erich Schubert */ -public interface DBIDIter { - /** - * Returns true if the iterator currently points to a valid object. - * - * @return a <code>boolean</code> value - */ - public boolean valid(); - +public interface DBIDIter extends DBIDRef, Iter { /** - * Moves the iterator forward to the next entry. + * Get the referenced {@link DBID}. * - * @throws java.util.NoSuchElementException if the iterator is already - * exhausted - */ - public void advance(); - - /** - * Return the integer value of the object ID, if possible. - * - * @return integer id - */ - public int getIntegerID(); - - /** - * Get the current DBID. + * Efficiency note: this may require materialization of a DBID object - if + * possible, use DBIDRef based APIs instead. * - * @return current DBID + * @return referenced DBID */ + @Override public DBID getDBID(); }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDMIter.java b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDMIter.java new file mode 100644 index 00000000..fe3b182c --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDMIter.java @@ -0,0 +1,38 @@ +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 + 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/>. + */ + +/** + * Modifiable DBID iterator. + * + * @author Erich Schubert + */ +public interface DBIDMIter extends DBIDIter { + /** + * Remove the object the iterator currently points to. + * + * Subsequent calls to {@link #getDBID} may return a different element. + * Call {@link #advance()} to advance the iterator to the next element for further processing. + */ + void remove(); +} 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 48a1f0ba..1b9ccc3b 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDRange.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDRange.java @@ -23,7 +23,6 @@ package de.lmu.ifi.dbs.elki.database.ids; along with this program. If not, see <http://www.gnu.org/licenses/>. */ - /** * Static DBID range. * @@ -39,5 +38,5 @@ public interface DBIDRange extends ArrayStaticDBIDs { * @param dbid ID to compute index for * @return index */ - public int getOffset(DBID dbid); + public int getOffset(DBIDRef dbid); }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDRef.java b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDRef.java new file mode 100644 index 00000000..0934b10b --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDRef.java @@ -0,0 +1,92 @@ +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 + 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/>. + */ + +/** + * Some object referencing a {@link DBID}. Could be a {@link DBID}, a + * {@link DBIDIter}, for example. + * + * Important note: <em>do not assume this reference to be stable</em>. Iterators + * are a good example how the DBIDRef may change. + * + * @author Erich Schubert + */ +public interface DBIDRef { + /** + * Get the referenced {@link DBID}. + * + * Efficiency note: this may require materialization of a DBID object. + * + * @return referenced DBID + */ + public DBID getDBID(); + + /** + * Return the integer value of the object ID, if possible. + * + * @return integer id + */ + public int getIntegerID(); + + /** + * WARNING: Hash codes of this interface <b>might not be stable</b> (e.g. for + * iterators). + * + * @return current hash code (<b>may change!</b>) + * + * @deprecated Do not use this hash code. Some implementations will not offer + * stable hash codes! + */ + @Override + @Deprecated + public int hashCode(); + + /** + * WARNING: calling equality on a reference may be an indicator of incorrect + * usage, as it is not clear whether the programmer meant the references to be + * the same or the DBIDs. + * + * @param obj Object to compare with + * @return True when they are the same object + */ + @Override + @Deprecated + public boolean equals(Object obj); + + /** + * Compare the <em>current</em> value of two referenced DBIDs. + * + * @param other Other DBID reference (or DBID) + * @return {@code true} when the references <em>currently</em> refer to the same. + */ + public boolean sameDBID(DBIDRef other); + + /** + * Compare two objects by the value of the referenced DBID. + * + * @param other Other DBID or object + * @return -1, 0 or +1 + */ + public int compareDBID(DBIDRef other); +}
\ No newline at end of file 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 cd2bd4e0..000659b9 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDUtil.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDUtil.java @@ -25,6 +25,7 @@ package de.lmu.ifi.dbs.elki.database.ids; import java.util.Random; +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.persistent.ByteBufferSerializer; @@ -185,15 +186,45 @@ public final class DBIDUtil { return intersection(second, first); } ModifiableDBIDs inter = newHashSet(first.size()); - for(DBID id : first) { - if(second.contains(id)) { - inter.add(id); + for(DBIDIter it = first.iter(); it.valid(); it.advance()) { + if(second.contains(it)) { + inter.add(it); } } return inter; } /** + * Compute the set symmetric intersection of two sets. + * + * @param first First set + * @param second Second set + * @param firstonly OUTPUT: elements only in first. MUST BE EMPTY + * @param intersection OUTPUT: elements in intersection. MUST BE EMPTY + * @param secondonly OUTPUT: elements only in second. MUST BE EMPTY + */ + // TODO: optimize? + public static void symmetricIntersection(DBIDs first, DBIDs second, HashSetModifiableDBIDs firstonly, HashSetModifiableDBIDs intersection, HashSetModifiableDBIDs secondonly) { + if(first.size() > second.size()) { + symmetricIntersection(second, first, secondonly, intersection, firstonly); + return; + } + assert(firstonly.size() == 0) : "OUTPUT set should be empty!"; + assert(intersection.size() == 0) : "OUTPUT set should be empty!"; + assert(secondonly.size() == 0) : "OUTPUT set should be empty!"; + // Initialize with second + secondonly.addDBIDs(second); + for(DBIDIter it = first.iter(); it.valid(); it.advance()) { + // Try to remove + if(secondonly.remove(it)) { + intersection.add(it); + } else { + firstonly.add(it); + } + } + } + + /** * Returns the union of the two specified collection of IDs. * * @param ids1 the first collection @@ -201,7 +232,7 @@ public final class DBIDUtil { * @return the union of ids1 and ids2 without duplicates */ public static ModifiableDBIDs union(DBIDs ids1, DBIDs ids2) { - ModifiableDBIDs result = DBIDUtil.newHashSet(); + ModifiableDBIDs result = DBIDUtil.newHashSet(Math.max(ids1.size(), ids2.size())); result.addDBIDs(ids1); result.addDBIDs(ids2); return result; @@ -215,8 +246,7 @@ public final class DBIDUtil { * @return the difference of ids1 minus ids2 */ public static ModifiableDBIDs difference(DBIDs ids1, DBIDs ids2) { - ModifiableDBIDs result = DBIDUtil.newHashSet(); - result.addDBIDs(ids1); + ModifiableDBIDs result = DBIDUtil.newHashSet(ids1); result.removeDBIDs(ids2); return result; } @@ -231,7 +261,11 @@ public final class DBIDUtil { if(existing instanceof StaticDBIDs) { return (StaticDBIDs) existing; } - return new UnmodifiableDBIDs(existing); + if (existing instanceof ArrayDBIDs) { + return new UnmodifiableArrayDBIDs((ArrayDBIDs)existing); + } else { + return new UnmodifiableDBIDs(existing); + } } /** @@ -293,7 +327,7 @@ public final class DBIDUtil { * * @return DBID pair */ - public static DBIDPair newPair(DBID id1, DBID id2) { + public static DBIDPair newPair(DBIDRef id1, DBIDRef id2) { return DBIDFactory.FACTORY.makePair(id1, id2); } @@ -319,7 +353,7 @@ public final class DBIDUtil { */ public static ModifiableDBIDs randomSample(DBIDs source, int k, Long seed) { if(k <= 0 || k > source.size()) { - throw new IllegalArgumentException("Illegal value for size of random sample: " + k); + throw new IllegalArgumentException("Illegal value for size of random sample: " + k+ " > "+source.size()+" or < 0"); } final Random random; if(seed != null) { 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 ef83ba69..e9a3e0ab 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/DBIDs.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/DBIDs.java @@ -32,18 +32,21 @@ import java.util.Iterator; * * @apiviz.landmark * @apiviz.composedOf DBID + * @apiviz.has DBIDIter */ public interface DBIDs extends Iterable<DBID> { /** - * Retrieve Iterator access to the IDs. + * Get a DBID iterator (a more efficient API). * - * @return an iterator for the IDs - */ - @Override - public Iterator<DBID> iterator(); - - /** - * Get a DBIDIterator (a more efficient API). + * usage example: + * + * <pre> + * {@code + * for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { + * DBID id = iter.getDBID(); + * } + * } + * </pre> * * @return iterator */ @@ -62,7 +65,7 @@ public interface DBIDs extends Iterable<DBID> { * @param o object to test * @return true when contained */ - public boolean contains(DBID o); + public boolean contains(DBIDRef o); /** * Test for an empty DBID collection. @@ -70,4 +73,13 @@ public interface DBIDs extends Iterable<DBID> { * @return true when empty. */ public boolean isEmpty(); + + /** + * Classic iterator. + * + * @deprecated Use {@link DBIDIter} API instead. + */ + @Override + @Deprecated + public Iterator<DBID> iterator(); } 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 5a7d6991..a85b8954 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/EmptyDBIDs.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/EmptyDBIDs.java @@ -26,12 +26,15 @@ package de.lmu.ifi.dbs.elki.database.ids; import java.util.Iterator; import java.util.NoSuchElementException; +import de.lmu.ifi.dbs.elki.logging.LoggingUtil; import de.lmu.ifi.dbs.elki.utilities.iterator.EmptyIterator; /** * Empty DBID collection. * * @author Erich Schubert + * + * @apiviz.composedOf EmptyDBIDIterator */ public class EmptyDBIDs implements ArrayStaticDBIDs, SetDBIDs { /** @@ -47,7 +50,7 @@ public class EmptyDBIDs implements ArrayStaticDBIDs, SetDBIDs { } @Override - public boolean contains(DBID o) { + public boolean contains(DBIDRef o) { return false; } @@ -77,7 +80,7 @@ public class EmptyDBIDs implements ArrayStaticDBIDs, SetDBIDs { } @Override - public int binarySearch(DBID key) { + public int binarySearch(DBIDRef key) { return -1; // Not found } @@ -106,5 +109,23 @@ public class EmptyDBIDs implements ArrayStaticDBIDs, SetDBIDs { public DBID getDBID() { throw new NoSuchElementException(); } + + @Override + public boolean equals(Object other) { + if (other instanceof DBID) { + LoggingUtil.warning("Programming error detected: DBIDItr.equals(DBID). Use sameDBID()!", new Throwable()); + } + return super.equals(other); + } + + @Override + public boolean sameDBID(DBIDRef other) { + return false; + } + + @Override + public int compareDBID(DBIDRef other) { + throw new UnsupportedOperationException("Invalid iterator position. Cannot compare."); + } } }
\ No newline at end of file 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 97646902..c92caef0 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/ModifiableDBIDs.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/ModifiableDBIDs.java @@ -54,17 +54,36 @@ public interface ModifiableDBIDs extends DBIDs { * * @param id ID to add */ - boolean add(DBID id); + boolean add(DBIDRef id); /** * Remove a single DBID from the collection. * * @param id ID to remove */ - boolean remove(DBID id); + boolean remove(DBIDRef id); /** * Clear this collection. */ void clear(); + + /** + * Get a <em>modifiable</em> DBID iterator (a more efficient API). + * + * usage example: + * + * <pre> + * {@code + * for(DBIDMIter iter = ids.iter(); iter.valid(); iter.advance()) { + * DBID id = iter.getDBID(); + * iter.remove(); + * } + * } + * </pre> + * + * @return modifiable iterator + */ + @Override + DBIDMIter iter(); }
\ 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 c517ea9f..91e307c2 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 @@ -1,10 +1,5 @@ package de.lmu.ifi.dbs.elki.database.ids.generic; -import java.util.Iterator; - -import de.lmu.ifi.dbs.elki.database.ids.DBID; -import de.lmu.ifi.dbs.elki.database.ids.DBIDIter; - /* This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures @@ -28,12 +23,18 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDIter; along with this program. If not, see <http://www.gnu.org/licenses/>. */ +import java.util.Iterator; + +import de.lmu.ifi.dbs.elki.database.ids.DBID; +import de.lmu.ifi.dbs.elki.database.ids.DBIDMIter; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; + /** * Iterator for classic collections. * * @author Erich Schubert */ -public class DBIDIterAdapter implements DBIDIter { +public class DBIDIterAdapter implements DBIDMIter { /** * Current DBID */ @@ -79,4 +80,21 @@ public class DBIDIterAdapter implements DBIDIter { public DBID getDBID() { return cur; } + + @Override + public void remove() { + iter.remove(); + } + + @Override + public boolean sameDBID(DBIDRef other) { + return cur.getIntegerID() == other.getIntegerID(); + } + + @Override + public int compareDBID(DBIDRef o) { + final int thisVal = cur.getIntegerID(); + final int anotherVal = o.getIntegerID(); + return (thisVal < anotherVal ? -1 : (thisVal == anotherVal ? 0 : 1)); + } }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/generic/GenericArrayModifiableDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/generic/GenericArrayModifiableDBIDs.java index f271180d..f02c5064 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/generic/GenericArrayModifiableDBIDs.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/generic/GenericArrayModifiableDBIDs.java @@ -30,6 +30,8 @@ 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.DBIDMIter; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; import de.lmu.ifi.dbs.elki.database.ids.DBIDs; /** @@ -80,7 +82,7 @@ public class GenericArrayModifiableDBIDs extends ArrayList<DBID> implements Arra public boolean addDBIDs(DBIDs ids) { super.ensureCapacity(size() + ids.size()); boolean changed = false; - for(DBID id : ids) { + for(DBIDIter id = ids.iter(); id.valid(); id.advance()) { changed |= add(id); } return changed; @@ -89,15 +91,20 @@ public class GenericArrayModifiableDBIDs extends ArrayList<DBID> implements Arra @Override public boolean removeDBIDs(DBIDs ids) { boolean changed = false; - for(DBID id : ids) { + for(DBIDIter id = ids.iter(); id.valid(); id.advance()) { changed |= super.remove(id); } return changed; } @Override - public boolean remove(DBID id) { - return super.remove(id); + public boolean add(DBIDRef id) { + return add(id.getDBID()); + } + + @Override + public boolean remove(DBIDRef id) { + return super.remove(id.getDBID()); } @Override @@ -111,17 +118,22 @@ public class GenericArrayModifiableDBIDs extends ArrayList<DBID> implements Arra } @Override - public DBIDIter iter() { + public DBIDMIter iter() { return new DBIDIterAdapter(iterator()); } @Override - public int binarySearch(DBID key) { - return Collections.binarySearch(this, key); + public int binarySearch(DBIDRef key) { + return Collections.binarySearch(this, key.getDBID()); } @Override - public boolean contains(DBID o) { + public boolean contains(DBIDRef o) { return super.contains(o); } + + @Override + public void swap(int a, int b) { + set(a, set(b, get(a))); + } }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/database/ids/generic/GenericHashSetModifiableDBIDs.java b/src/de/lmu/ifi/dbs/elki/database/ids/generic/GenericHashSetModifiableDBIDs.java index 31a8602c..6eadf0b1 100644 --- a/src/de/lmu/ifi/dbs/elki/database/ids/generic/GenericHashSetModifiableDBIDs.java +++ b/src/de/lmu/ifi/dbs/elki/database/ids/generic/GenericHashSetModifiableDBIDs.java @@ -24,10 +24,11 @@ package de.lmu.ifi.dbs.elki.database.ids.generic; */ import java.util.HashSet; -import java.util.Iterator; 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.DBIDMIter; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; import de.lmu.ifi.dbs.elki.database.ids.DBIDs; import de.lmu.ifi.dbs.elki.database.ids.HashSetModifiableDBIDs; @@ -72,7 +73,7 @@ public class GenericHashSetModifiableDBIDs extends HashSet<DBID> implements Hash */ public GenericHashSetModifiableDBIDs(DBIDs c) { super(c.size()); - for(DBID id : c) { + for(DBIDIter id = c.iter(); id.valid(); id.advance()) { add(id); } } @@ -80,7 +81,7 @@ public class GenericHashSetModifiableDBIDs extends HashSet<DBID> implements Hash @Override public boolean addDBIDs(DBIDs ids) { boolean changed = false; - for(DBID id : ids) { + for(DBIDIter id = ids.iter(); id.valid(); id.advance()) { changed |= add(id); } return changed; @@ -89,23 +90,27 @@ public class GenericHashSetModifiableDBIDs extends HashSet<DBID> implements Hash @Override public boolean removeDBIDs(DBIDs ids) { boolean changed = false; - for(DBID id : ids) { + for(DBIDIter id = ids.iter(); id.valid(); id.advance()) { changed |= super.remove(id); } return changed; } @Override - public boolean remove(DBID id) { - return super.remove(id); + public boolean add(DBIDRef id) { + return super.add(id.getDBID()); + } + + @Override + public boolean remove(DBIDRef id) { + return super.remove(id.getDBID()); } @Override public boolean retainAll(DBIDs ids) { boolean modified = false; - Iterator<DBID> it = iterator(); - while(it.hasNext()) { - if(!ids.contains(it.next())) { + for(DBIDMIter it = iter(); it.valid(); it.advance()) { + if(!ids.contains(it)) { it.remove(); modified = true; } @@ -114,12 +119,12 @@ public class GenericHashSetModifiableDBIDs extends HashSet<DBID> implements Hash } @Override - public DBIDIter iter() { + public DBIDMIter iter() { return new DBIDIterAdapter(iterator()); } @Override - public boolean contains(DBID o) { + public boolean contains(DBIDRef o) { return super.contains(o); } }
\ No newline at end of file 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 67c84290..13a6cc21 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 @@ -29,6 +29,7 @@ import java.util.Iterator; 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; import de.lmu.ifi.dbs.elki.database.ids.DBIDs; /** @@ -36,7 +37,7 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDs; * * @author Erich Schubert * - * @apiviz.uses de.lmu.ifi.dbs.elki.database.ids.DBIDs + * @apiviz.uses DBIDs */ public class MaskedDBIDs implements DBIDs { /** @@ -99,10 +100,10 @@ public class MaskedDBIDs implements DBIDs { } @Override - public boolean contains(DBID o) { + public boolean contains(DBIDRef o) { // TODO: optimize. for(DBID id : this) { - if(id.equals(o)) { + if(id.sameDBID(o)) { return true; } } @@ -191,6 +192,18 @@ public class MaskedDBIDs implements DBIDs { public DBID getDBID() { return data.get(pos); } + + @Override + public boolean sameDBID(DBIDRef other) { + return getIntegerID() == other.getIntegerID(); + } + + @Override + public int compareDBID(DBIDRef o) { + final int thisVal = getIntegerID(); + final int anotherVal = o.getIntegerID(); + return (thisVal < anotherVal ? -1 : (thisVal == anotherVal ? 0 : 1)); + } } /** @@ -253,7 +266,7 @@ public class MaskedDBIDs implements DBIDs { @Override public boolean valid() { - return pos >= 0; + return (pos >= 0) && (pos < data.size()); } @Override @@ -270,5 +283,17 @@ public class MaskedDBIDs implements DBIDs { public DBID getDBID() { return data.get(pos); } + + @Override + public boolean sameDBID(DBIDRef other) { + return getIntegerID() == other.getIntegerID(); + } + + @Override + public int compareDBID(DBIDRef o) { + final int thisVal = getIntegerID(); + final int anotherVal = o.getIntegerID(); + return (thisVal < anotherVal ? -1 : (thisVal == anotherVal ? 0 : 1)); + } } -} +}
\ No newline at end of file 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 97743867..16d83a56 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 @@ -27,6 +27,7 @@ import java.util.Iterator; 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.DBIDs; import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException; @@ -79,7 +80,7 @@ public class MergedDBIDs implements DBIDs { } @Override - public boolean contains(DBID o) { + public boolean contains(DBIDRef o) { for(DBIDs child : childs) { if(child.contains(o)) { return true; 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 new file mode 100644 index 00000000..35b092c2 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/ids/generic/UnmodifiableArrayDBIDs.java @@ -0,0 +1,101 @@ +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 + 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.Iterator; + +import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs; +import de.lmu.ifi.dbs.elki.database.ids.ArrayStaticDBIDs; +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.utilities.iterator.UnmodifiableIterator; + +/** + * Unmodifiable wrapper for DBIDs. + * + * @author Erich Schubert + * + * @apiviz.uses de.lmu.ifi.dbs.elki.database.ids.DBIDs + */ +public class UnmodifiableArrayDBIDs implements ArrayStaticDBIDs { + /** + * The DBIDs we wrap. + */ + final private ArrayDBIDs inner; + + /** + * Constructor. + * + * @param inner Inner DBID collection. + */ + public UnmodifiableArrayDBIDs(ArrayDBIDs inner) { + super(); + this.inner = inner; + } + + @Override + public boolean contains(DBIDRef o) { + return inner.contains(o); + } + + @Override + public boolean isEmpty() { + return inner.isEmpty(); + } + + @SuppressWarnings("deprecation") + @Override + public Iterator<DBID> iterator() { + return new UnmodifiableIterator<DBID>(inner.iterator()); + } + + @Override + public DBIDIter iter() { + return inner.iter(); + } + + @Override + public int size() { + return inner.size(); + } + + /** + * Returns a string representation of the inner DBID collection. + */ + @Override + public String toString() { + return inner.toString(); + } + + @Override + public DBID get(int i) { + return inner.get(i); + } + + @Override + public int binarySearch(DBIDRef key) { + return inner.binarySearch(key); + } +}
\ No newline at end of file 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 bd68e2fb..682b2e4b 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 @@ -27,6 +27,7 @@ import java.util.Iterator; 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.DBIDs; import de.lmu.ifi.dbs.elki.database.ids.StaticDBIDs; import de.lmu.ifi.dbs.elki.utilities.iterator.UnmodifiableIterator; @@ -55,7 +56,7 @@ public class UnmodifiableDBIDs implements StaticDBIDs { } @Override - public boolean contains(DBID o) { + public boolean contains(DBIDRef o) { return inner.contains(o); } @@ -64,6 +65,7 @@ public class UnmodifiableDBIDs implements StaticDBIDs { return inner.isEmpty(); } + @SuppressWarnings("deprecation") @Override public Iterator<DBID> iterator() { return new UnmodifiableIterator<DBID>(inner.iterator()); 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 ef4aee94..90ab5a6a 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 @@ -31,6 +31,8 @@ import de.lmu.ifi.dbs.elki.database.ids.ArrayStaticDBIDs; 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.DBIDIter; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; +import de.lmu.ifi.dbs.elki.logging.LoggingUtil; /** * Static (no modifications allowed) set of Database Object IDs. @@ -123,6 +125,24 @@ public class IntegerArrayStaticDBIDs extends AbstractList<DBID> implements Array return new IntegerDBID(ids[pos]); } + @Override + public boolean sameDBID(DBIDRef other) { + return ids[pos] == other.getIntegerID(); + } + + @Override + public boolean equals(Object other) { + if (other instanceof DBID) { + LoggingUtil.warning("Programming error detected: DBIDItr.equals(DBID). Use sameDBID()!", new Throwable()); + } + return super.equals(other); + } + + @Override + public int compareDBID(DBIDRef o) { + int anotherVal = o.getIntegerID(); + return (ids[pos] < anotherVal ? -1 : (ids[pos] == anotherVal ? 0 : 1)); + } } @Override @@ -131,7 +151,7 @@ public class IntegerArrayStaticDBIDs extends AbstractList<DBID> implements Array } @Override - public boolean contains(DBID o) { + public boolean contains(DBIDRef o) { final int oid = o.getIntegerID(); for(int i = 0; i < ids.length; i++) { if(ids[i] == oid) { @@ -164,7 +184,7 @@ public class IntegerArrayStaticDBIDs extends AbstractList<DBID> implements Array } @Override - public int binarySearch(DBID key) { + public int binarySearch(DBIDRef key) { return Arrays.binarySearch(ids, key.getIntegerID()); } }
\ 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 f9e83294..66c1f980 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 @@ -28,6 +28,8 @@ import java.util.Iterator; 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.logging.LoggingUtil; import de.lmu.ifi.dbs.elki.persistent.ByteArrayUtil; import de.lmu.ifi.dbs.elki.persistent.ByteBufferSerializer; import de.lmu.ifi.dbs.elki.persistent.FixedSizeByteBufferSerializer; @@ -49,7 +51,7 @@ import de.lmu.ifi.dbs.elki.persistent.FixedSizeByteBufferSerializer; * @apiviz.composedOf DynamicSerializer * @apiviz.composedOf StaticSerializer */ -class IntegerDBID implements DBID { +final class IntegerDBID implements DBID { /** * The actual object ID. */ @@ -75,6 +77,11 @@ class IntegerDBID implements DBID { this.id = id; } + @Override + public DBID getDBID() { + return this; + } + /** * Return the integer value of the object ID. * @@ -98,14 +105,29 @@ class IntegerDBID implements DBID { @Override public boolean equals(Object obj) { if(!(obj instanceof IntegerDBID)) { + if (obj instanceof DBIDRef) { + LoggingUtil.warning("Programming error: DBID.equals(DBIDRef) is not well-defined. use sameDBID!", new Throwable()); + } return false; } IntegerDBID other = (IntegerDBID) obj; return this.id == other.id; } + + @Override + public boolean sameDBID(DBIDRef other) { + return this.id == other.getIntegerID(); + } @Override - public int compareTo(DBID o) { + public int compareTo(DBIDRef o) { + int thisVal = this.id; + int anotherVal = o.getIntegerID(); + return (thisVal < anotherVal ? -1 : (thisVal == anotherVal ? 0 : 1)); + } + + @Override + public int compareDBID(DBIDRef o) { int thisVal = this.id; int anotherVal = o.getIntegerID(); return (thisVal < anotherVal ? -1 : (thisVal == anotherVal ? 0 : 1)); @@ -130,7 +152,7 @@ class IntegerDBID implements DBID { } @Override - public boolean contains(DBID o) { + public boolean contains(DBIDRef o) { return o.getIntegerID() == id; } @@ -140,8 +162,8 @@ class IntegerDBID implements DBID { } @Override - public int binarySearch(DBID key) { - return equals(key) ? 0 : -1; + public int binarySearch(DBIDRef key) { + return (id == key.getIntegerID()) ? 0 : -1; } /** @@ -207,6 +229,25 @@ class IntegerDBID implements DBID { public boolean valid() { return first; } + + @Override + public boolean equals(Object other) { + if (other instanceof DBID) { + LoggingUtil.warning("Programming error detected: DBIDItr.equals(DBID). Use sameDBID()!", new Throwable()); + } + return super.equals(other); + } + + @Override + public boolean sameDBID(DBIDRef other) { + return id == other.getIntegerID(); + } + + @Override + public int compareDBID(DBIDRef o) { + int anotherVal = o.getIntegerID(); + return (id < anotherVal ? -1 : (id == anotherVal ? 0 : 1)); + } } @Override 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 debe39a4..cad771d9 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 @@ -30,6 +30,7 @@ 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.DBIDIter; import de.lmu.ifi.dbs.elki.database.ids.DBIDRange; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; /** * Representing a DBID range allocation @@ -134,10 +135,25 @@ class IntegerDBIDRange extends AbstractList<DBID> implements DBIDRange { return new IntegerDBID(start + pos); } + @Override + public boolean equals(Object other) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean sameDBID(DBIDRef other) { + return start + pos == other.getIntegerID(); + } + + @Override + public int compareDBID(DBIDRef o) { + int anotherVal = o.getIntegerID(); + return (start + pos < anotherVal ? -1 : (start + pos == anotherVal ? 0 : 1)); + } } @Override - public boolean contains(DBID o) { + public boolean contains(DBIDRef o) { int oid = o.getIntegerID(); if(oid < start) { return false; @@ -180,12 +196,12 @@ class IntegerDBIDRange extends AbstractList<DBID> implements DBIDRange { * @return array offset */ @Override - public int getOffset(DBID dbid) { + public int getOffset(DBIDRef dbid) { return dbid.getIntegerID() - start; } @Override - public int binarySearch(DBID key) { + public int binarySearch(DBIDRef key) { int keyid = key.getIntegerID(); if(keyid < start) { return -1; 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 59fa34b5..8003e4ae 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 @@ -28,6 +28,7 @@ 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.DBIDs; import de.lmu.ifi.dbs.elki.database.ids.HashSetModifiableDBIDs; import de.lmu.ifi.dbs.elki.persistent.ByteBufferSerializer; @@ -132,7 +133,7 @@ public class SimpleDBIDFactory implements DBIDFactory { } @Override - public DBIDPair makePair(DBID first, DBID second) { + public DBIDPair makePair(DBIDRef first, DBIDRef second) { return new IntegerDBIDPair(first.getIntegerID(), second.getIntegerID()); } 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 b38286fe..80f65f29 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 @@ -30,6 +30,7 @@ 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.DBIDs; import de.lmu.ifi.dbs.elki.database.ids.HashSetModifiableDBIDs; import de.lmu.ifi.dbs.elki.persistent.ByteBufferSerializer; @@ -130,7 +131,7 @@ public class TrivialDBIDFactory implements DBIDFactory { } @Override - public DBIDPair makePair(DBID first, DBID second) { + public DBIDPair makePair(DBIDRef first, DBIDRef second) { return new IntegerDBIDPair(first.getIntegerID(), second.getIntegerID()); } 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 a060c6b8..e2bfbcd5 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 @@ -29,7 +29,9 @@ import java.util.Iterator; 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.DBIDMIter; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; +import de.lmu.ifi.dbs.elki.logging.LoggingUtil; /** * Abstract base class for GNU Trove array based lists. @@ -53,7 +55,7 @@ public abstract class TroveArrayDBIDs implements ArrayDBIDs { } @Override - public DBIDIter iter() { + public DBIDMIter iter() { return new DBIDItr(getStore()); } @@ -73,12 +75,12 @@ public abstract class TroveArrayDBIDs implements ArrayDBIDs { } @Override - public boolean contains(DBID o) { + public boolean contains(DBIDRef o) { return getStore().contains(o.getIntegerID()); } @Override - public int binarySearch(DBID key) { + public int binarySearch(DBIDRef key) { return getStore().binarySearch(key.getIntegerID()); } @@ -89,7 +91,7 @@ public abstract class TroveArrayDBIDs implements ArrayDBIDs { * * @apiviz.exclude */ - protected static class DBIDItr implements DBIDIter { + protected static class DBIDItr implements DBIDMIter { /** * Current position */ @@ -129,5 +131,31 @@ public abstract class TroveArrayDBIDs implements ArrayDBIDs { public DBID getDBID() { return new IntegerDBID(store.get(pos)); } + + @Override + public void remove() { + store.removeAt(pos); + pos--; + } + + @Override + public boolean sameDBID(DBIDRef other) { + return store.get(pos) == other.getIntegerID(); + } + + @Override + public boolean equals(Object other) { + if (other instanceof DBID) { + LoggingUtil.warning("Programming error detected: DBIDItr.equals(DBID). Use sameDBID()!", new Throwable()); + } + return super.equals(other); + } + + @Override + public int compareDBID(DBIDRef o) { + final int thisVal = store.get(pos); + final int anotherVal = o.getIntegerID(); + return (thisVal < anotherVal ? -1 : (thisVal == anotherVal ? 0 : 1)); + } } }
\ No newline at end of file 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 abcbba14..379ea8a6 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 @@ -31,6 +31,7 @@ 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.DBIDs; /** @@ -96,12 +97,12 @@ class TroveArrayModifiableDBIDs extends TroveArrayDBIDs implements ArrayModifiab } @Override - public boolean add(DBID e) { + public boolean add(DBIDRef e) { return store.add(e.getIntegerID()); } @Override - public boolean remove(DBID o) { + public boolean remove(DBIDRef o) { return store.remove(o.getIntegerID()); } @@ -141,4 +142,9 @@ class TroveArrayModifiableDBIDs extends TroveArrayDBIDs implements ArrayModifiab store.set(i, data[i].getIntegerID()); } } + + @Override + public void swap(int a, int b) { + store.set(a, store.set(b, store.get(a))); + } }
\ No newline at end of file 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 11fe669c..12656f7b 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 @@ -7,6 +7,8 @@ import gnu.trove.impl.hash.TIntHash; import gnu.trove.set.hash.TIntHashSet; 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.DBIDMIter; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; import de.lmu.ifi.dbs.elki.database.ids.DBIDs; import de.lmu.ifi.dbs.elki.database.ids.HashSetModifiableDBIDs; @@ -76,7 +78,7 @@ class TroveHashSetModifiableDBIDs implements HashSetModifiableDBIDs { } @Override - public DBIDIter iter() { + public DBIDMIter iter() { return new DBIDItr(store); } @@ -99,12 +101,12 @@ class TroveHashSetModifiableDBIDs implements HashSetModifiableDBIDs { } @Override - public boolean add(DBID e) { + public boolean add(DBIDRef e) { return store.add(e.getIntegerID()); } @Override - public boolean remove(DBID o) { + public boolean remove(DBIDRef o) { return store.remove(o.getIntegerID()); } @@ -142,7 +144,7 @@ class TroveHashSetModifiableDBIDs implements HashSetModifiableDBIDs { } @Override - public boolean contains(DBID o) { + public boolean contains(DBIDRef o) { return store.contains(o.getIntegerID()); } @@ -153,7 +155,7 @@ class TroveHashSetModifiableDBIDs implements HashSetModifiableDBIDs { * * @apiviz.exclude */ - protected static class DBIDItr extends THashPrimitiveIterator implements DBIDIter { + protected static class DBIDItr extends THashPrimitiveIterator implements DBIDMIter { /** * The has we access */ @@ -189,5 +191,17 @@ class TroveHashSetModifiableDBIDs implements HashSetModifiableDBIDs { public DBID getDBID() { return new IntegerDBID(hash._set[_index]); } + + @Override + public boolean sameDBID(DBIDRef other) { + return getIntegerID() == other.getIntegerID(); + } + + @Override + public int compareDBID(DBIDRef o) { + final int thisVal = hash._set[_index]; + final int anotherVal = o.getIntegerID(); + return (thisVal < anotherVal ? -1 : (thisVal == anotherVal ? 0 : 1)); + } } }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/database/query/DistanceDBIDResult.java b/src/de/lmu/ifi/dbs/elki/database/query/DistanceDBIDResult.java new file mode 100644 index 00000000..ead3eebc --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/query/DistanceDBIDResult.java @@ -0,0 +1,41 @@ +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 + 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.List; + +import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; + +/** + * Collection of objects and their distances. + * + * @author Erich Schubert + * + * @apiviz.composedOf DistanceResultPair + * + * @param <D> Distance type + */ +public interface DistanceDBIDResult<D extends Distance<D>> extends List<DistanceResultPair<D>> { + // Empty. TODO: add "sorted" property? +} diff --git a/src/de/lmu/ifi/dbs/elki/database/query/DistanceResultPair.java b/src/de/lmu/ifi/dbs/elki/database/query/DistanceResultPair.java index e7403628..b6cc129b 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/DistanceResultPair.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/DistanceResultPair.java @@ -24,6 +24,7 @@ package de.lmu.ifi.dbs.elki.database.query; */ import de.lmu.ifi.dbs.elki.database.ids.DBID; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; import de.lmu.ifi.dbs.elki.utilities.pairs.PairInterface; @@ -35,7 +36,7 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.PairInterface; * * @param <D> Distance type */ -public interface DistanceResultPair<D extends Distance<?>> extends PairInterface<D, DBID>, Comparable<DistanceResultPair<D>> { +public interface DistanceResultPair<D extends Distance<?>> extends PairInterface<D, DBID>, Comparable<DistanceResultPair<D>>, DBIDRef { /** * Getter for first * @@ -51,13 +52,6 @@ public interface DistanceResultPair<D extends Distance<?>> extends PairInterface public void setDistance(D first); /** - * Getter for second element in pair - * - * @return second element in pair - */ - public DBID getDBID(); - - /** * Setter for second * * @param second new value for second element diff --git a/src/de/lmu/ifi/dbs/elki/database/query/DoubleDistanceResultPair.java b/src/de/lmu/ifi/dbs/elki/database/query/DoubleDistanceResultPair.java index e0be7c40..23abc327 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/DoubleDistanceResultPair.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/DoubleDistanceResultPair.java @@ -24,6 +24,7 @@ package de.lmu.ifi.dbs.elki.database.query; */ import de.lmu.ifi.dbs.elki.database.ids.DBID; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; /** @@ -71,6 +72,21 @@ public class DoubleDistanceResultPair implements DistanceResultPair<DoubleDistan } @Override + public int getIntegerID() { + return id.getIntegerID(); + } + + @Override + public boolean sameDBID(DBIDRef other) { + return id.sameDBID(other); + } + + @Override + public int compareDBID(DBIDRef other) { + return id.compareDBID(other); + } + + @Override public void setID(DBID id) { this.id = id; } @@ -127,10 +143,10 @@ public class DoubleDistanceResultPair implements DistanceResultPair<DoubleDistan } if(obj instanceof DoubleDistanceResultPair) { DoubleDistanceResultPair ddrp = (DoubleDistanceResultPair) obj; - return distance == ddrp.distance && id.equals(ddrp.id); + return distance == ddrp.distance && id.sameDBID(ddrp.id); } DistanceResultPair<?> other = (DistanceResultPair<?>) obj; - return other.getDistance().equals(distance) && id.equals(other.getDBID()); + return other.getDistance().equals(distance) && id.sameDBID(other.getDBID()); } /** diff --git a/src/de/lmu/ifi/dbs/elki/database/query/GenericDistanceDBIDList.java b/src/de/lmu/ifi/dbs/elki/database/query/GenericDistanceDBIDList.java new file mode 100644 index 00000000..2283c401 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/database/query/GenericDistanceDBIDList.java @@ -0,0 +1,68 @@ +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 + 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.Collection; + +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>> extends ArrayList<DistanceResultPair<D>> implements DistanceDBIDResult<D> { + /** + * Serialization Version + */ + private static final long serialVersionUID = 1L; + + /** + * Constructor. + */ + public GenericDistanceDBIDList() { + super(); + } + + /** + * Constructor. + * + * @param c existing collection + */ + public GenericDistanceDBIDList(Collection<? extends DistanceResultPair<D>> c) { + super(c); + } + + /** + * Constructor. + * + * @param initialCapacity Capacity + */ + public GenericDistanceDBIDList(int initialCapacity) { + super(initialCapacity); + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/database/query/GenericDistanceResultPair.java b/src/de/lmu/ifi/dbs/elki/database/query/GenericDistanceResultPair.java index 4b838560..414f145a 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/GenericDistanceResultPair.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/GenericDistanceResultPair.java @@ -24,6 +24,7 @@ package de.lmu.ifi.dbs.elki.database.query; */ import de.lmu.ifi.dbs.elki.database.ids.DBID; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; import de.lmu.ifi.dbs.elki.utilities.pairs.Pair; @@ -74,6 +75,21 @@ public class GenericDistanceResultPair<D extends Distance<D>> extends Pair<D, DB public final DBID getDBID() { return second; } + + @Override + public int getIntegerID() { + return second.getIntegerID(); + } + + @Override + public boolean sameDBID(DBIDRef other) { + return second.sameDBID(other); + } + + @Override + public int compareDBID(DBIDRef other) { + return second.compareDBID(other); + } /** * Setter for second @@ -105,7 +121,7 @@ public class GenericDistanceResultPair<D extends Distance<D>> extends Pair<D, DB return false; } DistanceResultPair<?> other = (DistanceResultPair<?>) obj; - return first.equals(other.getDistance()) && second.equals(other.getDBID()); + return first.equals(other.getDistance()) && second.sameDBID(other.getDBID()); } @Override 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 92c116e3..ed1ee50c 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 @@ -24,6 +24,7 @@ package de.lmu.ifi.dbs.elki.database.query.distance; */ import de.lmu.ifi.dbs.elki.database.ids.DBID; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; @@ -46,7 +47,7 @@ public abstract class AbstractDatabaseDistanceQuery<O, D extends Distance<D>> ex } @Override - public D distance(O o1, DBID id2) { + public D distance(O o1, DBIDRef id2) { if(o1 instanceof DBID) { return distance((DBID) o1, id2); } @@ -54,7 +55,7 @@ public abstract class AbstractDatabaseDistanceQuery<O, D extends Distance<D>> ex } @Override - public D distance(DBID id1, O o2) { + public D distance(DBIDRef id1, O o2) { if(o2 instanceof DBID) { return distance(id1, (DBID) o2); } 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 10dde0ad..b85ddef0 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 @@ -23,7 +23,7 @@ package de.lmu.ifi.dbs.elki.database.query.distance; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import de.lmu.ifi.dbs.elki.database.ids.DBID; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; 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.distancevalue.Distance; @@ -55,7 +55,7 @@ public abstract class AbstractDistanceQuery<O, D extends Distance<D>> extends Ab * @return the distance between the two objects specified by their object ids */ @Override - public abstract D distance(DBID id1, DBID id2); + public abstract D distance(DBIDRef id1, DBIDRef id2); /** * Returns the distance between the two objects specified by their object ids. @@ -65,7 +65,7 @@ public abstract class AbstractDistanceQuery<O, D extends Distance<D>> extends Ab * @return the distance between the two objects specified by their object ids */ @Override - public abstract D distance(O o1, DBID id2); + public abstract D distance(O o1, DBIDRef id2); /** * Returns the distance between the two objects specified by their object ids. @@ -75,7 +75,7 @@ public abstract class AbstractDistanceQuery<O, D extends Distance<D>> extends Ab * @return the distance between the two objects specified by their object ids */ @Override - public abstract D distance(DBID id1, O o2); + public abstract D distance(DBIDRef id1, O o2); /** * Returns the distance between the two objects specified by their object ids. 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 2bb45623..28ca9b16 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 @@ -24,6 +24,7 @@ package de.lmu.ifi.dbs.elki.database.query.distance; */ import de.lmu.ifi.dbs.elki.database.ids.DBID; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.distance.distancefunction.DBIDDistanceFunction; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; @@ -56,7 +57,7 @@ public class DBIDDistanceQuery<D extends Distance<D>> extends AbstractDatabaseDi } @Override - public D distance(DBID id1, DBID id2) { + public D distance(DBIDRef id1, DBIDRef id2) { if(id1 == null) { throw new UnsupportedOperationException("This distance function can only be used for objects stored in the database."); } 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 1986b246..c026162d 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 @@ -23,7 +23,7 @@ package de.lmu.ifi.dbs.elki.database.query.distance; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import de.lmu.ifi.dbs.elki.database.ids.DBID; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; @@ -48,7 +48,7 @@ public interface DistanceQuery<O, D extends Distance<?>> extends DatabaseQuery { * @param id2 second object id * @return the distance between the two objects specified by their object ids */ - D distance(DBID id1, DBID id2); + D distance(DBIDRef id1, DBIDRef id2); /** * Returns the distance between the two objects specified by their object ids. @@ -57,7 +57,7 @@ public interface DistanceQuery<O, D extends Distance<?>> extends DatabaseQuery { * @param id2 second object id * @return the distance between the two objects specified by their object ids */ - D distance(O o1, DBID id2); + D distance(O o1, DBIDRef id2); /** * Returns the distance between the two objects specified by their object ids. @@ -66,7 +66,7 @@ public interface DistanceQuery<O, D extends Distance<?>> extends DatabaseQuery { * @param o2 second object * @return the distance between the two objects specified by their object ids */ - D distance(DBID id1, O o2); + D distance(DBIDRef id1, O o2); /** * Returns the distance between the two objects specified by their object ids. 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 5015dee1..75bd9e39 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 @@ -23,7 +23,7 @@ package de.lmu.ifi.dbs.elki.database.query.distance; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import de.lmu.ifi.dbs.elki.database.ids.DBID; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; @@ -57,20 +57,20 @@ public class PrimitiveDistanceQuery<O, D extends Distance<D>> extends AbstractDi } @Override - public D distance(DBID id1, DBID id2) { + public D distance(DBIDRef id1, DBIDRef id2) { O o1 = relation.get(id1); O o2 = relation.get(id2); return distance(o1, o2); } @Override - public D distance(O o1, DBID id2) { + public D distance(O o1, DBIDRef id2) { O o2 = relation.get(id2); return distance(o1, o2); } @Override - public D distance(DBID id1, O o2) { + public D distance(DBIDRef id1, O o2) { O o1 = relation.get(id1); return distance(o1, o2); } 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 4988c925..930d195c 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 @@ -23,7 +23,7 @@ package de.lmu.ifi.dbs.elki.database.query.distance; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import de.lmu.ifi.dbs.elki.database.ids.DBID; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; import de.lmu.ifi.dbs.elki.database.query.DistanceSimilarityQuery; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDistanceFunction; @@ -61,20 +61,20 @@ public class PrimitiveDistanceSimilarityQuery<O, D extends Distance<D>> extends } @Override - public D similarity(DBID id1, DBID id2) { + public D similarity(DBIDRef id1, DBIDRef id2) { O o1 = relation.get(id1); O o2 = relation.get(id2); return similarity(o1, o2); } @Override - public D similarity(O o1, DBID id2) { + public D similarity(O o1, DBIDRef id2) { O o2 = relation.get(id2); return similarity(o1, o2); } @Override - public D similarity(DBID id1, O o2) { + public D similarity(DBIDRef id1, O o2) { O o1 = relation.get(id1); return similarity(o1, o2); } 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 731148e8..e5df1452 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 @@ -23,7 +23,7 @@ package de.lmu.ifi.dbs.elki.database.query.knn; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import de.lmu.ifi.dbs.elki.database.ids.DBID; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; 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.distancevalue.Distance; @@ -50,7 +50,7 @@ public abstract class AbstractDistanceKNNQuery<O, D extends Distance<D>> extends } @Override - abstract public KNNResult<D> getKNNForDBID(DBID id, int k); + abstract public KNNResult<D> getKNNForDBID(DBIDRef id, int k); @Override abstract public KNNResult<D> getKNNForObject(O obj, int k); 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 80d91180..13bf58c2 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 @@ -28,6 +28,7 @@ import java.util.Map; 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.DBIDRef; import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.KNNHeap; @@ -51,7 +52,7 @@ public interface KNNQuery<O, D extends Distance<D>> extends DatabaseQuery { * @param k Number of neighbors requested * @return neighbors */ - public KNNResult<D> getKNNForDBID(DBID id, int k); + public KNNResult<D> getKNNForDBID(DBIDRef id, int k); /** * Bulk query method diff --git a/src/de/lmu/ifi/dbs/elki/database/query/knn/KNNResult.java b/src/de/lmu/ifi/dbs/elki/database/query/knn/KNNResult.java index d45fd8d7..e7612fcc 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/knn/KNNResult.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/knn/KNNResult.java @@ -23,10 +23,10 @@ package de.lmu.ifi.dbs.elki.database.query.knn; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import java.util.Collection; import java.util.List; import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs; +import de.lmu.ifi.dbs.elki.database.query.DistanceDBIDResult; import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; @@ -39,7 +39,7 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; * * @apiviz.composedOf DistanceResultPair */ -public interface KNNResult<D extends Distance<D>> extends Collection<DistanceResultPair<D>> { +public interface KNNResult<D extends Distance<D>> extends DistanceDBIDResult<D> { /** * Size */ @@ -58,6 +58,7 @@ public interface KNNResult<D extends Distance<D>> extends Collection<DistanceRes * * @param index */ + @Override public DistanceResultPair<D> get(int index); /** diff --git a/src/de/lmu/ifi/dbs/elki/database/query/knn/KNNUtil.java b/src/de/lmu/ifi/dbs/elki/database/query/knn/KNNUtil.java index 1179edb5..01deeaa0 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/knn/KNNUtil.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/knn/KNNUtil.java @@ -23,7 +23,6 @@ package de.lmu.ifi.dbs.elki.database.query.knn; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import java.util.AbstractCollection; import java.util.AbstractList; import java.util.Iterator; import java.util.List; @@ -31,6 +30,7 @@ import java.util.List; 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; import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; @@ -49,7 +49,7 @@ public final class KNNUtil { * * @param <D> Distance */ - protected static class KNNSubList<D extends Distance<D>> extends AbstractCollection<DistanceResultPair<D>> implements KNNResult<D> { + protected static class KNNSubList<D extends Distance<D>> extends AbstractList<DistanceResultPair<D>> implements KNNResult<D> { /** * Parameter k */ @@ -240,6 +240,18 @@ public final class KNNUtil { public DBID getDBID() { return cur.getDBID(); } + + @Override + public boolean sameDBID(DBIDRef other) { + return getIntegerID() == other.getIntegerID(); + } + + @Override + public int compareDBID(DBIDRef o) { + final int thisVal = getIntegerID(); + final int anotherVal = o.getIntegerID(); + return (thisVal < anotherVal ? -1 : (thisVal == anotherVal ? 0 : 1)); + } } /** @@ -284,9 +296,9 @@ public final class KNNUtil { } @Override - public boolean contains(DBID o) { - for(DBID id : this) { - if(id.equals(o)) { + public boolean contains(DBIDRef o) { + for (DBIDIter iter = iter(); iter.valid(); iter.advance()) { + if(iter.sameDBID(o)) { return true; } } @@ -304,7 +316,7 @@ public final class KNNUtil { */ @Override @Deprecated - public int binarySearch(DBID key) { + public int binarySearch(DBIDRef key) { throw new UnsupportedOperationException("Since the result is usually not sorted, a binary Search does not make sense!"); } } 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 d6492f43..b51dad4c 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 @@ -31,6 +31,8 @@ import java.util.Map.Entry; import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs; 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.DBIDUtil; import de.lmu.ifi.dbs.elki.database.query.LinearScanQuery; import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; @@ -64,28 +66,29 @@ 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(DBID candidateID : relation.iterDBIDs()) { - Integer index = -1; - for(DBID id : ids) { - index++; + for(DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) { + DBID candidateID = iter.getDBID(); + int index = 0; + for (DBIDIter iter2 = ids.iter(); iter2.valid(); iter2.advance()) { KNNHeap<D> heap = heaps.get(index); - heap.add(distanceQuery.distance(id, candidateID), candidateID); + heap.add(distanceQuery.distance(iter2, candidateID), candidateID); + index++; } } } @Override - public KNNResult<D> getKNNForDBID(DBID id, int k) { + public KNNResult<D> getKNNForDBID(DBIDRef id, int k) { KNNHeap<D> heap = new KNNHeap<D>(k); if(PrimitiveDistanceQuery.class.isInstance(distanceQuery)) { O obj = relation.get(id); - for(DBID candidateID : relation.iterDBIDs()) { - heap.add(distanceQuery.distance(obj, relation.get(candidateID)), candidateID); + for(DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) { + heap.add(distanceQuery.distance(obj, relation.get(iter)), iter); } } else { - for(DBID candidateID : relation.iterDBIDs()) { - heap.add(distanceQuery.distance(id, candidateID), candidateID); + for(DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) { + heap.add(distanceQuery.distance(id, iter), iter); } } return heap.toKNNList(); @@ -122,9 +125,8 @@ public class LinearScanKNNQuery<O, D extends Distance<D>> extends AbstractDistan @Override public KNNResult<D> getKNNForObject(O obj, int k) { KNNHeap<D> heap = new KNNHeap<D>(k); - for(DBID candidateID : relation.iterDBIDs()) { - O candidate = relation.get(candidateID); - heap.add(distanceQuery.distance(obj, candidate), candidateID); + for(DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) { + heap.add(distanceQuery.distance(obj, iter), iter); } return heap.toKNNList(); } 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 07632a34..59987282 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 @@ -30,6 +30,8 @@ import java.util.Map.Entry; 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; import de.lmu.ifi.dbs.elki.database.query.distance.PrimitiveDistanceQuery; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.KNNHeap; @@ -63,7 +65,8 @@ public class LinearScanPrimitiveDistanceKNNQuery<O, D extends Distance<D>> exten protected void linearScanBatchKNN(List<O> objs, List<KNNHeap<D>> heaps) { final int size = objs.size(); // Linear scan style KNN. - for(DBID candidateID : relation.iterDBIDs()) { + for(DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) { + DBID candidateID = iter.getDBID(); O candidate = relation.get(candidateID); for(int index = 0; index < size; index++) { O object = objs.get(index); @@ -74,7 +77,7 @@ public class LinearScanPrimitiveDistanceKNNQuery<O, D extends Distance<D>> exten } @Override - public KNNResult<D> getKNNForDBID(DBID id, int k) { + public KNNResult<D> getKNNForDBID(DBIDRef id, int k) { return getKNNForObject(relation.get(id), k); } @@ -83,9 +86,9 @@ public class LinearScanPrimitiveDistanceKNNQuery<O, D extends Distance<D>> exten final int size = ids.size(); final List<KNNHeap<D>> heaps = new ArrayList<KNNHeap<D>>(size); List<O> objs = new ArrayList<O>(size); - for(DBID id : ids) { + for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { heaps.add(new KNNHeap<D>(k)); - objs.add(relation.get(id)); + objs.add(relation.get(iter)); } linearScanBatchKNN(objs, heaps); 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 index 3f7dc04f..a10aaac5 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/knn/LinearScanRawDoubleDistanceKNNQuery.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/knn/LinearScanRawDoubleDistanceKNNQuery.java @@ -26,7 +26,8 @@ package de.lmu.ifi.dbs.elki.database.query.knn; import java.util.Arrays; import java.util.List; -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.query.DoubleDistanceResultPair; import de.lmu.ifi.dbs.elki.database.query.distance.PrimitiveDistanceQuery; import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction; @@ -56,7 +57,7 @@ public class LinearScanRawDoubleDistanceKNNQuery<O> extends LinearScanPrimitiveD } @Override - public KNNResult<DoubleDistance> getKNNForDBID(DBID id, int k) { + public KNNResult<DoubleDistance> getKNNForDBID(DBIDRef id, int k) { return getKNNForObject(relation.get(id), k); } @@ -67,10 +68,10 @@ public class LinearScanRawDoubleDistanceKNNQuery<O> extends LinearScanPrimitiveD // Optimization for double distances. final KNNHeap<DoubleDistance> heap = new KNNHeap<DoubleDistance>(k); double max = Double.POSITIVE_INFINITY; - for(DBID candidateID : relation.iterDBIDs()) { - final double doubleDistance = rawdist.doubleDistance(obj, relation.get(candidateID)); + for(DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) { + final double doubleDistance = rawdist.doubleDistance(obj, relation.get(iter)); if(doubleDistance <= max) { - heap.add(new DoubleDistanceResultPair(doubleDistance, candidateID)); + heap.add(new DoubleDistanceResultPair(doubleDistance, iter.getDBID())); // Update cutoff if(heap.size() >= heap.getK()) { max = ((DoubleDistanceResultPair) heap.peek()).getDoubleDistance(); @@ -91,13 +92,13 @@ public class LinearScanRawDoubleDistanceKNNQuery<O> extends LinearScanPrimitiveD // The distance is computed on arbitrary vectors, we can reduce object // loading by working on the actual vectors. - for(DBID candidateID : relation.iterDBIDs()) { - O candidate = relation.get(candidateID); + for(DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) { + O candidate = relation.get(iter); for(int index = 0; index < size; index++) { final KNNHeap<DoubleDistance> heap = heaps.get(index); double doubleDistance = rawdist.doubleDistance(objs.get(index), candidate); if(doubleDistance <= max[index]) { - heap.add(new DoubleDistanceResultPair(doubleDistance, candidateID)); + heap.add(new DoubleDistanceResultPair(doubleDistance, iter.getDBID())); if(heap.size() >= heap.getK()) { max[index] = ((DoubleDistanceResultPair) heap.peek()).getDoubleDistance(); } 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 93321609..09f93945 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 @@ -30,6 +30,8 @@ import java.util.Map.Entry; 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; import de.lmu.ifi.dbs.elki.database.query.AbstractDataBasedQuery; import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair; import de.lmu.ifi.dbs.elki.database.relation.Relation; @@ -77,7 +79,7 @@ public class PreprocessorKNNQuery<O, D extends Distance<D>, T extends KNNResult< } @Override - public KNNResult<D> getKNNForDBID(DBID id, int k) { + public KNNResult<D> getKNNForDBID(DBIDRef id, int k) { if(!warned && k > preprocessor.getK()) { LoggingUtil.warning("Requested more neighbors than preprocessed!"); } @@ -112,8 +114,8 @@ public class PreprocessorKNNQuery<O, D extends Distance<D>, T extends KNNResult< } List<KNNResult<D>> result = new ArrayList<KNNResult<D>>(ids.size()); if(k < preprocessor.getK()) { - for(DBID id : ids) { - KNNResult<D> dr = preprocessor.get(id); + for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { + KNNResult<D> dr = preprocessor.get(iter); int subk = k; D kdist = dr.get(subk - 1).getDistance(); while(subk < dr.size()) { @@ -135,8 +137,8 @@ public class PreprocessorKNNQuery<O, D extends Distance<D>, T extends KNNResult< } } else { - for(DBID id : ids) { - result.add(preprocessor.get(id)); + for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { + result.add(preprocessor.get(iter)); } } return result; 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 60426034..871c5e9e 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 @@ -23,11 +23,9 @@ package de.lmu.ifi.dbs.elki.database.query.range; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import java.util.List; - -import de.lmu.ifi.dbs.elki.database.ids.DBID; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; import de.lmu.ifi.dbs.elki.database.query.AbstractDataBasedQuery; -import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair; +import de.lmu.ifi.dbs.elki.database.query.DistanceDBIDResult; import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; @@ -57,8 +55,8 @@ public abstract class AbstractDistanceRangeQuery<O, D extends Distance<D>> exten } @Override - abstract public List<DistanceResultPair<D>> getRangeForDBID(DBID id, D range); + abstract public DistanceDBIDResult<D> getRangeForDBID(DBIDRef id, D range); @Override - abstract public List<DistanceResultPair<D>> getRangeForObject(O obj, D range); + abstract public DistanceDBIDResult<D> getRangeForObject(O obj, D range); }
\ No newline at end of file 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 dfe0b581..758d603e 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 @@ -23,10 +23,8 @@ package de.lmu.ifi.dbs.elki.database.query.range; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import java.util.List; - -import de.lmu.ifi.dbs.elki.database.ids.DBID; -import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; +import de.lmu.ifi.dbs.elki.database.query.DistanceDBIDResult; import de.lmu.ifi.dbs.elki.database.query.distance.PrimitiveDistanceQuery; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; @@ -54,7 +52,8 @@ public class LinearScanPrimitiveDistanceRangeQuery<O, D extends Distance<D>> ext } @Override - public List<DistanceResultPair<D>> getRangeForDBID(DBID id, D range) { + public DistanceDBIDResult<D> getRangeForDBID(DBIDRef id, D range) { + // Note: subtle optimization. Get "id" only once! return getRangeForObject(relation.get(id), range); } }
\ No newline at end of file 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 a7bb7db9..c8ddb1ec 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 @@ -23,12 +23,12 @@ package de.lmu.ifi.dbs.elki.database.query.range; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import java.util.ArrayList; import java.util.Collections; -import java.util.List; -import de.lmu.ifi.dbs.elki.database.ids.DBID; -import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair; +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.DistanceDBIDResult; +import de.lmu.ifi.dbs.elki.database.query.GenericDistanceDBIDList; import de.lmu.ifi.dbs.elki.database.query.GenericDistanceResultPair; import de.lmu.ifi.dbs.elki.database.query.LinearScanQuery; import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; @@ -56,12 +56,12 @@ public class LinearScanRangeQuery<O, D extends Distance<D>> extends AbstractDist } @Override - public List<DistanceResultPair<D>> getRangeForDBID(DBID id, D range) { - List<DistanceResultPair<D>> result = new ArrayList<DistanceResultPair<D>>(); - for(DBID currentID : relation.iterDBIDs()) { - D currentDistance = distanceQuery.distance(id, currentID); + public DistanceDBIDResult<D> getRangeForDBID(DBIDRef id, D range) { + GenericDistanceDBIDList<D> result = new GenericDistanceDBIDList<D>(); + for(DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) { + D currentDistance = distanceQuery.distance(id, iter); if(currentDistance.compareTo(range) <= 0) { - result.add(new GenericDistanceResultPair<D>(currentDistance, currentID)); + result.add(new GenericDistanceResultPair<D>(currentDistance, iter.getDBID())); } } Collections.sort(result); @@ -69,12 +69,12 @@ public class LinearScanRangeQuery<O, D extends Distance<D>> extends AbstractDist } @Override - public List<DistanceResultPair<D>> getRangeForObject(O obj, D range) { - List<DistanceResultPair<D>> result = new ArrayList<DistanceResultPair<D>>(); - for(DBID currentID : relation.iterDBIDs()) { - D currentDistance = distanceQuery.distance(currentID, obj); + public DistanceDBIDResult<D> getRangeForObject(O obj, D range) { + GenericDistanceDBIDList<D> result = new GenericDistanceDBIDList<D>(); + for(DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) { + D currentDistance = distanceQuery.distance(obj, iter); if(currentDistance.compareTo(range) <= 0) { - result.add(new GenericDistanceResultPair<D>(currentDistance, currentID)); + result.add(new GenericDistanceResultPair<D>(currentDistance, iter.getDBID())); } } Collections.sort(result); 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 index 18d1d173..c5ce2f55 100644 --- a/src/de/lmu/ifi/dbs/elki/database/query/range/LinearScanRawDoubleDistanceRangeQuery.java +++ b/src/de/lmu/ifi/dbs/elki/database/query/range/LinearScanRawDoubleDistanceRangeQuery.java @@ -23,13 +23,13 @@ package de.lmu.ifi.dbs.elki.database.query.range; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import java.util.ArrayList; import java.util.Collections; -import java.util.List; -import de.lmu.ifi.dbs.elki.database.ids.DBID; -import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair; +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.DistanceDBIDResult; import de.lmu.ifi.dbs.elki.database.query.DoubleDistanceResultPair; +import de.lmu.ifi.dbs.elki.database.query.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.distance.PrimitiveDistanceQuery; @@ -56,18 +56,18 @@ public class LinearScanRawDoubleDistanceRangeQuery<O> extends LinearScanRangeQue } @Override - public List<DistanceResultPair<DoubleDistance>> getRangeForDBID(DBID id, DoubleDistance range) { + 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); - List<DistanceResultPair<DoubleDistance>> result = new ArrayList<DistanceResultPair<DoubleDistance>>(); - for(DBID currentID : relation.iterDBIDs()) { - double doubleDistance = rawdist.doubleDistance(qo, relation.get(currentID)); + GenericDistanceDBIDList<DoubleDistance> result = new GenericDistanceDBIDList<DoubleDistance>(); + for(DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) { + double doubleDistance = rawdist.doubleDistance(qo, relation.get(iter)); if(doubleDistance <= epsilon) { - result.add(new DoubleDistanceResultPair(doubleDistance, currentID)); + result.add(new DoubleDistanceResultPair(doubleDistance, iter.getDBID())); } } Collections.sort(result); @@ -79,17 +79,17 @@ public class LinearScanRawDoubleDistanceRangeQuery<O> extends LinearScanRangeQue } @Override - public List<DistanceResultPair<DoubleDistance>> getRangeForObject(O obj, DoubleDistance range) { + 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(); - List<DistanceResultPair<DoubleDistance>> result = new ArrayList<DistanceResultPair<DoubleDistance>>(); - for(DBID currentID : relation.iterDBIDs()) { - double doubleDistance = rawdist.doubleDistance(obj, relation.get(currentID)); + GenericDistanceDBIDList<DoubleDistance> result = new GenericDistanceDBIDList<DoubleDistance>(); + for(DBIDIter iter = relation.getDBIDs().iter(); iter.valid(); iter.advance()) { + double doubleDistance = rawdist.doubleDistance(obj, relation.get(iter)); if(doubleDistance <= epsilon) { - result.add(new DoubleDistanceResultPair(doubleDistance, currentID)); + result.add(new DoubleDistanceResultPair(doubleDistance, iter.getDBID())); } } Collections.sort(result); 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 c2dbecd6..2c6842bf 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 @@ -23,11 +23,9 @@ package de.lmu.ifi.dbs.elki.database.query.range; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import java.util.List; - -import de.lmu.ifi.dbs.elki.database.ids.DBID; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery; -import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair; +import de.lmu.ifi.dbs.elki.database.query.DistanceDBIDResult; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; /** @@ -36,7 +34,7 @@ import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; * @author Erich Schubert * * @apiviz.landmark - * @apiviz.uses DistanceResultPair oneway - - «create» + * @apiviz.uses DistanceDBIDResult oneway - - «create» * * @param <O> Object type * @param <D> Distance type @@ -49,7 +47,7 @@ public interface RangeQuery<O, D extends Distance<D>> extends DatabaseQuery { * @param range Query range * @return neighbors */ - public List<DistanceResultPair<D>> getRangeForDBID(DBID id, D range); + public DistanceDBIDResult<D> getRangeForDBID(DBIDRef id, D range); /** * Get the nearest neighbors for a particular object in a given query range @@ -58,5 +56,5 @@ public interface RangeQuery<O, D extends Distance<D>> extends DatabaseQuery { * @param range Query range * @return neighbors */ - public List<DistanceResultPair<D>> getRangeForObject(O obj, D range); + public DistanceDBIDResult<D> getRangeForObject(O obj, D range); }
\ No newline at end of file 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 86e82c7e..fe4f49e1 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 @@ -25,7 +25,7 @@ package de.lmu.ifi.dbs.elki.database.query.rknn; import java.util.List; -import de.lmu.ifi.dbs.elki.database.ids.DBID; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; import de.lmu.ifi.dbs.elki.database.query.AbstractDataBasedQuery; import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair; import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; @@ -53,5 +53,5 @@ public abstract class AbstractRKNNQuery<O, D extends Distance<D>> extends Abstra } @Override - abstract public List<DistanceResultPair<D>> getRKNNForDBID(DBID id, int k); + abstract public List<DistanceResultPair<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 1449d7f0..1f901828 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 @@ -29,6 +29,8 @@ import java.util.List; 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; import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil; import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair; import de.lmu.ifi.dbs.elki.database.query.GenericDistanceResultPair; @@ -76,12 +78,12 @@ public class LinearScanRKNNQuery<O, D extends Distance<D>> extends AbstractRKNNQ List<? extends KNNResult<D>> kNNLists = knnQuery.getKNNForBulkDBIDs(allIDs, k); int i = 0; - for(DBID qid : allIDs) { + for (DBIDIter iter = allIDs.iter(); iter.valid(); iter.advance()) { KNNResult<D> knn = kNNLists.get(i); int last = Math.min(k - 1, knn.size() - 1); - D dist = distanceQuery.distance(obj, qid); + D dist = distanceQuery.distance(obj, iter); if(last < k - 1 || dist.compareTo(knn.get(last).getDistance()) < 1) { - rNNlist.add(new GenericDistanceResultPair<D>(dist, qid)); + rNNlist.add(new GenericDistanceResultPair<D>(dist, iter.getDBID())); } i++; } @@ -90,8 +92,24 @@ public class LinearScanRKNNQuery<O, D extends Distance<D>> extends AbstractRKNNQ } @Override - public List<DistanceResultPair<D>> getRKNNForDBID(DBID id, int k) { - return getRKNNForBulkDBIDs(id, k).get(0); + public List<DistanceResultPair<D>> getRKNNForDBID(DBIDRef id, int k) { + ArrayList<DistanceResultPair<D>> rNNList = new ArrayList<DistanceResultPair<D>>(); + + ArrayDBIDs allIDs = DBIDUtil.ensureArray(relation.getDBIDs()); + List<? extends KNNResult<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(DistanceResultPair<D> n : knn) { + if(n.sameDBID(id)) { + rNNList.add(new GenericDistanceResultPair<D>(n.getDistance(), iter.getDBID())); + } + } + i++; + } + Collections.sort(rNNList); + return rNNList; } @Override @@ -105,12 +123,13 @@ public class LinearScanRKNNQuery<O, D extends Distance<D>> extends AbstractRKNNQ List<? extends KNNResult<D>> kNNList = knnQuery.getKNNForBulkDBIDs(allIDs, k); int i = 0; - for(DBID qid : allIDs) { + for (DBIDIter iter = allIDs.iter(); iter.valid(); iter.advance()) { + DBID qid = iter.getDBID(); KNNResult<D> knn = kNNList.get(i); for(DistanceResultPair<D> n : knn) { int j = 0; - for(DBID id : ids) { - if(n.getDBID().equals(id)) { + for (DBIDIter iter2 = ids.iter(); iter2.valid(); iter2.advance()) { + if(n.getDBID().sameDBID(iter2)) { List<DistanceResultPair<D>> rNN = rNNList.get(j); rNN.add(new GenericDistanceResultPair<D>(n.getDistance(), qid)); } 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 2f8e841a..ab8c3b30 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 @@ -27,7 +27,8 @@ 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.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.query.AbstractDataBasedQuery; import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair; import de.lmu.ifi.dbs.elki.database.relation.Relation; @@ -74,7 +75,7 @@ public class PreprocessorRKNNQuery<O, D extends Distance<D>> extends AbstractDat } @Override - public List<DistanceResultPair<D>> getRKNNForDBID(DBID id, int k) { + public List<DistanceResultPair<D>> getRKNNForDBID(DBIDRef id, int k) { if(!warned && k != preprocessor.getK()) { LoggingUtil.warning("Requested more neighbors than preprocessed!"); } @@ -92,8 +93,8 @@ public class PreprocessorRKNNQuery<O, D extends Distance<D>> extends AbstractDat LoggingUtil.warning("Requested more neighbors than preprocessed!"); } List<List<DistanceResultPair<D>>> result = new ArrayList<List<DistanceResultPair<D>>>(ids.size()); - for(DBID id : ids) { - result.add(preprocessor.getRKNN(id)); + for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { + result.add(preprocessor.getRKNN(iter.getDBID())); } return result; } 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 e707b6ce..9ff6f790 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 @@ -26,7 +26,7 @@ package de.lmu.ifi.dbs.elki.database.query.rknn; import java.util.List; 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.DBIDRef; import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery; import de.lmu.ifi.dbs.elki.database.query.DistanceResultPair; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; @@ -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 List<DistanceResultPair<D>> getRKNNForDBID(DBID id, int k); + public List<DistanceResultPair<D>> getRKNNForDBID(DBIDRef id, int k); /** * Get the reverse k nearest neighbors for a particular object. 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 1af1c624..3d5ff71f 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 @@ -23,7 +23,7 @@ package de.lmu.ifi.dbs.elki.database.query.similarity; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import de.lmu.ifi.dbs.elki.database.ids.DBID; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; @@ -46,12 +46,12 @@ public abstract class AbstractDBIDSimilarityQuery<O, D extends Distance<D>> exte } @Override - public D similarity(O o1, DBID id2) { + public D similarity(O o1, DBIDRef id2) { throw new UnsupportedOperationException("This distance function can only be used for objects when referenced by ID."); } @Override - public D similarity(DBID id1, O o2) { + public D similarity(DBIDRef id1, O o2) { throw new UnsupportedOperationException("This distance function can only be used for objects when referenced by ID."); } 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 316d155c..21abe219 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 @@ -23,7 +23,7 @@ package de.lmu.ifi.dbs.elki.database.query.similarity; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import de.lmu.ifi.dbs.elki.database.ids.DBID; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; 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.distancevalue.Distance; @@ -55,7 +55,7 @@ public abstract class AbstractSimilarityQuery<O, D extends Distance<D>> extends * @return the distance between the two objects specified by their object ids */ @Override - public abstract D similarity(DBID id1, DBID id2); + public abstract D similarity(DBIDRef id1, DBIDRef id2); /** * Returns the distance between the two objects specified by their object ids. @@ -65,7 +65,7 @@ public abstract class AbstractSimilarityQuery<O, D extends Distance<D>> extends * @return the distance between the two objects specified by their object ids */ @Override - public abstract D similarity(O o1, DBID id2); + public abstract D similarity(O o1, DBIDRef id2); /** * Returns the distance between the two objects specified by their object ids. @@ -75,7 +75,7 @@ public abstract class AbstractSimilarityQuery<O, D extends Distance<D>> extends * @return the distance between the two objects specified by their object ids */ @Override - public abstract D similarity(DBID id1, O o2); + public abstract D similarity(DBIDRef id1, O o2); /** * Returns the distance between the two objects specified by their object ids. 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 f57e0bd5..5a604d0c 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 @@ -23,7 +23,7 @@ package de.lmu.ifi.dbs.elki.database.query.similarity; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import de.lmu.ifi.dbs.elki.database.ids.DBID; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; import de.lmu.ifi.dbs.elki.distance.similarityfunction.PrimitiveSimilarityFunction; @@ -54,20 +54,20 @@ public class PrimitiveSimilarityQuery<O, D extends Distance<D>> extends Abstract } @Override - public D similarity(DBID id1, DBID id2) { + public D similarity(DBIDRef id1, DBIDRef id2) { O o1 = relation.get(id1); O o2 = relation.get(id2); return similarity(o1, o2); } @Override - public D similarity(O o1, DBID id2) { + public D similarity(O o1, DBIDRef id2) { O o2 = relation.get(id2); return similarity(o1, o2); } @Override - public D similarity(DBID id1, O o2) { + public D similarity(DBIDRef id1, O o2) { O o1 = relation.get(id1); return similarity(o1, o2); } 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 c3fdaaa4..b25d13fc 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 @@ -23,7 +23,7 @@ package de.lmu.ifi.dbs.elki.database.query.similarity; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import de.lmu.ifi.dbs.elki.database.ids.DBID; +import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; @@ -50,7 +50,7 @@ public interface SimilarityQuery<O, D extends Distance<?>> extends DatabaseQuery * @return the similarity between the two objects specified by their object * ids */ - public abstract D similarity(DBID id1, DBID id2); + public abstract D similarity(DBIDRef id1, DBIDRef id2); /** * Returns the similarity between the two objects specified by their object @@ -61,7 +61,7 @@ public interface SimilarityQuery<O, D extends Distance<?>> extends DatabaseQuery * @return the similarity between the two objects specified by their object * ids */ - public abstract D similarity(O o1, DBID id2); + public abstract D similarity(O o1, DBIDRef id2); /** * Returns the similarity between the two objects specified by their object @@ -72,7 +72,7 @@ public interface SimilarityQuery<O, D extends Distance<?>> extends DatabaseQuery * @return the similarity between the two objects specified by their object * ids */ - public abstract D similarity(DBID id1, O o2); + public abstract D similarity(DBIDRef id1, O o2); /** * Returns the similarity between the two objects specified by their object 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 9d9ad672..4c25405b 100644 --- a/src/de/lmu/ifi/dbs/elki/database/relation/ConvertToStringView.java +++ b/src/de/lmu/ifi/dbs/elki/database/relation/ConvertToStringView.java @@ -26,10 +26,10 @@ package de.lmu.ifi.dbs.elki.database.relation; import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation; import de.lmu.ifi.dbs.elki.data.type.TypeUtil; import de.lmu.ifi.dbs.elki.database.Database; -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.DBIDs; import de.lmu.ifi.dbs.elki.result.AbstractHierarchicalResult; -import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator; /** * Representation adapter that uses toString() to produce a string @@ -59,17 +59,17 @@ public class ConvertToStringView extends AbstractHierarchicalResult implements R } @Override - public String get(DBID id) { + public String get(DBIDRef id) { return existing.get(id).toString(); } @Override - public void set(DBID id, String val) { + public void set(DBIDRef id, String val) { throw new UnsupportedOperationException("Covnersion representations are not writable!"); } @Override - public void delete(DBID id) { + public void delete(DBIDRef id) { throw new UnsupportedOperationException("Covnersion representations are not writable!"); } @@ -79,7 +79,7 @@ public class ConvertToStringView extends AbstractHierarchicalResult implements R } @Override - public IterableIterator<DBID> iterDBIDs() { + public DBIDIter iterDBIDs() { return existing.iterDBIDs(); } 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 62a6fd36..4898c518 100644 --- a/src/de/lmu/ifi/dbs/elki/database/relation/DBIDView.java +++ b/src/de/lmu/ifi/dbs/elki/database/relation/DBIDView.java @@ -28,11 +28,11 @@ import de.lmu.ifi.dbs.elki.data.type.TypeUtil; import de.lmu.ifi.dbs.elki.database.Database; import de.lmu.ifi.dbs.elki.database.UpdatableDatabase; 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.DBIDUtil; import de.lmu.ifi.dbs.elki.database.ids.DBIDs; import de.lmu.ifi.dbs.elki.result.AbstractHierarchicalResult; -import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator; -import de.lmu.ifi.dbs.elki.utilities.iterator.IterableUtil; /** * Pseudo-representation that is the object ID itself. @@ -68,20 +68,21 @@ public class DBIDView extends AbstractHierarchicalResult implements Relation<DBI } @Override - public DBID get(DBID id) { + public DBID get(DBIDRef id) { assert (ids.contains(id)); - return id; + return id.getDBID(); } @Override - public void set(DBID id, DBID val) { + public void set(DBIDRef id, DBID val) { throw new UnsupportedOperationException("DBIDs cannot be changed."); } @Override - public void delete(DBID id) { + public void delete(DBIDRef id) { if(database instanceof UpdatableDatabase) { - ((UpdatableDatabase) database).delete(id); + // TODO: skip getDBID() + ((UpdatableDatabase) database).delete(id.getDBID()); } else { throw new UnsupportedOperationException("Deletions are not supported."); @@ -99,8 +100,8 @@ public class DBIDView extends AbstractHierarchicalResult implements Relation<DBI } @Override - public IterableIterator<DBID> iterDBIDs() { - return IterableUtil.fromIterable(ids); + public DBIDIter iterDBIDs() { + return ids.iter(); } @Override 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 af65e84d..2d090e99 100644 --- a/src/de/lmu/ifi/dbs/elki/database/relation/MaterializedRelation.java +++ b/src/de/lmu/ifi/dbs/elki/database/relation/MaterializedRelation.java @@ -29,13 +29,12 @@ import de.lmu.ifi.dbs.elki.database.datastore.DataStore; import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory; import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil; import de.lmu.ifi.dbs.elki.database.datastore.WritableDataStore; -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.DBIDUtil; import de.lmu.ifi.dbs.elki.database.ids.DBIDs; import de.lmu.ifi.dbs.elki.database.ids.StaticDBIDs; import de.lmu.ifi.dbs.elki.result.AbstractHierarchicalResult; -import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator; -import de.lmu.ifi.dbs.elki.utilities.iterator.IterableUtil; /** * Represents a single representation. This is attached to a DBIDs object, which @@ -152,12 +151,12 @@ public class MaterializedRelation<O> extends AbstractHierarchicalResult implemen } @Override - public O get(DBID id) { + public O get(DBIDRef id) { return content.get(id); } @Override - public void set(DBID id, O val) { + public void set(DBIDRef id, O val) { assert (ids.contains(id)); if(content instanceof WritableDataStore) { ((WritableDataStore<O>) content).put(id, val); @@ -170,7 +169,7 @@ public class MaterializedRelation<O> extends AbstractHierarchicalResult implemen * @param id ID to delete */ @Override - public void delete(DBID id) { + public void delete(DBIDRef id) { assert (!ids.contains(id)); if(content instanceof WritableDataStore) { ((WritableDataStore<O>) content).delete(id); @@ -183,8 +182,8 @@ public class MaterializedRelation<O> extends AbstractHierarchicalResult implemen } @Override - public IterableIterator<DBID> iterDBIDs() { - return IterableUtil.fromIterable(ids); + public DBIDIter iterDBIDs() { + return ids.iter(); } @Override 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 190b15c6..8f2b8c92 100644 --- a/src/de/lmu/ifi/dbs/elki/database/relation/ProjectedView.java +++ b/src/de/lmu/ifi/dbs/elki/database/relation/ProjectedView.java @@ -3,10 +3,10 @@ package de.lmu.ifi.dbs.elki.database.relation; import de.lmu.ifi.dbs.elki.data.projection.Projection; import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation; import de.lmu.ifi.dbs.elki.database.Database; -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.DBIDs; import de.lmu.ifi.dbs.elki.result.AbstractHierarchicalResult; -import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator; /* This file is part of ELKI: @@ -78,17 +78,17 @@ public class ProjectedView<IN, OUT> extends AbstractHierarchicalResult implement } @Override - public OUT get(DBID id) { + public OUT get(DBIDRef id) { return projection.project(inner.get(id)); } @Override - public void set(DBID id, OUT val) { + public void set(DBIDRef id, OUT val) { throw new UnsupportedOperationException("Projections are read-only."); } @Override - public void delete(DBID id) { + public void delete(DBIDRef id) { inner.delete(id); } @@ -103,7 +103,7 @@ public class ProjectedView<IN, OUT> extends AbstractHierarchicalResult implement } @Override - public IterableIterator<DBID> iterDBIDs() { + public DBIDIter iterDBIDs() { return inner.iterDBIDs(); } 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 1ae761f3..9937c8ee 100644 --- a/src/de/lmu/ifi/dbs/elki/database/relation/ProxyView.java +++ b/src/de/lmu/ifi/dbs/elki/database/relation/ProxyView.java @@ -25,12 +25,11 @@ package de.lmu.ifi.dbs.elki.database.relation; import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation; import de.lmu.ifi.dbs.elki.database.Database; -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.DBIDUtil; import de.lmu.ifi.dbs.elki.database.ids.DBIDs; import de.lmu.ifi.dbs.elki.result.AbstractHierarchicalResult; -import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator; -import de.lmu.ifi.dbs.elki.utilities.iterator.IterableUtil; /** * A virtual partitioning of the database. For the accepted DBIDs, access is @@ -87,19 +86,19 @@ public class ProxyView<O> extends AbstractHierarchicalResult implements Relation } @Override - public O get(DBID id) { + public O get(DBIDRef id) { assert (idview.contains(id)) : "Accessing object not included in view."; return inner.get(id); } - + @Override - public void set(DBID id, O val) { + public void set(DBIDRef id, O val) { assert (idview.contains(id)) : "Accessing object not included in view."; inner.set(id, val); } @Override - public void delete(DBID id) { + public void delete(DBIDRef id) { throw new UnsupportedOperationException("Semantics of 'delete-from-virtual-partition' are not uniquely defined. Delete from IDs or from underlying data, please!"); } @@ -109,8 +108,8 @@ public class ProxyView<O> extends AbstractHierarchicalResult implements Relation } @Override - public IterableIterator<DBID> iterDBIDs() { - return IterableUtil.fromIterable(idview); + public DBIDIter iterDBIDs() { + return idview.iter(); } @Override 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 ebe1be3c..4969ad50 100644 --- a/src/de/lmu/ifi/dbs/elki/database/relation/Relation.java +++ b/src/de/lmu/ifi/dbs/elki/database/relation/Relation.java @@ -25,17 +25,19 @@ package de.lmu.ifi.dbs.elki.database.relation; import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation; import de.lmu.ifi.dbs.elki.database.Database; -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.DBIDs; import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery; import de.lmu.ifi.dbs.elki.result.HierarchicalResult; -import de.lmu.ifi.dbs.elki.utilities.iterator.IterableIterator; /** * An object representation from a database * * @author Erich Schubert - * + * + * @apiviz.uses DBIDRef + * * @param <O> Object type */ public interface Relation<O> extends DatabaseQuery, HierarchicalResult { @@ -47,15 +49,15 @@ public interface Relation<O> extends DatabaseQuery, HierarchicalResult { * @return Database */ public Database getDatabase(); - + /** * Get the representation of an object. * * @param id Object ID * @return object instance */ - public O get(DBID id); - + public O get(DBIDRef id); + /** * Set an object representation. * @@ -63,14 +65,14 @@ public interface Relation<O> extends DatabaseQuery, HierarchicalResult { * @param val Value */ // TODO: remove / move to a writable API? - public void set(DBID id, O val); + public void set(DBIDRef id, O val); /** * Delete an objects values. * * @param id ID to delete */ - public void delete(DBID id); + public void delete(DBIDRef id); /** * Get the data type of this representation @@ -78,7 +80,7 @@ public interface Relation<O> extends DatabaseQuery, HierarchicalResult { * @return Data type */ public SimpleTypeInformation<O> getDataTypeInformation(); - + /** * Get the IDs the query is defined for. * @@ -89,9 +91,19 @@ public interface Relation<O> extends DatabaseQuery, HierarchicalResult { /** * Get an iterator access to the DBIDs. * + * To iterate over all IDs, use the following code fragment: + * + * <pre> + * {@code + * for(DBIDIter iter = relation.iterDBIDs(); iter.valid(); iter.advance()) { + * DBID id = iter.getDBID(); + * } + * } + * </pre> + * * @return iterator for the DBIDs. */ - public IterableIterator<DBID> iterDBIDs(); + public DBIDIter iterDBIDs(); /** * Get the number of DBIDs. |