diff options
Diffstat (limited to 'src/de/lmu/ifi/dbs/elki/index')
250 files changed, 5477 insertions, 3880 deletions
diff --git a/src/de/lmu/ifi/dbs/elki/index/AbstractIndex.java b/src/de/lmu/ifi/dbs/elki/index/AbstractIndex.java index c9dbf3a0..ab4a1e3a 100644 --- a/src/de/lmu/ifi/dbs/elki/index/AbstractIndex.java +++ b/src/de/lmu/ifi/dbs/elki/index/AbstractIndex.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/AbstractRefiningIndex.java b/src/de/lmu/ifi/dbs/elki/index/AbstractRefiningIndex.java index b266824a..f196b6ce 100644 --- a/src/de/lmu/ifi/dbs/elki/index/AbstractRefiningIndex.java +++ b/src/de/lmu/ifi/dbs/elki/index/AbstractRefiningIndex.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -29,7 +29,6 @@ import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; import de.lmu.ifi.dbs.elki.database.query.knn.AbstractDistanceKNNQuery; import de.lmu.ifi.dbs.elki.database.query.range.AbstractDistanceRangeQuery; import de.lmu.ifi.dbs.elki.database.relation.Relation; -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; import de.lmu.ifi.dbs.elki.logging.Logging; import de.lmu.ifi.dbs.elki.logging.statistics.Counter; @@ -76,14 +75,14 @@ public abstract class AbstractRefiningIndex<O> extends AbstractIndex<O> { * @param i Increment. */ protected void countRefinements(int i) { - if (refinements != null) { + if(refinements != null) { refinements.increment(i); } } @Override public void logStatistics() { - if (refinements != null) { + if(refinements != null) { getLogger().statistics(refinements); } } @@ -106,13 +105,13 @@ public abstract class AbstractRefiningIndex<O> extends AbstractIndex<O> { * * @apiviz.excludeSubtypes */ - public abstract class AbstractRangeQuery<D extends Distance<D>> extends AbstractDistanceRangeQuery<O, D> { + public abstract class AbstractRangeQuery extends AbstractDistanceRangeQuery<O> { /** * Constructor. * * @param distanceQuery Distance query object */ - public AbstractRangeQuery(DistanceQuery<O, D> distanceQuery) { + public AbstractRangeQuery(DistanceQuery<O> distanceQuery) { super(distanceQuery); } @@ -123,7 +122,7 @@ public abstract class AbstractRefiningIndex<O> extends AbstractIndex<O> { * @param q Query object * @return Distance */ - protected D refine(DBIDRef id, O q) { + protected double refine(DBIDRef id, O q) { AbstractRefiningIndex.this.countRefinements(1); return distanceQuery.distance(q, id); } @@ -145,13 +144,13 @@ public abstract class AbstractRefiningIndex<O> extends AbstractIndex<O> { * * @apiviz.excludeSubtypes */ - public abstract class AbstractKNNQuery<D extends Distance<D>> extends AbstractDistanceKNNQuery<O, D> { + public abstract class AbstractKNNQuery extends AbstractDistanceKNNQuery<O> { /** * Constructor. * * @param distanceQuery Distance query object */ - public AbstractKNNQuery(DistanceQuery<O, D> distanceQuery) { + public AbstractKNNQuery(DistanceQuery<O> distanceQuery) { super(distanceQuery); } @@ -162,7 +161,7 @@ public abstract class AbstractRefiningIndex<O> extends AbstractIndex<O> { * @param q Query object * @return Distance */ - protected D refine(DBID id, O q) { + protected double refine(DBIDRef id, O q) { AbstractRefiningIndex.this.countRefinements(1); return distanceQuery.distance(q, id); } diff --git a/src/de/lmu/ifi/dbs/elki/index/DistanceIndex.java b/src/de/lmu/ifi/dbs/elki/index/DistanceIndex.java new file mode 100644 index 00000000..b9094c24 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/DistanceIndex.java @@ -0,0 +1,52 @@ +package de.lmu.ifi.dbs.elki.index; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2014 + 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.query.distance.DistanceQuery; +import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; + +/** + * Index with support for distance queries (e.g. precomputed distance matrixes, + * caches) + * + * @author Erich Schubert + * + * @apiviz.landmark + * @apiviz.excludeSubtypes + * @apiviz.has DistanceQuery oneway - - «provides» + * + * @param <O> Object type + */ +public interface DistanceIndex<O> extends Index { + /** + * Get a KNN query object for the given distance query and k. + * + * This function MAY return null, when the given distance is not supported! + * + * @param distanceFunction Distance function to use. + * @param hints Hints for the optimizer + * @return KNN Query object or {@code null} + */ + DistanceQuery<O> getDistanceQuery(DistanceFunction<? super O> distanceFunction, Object... hints); +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/DynamicIndex.java b/src/de/lmu/ifi/dbs/elki/index/DynamicIndex.java index 53f6d5fe..c6307dc3 100644 --- a/src/de/lmu/ifi/dbs/elki/index/DynamicIndex.java +++ b/src/de/lmu/ifi/dbs/elki/index/DynamicIndex.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/Index.java b/src/de/lmu/ifi/dbs/elki/index/Index.java index e2156a04..beb1df1c 100644 --- a/src/de/lmu/ifi/dbs/elki/index/Index.java +++ b/src/de/lmu/ifi/dbs/elki/index/Index.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/IndexFactory.java b/src/de/lmu/ifi/dbs/elki/index/IndexFactory.java index 80ac2ef5..6d82d2c5 100644 --- a/src/de/lmu/ifi/dbs/elki/index/IndexFactory.java +++ b/src/de/lmu/ifi/dbs/elki/index/IndexFactory.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -25,7 +25,6 @@ package de.lmu.ifi.dbs.elki.index; import de.lmu.ifi.dbs.elki.data.type.TypeInformation; import de.lmu.ifi.dbs.elki.database.relation.Relation; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable; /** * Factory interface for indexes. @@ -39,7 +38,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable; * @param <V> Input object type * @param <I> Index type */ -public interface IndexFactory<V, I extends Index> extends Parameterizable { +public interface IndexFactory<V, I extends Index> { /** * Sets the database in the distance function of this index (if existing). * diff --git a/src/de/lmu/ifi/dbs/elki/index/KNNIndex.java b/src/de/lmu/ifi/dbs/elki/index/KNNIndex.java index 0384a437..9944bd80 100644 --- a/src/de/lmu/ifi/dbs/elki/index/KNNIndex.java +++ b/src/de/lmu/ifi/dbs/elki/index/KNNIndex.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -25,7 +25,6 @@ package de.lmu.ifi.dbs.elki.index; import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery; -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; /** * Index with support for kNN queries. @@ -44,10 +43,9 @@ public interface KNNIndex<O> extends Index { * * This function MAY return null, when the given distance is not supported! * - * @param <D> Distance type * @param distanceQuery Distance query * @param hints Hints for the optimizer * @return KNN Query object or {@code null} */ - <D extends Distance<D>> KNNQuery<O, D> getKNNQuery(DistanceQuery<O, D> distanceQuery, Object... hints); + KNNQuery<O> getKNNQuery(DistanceQuery<O> distanceQuery, Object... hints); }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/PagedIndexFactory.java b/src/de/lmu/ifi/dbs/elki/index/PagedIndexFactory.java index 211a0fb3..a905f6f2 100644 --- a/src/de/lmu/ifi/dbs/elki/index/PagedIndexFactory.java +++ b/src/de/lmu/ifi/dbs/elki/index/PagedIndexFactory.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/RKNNIndex.java b/src/de/lmu/ifi/dbs/elki/index/RKNNIndex.java index 5a1f0f84..e5e32842 100644 --- a/src/de/lmu/ifi/dbs/elki/index/RKNNIndex.java +++ b/src/de/lmu/ifi/dbs/elki/index/RKNNIndex.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -25,7 +25,6 @@ package de.lmu.ifi.dbs.elki.index; import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; import de.lmu.ifi.dbs.elki.database.query.rknn.RKNNQuery; -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; /** * Index with support for kNN queries. @@ -44,10 +43,9 @@ public interface RKNNIndex<O> extends Index { * * This function MAY return null, when the given distance is not supported! * - * @param <D> Distance type * @param distanceQuery Distance query * @param hints Hints for the optimizer * @return KNN Query object or {@code null} */ - <D extends Distance<D>> RKNNQuery<O, D> getRKNNQuery(DistanceQuery<O, D> distanceQuery, Object... hints); + RKNNQuery<O> getRKNNQuery(DistanceQuery<O> distanceQuery, Object... hints); }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/RangeIndex.java b/src/de/lmu/ifi/dbs/elki/index/RangeIndex.java index cc5b7493..7a951c0b 100644 --- a/src/de/lmu/ifi/dbs/elki/index/RangeIndex.java +++ b/src/de/lmu/ifi/dbs/elki/index/RangeIndex.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -25,7 +25,6 @@ package de.lmu.ifi.dbs.elki.index; import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery; -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; /** * Index with support for kNN queries. @@ -44,10 +43,9 @@ public interface RangeIndex<O> extends Index { * * This function MAY return null, when the given distance is not supported! * - * @param <D> Distance type * @param distanceQuery Distance query * @param hints Hints for the optimizer * @return KNN Query object or {@code null} */ - <D extends Distance<D>> RangeQuery<O, D> getRangeQuery(DistanceQuery<O, D> distanceQuery, Object... hints); + RangeQuery<O> getRangeQuery(DistanceQuery<O> distanceQuery, Object... hints); }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/distancematrix/PrecomputedDistanceMatrix.java b/src/de/lmu/ifi/dbs/elki/index/distancematrix/PrecomputedDistanceMatrix.java new file mode 100644 index 00000000..83612236 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/distancematrix/PrecomputedDistanceMatrix.java @@ -0,0 +1,293 @@ +package de.lmu.ifi.dbs.elki.index.distancematrix; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2014 + 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.data.type.TypeInformation; +import de.lmu.ifi.dbs.elki.database.ids.DBIDArrayIter; +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.query.distance.DistanceQuery; +import de.lmu.ifi.dbs.elki.database.relation.Relation; +import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; +import de.lmu.ifi.dbs.elki.index.AbstractIndex; +import de.lmu.ifi.dbs.elki.index.DistanceIndex; +import de.lmu.ifi.dbs.elki.index.IndexFactory; +import de.lmu.ifi.dbs.elki.logging.Logging; +import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress; +import de.lmu.ifi.dbs.elki.logging.statistics.LongStatistic; +import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter; + +/** + * Distance matrix, for precomputing similarity for a small data set. + * + * This class uses a linear memory layout (not a ragged array), and assumes + * symmetry as well as strictness. This way, it only stores the upper triangle + * matrix with double precision. It has to store (n-1) * (n-2) distance values + * in memory, requiring 8 * (n-1) * (n-2) bytes. Since Java has a size limit of + * arrays of 31 bits (signed integer), we can store at most 2^16 objects + * (precisely, 65536 objects) in a single array, which needs about 16 GB of RAM. + * + * @author Erich Schubert + * + * @apiviz.has PrecomputedDistanceQuery + * + * @param <O> Object type + */ +public class PrecomputedDistanceMatrix<O> extends AbstractIndex<O> implements DistanceIndex<O> { + /** + * Class logger. + */ + private static final Logging LOG = Logging.getLogger(PrecomputedDistanceMatrix.class); + + /** + * Nested distance function. + */ + final protected DistanceFunction<? super O> distanceFunction; + + /** + * Nested distance query. + */ + protected DistanceQuery<O> distanceQuery; + + /** + * Distance matrix. + */ + private double[] matrix = null; + + /** + * DBID range. + */ + private DBIDRange ids; + + /** + * Size of DBID range. + */ + private int size; + + /** + * Constructor. + * + * @param relation Data relation + * @param distanceFunction Distance function + */ + public PrecomputedDistanceMatrix(Relation<O> relation, DistanceFunction<? super O> distanceFunction) { + super(relation); + this.distanceFunction = distanceFunction; + + if(!distanceFunction.isSymmetric()) { + throw new AbortException("Distance matrixes currently only support symmetric distance functions (Patches welcome)."); + } + } + + @Override + public void initialize() { + DBIDs rids = relation.getDBIDs(); + if(!(rids instanceof DBIDRange)) { + throw new AbortException("Distance matrixes are currently only supported for DBID ranges (as used by static databases) for performance reasons (Patches welcome)."); + } + ids = (DBIDRange) rids; + size = ids.size(); + if(size > 65536) { + throw new AbortException("Distance matrixes currently have a limit of 65536 objects (~16 GB). After this, the array size exceeds the Java integer range, and a different data structure needs to be used."); + } + + distanceQuery = distanceFunction.instantiate(relation); + + int msize = triangleSize(size); + matrix = new double[msize]; + DBIDArrayIter ix = ids.iter(), iy = ids.iter(); + + FiniteProgress prog = LOG.isVerbose() ? new FiniteProgress("Precomputing distance matrix", msize, LOG) : null; + int pos = 0; + for(ix.seek(0); ix.valid(); ix.advance()) { + // y < x -- must match {@link #getOffset}! + for(iy.seek(0); iy.getOffset() < ix.getOffset(); iy.advance()) { + matrix[pos] = distanceQuery.distance(ix, iy); + pos++; + LOG.incrementProcessed(prog); + } + } + LOG.ensureCompleted(prog); + } + + /** + * Compute the size of a complete x by x triangle (minus diagonal) + * + * @param x Offset + * @return Size of complete triangle + */ + protected static int triangleSize(int x) { + return (x * (x - 1)) >>> 1; + } + + /** + * Array offset computation. + * + * @param x X parameter + * @param y Y parameter + * @return Array offset + */ + private int getOffset(int x, int y) { + return (y < x) ? (triangleSize(x) + y) : (triangleSize(y) + x); + } + + @Override + public void logStatistics() { + if(matrix != null) { + LOG.statistics(new LongStatistic(this.getClass().getName() + ".matrix-size", matrix.length)); + } + } + + @Override + public String getLongName() { + return "Precomputed Distance Matrix"; + } + + @Override + public String getShortName() { + return "distance-matrix"; + } + + @Override + public DistanceQuery<O> getDistanceQuery(DistanceFunction<? super O> distanceFunction, Object... hints) { + if(this.distanceQuery.getDistanceFunction().equals(distanceFunction)) { + return new PrecomputedDistanceQuery(); + } + return null; + } + + /** + * Distance query using the precomputed matrix. + * + * @author Erich Schubert + */ + private class PrecomputedDistanceQuery implements DistanceQuery<O> { + @Override + public double distance(DBIDRef id1, DBIDRef id2) { + final int x = ids.getOffset(id1), y = ids.getOffset(id2); + return (x != y) ? matrix[getOffset(x, y)] : 0.; + } + + @Override + public double distance(O o1, DBIDRef id2) { + return distanceQuery.distance(o1, id2); + } + + @Override + public double distance(DBIDRef id1, O o2) { + return distanceQuery.distance(id1, o2); + } + + @Override + public double distance(O o1, O o2) { + return distanceQuery.distance(o1, o2); + } + + @Override + public DistanceFunction<? super O> getDistanceFunction() { + return distanceQuery.getDistanceFunction(); + } + + @Override + public Relation<? extends O> getRelation() { + return relation; + } + } + + /** + * Factory for the index. + * + * @author Erich Schubert + * + * @apiviz.has PrecomputedDistanceMatrix + * + * @param <O> Object type + */ + public static class Factory<O> implements IndexFactory<O, PrecomputedDistanceMatrix<O>> { + /** + * Nested distance function. + */ + final protected DistanceFunction<? super O> distanceFunction; + + /** + * Constructor. + * + * @param distanceFunction Distance function + */ + public Factory(DistanceFunction<? super O> distanceFunction) { + super(); + this.distanceFunction = distanceFunction; + } + + @Override + public PrecomputedDistanceMatrix<O> instantiate(Relation<O> relation) { + return new PrecomputedDistanceMatrix<>(relation, distanceFunction); + } + + @Override + public TypeInformation getInputTypeRestriction() { + return distanceFunction.getInputTypeRestriction(); + } + + /** + * Parameterizer. + * + * @author Erich Schubert + * + * @apiviz.exclude + * + * @param <O> Object type + */ + public static class Parameterizer<O> extends AbstractParameterizer { + /** + * Option parameter for the precomputed distance matrix. + */ + public static final OptionID DISTANCE_ID = new OptionID("matrix.distance", "Distance function for the precomputed distance matrix."); + + /** + * Nested distance function. + */ + protected DistanceFunction<? super O> distanceFunction; + + @Override + protected void makeOptions(Parameterization config) { + super.makeOptions(config); + ObjectParameter<DistanceFunction<? super O>> distanceP = new ObjectParameter<>(DISTANCE_ID, DistanceFunction.class); + if(config.grab(distanceP)) { + distanceFunction = distanceP.instantiateClass(config); + } + } + + @Override + protected Factory<O> makeInstance() { + return new Factory<>(distanceFunction); + } + } + } +} diff --git a/src/de/lmu/ifi/dbs/elki/index/distancematrix/package-info.java b/src/de/lmu/ifi/dbs/elki/index/distancematrix/package-info.java new file mode 100644 index 00000000..08593048 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/distancematrix/package-info.java @@ -0,0 +1,27 @@ +/** + * Precomputed distance matrix. + */ + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2014 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package de.lmu.ifi.dbs.elki.index.distancematrix;
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/idistance/InMemoryIDistanceIndex.java b/src/de/lmu/ifi/dbs/elki/index/idistance/InMemoryIDistanceIndex.java new file mode 100644 index 00000000..926e77ad --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/idistance/InMemoryIDistanceIndex.java @@ -0,0 +1,559 @@ +package de.lmu.ifi.dbs.elki.index.idistance; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2014 + 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.algorithm.clustering.kmeans.initialization.KMedoidsInitialization; +import de.lmu.ifi.dbs.elki.data.type.TypeInformation; +import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs; +import de.lmu.ifi.dbs.elki.database.ids.DBIDArrayIter; +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.DoubleDBIDList; +import de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDListIter; +import de.lmu.ifi.dbs.elki.database.ids.KNNHeap; +import de.lmu.ifi.dbs.elki.database.ids.KNNList; +import de.lmu.ifi.dbs.elki.database.ids.ModifiableDoubleDBIDList; +import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; +import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery; +import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery; +import de.lmu.ifi.dbs.elki.database.relation.Relation; +import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; +import de.lmu.ifi.dbs.elki.index.AbstractRefiningIndex; +import de.lmu.ifi.dbs.elki.index.IndexFactory; +import de.lmu.ifi.dbs.elki.index.KNNIndex; +import de.lmu.ifi.dbs.elki.index.RangeIndex; +import de.lmu.ifi.dbs.elki.logging.Logging; +import de.lmu.ifi.dbs.elki.logging.statistics.DoubleStatistic; +import de.lmu.ifi.dbs.elki.logging.statistics.LongStatistic; +import de.lmu.ifi.dbs.elki.math.MeanVarianceMinMax; +import de.lmu.ifi.dbs.elki.utilities.documentation.Reference; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.CommonConstraints; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter; +import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleIntPair; + +/** + * In-memory iDistance index, a metric indexing method using a reference point + * embedding. + * + * <b>Important note:</b> we are currently using a different query strategy. The + * original publication discusses queries based on repeated <em>radius</em> + * queries. We use a strategy based on shrinking spheres, iteratively refined + * starting with the closes reference point. We also do not use a B+-tree as + * data structure, but simple in-memory lists. Therefore, we cannot report page + * accesses needed. + * + * Feel free to contribute improved query strategies. All the code is + * essentially here, you only need to query every reference point list, not just + * the best. + * + * Reference: + * <p> + * C. Yu, B. C. Ooi, K. L. Tan, H. V. Jagadish<br /> + * Indexing the Distance: An Efficient Method to KNN Processing.<br /> + * In Proceedings of the 27th International Conference on Very Large Data Bases + * </p> + * + * <p> + * H. V. Jagadish, B. C. Ooi, K. L. Tan, C. Yu, R. Zhang<br /> + * iDistance: An adaptive B+-tree based indexing method for nearest neighbor + * search.<br /> + * ACM Transactions on Database Systems (TODS), 30(2), 364-397. + * </p> + * + * @author Erich Schubert + * + * @param <O> Object type + */ +@Reference(authors = "C. Yu, B. C. Ooi, K. L. Tan, H. V. Jagadish", title = "Indexing the distance: An efficient method to knn processing", booktitle = "In Proceedings of the 27th International Conference on Very Large Data Bases", url = "http://www.vldb.org/conf/2001/P421.pdf") +public class InMemoryIDistanceIndex<O> extends AbstractRefiningIndex<O> implements RangeIndex<O>, KNNIndex<O> { + /** + * Class logger. + */ + private static final Logging LOG = Logging.getLogger(InMemoryIDistanceIndex.class); + + /** + * Distance query. + */ + private DistanceQuery<O> distanceQuery; + + /** + * Initialization method. + */ + private KMedoidsInitialization<O> initialization; + + /** + * Number of reference points. + */ + private int numref; + + /** + * Reference points. + */ + private ArrayDBIDs referencepoints; + + /** + * The actual index. + */ + private ModifiableDoubleDBIDList[] index; + + /** + * Second reference, for documentation generation. + */ + @Reference(authors = "H. V. Jagadish, B. C. Ooi, K. L. Tan, C. Yu, R. Zhang", title = "iDistance: An adaptive B+-tree based indexing method for nearest neighbor search", booktitle = "ACM Transactions on Database Systems (TODS), 30(2), 364-397") + public static final Void SECOND_REFERENCE = null; + + /** + * Constructor. + * + * @param relation Data relation + * @param distance Distance + * @param initialization Initialization method + * @param numref Number of reference points + */ + public InMemoryIDistanceIndex(Relation<O> relation, DistanceQuery<O> distance, KMedoidsInitialization<O> initialization, int numref) { + super(relation); + this.distanceQuery = distance; + this.initialization = initialization; + this.numref = numref; + if(!distance.getDistanceFunction().isMetric()) { + LOG.warning("iDistance assumes metric distance functions.\n" // + + distance.getDistanceFunction().getClass() + " does not report itself as metric.\n" // + + "iDistance will run, but may yield approximate results."); + } + } + + @Override + public void initialize() { + referencepoints = DBIDUtil.ensureArray(initialization.chooseInitialMedoids(numref, relation.getDBIDs(), distanceQuery)); + final int k = referencepoints.size(); // should be the same k anyway. + index = new ModifiableDoubleDBIDList[k]; + for(int i = 0; i < k; i++) { + index[i] = DBIDUtil.newDistanceDBIDList(relation.size() / (2 * k)); + } + // TODO: add optimized codepath for primitive distances. + DBIDArrayIter riter = referencepoints.iter(); + for(DBIDIter oiter = relation.iterDBIDs(); oiter.valid(); oiter.advance()) { + double bestd = Double.POSITIVE_INFINITY; + int besti = -1; + for(riter.seek(0); riter.valid(); riter.advance()) { + double dist = distanceQuery.distance(oiter, riter); + if(dist < bestd) { + bestd = dist; + besti = riter.getOffset(); + } + } + assert (besti >= 0 && besti < k); + index[besti].add(bestd, oiter); + } + + // Sort index. + for(int i = 0; i < k; i++) { + index[i].sort(); + } + } + + @Override + public KNNQuery<O> getKNNQuery(DistanceQuery<O> distanceQuery, Object... hints) { + // Query on the relation we index + if(distanceQuery.getRelation() != relation) { + return null; + } + DistanceFunction<? super O> distanceFunction = (DistanceFunction<? super O>) distanceQuery.getDistanceFunction(); + if(!this.getDistanceFunction().equals(distanceFunction)) { + if(LOG.isDebugging()) { + LOG.debug("Distance function not supported by index - or 'equals' not implemented right!"); + } + return null; + } + return new IDistanceKNNQuery(distanceQuery); + } + + @Override + public RangeQuery<O> getRangeQuery(DistanceQuery<O> distanceQuery, Object... hints) { + // Query on the relation we index + if(distanceQuery.getRelation() != relation) { + return null; + } + DistanceFunction<? super O> distanceFunction = (DistanceFunction<? super O>) distanceQuery.getDistanceFunction(); + if(!this.getDistanceFunction().equals(distanceFunction)) { + if(LOG.isDebugging()) { + LOG.debug("Distance function not supported by index - or 'equals' not implemented right!"); + } + return null; + } + return new IDistanceRangeQuery(distanceQuery); + } + + /** + * Distance function. + * + * @return Distance function + */ + private DistanceFunction<? super O> getDistanceFunction() { + return distanceQuery.getDistanceFunction(); + } + + @Override + public String getLongName() { + return "iDistance index"; + } + + @Override + public String getShortName() { + return "idistance-index"; + } + + @Override + public Logging getLogger() { + return LOG; + } + + @Override + public void logStatistics() { + super.logStatistics(); + MeanVarianceMinMax mm = new MeanVarianceMinMax(); + for(int i = 0; i < index.length; i++) { + mm.put(index[i].size()); + } + LOG.statistics(new LongStatistic(InMemoryIDistanceIndex.class.getName() + ".size.min", (int) mm.getMin())); + LOG.statistics(new DoubleStatistic(InMemoryIDistanceIndex.class.getName() + ".size.mean", mm.getMean())); + LOG.statistics(new LongStatistic(InMemoryIDistanceIndex.class.getName() + ".size.max", (int) mm.getMax())); + } + + /** + * Sort the reference points by distance to the query object + * + * @param distanceQuery Distance query + * @param obj Query object + * @param referencepoints Iterator for reference points + * @return Sorted array. + */ + protected static <O> DoubleIntPair[] rankReferencePoints(DistanceQuery<O> distanceQuery, O obj, ArrayDBIDs referencepoints) { + DoubleIntPair[] priority = new DoubleIntPair[referencepoints.size()]; + // Compute distances to reference points. + for(DBIDArrayIter iter = referencepoints.iter(); iter.valid(); iter.advance()) { + final int i = iter.getOffset(); + final double dist = distanceQuery.distance(obj, iter); + priority[i] = new DoubleIntPair(dist, i); + } + Arrays.sort(priority); + return priority; + } + + /** + * Seek an iterator to the desired position, using binary search. + * + * @param index Index to search + * @param iter Iterator + * @param val Distance to search to + */ + protected static void binarySearch(ModifiableDoubleDBIDList index, DoubleDBIDListIter iter, double val) { + // Binary search. TODO: move this into the DoubleDBIDList class. + int left = 0, right = index.size(); + while(left < right) { + final int mid = (left + right) >>> 1; + final double curd = iter.seek(mid).doubleValue(); + if(val < curd) { + right = mid; + } + else if(val > curd) { + left = mid + 1; + } + else { + left = mid; + break; + } + } + if(left >= index.size()) { + --left; + } + iter.seek(left); + } + + /** + * kNN query implementation. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + protected class IDistanceKNNQuery extends AbstractRefiningIndex<O>.AbstractKNNQuery { + /** + * Constructor. + * + * @param distanceQuery Distance query + */ + public IDistanceKNNQuery(DistanceQuery<O> distanceQuery) { + super(distanceQuery); + } + + @Override + public KNNList getKNNForObject(O obj, int k) { + DoubleIntPair[] priority = rankReferencePoints(distanceQuery, obj, referencepoints); + // Approximate kNN search. We do not check _every_ list. + KNNHeap heap = DBIDUtil.newHeap(k); + + for(DoubleIntPair pair : priority) { + final ModifiableDoubleDBIDList nindex = index[pair.second]; + final double refd = pair.first; + + final DoubleDBIDListIter ifwd = nindex.iter(), ibwd = nindex.iter(); + binarySearch(nindex, ibwd, refd); + ifwd.seek(ibwd.getOffset() + 1); + + // This assumes a metric, as we exploit triangle inequality: + // Lower bound for candidates further from the reference object: + // d(candidate, reference) <= d(candidate, query) + d(query, reference) + // d(candidate, reference) - d(query, reference) <= d(candidate, query) + double lbfwd = ifwd.valid() ? Math.abs(ifwd.doubleValue() - refd) : Double.NaN; + // Lower bound for candidates closer to the reference object: + // d(query, reference) <= d(query, candidate) + d(candidate, reference) + // d(query, reference) - d(candidate, reference) <= d(query, candidate) + double lbbwd = ibwd.valid() ? Math.abs(ibwd.doubleValue() - refd) : Double.NaN; + // Current query radius. + double kdist = heap.getKNNDistance(); + while(true) { + // Handle NaN carefully. + if(!(lbfwd <= kdist) && !(lbbwd <= kdist)) { + break; + } + // Careful: NaN handling: not NaN and not worse than fwd (may be NaN). + if(lbfwd <= kdist && !(lbfwd > lbbwd)) { + final double dist = refine(ifwd, obj); + if(dist <= kdist) { + heap.insert(dist, ifwd); + kdist = heap.getKNNDistance(); + } + // Advance iterator: + ifwd.advance(); + lbfwd = ifwd.valid() ? Math.abs(ifwd.doubleValue() - refd) : Double.NaN; + } + if(lbbwd <= kdist && !(lbbwd > lbfwd)) { + final double dist = refine(ibwd, obj); + if(dist <= kdist) { + heap.insert(dist, ibwd); + kdist = heap.getKNNDistance(); + } + // Retract iterator: + ibwd.retract(); + lbbwd = ibwd.valid() ? Math.abs(ibwd.doubleValue() - refd) : Double.NaN; + } + } + } + + return heap.toKNNList(); + } + } + + /** + * Exact Range query implementation. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + protected class IDistanceRangeQuery extends AbstractRefiningIndex<O>.AbstractRangeQuery { + /** + * Constructor. + * + * @param distanceQuery Distance query + */ + public IDistanceRangeQuery(DistanceQuery<O> distanceQuery) { + super(distanceQuery); + } + + @Override + public DoubleDBIDList getRangeForObject(O obj, double range) { + DoubleIntPair[] priority = rankReferencePoints(distanceQuery, obj, referencepoints); + ModifiableDoubleDBIDList result = DBIDUtil.newDistanceDBIDList(); + for(DoubleIntPair pair : priority) { + final ModifiableDoubleDBIDList nindex = index[pair.second]; + final double refd = pair.first; + + DoubleDBIDListIter ifwd = nindex.iter(), ibwd = nindex.iter(); + binarySearch(nindex, ibwd, refd); + ifwd.seek(ibwd.getOffset() + 1); + + // This assumes a metric, as we exploit triangle inequality: + // Lower bound for candidates further from the reference object: + // d(candidate, reference) <= d(candidate, query) + d(query, reference) + // d(candidate, reference) - d(query, reference) <= d(candidate, query) + double lbfwd = ifwd.valid() ? Math.abs(ifwd.doubleValue() - refd) : Double.NaN; + // Lower bound for candidates closer to the reference object: + // d(query, reference) <= d(query, candidate) + d(candidate, reference) + // d(query, reference) - d(candidate, reference) <= d(query, candidate) + double lbbwd = ibwd.valid() ? Math.abs(ibwd.doubleValue() - refd) : Double.NaN; + while(true) { + // Handle NaN carefully. + if(!(lbfwd <= range) && !(lbbwd <= range)) { + break; + } + // Careful: NaN handling: not NaN and not worse than fwd (may be NaN). + if(lbfwd <= range && !(lbfwd > lbbwd)) { + final double dist = refine(ifwd, obj); + if(dist <= range) { + result.add(dist, ifwd); + } + // Advance iterator: + ifwd.advance(); + lbfwd = ifwd.valid() ? Math.abs(ifwd.doubleValue() - refd) : Double.NaN; + } + if(lbbwd <= range && !(lbbwd > lbfwd)) { + final double dist = refine(ibwd, obj); + if(dist <= range) { + result.add(dist, ibwd); + } + // Retract iterator: + ibwd.retract(); + lbbwd = ibwd.valid() ? Math.abs(ibwd.doubleValue() - refd) : Double.NaN; + } + } + } + result.sort(); + return result; + } + } + + /** + * Index factory for iDistance indexes. + * + * @author Erich Schubert + * + * @apiviz.has InMemoryIDistanceIndex + * + * @param <V> Data type. + */ + public static class Factory<V> implements IndexFactory<V, InMemoryIDistanceIndex<V>> { + /** + * Distance function to use. + */ + DistanceFunction<? super V> distance; + + /** + * Initialization method. + */ + KMedoidsInitialization<V> initialization; + + /** + * Number of reference points + */ + int k; + + /** + * Constructor. + * + * @param distance Distance function + * @param initialization Initialization method + * @param k Number of reference points + */ + public Factory(DistanceFunction<? super V> distance, KMedoidsInitialization<V> initialization, int k) { + super(); + this.distance = distance; + this.initialization = initialization; + this.k = k; + } + + @Override + public InMemoryIDistanceIndex<V> instantiate(Relation<V> relation) { + return new InMemoryIDistanceIndex<>(relation, distance.instantiate(relation), initialization, k); + } + + @Override + public TypeInformation getInputTypeRestriction() { + return distance.getInputTypeRestriction(); + } + + /** + * Parameterization class. + * + * @author Erich Schubert + * + * @apiviz.exclude + * + * @param <V> object type. + */ + public static class Parameterizer<V> extends AbstractParameterizer { + /** + * Parameter for the distance function + */ + public static final OptionID DISTANCE_ID = new OptionID("idistance.distance", "Distance function to build the index for."); + + /** + * Initialization method. + */ + public static final OptionID REFERENCE_ID = new OptionID("idistance.reference", "Method to choose the reference points."); + + /** + * Number of reference points. + */ + public static final OptionID K_ID = new OptionID("idistance.k", "Number of reference points to use."); + + /** + * Distance function to use. + */ + DistanceFunction<? super V> distance; + + /** + * Initialization method. + */ + KMedoidsInitialization<V> initialization; + + /** + * Number of reference points + */ + int k; + + @Override + protected void makeOptions(Parameterization config) { + super.makeOptions(config); + ObjectParameter<DistanceFunction<? super V>> distanceP = new ObjectParameter<>(DISTANCE_ID, DistanceFunction.class); + if(config.grab(distanceP)) { + distance = distanceP.instantiateClass(config); + } + + ObjectParameter<KMedoidsInitialization<V>> initializationP = new ObjectParameter<>(REFERENCE_ID, KMedoidsInitialization.class); + if(config.grab(initializationP)) { + initialization = initializationP.instantiateClass(config); + } + + IntParameter kP = new IntParameter(K_ID)// + .addConstraint(CommonConstraints.GREATER_EQUAL_ONE_INT); + if(config.grab(kP)) { + k = kP.intValue(); + } + } + + @Override + protected InMemoryIDistanceIndex.Factory<V> makeInstance() { + return new InMemoryIDistanceIndex.Factory<>(distance, initialization, k); + } + } + } +} diff --git a/src/de/lmu/ifi/dbs/elki/index/idistance/package-info.java b/src/de/lmu/ifi/dbs/elki/index/idistance/package-info.java new file mode 100644 index 00000000..7b1fb9a7 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/idistance/package-info.java @@ -0,0 +1,27 @@ +/** + * iDistance is a distance based indexing technique, using a reference points embedding. + */ + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2014 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package de.lmu.ifi.dbs.elki.index.idistance;
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/invertedlist/InMemoryInvertedIndex.java b/src/de/lmu/ifi/dbs/elki/index/invertedlist/InMemoryInvertedIndex.java new file mode 100644 index 00000000..91d2da7a --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/invertedlist/InMemoryInvertedIndex.java @@ -0,0 +1,474 @@ +package de.lmu.ifi.dbs.elki.index.invertedlist; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2014 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +import java.util.ArrayList; + +import de.lmu.ifi.dbs.elki.data.NumberVector; +import de.lmu.ifi.dbs.elki.data.SparseNumberVector; +import de.lmu.ifi.dbs.elki.data.type.TypeInformation; +import de.lmu.ifi.dbs.elki.data.type.TypeUtil; +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.WritableDoubleDataStore; +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.DoubleDBIDList; +import de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDListIter; +import de.lmu.ifi.dbs.elki.database.ids.HashSetModifiableDBIDs; +import de.lmu.ifi.dbs.elki.database.ids.KNNHeap; +import de.lmu.ifi.dbs.elki.database.ids.KNNList; +import de.lmu.ifi.dbs.elki.database.ids.ModifiableDoubleDBIDList; +import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; +import de.lmu.ifi.dbs.elki.database.query.knn.AbstractDistanceKNNQuery; +import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery; +import de.lmu.ifi.dbs.elki.database.query.range.AbstractDistanceRangeQuery; +import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery; +import de.lmu.ifi.dbs.elki.database.relation.Relation; +import de.lmu.ifi.dbs.elki.distance.distancefunction.ArcCosineDistanceFunction; +import de.lmu.ifi.dbs.elki.distance.distancefunction.CosineDistanceFunction; +import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; +import de.lmu.ifi.dbs.elki.index.AbstractIndex; +import de.lmu.ifi.dbs.elki.index.IndexFactory; +import de.lmu.ifi.dbs.elki.index.KNNIndex; +import de.lmu.ifi.dbs.elki.index.RangeIndex; +import de.lmu.ifi.dbs.elki.logging.Logging; +import de.lmu.ifi.dbs.elki.logging.statistics.DoubleStatistic; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer; + +/** + * Simple index using inverted lists. + * + * @author Erich Schubert + * + * @param <V> Vector type + */ +public class InMemoryInvertedIndex<V extends NumberVector> extends AbstractIndex<V> implements KNNIndex<V>, RangeIndex<V> { + /** + * Class logger. + */ + private static final Logging LOG = Logging.getLogger(InMemoryInvertedIndex.class); + + /** + * Inverted index. + */ + ArrayList<ModifiableDoubleDBIDList> index; + + /** + * Length storage. + */ + WritableDoubleDataStore length; + + /** + * Constructor. + * + * @param relation Data. + */ + public InMemoryInvertedIndex(Relation<V> relation) { + super(relation); + } + + @Override + public void initialize() { + if(index != null) { + LOG.warning("Index was already initialized!"); + } + index = new ArrayList<>(); + length = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_DB); + for(DBIDIter iter = relation.iterDBIDs(); iter.valid(); iter.advance()) { + V obj = relation.get(iter); + if(obj instanceof SparseNumberVector) { + indexSparse(iter, (SparseNumberVector) obj); + } + else { + indexDense(iter, obj); + } + } + // Sort indexes + long count = 0L; + for(ModifiableDoubleDBIDList column : index) { + column.sort(); + count += column.size(); + } + double sparsity = count / (index.size() * (double) relation.size()); + if(sparsity > .2) { + LOG.warning("Inverted list indexes only perform well for very sparse data. Your data set has a sparsity of " + sparsity); + } + } + + /** + * Index a single (sparse) instance. + * + * @param ref Object reference + * @param obj Object to index. + */ + private void indexSparse(DBIDRef ref, SparseNumberVector obj) { + double len = 0.; + for(int iter = obj.iter(); obj.iterValid(iter); iter = obj.iterAdvance(iter)) { + final int dim = obj.iterDim(iter); + final double val = obj.iterDoubleValue(iter); + if(val == 0. || val != val) { + continue; + } + len += val * val; + getOrCreateColumn(dim).add(val, ref); + } + length.put(ref, len); + } + + /** + * Index a single (dense) instance. + * + * @param ref Object reference + * @param obj Object to index. + */ + private void indexDense(DBIDRef ref, V obj) { + double len = 0.; + for(int dim = 0, max = obj.getDimensionality(); dim < max; dim++) { + final double val = obj.doubleValue(dim); + if(val == 0. || val != val) { + continue; + } + len += val * val; + getOrCreateColumn(dim).add(val, ref); + } + length.put(ref, Math.sqrt(len)); + } + + /** + * Get (or create) a column. + * + * @param dim Dimension + * @return Column + */ + private ModifiableDoubleDBIDList getOrCreateColumn(int dim) { + while(dim >= index.size()) { + index.add(DBIDUtil.newDistanceDBIDList()); + } + return index.get(dim); + } + + /** + * Query the most similar objects, sparse version. + * + * @param obj Query object + * @param scores Score storage + * @param cands Non-zero objects set + * @return Result + */ + private double naiveQuerySparse(SparseNumberVector obj, WritableDoubleDataStore scores, HashSetModifiableDBIDs cands) { + double len = 0.; // Length of query object, for final normalization + for(int iter = obj.iter(); obj.iterValid(iter); iter = obj.iterAdvance(iter)) { + final int dim = obj.iterDim(iter); + final double val = obj.iterDoubleValue(iter); + if(val == 0. || val != val) { + continue; + } + len += val * val; + // No matching documents in index: + if(dim >= index.size()) { + continue; + } + ModifiableDoubleDBIDList column = index.get(dim); + for(DoubleDBIDListIter n = column.iter(); n.valid(); n.advance()) { + scores.increment(n, n.doubleValue() * val); + cands.add(n); + } + } + return Math.sqrt(len); + } + + /** + * Query the most similar objects, dense version. + * + * @param obj Query object + * @param scores Score storage + * @param cands Non-zero objects set + * @return Result + */ + private double naiveQueryDense(NumberVector obj, WritableDoubleDataStore scores, HashSetModifiableDBIDs cands) { + double len = 0.; // Length of query object, for final normalization + for(int dim = 0, max = obj.getDimensionality(); dim < max; dim++) { + final double val = obj.doubleValue(dim); + if(val == 0. || val != val) { + continue; + } + len += val * val; + // No matching documents in index: + if(dim >= index.size()) { + continue; + } + ModifiableDoubleDBIDList column = index.get(dim); + for(DoubleDBIDListIter n = column.iter(); n.valid(); n.advance()) { + scores.increment(n, n.doubleValue() * val); + cands.add(n); + } + } + return Math.sqrt(len); + } + + /** + * Query the most similar objects, abstract version. + * + * @param obj Query object + * @param scores Score storage (must be initialized with zeros!) + * @param cands Non-zero objects set (must be empty) + * @return Result + */ + private double naiveQuery(V obj, WritableDoubleDataStore scores, HashSetModifiableDBIDs cands) { + if(obj instanceof SparseNumberVector) { + return naiveQuerySparse((SparseNumberVector) obj, scores, cands); + } + else { + return naiveQueryDense(obj, scores, cands); + } + } + + @Override + public void logStatistics() { + long count = 0L; + for(ModifiableDoubleDBIDList column : index) { + count += column.size(); + } + double sparsity = count / (index.size() * (double) relation.size()); + LOG.statistics(new DoubleStatistic(this.getClass().getName() + ".sparsity", sparsity)); + } + + @Override + public KNNQuery<V> getKNNQuery(DistanceQuery<V> distanceQuery, Object... hints) { + DistanceFunction<? super V> df = distanceQuery.getDistanceFunction(); + if(df instanceof CosineDistanceFunction) { + return new CosineKNNQuery(distanceQuery); + } + if(df instanceof ArcCosineDistanceFunction) { + return new ArcCosineKNNQuery(distanceQuery); + } + return null; + } + + @Override + public RangeQuery<V> getRangeQuery(DistanceQuery<V> distanceQuery, Object... hints) { + DistanceFunction<? super V> df = distanceQuery.getDistanceFunction(); + if(df instanceof CosineDistanceFunction) { + return new CosineRangeQuery(distanceQuery); + } + if(df instanceof ArcCosineDistanceFunction) { + return new ArcCosineRangeQuery(distanceQuery); + } + return null; + } + + @Override + public String getLongName() { + return "Inverted lists index"; + } + + @Override + public String getShortName() { + return "inverted-lists"; + } + + /** + * kNN query object, for cosine distance. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + protected class CosineKNNQuery extends AbstractDistanceKNNQuery<V> { + /** + * Constructor. + * + * @param distanceQuery Distance query + */ + public CosineKNNQuery(DistanceQuery<V> distanceQuery) { + super(distanceQuery); + } + + @Override + public KNNList getKNNForObject(V obj, int k) { + HashSetModifiableDBIDs cands = DBIDUtil.newHashSet(); + WritableDoubleDataStore scores = DataStoreUtil.makeDoubleStorage(cands, // + DataStoreFactory.HINT_TEMP | DataStoreFactory.HINT_HOT, 0.); + double len = naiveQuery(obj, scores, cands); + // TODO: delay the division by len! + KNNHeap heap = DBIDUtil.newHeap(k); + for(DBIDIter n = cands.iter(); n.valid(); n.advance()) { + double dist = 1. - scores.doubleValue(n) / (length.doubleValue(n) * len); + if(heap.getKNNDistance() >= dist) { + heap.insert(dist, n); + } + } + + return heap.toKNNList(); + } + } + + /** + * kNN query object, for arc cosine distance. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + protected class ArcCosineKNNQuery extends AbstractDistanceKNNQuery<V> { + /** + * Constructor. + * + * @param distanceQuery Distance query + */ + public ArcCosineKNNQuery(DistanceQuery<V> distanceQuery) { + super(distanceQuery); + } + + @Override + public KNNList getKNNForObject(V obj, int k) { + HashSetModifiableDBIDs cands = DBIDUtil.newHashSet(); + WritableDoubleDataStore scores = DataStoreUtil.makeDoubleStorage(cands, // + DataStoreFactory.HINT_TEMP | DataStoreFactory.HINT_HOT, 0.); + double len = naiveQuery(obj, scores, cands); + // TODO: delay the division by len and acos! + KNNHeap heap = DBIDUtil.newHeap(k); + for(DBIDIter n = cands.iter(); n.valid(); n.advance()) { + double dist = Math.acos(scores.doubleValue(n) / (length.doubleValue(n) * len)); + if(heap.getKNNDistance() >= dist) { + heap.insert(dist, n); + } + } + + return heap.toKNNList(); + } + } + + /** + * kNN query object, for cosine distance. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + protected class CosineRangeQuery extends AbstractDistanceRangeQuery<V> { + /** + * Constructor. + * + * @param distanceQuery Distance query + */ + public CosineRangeQuery(DistanceQuery<V> distanceQuery) { + super(distanceQuery); + } + + @Override + public DoubleDBIDList getRangeForObject(V obj, double range) { + HashSetModifiableDBIDs cands = DBIDUtil.newHashSet(); + WritableDoubleDataStore scores = DataStoreUtil.makeDoubleStorage(cands, // + DataStoreFactory.HINT_TEMP | DataStoreFactory.HINT_HOT, 0.); + double len = naiveQuery(obj, scores, cands); + ModifiableDoubleDBIDList list = DBIDUtil.newDistanceDBIDList(); + // dist = 1 - sim/len <-> sim = len * (1-dist) + double simrange = (1. - range) * len; + for(DBIDIter n = cands.iter(); n.valid(); n.advance()) { + double sim = scores.doubleValue(n) / length.doubleValue(n); + if(sim >= simrange) { + list.add(1. - sim / len, n); + } + } + list.sort(); + return list; + } + } + + /** + * kNN query object, for cosine distance. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + protected class ArcCosineRangeQuery extends AbstractDistanceRangeQuery<V> { + /** + * Constructor. + * + * @param distanceQuery Distance query + */ + public ArcCosineRangeQuery(DistanceQuery<V> distanceQuery) { + super(distanceQuery); + } + + @Override + public DoubleDBIDList getRangeForObject(V obj, double range) { + HashSetModifiableDBIDs cands = DBIDUtil.newHashSet(); + WritableDoubleDataStore scores = DataStoreUtil.makeDoubleStorage(cands, // + DataStoreFactory.HINT_TEMP | DataStoreFactory.HINT_HOT, 0.); + double len = naiveQuery(obj, scores, cands); + // dist = acos(sim/len) <-> sim = cos(dist)*len + double simrange = Math.cos(range) * len; + ModifiableDoubleDBIDList list = DBIDUtil.newDistanceDBIDList(); + for(DBIDIter n = cands.iter(); n.valid(); n.advance()) { + double sim = scores.doubleValue(n) / length.doubleValue(n); + if(sim >= simrange) { + list.add(Math.acos(sim / len), n); + } + } + list.sort(); + return list; + } + } + + /** + * Index factory + * + * @author Erich Schubert + * + * @apiviz.has InMemoryInvertedIndex + * + * @param <V> Vector type + */ + public static class Factory<V extends NumberVector> implements IndexFactory<V, InMemoryInvertedIndex<V>> { + @Override + public InMemoryInvertedIndex<V> instantiate(Relation<V> relation) { + return new InMemoryInvertedIndex<>(relation); + } + + @Override + public TypeInformation getInputTypeRestriction() { + return TypeUtil.NUMBER_VECTOR_VARIABLE_LENGTH; + } + + /** + * Parameterizer for inverted list index. + * + * @author Erich Schubert + * + * @apiviz.exclude + * + * @param <V> Vector type + */ + public static class Parameterizer<V extends NumberVector> extends AbstractParameterizer { + @Override + protected Factory<V> makeInstance() { + return new Factory<>(); + } + } + } +} diff --git a/src/de/lmu/ifi/dbs/elki/index/invertedlist/package-info.java b/src/de/lmu/ifi/dbs/elki/index/invertedlist/package-info.java new file mode 100644 index 00000000..55c00f7d --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/invertedlist/package-info.java @@ -0,0 +1,27 @@ +/** + * Indexes using inverted lists. + */ + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2014 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +package de.lmu.ifi.dbs.elki.index.invertedlist;
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/lsh/InMemoryLSHIndex.java b/src/de/lmu/ifi/dbs/elki/index/lsh/InMemoryLSHIndex.java index 8ae3cd69..1915e0ce 100644 --- a/src/de/lmu/ifi/dbs/elki/index/lsh/InMemoryLSHIndex.java +++ b/src/de/lmu/ifi/dbs/elki/index/lsh/InMemoryLSHIndex.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.lsh; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -32,18 +32,17 @@ import de.lmu.ifi.dbs.elki.data.type.TypeInformation; 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.DoubleDBIDList; +import de.lmu.ifi.dbs.elki.database.ids.KNNHeap; +import de.lmu.ifi.dbs.elki.database.ids.KNNList; import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs; -import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNHeap; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList; -import de.lmu.ifi.dbs.elki.database.ids.generic.GenericDistanceDBIDList; +import de.lmu.ifi.dbs.elki.database.ids.ModifiableDoubleDBIDList; import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery; import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery; import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; import de.lmu.ifi.dbs.elki.index.AbstractRefiningIndex; import de.lmu.ifi.dbs.elki.index.IndexFactory; import de.lmu.ifi.dbs.elki.index.KNNIndex; @@ -65,6 +64,9 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter; * * @author Erich Schubert * + * @apiviz.has LocalitySensitiveHashFunctionFamily + * @apiviz.has Instance + * * @param <V> Object type to index */ public class InMemoryLSHIndex<V> implements IndexFactory<V, InMemoryLSHIndex<V>.Instance> { @@ -79,7 +81,7 @@ public class InMemoryLSHIndex<V> implements IndexFactory<V, InMemoryLSHIndex<V>. LocalitySensitiveHashFunctionFamily<? super V> family; /** - * Number of hash functions for each table. + * Number of hash tables to use. */ int l; @@ -116,6 +118,8 @@ public class InMemoryLSHIndex<V> implements IndexFactory<V, InMemoryLSHIndex<V>. * Instance of a LSH index for a single relation. * * @author Erich Schubert + * + * @apiviz.has LocalitySensitiveHashFunction */ public class Instance extends AbstractRefiningIndex<V> implements KNNIndex<V>, RangeIndex<V> { /** @@ -188,13 +192,9 @@ public class InMemoryLSHIndex<V> implements IndexFactory<V, InMemoryLSHIndex<V>. table.put(bucket, newbuck); } } - if(progress != null) { - progress.incrementProcessed(LOG); - } - } - if(progress != null) { - progress.ensureCompleted(LOG); + LOG.incrementProcessed(progress); } + LOG.ensureCompleted(progress); if(LOG.isStatistics()) { int min = Integer.MAX_VALUE, max = 0; for(int i = 0; i < numhash; i++) { @@ -210,8 +210,8 @@ public class InMemoryLSHIndex<V> implements IndexFactory<V, InMemoryLSHIndex<V>. } } } - LOG.statistics(new LongStatistic(this.getClass().getName() + ".fill.min", max)); - LOG.statistics(new LongStatistic(this.getClass().getName() + ".fill.max", min)); + LOG.statistics(new LongStatistic(this.getClass().getName() + ".fill.min", min)); + LOG.statistics(new LongStatistic(this.getClass().getName() + ".fill.max", max)); LOG.statistics(new LongStatistic(this.getClass().getName() + ".hashtables", hashtables.size())); } } @@ -222,31 +222,31 @@ public class InMemoryLSHIndex<V> implements IndexFactory<V, InMemoryLSHIndex<V>. } @Override - public <D extends Distance<D>> KNNQuery<V, D> getKNNQuery(DistanceQuery<V, D> distanceQuery, Object... hints) { + public KNNQuery<V> getKNNQuery(DistanceQuery<V> distanceQuery, Object... hints) { for(Object hint : hints) { if(DatabaseQuery.HINT_EXACT.equals(hint)) { return null; } } - DistanceFunction<? super V, D> df = distanceQuery.getDistanceFunction(); + DistanceFunction<? super V> df = distanceQuery.getDistanceFunction(); if(!family.isCompatible(df)) { return null; } - return (KNNQuery<V, D>) new LSHKNNQuery<>(distanceQuery); + return new LSHKNNQuery(distanceQuery); } @Override - public <D extends Distance<D>> RangeQuery<V, D> getRangeQuery(DistanceQuery<V, D> distanceQuery, Object... hints) { + public RangeQuery<V> getRangeQuery(DistanceQuery<V> distanceQuery, Object... hints) { for(Object hint : hints) { if(DatabaseQuery.HINT_EXACT.equals(hint)) { return null; } } - DistanceFunction<? super V, D> df = distanceQuery.getDistanceFunction(); + DistanceFunction<? super V> df = distanceQuery.getDistanceFunction(); if(!family.isCompatible(df)) { return null; } - return (RangeQuery<V, D>) new LSHRangeQuery<>(distanceQuery); + return new LSHRangeQuery(distanceQuery); } /** @@ -255,21 +255,19 @@ public class InMemoryLSHIndex<V> implements IndexFactory<V, InMemoryLSHIndex<V>. * @author Erich Schubert * * @apiviz.exclude - * - * @param <D> Distance type */ - protected class LSHKNNQuery<D extends Distance<D>> extends AbstractKNNQuery<D> { + protected class LSHKNNQuery extends AbstractKNNQuery { /** * Constructor. * * @param distanceQuery */ - public LSHKNNQuery(DistanceQuery<V, D> distanceQuery) { + public LSHKNNQuery(DistanceQuery<V> distanceQuery) { super(distanceQuery); } @Override - public KNNList<D> getKNNForObject(V obj, int k) { + public KNNList getKNNForObject(V obj, int k) { ModifiableDBIDs candidates = null; final int numhash = hashtables.size(); for(int i = 0; i < numhash; i++) { @@ -292,9 +290,9 @@ public class InMemoryLSHIndex<V> implements IndexFactory<V, InMemoryLSHIndex<V>. } // Refine. - KNNHeap<D> heap = DBIDUtil.newHeap(distanceQuery.getDistanceFactory(), k); + KNNHeap heap = DBIDUtil.newHeap(k); for(DBIDIter iter = candidates.iter(); iter.valid(); iter.advance()) { - final D dist = distanceQuery.distance(obj, iter); + final double dist = distanceQuery.distance(obj, iter); super.incRefinements(1); heap.insert(dist, iter); } @@ -308,21 +306,19 @@ public class InMemoryLSHIndex<V> implements IndexFactory<V, InMemoryLSHIndex<V>. * @author Erich Schubert * * @apiviz.exclude - * - * @param <D> Distance type */ - protected class LSHRangeQuery<D extends Distance<D>> extends AbstractRangeQuery<D> { + protected class LSHRangeQuery extends AbstractRangeQuery { /** * Constructor. * * @param distanceQuery */ - public LSHRangeQuery(DistanceQuery<V, D> distanceQuery) { + public LSHRangeQuery(DistanceQuery<V> distanceQuery) { super(distanceQuery); } @Override - public DistanceDBIDList<D> getRangeForObject(V obj, D range) { + public DoubleDBIDList getRangeForObject(V obj, double range) { ModifiableDBIDs candidates = DBIDUtil.newHashSet(); final int numhash = hashtables.size(); for(int i = 0; i < numhash; i++) { @@ -339,11 +335,11 @@ public class InMemoryLSHIndex<V> implements IndexFactory<V, InMemoryLSHIndex<V>. } // Refine. - GenericDistanceDBIDList<D> result = new GenericDistanceDBIDList<>(); + ModifiableDoubleDBIDList result = DBIDUtil.newDistanceDBIDList(); for(DBIDIter iter = candidates.iter(); iter.valid(); iter.advance()) { - final D dist = distanceQuery.distance(obj, iter); + final double dist = distanceQuery.distance(obj, iter); super.incRefinements(1); - if(range.compareTo(dist) >= 0) { + if(dist <= range) { result.add(dist, iter); } } diff --git a/src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/AbstractHashFunctionFamily.java b/src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/AbstractProjectedHashFunctionFamily.java index 1c5502eb..d101ff2c 100644 --- a/src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/AbstractHashFunctionFamily.java +++ b/src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/AbstractProjectedHashFunctionFamily.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.lsh.hashfamilies; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -34,7 +34,7 @@ import de.lmu.ifi.dbs.elki.database.relation.RelationUtil; import de.lmu.ifi.dbs.elki.index.lsh.hashfunctions.LocalitySensitiveHashFunction; import de.lmu.ifi.dbs.elki.index.lsh.hashfunctions.MultipleProjectionsLocalitySensitiveHashFunction; import de.lmu.ifi.dbs.elki.math.linearalgebra.randomprojections.RandomProjectionFamily; -import de.lmu.ifi.dbs.elki.utilities.RandomFactory; +import de.lmu.ifi.dbs.elki.math.random.RandomFactory; import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer; import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID; import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.CommonConstraints; @@ -47,8 +47,11 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.RandomParameter; * Abstract base class for projection based hash functions. * * @author Erich Schubert + * + * @apiviz.uses RandomProjectionFamily + * @apiviz.has MultipleProjectionsLocalitySensitiveHashFunction */ -public abstract class AbstractHashFunctionFamily implements LocalitySensitiveHashFunctionFamily<NumberVector<?>> { +public abstract class AbstractProjectedHashFunctionFamily implements LocalitySensitiveHashFunctionFamily<NumberVector> { /** * Random generator to use. */ @@ -77,7 +80,7 @@ public abstract class AbstractHashFunctionFamily implements LocalitySensitiveHas * @param width Bin width * @param k Number of projections for each hash function. */ - public AbstractHashFunctionFamily(RandomFactory random, RandomProjectionFamily proj, double width, int k) { + public AbstractProjectedHashFunctionFamily(RandomFactory random, RandomProjectionFamily proj, double width, int k) { super(); this.random = random; this.proj = proj; @@ -86,9 +89,9 @@ public abstract class AbstractHashFunctionFamily implements LocalitySensitiveHas } @Override - public ArrayList<? extends LocalitySensitiveHashFunction<? super NumberVector<?>>> generateHashFunctions(Relation<? extends NumberVector<?>> relation, int l) { + public ArrayList<? extends LocalitySensitiveHashFunction<? super NumberVector>> generateHashFunctions(Relation<? extends NumberVector> relation, int l) { int dim = RelationUtil.dimensionality(relation); - ArrayList<LocalitySensitiveHashFunction<? super NumberVector<?>>> ps = new ArrayList<>(l); + ArrayList<LocalitySensitiveHashFunction<? super NumberVector>> ps = new ArrayList<>(l); final Random rnd = random.getSingleThreadedRandom(); for(int i = 0; i < l; i++) { RandomProjectionFamily.Projection mat = proj.generateProjection(dim, k); diff --git a/src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/EuclideanHashFunctionFamily.java b/src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/EuclideanHashFunctionFamily.java index 0aa983e5..0bb229d6 100644 --- a/src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/EuclideanHashFunctionFamily.java +++ b/src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/EuclideanHashFunctionFamily.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.lsh.hashfamilies; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -25,7 +25,7 @@ package de.lmu.ifi.dbs.elki.index.lsh.hashfamilies; import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction; import de.lmu.ifi.dbs.elki.math.linearalgebra.randomprojections.GaussianRandomProjectionFamily; -import de.lmu.ifi.dbs.elki.utilities.RandomFactory; +import de.lmu.ifi.dbs.elki.math.random.RandomFactory; import de.lmu.ifi.dbs.elki.utilities.documentation.Reference; /** @@ -39,9 +39,14 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Reference; * </p> * * @author Erich Schubert + * + * @apiviz.uses GaussianRandomProjectionFamily */ -@Reference(authors = "M. Datar and N. Immorlica and P. Indyk and V. S. Mirrokni", title = "Locality-sensitive hashing scheme based on p-stable distributions", booktitle = "Proc. 20th annual symposium on Computational geometry", url = "http://dx.doi.org/10.1145/997817.997857") -public class EuclideanHashFunctionFamily extends AbstractHashFunctionFamily { +@Reference(authors = "M. Datar and N. Immorlica and P. Indyk and V. S. Mirrokni", // +title = "Locality-sensitive hashing scheme based on p-stable distributions", // +booktitle = "Proc. 20th annual symposium on Computational geometry", // +url = "http://dx.doi.org/10.1145/997817.997857") +public class EuclideanHashFunctionFamily extends AbstractProjectedHashFunctionFamily { /** * Constructor. * @@ -54,7 +59,7 @@ public class EuclideanHashFunctionFamily extends AbstractHashFunctionFamily { } @Override - public boolean isCompatible(DistanceFunction<?, ?> df) { + public boolean isCompatible(DistanceFunction<?> df) { return EuclideanDistanceFunction.class.isInstance(df); } @@ -65,7 +70,7 @@ public class EuclideanHashFunctionFamily extends AbstractHashFunctionFamily { * * @apiviz.exclude */ - public static class Parameterizer extends AbstractHashFunctionFamily.Parameterizer { + public static class Parameterizer extends AbstractProjectedHashFunctionFamily.Parameterizer { @Override protected EuclideanHashFunctionFamily makeInstance() { return new EuclideanHashFunctionFamily(random, width, k); diff --git a/src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/LocalitySensitiveHashFunctionFamily.java b/src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/LocalitySensitiveHashFunctionFamily.java index 4d3468bb..14608145 100644 --- a/src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/LocalitySensitiveHashFunctionFamily.java +++ b/src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/LocalitySensitiveHashFunctionFamily.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.lsh.hashfamilies; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -49,10 +49,10 @@ public interface LocalitySensitiveHashFunctionFamily<V> { * Generate hash functions for the given relation. * * @param relation Relation to index - * @param k number of hash functions per table. + * @param l Number of hash tables to use * @return Family of hash functions */ - ArrayList<? extends LocalitySensitiveHashFunction<? super V>> generateHashFunctions(Relation<? extends V> relation, int k); + ArrayList<? extends LocalitySensitiveHashFunction<? super V>> generateHashFunctions(Relation<? extends V> relation, int l); /** * Check whether the given distance function can be accelerated using this @@ -61,5 +61,5 @@ public interface LocalitySensitiveHashFunctionFamily<V> { * @param df Distance function. * @return {@code true} when appropriate. */ - boolean isCompatible(DistanceFunction<?, ?> df); + boolean isCompatible(DistanceFunction<?> df); } diff --git a/src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/ManhattanHashFunctionFamily.java b/src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/ManhattanHashFunctionFamily.java index a117c44c..6a68f763 100644 --- a/src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/ManhattanHashFunctionFamily.java +++ b/src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/ManhattanHashFunctionFamily.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.lsh.hashfamilies; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -26,7 +26,7 @@ package de.lmu.ifi.dbs.elki.index.lsh.hashfamilies; import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.ManhattanDistanceFunction; import de.lmu.ifi.dbs.elki.math.linearalgebra.randomprojections.CauchyRandomProjectionFamily; -import de.lmu.ifi.dbs.elki.utilities.RandomFactory; +import de.lmu.ifi.dbs.elki.math.random.RandomFactory; import de.lmu.ifi.dbs.elki.utilities.documentation.Reference; /** @@ -40,9 +40,14 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Reference; * </p> * * @author Erich Schubert + * + * @apiviz.uses CauchyRandomProjectionFamily */ -@Reference(authors = "M. Datar and N. Immorlica and P. Indyk and V. S. Mirrokni", title = "Locality-sensitive hashing scheme based on p-stable distributions", booktitle = "Proc. 20th annual symposium on Computational geometry", url = "http://dx.doi.org/10.1145/997817.997857") -public class ManhattanHashFunctionFamily extends AbstractHashFunctionFamily { +@Reference(authors = "M. Datar and N. Immorlica and P. Indyk and V. S. Mirrokni", // +title = "Locality-sensitive hashing scheme based on p-stable distributions", // +booktitle = "Proc. 20th annual symposium on Computational geometry", // +url = "http://dx.doi.org/10.1145/997817.997857") +public class ManhattanHashFunctionFamily extends AbstractProjectedHashFunctionFamily { /** * Constructor. * @@ -55,7 +60,7 @@ public class ManhattanHashFunctionFamily extends AbstractHashFunctionFamily { } @Override - public boolean isCompatible(DistanceFunction<?, ?> df) { + public boolean isCompatible(DistanceFunction<?> df) { // TODO: also allow HistogramIntersectionDistance? return ManhattanDistanceFunction.class.isInstance(df); } @@ -67,7 +72,7 @@ public class ManhattanHashFunctionFamily extends AbstractHashFunctionFamily { * * @apiviz.exclude */ - public static class Parameterizer extends AbstractHashFunctionFamily.Parameterizer { + public static class Parameterizer extends AbstractProjectedHashFunctionFamily.Parameterizer { @Override protected ManhattanHashFunctionFamily makeInstance() { return new ManhattanHashFunctionFamily(random, width, k); diff --git a/src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/package-info.java b/src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/package-info.java index 5afa0489..84a3a244 100644 --- a/src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/lsh/hashfamilies/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/lsh/hashfunctions/LocalitySensitiveHashFunction.java b/src/de/lmu/ifi/dbs/elki/index/lsh/hashfunctions/LocalitySensitiveHashFunction.java index c43f60a5..8186c2e4 100644 --- a/src/de/lmu/ifi/dbs/elki/index/lsh/hashfunctions/LocalitySensitiveHashFunction.java +++ b/src/de/lmu/ifi/dbs/elki/index/lsh/hashfunctions/LocalitySensitiveHashFunction.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.lsh.hashfunctions; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/lsh/hashfunctions/MultipleProjectionsLocalitySensitiveHashFunction.java b/src/de/lmu/ifi/dbs/elki/index/lsh/hashfunctions/MultipleProjectionsLocalitySensitiveHashFunction.java index 59f31b0a..ba352108 100644 --- a/src/de/lmu/ifi/dbs/elki/index/lsh/hashfunctions/MultipleProjectionsLocalitySensitiveHashFunction.java +++ b/src/de/lmu/ifi/dbs/elki/index/lsh/hashfunctions/MultipleProjectionsLocalitySensitiveHashFunction.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.lsh.hashfunctions; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -41,8 +41,11 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Reference; * * @author Erich Schubert */ -@Reference(authors = "M. Datar and N. Immorlica and P. Indyk and V. S. Mirrokni", title = "Locality-sensitive hashing scheme based on p-stable distributions", booktitle = "Proc. 20th annual symposium on Computational geometry", url = "http://dx.doi.org/10.1145/997817.997857") -public class MultipleProjectionsLocalitySensitiveHashFunction implements LocalitySensitiveHashFunction<NumberVector<?>> { +@Reference(authors = "M. Datar and N. Immorlica and P. Indyk and V. S. Mirrokni", // +title = "Locality-sensitive hashing scheme based on p-stable distributions", // +booktitle = "Proc. 20th annual symposium on Computational geometry", // +url = "http://dx.doi.org/10.1145/997817.997857") +public class MultipleProjectionsLocalitySensitiveHashFunction implements LocalitySensitiveHashFunction<NumberVector> { /** * Projection matrix. */ @@ -54,9 +57,9 @@ public class MultipleProjectionsLocalitySensitiveHashFunction implements Localit double[] shift; /** - * Scaling factor. + * Scaling factor: inverse of width. */ - double width; + double iwidth; /** * Random numbers for mixing the hash codes of the individual functions @@ -73,28 +76,33 @@ public class MultipleProjectionsLocalitySensitiveHashFunction implements Localit public MultipleProjectionsLocalitySensitiveHashFunction(RandomProjectionFamily.Projection projection, double width, Random rnd) { super(); this.projection = projection; - this.width = width; + this.iwidth = 1. / width; // Generate random shifts: final int num = projection.getOutputDimensionality(); this.shift = new double[num]; this.randoms1 = new int[num]; - for (int i = 0; i < num; i++) { + for(int i = 0; i < num; i++) { shift[i] = rnd.nextDouble() * width; // Produce a large random number; although 7FFFFFFF would likely be large // enough, we try to stick to the suggested approach (which assumes // unsigned integers). - randoms1[i] = (rnd.nextInt(0x7FFFFFFD) << 1) + rnd.nextInt(1) + 1; + randoms1[i] = (rnd.nextInt(0x10000D) << 16) + rnd.nextInt(0xFFFFD) + 1; } } + /** + * Bit mask for signed int to unsigned long conversion. + */ + private final static long MASK32 = 0xFFFFFFFFL; + @Override - public int hashObject(NumberVector<?> vec) { + public int hashObject(NumberVector vec) { long t1sum = 0L; // Project the vector: final double[] proj = projection.project(vec); - for (int i = 0; i < shift.length; i++) { - int ai = (int) Math.floor((proj[i] + shift[i]) / width); - t1sum += randoms1[i] * (long) ai; + for(int i = 0; i < shift.length; i++) { + int ai = (int) Math.floor((proj[i] + shift[i]) * iwidth); + t1sum += (randoms1[i] & MASK32) * ai; // unsigned math! } return fastModPrime(t1sum); } @@ -111,7 +119,7 @@ public class MultipleProjectionsLocalitySensitiveHashFunction implements Localit // Use fast multiplication with 5 for high: int alpha = ((int) data) + (high << 2 + high); // Note that in Java, PRIME will be negative. - if (alpha < 0 && alpha > -5) { + if(alpha < 0 && alpha > -5) { alpha = alpha + 5; } return alpha; diff --git a/src/de/lmu/ifi/dbs/elki/index/lsh/hashfunctions/package-info.java b/src/de/lmu/ifi/dbs/elki/index/lsh/hashfunctions/package-info.java index e30550f6..d06249db 100644 --- a/src/de/lmu/ifi/dbs/elki/index/lsh/hashfunctions/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/lsh/hashfunctions/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/lsh/package-info.java b/src/de/lmu/ifi/dbs/elki/index/lsh/package-info.java index 78eb59f7..62409f05 100644 --- a/src/de/lmu/ifi/dbs/elki/index/lsh/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/lsh/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/package-info.java b/src/de/lmu/ifi/dbs/elki/index/package-info.java index f985629d..91151b3c 100644 --- a/src/de/lmu/ifi/dbs/elki/index/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/package-info.java @@ -8,7 +8,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/AbstractPreprocessorIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/AbstractPreprocessorIndex.java index 720efc56..0314fb86 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/AbstractPreprocessorIndex.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/AbstractPreprocessorIndex.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/LocalProjectionIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/LocalProjectionIndex.java index 0229c4e5..1f3b8ff8 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/LocalProjectionIndex.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/LocalProjectionIndex.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -40,7 +40,7 @@ import de.lmu.ifi.dbs.elki.math.linearalgebra.ProjectionResult; * @param <V> Vector type * @param <P> Projection result type */ -public interface LocalProjectionIndex<V extends NumberVector<?>, P extends ProjectionResult> extends Index { +public interface LocalProjectionIndex<V extends NumberVector, P extends ProjectionResult> extends Index { /** * Get the precomputed local projection for a particular object ID. * @@ -60,7 +60,7 @@ public interface LocalProjectionIndex<V extends NumberVector<?>, P extends Proje * @param <V> Vector type * @param <I> Index type */ - public static interface Factory<V extends NumberVector<?>, I extends LocalProjectionIndex<V, ?>> extends IndexFactory<V, I> { + public static interface Factory<V extends NumberVector, I extends LocalProjectionIndex<V, ?>> extends IndexFactory<V, I> { /** * Instantiate the index for a given database. * diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/AbstractMaterializeKNNPreprocessor.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/AbstractMaterializeKNNPreprocessor.java index 927678c2..9c950d95 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/AbstractMaterializeKNNPreprocessor.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/AbstractMaterializeKNNPreprocessor.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.knn; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -28,14 +28,13 @@ 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.DBIDRef; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList; +import de.lmu.ifi.dbs.elki.database.ids.KNNList; import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery; import de.lmu.ifi.dbs.elki.database.query.knn.PreprocessorKNNQuery; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; import de.lmu.ifi.dbs.elki.index.IndexFactory; import de.lmu.ifi.dbs.elki.index.KNNIndex; import de.lmu.ifi.dbs.elki.index.preprocessed.AbstractPreprocessorIndex; @@ -52,10 +51,8 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter; * @author Erich Schubert * * @param <O> Object type - * @param <D> Distance type - * @param <T> Result type */ -public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D>, T extends KNNList<D>> extends AbstractPreprocessorIndex<O, T> implements KNNIndex<O> { +public abstract class AbstractMaterializeKNNPreprocessor<O> extends AbstractPreprocessorIndex<O, KNNList> implements KNNIndex<O> { /** * The query k value. */ @@ -64,12 +61,12 @@ public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D /** * The distance function to be used. */ - protected final DistanceFunction<? super O, D> distanceFunction; + protected final DistanceFunction<? super O> distanceFunction; /** * The distance query we used. */ - protected final DistanceQuery<O, D> distanceQuery; + protected final DistanceQuery<O> distanceQuery; /** * Constructor. @@ -78,7 +75,7 @@ public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D * @param distanceFunction Distance function * @param k k */ - public AbstractMaterializeKNNPreprocessor(Relation<O> relation, DistanceFunction<? super O, D> distanceFunction, int k) { + public AbstractMaterializeKNNPreprocessor(Relation<O> relation, DistanceFunction<? super O> distanceFunction, int k) { super(relation); this.k = k; this.distanceFunction = distanceFunction; @@ -86,20 +83,11 @@ public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D } /** - * Get the distance factory. - * - * @return distance factory - */ - public D getDistanceFactory() { - return distanceFunction.getDistanceFactory(); - } - - /** * The distance query we used. * * @return Distance query */ - public DistanceQuery<O, D> getDistanceQuery() { + public DistanceQuery<O> getDistanceQuery() { return distanceQuery; } @@ -123,7 +111,7 @@ public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D * @param id Object ID * @return Neighbors */ - public KNNList<D> get(DBIDRef id) { + public KNNList get(DBIDRef id) { if(storage == null) { if(getLogger().isDebugging()) { getLogger().debug("Running kNN preprocessor: " + this.getClass()); @@ -137,7 +125,7 @@ public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D * Create the default storage. */ void createStorage() { - WritableDataStore<T> s = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT, KNNList.class); + WritableDataStore<KNNList> s = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT, KNNList.class); storage = s; } @@ -155,7 +143,7 @@ public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D @SuppressWarnings("unchecked") @Override - public <S extends Distance<S>> KNNQuery<O, S> getKNNQuery(DistanceQuery<O, S> distQ, Object... hints) { + public KNNQuery<O> getKNNQuery(DistanceQuery<O> distQ, Object... hints) { if(!this.distanceFunction.equals(distQ.getDistanceFunction())) { return null; } @@ -169,8 +157,8 @@ public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D } } // To make compilers happy: - AbstractMaterializeKNNPreprocessor<?, ?, ?> tmp = this; - return new PreprocessorKNNQuery<>(relation, (AbstractMaterializeKNNPreprocessor<O, S, KNNList<S>>) tmp); + AbstractMaterializeKNNPreprocessor<?> tmp = this; + return new PreprocessorKNNQuery<>(relation, (AbstractMaterializeKNNPreprocessor<O>) tmp); } /** @@ -183,9 +171,8 @@ public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D * @apiviz.uses AbstractMaterializeKNNPreprocessor oneway - - «create» * * @param <O> The object type - * @param <D> The distance type */ - public abstract static class Factory<O, D extends Distance<D>, T extends KNNList<D>> implements IndexFactory<O, KNNIndex<O>> { + public abstract static class Factory<O> implements IndexFactory<O, KNNIndex<O>> { /** * Parameter to specify the number of nearest neighbors of an object to be * materialized. must be an integer greater than 1. @@ -216,7 +203,7 @@ public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D /** * Hold the distance function to be used. */ - protected DistanceFunction<? super O, D> distanceFunction; + protected DistanceFunction<? super O> distanceFunction; /** * Index factory. @@ -224,14 +211,14 @@ public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D * @param k k parameter * @param distanceFunction distance function */ - public Factory(int k, DistanceFunction<? super O, D> distanceFunction) { + public Factory(int k, DistanceFunction<? super O> distanceFunction) { super(); this.k = k; this.distanceFunction = distanceFunction; } @Override - public abstract AbstractMaterializeKNNPreprocessor<O, D, T> instantiate(Relation<O> relation); + public abstract AbstractMaterializeKNNPreprocessor<O> instantiate(Relation<O> relation); /** * Get the distance function. @@ -239,19 +226,10 @@ public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D * @return Distance function */ // TODO: hide this? - public DistanceFunction<? super O, D> getDistanceFunction() { + public DistanceFunction<? super O> getDistanceFunction() { return distanceFunction; } - /** - * Get the distance factory. - * - * @return Distance factory - */ - public D getDistanceFactory() { - return distanceFunction.getDistanceFactory(); - } - @Override public TypeInformation getInputTypeRestriction() { return distanceFunction.getInputTypeRestriction(); @@ -263,8 +241,10 @@ public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D * @author Erich Schubert * * @apiviz.exclude + * + * @param <O> Object type */ - public abstract static class Parameterizer<O, D extends Distance<D>> extends AbstractParameterizer { + public abstract static class Parameterizer<O> extends AbstractParameterizer { /** * Holds the value of {@link #K_ID}. */ @@ -273,7 +253,7 @@ public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D /** * Hold the distance function to be used. */ - protected DistanceFunction<? super O, D> distanceFunction; + protected DistanceFunction<? super O> distanceFunction; @Override protected void makeOptions(Parameterization config) { @@ -286,14 +266,14 @@ public abstract class AbstractMaterializeKNNPreprocessor<O, D extends Distance<D } // distance function - final ObjectParameter<DistanceFunction<? super O, D>> distanceFunctionP = new ObjectParameter<>(DISTANCE_FUNCTION_ID, DistanceFunction.class, EuclideanDistanceFunction.class); + final ObjectParameter<DistanceFunction<? super O>> distanceFunctionP = new ObjectParameter<>(DISTANCE_FUNCTION_ID, DistanceFunction.class, EuclideanDistanceFunction.class); if(config.grab(distanceFunctionP)) { distanceFunction = distanceFunctionP.instantiateClass(config); } } @Override - protected abstract Factory<O, D, ?> makeInstance(); + protected abstract Factory<O> makeInstance(); } } }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/CachedDoubleDistanceKNNPreprocessor.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/CachedDoubleDistanceKNNPreprocessor.java index c36948be..eec9e812 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/CachedDoubleDistanceKNNPreprocessor.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/CachedDoubleDistanceKNNPreprocessor.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.knn; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -29,20 +29,16 @@ import java.io.RandomAccessFile; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.FileChannel.MapMode; -import java.util.ArrayList; import de.lmu.ifi.dbs.elki.application.cache.CacheDoubleDistanceKNNLists; 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.distance.DoubleDistanceDBIDPair; -import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNList; -import de.lmu.ifi.dbs.elki.database.ids.generic.DoubleDistanceDBIDPairKNNList; +import de.lmu.ifi.dbs.elki.database.ids.KNNHeap; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; import de.lmu.ifi.dbs.elki.logging.Logging; -import de.lmu.ifi.dbs.elki.persistent.ByteArrayUtil; import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException; +import de.lmu.ifi.dbs.elki.utilities.io.ByteArrayUtil; import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.FileParameter; @@ -54,7 +50,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.FileParameter; * * @param <O> Object type */ -public class CachedDoubleDistanceKNNPreprocessor<O> extends AbstractMaterializeKNNPreprocessor<O, DoubleDistance, DoubleDistanceKNNList> { +public class CachedDoubleDistanceKNNPreprocessor<O> extends AbstractMaterializeKNNPreprocessor<O> { /** * File to load. */ @@ -68,7 +64,7 @@ public class CachedDoubleDistanceKNNPreprocessor<O> extends AbstractMaterializeK * @param k K * @param file File to load */ - public CachedDoubleDistanceKNNPreprocessor(Relation<O> relation, DistanceFunction<? super O, DoubleDistance> distanceFunction, int k, File file) { + public CachedDoubleDistanceKNNPreprocessor(Relation<O> relation, DistanceFunction<? super O> distanceFunction, int k, File file) { super(relation, distanceFunction, k); this.filename = file; } @@ -86,28 +82,31 @@ public class CachedDoubleDistanceKNNPreprocessor<O> extends AbstractMaterializeK FileChannel channel = file.getChannel()) { // check magic header int header = file.readInt(); - if (header != CacheDoubleDistanceKNNLists.KNN_CACHE_MAGIC) { + if(header != CacheDoubleDistanceKNNLists.KNN_CACHE_MAGIC) { throw new AbortException("Cache magic number does not match."); } MappedByteBuffer buffer = channel.map(MapMode.READ_ONLY, 4, file.length() - 4); - for (DBIDIter iter = relation.iterDBIDs(); iter.valid(); iter.advance()) { + for(DBIDIter iter = relation.iterDBIDs(); iter.valid(); iter.advance()) { int dbid = ByteArrayUtil.readUnsignedVarint(buffer); int nnsize = ByteArrayUtil.readUnsignedVarint(buffer); - if (nnsize < k) { + if(nnsize < k) { throw new AbortException("kNN cache contains fewer than k objects!"); } - ArrayList<DoubleDistanceDBIDPair> col = new ArrayList<>(nnsize); - for (int i = 0; i < nnsize; i++) { + // FIXME: avoid the KNNHeap to KNNList roundtrip. + // FIXME: use a DBIDVar instead of importInteger. + KNNHeap knn = DBIDUtil.newHeap(k); + for(int i = 0; i < nnsize; i++) { int nid = ByteArrayUtil.readUnsignedVarint(buffer); double dist = buffer.getDouble(); - col.add(DBIDUtil.newDistancePair(dist, DBIDUtil.importInteger(nid))); + knn.insert(dist, DBIDUtil.importInteger(nid)); } - storage.put(DBIDUtil.importInteger(dbid), new DoubleDistanceDBIDPairKNNList(col, nnsize)); + storage.put(DBIDUtil.importInteger(dbid), knn.toKNNList()); } - if (buffer.hasRemaining()) { + if(buffer.hasRemaining()) { LOG.warning("kNN cache has " + buffer.remaining() + " bytes remaining!"); } - } catch (IOException e) { + } + catch(IOException e) { throw new AbortException("I/O error in loading kNN cache: " + e.getMessage(), e); } } @@ -143,7 +142,7 @@ public class CachedDoubleDistanceKNNPreprocessor<O> extends AbstractMaterializeK * * @param <O> The object type */ - public static class Factory<O> extends AbstractMaterializeKNNPreprocessor.Factory<O, DoubleDistance, DoubleDistanceKNNList> { + public static class Factory<O> extends AbstractMaterializeKNNPreprocessor.Factory<O> { /** * Filename to load. */ @@ -156,7 +155,7 @@ public class CachedDoubleDistanceKNNPreprocessor<O> extends AbstractMaterializeK * @param distanceFunction distance function * @param filename Cache file */ - public Factory(int k, DistanceFunction<? super O, DoubleDistance> distanceFunction, File filename) { + public Factory(int k, DistanceFunction<? super O> distanceFunction, File filename) { super(k, distanceFunction); this.filename = filename; } @@ -174,7 +173,7 @@ public class CachedDoubleDistanceKNNPreprocessor<O> extends AbstractMaterializeK * * @apiviz.exclude */ - public static class Parameterizer<O> extends AbstractMaterializeKNNPreprocessor.Factory.Parameterizer<O, DoubleDistance> { + public static class Parameterizer<O> extends AbstractMaterializeKNNPreprocessor.Factory.Parameterizer<O> { /** * Option ID for the kNN file. */ @@ -191,7 +190,7 @@ public class CachedDoubleDistanceKNNPreprocessor<O> extends AbstractMaterializeK // Input file parameter final FileParameter cpar = new FileParameter(CACHE_ID, FileParameter.FileType.INPUT_FILE); - if (config.grab(cpar)) { + if(config.grab(cpar)) { filename = cpar.getValue(); } } diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/KNNChangeEvent.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/KNNChangeEvent.java index 275c1c97..888c1c22 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/KNNChangeEvent.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/KNNChangeEvent.java @@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.knn; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2013 +Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/KNNJoinMaterializeKNNPreprocessor.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/KNNJoinMaterializeKNNPreprocessor.java index 44100604..8f55b519 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/KNNJoinMaterializeKNNPreprocessor.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/KNNJoinMaterializeKNNPreprocessor.java @@ -1,20 +1,10 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.knn; -import de.lmu.ifi.dbs.elki.algorithm.KNNJoin; -import de.lmu.ifi.dbs.elki.data.NumberVector; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList; -import de.lmu.ifi.dbs.elki.database.relation.Relation; -import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; -import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry; -import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rstar.RStarTreeNode; -import de.lmu.ifi.dbs.elki.logging.Logging; - /* This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -32,6 +22,13 @@ import de.lmu.ifi.dbs.elki.logging.Logging; 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.algorithm.KNNJoin; +import de.lmu.ifi.dbs.elki.data.NumberVector; +import de.lmu.ifi.dbs.elki.database.relation.Relation; +import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; +import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rstar.RStarTreeNode; +import de.lmu.ifi.dbs.elki.logging.Logging; /** * Class to materialize the kNN using a spatial join on an R-tree. @@ -39,9 +36,8 @@ import de.lmu.ifi.dbs.elki.logging.Logging; * @author Erich Schubert * * @param <V> vector type - * @param <D> distance type */ -public class KNNJoinMaterializeKNNPreprocessor<V extends NumberVector<?>, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor<V, D, KNNList<D>> { +public class KNNJoinMaterializeKNNPreprocessor<V extends NumberVector> extends AbstractMaterializeKNNPreprocessor<V> { /** * Logging class. */ @@ -54,14 +50,14 @@ public class KNNJoinMaterializeKNNPreprocessor<V extends NumberVector<?>, D exte * @param distanceFunction Distance function * @param k k */ - public KNNJoinMaterializeKNNPreprocessor(Relation<V> relation, DistanceFunction<? super V, D> distanceFunction, int k) { + public KNNJoinMaterializeKNNPreprocessor(Relation<V> relation, DistanceFunction<? super V> distanceFunction, int k) { super(relation, distanceFunction, k); } @Override protected void preprocess() { // Run KNNJoin - KNNJoin<V, D, ?, ?> knnjoin = new KNNJoin<V, D, RStarTreeNode, SpatialEntry>(distanceFunction, k); + KNNJoin<V, ?, ?> knnjoin = new KNNJoin<V, RStarTreeNode, SpatialEntry>(distanceFunction, k); storage = knnjoin.run(relation.getDatabase(), relation); } @@ -95,21 +91,20 @@ public class KNNJoinMaterializeKNNPreprocessor<V extends NumberVector<?>, D exte * @apiviz.uses AbstractMaterializeKNNPreprocessor oneway - - «create» * * @param <O> The object type - * @param <D> The distance type */ - public static class Factory<O extends NumberVector<?>, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor.Factory<O, D, KNNList<D>> { + public static class Factory<O extends NumberVector> extends AbstractMaterializeKNNPreprocessor.Factory<O> { /** * Constructor. * * @param k K * @param distanceFunction distance function */ - public Factory(int k, DistanceFunction<? super O, D> distanceFunction) { + public Factory(int k, DistanceFunction<? super O> distanceFunction) { super(k, distanceFunction); } @Override - public KNNJoinMaterializeKNNPreprocessor<O, D> instantiate(Relation<O> relation) { + public KNNJoinMaterializeKNNPreprocessor<O> instantiate(Relation<O> relation) { return new KNNJoinMaterializeKNNPreprocessor<>(relation, distanceFunction, k); } @@ -121,11 +116,10 @@ public class KNNJoinMaterializeKNNPreprocessor<V extends NumberVector<?>, D exte * @apiviz.exclude * * @param <O> Object type - * @param <D> Distance type */ - public static class Parameterizer<O extends NumberVector<?>, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor.Factory.Parameterizer<O, D> { + public static class Parameterizer<O extends NumberVector> extends AbstractMaterializeKNNPreprocessor.Factory.Parameterizer<O> { @Override - protected KNNJoinMaterializeKNNPreprocessor.Factory<O, D> makeInstance() { + protected KNNJoinMaterializeKNNPreprocessor.Factory<O> makeInstance() { return new KNNJoinMaterializeKNNPreprocessor.Factory<>(k, distanceFunction); } } diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/KNNListener.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/KNNListener.java index 8c78cdc0..e26106de 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/KNNListener.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/KNNListener.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.knn; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/MaterializeKNNAndRKNNPreprocessor.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/MaterializeKNNAndRKNNPreprocessor.java index fba2b168..49e23dde 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/MaterializeKNNAndRKNNPreprocessor.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/MaterializeKNNAndRKNNPreprocessor.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.knn; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -25,7 +25,6 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.knn; import java.util.ArrayList; import java.util.Collection; -import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.TreeSet; @@ -40,22 +39,19 @@ 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.DoubleDBIDList; +import de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDListIter; +import de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDPair; import de.lmu.ifi.dbs.elki.database.ids.HashSetModifiableDBIDs; +import de.lmu.ifi.dbs.elki.database.ids.KNNHeap; +import de.lmu.ifi.dbs.elki.database.ids.KNNList; +import de.lmu.ifi.dbs.elki.database.ids.ModifiableDoubleDBIDList; import de.lmu.ifi.dbs.elki.database.ids.SetDBIDs; -import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter; -import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDPair; -import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPair; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNHeap; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList; -import de.lmu.ifi.dbs.elki.database.ids.generic.GenericDistanceDBIDList; import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; import de.lmu.ifi.dbs.elki.database.query.rknn.PreprocessorRKNNQuery; import de.lmu.ifi.dbs.elki.database.query.rknn.RKNNQuery; import de.lmu.ifi.dbs.elki.database.relation.Relation; -import de.lmu.ifi.dbs.elki.distance.DistanceUtil; import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distanceresultlist.DistanceDBIDResultUtil; -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; import de.lmu.ifi.dbs.elki.index.RKNNIndex; import de.lmu.ifi.dbs.elki.logging.Logging; import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress; @@ -70,12 +66,12 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Title; * @author Elke Achtert * * @param <O> the type of database objects the preprocessor can be applied to - * @param <D> the type of distance the used distance function will return + * @param the type of distance the used distance function will return */ // TODO: rewrite the double optimization. Maybe use a specialized subclass? @Title("Materialize kNN and RkNN Neighborhood preprocessor") @Description("Materializes the k nearest neighbors and the reverse k nearest neighbors of objects of a database.") -public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends MaterializeKNNPreprocessor<O, D> implements RKNNIndex<O> { +public class MaterializeKNNAndRKNNPreprocessor<O> extends MaterializeKNNPreprocessor<O> implements RKNNIndex<O> { /** * Logger to use. */ @@ -84,12 +80,7 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends /** * Additional data storage for RkNN. */ - private WritableDataStore<TreeSet<DistanceDBIDPair<D>>> materialized_RkNN; - - /** - * Use optimizations for double values - */ - protected boolean doubleOptimize; + private WritableDataStore<TreeSet<DoubleDBIDPair>> materialized_RkNN; /** * Constructor. @@ -98,9 +89,8 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends * @param distanceFunction the distance function to use * @param k query k */ - public MaterializeKNNAndRKNNPreprocessor(Relation<O> relation, DistanceFunction<? super O, D> distanceFunction, int k) { + public MaterializeKNNAndRKNNPreprocessor(Relation<O> relation, DistanceFunction<? super O> distanceFunction, int k) { super(relation, distanceFunction, k); - this.doubleOptimize = DistanceUtil.isDoubleDistanceFunction(distanceFunction); } @Override @@ -118,39 +108,30 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends */ private void materializeKNNAndRKNNs(ArrayDBIDs ids, FiniteProgress progress) { // add an empty list to each rknn - Comparator<? super DistanceDBIDPair<D>> comp = DistanceDBIDResultUtil.distanceComparator(); for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { if(materialized_RkNN.get(iter) == null) { - materialized_RkNN.put(iter, new TreeSet<>(comp)); + materialized_RkNN.put(iter, new TreeSet<DoubleDBIDPair>()); } } // knn query - List<? extends KNNList<D>> kNNList = knnQuery.getKNNForBulkDBIDs(ids, k); + List<? extends KNNList> kNNList = knnQuery.getKNNForBulkDBIDs(ids, k); int i = 0; for(DBIDIter id = ids.iter(); id.valid(); id.advance(), i++) { - KNNList<D> kNNs = kNNList.get(i); + KNNList kNNs = kNNList.get(i); storage.put(id, kNNs); - for(DistanceDBIDListIter<D> iter = kNNs.iter(); iter.valid(); iter.advance()) { - TreeSet<DistanceDBIDPair<D>> rknns = materialized_RkNN.get(iter); + for(DoubleDBIDListIter iter = kNNs.iter(); iter.valid(); iter.advance()) { + TreeSet<DoubleDBIDPair> rknns = materialized_RkNN.get(iter); rknns.add(makePair(iter, id)); } - if(progress != null) { - progress.incrementProcessed(getLogger()); - } + getLogger().incrementProcessed(progress); } - if(progress != null) { - progress.ensureCompleted(getLogger()); - } + getLogger().ensureCompleted(progress); } - @SuppressWarnings("unchecked") - private DistanceDBIDPair<D> makePair(DistanceDBIDListIter<D> iter, DBIDIter id) { - if(doubleOptimize) { - return (DistanceDBIDPair<D>) DBIDUtil.newDistancePair(((DoubleDistanceDBIDPair) iter.getDistancePair()).doubleDistance(), id); - } - return DBIDUtil.newDistancePair(iter.getDistance(), id); + private DoubleDBIDPair makePair(DoubleDBIDListIter iter, DBIDIter id) { + return DBIDUtil.newPair(iter.getPair().doubleValue(), id); } @Override @@ -159,26 +140,18 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends ArrayDBIDs aids = DBIDUtil.ensureArray(ids); // materialize the new kNNs and RkNNs - if(stepprog != null) { - stepprog.beginStep(1, "New insertions ocurred, materialize their new kNNs and RkNNs.", getLogger()); - } + getLogger().beginStep(stepprog, 1, "New insertions ocurred, materialize their new kNNs and RkNNs."); materializeKNNAndRKNNs(aids, null); // update the old kNNs and RkNNs - if(stepprog != null) { - stepprog.beginStep(2, "New insertions ocurred, update the affected kNNs and RkNNs.", getLogger()); - } + getLogger().beginStep(stepprog, 2, "New insertions ocurred, update the affected kNNs and RkNNs."); ArrayDBIDs rkNN_ids = updateKNNsAndRkNNs(ids); // inform listener - if(stepprog != null) { - stepprog.beginStep(3, "New insertions ocurred, inform listeners.", getLogger()); - } + getLogger().beginStep(stepprog, 3, "New insertions ocurred, inform listeners."); fireKNNsInserted(ids, rkNN_ids); - if(stepprog != null) { - stepprog.ensureCompleted(getLogger()); - } + getLogger().ensureCompleted(stepprog); } /** @@ -193,13 +166,13 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends ArrayModifiableDBIDs rkNN_ids = DBIDUtil.newArray(); DBIDs oldids = DBIDUtil.difference(relation.getDBIDs(), ids); for(DBIDIter id = oldids.iter(); id.valid(); id.advance()) { - KNNList<D> oldkNNs = storage.get(id); - D knnDist = oldkNNs.getKNNDistance(); + KNNList oldkNNs = storage.get(id); + double knnDist = oldkNNs.getKNNDistance(); // look for new kNNs - KNNHeap<D> heap = null; + KNNHeap heap = null; for(DBIDIter newid = ids.iter(); newid.valid(); newid.advance()) { - D dist = distanceQuery.distance(id, newid); - if(dist.compareTo(knnDist) <= 0) { + double dist = distanceQuery.distance(id, newid); + if(dist <= knnDist) { // New id changes the kNNs of oldid. if(heap == null) { heap = DBIDUtil.newHeap(oldkNNs); @@ -209,18 +182,18 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends } // kNNs for oldid have changed: if(heap != null) { - KNNList<D> newkNNs = heap.toKNNList(); + KNNList newkNNs = heap.toKNNList(); storage.put(id, newkNNs); // get the difference int i = 0; int j = 0; - GenericDistanceDBIDList<D> added = new GenericDistanceDBIDList<>(); - GenericDistanceDBIDList<D> removed = new GenericDistanceDBIDList<>(); + ModifiableDoubleDBIDList added = DBIDUtil.newDistanceDBIDList(); + ModifiableDoubleDBIDList removed = DBIDUtil.newDistanceDBIDList(); // TODO: use iterators. while(i < oldkNNs.size() && j < newkNNs.size()) { - DistanceDBIDPair<D> drp1 = oldkNNs.get(i); - DistanceDBIDPair<D> drp2 = newkNNs.get(j); + DoubleDBIDPair drp1 = oldkNNs.get(i); + DoubleDBIDPair drp2 = newkNNs.get(j); // NOTE: we assume that on ties they are ordered the same way! if(!DBIDUtil.equal(drp1, drp2)) { added.add(drp2); @@ -240,13 +213,13 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends } } // add new RkNN - for(DistanceDBIDListIter<D> newnn = added.iter(); newnn.valid(); newnn.advance()) { - TreeSet<DistanceDBIDPair<D>> rknns = materialized_RkNN.get(newnn); + for(DoubleDBIDListIter newnn = added.iter(); newnn.valid(); newnn.advance()) { + TreeSet<DoubleDBIDPair> rknns = materialized_RkNN.get(newnn); rknns.add(makePair(newnn, id)); } // remove old RkNN - for(DistanceDBIDListIter<D> oldnn = removed.iter(); oldnn.valid(); oldnn.advance()) { - TreeSet<DistanceDBIDPair<D>> rknns = materialized_RkNN.get(oldnn); + for(DoubleDBIDListIter oldnn = removed.iter(); oldnn.valid(); oldnn.advance()) { + TreeSet<DoubleDBIDPair> rknns = materialized_RkNN.get(oldnn); rknns.remove(makePair(oldnn, id)); } @@ -262,12 +235,10 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends ArrayDBIDs aids = DBIDUtil.ensureArray(ids); // delete the materialized (old) kNNs and RkNNs - if(stepprog != null) { - stepprog.beginStep(1, "New deletions ocurred, remove their materialized kNNs and RkNNs.", getLogger()); - } + getLogger().beginStep(stepprog, 1, "New deletions ocurred, remove their materialized kNNs and RkNNs."); // Temporary storage of removed lists - List<KNNList<D>> kNNs = new ArrayList<>(ids.size()); - List<TreeSet<DistanceDBIDPair<D>>> rkNNs = new ArrayList<>(ids.size()); + List<KNNList> kNNs = new ArrayList<>(ids.size()); + List<TreeSet<DoubleDBIDPair>> rkNNs = new ArrayList<>(ids.size()); for(DBIDIter iter = aids.iter(); iter.valid(); iter.advance()) { kNNs.add(storage.get(iter)); storage.delete(iter); @@ -279,16 +250,14 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends ArrayDBIDs rkNN_ids = affectedRkNN(rkNNs, aids); // update the affected kNNs and RkNNs - if(stepprog != null) { - stepprog.beginStep(2, "New deletions ocurred, update the affected kNNs and RkNNs.", getLogger()); - } + getLogger().beginStep(stepprog, 2, "New deletions ocurred, update the affected kNNs and RkNNs."); // Recompute the kNN for affected objects (in rkNN lists) { - List<? extends KNNList<D>> kNNList = knnQuery.getKNNForBulkDBIDs(rkNN_ids, k); + List<? extends KNNList> kNNList = knnQuery.getKNNForBulkDBIDs(rkNN_ids, k); int i = 0; for(DBIDIter reknn = rkNN_ids.iter(); reknn.valid(); reknn.advance(), i++) { storage.put(reknn, kNNList.get(i)); - for(DistanceDBIDListIter<D> it = kNNList.get(i).iter(); it.valid(); it.advance()) { + for(DoubleDBIDListIter it = kNNList.get(i).iter(); it.valid(); it.advance()) { materialized_RkNN.get(it).add(makePair(it, reknn)); } } @@ -297,8 +266,8 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends { SetDBIDs idsSet = DBIDUtil.ensureSet(ids); for(DBIDIter nn = kNN_ids.iter(); nn.valid(); nn.advance()) { - TreeSet<DistanceDBIDPair<D>> rkNN = materialized_RkNN.get(nn); - for(Iterator<DistanceDBIDPair<D>> it = rkNN.iterator(); it.hasNext();) { + TreeSet<DoubleDBIDPair> rkNN = materialized_RkNN.get(nn); + for(Iterator<DoubleDBIDPair> it = rkNN.iterator(); it.hasNext();) { if(idsSet.contains(it.next())) { it.remove(); } @@ -307,14 +276,10 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends } // inform listener - if(stepprog != null) { - stepprog.beginStep(3, "New deletions ocurred, inform listeners.", getLogger()); - } + getLogger().beginStep(stepprog, 3, "New deletions ocurred, inform listeners."); fireKNNsRemoved(ids, rkNN_ids); - if(stepprog != null) { - stepprog.ensureCompleted(getLogger()); - } + getLogger().ensureCompleted(stepprog); } /** @@ -324,9 +289,9 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends * @param remove the ids to remove * @return the DBIDs in the given collection */ - protected ArrayDBIDs affectedkNN(List<? extends KNNList<D>> extraxt, DBIDs remove) { + protected ArrayDBIDs affectedkNN(List<? extends KNNList> extraxt, DBIDs remove) { HashSetModifiableDBIDs ids = DBIDUtil.newHashSet(); - for(KNNList<D> drps : extraxt) { + for(KNNList drps : extraxt) { for(DBIDIter iter = drps.iter(); iter.valid(); iter.advance()) { ids.add(iter); } @@ -343,10 +308,10 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends * @param remove the ids to remove * @return the DBIDs in the given collection */ - protected ArrayDBIDs affectedRkNN(List<? extends Collection<DistanceDBIDPair<D>>> extraxt, DBIDs remove) { + protected ArrayDBIDs affectedRkNN(List<? extends Collection<DoubleDBIDPair>> extraxt, DBIDs remove) { HashSetModifiableDBIDs ids = DBIDUtil.newHashSet(); - for(Collection<DistanceDBIDPair<D>> drps : extraxt) { - for(DistanceDBIDPair<D> drp : drps) { + for(Collection<DoubleDBIDPair> drps : extraxt) { + for(DoubleDBIDPair drp : drps) { ids.add(drp); } } @@ -361,7 +326,7 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends * @param id the query id * @return the kNNs */ - public KNNList<D> getKNN(DBID id) { + public KNNList getKNN(DBID id) { return storage.get(id); } @@ -371,22 +336,21 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends * @param id the query id * @return the RkNNs */ - public GenericDistanceDBIDList<D> getRKNN(DBIDRef id) { - TreeSet<DistanceDBIDPair<D>> rKNN = materialized_RkNN.get(id); + public DoubleDBIDList getRKNN(DBIDRef id) { + TreeSet<DoubleDBIDPair> rKNN = materialized_RkNN.get(id); if(rKNN == null) { return null; } - GenericDistanceDBIDList<D> ret = new GenericDistanceDBIDList<>(rKNN.size()); - for(DistanceDBIDPair<D> pair : rKNN) { + ModifiableDoubleDBIDList ret = DBIDUtil.newDistanceDBIDList(rKNN.size()); + for(DoubleDBIDPair pair : rKNN) { ret.add(pair); } ret.sort(); return ret; } - @SuppressWarnings("unchecked") @Override - public <S extends Distance<S>> RKNNQuery<O, S> getRKNNQuery(DistanceQuery<O, S> distanceQuery, Object... hints) { + public RKNNQuery<O> getRKNNQuery(DistanceQuery<O> distanceQuery, Object... hints) { if(!this.distanceFunction.equals(distanceQuery.getDistanceFunction())) { return null; } @@ -399,7 +363,7 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends break; } } - return new PreprocessorRKNNQuery<>(relation, (MaterializeKNNAndRKNNPreprocessor<O, S>) this); + return new PreprocessorRKNNQuery<>(relation, this); } @Override @@ -423,22 +387,22 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends * @author Elke Achtert * * @param <O> The object type - * @param <D> The distance type + * @param The distance type */ - public static class Factory<O, D extends Distance<D>> extends MaterializeKNNPreprocessor.Factory<O, D> { + public static class Factory<O> extends MaterializeKNNPreprocessor.Factory<O> { /** * Constructor. * * @param k k * @param distanceFunction distance function */ - public Factory(int k, DistanceFunction<? super O, D> distanceFunction) { + public Factory(int k, DistanceFunction<? super O> distanceFunction) { super(k, distanceFunction); } @Override - public MaterializeKNNAndRKNNPreprocessor<O, D> instantiate(Relation<O> relation) { - MaterializeKNNAndRKNNPreprocessor<O, D> instance = new MaterializeKNNAndRKNNPreprocessor<>(relation, distanceFunction, k); + public MaterializeKNNAndRKNNPreprocessor<O> instantiate(Relation<O> relation) { + MaterializeKNNAndRKNNPreprocessor<O> instance = new MaterializeKNNAndRKNNPreprocessor<>(relation, distanceFunction, k); return instance; } @@ -449,9 +413,9 @@ public class MaterializeKNNAndRKNNPreprocessor<O, D extends Distance<D>> extends * * @apiviz.exclude */ - public static class Parameterizer<O, D extends Distance<D>> extends MaterializeKNNPreprocessor.Factory.Parameterizer<O, D> { + public static class Parameterizer<O> extends MaterializeKNNPreprocessor.Factory.Parameterizer<O> { @Override - protected Factory<O, D> makeInstance() { + protected Factory<O> makeInstance() { return new Factory<>(k, distanceFunction); } } diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/MaterializeKNNPreprocessor.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/MaterializeKNNPreprocessor.java index 50ef21ed..ef48e4cb 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/MaterializeKNNPreprocessor.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/MaterializeKNNPreprocessor.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.knn; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -33,14 +33,13 @@ import de.lmu.ifi.dbs.elki.database.ids.DBIDIter; import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil; import de.lmu.ifi.dbs.elki.database.ids.DBIDs; +import de.lmu.ifi.dbs.elki.database.ids.KNNHeap; +import de.lmu.ifi.dbs.elki.database.ids.KNNList; import de.lmu.ifi.dbs.elki.database.ids.SetDBIDs; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNHeap; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList; import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery; import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; import de.lmu.ifi.dbs.elki.index.DynamicIndex; import de.lmu.ifi.dbs.elki.logging.Logging; import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress; @@ -63,11 +62,10 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Title; * @apiviz.has KNNListener * * @param <O> the type of database objects the preprocessor can be applied to - * @param <D> the type of distance the used distance function will return */ @Title("Materialize kNN Neighborhood preprocessor") @Description("Materializes the k nearest neighbors of objects of a database.") -public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor<O, D, KNNList<D>> implements DynamicIndex { +public class MaterializeKNNPreprocessor<O> extends AbstractMaterializeKNNPreprocessor<O> implements DynamicIndex { /** * Logger to use. */ @@ -83,7 +81,7 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra /** * KNNQuery instance to use. */ - protected final KNNQuery<O, D> knnQuery; + protected final KNNQuery<O> knnQuery; /** * Holds the listener. @@ -97,7 +95,7 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra * @param distanceFunction the distance function to use * @param k query k */ - public MaterializeKNNPreprocessor(Relation<O> relation, DistanceFunction<? super O, D> distanceFunction, int k) { + public MaterializeKNNPreprocessor(Relation<O> relation, DistanceFunction<? super O> distanceFunction, int k) { super(relation, distanceFunction, k); this.knnQuery = relation.getDatabase().getKNNQuery(distanceQuery, k, DatabaseQuery.HINT_BULK, DatabaseQuery.HINT_HEAVY_USE, DatabaseQuery.HINT_NO_CACHE); } @@ -111,42 +109,33 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra ArrayDBIDs ids = DBIDUtil.ensureArray(relation.getDBIDs()); - if (LOG.isStatistics()) { + if(LOG.isStatistics()) { LOG.statistics(new LongStatistic(this.getClass().getName() + ".k", k)); } - Duration duration = LOG.isStatistics() ? LOG.newDuration(this.getClass().getName() + ".precomputation-time") : null; - if (duration != null) { - duration.begin(); - } + Duration duration = LOG.isStatistics() ? LOG.newDuration(this.getClass().getName() + ".precomputation-time").begin() : null; FiniteProgress progress = getLogger().isVerbose() ? new FiniteProgress("Materializing k nearest neighbors (k=" + k + ")", ids.size(), getLogger()) : null; // Try bulk - List<? extends KNNList<D>> kNNList = null; - if (usebulk) { + List<? extends KNNList> kNNList = null; + if(usebulk) { kNNList = knnQuery.getKNNForBulkDBIDs(ids, k); - if (kNNList != null) { + if(kNNList != null) { int i = 0; - for (DBIDIter id = ids.iter(); id.valid(); id.advance(), i++) { + for(DBIDIter id = ids.iter(); id.valid(); id.advance(), i++) { storage.put(id, kNNList.get(i)); - if (progress != null) { - progress.incrementProcessed(getLogger()); - } + getLogger().incrementProcessed(progress); } } - } else { - for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { - KNNList<D> knn = knnQuery.getKNNForDBID(iter, k); + } + else { + for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { + KNNList knn = knnQuery.getKNNForDBID(iter, k); storage.put(iter, knn); - if (progress != null) { - progress.incrementProcessed(getLogger()); - } + getLogger().incrementProcessed(progress); } } - if (progress != null) { - progress.ensureCompleted(getLogger()); - } - if (duration != null) { - duration.end(); - LOG.statistics(duration); + getLogger().ensureCompleted(progress); + if(duration != null) { + LOG.statistics(duration.end()); } } @@ -157,9 +146,10 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra @Override public void insertAll(DBIDs ids) { - if (storage == null && ids.size() > 0) { + if(storage == null && ids.size() > 0) { preprocess(); - } else { + } + else { objectsInserted(ids); } } @@ -186,32 +176,24 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra ArrayDBIDs aids = DBIDUtil.ensureArray(ids); // materialize the new kNNs - if (stepprog != null) { - stepprog.beginStep(1, "New insertions ocurred, materialize their new kNNs.", getLogger()); - } + getLogger().beginStep(stepprog, 1, "New insertions ocurred, materialize their new kNNs."); // Bulk-query kNNs - List<? extends KNNList<D>> kNNList = knnQuery.getKNNForBulkDBIDs(aids, k); + List<? extends KNNList> kNNList = knnQuery.getKNNForBulkDBIDs(aids, k); // Store in storage DBIDIter iter = aids.iter(); - for (int i = 0; i < aids.size(); i++, iter.advance()) { + for(int i = 0; i < aids.size(); i++, iter.advance()) { storage.put(iter, kNNList.get(i)); } // update the affected kNNs - if (stepprog != null) { - stepprog.beginStep(2, "New insertions ocurred, update the affected kNNs.", getLogger()); - } + getLogger().beginStep(stepprog, 2, "New insertions ocurred, update the affected kNNs."); ArrayDBIDs rkNN_ids = updateKNNsAfterInsertion(ids); // inform listener - if (stepprog != null) { - stepprog.beginStep(3, "New insertions ocurred, inform listeners.", getLogger()); - } + getLogger().beginStep(stepprog, 3, "New insertions ocurred, inform listeners."); fireKNNsInserted(ids, rkNN_ids); - if (stepprog != null) { - stepprog.setCompleted(getLogger()); - } + getLogger().setCompleted(stepprog); } /** @@ -225,21 +207,21 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra private ArrayDBIDs updateKNNsAfterInsertion(DBIDs ids) { ArrayModifiableDBIDs rkNN_ids = DBIDUtil.newArray(); DBIDs oldids = DBIDUtil.difference(relation.getDBIDs(), ids); - for (DBIDIter iter = oldids.iter(); iter.valid(); iter.advance()) { - KNNList<D> kNNs = storage.get(iter); - D knnDist = kNNs.get(kNNs.size() - 1).getDistance(); + for(DBIDIter iter = oldids.iter(); iter.valid(); iter.advance()) { + KNNList kNNs = storage.get(iter); + double knnDist = kNNs.getKNNDistance(); // look for new kNNs - KNNHeap<D> heap = null; - for (DBIDIter iter2 = ids.iter(); iter2.valid(); iter2.advance()) { - D dist = distanceQuery.distance(iter, iter2); - if (dist.compareTo(knnDist) <= 0) { - if (heap == null) { + KNNHeap heap = null; + for(DBIDIter iter2 = ids.iter(); iter2.valid(); iter2.advance()) { + double dist = distanceQuery.distance(iter, iter2); + if(dist <= knnDist) { + if(heap == null) { heap = DBIDUtil.newHeap(kNNs); } heap.insert(dist, iter2); } } - if (heap != null) { + if(heap != null) { kNNs = heap.toKNNList(); storage.put(iter, kNNs); rkNN_ids.add(iter); @@ -258,10 +240,10 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra private ArrayDBIDs updateKNNsAfterDeletion(DBIDs ids) { SetDBIDs idsSet = DBIDUtil.ensureSet(ids); ArrayModifiableDBIDs rkNN_ids = DBIDUtil.newArray(); - for (DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) { - KNNList<D> kNNs = storage.get(iditer); - for (DBIDIter it = kNNs.iter(); it.valid(); it.advance()) { - if (idsSet.contains(it)) { + for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) { + KNNList kNNs = storage.get(iditer); + for(DBIDIter it = kNNs.iter(); it.valid(); it.advance()) { + if(idsSet.contains(it)) { rkNN_ids.add(iditer); break; } @@ -269,9 +251,9 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra } // update the kNNs of the RkNNs - List<? extends KNNList<D>> kNNList = knnQuery.getKNNForBulkDBIDs(rkNN_ids, k); + List<? extends KNNList> kNNList = knnQuery.getKNNForBulkDBIDs(rkNN_ids, k); DBIDIter iter = rkNN_ids.iter(); - for (int i = 0; i < rkNN_ids.size(); i++, iter.advance()) { + for(int i = 0; i < rkNN_ids.size(); i++, iter.advance()) { storage.put(iter, kNNList.get(i)); } @@ -288,28 +270,20 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra StepProgress stepprog = getLogger().isVerbose() ? new StepProgress(3) : null; // delete the materialized (old) kNNs - if (stepprog != null) { - stepprog.beginStep(1, "New deletions ocurred, remove their materialized kNNs.", getLogger()); - } - for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { + getLogger().beginStep(stepprog, 1, "New deletions ocurred, remove their materialized kNNs."); + for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { storage.delete(iter); } // update the affected kNNs - if (stepprog != null) { - stepprog.beginStep(2, "New deletions ocurred, update the affected kNNs.", getLogger()); - } + getLogger().beginStep(stepprog, 2, "New deletions ocurred, update the affected kNNs."); ArrayDBIDs rkNN_ids = updateKNNsAfterDeletion(ids); // inform listener - if (stepprog != null) { - stepprog.beginStep(3, "New deletions ocurred, inform listeners.", getLogger()); - } + getLogger().beginStep(stepprog, 3, "New deletions ocurred, inform listeners."); fireKNNsRemoved(ids, rkNN_ids); - if (stepprog != null) { - stepprog.ensureCompleted(getLogger()); - } + getLogger().ensureCompleted(stepprog); } /** @@ -324,8 +298,8 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra protected void fireKNNsInserted(DBIDs insertions, DBIDs updates) { KNNChangeEvent e = new KNNChangeEvent(this, KNNChangeEvent.Type.INSERT, insertions, updates); Object[] listeners = listenerList.getListenerList(); - for (int i = listeners.length - 2; i >= 0; i -= 2) { - if (listeners[i] == KNNListener.class) { + for(int i = listeners.length - 2; i >= 0; i -= 2) { + if(listeners[i] == KNNListener.class) { ((KNNListener) listeners[i + 1]).kNNsChanged(e); } } @@ -342,8 +316,8 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra protected void fireKNNsRemoved(DBIDs removals, DBIDs updates) { KNNChangeEvent e = new KNNChangeEvent(this, KNNChangeEvent.Type.DELETE, removals, updates); Object[] listeners = listenerList.getListenerList(); - for (int i = listeners.length - 2; i >= 0; i -= 2) { - if (listeners[i] == KNNListener.class) { + for(int i = listeners.length - 2; i >= 0; i -= 2) { + if(listeners[i] == KNNListener.class) { ((KNNListener) listeners[i + 1]).kNNsChanged(e); } } @@ -403,22 +377,21 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra * @apiviz.uses MaterializeKNNPreprocessor oneway - - «create» * * @param <O> The object type - * @param <D> The distance type */ - public static class Factory<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor.Factory<O, D, KNNList<D>> { + public static class Factory<O> extends AbstractMaterializeKNNPreprocessor.Factory<O> { /** * Index factory. * * @param k k parameter * @param distanceFunction distance function */ - public Factory(int k, DistanceFunction<? super O, D> distanceFunction) { + public Factory(int k, DistanceFunction<? super O> distanceFunction) { super(k, distanceFunction); } @Override - public MaterializeKNNPreprocessor<O, D> instantiate(Relation<O> relation) { - MaterializeKNNPreprocessor<O, D> instance = new MaterializeKNNPreprocessor<>(relation, distanceFunction, k); + public MaterializeKNNPreprocessor<O> instantiate(Relation<O> relation) { + MaterializeKNNPreprocessor<O> instance = new MaterializeKNNPreprocessor<>(relation, distanceFunction, k); return instance; } @@ -429,9 +402,9 @@ public class MaterializeKNNPreprocessor<O, D extends Distance<D>> extends Abstra * * @apiviz.exclude */ - public static class Parameterizer<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor.Factory.Parameterizer<O, D> { + public static class Parameterizer<O> extends AbstractMaterializeKNNPreprocessor.Factory.Parameterizer<O> { @Override - protected Factory<O, D> makeInstance() { + protected Factory<O> makeInstance() { return new Factory<>(k, distanceFunction); } } diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/MetricalIndexApproximationMaterializeKNNPreprocessor.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/MetricalIndexApproximationMaterializeKNNPreprocessor.java index 43798fbc..b3e73abb 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/MetricalIndexApproximationMaterializeKNNPreprocessor.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/MetricalIndexApproximationMaterializeKNNPreprocessor.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.knn; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,8 +23,10 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.knn; along with this program. If not, see <http://www.gnu.org/licenses/>. */ +import gnu.trove.impl.Constants; +import gnu.trove.map.hash.TObjectDoubleHashMap; + import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import de.lmu.ifi.dbs.elki.data.NumberVector; @@ -32,12 +34,10 @@ import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs; import de.lmu.ifi.dbs.elki.database.ids.DBIDIter; import de.lmu.ifi.dbs.elki.database.ids.DBIDPair; import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNHeap; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList; +import de.lmu.ifi.dbs.elki.database.ids.KNNHeap; import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; import de.lmu.ifi.dbs.elki.index.tree.LeafEntry; import de.lmu.ifi.dbs.elki.index.tree.Node; import de.lmu.ifi.dbs.elki.index.tree.metrical.MetricalIndexTree; @@ -63,13 +63,12 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Title; * @apiviz.uses MetricalIndexTree * * @param <O> the type of database objects the preprocessor can be applied to - * @param <D> the type of distance the used distance function will return * @param <N> the type of spatial nodes in the spatial index * @param <E> the type of spatial entries in the spatial index */ @Title("Spatial Approximation Materialize kNN Preprocessor") @Description("Caterializes the (approximate) k nearest neighbors of objects of a database using a spatial approximation.") -public class MetricalIndexApproximationMaterializeKNNPreprocessor<O extends NumberVector<?>, D extends Distance<D>, N extends Node<E>, E extends MTreeEntry> extends AbstractMaterializeKNNPreprocessor<O, D, KNNList<D>> { +public class MetricalIndexApproximationMaterializeKNNPreprocessor<O extends NumberVector, N extends Node<E>, E extends MTreeEntry> extends AbstractMaterializeKNNPreprocessor<O> { /** * Logger to use */ @@ -82,15 +81,15 @@ public class MetricalIndexApproximationMaterializeKNNPreprocessor<O extends Numb * @param distanceFunction the distance function to use * @param k query k */ - public MetricalIndexApproximationMaterializeKNNPreprocessor(Relation<O> relation, DistanceFunction<? super O, D> distanceFunction, int k) { + public MetricalIndexApproximationMaterializeKNNPreprocessor(Relation<O> relation, DistanceFunction<? super O> distanceFunction, int k) { super(relation, distanceFunction, k); } @Override protected void preprocess() { - DistanceQuery<O, D> distanceQuery = relation.getDatabase().getDistanceQuery(relation, distanceFunction); + DistanceQuery<O> distanceQuery = relation.getDatabase().getDistanceQuery(relation, distanceFunction); - MetricalIndexTree<O, D, N, E> index = getMetricalIndex(relation); + MetricalIndexTree<O, N, E> index = getMetricalIndex(relation); createStorage(); MeanVariance pagesize = new MeanVariance(); @@ -113,13 +112,13 @@ public class MetricalIndexApproximationMaterializeKNNPreprocessor<O extends Numb for(int i = 0; i < size; i++) { ids.add(((LeafEntry) node.getEntry(i)).getDBID()); } - HashMap<DBIDPair, D> cache = new HashMap<>((size * size * 3) >> 2); + TObjectDoubleHashMap<DBIDPair> cache = new TObjectDoubleHashMap<>((size * size * 3) >> 2, Constants.DEFAULT_LOAD_FACTOR, Double.NaN); for(DBIDIter id = ids.iter(); id.valid(); id.advance()) { - KNNHeap<D> kNN = DBIDUtil.newHeap(distanceFunction.getDistanceFactory(), k); + KNNHeap kNN = DBIDUtil.newHeap(k); for(DBIDIter id2 = ids.iter(); id2.valid(); id2.advance()) { DBIDPair key = DBIDUtil.newPair(id, id2); - D d = cache.remove(key); - if(d != null) { + double d = cache.remove(key); + if(d == d) { // Not NaN // consume the previous result. kNN.insert(d, id2); } @@ -140,13 +139,9 @@ public class MetricalIndexApproximationMaterializeKNNPreprocessor<O extends Numb getLogger().warning("Cache should be empty after each run, but still has " + cache.size() + " elements."); } } - if(progress != null) { - progress.incrementProcessed(getLogger()); - } - } - if(progress != null) { - progress.ensureCompleted(getLogger()); + getLogger().incrementProcessed(progress); } + getLogger().ensureCompleted(progress); if(getLogger().isVerbose()) { getLogger().verbose("Average page size = " + pagesize.getMean() + " +- " + pagesize.getSampleStddev()); getLogger().verbose("On average, " + ksize.getMean() + " +- " + ksize.getSampleStddev() + " neighbors returned."); @@ -161,9 +156,9 @@ public class MetricalIndexApproximationMaterializeKNNPreprocessor<O extends Numb * @return Metrical index * @throws IllegalStateException when the cast fails. */ - private MetricalIndexTree<O, D, N, E> getMetricalIndex(Relation<O> relation) throws IllegalStateException { - Class<MetricalIndexTree<O, D, N, E>> mcls = ClassGenericsUtil.uglyCastIntoSubclass(MetricalIndexTree.class); - ArrayList<MetricalIndexTree<O, D, N, E>> indexes = ResultUtil.filterResults(relation.getDatabase(), mcls); + private MetricalIndexTree<O, N, E> getMetricalIndex(Relation<O> relation) throws IllegalStateException { + Class<MetricalIndexTree<O, N, E>> mcls = ClassGenericsUtil.uglyCastIntoSubclass(MetricalIndexTree.class); + ArrayList<MetricalIndexTree<O, N, E>> indexes = ResultUtil.filterResults(relation.getDatabase(), mcls); // FIXME: check we got the right the representation if(indexes.size() == 1) { return indexes.get(0); @@ -204,24 +199,23 @@ public class MetricalIndexApproximationMaterializeKNNPreprocessor<O extends Numb * - «create» * * @param <O> the type of database objects the preprocessor can be applied to - * @param <D> the type of distance the used distance function will return * @param <N> the type of spatial nodes in the spatial index * @param <E> the type of spatial entries in the spatial index */ - public static class Factory<O extends NumberVector<?>, D extends Distance<D>, N extends Node<E>, E extends MTreeEntry> extends AbstractMaterializeKNNPreprocessor.Factory<O, D, KNNList<D>> { + public static class Factory<O extends NumberVector, N extends Node<E>, E extends MTreeEntry> extends AbstractMaterializeKNNPreprocessor.Factory<O> { /** * Constructor. * * @param k k * @param distanceFunction distance function */ - public Factory(int k, DistanceFunction<? super O, D> distanceFunction) { + public Factory(int k, DistanceFunction<? super O> distanceFunction) { super(k, distanceFunction); } @Override - public MetricalIndexApproximationMaterializeKNNPreprocessor<O, D, N, E> instantiate(Relation<O> relation) { - MetricalIndexApproximationMaterializeKNNPreprocessor<O, D, N, E> instance = new MetricalIndexApproximationMaterializeKNNPreprocessor<>(relation, distanceFunction, k); + public MetricalIndexApproximationMaterializeKNNPreprocessor<O, N, E> instantiate(Relation<O> relation) { + MetricalIndexApproximationMaterializeKNNPreprocessor<O, N, E> instance = new MetricalIndexApproximationMaterializeKNNPreprocessor<>(relation, distanceFunction, k); return instance; } @@ -232,9 +226,9 @@ public class MetricalIndexApproximationMaterializeKNNPreprocessor<O extends Numb * * @apiviz.exclude */ - public static class Parameterizer<O extends NumberVector<?>, D extends Distance<D>, N extends Node<E>, E extends MTreeEntry> extends AbstractMaterializeKNNPreprocessor.Factory.Parameterizer<O, D> { + public static class Parameterizer<O extends NumberVector, N extends Node<E>, E extends MTreeEntry> extends AbstractMaterializeKNNPreprocessor.Factory.Parameterizer<O> { @Override - protected Factory<O, D, N, E> makeInstance() { + protected Factory<O, N, E> makeInstance() { return new Factory<>(k, distanceFunction); } } diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/PartitionApproximationMaterializeKNNPreprocessor.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/PartitionApproximationMaterializeKNNPreprocessor.java index b6cc5103..ef276e78 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/PartitionApproximationMaterializeKNNPreprocessor.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/PartitionApproximationMaterializeKNNPreprocessor.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.knn; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,24 +23,23 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.knn; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import java.util.HashMap; - +import gnu.trove.impl.Constants; +import gnu.trove.map.hash.TObjectDoubleHashMap; 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.ids.ArrayDBIDs; import de.lmu.ifi.dbs.elki.database.ids.DBIDIter; import de.lmu.ifi.dbs.elki.database.ids.DBIDPair; import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNHeap; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList; +import de.lmu.ifi.dbs.elki.database.ids.KNNHeap; +import de.lmu.ifi.dbs.elki.database.ids.KNNList; import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; import de.lmu.ifi.dbs.elki.logging.Logging; import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress; import de.lmu.ifi.dbs.elki.math.MeanVariance; -import de.lmu.ifi.dbs.elki.utilities.RandomFactory; +import de.lmu.ifi.dbs.elki.math.random.RandomFactory; import de.lmu.ifi.dbs.elki.utilities.documentation.Description; import de.lmu.ifi.dbs.elki.utilities.documentation.Title; import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID; @@ -58,11 +57,10 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.RandomParameter; * @author Erich Schubert * * @param <O> the type of database objects the preprocessor can be applied to - * @param <D> the type of distance the used distance function will return */ @Title("Partitioning Approximate kNN Preprocessor") @Description("Caterializes the (approximate) k nearest neighbors of objects of a database by partitioning and only computing kNN within each partition.") -public class PartitionApproximationMaterializeKNNPreprocessor<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor<O, D, KNNList<D>> { +public class PartitionApproximationMaterializeKNNPreprocessor<O> extends AbstractMaterializeKNNPreprocessor<O> { /** * Logger to use */ @@ -87,7 +85,7 @@ public class PartitionApproximationMaterializeKNNPreprocessor<O, D extends Dista * @param partitions Number of partitions * @param rnd Random number generator */ - public PartitionApproximationMaterializeKNNPreprocessor(Relation<O> relation, DistanceFunction<? super O, D> distanceFunction, int k, int partitions, RandomFactory rnd) { + public PartitionApproximationMaterializeKNNPreprocessor(Relation<O> relation, DistanceFunction<? super O> distanceFunction, int k, int partitions, RandomFactory rnd) { super(relation, distanceFunction, k); this.partitions = partitions; this.rnd = rnd; @@ -95,7 +93,7 @@ public class PartitionApproximationMaterializeKNNPreprocessor<O, D extends Dista @Override protected void preprocess() { - DistanceQuery<O, D> distanceQuery = relation.getDatabase().getDistanceQuery(relation, distanceFunction); + DistanceQuery<O> distanceQuery = relation.getDatabase().getDistanceQuery(relation, distanceFunction); storage = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, KNNList.class); MeanVariance ksize = new MeanVariance(); if(LOG.isVerbose()) { @@ -109,13 +107,13 @@ public class PartitionApproximationMaterializeKNNPreprocessor<O, D extends Dista for(int part = 0; part < partitions; part++) { final ArrayDBIDs ids = parts[part]; final int size = ids.size(); - HashMap<DBIDPair, D> cache = new HashMap<>((size * size * 3) >> 3); + TObjectDoubleHashMap<DBIDPair> cache = new TObjectDoubleHashMap<>((size * size * 3) >> 3, Constants.DEFAULT_LOAD_FACTOR, Double.NaN); for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { - KNNHeap<D> kNN = DBIDUtil.newHeap(distanceFunction.getDistanceFactory(), k); + KNNHeap kNN = DBIDUtil.newHeap(k); for(DBIDIter iter2 = ids.iter(); iter2.valid(); iter2.advance()) { DBIDPair key = DBIDUtil.newPair(iter, iter2); - D d = cache.remove(key); - if(d != null) { + double d = cache.remove(key); + if(d == d) { // Not NaN // consume the previous result. kNN.insert(d, iter2); } @@ -136,13 +134,9 @@ public class PartitionApproximationMaterializeKNNPreprocessor<O, D extends Dista LOG.warning("Cache should be empty after each run, but still has " + cache.size() + " elements."); } } - if(progress != null) { - progress.incrementProcessed(LOG); - } - } - if(progress != null) { - progress.ensureCompleted(LOG); + LOG.incrementProcessed(progress); } + LOG.ensureCompleted(progress); if(LOG.isVerbose()) { LOG.verbose("On average, " + ksize.getMean() + " +- " + ksize.getSampleStddev() + " neighbors returned."); } @@ -178,9 +172,8 @@ public class PartitionApproximationMaterializeKNNPreprocessor<O, D extends Dista * «create» * * @param <O> The object type - * @param <D> The distance type */ - public static class Factory<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor.Factory<O, D, KNNList<D>> { + public static class Factory<O> extends AbstractMaterializeKNNPreprocessor.Factory<O> { /** * The number of partitions to use */ @@ -199,15 +192,15 @@ public class PartitionApproximationMaterializeKNNPreprocessor<O, D extends Dista * @param partitions number of partitions * @param rnd */ - public Factory(int k, DistanceFunction<? super O, D> distanceFunction, int partitions, RandomFactory rnd) { + public Factory(int k, DistanceFunction<? super O> distanceFunction, int partitions, RandomFactory rnd) { super(k, distanceFunction); this.partitions = partitions; this.rnd = rnd; } @Override - public PartitionApproximationMaterializeKNNPreprocessor<O, D> instantiate(Relation<O> relation) { - PartitionApproximationMaterializeKNNPreprocessor<O, D> instance = new PartitionApproximationMaterializeKNNPreprocessor<>(relation, distanceFunction, k, partitions, rnd); + public PartitionApproximationMaterializeKNNPreprocessor<O> instantiate(Relation<O> relation) { + PartitionApproximationMaterializeKNNPreprocessor<O> instance = new PartitionApproximationMaterializeKNNPreprocessor<>(relation, distanceFunction, k, partitions, rnd); return instance; } @@ -218,7 +211,7 @@ public class PartitionApproximationMaterializeKNNPreprocessor<O, D extends Dista * * @apiviz.exclude */ - public static class Parameterizer<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor.Factory.Parameterizer<O, D> { + public static class Parameterizer<O> extends AbstractMaterializeKNNPreprocessor.Factory.Parameterizer<O> { /** * Parameter to specify the number of partitions to use for materializing * the kNN. Must be an integer greater than 1. @@ -261,7 +254,7 @@ public class PartitionApproximationMaterializeKNNPreprocessor<O, D extends Dista } @Override - protected Factory<O, D> makeInstance() { + protected Factory<O> makeInstance() { return new Factory<>(k, distanceFunction, partitions, rnd); } } diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/RandomSampleKNNPreprocessor.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/RandomSampleKNNPreprocessor.java index 87b5a3c0..0f07713f 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/RandomSampleKNNPreprocessor.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/RandomSampleKNNPreprocessor.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.knn; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -29,15 +29,14 @@ import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs; import de.lmu.ifi.dbs.elki.database.ids.DBIDIter; import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil; import de.lmu.ifi.dbs.elki.database.ids.DBIDs; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNHeap; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList; +import de.lmu.ifi.dbs.elki.database.ids.KNNHeap; +import de.lmu.ifi.dbs.elki.database.ids.KNNList; import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; import de.lmu.ifi.dbs.elki.logging.Logging; import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress; -import de.lmu.ifi.dbs.elki.utilities.RandomFactory; +import de.lmu.ifi.dbs.elki.math.random.RandomFactory; import de.lmu.ifi.dbs.elki.utilities.documentation.Reference; import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID; import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.CommonConstraints; @@ -60,10 +59,9 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.RandomParameter; * @author Erich Schubert * * @param <O> Object type - * @param <D> Distance type */ @Reference(title = "Subsampling for Efficient and Effective Unsupervised Outlier Detection Ensembles", authors = "A. Zimek and M. Gaudet and R. J. G. B. Campello and J. Sander", booktitle = "Proc. 19th ACM SIGKDD International Conference on Knowledge Discovery and Data Mining, KDD '13") -public class RandomSampleKNNPreprocessor<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor<O, D, KNNList<D>> { +public class RandomSampleKNNPreprocessor<O> extends AbstractMaterializeKNNPreprocessor<O> { /** * Logger */ @@ -88,7 +86,7 @@ public class RandomSampleKNNPreprocessor<O, D extends Distance<D>> extends Abstr * @param share Relative share * @param rnd Random generator */ - public RandomSampleKNNPreprocessor(Relation<O> relation, DistanceFunction<? super O, D> distanceFunction, int k, double share, RandomFactory rnd) { + public RandomSampleKNNPreprocessor(Relation<O> relation, DistanceFunction<? super O> distanceFunction, int k, double share, RandomFactory rnd) { super(relation, distanceFunction, k); this.share = share; this.rnd = rnd; @@ -96,7 +94,7 @@ public class RandomSampleKNNPreprocessor<O, D extends Distance<D>> extends Abstr @Override protected void preprocess() { - DistanceQuery<O, D> distanceQuery = relation.getDatabase().getDistanceQuery(relation, distanceFunction); + DistanceQuery<O> distanceQuery = relation.getDatabase().getDistanceQuery(relation, distanceFunction); storage = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, KNNList.class); FiniteProgress progress = getLogger().isVerbose() ? new FiniteProgress("Materializing random-sample k nearest neighbors (k=" + k + ")", relation.size(), getLogger()) : null; @@ -104,23 +102,19 @@ public class RandomSampleKNNPreprocessor<O, D extends Distance<D>> extends Abstr final int samplesize = (int) (ids.size() * share); for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { - KNNHeap<D> kNN = DBIDUtil.newHeap(distanceFunction.getDistanceFactory(), k); + KNNHeap kNN = DBIDUtil.newHeap(k); DBIDs rsamp = DBIDUtil.randomSample(ids, samplesize, rnd); for(DBIDIter iter2 = rsamp.iter(); iter2.valid(); iter2.advance()) { - D dist = distanceQuery.distance(iter, iter2); + double dist = distanceQuery.distance(iter, iter2); kNN.insert(dist, iter2); } storage.put(iter, kNN.toKNNList()); - if(progress != null) { - progress.incrementProcessed(getLogger()); - } + getLogger().incrementProcessed(progress); } - if(progress != null) { - progress.ensureCompleted(getLogger()); - } + getLogger().ensureCompleted(progress); } @Override @@ -153,9 +147,8 @@ public class RandomSampleKNNPreprocessor<O, D extends Distance<D>> extends Abstr * @apiviz.uses AbstractMaterializeKNNPreprocessor oneway - - «create» * * @param <O> The object type - * @param <D> The distance type */ - public static class Factory<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor.Factory<O, D, KNNList<D>> { + public static class Factory<O> extends AbstractMaterializeKNNPreprocessor.Factory<O> { /** * Relative share of objects to get */ @@ -174,14 +167,14 @@ public class RandomSampleKNNPreprocessor<O, D extends Distance<D>> extends Abstr * @param share Sample size (relative) * @param rnd Random generator */ - public Factory(int k, DistanceFunction<? super O, D> distanceFunction, double share, RandomFactory rnd) { + public Factory(int k, DistanceFunction<? super O> distanceFunction, double share, RandomFactory rnd) { super(k, distanceFunction); this.share = share; this.rnd = rnd; } @Override - public RandomSampleKNNPreprocessor<O, D> instantiate(Relation<O> relation) { + public RandomSampleKNNPreprocessor<O> instantiate(Relation<O> relation) { return new RandomSampleKNNPreprocessor<>(relation, distanceFunction, k, share, rnd); } @@ -193,9 +186,8 @@ public class RandomSampleKNNPreprocessor<O, D extends Distance<D>> extends Abstr * @apiviz.exclude * * @param <O> Object type - * @param <D> Distance type */ - public static class Parameterizer<O, D extends Distance<D>> extends AbstractMaterializeKNNPreprocessor.Factory.Parameterizer<O, D> { + public static class Parameterizer<O> extends AbstractMaterializeKNNPreprocessor.Factory.Parameterizer<O> { /** * Parameter to specify how many objects to consider for computing the * kNN. @@ -241,7 +233,7 @@ public class RandomSampleKNNPreprocessor<O, D extends Distance<D>> extends Abstr } @Override - protected RandomSampleKNNPreprocessor.Factory<O, D> makeInstance() { + protected RandomSampleKNNPreprocessor.Factory<O> makeInstance() { return new RandomSampleKNNPreprocessor.Factory<>(k, distanceFunction, share, rnd); } } diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/SpatialApproximationMaterializeKNNPreprocessor.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/SpatialApproximationMaterializeKNNPreprocessor.java index 83f8f6d8..cd363091 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/SpatialApproximationMaterializeKNNPreprocessor.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/SpatialApproximationMaterializeKNNPreprocessor.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.knn; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,8 +23,10 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.knn; along with this program. If not, see <http://www.gnu.org/licenses/>. */ +import gnu.trove.impl.Constants; +import gnu.trove.map.hash.TObjectDoubleHashMap; + import java.util.Collection; -import java.util.HashMap; import java.util.List; import de.lmu.ifi.dbs.elki.data.NumberVector; @@ -34,12 +36,11 @@ import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs; import de.lmu.ifi.dbs.elki.database.ids.DBIDIter; import de.lmu.ifi.dbs.elki.database.ids.DBIDPair; import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNHeap; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList; +import de.lmu.ifi.dbs.elki.database.ids.KNNHeap; +import de.lmu.ifi.dbs.elki.database.ids.KNNList; import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; import de.lmu.ifi.dbs.elki.index.tree.LeafEntry; import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry; import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialIndexTree; @@ -64,13 +65,12 @@ import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException; * * @apiviz.uses SpatialIndexTree * - * @param <D> the type of distance the used distance function will return * @param <N> the type of spatial nodes in the spatial index * @param <E> the type of spatial entries in the spatial index */ @Title("Spatial Approximation Materialize kNN Preprocessor") @Description("Caterializes the (approximate) k nearest neighbors of objects of a database using a spatial approximation.") -public class SpatialApproximationMaterializeKNNPreprocessor<O extends NumberVector<?>, D extends Distance<D>, N extends SpatialNode<N, E>, E extends SpatialEntry> extends AbstractMaterializeKNNPreprocessor<O, D, KNNList<D>> { +public class SpatialApproximationMaterializeKNNPreprocessor<O extends NumberVector, N extends SpatialNode<N, E>, E extends SpatialEntry> extends AbstractMaterializeKNNPreprocessor<O> { /** * Logger to use */ @@ -83,13 +83,13 @@ public class SpatialApproximationMaterializeKNNPreprocessor<O extends NumberVect * @param distanceFunction the distance function to use * @param k query k */ - public SpatialApproximationMaterializeKNNPreprocessor(Relation<O> relation, DistanceFunction<? super O, D> distanceFunction, int k) { + public SpatialApproximationMaterializeKNNPreprocessor(Relation<O> relation, DistanceFunction<? super O> distanceFunction, int k) { super(relation, distanceFunction, k); } @Override protected void preprocess() { - DistanceQuery<O, D> distanceQuery = relation.getDatabase().getDistanceQuery(relation, distanceFunction); + DistanceQuery<O> distanceQuery = relation.getDatabase().getDistanceQuery(relation, distanceFunction); Collection<SpatialIndexTree<N, E>> indexes = ResultUtil.filterResults(relation, SpatialIndexTree.class); if(indexes.size() != 1) { @@ -118,13 +118,13 @@ public class SpatialApproximationMaterializeKNNPreprocessor<O extends NumberVect for(int i = 0; i < size; i++) { ids.add(((LeafEntry) node.getEntry(i)).getDBID()); } - HashMap<DBIDPair, D> cache = new HashMap<>((size * size * 3) >> 3); + TObjectDoubleHashMap<DBIDPair> cache = new TObjectDoubleHashMap<>((size * size * 3) >> 3, Constants.DEFAULT_LOAD_FACTOR, Double.NaN); for(DBIDIter id = ids.iter(); id.valid(); id.advance()) { - KNNHeap<D> kNN = DBIDUtil.newHeap(distanceFunction.getDistanceFactory(), k); + KNNHeap kNN = DBIDUtil.newHeap(k); for(DBIDIter id2 = ids.iter(); id2.valid(); id2.advance()) { DBIDPair key = DBIDUtil.newPair(id, id2); - D d = cache.remove(key); - if(d != null) { + double d = cache.remove(key); + if(d == d) { // Not NaN // consume the previous result. kNN.insert(d, id2); } @@ -145,13 +145,9 @@ public class SpatialApproximationMaterializeKNNPreprocessor<O extends NumberVect getLogger().warning("Cache should be empty after each run, but still has " + cache.size() + " elements."); } } - if(progress != null) { - progress.incrementProcessed(getLogger()); - } - } - if(progress != null) { - progress.ensureCompleted(getLogger()); + getLogger().incrementProcessed(progress); } + getLogger().ensureCompleted(progress); if(getLogger().isVerbose()) { getLogger().verbose("Average page size = " + pagesize.getMean() + " +- " + pagesize.getSampleStddev()); getLogger().verbose("On average, " + ksize.getMean() + " +- " + ksize.getSampleStddev() + " neighbors returned."); @@ -187,24 +183,23 @@ public class SpatialApproximationMaterializeKNNPreprocessor<O extends NumberVect * @apiviz.uses SpatialApproximationMaterializeKNNPreprocessor oneway - - * «create» * - * @param <D> the type of distance the used distance function will return * @param <N> the type of spatial nodes in the spatial index * @param <E> the type of spatial entries in the spatial index */ - public static class Factory<D extends Distance<D>, N extends SpatialNode<N, E>, E extends SpatialEntry> extends AbstractMaterializeKNNPreprocessor.Factory<NumberVector<?>, D, KNNList<D>> { + public static class Factory<N extends SpatialNode<N, E>, E extends SpatialEntry> extends AbstractMaterializeKNNPreprocessor.Factory<NumberVector> { /** * Constructor. * * @param k k * @param distanceFunction distance function */ - public Factory(int k, DistanceFunction<? super NumberVector<?>, D> distanceFunction) { + public Factory(int k, DistanceFunction<? super NumberVector> distanceFunction) { super(k, distanceFunction); } @Override - public SpatialApproximationMaterializeKNNPreprocessor<NumberVector<?>, D, N, E> instantiate(Relation<NumberVector<?>> relation) { - SpatialApproximationMaterializeKNNPreprocessor<NumberVector<?>, D, N, E> instance = new SpatialApproximationMaterializeKNNPreprocessor<>(relation, distanceFunction, k); + public SpatialApproximationMaterializeKNNPreprocessor<NumberVector, N, E> instantiate(Relation<NumberVector> relation) { + SpatialApproximationMaterializeKNNPreprocessor<NumberVector, N, E> instance = new SpatialApproximationMaterializeKNNPreprocessor<>(relation, distanceFunction, k); return instance; } @@ -215,9 +210,9 @@ public class SpatialApproximationMaterializeKNNPreprocessor<O extends NumberVect * * @apiviz.exclude */ - public static class Parameterizer<D extends Distance<D>, N extends SpatialNode<N, E>, E extends SpatialEntry> extends AbstractMaterializeKNNPreprocessor.Factory.Parameterizer<NumberVector<?>, D> { + public static class Parameterizer<N extends SpatialNode<N, E>, E extends SpatialEntry> extends AbstractMaterializeKNNPreprocessor.Factory.Parameterizer<NumberVector> { @Override - protected Factory<D, N, E> makeInstance() { + protected Factory<N, E> makeInstance() { return new Factory<>(k, distanceFunction); } } diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/package-info.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/package-info.java index 47339bb4..f5e3d978 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/knn/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2013 +Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/AbstractFilteredPCAIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/AbstractFilteredPCAIndex.java index 67a2effc..9599e310 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/AbstractFilteredPCAIndex.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/AbstractFilteredPCAIndex.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.localpca; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -29,11 +29,10 @@ 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.ids.DBIDIter; import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; -import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList; +import de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDList; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; import de.lmu.ifi.dbs.elki.index.preprocessed.AbstractPreprocessorIndex; import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress; import de.lmu.ifi.dbs.elki.math.linearalgebra.pca.PCAFilteredResult; @@ -44,7 +43,6 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Title; import de.lmu.ifi.dbs.elki.utilities.exceptions.ExceptionMessages; import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer; import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter; @@ -61,11 +59,11 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter; // TODO: loosen DoubleDistance restriction. @Title("Local PCA Preprocessor") @Description("Materializes the local PCA and the locally weighted matrix of objects of a database.") -public abstract class AbstractFilteredPCAIndex<NV extends NumberVector<?>> extends AbstractPreprocessorIndex<NV, PCAFilteredResult> implements FilteredLocalPCAIndex<NV> { +public abstract class AbstractFilteredPCAIndex<NV extends NumberVector> extends AbstractPreprocessorIndex<NV, PCAFilteredResult> implements FilteredLocalPCAIndex<NV> { /** * PCA utility object. */ - protected final PCAFilteredRunner<NV> pca; + protected final PCAFilteredRunner pca; /** * Constructor. @@ -73,7 +71,7 @@ public abstract class AbstractFilteredPCAIndex<NV extends NumberVector<?>> exten * @param relation Relation to use * @param pca PCA runner to use */ - public AbstractFilteredPCAIndex(Relation<NV> relation, PCAFilteredRunner<NV> pca) { + public AbstractFilteredPCAIndex(Relation<NV> relation, PCAFilteredRunner pca) { super(relation); this.pca = pca; } @@ -97,19 +95,15 @@ public abstract class AbstractFilteredPCAIndex<NV extends NumberVector<?>> exten // TODO: use a bulk operation? for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) { - DistanceDBIDList<DoubleDistance> objects = objectsForPCA(iditer); + DoubleDBIDList objects = objectsForPCA(iditer); PCAFilteredResult pcares = pca.processQueryResult(objects, relation); storage.put(iditer, pcares); - if(progress != null) { - progress.incrementProcessed(getLogger()); - } - } - if(progress != null) { - progress.ensureCompleted(getLogger()); + getLogger().incrementProcessed(progress); } + getLogger().ensureCompleted(progress); long end = System.currentTimeMillis(); if(getLogger().isVerbose()) { @@ -134,7 +128,7 @@ public abstract class AbstractFilteredPCAIndex<NV extends NumberVector<?>> exten * @return the list of the objects (i.e. the ids and the distances to the * query object) to be considered within the PCA */ - protected abstract DistanceDBIDList<DoubleDistance> objectsForPCA(DBIDRef id); + protected abstract DoubleDBIDList objectsForPCA(DBIDRef id); /** * Factory class. @@ -144,7 +138,7 @@ public abstract class AbstractFilteredPCAIndex<NV extends NumberVector<?>> exten * @apiviz.stereotype factory * @apiviz.uses AbstractFilteredPCAIndex oneway - - «create» */ - public abstract static class Factory<NV extends NumberVector<?>, I extends AbstractFilteredPCAIndex<NV>> implements FilteredLocalPCAIndex.Factory<NV, I>, Parameterizable { + public abstract static class Factory<NV extends NumberVector, I extends AbstractFilteredPCAIndex<NV>> implements FilteredLocalPCAIndex.Factory<NV, I> { /** * Parameter to specify the distance function used for running PCA. * @@ -156,12 +150,12 @@ public abstract class AbstractFilteredPCAIndex<NV extends NumberVector<?>> exten * Holds the instance of the distance function specified by * {@link #PCA_DISTANCE_ID}. */ - protected DistanceFunction<NV, DoubleDistance> pcaDistanceFunction; + protected DistanceFunction<NV> pcaDistanceFunction; /** * PCA utility object. */ - protected PCAFilteredRunner<NV> pca; + protected PCAFilteredRunner pca; /** * Constructor. @@ -169,7 +163,7 @@ public abstract class AbstractFilteredPCAIndex<NV extends NumberVector<?>> exten * @param pcaDistanceFunction distance Function * @param pca PCA runner */ - public Factory(DistanceFunction<NV, DoubleDistance> pcaDistanceFunction, PCAFilteredRunner<NV> pca) { + public Factory(DistanceFunction<NV> pcaDistanceFunction, PCAFilteredRunner pca) { super(); this.pcaDistanceFunction = pcaDistanceFunction; this.pca = pca; @@ -190,28 +184,28 @@ public abstract class AbstractFilteredPCAIndex<NV extends NumberVector<?>> exten * * @apiviz.exclude */ - public abstract static class Parameterizer<NV extends NumberVector<?>, I extends AbstractFilteredPCAIndex<NV>> extends AbstractParameterizer { + public abstract static class Parameterizer<NV extends NumberVector, I extends AbstractFilteredPCAIndex<NV>> extends AbstractParameterizer { /** * Holds the instance of the distance function specified by * {@link #PCA_DISTANCE_ID}. */ - protected DistanceFunction<NV, DoubleDistance> pcaDistanceFunction; + protected DistanceFunction<NV> pcaDistanceFunction; /** * PCA utility object. */ - protected PCAFilteredRunner<NV> pca; + protected PCAFilteredRunner pca; @Override protected void makeOptions(Parameterization config) { super.makeOptions(config); - final ObjectParameter<DistanceFunction<NV, DoubleDistance>> pcaDistanceFunctionP = new ObjectParameter<>(PCA_DISTANCE_ID, DistanceFunction.class, EuclideanDistanceFunction.class); + final ObjectParameter<DistanceFunction<NV>> pcaDistanceFunctionP = new ObjectParameter<>(PCA_DISTANCE_ID, DistanceFunction.class, EuclideanDistanceFunction.class); if(config.grab(pcaDistanceFunctionP)) { pcaDistanceFunction = pcaDistanceFunctionP.instantiateClass(config); } - Class<PCAFilteredRunner<NV>> cls = ClassGenericsUtil.uglyCastIntoSubclass(PCAFilteredRunner.class); + Class<PCAFilteredRunner> cls = ClassGenericsUtil.uglyCastIntoSubclass(PCAFilteredRunner.class); pca = config.tryInstantiate(cls); } } diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/FilteredLocalPCAIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/FilteredLocalPCAIndex.java index 2d64cbc0..85b98643 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/FilteredLocalPCAIndex.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/FilteredLocalPCAIndex.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.localpca; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -36,7 +36,7 @@ import de.lmu.ifi.dbs.elki.math.linearalgebra.pca.PCAFilteredResult; * * @param <NV> Vector type */ -public interface FilteredLocalPCAIndex<NV extends NumberVector<?>> extends LocalProjectionIndex<NV, PCAFilteredResult> { +public interface FilteredLocalPCAIndex<NV extends NumberVector> extends LocalProjectionIndex<NV, PCAFilteredResult> { /** * Get the precomputed local PCA for a particular object ID. * @@ -57,7 +57,7 @@ public interface FilteredLocalPCAIndex<NV extends NumberVector<?>> extends Local * @param <NV> Vector type * @param <I> Index type produced */ - public static interface Factory<NV extends NumberVector<?>, I extends FilteredLocalPCAIndex<NV>> extends LocalProjectionIndex.Factory<NV, I> { + public static interface Factory<NV extends NumberVector, I extends FilteredLocalPCAIndex<NV>> extends LocalProjectionIndex.Factory<NV, I> { /** * Instantiate the index for a given database. * diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/KNNQueryFilteredPCAIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/KNNQueryFilteredPCAIndex.java index 89c10bf2..49197bda 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/KNNQueryFilteredPCAIndex.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/KNNQueryFilteredPCAIndex.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.localpca; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -26,12 +26,11 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.localpca; import de.lmu.ifi.dbs.elki.data.NumberVector; import de.lmu.ifi.dbs.elki.database.QueryUtil; import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList; +import de.lmu.ifi.dbs.elki.database.ids.KNNList; import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.database.relation.RelationUtil; import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; import de.lmu.ifi.dbs.elki.logging.Logging; import de.lmu.ifi.dbs.elki.math.linearalgebra.pca.PCAFilteredRunner; import de.lmu.ifi.dbs.elki.utilities.documentation.Description; @@ -53,10 +52,9 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter; * * @param <NV> Vector type */ -// TODO: loosen DoubleDistance restriction. @Title("Knn Query Based Local PCA Preprocessor") @Description("Materializes the local PCA and the locally weighted matrix of objects of a database. The PCA is based on k nearest neighbor queries.") -public class KNNQueryFilteredPCAIndex<NV extends NumberVector<?>> extends AbstractFilteredPCAIndex<NV> { +public class KNNQueryFilteredPCAIndex<NV extends NumberVector> extends AbstractFilteredPCAIndex<NV> { /** * Logger. */ @@ -65,10 +63,10 @@ public class KNNQueryFilteredPCAIndex<NV extends NumberVector<?>> extends Abstra /** * The kNN query instance we use. */ - private final KNNQuery<NV, DoubleDistance> knnQuery; + private final KNNQuery<NV> knnQuery; /** - * Query k. + * Number of neighbors to query. */ private final int k; @@ -80,7 +78,7 @@ public class KNNQueryFilteredPCAIndex<NV extends NumberVector<?>> extends Abstra * @param knnQuery KNN Query to use * @param k k value */ - public KNNQueryFilteredPCAIndex(Relation<NV> relation, PCAFilteredRunner<NV> pca, KNNQuery<NV, DoubleDistance> knnQuery, int k) { + public KNNQueryFilteredPCAIndex(Relation<NV> relation, PCAFilteredRunner pca, KNNQuery<NV> knnQuery, int k) { super(relation, pca); this.knnQuery = knnQuery; this.k = k; @@ -92,7 +90,7 @@ public class KNNQueryFilteredPCAIndex<NV extends NumberVector<?>> extends Abstra } @Override - protected KNNList<DoubleDistance> objectsForPCA(DBIDRef id) { + protected KNNList objectsForPCA(DBIDRef id) { return knnQuery.getKNNForDBID(id, k); } @@ -125,25 +123,11 @@ public class KNNQueryFilteredPCAIndex<NV extends NumberVector<?>> extends Abstra * @apiviz.landmark * @apiviz.uses KNNQueryFilteredPCAIndex oneway - - «create» */ - public static class Factory<V extends NumberVector<?>> extends AbstractFilteredPCAIndex.Factory<V, KNNQueryFilteredPCAIndex<V>> { + public static class Factory<V extends NumberVector> extends AbstractFilteredPCAIndex.Factory<V, KNNQueryFilteredPCAIndex<V>> { /** - * Optional parameter to specify the number of nearest neighbors considered - * in the PCA, must be an integer greater than 0. If this parameter is not - * set, k is set to three times of the dimensionality of the database - * objects. - * <p> - * Key: {@code -localpca.k} - * </p> - * <p> - * Default value: three times of the dimensionality of the database objects - * </p> + * Number of neighbors to query. */ - public static final OptionID K_ID = new OptionID("localpca.k", "The number of nearest neighbors considered in the PCA. " + "If this parameter is not set, k ist set to three " + "times of the dimensionality of the database objects."); - - /** - * Holds the value of {@link #K_ID}. - */ - private Integer k = null; + private int k; /** * Constructor. @@ -152,7 +136,7 @@ public class KNNQueryFilteredPCAIndex<NV extends NumberVector<?>> extends Abstra * @param pca PCA class * @param k k */ - public Factory(DistanceFunction<V, DoubleDistance> pcaDistanceFunction, PCAFilteredRunner<V> pca, Integer k) { + public Factory(DistanceFunction<V> pcaDistanceFunction, PCAFilteredRunner pca, int k) { super(pcaDistanceFunction, pca); this.k = k; } @@ -160,7 +144,7 @@ public class KNNQueryFilteredPCAIndex<NV extends NumberVector<?>> extends Abstra @Override public KNNQueryFilteredPCAIndex<V> instantiate(Relation<V> relation) { // TODO: set bulk flag, once the parent class supports bulk. - KNNQuery<V, DoubleDistance> knnquery = QueryUtil.getKNNQuery(relation, pcaDistanceFunction, k); + KNNQuery<V> knnquery = QueryUtil.getKNNQuery(relation, pcaDistanceFunction, k); return new KNNQueryFilteredPCAIndex<>(relation, pca, knnquery, k); } @@ -171,16 +155,34 @@ public class KNNQueryFilteredPCAIndex<NV extends NumberVector<?>> extends Abstra * * @apiviz.exclude */ - public static class Parameterizer<NV extends NumberVector<?>> extends AbstractFilteredPCAIndex.Factory.Parameterizer<NV, KNNQueryFilteredPCAIndex<NV>> { + public static class Parameterizer<NV extends NumberVector> extends AbstractFilteredPCAIndex.Factory.Parameterizer<NV, KNNQueryFilteredPCAIndex<NV>> { + /** + * Optional parameter to specify the number of nearest neighbors + * considered in the PCA, must be an integer greater than 0. If this + * parameter is not set, k is set to three times of the dimensionality of + * the database objects. + * <p> + * Key: {@code -localpca.k} + * </p> + * <p> + * Default value: three times of the dimensionality of the database + * objects + * </p> + */ + public static final OptionID K_ID = new OptionID("localpca.k", "The number of nearest neighbors considered in the PCA. " + "If this parameter is not set, k ist set to three " + "times of the dimensionality of the database objects."); + + /** + * Number of neighbors to query. + */ protected int k = 0; @Override protected void makeOptions(Parameterization config) { super.makeOptions(config); - final IntParameter kP = new IntParameter(K_ID); - kP.addConstraint(CommonConstraints.GREATER_EQUAL_ONE_INT); + final IntParameter kP = new IntParameter(K_ID) // + .addConstraint(CommonConstraints.GREATER_THAN_ONE_INT); if(config.grab(kP)) { - k = kP.getValue(); + k = kP.intValue(); } } diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/RangeQueryFilteredPCAIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/RangeQueryFilteredPCAIndex.java deleted file mode 100644 index 03b49df3..00000000 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/RangeQueryFilteredPCAIndex.java +++ /dev/null @@ -1,178 +0,0 @@ -package de.lmu.ifi.dbs.elki.index.preprocessed.localpca; - -/* - This file is part of ELKI: - Environment for Developing KDD-Applications Supported by Index-Structures - - Copyright (C) 2013 - Ludwig-Maximilians-Universität München - Lehr- und Forschungseinheit für Datenbanksysteme - ELKI Development Team - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -import de.lmu.ifi.dbs.elki.data.NumberVector; -import de.lmu.ifi.dbs.elki.database.QueryUtil; -import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; -import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList; -import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery; -import de.lmu.ifi.dbs.elki.database.relation.Relation; -import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; -import de.lmu.ifi.dbs.elki.logging.Logging; -import de.lmu.ifi.dbs.elki.math.linearalgebra.pca.PCAFilteredRunner; -import de.lmu.ifi.dbs.elki.utilities.documentation.Description; -import de.lmu.ifi.dbs.elki.utilities.documentation.Title; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DistanceParameter; - -/** - * Provides the local neighborhood to be considered in the PCA as the neighbors - * within an epsilon range query of an object. - * - * @author Elke Achtert - * @author Erich Schubert - * - * @apiviz.uses RangeQuery - * - * @param <NV> Vector type - */ -@Title("Range Query Based Local PCA Preprocessor") -@Description("Materializes the local PCA and the locally weighted matrix of objects of a database. The PCA is based on epsilon range queries.") -public class RangeQueryFilteredPCAIndex<NV extends NumberVector<?>> extends AbstractFilteredPCAIndex<NV> { - // TODO: lose DoubleDistance restriction. - /** - * Logger. - */ - private static final Logging LOG = Logging.getLogger(RangeQueryFilteredPCAIndex.class); - - /** - * The kNN query instance we use. - */ - private final RangeQuery<NV, DoubleDistance> rangeQuery; - - /** - * Query epsilon. - */ - private final DoubleDistance epsilon; - - /** - * Constructor. - * - * @param database Database to use - * @param pca PCA Runner to use - * @param rangeQuery Range Query to use - * @param epsilon Query range - */ - public RangeQueryFilteredPCAIndex(Relation<NV> database, PCAFilteredRunner<NV> pca, RangeQuery<NV, DoubleDistance> rangeQuery, DoubleDistance epsilon) { - super(database, pca); - this.rangeQuery = rangeQuery; - this.epsilon = epsilon; - } - - @Override - protected DistanceDBIDList<DoubleDistance> objectsForPCA(DBIDRef id) { - return rangeQuery.getRangeForDBID(id, epsilon); - } - - @Override - public String getLongName() { - return "kNN-based local filtered PCA"; - } - - @Override - public String getShortName() { - return "kNNFilteredPCA"; - } - - @Override - protected Logging getLogger() { - return LOG; - } - - @Override - public void logStatistics() { - // No statistics to log. - } - - /** - * Factory class. - * - * @author Erich Schubert - * - * @apiviz.stereotype factory - * @apiviz.uses RangeQueryFilteredPCAIndex oneway - - «create» - */ - public static class Factory<V extends NumberVector<?>> extends AbstractFilteredPCAIndex.Factory<V, RangeQueryFilteredPCAIndex<V>> { - /** - * Parameter to specify the maximum radius of the neighborhood to be - * considered in the PCA, must be suitable to the distance function - * specified. - * - * Key: {@code -localpca.epsilon} - */ - public static final OptionID EPSILON_ID = new OptionID("localpca.epsilon", "The maximum radius of the neighborhood to be considered in the PCA."); - - /** - * Holds the value of {@link #EPSILON_ID}. - */ - protected DoubleDistance epsilon; - - /** - * Constructor. - * - * @param pcaDistanceFunction distance function - * @param pca PCA - * @param epsilon range value - */ - public Factory(DistanceFunction<V, DoubleDistance> pcaDistanceFunction, PCAFilteredRunner<V> pca, DoubleDistance epsilon) { - super(pcaDistanceFunction, pca); - this.epsilon = epsilon; - } - - @Override - public RangeQueryFilteredPCAIndex<V> instantiate(Relation<V> relation) { - // TODO: set bulk flag, once the parent class supports bulk. - RangeQuery<V, DoubleDistance> rangequery = QueryUtil.getRangeQuery(relation, pcaDistanceFunction); - return new RangeQueryFilteredPCAIndex<>(relation, pca, rangequery, epsilon); - } - - /** - * Parameterization class. - * - * @author Erich Schubert - * - * @apiviz.exclude - */ - public static class Parameterizer<NV extends NumberVector<?>> extends AbstractFilteredPCAIndex.Factory.Parameterizer<NV, RangeQueryFilteredPCAIndex<NV>> { - protected DoubleDistance epsilon = null; - - @Override - protected void makeOptions(Parameterization config) { - super.makeOptions(config); - DistanceParameter<DoubleDistance> epsilonP = new DistanceParameter<>(EPSILON_ID, pcaDistanceFunction != null ? pcaDistanceFunction.getDistanceFactory() : null); - if(config.grab(epsilonP)) { - epsilon = epsilonP.getValue(); - } - } - - @Override - protected Factory<NV> makeInstance() { - return new Factory<>(pcaDistanceFunction, pca, epsilon); - } - } - } -}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/package-info.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/package-info.java index 536dbb3c..a44b99a3 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/localpca/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2013 +Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/package-info.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/package-info.java index 2edb1244..8107fe74 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2013 +Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/AbstractPreferenceVectorIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/AbstractPreferenceVectorIndex.java index dd43e027..80753ace 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/AbstractPreferenceVectorIndex.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/AbstractPreferenceVectorIndex.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.preference; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,15 +23,12 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.preference; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import java.util.BitSet; - import de.lmu.ifi.dbs.elki.data.NumberVector; import de.lmu.ifi.dbs.elki.data.type.TypeInformation; import de.lmu.ifi.dbs.elki.data.type.TypeUtil; import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.index.preprocessed.AbstractPreprocessorIndex; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable; /** * Abstract base class for preference vector based algorithms. @@ -40,7 +37,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable; * * @param <NV> Number vector */ -public abstract class AbstractPreferenceVectorIndex<NV extends NumberVector<?>> extends AbstractPreprocessorIndex<NV, BitSet> implements PreferenceVectorIndex<NV> { +public abstract class AbstractPreferenceVectorIndex<NV extends NumberVector> extends AbstractPreprocessorIndex<NV, long[]> implements PreferenceVectorIndex<NV> { /** * Constructor. * @@ -51,7 +48,7 @@ public abstract class AbstractPreferenceVectorIndex<NV extends NumberVector<?>> } @Override - public BitSet getPreferenceVector(DBIDRef objid) { + public long[] getPreferenceVector(DBIDRef objid) { if(storage == null) { initialize(); } @@ -66,7 +63,7 @@ public abstract class AbstractPreferenceVectorIndex<NV extends NumberVector<?>> * @apiviz.stereotype factory * @apiviz.uses AbstractPreferenceVectorIndex oneway - - «create» */ - public abstract static class Factory<V extends NumberVector<?>, I extends PreferenceVectorIndex<V>> implements PreferenceVectorIndex.Factory<V, I>, Parameterizable { + public abstract static class Factory<V extends NumberVector, I extends PreferenceVectorIndex<V>> implements PreferenceVectorIndex.Factory<V, I> { @Override public abstract I instantiate(Relation<V> relation); diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/DiSHPreferenceVectorIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/DiSHPreferenceVectorIndex.java index 99a13a23..ccc04d45 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/DiSHPreferenceVectorIndex.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/DiSHPreferenceVectorIndex.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.preference; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -25,17 +25,17 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.preference; import java.util.ArrayList; import java.util.Arrays; -import java.util.BitSet; import java.util.HashMap; import java.util.List; import java.util.Map; -import de.lmu.ifi.dbs.elki.algorithm.APRIORI; -import de.lmu.ifi.dbs.elki.data.Bit; +import de.lmu.ifi.dbs.elki.algorithm.itemsetmining.APRIORI; +import de.lmu.ifi.dbs.elki.algorithm.itemsetmining.Itemset; import de.lmu.ifi.dbs.elki.data.BitVector; import de.lmu.ifi.dbs.elki.data.NumberVector; import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation; import de.lmu.ifi.dbs.elki.data.type.VectorFieldTypeInformation; +import de.lmu.ifi.dbs.elki.database.Database; import de.lmu.ifi.dbs.elki.database.HashmapDatabase; import de.lmu.ifi.dbs.elki.database.UpdatableDatabase; import de.lmu.ifi.dbs.elki.database.datastore.DataStoreFactory; @@ -43,23 +43,21 @@ import de.lmu.ifi.dbs.elki.database.datastore.DataStoreUtil; 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.DoubleDBIDList; import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs; -import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList; import de.lmu.ifi.dbs.elki.database.query.distance.PrimitiveDistanceQuery; import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.database.relation.RelationUtil; import de.lmu.ifi.dbs.elki.datasource.bundle.SingleObjectBundle; -import de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.DimensionSelectingDistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; +import de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.OnedimensionalDistanceFunction; import de.lmu.ifi.dbs.elki.logging.Logging; import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress; import de.lmu.ifi.dbs.elki.result.AprioriResult; +import de.lmu.ifi.dbs.elki.utilities.BitsUtil; import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil; -import de.lmu.ifi.dbs.elki.utilities.FormatUtil; import de.lmu.ifi.dbs.elki.utilities.documentation.Description; import de.lmu.ifi.dbs.elki.utilities.exceptions.ExceptionMessages; -import de.lmu.ifi.dbs.elki.utilities.exceptions.UnableToComplyException; import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer; import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID; import de.lmu.ifi.dbs.elki.utilities.optionhandling.WrongParameterValueException; @@ -78,7 +76,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter; * @param <V> Vector type */ @Description("Computes the preference vector of objects of a certain database according to the DiSH algorithm.") -public class DiSHPreferenceVectorIndex<V extends NumberVector<?>> extends AbstractPreferenceVectorIndex<V> implements PreferenceVectorIndex<V> { +public class DiSHPreferenceVectorIndex<V extends NumberVector> extends AbstractPreferenceVectorIndex<V> implements PreferenceVectorIndex<V> { /** * Logger to use. */ @@ -103,7 +101,7 @@ public class DiSHPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra /** * The epsilon value for each dimension. */ - protected DoubleDistance[] epsilon; + protected double[] epsilon; /** * Threshold for minimum number of points in the neighborhood. @@ -123,7 +121,7 @@ public class DiSHPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra * @param minpts MinPts value * @param strategy Strategy */ - public DiSHPreferenceVectorIndex(Relation<V> relation, DoubleDistance[] epsilon, int minpts, Strategy strategy) { + public DiSHPreferenceVectorIndex(Relation<V> relation, double[] epsilon, int minpts, Strategy strategy) { super(relation); this.epsilon = epsilon; this.minpts = minpts; @@ -136,7 +134,7 @@ public class DiSHPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra throw new IllegalArgumentException(ExceptionMessages.DATABASE_EMPTY); } - storage = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP, BitSet.class); + storage = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP, long[].class); if(LOG.isDebugging()) { StringBuilder msg = new StringBuilder(); @@ -152,13 +150,13 @@ public class DiSHPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra // only one epsilon value specified int dim = RelationUtil.dimensionality(relation); if(epsilon.length == 1 && dim != 1) { - DoubleDistance eps = epsilon[0]; - epsilon = new DoubleDistance[dim]; + double eps = epsilon[0]; + epsilon = new double[dim]; Arrays.fill(epsilon, eps); } // epsilons as string - RangeQuery<V, DoubleDistance>[] rangeQueries = initRangeQueries(relation, dim); + RangeQuery<V>[] rangeQueries = initRangeQueries(relation, dim); for(DBIDIter it = relation.iterDBIDs(); it.valid(); it.advance()) { StringBuilder msg = new StringBuilder(); @@ -172,7 +170,7 @@ public class DiSHPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra // determine neighbors in each dimension ModifiableDBIDs[] allNeighbors = new ModifiableDBIDs[dim]; for(int d = 0; d < dim; d++) { - DistanceDBIDList<DoubleDistance> qrList = rangeQueries[d].getRangeForDBID(it, epsilon[d]); + DoubleDBIDList qrList = rangeQueries[d].getRangeForDBID(it, epsilon[d]); allNeighbors[d] = DBIDUtil.newHashSet(qrList); } @@ -184,24 +182,15 @@ public class DiSHPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra } } - try { - storage.put(it, determinePreferenceVector(relation, allNeighbors, msg)); - } - catch(UnableToComplyException e) { - throw new IllegalStateException(e); - } + storage.put(it, determinePreferenceVector(relation, allNeighbors, msg)); if(LOG.isDebugging()) { LOG.debugFine(msg.toString()); } - if(progress != null) { - progress.incrementProcessed(LOG); - } - } - if(progress != null) { - progress.ensureCompleted(LOG); + LOG.incrementProcessed(progress); } + LOG.ensureCompleted(progress); long end = System.currentTimeMillis(); // TODO: re-add timing code! @@ -218,10 +207,8 @@ public class DiSHPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra * @param neighborIDs the list of ids of the neighbors in each dimension * @param msg a string buffer for debug messages * @return the preference vector - * - * @throws de.lmu.ifi.dbs.elki.utilities.exceptions.UnableToComplyException */ - private BitSet determinePreferenceVector(Relation<V> relation, ModifiableDBIDs[] neighborIDs, StringBuilder msg) throws UnableToComplyException { + private long[] determinePreferenceVector(Relation<V> relation, ModifiableDBIDs[] neighborIDs, StringBuilder msg) { if(strategy.equals(Strategy.APRIORI)) { return determinePreferenceVectorByApriori(relation, neighborIDs, msg); } @@ -240,31 +227,25 @@ public class DiSHPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra * @param neighborIDs the list of ids of the neighbors in each dimension * @param msg a string buffer for debug messages * @return the preference vector - * - * @throws de.lmu.ifi.dbs.elki.utilities.exceptions.UnableToComplyException - * */ - private BitSet determinePreferenceVectorByApriori(Relation<V> relation, ModifiableDBIDs[] neighborIDs, StringBuilder msg) throws UnableToComplyException { + private long[] determinePreferenceVectorByApriori(Relation<V> relation, ModifiableDBIDs[] neighborIDs, StringBuilder msg) { int dimensionality = neighborIDs.length; // database for apriori UpdatableDatabase apriori_db = new HashmapDatabase(); - SimpleTypeInformation<?> bitmeta = new VectorFieldTypeInformation<>(BitVector.class, dimensionality); + SimpleTypeInformation<?> bitmeta = VectorFieldTypeInformation.typeRequest(BitVector.class, dimensionality, dimensionality); for(DBIDIter it = relation.iterDBIDs(); it.valid(); it.advance()) { - Bit[] bits = new Bit[dimensionality]; + long[] bits = BitsUtil.zero(dimensionality); boolean allFalse = true; for(int d = 0; d < dimensionality; d++) { if(neighborIDs[d].contains(it)) { - bits[d] = Bit.TRUE; + BitsUtil.setI(bits, d); allFalse = false; } - else { - bits[d] = Bit.FALSE; - } } if(!allFalse) { SingleObjectBundle oaa = new SingleObjectBundle(); - oaa.append(bitmeta, new BitVector(bits)); + oaa.append(bitmeta, new BitVector(bits, dimensionality)); apriori_db.insert(oaa); } } @@ -272,27 +253,24 @@ public class DiSHPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra AprioriResult aprioriResult = apriori.run(apriori_db); // result of apriori - List<BitSet> frequentItemsets = aprioriResult.getSolution(); - Map<BitSet, Integer> supports = aprioriResult.getSupports(); + List<Itemset> frequentItemsets = aprioriResult.getItemsets(); if(LOG.isDebugging()) { msg.append("\n Frequent itemsets: ").append(frequentItemsets); - msg.append("\n All supports: ").append(supports); } int maxSupport = 0; int maxCardinality = 0; - BitSet preferenceVector = new BitSet(); - for(BitSet bitSet : frequentItemsets) { - int cardinality = bitSet.cardinality(); - if((maxCardinality < cardinality) || (maxCardinality == cardinality && maxSupport == supports.get(bitSet))) { - preferenceVector = bitSet; - maxCardinality = cardinality; - maxSupport = supports.get(bitSet); + long[] preferenceVector = BitsUtil.zero(dimensionality); + for(Itemset itemset : frequentItemsets) { + if((maxCardinality < itemset.length()) || (maxCardinality == itemset.length() && maxSupport == itemset.getSupport())) { + preferenceVector = itemset.getItems(); + maxCardinality = itemset.length(); + maxSupport = itemset.getSupport(); } } if(LOG.isDebugging()) { msg.append("\n preference "); - msg.append(FormatUtil.format(dimensionality, preferenceVector)); + msg.append(BitsUtil.toStringLow(preferenceVector, dimensionality)); msg.append('\n'); LOG.debugFine(msg.toString()); } @@ -307,9 +285,9 @@ public class DiSHPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra * @param msg a string buffer for debug messages * @return the preference vector */ - private BitSet determinePreferenceVectorByMaxIntersection(ModifiableDBIDs[] neighborIDs, StringBuilder msg) { + private long[] determinePreferenceVectorByMaxIntersection(ModifiableDBIDs[] neighborIDs, StringBuilder msg) { int dimensionality = neighborIDs.length; - BitSet preferenceVector = new BitSet(dimensionality); + long[] preferenceVector = BitsUtil.zero(dimensionality); Map<Integer, ModifiableDBIDs> candidates = new HashMap<>(dimensionality); for(int i = 0; i < dimensionality; i++) { @@ -325,7 +303,7 @@ public class DiSHPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra if(!candidates.isEmpty()) { int i = max(candidates); ModifiableDBIDs intersection = candidates.remove(i); - preferenceVector.set(i); + BitsUtil.setI(preferenceVector, i); while(!candidates.isEmpty()) { ModifiableDBIDs newIntersection = DBIDUtil.newHashSet(); i = maxIntersection(candidates, intersection, newIntersection); @@ -338,14 +316,14 @@ public class DiSHPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra break; } else { - preferenceVector.set(i); + BitsUtil.setI(preferenceVector, i); } } } if(LOG.isDebugging()) { msg.append("\n preference "); - msg.append(FormatUtil.format(dimensionality, preferenceVector)); + msg.append(BitsUtil.toStringLow(preferenceVector, dimensionality)); msg.append('\n'); LOG.debug(msg.toString()); } @@ -405,11 +383,12 @@ public class DiSHPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra * @return the dimension selecting distancefunctions to determine the * preference vectors */ - private RangeQuery<V, DoubleDistance>[] initRangeQueries(Relation<V> relation, int dimensionality) { - Class<RangeQuery<V, DoubleDistance>> rqcls = ClassGenericsUtil.uglyCastIntoSubclass(RangeQuery.class); - RangeQuery<V, DoubleDistance>[] rangeQueries = ClassGenericsUtil.newArrayOfNull(dimensionality, rqcls); + private RangeQuery<V>[] initRangeQueries(Relation<V> relation, int dimensionality) { + Database db = relation.getDatabase(); + Class<RangeQuery<V>> rqcls = ClassGenericsUtil.uglyCastIntoSubclass(RangeQuery.class); + RangeQuery<V>[] rangeQueries = ClassGenericsUtil.newArrayOfNull(dimensionality, rqcls); for(int d = 0; d < dimensionality; d++) { - rangeQueries[d] = relation.getDatabase().getRangeQuery(new PrimitiveDistanceQuery<>(relation, new DimensionSelectingDistanceFunction(d))); + rangeQueries[d] = db.getRangeQuery(new PrimitiveDistanceQuery<>(relation, new OnedimensionalDistanceFunction(d))); } return rangeQueries; } @@ -444,11 +423,11 @@ public class DiSHPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra * * @param <V> Vector type */ - public static class Factory<V extends NumberVector<?>> extends AbstractPreferenceVectorIndex.Factory<V, DiSHPreferenceVectorIndex<V>> { + public static class Factory<V extends NumberVector> extends AbstractPreferenceVectorIndex.Factory<V, DiSHPreferenceVectorIndex<V>> { /** * The default value for epsilon. */ - public static final DoubleDistance DEFAULT_EPSILON = new DoubleDistance(0.001); + public static final double DEFAULT_EPSILON = 0.001; /** * A comma separated list of positive doubles specifying the maximum radius @@ -509,7 +488,7 @@ public class DiSHPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra /** * The epsilon value for each dimension. */ - protected DoubleDistance[] epsilon; + protected double[] epsilon; /** * Threshold for minimum number of points in the neighborhood. @@ -528,7 +507,7 @@ public class DiSHPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra * @param minpts Minpts * @param strategy Strategy */ - public Factory(DoubleDistance[] epsilon, int minpts, Strategy strategy) { + public Factory(double[] epsilon, int minpts, Strategy strategy) { super(); this.epsilon = epsilon; this.minpts = minpts; @@ -556,11 +535,11 @@ public class DiSHPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra * * @apiviz.exclude */ - public static class Parameterizer<V extends NumberVector<?>> extends AbstractParameterizer { + public static class Parameterizer<V extends NumberVector> extends AbstractParameterizer { /** * The epsilon value for each dimension. */ - protected DoubleDistance[] epsilon; + protected double[] epsilon; /** * Threshold for minimum number of points in the neighborhood. @@ -584,16 +563,16 @@ public class DiSHPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra // parameter epsilon // todo: constraint auf positive werte List<Double> defaultEps = new ArrayList<>(); - defaultEps.add(DEFAULT_EPSILON.doubleValue()); + defaultEps.add(DEFAULT_EPSILON); final DoubleListParameter epsilonP = new DoubleListParameter(EPSILON_ID, true); epsilonP.setDefaultValue(defaultEps); if(config.grab(epsilonP)) { List<Double> eps_list = epsilonP.getValue(); - epsilon = new DoubleDistance[eps_list.size()]; + epsilon = new double[eps_list.size()]; for(int d = 0; d < eps_list.size(); d++) { - epsilon[d] = new DoubleDistance(eps_list.get(d)); - if(epsilon[d].doubleValue() < 0) { + epsilon[d] = eps_list.get(d); + if(epsilon[d] < 0) { config.reportError(new WrongParameterValueException(epsilonP, eps_list.toString())); } } diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/HiSCPreferenceVectorIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/HiSCPreferenceVectorIndex.java index 8ead8458..843e4eda 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/HiSCPreferenceVectorIndex.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/HiSCPreferenceVectorIndex.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.preference; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,8 +23,6 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.preference; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import java.util.BitSet; - import de.lmu.ifi.dbs.elki.algorithm.clustering.subspace.HiSC; import de.lmu.ifi.dbs.elki.data.NumberVector; import de.lmu.ifi.dbs.elki.database.QueryUtil; @@ -34,15 +32,14 @@ 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.distance.KNNList; +import de.lmu.ifi.dbs.elki.database.ids.KNNList; import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.database.relation.RelationUtil; import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; import de.lmu.ifi.dbs.elki.logging.Logging; import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress; -import de.lmu.ifi.dbs.elki.utilities.DatabaseUtil; +import de.lmu.ifi.dbs.elki.utilities.BitsUtil; import de.lmu.ifi.dbs.elki.utilities.FormatUtil; import de.lmu.ifi.dbs.elki.utilities.documentation.Description; import de.lmu.ifi.dbs.elki.utilities.documentation.Title; @@ -66,7 +63,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter; */ @Title("HiSC Preprocessor") @Description("Computes the preference vector of objects of a certain database according to the HiSC algorithm.") -public class HiSCPreferenceVectorIndex<V extends NumberVector<?>> extends AbstractPreferenceVectorIndex<V> implements PreferenceVectorIndex<V> { +public class HiSCPreferenceVectorIndex<V extends NumberVector> extends AbstractPreferenceVectorIndex<V> implements PreferenceVectorIndex<V> { /** * Logger to use. */ @@ -101,14 +98,14 @@ public class HiSCPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra throw new IllegalArgumentException(ExceptionMessages.DATABASE_EMPTY); } - storage = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP, BitSet.class); + storage = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP, long[].class); StringBuilder msg = new StringBuilder(); long start = System.currentTimeMillis(); FiniteProgress progress = LOG.isVerbose() ? new FiniteProgress("Preprocessing preference vector", relation.size(), LOG) : null; - KNNQuery<V, DoubleDistance> knnQuery = QueryUtil.getKNNQuery(relation, EuclideanDistanceFunction.STATIC, k); + KNNQuery<V> knnQuery = QueryUtil.getKNNQuery(relation, EuclideanDistanceFunction.STATIC, k); for(DBIDIter it = relation.iterDBIDs(); it.valid(); it.advance()) { if(LOG.isDebugging()) { @@ -117,17 +114,13 @@ public class HiSCPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra msg.append("\n knns: "); } - KNNList<DoubleDistance> knns = knnQuery.getKNNForDBID(it, k); - BitSet preferenceVector = determinePreferenceVector(relation, it, knns, msg); + KNNList knns = knnQuery.getKNNForDBID(it, k); + long[] preferenceVector = determinePreferenceVector(relation, it, knns, msg); storage.put(it, preferenceVector); - if(progress != null) { - progress.incrementProcessed(LOG); - } - } - if(progress != null) { - progress.ensureCompleted(LOG); + LOG.incrementProcessed(progress); } + LOG.ensureCompleted(progress); if(LOG.isDebugging()) { LOG.debugFine(msg.toString()); @@ -151,24 +144,24 @@ public class HiSCPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra * @param msg a string buffer for debug messages * @return the preference vector */ - private BitSet determinePreferenceVector(Relation<V> relation, DBIDRef id, DBIDs neighborIDs, StringBuilder msg) { + private long[] determinePreferenceVector(Relation<V> relation, DBIDRef id, DBIDs neighborIDs, StringBuilder msg) { // variances - double[] variances = DatabaseUtil.variances(relation, relation.get(id), neighborIDs); + double[] variances = RelationUtil.variances(relation, relation.get(id), neighborIDs); // preference vector - BitSet preferenceVector = new BitSet(variances.length); + long[] preferenceVector = BitsUtil.zero(variances.length); for(int d = 0; d < variances.length; d++) { if(variances[d] < alpha) { - preferenceVector.set(d); + BitsUtil.setI(preferenceVector, d); } } if(msg != null && LOG.isDebugging()) { msg.append("\nalpha ").append(alpha); msg.append("\nvariances "); - msg.append(FormatUtil.format(variances, ", ", 4)); + msg.append(FormatUtil.format(variances, ", ", FormatUtil.NF4)); msg.append("\npreference "); - msg.append(FormatUtil.format(variances.length, preferenceVector)); + msg.append(BitsUtil.toStringLow(preferenceVector, variances.length)); } return preferenceVector; @@ -204,7 +197,7 @@ public class HiSCPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra * * @param <V> Vector type */ - public static class Factory<V extends NumberVector<?>> extends AbstractPreferenceVectorIndex.Factory<V, HiSCPreferenceVectorIndex<V>> { + public static class Factory<V extends NumberVector> extends AbstractPreferenceVectorIndex.Factory<V, HiSCPreferenceVectorIndex<V>> { /** * The default value for alpha. */ @@ -276,7 +269,7 @@ public class HiSCPreferenceVectorIndex<V extends NumberVector<?>> extends Abstra * * @apiviz.exclude */ - public static class Parameterizer<V extends NumberVector<?>> extends AbstractParameterizer { + public static class Parameterizer<V extends NumberVector> extends AbstractParameterizer { /** * Holds the value of parameter {@link #ALPHA_ID}. */ diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/PreferenceVectorIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/PreferenceVectorIndex.java index 87a9d3dd..45d88dd5 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/PreferenceVectorIndex.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/PreferenceVectorIndex.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.preference; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,8 +23,6 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.preference; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import java.util.BitSet; - import de.lmu.ifi.dbs.elki.data.NumberVector; import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; import de.lmu.ifi.dbs.elki.database.relation.Relation; @@ -38,14 +36,14 @@ import de.lmu.ifi.dbs.elki.index.IndexFactory; * * @param <NV> Vector type */ -public interface PreferenceVectorIndex<NV extends NumberVector<?>> extends Index { +public interface PreferenceVectorIndex<NV extends NumberVector> extends Index { /** * Get the precomputed preference vector for a particular object ID. * * @param id Object ID * @return Matrix */ - public BitSet getPreferenceVector(DBIDRef id); + public long[] getPreferenceVector(DBIDRef id); /** * Factory interface @@ -58,7 +56,7 @@ public interface PreferenceVectorIndex<NV extends NumberVector<?>> extends Index * @param <V> vector type * @param <I> index type */ - public static interface Factory<V extends NumberVector<?>, I extends PreferenceVectorIndex<V>> extends IndexFactory<V, I> { + public static interface Factory<V extends NumberVector, I extends PreferenceVectorIndex<V>> extends IndexFactory<V, I> { /** * Instantiate the index for a given database. * diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/package-info.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/package-info.java index e840bfd0..f912afb7 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/preference/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2013 +Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/snn/SharedNearestNeighborIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/snn/SharedNearestNeighborIndex.java index cdb1d0bb..89089847 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/snn/SharedNearestNeighborIndex.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/snn/SharedNearestNeighborIndex.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.snn; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/snn/SharedNearestNeighborPreprocessor.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/snn/SharedNearestNeighborPreprocessor.java index 650e2169..a327abf7 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/snn/SharedNearestNeighborPreprocessor.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/snn/SharedNearestNeighborPreprocessor.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.preprocessed.snn; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -32,12 +32,11 @@ import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs; import de.lmu.ifi.dbs.elki.database.ids.DBIDIter; import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList; +import de.lmu.ifi.dbs.elki.database.ids.DBIDs; import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; import de.lmu.ifi.dbs.elki.index.preprocessed.AbstractPreprocessorIndex; import de.lmu.ifi.dbs.elki.index.preprocessed.knn.MaterializeKNNPreprocessor; import de.lmu.ifi.dbs.elki.logging.Logging; @@ -46,7 +45,6 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Description; import de.lmu.ifi.dbs.elki.utilities.documentation.Title; import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer; import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable; import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.CommonConstraints; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization; import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter; @@ -69,11 +67,10 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter; * @apiviz.has DistanceFunction * * @param <O> the type of database objects the preprocessor can be applied to - * @param <D> the type of distance the used distance function will return */ @Title("Shared nearest neighbor Preprocessor") @Description("Computes the k nearest neighbors of objects of a certain database.") -public class SharedNearestNeighborPreprocessor<O, D extends Distance<D>> extends AbstractPreprocessorIndex<O, ArrayDBIDs> implements SharedNearestNeighborIndex<O> { +public class SharedNearestNeighborPreprocessor<O> extends AbstractPreprocessorIndex<O, ArrayDBIDs> implements SharedNearestNeighborIndex<O> { /** * Get a logger for this class. */ @@ -87,7 +84,7 @@ public class SharedNearestNeighborPreprocessor<O, D extends Distance<D>> extends /** * Hold the distance function to be used. */ - protected DistanceFunction<O, D> distanceFunction; + protected DistanceFunction<O> distanceFunction; /** * Constructor. @@ -96,7 +93,7 @@ public class SharedNearestNeighborPreprocessor<O, D extends Distance<D>> extends * @param numberOfNeighbors Number of neighbors * @param distanceFunction Distance function */ - public SharedNearestNeighborPreprocessor(Relation<O> relation, int numberOfNeighbors, DistanceFunction<O, D> distanceFunction) { + public SharedNearestNeighborPreprocessor(Relation<O> relation, int numberOfNeighbors, DistanceFunction<O> distanceFunction) { super(relation); this.numberOfNeighbors = numberOfNeighbors; this.distanceFunction = distanceFunction; @@ -108,12 +105,12 @@ public class SharedNearestNeighborPreprocessor<O, D extends Distance<D>> extends getLogger().verbose("Assigning nearest neighbor lists to database objects"); } storage = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP, ArrayDBIDs.class); - KNNQuery<O, D> knnquery = QueryUtil.getKNNQuery(relation, distanceFunction, numberOfNeighbors); + KNNQuery<O> knnquery = QueryUtil.getKNNQuery(relation, distanceFunction, numberOfNeighbors); FiniteProgress progress = getLogger().isVerbose() ? new FiniteProgress("assigning nearest neighbor lists", relation.size(), getLogger()) : null; for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) { ArrayModifiableDBIDs neighbors = DBIDUtil.newArray(numberOfNeighbors); - KNNList<D> kNN = knnquery.getKNNForDBID(iditer, numberOfNeighbors); + DBIDs kNN = knnquery.getKNNForDBID(iditer, numberOfNeighbors); for(DBIDIter iter = kNN.iter(); iter.valid(); iter.advance()) { // if(!id.equals(nid)) { neighbors.add(iter); @@ -125,13 +122,9 @@ public class SharedNearestNeighborPreprocessor<O, D extends Distance<D>> extends } neighbors.sort(); storage.put(iditer, neighbors); - if(progress != null) { - progress.incrementProcessed(getLogger()); - } - } - if(progress != null) { - progress.ensureCompleted(getLogger()); + getLogger().incrementProcessed(progress); } + getLogger().ensureCompleted(progress); } @Override @@ -180,7 +173,7 @@ public class SharedNearestNeighborPreprocessor<O, D extends Distance<D>> extends * @apiviz.stereotype factory * @apiviz.uses SharedNearestNeighborPreprocessor oneway - - «create» */ - public static class Factory<O, D extends Distance<D>> implements SharedNearestNeighborIndex.Factory<O, SharedNearestNeighborPreprocessor<O, D>>, Parameterizable { + public static class Factory<O> implements SharedNearestNeighborIndex.Factory<O, SharedNearestNeighborPreprocessor<O>> { /** * Parameter to indicate the number of neighbors to be taken into account * for the shared-nearest-neighbor similarity. @@ -215,7 +208,7 @@ public class SharedNearestNeighborPreprocessor<O, D extends Distance<D>> extends /** * Hold the distance function to be used. */ - protected DistanceFunction<O, D> distanceFunction; + protected DistanceFunction<O> distanceFunction; /** * Constructor. @@ -223,14 +216,14 @@ public class SharedNearestNeighborPreprocessor<O, D extends Distance<D>> extends * @param numberOfNeighbors Number of neighbors * @param distanceFunction Distance function */ - public Factory(int numberOfNeighbors, DistanceFunction<O, D> distanceFunction) { + public Factory(int numberOfNeighbors, DistanceFunction<O> distanceFunction) { super(); this.numberOfNeighbors = numberOfNeighbors; this.distanceFunction = distanceFunction; } @Override - public SharedNearestNeighborPreprocessor<O, D> instantiate(Relation<O> relation) { + public SharedNearestNeighborPreprocessor<O> instantiate(Relation<O> relation) { return new SharedNearestNeighborPreprocessor<>(relation, numberOfNeighbors, distanceFunction); } @@ -256,7 +249,7 @@ public class SharedNearestNeighborPreprocessor<O, D extends Distance<D>> extends * * @apiviz.exclude */ - public static class Parameterizer<O, D extends Distance<D>> extends AbstractParameterizer { + public static class Parameterizer<O> extends AbstractParameterizer { /** * Holds the number of nearest neighbors to be used. */ @@ -265,7 +258,7 @@ public class SharedNearestNeighborPreprocessor<O, D extends Distance<D>> extends /** * Hold the distance function to be used. */ - protected DistanceFunction<O, D> distanceFunction; + protected DistanceFunction<O> distanceFunction; @Override protected void makeOptions(Parameterization config) { @@ -276,14 +269,14 @@ public class SharedNearestNeighborPreprocessor<O, D extends Distance<D>> extends numberOfNeighbors = numberOfNeighborsP.getValue(); } - final ObjectParameter<DistanceFunction<O, D>> distanceFunctionP = new ObjectParameter<>(DISTANCE_FUNCTION_ID, DistanceFunction.class, EuclideanDistanceFunction.class); + final ObjectParameter<DistanceFunction<O>> distanceFunctionP = new ObjectParameter<>(DISTANCE_FUNCTION_ID, DistanceFunction.class, EuclideanDistanceFunction.class); if(config.grab(distanceFunctionP)) { distanceFunction = distanceFunctionP.instantiateClass(config); } } @Override - protected Factory<O, D> makeInstance() { + protected Factory<O> makeInstance() { return new Factory<>(numberOfNeighbors, distanceFunction); } } diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/snn/package-info.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/snn/package-info.java index 5612f655..8c81623c 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/snn/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/preprocessed/snn/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2013 +Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/AbstractSubspaceProjectionIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/AbstractSubspaceProjectionIndex.java deleted file mode 100644 index a219444e..00000000 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/AbstractSubspaceProjectionIndex.java +++ /dev/null @@ -1,272 +0,0 @@ -package de.lmu.ifi.dbs.elki.index.preprocessed.subspaceproj; - -/* - This file is part of ELKI: - Environment for Developing KDD-Applications Supported by Index-Structures - - Copyright (C) 2013 - Ludwig-Maximilians-Universität München - Lehr- und Forschungseinheit für Datenbanksysteme - ELKI Development Team - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -import de.lmu.ifi.dbs.elki.algorithm.clustering.AbstractProjectedDBSCAN; -import de.lmu.ifi.dbs.elki.data.NumberVector; -import de.lmu.ifi.dbs.elki.data.type.TypeInformation; -import de.lmu.ifi.dbs.elki.data.type.TypeUtil; -import de.lmu.ifi.dbs.elki.database.QueryUtil; -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.ids.DBIDIter; -import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; -import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList; -import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDPair; -import de.lmu.ifi.dbs.elki.database.ids.generic.GenericDistanceDBIDList; -import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery; -import de.lmu.ifi.dbs.elki.database.relation.Relation; -import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; -import de.lmu.ifi.dbs.elki.index.preprocessed.AbstractPreprocessorIndex; -import de.lmu.ifi.dbs.elki.logging.progress.FiniteProgress; -import de.lmu.ifi.dbs.elki.math.linearalgebra.ProjectionResult; -import de.lmu.ifi.dbs.elki.utilities.documentation.Description; -import de.lmu.ifi.dbs.elki.utilities.documentation.Title; -import de.lmu.ifi.dbs.elki.utilities.exceptions.ExceptionMessages; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.CommonConstraints; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DistanceParameter; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter; - -/** - * Abstract base class for a local PCA based index. - * - * @author Elke Achtert - * @author Erich Schubert - * - * @apiviz.has DistanceFunction - * - * @param <NV> Vector type - */ -@Title("Local PCA Preprocessor") -@Description("Materializes the local PCA and the locally weighted matrix of objects of a database.") -public abstract class AbstractSubspaceProjectionIndex<NV extends NumberVector<?>, D extends Distance<D>, P extends ProjectionResult> extends AbstractPreprocessorIndex<NV, P> implements SubspaceProjectionIndex<NV, P> { - /** - * Contains the value of parameter epsilon; - */ - protected D epsilon; - - /** - * The distance function for the variance analysis. - */ - protected DistanceFunction<NV, D> rangeQueryDistanceFunction; - - /** - * Holds the value of parameter minpts. - */ - protected int minpts; - - /** - * Constructor. - * - * @param relation Relation - * @param epsilon Maximum Epsilon - * @param rangeQueryDistanceFunction range query - * @param minpts Minpts - */ - public AbstractSubspaceProjectionIndex(Relation<NV> relation, D epsilon, DistanceFunction<NV, D> rangeQueryDistanceFunction, int minpts) { - super(relation); - this.epsilon = epsilon; - this.rangeQueryDistanceFunction = rangeQueryDistanceFunction; - this.minpts = minpts; - } - - @Override - public void initialize() { - if(relation == null || relation.size() <= 0) { - throw new IllegalArgumentException(ExceptionMessages.DATABASE_EMPTY); - } - if(storage != null) { - // Preprocessor was already run. - return; - } - storage = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP, ProjectionResult.class); - - long start = System.currentTimeMillis(); - RangeQuery<NV, D> rangeQuery = QueryUtil.getRangeQuery(relation, rangeQueryDistanceFunction); - - FiniteProgress progress = getLogger().isVerbose() ? new FiniteProgress(this.getClass().getName(), relation.size(), getLogger()) : null; - for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) { - DistanceDBIDList<D> neighbors = rangeQuery.getRangeForDBID(iditer, epsilon); - - final P pres; - if(neighbors.size() >= minpts) { - pres = computeProjection(iditer, neighbors, relation); - } - else { - DistanceDBIDPair<D> firstQR = neighbors.iter().getDistancePair(); - GenericDistanceDBIDList<D> newne = new GenericDistanceDBIDList<>(); - newne.add(firstQR); - pres = computeProjection(iditer, newne, relation); - } - storage.put(iditer, pres); - - if(progress != null) { - progress.incrementProcessed(getLogger()); - } - } - if(progress != null) { - progress.ensureCompleted(getLogger()); - } - - long end = System.currentTimeMillis(); - // TODO: re-add timing code! - if(true) { - long elapsedTime = end - start; - getLogger().verbose(this.getClass().getName() + " runtime: " + elapsedTime + " milliseconds."); - } - } - - @Override - public P getLocalProjection(DBIDRef objid) { - if(storage == null) { - initialize(); - } - return storage.get(objid); - } - - /** - * This method implements the type of variance analysis to be computed for a - * given point. - * <p/> - * Example1: for 4C, this method should implement a PCA for the given point. - * Example2: for PreDeCon, this method should implement a simple axis-parallel - * variance analysis. - * - * @param id the given point - * @param neighbors the neighbors as query results of the given point - * @param relation the database for which the preprocessing is performed - * - * @return local subspace projection - */ - protected abstract P computeProjection(DBIDRef id, DistanceDBIDList<D> neighbors, Relation<NV> relation); - - /** - * Factory class - * - * @author Erich Schubert - * - * @apiviz.stereotype factory - * @apiviz.uses AbstractSubspaceProjectionIndex oneway - - «create» - */ - public abstract static class Factory<NV extends NumberVector<?>, D extends Distance<D>, I extends AbstractSubspaceProjectionIndex<NV, D, ?>> implements SubspaceProjectionIndex.Factory<NV, I>, Parameterizable { - /** - * Contains the value of parameter epsilon; - */ - protected D epsilon; - - /** - * The distance function for the variance analysis. - */ - protected DistanceFunction<NV, D> rangeQueryDistanceFunction; - - /** - * Holds the value of parameter minpts. - */ - protected int minpts; - - /** - * Constructor. - * - * @param epsilon - * @param rangeQueryDistanceFunction - * @param minpts - */ - public Factory(D epsilon, DistanceFunction<NV, D> rangeQueryDistanceFunction, int minpts) { - super(); - this.epsilon = epsilon; - this.rangeQueryDistanceFunction = rangeQueryDistanceFunction; - this.minpts = minpts; - } - - @Override - public abstract I instantiate(Relation<NV> relation); - - @Override - public TypeInformation getInputTypeRestriction() { - return TypeUtil.NUMBER_VECTOR_FIELD; - } - - /** - * Parameterization class. - * - * @author Erich Schubert - * - * @apiviz.exclude - */ - public abstract static class Parameterizer<NV extends NumberVector<?>, D extends Distance<D>, C> extends AbstractParameterizer { - /** - * Contains the value of parameter epsilon; - */ - protected D epsilon = null; - - /** - * The distance function for the variance analysis. - */ - protected DistanceFunction<NV, D> rangeQueryDistanceFunction = null; - - /** - * Holds the value of parameter minpts. - */ - protected int minpts = 0; - - @Override - protected void makeOptions(Parameterization config) { - super.makeOptions(config); - configRangeQueryDistanceFunction(config); - configEpsilon(config, rangeQueryDistanceFunction); - configMinPts(config); - } - - protected void configRangeQueryDistanceFunction(Parameterization config) { - ObjectParameter<DistanceFunction<NV, D>> rangeQueryDistanceP = new ObjectParameter<>(AbstractProjectedDBSCAN.INNER_DISTANCE_FUNCTION_ID, DistanceFunction.class, EuclideanDistanceFunction.class); - if(config.grab(rangeQueryDistanceP)) { - rangeQueryDistanceFunction = rangeQueryDistanceP.instantiateClass(config); - } - } - - protected void configEpsilon(Parameterization config, DistanceFunction<NV, D> rangeQueryDistanceFunction) { - D distanceParser = rangeQueryDistanceFunction != null ? rangeQueryDistanceFunction.getDistanceFactory() : null; - DistanceParameter<D> epsilonP = new DistanceParameter<>(AbstractProjectedDBSCAN.EPSILON_ID, distanceParser); - // parameter epsilon - if(config.grab(epsilonP)) { - epsilon = epsilonP.getValue(); - } - } - - protected void configMinPts(Parameterization config) { - IntParameter minptsP = new IntParameter(AbstractProjectedDBSCAN.MINPTS_ID); - minptsP.addConstraint(CommonConstraints.GREATER_EQUAL_ONE_INT); - if(config.grab(minptsP)) { - minpts = minptsP.intValue(); - } - } - } - } -}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/FourCSubspaceIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/FourCSubspaceIndex.java deleted file mode 100644 index 35aaa40c..00000000 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/FourCSubspaceIndex.java +++ /dev/null @@ -1,260 +0,0 @@ -package de.lmu.ifi.dbs.elki.index.preprocessed.subspaceproj; - -/* - This file is part of ELKI: - Environment for Developing KDD-Applications Supported by Index-Structures - - Copyright (C) 2013 - Ludwig-Maximilians-Universität München - Lehr- und Forschungseinheit für Datenbanksysteme - ELKI Development Team - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -import java.util.ArrayList; - -import de.lmu.ifi.dbs.elki.data.NumberVector; -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.ModifiableDBIDs; -import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList; -import de.lmu.ifi.dbs.elki.database.relation.Relation; -import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; -import de.lmu.ifi.dbs.elki.logging.Logging; -import de.lmu.ifi.dbs.elki.logging.LoggingUtil; -import de.lmu.ifi.dbs.elki.math.linearalgebra.pca.LimitEigenPairFilter; -import de.lmu.ifi.dbs.elki.math.linearalgebra.pca.PCAFilteredResult; -import de.lmu.ifi.dbs.elki.math.linearalgebra.pca.PCAFilteredRunner; -import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil; -import de.lmu.ifi.dbs.elki.utilities.documentation.Description; -import de.lmu.ifi.dbs.elki.utilities.documentation.Title; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.ParameterException; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.WrongParameterValueException; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.CommonConstraints; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.GlobalParameterConstraint; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.ParameterConstraint; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.ParameterFlagGlobalConstraint; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.ListParameterization; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleParameter; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.Flag; - -/** - * Preprocessor for 4C local dimensionality and locally weighted matrix - * assignment to objects of a certain database. - * - * @author Arthur Zimek - * - * @apiviz.composedOf PCAFilteredRunner - * - * @param <V> Vector type - * @param <D> Distance type - */ -@Title("4C Preprocessor") -@Description("Computes the local dimensionality and locally weighted matrix of objects of a certain database according to the 4C algorithm.\n" + "The PCA is based on epsilon range queries.") -public class FourCSubspaceIndex<V extends NumberVector<?>, D extends Distance<D>> extends AbstractSubspaceProjectionIndex<V, D, PCAFilteredResult> { - /** - * Our logger - */ - private static final Logging LOG = Logging.getLogger(FourCSubspaceIndex.class); - - /** - * The Filtered PCA Runner - */ - private PCAFilteredRunner<V> pca; - - /** - * Full constructor. - * - * @param relation Relation - * @param epsilon Epsilon value - * @param rangeQueryDistanceFunction - * @param minpts MinPts value - * @param pca PCA runner - */ - public FourCSubspaceIndex(Relation<V> relation, D epsilon, DistanceFunction<V, D> rangeQueryDistanceFunction, int minpts, PCAFilteredRunner<V> pca) { - super(relation, epsilon, rangeQueryDistanceFunction, minpts); - this.pca = pca; - } - - @Override - protected PCAFilteredResult computeProjection(DBIDRef id, DistanceDBIDList<D> neighbors, Relation<V> database) { - ModifiableDBIDs ids = DBIDUtil.newArray(neighbors.size()); - for(DBIDIter neighbor = neighbors.iter(); neighbor.valid(); neighbor.advance()) { - ids.add(neighbor); - } - PCAFilteredResult pcares = pca.processIds(ids, database); - - if(LOG.isDebugging()) { - StringBuilder msg = new StringBuilder(); - msg.append(id).append(' '); // .append(database.getObjectLabelQuery().get(id)); - msg.append("\ncorrDim ").append(pcares.getCorrelationDimension()); - LOG.debugFine(msg.toString()); - } - return pcares; - } - - @Override - protected Logging getLogger() { - return LOG; - } - - @Override - public String getLongName() { - return "4C local Subspaces"; - } - - @Override - public String getShortName() { - return "4C-subspaces"; - } - - @Override - public void logStatistics() { - // No statistics to log. - } - - /** - * Factory class for 4C preprocessors. - * - * @author Erich Schubert - * - * @apiviz.stereotype factory - * @apiviz.uses FourCSubspaceIndex oneway - - «creates» - * - * @param <V> Vector type - * @param <D> Distance type - */ - public static class Factory<V extends NumberVector<?>, D extends Distance<D>> extends AbstractSubspaceProjectionIndex.Factory<V, D, FourCSubspaceIndex<V, D>> { - /** - * The default value for delta. - */ - public static final double DEFAULT_DELTA = LimitEigenPairFilter.DEFAULT_DELTA; - - /** - * The Filtered PCA Runner - */ - private PCAFilteredRunner<V> pca; - - /** - * Constructor. - * - * @param epsilon - * @param rangeQueryDistanceFunction - * @param minpts - * @param pca - */ - public Factory(D epsilon, DistanceFunction<V, D> rangeQueryDistanceFunction, int minpts, PCAFilteredRunner<V> pca) { - super(epsilon, rangeQueryDistanceFunction, minpts); - this.pca = pca; - } - - @Override - public FourCSubspaceIndex<V, D> instantiate(Relation<V> relation) { - return new FourCSubspaceIndex<>(relation, epsilon, rangeQueryDistanceFunction, minpts, pca); - } - - /** - * Parameterization class. - * - * @author Erich Schubert - * - * @apiviz.exclude - */ - public static class Parameterizer<V extends NumberVector<?>, D extends Distance<D>> extends AbstractSubspaceProjectionIndex.Factory.Parameterizer<V, D, Factory<V, D>> { - /** - * The Filtered PCA Runner - */ - private PCAFilteredRunner<V> pca; - - @Override - protected void makeOptions(Parameterization config) { - super.makeOptions(config); - // flag absolute - boolean absolute = false; - Flag absoluteF = new Flag(LimitEigenPairFilter.EIGENPAIR_FILTER_ABSOLUTE); - if(config.grab(absoluteF)) { - absolute = absoluteF.isTrue(); - } - - // Parameter delta - double delta = 0.0; - DoubleParameter deltaP = new DoubleParameter(LimitEigenPairFilter.EIGENPAIR_FILTER_DELTA, DEFAULT_DELTA); - deltaP.addConstraint(CommonConstraints.GREATER_EQUAL_ZERO_DOUBLE); - if(config.grab(deltaP)) { - delta = deltaP.doubleValue(); - } - // Absolute flag doesn't have a sensible default value for delta. - if(absolute && deltaP.tookDefaultValue()) { - config.reportError(new WrongParameterValueException("Illegal parameter setting: " + "Flag " + absoluteF.getName() + " is set, " + "but no value for " + deltaP.getName() + " is specified.")); - } - - // if (optionHandler.isSet(DELTA_P)) { - // delta = (Double) optionHandler.getOptionValue(DELTA_P); - // try { - // if (!absolute && delta < 0 || delta > 1) - // throw new WrongParameterValueException(DELTA_P, "delta", DELTA_D); - // } catch (NumberFormatException e) { - // throw new WrongParameterValueException(DELTA_P, "delta", DELTA_D, e); - // } - // } else if (!absolute) { - // delta = LimitEigenPairFilter.DEFAULT_DELTA; - // } else { - // throw new WrongParameterValueException("Illegal parameter setting: " - // + - // "Flag " + ABSOLUTE_F + " is set, " + "but no value for " + DELTA_P + - // " is specified."); - // } - - // Parameterize PCA - ListParameterization pcaParameters = new ListParameterization(); - // eigen pair filter - pcaParameters.addParameter(PCAFilteredRunner.PCA_EIGENPAIR_FILTER, LimitEigenPairFilter.class.getName()); - // abs - if(absolute) { - pcaParameters.addFlag(LimitEigenPairFilter.EIGENPAIR_FILTER_ABSOLUTE); - } - // delta - pcaParameters.addParameter(LimitEigenPairFilter.EIGENPAIR_FILTER_DELTA, delta); - // big value - pcaParameters.addParameter(PCAFilteredRunner.BIG_ID, 50); - // small value - pcaParameters.addParameter(PCAFilteredRunner.SMALL_ID, 1); - Class<PCAFilteredRunner<V>> cls = ClassGenericsUtil.uglyCastIntoSubclass(PCAFilteredRunner.class); - pca = pcaParameters.tryInstantiate(cls); - for(ParameterException e : pcaParameters.getErrors()) { - LoggingUtil.warning("Error in internal parameterization: " + e.getMessage()); - } - - final ArrayList<ParameterConstraint<? super Double>> deltaCons = new ArrayList<>(); - // TODO: this constraint is already set in the parameter itself, since - // it - // also applies to the relative case, right? -- erich - // deltaCons.add(CommonConstraints.NONNEGATIVE_DOUBLE); - deltaCons.add(CommonConstraints.LESS_EQUAL_ONE_DOUBLE); - - GlobalParameterConstraint gpc = new ParameterFlagGlobalConstraint<>(deltaP, deltaCons, absoluteF, false); - config.checkConstraint(gpc); - } - - @Override - protected Factory<V, D> makeInstance() { - return new Factory<>(epsilon, rangeQueryDistanceFunction, minpts, pca); - } - } - } -} diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/PreDeConSubspaceIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/PreDeConSubspaceIndex.java deleted file mode 100644 index ca322224..00000000 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/PreDeConSubspaceIndex.java +++ /dev/null @@ -1,254 +0,0 @@ -package de.lmu.ifi.dbs.elki.index.preprocessed.subspaceproj; - -/* - This file is part of ELKI: - Environment for Developing KDD-Applications Supported by Index-Structures - - Copyright (C) 2013 - Ludwig-Maximilians-Universität München - Lehr- und Forschungseinheit für Datenbanksysteme - ELKI Development Team - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -import de.lmu.ifi.dbs.elki.data.NumberVector; -import de.lmu.ifi.dbs.elki.database.ids.DBIDIter; -import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; -import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList; -import de.lmu.ifi.dbs.elki.database.relation.Relation; -import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; -import de.lmu.ifi.dbs.elki.logging.Logging; -import de.lmu.ifi.dbs.elki.math.linearalgebra.Matrix; -import de.lmu.ifi.dbs.elki.math.linearalgebra.SubspaceProjectionResult; -import de.lmu.ifi.dbs.elki.utilities.FormatUtil; -import de.lmu.ifi.dbs.elki.utilities.documentation.Description; -import de.lmu.ifi.dbs.elki.utilities.documentation.Title; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.CommonConstraints; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.DoubleParameter; - -/** - * Preprocessor for PreDeCon local dimensionality and locally weighted matrix - * assignment to objects of a certain database. - * - * @author Peer Kröger - * - * @apiviz.has SubspaceProjectionResult - * - * @param <D> Distance type - * @param <V> Vector type - */ -@Title("PreDeCon Preprocessor") -@Description("Computes the projected dimension of objects of a certain database according to the PreDeCon algorithm.\n" + "The variance analysis is based on epsilon range queries.") -public class PreDeConSubspaceIndex<V extends NumberVector<?>, D extends Distance<D>> extends AbstractSubspaceProjectionIndex<V, D, SubspaceProjectionResult> { - /** - * The logger for this class. - */ - private static final Logging LOG = Logging.getLogger(PreDeConSubspaceIndex.class); - - /** - * The threshold for small eigenvalues. - */ - protected double delta; - - /** - * The kappa value for generating the variance vector. - */ - private final int kappa = 50; - - /** - * Constructor. - * - * @param relation Relation - * @param epsilon Epsilon value - * @param rangeQueryDistanceFunction range query distance - * @param minpts Minpts parameter - * @param delta Delta value - */ - public PreDeConSubspaceIndex(Relation<V> relation, D epsilon, DistanceFunction<V, D> rangeQueryDistanceFunction, int minpts, double delta) { - super(relation, epsilon, rangeQueryDistanceFunction, minpts); - this.delta = delta; - } - - @Override - protected SubspaceProjectionResult computeProjection(DBIDRef id, DistanceDBIDList<D> neighbors, Relation<V> database) { - StringBuilder msg = null; - - int referenceSetSize = neighbors.size(); - V obj = database.get(id); - - if(getLogger().isDebugging()) { - msg = new StringBuilder(); - msg.append("referenceSetSize = ").append(referenceSetSize); - msg.append("\ndelta = ").append(delta); - } - - if(referenceSetSize == 0) { - throw new RuntimeException("Reference Set Size = 0. This should never happen!"); - } - - // prepare similarity matrix - int dim = obj.getDimensionality(); - Matrix simMatrix = new Matrix(dim, dim, 0); - for(int i = 0; i < dim; i++) { - simMatrix.set(i, i, 1); - } - - // prepare projected dimensionality - int projDim = 0; - - // start variance analysis - double[] sum = new double[dim]; - for(DBIDIter neighbor = neighbors.iter(); neighbor.valid(); neighbor.advance()) { - V o = database.get(neighbor); - for(int d = 0; d < dim; d++) { - final double diff = obj.doubleValue(d) - o.doubleValue(d); - sum[d] += diff * diff; - } - } - - for(int d = 0; d < dim; d++) { - if(Math.sqrt(sum[d]) / referenceSetSize <= delta) { - if(msg != null) { - msg.append("\nsum[").append(d).append("]= ").append(sum[d]); - msg.append("\n Math.sqrt(sum[d]) / referenceSetSize)= ").append(Math.sqrt(sum[d]) / referenceSetSize); - } - // projDim++; - simMatrix.set(d, d, kappa); - } - else { - // bug in paper? - projDim++; - } - } - - if(projDim == 0) { - if(msg != null) { - // msg.append("\nprojDim == 0!"); - } - projDim = dim; - } - - if(msg != null) { - msg.append("\nprojDim "); - // .append(database.getObjectLabelQuery().get(id)); - msg.append(": ").append(projDim); - msg.append("\nsimMatrix "); - // .append(database.getObjectLabelQuery().get(id)); - msg.append(": ").append(FormatUtil.format(simMatrix, FormatUtil.NF4)); - getLogger().debugFine(msg.toString()); - } - - return new SubspaceProjectionResult(projDim, simMatrix); - } - - @Override - public String getLongName() { - return "PreDeCon Subspaces"; - } - - @Override - public String getShortName() { - return "PreDeCon-subsp"; - } - - @Override - protected Logging getLogger() { - return LOG; - } - - @Override - public void logStatistics() { - // No statistics to log. - } - - /** - * Factory. - * - * @author Erich Schubert - * - * @apiviz.stereotype factory - * @apiviz.uses PreDeConSubspaceIndex oneway - - «creates» - * - * @param <V> Vector type - * @param <D> Distance type - */ - public static class Factory<V extends NumberVector<?>, D extends Distance<D>> extends AbstractSubspaceProjectionIndex.Factory<V, D, PreDeConSubspaceIndex<V, D>> { - /** - * The default value for delta. - */ - public static final double DEFAULT_DELTA = 0.01; - - /** - * Parameter for Delta. - */ - public static final OptionID DELTA_ID = new OptionID("predecon.delta", "a double between 0 and 1 specifying the threshold for small Eigenvalues (default is delta = " + DEFAULT_DELTA + ")."); - - /** - * The threshold for small eigenvalues. - */ - protected double delta; - - /** - * Constructor. - * - * @param epsilon - * @param rangeQueryDistanceFunction - * @param minpts - * @param delta - */ - public Factory(D epsilon, DistanceFunction<V, D> rangeQueryDistanceFunction, int minpts, double delta) { - super(epsilon, rangeQueryDistanceFunction, minpts); - this.delta = delta; - } - - @Override - public PreDeConSubspaceIndex<V, D> instantiate(Relation<V> relation) { - return new PreDeConSubspaceIndex<>(relation, epsilon, rangeQueryDistanceFunction, minpts, delta); - } - - /** - * Parameterization class. - * - * @author Erich Schubert - * - * @apiviz.exclude - */ - public static class Parameterizer<V extends NumberVector<?>, D extends Distance<D>> extends AbstractSubspaceProjectionIndex.Factory.Parameterizer<V, D, Factory<V, D>> { - /** - * The threshold for small eigenvalues. - */ - protected double delta; - - @Override - protected void makeOptions(Parameterization config) { - super.makeOptions(config); - DoubleParameter deltaP = new DoubleParameter(DELTA_ID, DEFAULT_DELTA); - deltaP.addConstraint(CommonConstraints.GREATER_THAN_ZERO_DOUBLE); - deltaP.addConstraint(CommonConstraints.LESS_THAN_ONE_DOUBLE); - if(config.grab(deltaP)) { - delta = deltaP.doubleValue(); - } - } - - @Override - protected Factory<V, D> makeInstance() { - return new Factory<>(epsilon, rangeQueryDistanceFunction, minpts, delta); - } - } - } -} diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/SubspaceProjectionIndex.java b/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/SubspaceProjectionIndex.java deleted file mode 100644 index f0fbbd35..00000000 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/SubspaceProjectionIndex.java +++ /dev/null @@ -1,74 +0,0 @@ -package de.lmu.ifi.dbs.elki.index.preprocessed.subspaceproj; - -/* - This file is part of ELKI: - Environment for Developing KDD-Applications Supported by Index-Structures - - Copyright (C) 2013 - Ludwig-Maximilians-Universität München - Lehr- und Forschungseinheit für Datenbanksysteme - ELKI Development Team - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -import de.lmu.ifi.dbs.elki.data.NumberVector; -import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; -import de.lmu.ifi.dbs.elki.database.relation.Relation; -import de.lmu.ifi.dbs.elki.index.preprocessed.LocalProjectionIndex; -import de.lmu.ifi.dbs.elki.math.linearalgebra.ProjectionResult; - -/** - * Interface for an index providing local subspaces. - * - * @author Erich Schubert - * - * @apiviz.landmark - * - * @param <NV> Vector type - */ -public interface SubspaceProjectionIndex<NV extends NumberVector<?>, P extends ProjectionResult> extends LocalProjectionIndex<NV, P> { - /** - * Get the precomputed local subspace for a particular object ID. - * - * @param objid Object ID - * @return Matrix - */ - @Override - public P getLocalProjection(DBIDRef objid); - - /** - * Factory interface - * - * @author Erich Schubert - * - * @apiviz.landmark - * @apiviz.stereotype factory - * @apiviz.uses SubspaceProjectionIndex oneway - - «create» - * - * @param <NV> Vector type - * @param <I> Index type produced - */ - public static interface Factory<NV extends NumberVector<?>, I extends SubspaceProjectionIndex<NV, ?>> extends LocalProjectionIndex.Factory<NV, I> { - /** - * Instantiate the index for a given database. - * - * @param relation Relation - * - * @return Index - */ - @Override - public I instantiate(Relation<NV> relation); - } -}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/projected/LatLngAsECEFIndex.java b/src/de/lmu/ifi/dbs/elki/index/projected/LatLngAsECEFIndex.java index 8449996b..efa88eb0 100644 --- a/src/de/lmu/ifi/dbs/elki/index/projected/LatLngAsECEFIndex.java +++ b/src/de/lmu/ifi/dbs/elki/index/projected/LatLngAsECEFIndex.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.projected; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -42,8 +42,6 @@ import de.lmu.ifi.dbs.elki.database.relation.ProjectedView; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.distance.distancefunction.geo.LatLngDistanceFunction; import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; -import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; import de.lmu.ifi.dbs.elki.index.Index; import de.lmu.ifi.dbs.elki.index.IndexFactory; import de.lmu.ifi.dbs.elki.index.KNNIndex; @@ -77,9 +75,11 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter; * * @author Erich Schubert * + * @apiviz.composedOf LatLngToECEFProjection + * * @param <O> Object type */ -public class LatLngAsECEFIndex<O extends NumberVector<?>> extends ProjectedIndex<O, O> { +public class LatLngAsECEFIndex<O extends NumberVector> extends ProjectedIndex<O, O> { /** * Constructor. * @@ -105,77 +105,77 @@ public class LatLngAsECEFIndex<O extends NumberVector<?>> extends ProjectedIndex @SuppressWarnings("unchecked") @Override - public <D extends Distance<D>> KNNQuery<O, D> getKNNQuery(DistanceQuery<O, D> distanceQuery, Object... hints) { - if (!(inner instanceof KNNIndex)) { + public KNNQuery<O> getKNNQuery(DistanceQuery<O> distanceQuery, Object... hints) { + if(!(inner instanceof KNNIndex)) { return null; } - if (distanceQuery.getRelation() != relation) { + if(distanceQuery.getRelation() != relation) { return null; } - if (!LatLngDistanceFunction.class.isInstance(distanceQuery.getDistanceFunction())) { + if(!LatLngDistanceFunction.class.isInstance(distanceQuery.getDistanceFunction())) { return null; } - for (Object o : hints) { - if (o == DatabaseQuery.HINT_EXACT) { + for(Object o : hints) { + if(o == DatabaseQuery.HINT_EXACT) { return null; } } - SpatialPrimitiveDistanceQuery<O, DoubleDistance> innerQuery = EuclideanDistanceFunction.STATIC.instantiate(view); - KNNQuery<O, DoubleDistance> innerq = ((KNNIndex<O>) inner).getKNNQuery(innerQuery, hints); - if (innerq == null) { + SpatialPrimitiveDistanceQuery<O> innerQuery = EuclideanDistanceFunction.STATIC.instantiate(view); + KNNQuery<O> innerq = ((KNNIndex<O>) inner).getKNNQuery(innerQuery, hints); + if(innerq == null) { return null; } - return (KNNQuery<O, D>) new ProjectedKNNQuery<DoubleDistance>((DistanceQuery<O, DoubleDistance>) distanceQuery, innerq); + return new ProjectedKNNQuery(distanceQuery, innerq); } @SuppressWarnings("unchecked") @Override - public <D extends Distance<D>> RangeQuery<O, D> getRangeQuery(DistanceQuery<O, D> distanceQuery, Object... hints) { - if (!(inner instanceof RangeIndex)) { + public RangeQuery<O> getRangeQuery(DistanceQuery<O> distanceQuery, Object... hints) { + if(!(inner instanceof RangeIndex)) { return null; } - if (distanceQuery.getRelation() != relation) { + if(distanceQuery.getRelation() != relation) { return null; } - if (!LatLngDistanceFunction.class.isInstance(distanceQuery.getDistanceFunction())) { + if(!LatLngDistanceFunction.class.isInstance(distanceQuery.getDistanceFunction())) { return null; } - for (Object o : hints) { - if (o == DatabaseQuery.HINT_EXACT) { + for(Object o : hints) { + if(o == DatabaseQuery.HINT_EXACT) { return null; } } - SpatialPrimitiveDistanceQuery<O, DoubleDistance> innerQuery = EuclideanDistanceFunction.STATIC.instantiate(view); - RangeQuery<O, DoubleDistance> innerq = ((RangeIndex<O>) inner).getRangeQuery(innerQuery, hints); - if (innerq == null) { + SpatialPrimitiveDistanceQuery<O> innerQuery = EuclideanDistanceFunction.STATIC.instantiate(view); + RangeQuery<O> innerq = ((RangeIndex<O>) inner).getRangeQuery(innerQuery, hints); + if(innerq == null) { return null; } - return (RangeQuery<O, D>) new ProjectedRangeQuery<DoubleDistance>((DistanceQuery<O, DoubleDistance>) distanceQuery, innerq); + return new ProjectedRangeQuery(distanceQuery, innerq); } @SuppressWarnings("unchecked") @Override - public <D extends Distance<D>> RKNNQuery<O, D> getRKNNQuery(DistanceQuery<O, D> distanceQuery, Object... hints) { - if (!(inner instanceof RKNNIndex)) { + public RKNNQuery<O> getRKNNQuery(DistanceQuery<O> distanceQuery, Object... hints) { + if(!(inner instanceof RKNNIndex)) { return null; } - if (distanceQuery.getRelation() != relation) { + if(distanceQuery.getRelation() != relation) { return null; } - if (!LatLngDistanceFunction.class.isInstance(distanceQuery.getDistanceFunction())) { + if(!LatLngDistanceFunction.class.isInstance(distanceQuery.getDistanceFunction())) { return null; } - for (Object o : hints) { - if (o == DatabaseQuery.HINT_EXACT) { + for(Object o : hints) { + if(o == DatabaseQuery.HINT_EXACT) { return null; } } - SpatialPrimitiveDistanceQuery<O, DoubleDistance> innerQuery = EuclideanDistanceFunction.STATIC.instantiate(view); - RKNNQuery<O, DoubleDistance> innerq = ((RKNNIndex<O>) inner).getRKNNQuery(innerQuery, hints); - if (innerq == null) { + SpatialPrimitiveDistanceQuery<O> innerQuery = EuclideanDistanceFunction.STATIC.instantiate(view); + RKNNQuery<O> innerq = ((RKNNIndex<O>) inner).getRKNNQuery(innerQuery, hints); + if(innerq == null) { return null; } - return (RKNNQuery<O, D>) new ProjectedRKNNQuery<DoubleDistance>((DistanceQuery<O, DoubleDistance>) distanceQuery, innerq); + return new ProjectedRKNNQuery(distanceQuery, innerq); } /** @@ -187,7 +187,7 @@ public class LatLngAsECEFIndex<O extends NumberVector<?>> extends ProjectedIndex * * @param <O> Data type. */ - public static class Factory<O extends NumberVector<?>> extends ProjectedIndex.Factory<O, O> { + public static class Factory<O extends NumberVector> extends ProjectedIndex.Factory<O, O> { /** * Disable refinement of distances. */ @@ -207,23 +207,24 @@ public class LatLngAsECEFIndex<O extends NumberVector<?>> extends ProjectedIndex @Override public ProjectedIndex<O, O> instantiate(Relation<O> relation) { - if (!proj.getInputDataTypeInformation().isAssignableFromType(relation.getDataTypeInformation())) { + if(!proj.getInputDataTypeInformation().isAssignableFromType(relation.getDataTypeInformation())) { return null; } proj.initialize(relation.getDataTypeInformation()); final Relation<O> view; - if (materialize) { + if(materialize) { DBIDs ids = relation.getDBIDs(); WritableDataStore<O> content = DataStoreUtil.makeStorage(ids, DataStoreFactory.HINT_DB, proj.getOutputDataTypeInformation().getRestrictionClass()); - for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { + for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { content.put(iter, proj.project(relation.get(iter))); } view = new MaterializedRelation<>("ECEF Projection", "ecef-projection", proj.getOutputDataTypeInformation(), content, ids); - } else { + } + else { view = new ProjectedView<>(relation, proj); } Index inneri = inner.instantiate(view); - if (inneri == null) { + if(inneri == null) { return null; } return new LatLngAsECEFIndex<>(relation, proj, view, inneri, norefine); @@ -238,7 +239,7 @@ public class LatLngAsECEFIndex<O extends NumberVector<?>> extends ProjectedIndex * * @param <O> Outer object type. */ - public static class Parameterizer<O extends NumberVector<?>> extends AbstractParameterizer { + public static class Parameterizer<O extends NumberVector> extends AbstractParameterizer { /** * Inner index factory. */ @@ -263,22 +264,22 @@ public class LatLngAsECEFIndex<O extends NumberVector<?>> extends ProjectedIndex protected void makeOptions(Parameterization config) { super.makeOptions(config); ObjectParameter<EarthModel> modelP = new ObjectParameter<>(EarthModel.MODEL_ID, EarthModel.class, SphericalVincentyEarthModel.class); - if (config.grab(modelP)) { + if(config.grab(modelP)) { model = modelP.instantiateClass(config); } ObjectParameter<IndexFactory<O, ?>> innerP = new ObjectParameter<>(ProjectedIndex.Factory.Parameterizer.INDEX_ID, IndexFactory.class); - if (config.grab(innerP)) { + if(config.grab(innerP)) { inner = innerP.instantiateClass(config); } Flag materializeF = new Flag(ProjectedIndex.Factory.Parameterizer.MATERIALIZE_FLAG); - if (config.grab(materializeF)) { + if(config.grab(materializeF)) { materialize = materializeF.isTrue(); } Flag norefineF = new Flag(ProjectedIndex.Factory.Parameterizer.DISABLE_REFINE_FLAG); - if (config.grab(norefineF)) { + if(config.grab(norefineF)) { norefine = norefineF.isTrue(); } } diff --git a/src/de/lmu/ifi/dbs/elki/index/projected/LngLatAsECEFIndex.java b/src/de/lmu/ifi/dbs/elki/index/projected/LngLatAsECEFIndex.java index 4bf97659..23d6ae96 100644 --- a/src/de/lmu/ifi/dbs/elki/index/projected/LngLatAsECEFIndex.java +++ b/src/de/lmu/ifi/dbs/elki/index/projected/LngLatAsECEFIndex.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.projected; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -42,8 +42,6 @@ import de.lmu.ifi.dbs.elki.database.relation.ProjectedView; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.distance.distancefunction.geo.LngLatDistanceFunction; import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; -import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; import de.lmu.ifi.dbs.elki.index.Index; import de.lmu.ifi.dbs.elki.index.IndexFactory; import de.lmu.ifi.dbs.elki.index.KNNIndex; @@ -77,9 +75,11 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter; * * @author Erich Schubert * + * @apiviz.composedOf LngLatToECEFProjection + * * @param <O> Object type */ -public class LngLatAsECEFIndex<O extends NumberVector<?>> extends ProjectedIndex<O, O> { +public class LngLatAsECEFIndex<O extends NumberVector> extends ProjectedIndex<O, O> { /** * Constructor. * @@ -105,7 +105,7 @@ public class LngLatAsECEFIndex<O extends NumberVector<?>> extends ProjectedIndex @SuppressWarnings("unchecked") @Override - public <D extends Distance<D>> KNNQuery<O, D> getKNNQuery(DistanceQuery<O, D> distanceQuery, Object... hints) { + public KNNQuery<O> getKNNQuery(DistanceQuery<O> distanceQuery, Object... hints) { if (!(inner instanceof KNNIndex)) { return null; } @@ -120,17 +120,17 @@ public class LngLatAsECEFIndex<O extends NumberVector<?>> extends ProjectedIndex return null; } } - SpatialPrimitiveDistanceQuery<O, DoubleDistance> innerQuery = EuclideanDistanceFunction.STATIC.instantiate(view); - KNNQuery<O, DoubleDistance> innerq = ((KNNIndex<O>) inner).getKNNQuery(innerQuery, hints); + SpatialPrimitiveDistanceQuery<O> innerQuery = EuclideanDistanceFunction.STATIC.instantiate(view); + KNNQuery<O> innerq = ((KNNIndex<O>) inner).getKNNQuery(innerQuery, hints); if (innerq == null) { return null; } - return (KNNQuery<O, D>) new ProjectedKNNQuery<DoubleDistance>((DistanceQuery<O, DoubleDistance>) distanceQuery, innerq); + return new ProjectedKNNQuery(distanceQuery, innerq); } @SuppressWarnings("unchecked") @Override - public <D extends Distance<D>> RangeQuery<O, D> getRangeQuery(DistanceQuery<O, D> distanceQuery, Object... hints) { + public RangeQuery<O> getRangeQuery(DistanceQuery<O> distanceQuery, Object... hints) { if (!(inner instanceof RangeIndex)) { return null; } @@ -145,17 +145,17 @@ public class LngLatAsECEFIndex<O extends NumberVector<?>> extends ProjectedIndex return null; } } - SpatialPrimitiveDistanceQuery<O, DoubleDistance> innerQuery = EuclideanDistanceFunction.STATIC.instantiate(view); - RangeQuery<O, DoubleDistance> innerq = ((RangeIndex<O>) inner).getRangeQuery(innerQuery, hints); + SpatialPrimitiveDistanceQuery<O> innerQuery = EuclideanDistanceFunction.STATIC.instantiate(view); + RangeQuery<O> innerq = ((RangeIndex<O>) inner).getRangeQuery(innerQuery, hints); if (innerq == null) { return null; } - return (RangeQuery<O, D>) new ProjectedRangeQuery<DoubleDistance>((DistanceQuery<O, DoubleDistance>) distanceQuery, innerq); + return new ProjectedRangeQuery(distanceQuery, innerq); } @SuppressWarnings("unchecked") @Override - public <D extends Distance<D>> RKNNQuery<O, D> getRKNNQuery(DistanceQuery<O, D> distanceQuery, Object... hints) { + public RKNNQuery<O> getRKNNQuery(DistanceQuery<O> distanceQuery, Object... hints) { if (!(inner instanceof RKNNIndex)) { return null; } @@ -170,12 +170,12 @@ public class LngLatAsECEFIndex<O extends NumberVector<?>> extends ProjectedIndex return null; } } - SpatialPrimitiveDistanceQuery<O, DoubleDistance> innerQuery = EuclideanDistanceFunction.STATIC.instantiate(view); - RKNNQuery<O, DoubleDistance> innerq = ((RKNNIndex<O>) inner).getRKNNQuery(innerQuery, hints); + SpatialPrimitiveDistanceQuery<O> innerQuery = EuclideanDistanceFunction.STATIC.instantiate(view); + RKNNQuery<O> innerq = ((RKNNIndex<O>) inner).getRKNNQuery(innerQuery, hints); if (innerq == null) { return null; } - return (RKNNQuery<O, D>) new ProjectedRKNNQuery<DoubleDistance>((DistanceQuery<O, DoubleDistance>) distanceQuery, innerq); + return new ProjectedRKNNQuery(distanceQuery, innerq); } /** @@ -187,7 +187,7 @@ public class LngLatAsECEFIndex<O extends NumberVector<?>> extends ProjectedIndex * * @param <O> Data type. */ - public static class Factory<O extends NumberVector<?>> extends ProjectedIndex.Factory<O, O> { + public static class Factory<O extends NumberVector> extends ProjectedIndex.Factory<O, O> { /** * Constructor. * @@ -233,7 +233,7 @@ public class LngLatAsECEFIndex<O extends NumberVector<?>> extends ProjectedIndex * * @param <O> Outer object type. */ - public static class Parameterizer<O extends NumberVector<?>> extends AbstractParameterizer { + public static class Parameterizer<O extends NumberVector> extends AbstractParameterizer { /** * Inner index factory. */ diff --git a/src/de/lmu/ifi/dbs/elki/index/projected/PINN.java b/src/de/lmu/ifi/dbs/elki/index/projected/PINN.java index b3e617b8..2294455a 100644 --- a/src/de/lmu/ifi/dbs/elki/index/projected/PINN.java +++ b/src/de/lmu/ifi/dbs/elki/index/projected/PINN.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.projected; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -27,7 +27,7 @@ import de.lmu.ifi.dbs.elki.data.NumberVector; import de.lmu.ifi.dbs.elki.data.projection.RandomProjection; import de.lmu.ifi.dbs.elki.index.IndexFactory; import de.lmu.ifi.dbs.elki.math.linearalgebra.randomprojections.AchlioptasRandomProjectionFamily; -import de.lmu.ifi.dbs.elki.utilities.RandomFactory; +import de.lmu.ifi.dbs.elki.math.random.RandomFactory; import de.lmu.ifi.dbs.elki.utilities.documentation.Reference; import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer; import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID; @@ -57,7 +57,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.RandomParameter; * @param <O> Object type */ @Reference(title = "Finding local anomalies in very high dimensional space", authors = "T. de Vries, S. Chawla, M. E. Houle", booktitle = "Proc. IEEE 10th International Conference on Data Mining (ICDM)", url = "http://dx.doi.org/10.1109/ICDM.2010.151") -public class PINN<O extends NumberVector<?>> extends ProjectedIndex.Factory<O, O> { +public class PINN<O extends NumberVector> extends ProjectedIndex.Factory<O, O> { /** * Constructor. * @@ -80,7 +80,7 @@ public class PINN<O extends NumberVector<?>> extends ProjectedIndex.Factory<O, O * * @param <O> Outer object type. */ - public static class Parameterizer<O extends NumberVector<?>> extends AbstractParameterizer { + public static class Parameterizer<O extends NumberVector> extends AbstractParameterizer { /** * Target dimensionality. */ diff --git a/src/de/lmu/ifi/dbs/elki/index/projected/ProjectedIndex.java b/src/de/lmu/ifi/dbs/elki/index/projected/ProjectedIndex.java index f71ced70..0d876dea 100644 --- a/src/de/lmu/ifi/dbs/elki/index/projected/ProjectedIndex.java +++ b/src/de/lmu/ifi/dbs/elki/index/projected/ProjectedIndex.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.projected; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -35,15 +35,11 @@ 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.distance.DistanceDBIDList; -import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter; -import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPairList; -import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNHeap; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNHeap; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList; -import de.lmu.ifi.dbs.elki.database.ids.distance.ModifiableDistanceDBIDList; -import de.lmu.ifi.dbs.elki.database.ids.distance.ModifiableDoubleDistanceDBIDList; -import de.lmu.ifi.dbs.elki.database.ids.generic.GenericDistanceDBIDList; +import de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDList; +import de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDListIter; +import de.lmu.ifi.dbs.elki.database.ids.KNNHeap; +import de.lmu.ifi.dbs.elki.database.ids.KNNList; +import de.lmu.ifi.dbs.elki.database.ids.ModifiableDoubleDBIDList; import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery; import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery; @@ -54,9 +50,6 @@ import de.lmu.ifi.dbs.elki.database.relation.MaterializedRelation; import de.lmu.ifi.dbs.elki.database.relation.ProjectedView; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; -import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; import de.lmu.ifi.dbs.elki.index.Index; import de.lmu.ifi.dbs.elki.index.IndexFactory; import de.lmu.ifi.dbs.elki.index.KNNIndex; @@ -87,9 +80,10 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter; * * @author Erich Schubert * - * @apiviz.composedOf ProjectedKNNQuery - * @apiviz.composedOf ProjectedRangeQuery - * @apiviz.composedOf ProjectedRKNNQuery + * @apiviz.composedOf Projection + * @apiviz.has ProjectedKNNQuery + * @apiviz.has ProjectedRangeQuery + * @apiviz.has ProjectedRKNNQuery * * @param <O> Outer object type. * @param <I> Inner object type. @@ -189,7 +183,7 @@ public class ProjectedIndex<O, I> implements KNNIndex<O>, RKNNIndex<O>, RangeInd } @Override - public <D extends Distance<D>> KNNQuery<O, D> getKNNQuery(DistanceQuery<O, D> distanceQuery, Object... hints) { + public KNNQuery<O> getKNNQuery(DistanceQuery<O> distanceQuery, Object... hints) { if(!(inner instanceof KNNIndex)) { return null; } @@ -202,17 +196,17 @@ public class ProjectedIndex<O, I> implements KNNIndex<O>, RKNNIndex<O>, RangeInd } } @SuppressWarnings("unchecked") - DistanceQuery<I, D> innerQuery = ((DistanceFunction<? super I, D>) distanceQuery.getDistanceFunction()).instantiate(view); + DistanceQuery<I> innerQuery = ((DistanceFunction<? super I>) distanceQuery.getDistanceFunction()).instantiate(view); @SuppressWarnings("unchecked") - KNNQuery<I, D> innerq = ((KNNIndex<I>) inner).getKNNQuery(innerQuery, hints); + KNNQuery<I> innerq = ((KNNIndex<I>) inner).getKNNQuery(innerQuery, hints); if(innerq == null) { return null; } - return new ProjectedKNNQuery<>(distanceQuery, innerq); + return new ProjectedKNNQuery(distanceQuery, innerq); } @Override - public <D extends Distance<D>> RangeQuery<O, D> getRangeQuery(DistanceQuery<O, D> distanceQuery, Object... hints) { + public RangeQuery<O> getRangeQuery(DistanceQuery<O> distanceQuery, Object... hints) { if(!(inner instanceof RangeIndex)) { return null; } @@ -225,17 +219,17 @@ public class ProjectedIndex<O, I> implements KNNIndex<O>, RKNNIndex<O>, RangeInd } } @SuppressWarnings("unchecked") - DistanceQuery<I, D> innerQuery = ((DistanceFunction<? super I, D>) distanceQuery.getDistanceFunction()).instantiate(view); + DistanceQuery<I> innerQuery = ((DistanceFunction<? super I>) distanceQuery.getDistanceFunction()).instantiate(view); @SuppressWarnings("unchecked") - RangeQuery<I, D> innerq = ((RangeIndex<I>) inner).getRangeQuery(innerQuery, hints); + RangeQuery<I> innerq = ((RangeIndex<I>) inner).getRangeQuery(innerQuery, hints); if(innerq == null) { return null; } - return new ProjectedRangeQuery<>(distanceQuery, innerq); + return new ProjectedRangeQuery(distanceQuery, innerq); } @Override - public <D extends Distance<D>> RKNNQuery<O, D> getRKNNQuery(DistanceQuery<O, D> distanceQuery, Object... hints) { + public RKNNQuery<O> getRKNNQuery(DistanceQuery<O> distanceQuery, Object... hints) { if(!(inner instanceof RKNNIndex)) { return null; } @@ -248,13 +242,13 @@ public class ProjectedIndex<O, I> implements KNNIndex<O>, RKNNIndex<O>, RangeInd } } @SuppressWarnings("unchecked") - DistanceQuery<I, D> innerQuery = ((DistanceFunction<? super I, D>) distanceQuery.getDistanceFunction()).instantiate(view); + DistanceQuery<I> innerQuery = ((DistanceFunction<? super I>) distanceQuery.getDistanceFunction()).instantiate(view); @SuppressWarnings("unchecked") - RKNNQuery<I, D> innerq = ((RKNNIndex<I>) inner).getRKNNQuery(innerQuery, hints); + RKNNQuery<I> innerq = ((RKNNIndex<I>) inner).getRKNNQuery(innerQuery, hints); if(innerq == null) { return null; } - return new ProjectedRKNNQuery<>(distanceQuery, innerq); + return new ProjectedRKNNQuery(distanceQuery, innerq); } /** @@ -262,66 +256,54 @@ public class ProjectedIndex<O, I> implements KNNIndex<O>, RKNNIndex<O>, RangeInd * * @author Erich Schubert * - * @param <D> Distance type + * @param Distance type */ - class ProjectedKNNQuery<D extends Distance<D>> implements KNNQuery<O, D> { + class ProjectedKNNQuery implements KNNQuery<O> { /** * Inner kNN query. */ - KNNQuery<I, D> inner; + KNNQuery<I> inner; /** * Distance query for refinement. */ - DistanceQuery<O, D> distq; + DistanceQuery<O> distq; /** * Constructor. * * @param inner Inner kNN query. */ - public ProjectedKNNQuery(DistanceQuery<O, D> distanceQuery, KNNQuery<I, D> inner) { + public ProjectedKNNQuery(DistanceQuery<O> distanceQuery, KNNQuery<I> inner) { super(); this.inner = inner; this.distq = distanceQuery; } @Override - public KNNList<D> getKNNForDBID(DBIDRef id, int k) { + public KNNList getKNNForDBID(DBIDRef id, int k) { // So we have to project the query point only once: return getKNNForObject(relation.get(id), k); } @Override - public List<? extends KNNList<D>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) { + public List<? extends KNNList> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) { return inner.getKNNForBulkDBIDs(ids, k); } - @SuppressWarnings("unchecked") @Override - public KNNList<D> getKNNForObject(O obj, int k) { + public KNNList getKNNForObject(O obj, int k) { final I pobj = proj.project(obj); if(norefine) { return inner.getKNNForObject(pobj, k); } - KNNList<D> ilist = inner.getKNNForObject(pobj, (int) Math.ceil(k * kmulti)); - if(distq.getDistanceFunction() instanceof PrimitiveDoubleDistanceFunction) { - PrimitiveDoubleDistanceFunction<? super O> df = (PrimitiveDoubleDistanceFunction<? super O>) distq.getDistanceFunction(); - DoubleDistanceKNNHeap heap = DBIDUtil.newDoubleDistanceHeap(k); - for(DistanceDBIDListIter<D> iter = ilist.iter(); iter.valid(); iter.advance()) { - heap.insert(df.doubleDistance(obj, distq.getRelation().get(iter)), iter); - countRefinement(); - } - return (KNNList<D>) heap.toKNNList(); - } - else { - KNNHeap<D> heap = DBIDUtil.newHeap(distq.getDistanceFactory(), k); - for(DistanceDBIDListIter<D> iter = ilist.iter(); iter.valid(); iter.advance()) { - heap.insert(distq.distance(obj, iter), iter); - countRefinement(); - } - return heap.toKNNList(); + KNNList ilist = inner.getKNNForObject(pobj, (int) Math.ceil(k * kmulti)); + KNNHeap heap = DBIDUtil.newHeap(k); + for(DoubleDBIDListIter iter = ilist.iter(); iter.valid(); iter.advance()) { + heap.insert(distq.distance(obj, iter), iter); + countRefinement(); } + return heap.toKNNList(); } } @@ -330,62 +312,46 @@ public class ProjectedIndex<O, I> implements KNNIndex<O>, RKNNIndex<O>, RangeInd * * @author Erich Schubert * - * @param <D> Distance type + * @param Distance type */ - class ProjectedRangeQuery<D extends Distance<D>> extends AbstractDistanceRangeQuery<O, D> { + class ProjectedRangeQuery extends AbstractDistanceRangeQuery<O> { /** * Inner range query. */ - RangeQuery<I, D> inner; + RangeQuery<I> inner; /** * Constructor. * * @param inner Inner range query. */ - public ProjectedRangeQuery(DistanceQuery<O, D> distanceQuery, RangeQuery<I, D> inner) { + public ProjectedRangeQuery(DistanceQuery<O> distanceQuery, RangeQuery<I> inner) { super(distanceQuery); this.inner = inner; } @Override - public DistanceDBIDList<D> getRangeForDBID(DBIDRef id, D range) { + public DoubleDBIDList getRangeForDBID(DBIDRef id, double range) { // So we have to project the query point only once: return getRangeForObject(relation.get(id), range); } - @SuppressWarnings({ "unchecked" }) @Override - public DistanceDBIDList<D> getRangeForObject(O obj, D range) { + public DoubleDBIDList getRangeForObject(O obj, double range) { final I pobj = proj.project(obj); - DistanceDBIDList<D> ilist = inner.getRangeForObject(pobj, range); + DoubleDBIDList ilist = inner.getRangeForObject(pobj, range); if(norefine) { return ilist; } - if(distanceQuery.getDistanceFunction() instanceof PrimitiveDoubleDistanceFunction) { - PrimitiveDoubleDistanceFunction<? super O> df = (PrimitiveDoubleDistanceFunction<? super O>) distanceQuery.getDistanceFunction(); - double drange = ((DoubleDistance) range).doubleValue(); - ModifiableDoubleDistanceDBIDList olist = new DoubleDistanceDBIDPairList(ilist.size()); - for(DistanceDBIDListIter<D> iter = ilist.iter(); iter.valid(); iter.advance()) { - final double dist = df.doubleDistance(obj, distanceQuery.getRelation().get(iter)); - countRefinement(); - if(dist <= drange) { - olist.add(dist, iter); - } - } - return (DistanceDBIDList<D>) olist; - } - else { - ModifiableDistanceDBIDList<D> olist = new GenericDistanceDBIDList<>(ilist.size()); - for(DistanceDBIDListIter<D> iter = ilist.iter(); iter.valid(); iter.advance()) { - D dist = distanceQuery.distance(obj, iter); - countRefinement(); - if(range.compareTo(dist) <= 0) { - olist.add(dist, iter); - } + ModifiableDoubleDBIDList olist = DBIDUtil.newDistanceDBIDList(ilist.size()); + for(DoubleDBIDListIter iter = ilist.iter(); iter.valid(); iter.advance()) { + double dist = distanceQuery.distance(obj, iter); + countRefinement(); + if(range <= dist) { + olist.add(dist, iter); } - return olist; } + return olist; } } @@ -394,67 +360,54 @@ public class ProjectedIndex<O, I> implements KNNIndex<O>, RKNNIndex<O>, RangeInd * * @author Erich Schubert * - * @param <D> Distance type + * @param Distance type */ - class ProjectedRKNNQuery<D extends Distance<D>> implements RKNNQuery<O, D> { + class ProjectedRKNNQuery implements RKNNQuery<O> { /** * Inner RkNN query. */ - RKNNQuery<I, D> inner; + RKNNQuery<I> inner; /** * Distance query for refinement. */ - DistanceQuery<O, D> distq; + DistanceQuery<O> distq; /** * Constructor. * * @param inner Inner RkNN query. */ - public ProjectedRKNNQuery(DistanceQuery<O, D> distanceQuery, RKNNQuery<I, D> inner) { + public ProjectedRKNNQuery(DistanceQuery<O> distanceQuery, RKNNQuery<I> inner) { super(); this.inner = inner; this.distq = distanceQuery; } @Override - public DistanceDBIDList<D> getRKNNForDBID(DBIDRef id, int k) { + public DoubleDBIDList getRKNNForDBID(DBIDRef id, int k) { // So we have to project the query point only once: return getRKNNForObject(relation.get(id), k); } - @SuppressWarnings("unchecked") @Override - public DistanceDBIDList<D> getRKNNForObject(O obj, int k) { + public DoubleDBIDList getRKNNForObject(O obj, int k) { final I pobj = proj.project(obj); if(norefine) { return inner.getRKNNForObject(pobj, k); } - DistanceDBIDList<D> ilist = inner.getRKNNForObject(pobj, (int) Math.ceil(k * kmulti)); - if(distq.getDistanceFunction() instanceof PrimitiveDoubleDistanceFunction) { - PrimitiveDoubleDistanceFunction<? super O> df = (PrimitiveDoubleDistanceFunction<? super O>) distq.getDistanceFunction(); - ModifiableDoubleDistanceDBIDList olist = new DoubleDistanceDBIDPairList(ilist.size()); - for(DistanceDBIDListIter<D> iter = ilist.iter(); iter.valid(); iter.advance()) { - final double dist = df.doubleDistance(obj, distq.getRelation().get(iter)); - countRefinement(); - olist.add(dist, iter); - } - return (DistanceDBIDList<D>) olist; - } - else { - ModifiableDistanceDBIDList<D> olist = new GenericDistanceDBIDList<>(ilist.size()); - for(DistanceDBIDListIter<D> iter = ilist.iter(); iter.valid(); iter.advance()) { - D dist = distq.distance(obj, iter); - countRefinement(); - olist.add(dist, iter); - } - return olist; + DoubleDBIDList ilist = inner.getRKNNForObject(pobj, (int) Math.ceil(k * kmulti)); + ModifiableDoubleDBIDList olist = DBIDUtil.newDistanceDBIDList(ilist.size()); + for(DoubleDBIDListIter iter = ilist.iter(); iter.valid(); iter.advance()) { + double dist = distq.distance(obj, iter); + countRefinement(); + olist.add(dist, iter); } + return olist; } @Override - public List<? extends DistanceDBIDList<D>> getRKNNForBulkDBIDs(ArrayDBIDs ids, int k) { + public List<? extends DoubleDBIDList> getRKNNForBulkDBIDs(ArrayDBIDs ids, int k) { return inner.getRKNNForBulkDBIDs(ids, k); } } diff --git a/src/de/lmu/ifi/dbs/elki/index/projected/package-info.java b/src/de/lmu/ifi/dbs/elki/index/projected/package-info.java index 8a311292..3dc9c2af 100644 --- a/src/de/lmu/ifi/dbs/elki/index/projected/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/projected/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/AbstractDirectoryEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/AbstractDirectoryEntry.java index a75a49eb..ebd36547 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/AbstractDirectoryEntry.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/AbstractDirectoryEntry.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -46,7 +46,7 @@ public abstract class AbstractDirectoryEntry implements DirectoryEntry { } /** - * Provides a new AbstractEntry with the specified id. + * Constructor. * * @param id the id of the object (node or data object) represented by this * entry. diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/AbstractLeafEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/AbstractLeafEntry.java index 15c8c589..b36bf72d 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/AbstractLeafEntry.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/AbstractLeafEntry.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -49,7 +49,7 @@ public abstract class AbstractLeafEntry implements LeafEntry { } /** - * Provides a new AbstractEntry with the specified id. + * Constructor. * * @param id the id of the object (node or data object) represented by this * entry. diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/AbstractNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/AbstractNode.java index 2748b76e..444f62cc 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/AbstractNode.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/AbstractNode.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/BreadthFirstEnumeration.java b/src/de/lmu/ifi/dbs/elki/index/tree/BreadthFirstEnumeration.java index ec33050b..bbb1e0cc 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/BreadthFirstEnumeration.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/BreadthFirstEnumeration.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -29,7 +29,7 @@ import java.util.NoSuchElementException; import java.util.Queue; /** - * Provides a breadth first enumeration over the nodes of an index structure. + * Breadth first enumeration over the nodes of an index structure. * * @author Elke Achtert * diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/DirectoryEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/DirectoryEntry.java index c7d74f13..a89157e0 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/DirectoryEntry.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/DirectoryEntry.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/Entry.java b/src/de/lmu/ifi/dbs/elki/index/tree/Entry.java index c9c5e90a..1f2aa21c 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/Entry.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/Entry.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/IndexTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/IndexTree.java index ee3bd5d6..92bc4c1b 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/IndexTree.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/IndexTree.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/IndexTreePath.java b/src/de/lmu/ifi/dbs/elki/index/tree/IndexTreePath.java index d9534e91..5b63d39f 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/IndexTreePath.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/IndexTreePath.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/LeafEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/LeafEntry.java index d020c8b1..6ede0ce4 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/LeafEntry.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/LeafEntry.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/Node.java b/src/de/lmu/ifi/dbs/elki/index/tree/Node.java index 9f393f52..7831bfdd 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/Node.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/Node.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexHeader.java b/src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexHeader.java index 42688ef0..b1d6e42d 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexHeader.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexHeader.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexPathComponent.java b/src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexPathComponent.java index 1ef146cf..95276bad 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexPathComponent.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/TreeIndexPathComponent.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/MetricalIndexTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/MetricalIndexTree.java index 2494eb39..b1b323e9 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/MetricalIndexTree.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/MetricalIndexTree.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -26,7 +26,6 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical; import java.util.List; import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; import de.lmu.ifi.dbs.elki.index.tree.Entry; import de.lmu.ifi.dbs.elki.index.tree.IndexTree; import de.lmu.ifi.dbs.elki.index.tree.Node; @@ -38,11 +37,10 @@ import de.lmu.ifi.dbs.elki.persistent.PageFile; * @author Elke Achtert * * @param <O> the type of objects stored in the index - * @param <D> the type of Distance used in the metrical index * @param <N> the type of nodes used in the metrical index * @param <E> the type of entries used in the metrical index */ -public abstract class MetricalIndexTree<O, D extends Distance<D>, N extends Node<E>, E extends Entry> extends IndexTree<N, E> { +public abstract class MetricalIndexTree<O, N extends Node<E>, E extends Entry> extends IndexTree<N, E> { /** * Constructor. * @@ -57,7 +55,7 @@ public abstract class MetricalIndexTree<O, D extends Distance<D>, N extends Node * * @return the distance function of this metrical index */ - public abstract DistanceFunction<? super O, D> getDistanceFunction(); + public abstract DistanceFunction<? super O> getDistanceFunction(); /** * Returns a list of entries pointing to the leaf nodes of this spatial index. diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTree.java index 61ca9116..f1ef3b9b 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTree.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTree.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -30,7 +30,6 @@ 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.distance.distancefunction.DistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.tree.BreadthFirstEnumeration; import de.lmu.ifi.dbs.elki.index.tree.IndexTreePath; import de.lmu.ifi.dbs.elki.index.tree.TreeIndexPathComponent; @@ -54,12 +53,11 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleIntPair; * @apiviz.excludeSubtypes * * @param <O> the type of DatabaseObject to be stored in the metrical index - * @param <D> the type of Distance used in the metrical index * @param <N> the type of MetricalNode used in the metrical index * @param <E> the type of MetricalEntry used in the metrical index * @param <S> the type to store settings in. */ -public abstract class AbstractMTree<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry, S extends MTreeSettings<O, D, N, E>> extends MetricalIndexTree<O, D, N, E> { +public abstract class AbstractMTree<O, N extends AbstractMTreeNode<O, N, E>, E extends MTreeEntry, S extends MTreeSettings<O, N, E>> extends MetricalIndexTree<O, N, E> { /** * Debugging flag: do extra integrity checks. */ @@ -87,20 +85,11 @@ public abstract class AbstractMTree<O, D extends NumberDistance<D, ?>, N extends } @Override - public final DistanceFunction<? super O, D> getDistanceFunction() { + public final DistanceFunction<? super O> getDistanceFunction() { return settings.distanceFunction; } /** - * Get the distance factory. - * - * @return the distance factory used - */ - public final D getDistanceFactory() { - return settings.distanceFunction.getDistanceFactory(); - } - - /** * Returns a string representation of this M-Tree by performing a breadth * first enumeration on the tree and adding the string representation of the * visited nodes and their entries to the result. @@ -117,8 +106,8 @@ public abstract class AbstractMTree<O, D extends NumberDistance<D, ?>, N extends N node = getRoot(); - while (!node.isLeaf()) { - if (node.getNumEntries() > 0) { + while(!node.isLeaf()) { + if(node.getNumEntries() > 0) { E entry = node.getEntry(0); node = getNode(entry); levels++; @@ -126,20 +115,22 @@ public abstract class AbstractMTree<O, D extends NumberDistance<D, ?>, N extends } BreadthFirstEnumeration<N, E> enumeration = new BreadthFirstEnumeration<>(this, getRootPath()); - while (enumeration.hasMoreElements()) { + while(enumeration.hasMoreElements()) { IndexTreePath<E> path = enumeration.nextElement(); E entry = path.getLastPathComponent().getEntry(); - if (entry.isLeafEntry()) { + if(entry.isLeafEntry()) { objects++; result.append("\n ").append(entry.toString()); - } else { + } + else { node = getNode(entry); result.append("\n\n").append(node).append(", numEntries = ").append(node.getNumEntries()); result.append("\n").append(entry.toString()); - if (node.isLeaf()) { + if(node.isLeaf()) { leafNodes++; - } else { + } + else { dirNodes++; } } @@ -165,27 +156,27 @@ public abstract class AbstractMTree<O, D extends NumberDistance<D, ?>, N extends */ // todo: implement a bulk load for M-Tree and remove this method public void insert(E entry, boolean withPreInsert) { - if (getLogger().isDebugging()) { + if(getLogger().isDebugging()) { getLogger().debugFine("insert " + entry.getRoutingObjectID() + "\n"); } - if (!initialized) { + if(!initialized) { initialize(entry); } // choose subtree for insertion IndexTreePath<E> subtree = settings.insertStrategy.choosePath(this, entry); - if (getLogger().isDebugging()) { + if(getLogger().isDebugging()) { getLogger().debugFine("insertion-subtree " + subtree + "\n"); } // determine parent distance E parentEntry = subtree.getLastPathComponent().getEntry(); - double parentDistance = distance(parentEntry.getRoutingObjectID(), entry.getRoutingObjectID()).doubleValue(); + double parentDistance = distance(parentEntry.getRoutingObjectID(), entry.getRoutingObjectID()); entry.setParentDistance(parentDistance); // create leaf entry and do pre insert - if (withPreInsert) { + if(withPreInsert) { preInsert(entry); } @@ -198,8 +189,8 @@ public abstract class AbstractMTree<O, D extends NumberDistance<D, ?>, N extends adjustTree(subtree); // test - if (EXTRA_INTEGRITY_CHECKS) { - if (withPreInsert) { + if(EXTRA_INTEGRITY_CHECKS) { + if(withPreInsert) { getRoot().integrityCheck(this, getRootEntry()); } } @@ -211,10 +202,10 @@ public abstract class AbstractMTree<O, D extends NumberDistance<D, ?>, N extends * @param entries Entries to insert */ public void insertAll(List<E> entries) { - if (!initialized && entries.size() > 0) { + if(!initialized && entries.size() > 0) { initialize(entries.get(0)); } - for (E entry : entries) { + for(E entry : entries) { insert(entry, false); } } @@ -236,9 +227,9 @@ public abstract class AbstractMTree<O, D extends NumberDistance<D, ?>, N extends protected final List<DoubleIntPair> getSortedEntries(N node, DBID q) { List<DoubleIntPair> result = new ArrayList<>(); - for (int i = 0; i < node.getNumEntries(); i++) { + for(int i = 0; i < node.getNumEntries(); i++) { E entry = node.getEntry(i); - double distance = distance(entry.getRoutingObjectID(), q).doubleValue(); + double distance = distance(entry.getRoutingObjectID(), q); double radius = entry.getCoveringRadius(); double minDist = (radius > distance) ? 0.0 : distance - radius; @@ -256,7 +247,7 @@ public abstract class AbstractMTree<O, D extends NumberDistance<D, ?>, N extends * @param id2 the second id * @return the distance between the two specified ids */ - public abstract D distance(DBIDRef id1, DBIDRef id2); + public abstract double distance(DBIDRef id1, DBIDRef id2); /** * Returns the distance between the routing object of two entries. @@ -265,7 +256,7 @@ public abstract class AbstractMTree<O, D extends NumberDistance<D, ?>, N extends * @param e2 Second entry * @return the distance between the two routing objects */ - public final D distance(E e1, E e2) { + public final double distance(E e1, E e2) { return distance(e1.getRoutingObjectID(), e2.getRoutingObjectID()); } @@ -286,7 +277,7 @@ public abstract class AbstractMTree<O, D extends NumberDistance<D, ?>, N extends * @param subtree the subtree to be adjusted */ private void adjustTree(IndexTreePath<E> subtree) { - if (getLogger().isDebugging()) { + if(getLogger().isDebugging()) { getLogger().debugFine("Adjust tree " + subtree + "\n"); } @@ -295,7 +286,7 @@ public abstract class AbstractMTree<O, D extends NumberDistance<D, ?>, N extends N node = getNode(subtree.getLastPathComponent().getEntry()); // overflow in node; split the node - if (hasOverflow(node)) { + if(hasOverflow(node)) { // do the split Assignments<E> assignments = settings.splitStrategy.split(this, node); final N newNode = node.isLeaf() ? createNewLeafNode() : createNewDirectoryNode(); @@ -303,12 +294,12 @@ public abstract class AbstractMTree<O, D extends NumberDistance<D, ?>, N extends List<E> entries1 = new ArrayList<>(assignments.getFirstAssignments().size()); List<E> entries2 = new ArrayList<>(assignments.getSecondAssignments().size()); // Store final parent distances: - for (DistanceEntry<E> ent : assignments.getFirstAssignments()) { + for(DistanceEntry<E> ent : assignments.getFirstAssignments()) { final E e = ent.getEntry(); e.setParentDistance(ent.getDistance()); entries1.add(e); } - for (DistanceEntry<E> ent : assignments.getSecondAssignments()) { + for(DistanceEntry<E> ent : assignments.getSecondAssignments()) { final E e = ent.getEntry(); e.setParentDistance(ent.getDistance()); entries2.add(e); @@ -319,14 +310,14 @@ public abstract class AbstractMTree<O, D extends NumberDistance<D, ?>, N extends writeNode(node); writeNode(newNode); - if (getLogger().isDebugging()) { + if(getLogger().isDebugging()) { String msg = "Split Node " + node.getPageID() + " (" + this.getClass() + ")\n" + " newNode " + newNode.getPageID() + "\n" + " firstPromoted " + assignments.getFirstRoutingObject() + "\n" + " firstAssignments(" + node.getPageID() + ") " + assignments.getFirstAssignments() + "\n" + " firstCR " + assignments.getFirstCoveringRadius() + "\n" + " secondPromoted " + assignments.getSecondRoutingObject() + "\n" + " secondAssignments(" + newNode.getPageID() + ") " + assignments.getSecondAssignments() + "\n" + " secondCR " + assignments.getSecondCoveringRadius() + "\n"; getLogger().debugFine(msg); } // if root was split: create a new root that points the two split // nodes - if (isRoot(node)) { + if(isRoot(node)) { // FIXME: stimmen die parentDistance der Kinder in node & splitNode? IndexTreePath<E> newRootPath = createNewRoot(node, newNode, assignments.getFirstRoutingObject(), assignments.getSecondRoutingObject()); adjustTree(newRootPath); @@ -336,16 +327,16 @@ public abstract class AbstractMTree<O, D extends NumberDistance<D, ?>, N extends // get the parent and add the new split node E parentEntry = subtree.getParentPath().getLastPathComponent().getEntry(); N parent = getNode(parentEntry); - if (getLogger().isDebugging()) { + if(getLogger().isDebugging()) { getLogger().debugFine("parent " + parent); } - double parentDistance2 = distance(parentEntry.getRoutingObjectID(), assignments.getSecondRoutingObject()).doubleValue(); + double parentDistance2 = distance(parentEntry.getRoutingObjectID(), assignments.getSecondRoutingObject()); // logger.warning("parent: "+parent.toString()+" split: " + // splitNode.toString()+ " dist:"+parentDistance2); parent.addDirectoryEntry(createNewDirectoryEntry(newNode, assignments.getSecondRoutingObject(), parentDistance2)); // adjust the entry representing the (old) node, that has been split - double parentDistance1 = distance(parentEntry.getRoutingObjectID(), assignments.getFirstRoutingObject()).doubleValue(); + double parentDistance1 = distance(parentEntry.getRoutingObjectID(), assignments.getFirstRoutingObject()); // logger.warning("parent: "+parent.toString()+" node: " + // node.toString()+ " dist:"+parentDistance1); node.adjustEntry(parent.getEntry(nodeIndex), assignments.getFirstRoutingObject(), parentDistance1, this); @@ -358,7 +349,7 @@ public abstract class AbstractMTree<O, D extends NumberDistance<D, ?>, N extends // no overflow, only adjust parameters of the entry representing the // node else { - if (!isRoot(node)) { + if(!isRoot(node)) { E parentEntry = subtree.getParentPath().getLastPathComponent().getEntry(); N parent = getNode(parentEntry); int index = subtree.getLastPathComponent().getIndex(); @@ -385,7 +376,7 @@ public abstract class AbstractMTree<O, D extends NumberDistance<D, ?>, N extends * otherwise */ private boolean hasOverflow(N node) { - if (node.isLeaf()) { + if(node.isLeaf()) { return node.getNumEntries() == leafCapacity; } @@ -411,9 +402,9 @@ public abstract class AbstractMTree<O, D extends NumberDistance<D, ?>, N extends // switch the ids oldRoot.setPageID(root.getPageID()); - if (!oldRoot.isLeaf()) { + if(!oldRoot.isLeaf()) { // FIXME: what is happening here? - for (int i = 0; i < oldRoot.getNumEntries(); i++) { + for(int i = 0; i < oldRoot.getNumEntries(); i++) { N node = getNode(oldRoot.getEntry(i)); writeNode(node); } @@ -437,7 +428,7 @@ public abstract class AbstractMTree<O, D extends NumberDistance<D, ?>, N extends writeNode(root); writeNode(oldRoot); writeNode(newNode); - if (getLogger().isDebugging()) { + if(getLogger().isDebugging()) { String msg = "Create new Root: ID=" + root.getPageID(); msg += "\nchild1 " + oldRoot; msg += "\nchild2 " + newNode; @@ -451,13 +442,13 @@ public abstract class AbstractMTree<O, D extends NumberDistance<D, ?>, N extends public List<E> getLeaves() { List<E> result = new ArrayList<>(); BreadthFirstEnumeration<N, E> enumeration = new BreadthFirstEnumeration<>(this, getRootPath()); - while (enumeration.hasMoreElements()) { + while(enumeration.hasMoreElements()) { IndexTreePath<E> path = enumeration.nextElement(); E entry = path.getLastPathComponent().getEntry(); - if (!entry.isLeafEntry()) { + if(!entry.isLeafEntry()) { // TODO: any way to skip unnecessary reads? N node = getNode(entry); - if (node.isLeaf()) { + if(node.isLeaf()) { result.add(entry); } } @@ -474,8 +465,8 @@ public abstract class AbstractMTree<O, D extends NumberDistance<D, ?>, N extends int levels = 0; N node = getRoot(); - while (!node.isLeaf()) { - if (node.getNumEntries() > 0) { + while(!node.isLeaf()) { + if(node.getNumEntries() > 0) { E entry = node.getEntry(0); node = getNode(entry); levels++; @@ -488,7 +479,7 @@ public abstract class AbstractMTree<O, D extends NumberDistance<D, ?>, N extends public void logStatistics() { super.logStatistics(); Logging log = getLogger(); - if (log.isStatistics()) { + if(log.isStatistics()) { log.statistics(new LongStatistic(this.getClass().getName() + ".height", getHeight())); statistics.logStatistics(); } @@ -532,7 +523,7 @@ public abstract class AbstractMTree<O, D extends NumberDistance<D, ?>, N extends * Count a distance computation. */ public void countDistanceCalculation() { - if (distanceCalcs != null) { + if(distanceCalcs != null) { distanceCalcs.increment(); } } @@ -541,7 +532,7 @@ public abstract class AbstractMTree<O, D extends NumberDistance<D, ?>, N extends * Count a knn query invocation. */ public void countKNNQuery() { - if (knnQueries != null) { + if(knnQueries != null) { knnQueries.increment(); } } @@ -550,7 +541,7 @@ public abstract class AbstractMTree<O, D extends NumberDistance<D, ?>, N extends * Count a range query invocation. */ public void countRangeQuery() { - if (rangeQueries != null) { + if(rangeQueries != null) { rangeQueries.increment(); } } @@ -560,13 +551,13 @@ public abstract class AbstractMTree<O, D extends NumberDistance<D, ?>, N extends */ public void logStatistics() { Logging log = getLogger(); - if (statistics.distanceCalcs != null) { + if(statistics.distanceCalcs != null) { log.statistics(statistics.distanceCalcs); } - if (statistics.knnQueries != null) { + if(statistics.knnQueries != null) { log.statistics(statistics.knnQueries); } - if (statistics.rangeQueries != null) { + if(statistics.rangeQueries != null) { log.statistics(statistics.rangeQueries); } } diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTreeFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTreeFactory.java index 7a0baa8a..458bf96b 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTreeFactory.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTreeFactory.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -26,7 +26,6 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants; import de.lmu.ifi.dbs.elki.data.type.TypeInformation; import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.Index; import de.lmu.ifi.dbs.elki.index.PagedIndexFactory; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.insert.MTreeInsert; @@ -48,12 +47,11 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter; * @apiviz.excludeSubtypes * * @param <O> Object type - * @param <D> Distance type * @param <N> Node type * @param <E> Entry type * @param <I> Index type */ -public abstract class AbstractMTreeFactory<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry, I extends AbstractMTree<O, D, N, E, S> & Index, S extends MTreeSettings<O, D, N, E>> extends PagedIndexFactory<O, I> { +public abstract class AbstractMTreeFactory<O, N extends AbstractMTreeNode<O, N, E>, E extends MTreeEntry, I extends AbstractMTree<O, N, E, S> & Index, S extends MTreeSettings<O, N, E>> extends PagedIndexFactory<O, I> { /** * Tree settings. */ @@ -82,7 +80,7 @@ public abstract class AbstractMTreeFactory<O, D extends NumberDistance<D, ?>, N * * @apiviz.exclude */ - public abstract static class Parameterizer<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry, S extends MTreeSettings<O, D, N, E>> extends PagedIndexFactory.Parameterizer<O> { + public abstract static class Parameterizer<O, N extends AbstractMTreeNode<O, N, E>, E extends MTreeEntry, S extends MTreeSettings<O, N, E>> extends PagedIndexFactory.Parameterizer<O> { /** * Parameter to specify the distance function to determine the distance * between database objects, must extend @@ -122,15 +120,15 @@ public abstract class AbstractMTreeFactory<O, D extends NumberDistance<D, ?>, N protected void makeOptions(Parameterization config) { super.makeOptions(config); settings = makeSettings(); - ObjectParameter<DistanceFunction<O, D>> distanceFunctionP = new ObjectParameter<>(DISTANCE_FUNCTION_ID, DistanceFunction.class, EuclideanDistanceFunction.class); + ObjectParameter<DistanceFunction<O>> distanceFunctionP = new ObjectParameter<>(DISTANCE_FUNCTION_ID, DistanceFunction.class, EuclideanDistanceFunction.class); if (config.grab(distanceFunctionP)) { settings.distanceFunction = distanceFunctionP.instantiateClass(config); } - ObjectParameter<MTreeSplit<O, D, N, E>> splitStrategyP = new ObjectParameter<>(SPLIT_STRATEGY_ID, MTreeSplit.class, MMRadSplit.class); + ObjectParameter<MTreeSplit<O, N, E>> splitStrategyP = new ObjectParameter<>(SPLIT_STRATEGY_ID, MTreeSplit.class, MMRadSplit.class); if (config.grab(splitStrategyP)) { settings.splitStrategy = splitStrategyP.instantiateClass(config); } - ObjectParameter<MTreeInsert<O, D, N, E>> insertStrategyP = new ObjectParameter<>(INSERT_STRATEGY_ID, MTreeInsert.class, MinimumEnlargementInsert.class); + ObjectParameter<MTreeInsert<O, N, E>> insertStrategyP = new ObjectParameter<>(INSERT_STRATEGY_ID, MTreeInsert.class, MinimumEnlargementInsert.class); if (config.grab(insertStrategyP)) { settings.insertStrategy = insertStrategyP.instantiateClass(config); } @@ -139,6 +137,6 @@ public abstract class AbstractMTreeFactory<O, D extends NumberDistance<D, ?>, N abstract protected S makeSettings(); @Override - protected abstract AbstractMTreeFactory<O, D, N, E, ?, ?> makeInstance(); + protected abstract AbstractMTreeFactory<O, N, E, ?, ?> makeInstance(); } } diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTreeNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTreeNode.java index 1c1f486c..98b51b44 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTreeNode.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/AbstractMTreeNode.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -26,7 +26,6 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants; import java.util.logging.Logger; import de.lmu.ifi.dbs.elki.database.ids.DBID; -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.tree.AbstractNode; import de.lmu.ifi.dbs.elki.logging.LoggingConfiguration; @@ -39,11 +38,10 @@ import de.lmu.ifi.dbs.elki.logging.LoggingConfiguration; * @apiviz.excludeSubtypes * * @param <O> the type of DatabaseObject to be stored in the M-Tree - * @param <D> the type of Distance used in the M-Tree * @param <N> the type of AbstractMTreeNode used in the M-Tree * @param <E> the type of MetricalEntry used in the M-Tree */ -public abstract class AbstractMTreeNode<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry> extends AbstractNode<E> { +public abstract class AbstractMTreeNode<O, N extends AbstractMTreeNode<O, N, E>, E extends MTreeEntry> extends AbstractNode<E> { /** * Empty constructor for Externalizable interface. */ @@ -73,14 +71,14 @@ public abstract class AbstractMTreeNode<O, D extends NumberDistance<D, ?>, N ext * the routing object of the parent node * @param mTree the M-Tree object holding this node */ - public void adjustEntry(E entry, DBID routingObjectID, double parentDistance, AbstractMTree<O, D, N, E, ?> mTree) { + public void adjustEntry(E entry, DBID routingObjectID, double parentDistance, AbstractMTree<O, N, E, ?> mTree) { entry.setRoutingObjectID(routingObjectID); entry.setParentDistance(parentDistance); entry.setCoveringRadius(coveringRadius(entry.getRoutingObjectID(), mTree)); for (int i = 0; i < getNumEntries(); i++) { E childEntry = getEntry(i); - double dist = mTree.distance(routingObjectID, childEntry.getRoutingObjectID()).doubleValue(); + double dist = mTree.distance(routingObjectID, childEntry.getRoutingObjectID()); childEntry.setParentDistance(dist); } } @@ -92,11 +90,11 @@ public abstract class AbstractMTreeNode<O, D extends NumberDistance<D, ?>, N ext * @param mTree the M-Tree * @return the covering radius of this node */ - public double coveringRadius(DBID routingObjectID, AbstractMTree<O, D, N, E, ?> mTree) { + public double coveringRadius(DBID routingObjectID, AbstractMTree<O, N, E, ?> mTree) { double coveringRadius = 0.; for (int i = 0; i < getNumEntries(); i++) { E entry = getEntry(i); - double distance = mTree.distance(entry.getRoutingObjectID(), routingObjectID).doubleValue() + entry.getCoveringRadius(); + double distance = mTree.distance(entry.getRoutingObjectID(), routingObjectID) + entry.getCoveringRadius(); coveringRadius = Math.max(coveringRadius, distance); } return coveringRadius; @@ -109,7 +107,7 @@ public abstract class AbstractMTreeNode<O, D extends NumberDistance<D, ?>, N ext * @param entry the entry representing this node */ @SuppressWarnings("unchecked") - public final void integrityCheck(AbstractMTree<O, D, N, E, ?> mTree, E entry) { + public final void integrityCheck(AbstractMTree<O, N, E, ?> mTree, E entry) { // leaf node if (isLeaf()) { for (int i = 0; i < getCapacity(); i++) { @@ -174,10 +172,10 @@ public abstract class AbstractMTreeNode<O, D extends NumberDistance<D, ?>, N ext * @param index the index of the entry in the parents child arry * @param mTree the M-Tree holding this node */ - protected void integrityCheckParameters(E parentEntry, N parent, int index, AbstractMTree<O, D, N, E, ?> mTree) { + protected void integrityCheckParameters(E parentEntry, N parent, int index, AbstractMTree<O, N, E, ?> mTree) { // test if parent distance is correctly set E entry = parent.getEntry(index); - double parentDistance = mTree.distance(entry.getRoutingObjectID(), parentEntry.getRoutingObjectID()).doubleValue(); + double parentDistance = mTree.distance(entry.getRoutingObjectID(), parentEntry.getRoutingObjectID()); if (Math.abs(entry.getParentDistance() - parentDistance) > 1E-10) { throw new RuntimeException("Wrong parent distance in node " + parent.getPageID() + " at index " + index + " (child " + entry + ")" + "\nsoll: " + parentDistance + ",\n ist: " + entry.getParentDistance()); } diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeDirectoryEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeDirectoryEntry.java index 92d0a7ea..ea2cd416 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeDirectoryEntry.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeDirectoryEntry.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -66,7 +66,7 @@ public class MTreeDirectoryEntry extends AbstractDirectoryEntry implements MTree } /** - * Provides a new MTreeDirectoryEntry with the given parameters. + * Constructor. * * @param objectID the id of the routing object * @param parentDistance the distance from the routing object of this entry to diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeEntry.java index 66628087..ebae6a4f 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeEntry.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeEntry.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeLeafEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeLeafEntry.java index cfb22bac..c53cc4d6 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeLeafEntry.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeLeafEntry.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -58,7 +58,7 @@ public class MTreeLeafEntry extends AbstractLeafEntry implements MTreeEntry { } /** - * Provides a new MTreeLeafEntry object with the given parameters. + * Constructor. * * @param objectID the id of the underlying data object * @param parentDistance the distance from the underlying data object to its diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeSettings.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeSettings.java index 59f6e598..46a0851a 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeSettings.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/MTreeSettings.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -24,7 +24,6 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants; */ import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.insert.MTreeInsert; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.split.MTreeSplit; @@ -34,23 +33,22 @@ import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.split.MT * @author Erich Schubert * * @param <O> Object type - * @param <D> Distance type * @param <N> Node type * @param <E> Entry type */ -public class MTreeSettings<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry> { +public class MTreeSettings<O, N extends AbstractMTreeNode<O, N, E>, E extends MTreeEntry> { /** * Holds the instance of the trees distance function. */ - protected DistanceFunction<? super O, D> distanceFunction; + protected DistanceFunction<? super O> distanceFunction; /** * Splitting strategy. */ - protected MTreeSplit<O, D, N, E> splitStrategy; + protected MTreeSplit<O, N, E> splitStrategy; /** * Insertion strategy. */ - protected MTreeInsert<O, D, N, E> insertStrategy; + protected MTreeInsert<O, N, E> insertStrategy; } diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTree.java index aec4410e..2f71f540 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTree.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTree.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -31,12 +31,11 @@ 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.distance.DistanceDBIDList; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList; +import de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDList; +import de.lmu.ifi.dbs.elki.database.ids.KNNList; import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery; import de.lmu.ifi.dbs.elki.database.relation.Relation; -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry; @@ -51,21 +50,20 @@ import de.lmu.ifi.dbs.elki.persistent.PageFile; * * @author Elke Achtert * @param <O> the type of DatabaseObject to be stored in the metrical index - * @param <D> the type of Distance used in the metrical index * @param <N> the type of MetricalNode used in the metrical index * @param <E> the type of MetricalEntry used in the metrical index * @param <S> the type of Settings kept. */ -public abstract class AbstractMkTree<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry, S extends MTreeSettings<O, D, N, E>> extends AbstractMTree<O, D, N, E, S> { +public abstract class AbstractMkTree<O, N extends AbstractMTreeNode<O, N, E>, E extends MTreeEntry, S extends MTreeSettings<O, N, E>> extends AbstractMTree<O, N, E, S> { /** * Internal class for performing knn queries */ - protected KNNQuery<O, D> knnq; + protected KNNQuery<O> knnq; /** * Distance query to use. */ - private DistanceQuery<O, D> distanceQuery; + private DistanceQuery<O> distanceQuery; /** * Constructor. @@ -82,9 +80,9 @@ public abstract class AbstractMkTree<O, D extends NumberDistance<D, ?>, N extend } @Override - public D distance(DBIDRef id1, DBIDRef id2) { - if (id1 == null || id2 == null) { - return getDistanceFactory().undefinedDistance(); + public double distance(DBIDRef id1, DBIDRef id2) { + if(id1 == null || id2 == null) { + return Double.NaN; } statistics.countDistanceCalculation(); return distanceQuery.distance(id1, id2); @@ -98,7 +96,7 @@ public abstract class AbstractMkTree<O, D extends NumberDistance<D, ?>, N extend * @param k the number of nearest neighbors to be returned * @return a List of the query results */ - public abstract DistanceDBIDList<D> reverseKNNQuery(final DBIDRef id, int k); + public abstract DoubleDBIDList reverseKNNQuery(final DBIDRef id, int k); /** * Performs a batch k-nearest neighbor query for a list of query objects. @@ -111,9 +109,9 @@ public abstract class AbstractMkTree<O, D extends NumberDistance<D, ?>, N extend * @deprecated Change to use by-object NN lookups instead. */ @Deprecated - protected final Map<DBID, KNNList<D>> batchNN(N node, DBIDs ids, int kmax) { - Map<DBID, KNNList<D>> res = new HashMap<>(ids.size()); - for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { + protected final Map<DBID, KNNList> batchNN(N node, DBIDs ids, int kmax) { + Map<DBID, KNNList> res = new HashMap<>(ids.size()); + for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { DBID id = DBIDUtil.deref(iter); res.put(id, knnq.getKNNForDBID(id, kmax)); } diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTreeUnified.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTreeUnified.java index 455d372a..4c43e667 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTreeUnified.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTreeUnified.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -28,10 +28,9 @@ import java.util.Map; import de.lmu.ifi.dbs.elki.database.ids.DBID; import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil; +import de.lmu.ifi.dbs.elki.database.ids.KNNList; import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList; import de.lmu.ifi.dbs.elki.database.relation.Relation; -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.tree.TreeIndexHeader; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry; @@ -48,12 +47,11 @@ import de.lmu.ifi.dbs.elki.persistent.PageFile; * @apiviz.composedOf MkTreeSettings * * @param <O> the type of DatabaseObject to be stored in the metrical index - * @param <D> the type of Distance used in the metrical index * @param <N> the type of MetricalNode used in the metrical index * @param <E> the type of MetricalEntry used in the metrical index * @param <S> the type of Settings used. */ -public abstract class AbstractMkTreeUnified<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry, S extends MkTreeSettings<O, D, N, E>> extends AbstractMkTree<O, D, N, E, S> { +public abstract class AbstractMkTreeUnified<O, N extends AbstractMTreeNode<O, N, E>, E extends MTreeEntry, S extends MkTreeSettings<O, N, E>> extends AbstractMkTree<O, N, E, S> { /** * Constructor. * @@ -92,7 +90,7 @@ public abstract class AbstractMkTreeUnified<O, D extends NumberDistance<D, ?>, N } // do batch nn - Map<DBID, KNNList<D>> knnLists = batchNN(getRoot(), ids, settings.k_max); + Map<DBID, KNNList> knnLists = batchNN(getRoot(), ids, settings.k_max); // adjust the knn distances kNNdistanceAdjustment(getRootEntry(), knnLists); @@ -108,7 +106,7 @@ public abstract class AbstractMkTreeUnified<O, D extends NumberDistance<D, ?>, N * @param entry the root entry of the current subtree * @param knnLists a map of knn lists for each leaf entry */ - protected abstract void kNNdistanceAdjustment(E entry, Map<DBID, KNNList<D>> knnLists); + protected abstract void kNNdistanceAdjustment(E entry, Map<DBID, KNNList> knnLists); /** * Get the value of k_max. diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTreeUnifiedFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTreeUnifiedFactory.java index 996b2438..9997713d 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTreeUnifiedFactory.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/AbstractMkTreeUnifiedFactory.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,7 +23,6 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.Index; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeFactory; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode; @@ -43,12 +42,11 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter; * @apiviz.uses AbstractMkTreeUnified oneway - - «create» * * @param <O> Object type - * @param <D> Distance type * @param <N> Node type * @param <E> Entry type * @param <I> Index type */ -public abstract class AbstractMkTreeUnifiedFactory<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry, I extends AbstractMkTree<O, D, N, E, S> & Index, S extends MkTreeSettings<O, D, N, E>> extends AbstractMTreeFactory<O, D, N, E, I, S> { +public abstract class AbstractMkTreeUnifiedFactory<O, N extends AbstractMTreeNode<O, N, E>, E extends MTreeEntry, I extends AbstractMkTree<O, N, E, S> & Index, S extends MkTreeSettings<O, N, E>> extends AbstractMTreeFactory<O, N, E, I, S> { /** * Constructor. * @@ -66,7 +64,7 @@ public abstract class AbstractMkTreeUnifiedFactory<O, D extends NumberDistance<D * * @apiviz.exclude */ - public abstract static class Parameterizer<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry, S extends MkTreeSettings<O, D, N, E>> extends AbstractMTreeFactory.Parameterizer<O, D, N, E, S> { + public abstract static class Parameterizer<O, N extends AbstractMTreeNode<O, N, E>, E extends MTreeEntry, S extends MkTreeSettings<O, N, E>> extends AbstractMTreeFactory.Parameterizer<O, N, E, S> { /** * Parameter specifying the maximal number k of reverse k nearest neighbors * to be supported, must be an integer greater than 0. @@ -88,6 +86,6 @@ public abstract class AbstractMkTreeUnifiedFactory<O, D extends NumberDistance<D } @Override - protected abstract AbstractMkTreeUnifiedFactory<O, D, N, E, ?, S> makeInstance(); + protected abstract AbstractMkTreeUnifiedFactory<O, N, E, ?, S> makeInstance(); } } diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/MkTreeHeader.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/MkTreeHeader.java index ff49d789..47f0eda0 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/MkTreeHeader.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/MkTreeHeader.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/MkTreeSettings.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/MkTreeSettings.java index 6a957bd7..8d5fa450 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/MkTreeSettings.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/MkTreeSettings.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,7 +23,6 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeSettings; @@ -34,11 +33,10 @@ import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeSettings; * @author Erich Schubert * * @param <O> Object type - * @param <D> Distance type * @param <N> Node type * @param <E> Entry type */ -public class MkTreeSettings<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry> extends MTreeSettings<O, D, N, E> { +public class MkTreeSettings<O, N extends AbstractMTreeNode<O, N, E>, E extends MTreeEntry> extends MTreeSettings<O, N, E> { /** * Holds the maximum value of k to support. */ diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppDirectoryEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppDirectoryEntry.java index fd6f6bab..89d0cba1 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppDirectoryEntry.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppDirectoryEntry.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkapp; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -56,7 +56,7 @@ class MkAppDirectoryEntry extends MTreeDirectoryEntry implements MkAppEntry { } /** - * Provides a new MkCoPDirectoryEntry with the given parameters. + * Constructor. * * @param objectID the id of the routing object * @param parentDistance the distance from the object to its parent diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppEntry.java index 5424f6f1..54cfcc29 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppEntry.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppEntry.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkapp; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppLeafEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppLeafEntry.java index e1f2305a..c2f81af2 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppLeafEntry.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppLeafEntry.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkapp; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -56,7 +56,7 @@ class MkAppLeafEntry extends MTreeLeafEntry implements MkAppEntry { } /** - * Provides a new MkAppLeafEntry with the given parameters. + * Constructor. * * @param objectID the id of the underlying data object * @param parentDistance the distance from the underlying data object to its diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTree.java index 1ff0a030..41a83fcf 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTree.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTree.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkapp; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,7 +23,6 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkapp; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -33,22 +32,21 @@ 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.DoubleDBIDList; +import de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDListIter; +import de.lmu.ifi.dbs.elki.database.ids.KNNList; import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs; -import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList; -import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList; -import de.lmu.ifi.dbs.elki.database.ids.generic.GenericDistanceDBIDList; +import de.lmu.ifi.dbs.elki.database.ids.ModifiableDoubleDBIDList; import de.lmu.ifi.dbs.elki.database.relation.Relation; -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.tree.LeafEntry; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.AbstractMkTree; import de.lmu.ifi.dbs.elki.index.tree.query.GenericMTreeDistanceSearchCandidate; import de.lmu.ifi.dbs.elki.logging.Logging; import de.lmu.ifi.dbs.elki.math.statistics.PolynomialRegression; -import de.lmu.ifi.dbs.elki.persistent.ByteArrayUtil; import de.lmu.ifi.dbs.elki.persistent.PageFile; import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.Heap; import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.UpdatableHeap; +import de.lmu.ifi.dbs.elki.utilities.io.ByteArrayUtil; /** * MkAppTree is a metrical index structure based on the concepts of the M-Tree @@ -61,9 +59,8 @@ import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.UpdatableHeap; * @apiviz.has MkAppTreeNode oneway - - contains * * @param <O> the type of DatabaseObject to be stored in the metrical index - * @param <D> the type of NumberDistance used in the metrical index */ -public class MkAppTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree<O, D, MkAppTreeNode<O, D>, MkAppEntry, MkAppTreeSettings<O, D>> { +public class MkAppTree<O> extends AbstractMkTree<O, MkAppTreeNode<O>, MkAppEntry, MkAppTreeSettings<O>> { /** * The logger for this class. */ @@ -76,7 +73,7 @@ public class MkAppTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree * @param pageFile Page file * @param settings Tree settings */ - public MkAppTree(Relation<O> relation, PageFile<MkAppTreeNode<O, D>> pageFile, MkAppTreeSettings<O, D> settings) { + public MkAppTree(Relation<O> relation, PageFile<MkAppTreeNode<O>> pageFile, MkAppTreeSettings<O> settings) { super(relation, pageFile, settings); } @@ -103,34 +100,34 @@ public class MkAppTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree */ @Override public void insertAll(List<MkAppEntry> entries) { - if (entries.isEmpty()) { + if(entries.isEmpty()) { return; } - if (LOG.isDebugging()) { + if(LOG.isDebugging()) { LOG.debugFine("insert " + entries + "\n"); } - if (!initialized) { + if(!initialized) { initialize(entries.get(0)); } ModifiableDBIDs ids = DBIDUtil.newArray(entries.size()); // insert - for (MkAppEntry entry : entries) { + for(MkAppEntry entry : entries) { ids.add(entry.getRoutingObjectID()); // insert the object super.insert(entry, false); } // do batch nn - Map<DBID, KNNList<D>> knnLists = batchNN(getRoot(), ids, settings.k_max + 1); + Map<DBID, KNNList> knnLists = batchNN(getRoot(), ids, settings.k_max + 1); // adjust the knn distances adjustApproximatedKNNDistances(getRootEntry(), knnLists); - if (EXTRA_INTEGRITY_CHECKS) { + if(EXTRA_INTEGRITY_CHECKS) { getRoot().integrityCheck(this, getRootEntry()); } } @@ -144,49 +141,48 @@ public class MkAppTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree * @return a List of the query results */ @Override - public DistanceDBIDList<D> reverseKNNQuery(DBIDRef id, int k) { - GenericDistanceDBIDList<D> result = new GenericDistanceDBIDList<>(); + public DoubleDBIDList reverseKNNQuery(DBIDRef id, int k) { + ModifiableDoubleDBIDList result = DBIDUtil.newDistanceDBIDList(); final Heap<GenericMTreeDistanceSearchCandidate> pq = new UpdatableHeap<>(); // push root pq.add(new GenericMTreeDistanceSearchCandidate(0., getRootID(), null)); // search in tree - while (!pq.isEmpty()) { + while(!pq.isEmpty()) { GenericMTreeDistanceSearchCandidate pqNode = pq.poll(); // FIXME: cache the distance to the routing object in the queue node! - MkAppTreeNode<O, D> node = getNode(pqNode.nodeID); + MkAppTreeNode<O> node = getNode(pqNode.nodeID); // directory node - if (!node.isLeaf()) { - for (int i = 0; i < node.getNumEntries(); i++) { + if(!node.isLeaf()) { + for(int i = 0; i < node.getNumEntries(); i++) { MkAppEntry entry = node.getEntry(i); - double distance = distance(entry.getRoutingObjectID(), id).doubleValue(); + double distance = distance(entry.getRoutingObjectID(), id); double minDist = (entry.getCoveringRadius() > distance) ? 0. : distance - entry.getCoveringRadius(); double approxValue = settings.log ? Math.exp(entry.approximatedValueAt(k)) : entry.approximatedValueAt(k); - if (approxValue < 0) { + if(approxValue < 0) { approxValue = 0; } - if (minDist <= approxValue) { + if(minDist <= approxValue) { pq.add(new GenericMTreeDistanceSearchCandidate(minDist, getPageID(entry), entry.getRoutingObjectID())); } } } // data node else { - for (int i = 0; i < node.getNumEntries(); i++) { + for(int i = 0; i < node.getNumEntries(); i++) { MkAppLeafEntry entry = (MkAppLeafEntry) node.getEntry(i); - D distance = distance(entry.getRoutingObjectID(), id); + double distance = distance(entry.getRoutingObjectID(), id); double approxValue = settings.log ? StrictMath.exp(entry.approximatedValueAt(k)) : entry.approximatedValueAt(k); - if (approxValue < 0) { + if(approxValue < 0) { approxValue = 0; } - D approximatedKnnDist = getDistanceFactory().fromDouble(approxValue); - if (distance.compareTo(approximatedKnnDist) <= 0) { + if(distance <= approxValue) { result.add(distance, entry.getRoutingObjectID()); } } @@ -213,7 +209,7 @@ public class MkAppTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree // overhead = index(4), numEntries(4), id(4), isLeaf(0.125) double overhead = 12.125; - if (getPageSize() - overhead < 0) { + if(getPageSize() - overhead < 0) { throw new RuntimeException("Node size of " + getPageSize() + " Bytes is chosen too small!"); } @@ -221,11 +217,11 @@ public class MkAppTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree // coveringRadius + parentDistance + approx) + 1 dirCapacity = (int) (getPageSize() - overhead) / (4 + 4 + distanceSize + distanceSize + (settings.p + 1) * 4 + 2) + 1; - if (dirCapacity <= 1) { + if(dirCapacity <= 1) { throw new RuntimeException("Node size of " + getPageSize() + " Bytes is chosen too small!"); } - if (dirCapacity < 10) { + if(dirCapacity < 10) { LOG.warning("Page size is choosen too small! Maximum number of entries " + "in a directory node = " + (dirCapacity - 1)); } @@ -234,39 +230,37 @@ public class MkAppTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree // approx) + 1 leafCapacity = (int) (getPageSize() - overhead) / (4 + distanceSize + (settings.p + 1) * 4 + 2) + 1; - if (leafCapacity <= 1) { + if(leafCapacity <= 1) { throw new RuntimeException("Node size of " + getPageSize() + " Bytes is chosen too small!"); } - if (leafCapacity < 10) { + if(leafCapacity < 10) { LOG.warning("Page size is choosen too small! Maximum number of entries " + "in a leaf node = " + (leafCapacity - 1)); } initialized = true; - if (LOG.isVerbose()) { + if(LOG.isVerbose()) { LOG.verbose("Directory Capacity: " + (dirCapacity - 1) + "\nLeaf Capacity: " + (leafCapacity - 1)); } } - private List<D> getMeanKNNList(DBIDs ids, Map<DBID, KNNList<D>> knnLists) { + private double[] getMeanKNNList(DBIDs ids, Map<DBID, KNNList> knnLists) { double[] means = new double[settings.k_max]; - for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { + for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { DBID id = DBIDUtil.deref(iter); - KNNList<D> knns = knnLists.get(id); + KNNList knns = knnLists.get(id); int k = 0; - for (DistanceDBIDListIter<D> it = knns.iter(); k < settings.k_max && it.valid(); it.advance(), k++) { - means[k] += it.getDistance().doubleValue(); + for(DoubleDBIDListIter it = knns.iter(); k < settings.k_max && it.valid(); it.advance(), k++) { + means[k] += it.doubleValue(); } } - List<D> result = new ArrayList<>(); - for (int k = 0; k < settings.k_max; k++) { + for(int k = 0; k < settings.k_max; k++) { means[k] /= ids.size(); - result.add(getDistanceFactory().fromDouble(means[k])); } - return result; + return means; } /** @@ -275,19 +269,20 @@ public class MkAppTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree * @param entry the root entry of the current subtree * @param knnLists a map of knn lists for each leaf entry */ - private void adjustApproximatedKNNDistances(MkAppEntry entry, Map<DBID, KNNList<D>> knnLists) { - MkAppTreeNode<O, D> node = getNode(entry); + private void adjustApproximatedKNNDistances(MkAppEntry entry, Map<DBID, KNNList> knnLists) { + MkAppTreeNode<O> node = getNode(entry); - if (node.isLeaf()) { - for (int i = 0; i < node.getNumEntries(); i++) { + if(node.isLeaf()) { + for(int i = 0; i < node.getNumEntries(); i++) { MkAppLeafEntry leafEntry = (MkAppLeafEntry) node.getEntry(i); // approximateKnnDistances(leafEntry, // getKNNList(leafEntry.getRoutingObjectID(), knnLists)); PolynomialApproximation approx = approximateKnnDistances(getMeanKNNList(leafEntry.getDBID(), knnLists)); leafEntry.setKnnDistanceApproximation(approx); } - } else { - for (int i = 0; i < node.getNumEntries(); i++) { + } + else { + for(int i = 0; i < node.getNumEntries(); i++) { MkAppEntry dirEntry = node.getEntry(i); adjustApproximatedKNNDistances(dirEntry, knnLists); } @@ -307,15 +302,16 @@ public class MkAppTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree * @param result the result list containing the ids of the leaf entries stored * in the specified subtree */ - private void leafEntryIDs(MkAppTreeNode<O, D> node, ModifiableDBIDs result) { - if (node.isLeaf()) { - for (int i = 0; i < node.getNumEntries(); i++) { + private void leafEntryIDs(MkAppTreeNode<O> node, ModifiableDBIDs result) { + if(node.isLeaf()) { + for(int i = 0; i < node.getNumEntries(); i++) { MkAppEntry entry = node.getEntry(i); result.add(((LeafEntry) entry).getDBID()); } - } else { - for (int i = 0; i < node.getNumEntries(); i++) { - MkAppTreeNode<O, D> childNode = getNode(node.getEntry(i)); + } + else { + for(int i = 0; i < node.getNumEntries(); i++) { + MkAppTreeNode<O> childNode = getNode(node.getEntry(i)); leafEntryIDs(childNode, result); } } @@ -327,17 +323,18 @@ public class MkAppTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree * @param knnDistances the knn-distances of the leaf entry * @return the polynomial approximation of the specified knn-distances. */ - private PolynomialApproximation approximateKnnDistances(List<D> knnDistances) { + private PolynomialApproximation approximateKnnDistances(double[] knnDistances) { StringBuilder msg = new StringBuilder(); // count the zero distances (necessary of log-log space is used) int k_0 = 0; - if (settings.log) { - for (int i = 0; i < settings.k_max; i++) { - double dist = knnDistances.get(i).doubleValue(); - if (dist == 0) { + if(settings.log) { + for(int i = 0; i < settings.k_max; i++) { + double dist = knnDistances[i]; + if(dist == 0) { k_0++; - } else { + } + else { break; } } @@ -346,20 +343,21 @@ public class MkAppTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree de.lmu.ifi.dbs.elki.math.linearalgebra.Vector x = new de.lmu.ifi.dbs.elki.math.linearalgebra.Vector(settings.k_max - k_0); de.lmu.ifi.dbs.elki.math.linearalgebra.Vector y = new de.lmu.ifi.dbs.elki.math.linearalgebra.Vector(settings.k_max - k_0); - for (int k = 0; k < settings.k_max - k_0; k++) { - if (settings.log) { + for(int k = 0; k < settings.k_max - k_0; k++) { + if(settings.log) { x.set(k, Math.log(k + k_0)); - y.set(k, Math.log(knnDistances.get(k + k_0).doubleValue())); - } else { + y.set(k, Math.log(knnDistances[k + k_0])); + } + else { x.set(k, k + k_0); - y.set(k, knnDistances.get(k + k_0).doubleValue()); + y.set(k, knnDistances[k + k_0]); } } PolynomialRegression regression = new PolynomialRegression(y, x, settings.p); PolynomialApproximation approximation = new PolynomialApproximation(regression.getEstimatedCoefficients().getArrayCopy()); - if (LOG.isDebugging()) { + if(LOG.isDebugging()) { msg.append("approximation ").append(approximation); LOG.debugFine(msg.toString()); } @@ -373,7 +371,7 @@ public class MkAppTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree * @return a new leaf node */ @Override - protected MkAppTreeNode<O, D> createNewLeafNode() { + protected MkAppTreeNode<O> createNewLeafNode() { return new MkAppTreeNode<>(leafCapacity, true); } @@ -383,7 +381,7 @@ public class MkAppTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree * @return a new directory node */ @Override - protected MkAppTreeNode<O, D> createNewDirectoryNode() { + protected MkAppTreeNode<O> createNewDirectoryNode() { return new MkAppTreeNode<>(dirCapacity, false); } @@ -396,7 +394,7 @@ public class MkAppTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree * the routing object of the parent node */ @Override - protected MkAppEntry createNewDirectoryEntry(MkAppTreeNode<O, D> node, DBID routingObjectID, double parentDistance) { + protected MkAppEntry createNewDirectoryEntry(MkAppTreeNode<O> node, DBID routingObjectID, double parentDistance) { return new MkAppDirectoryEntry(routingObjectID, parentDistance, node.getPageID(), node.coveringRadius(routingObjectID, this), null); } diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeFactory.java index 1d4b7fe4..0bffdd29 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeFactory.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeFactory.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkapp; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -24,7 +24,6 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkapp; */ import de.lmu.ifi.dbs.elki.database.relation.Relation; -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeFactory; import de.lmu.ifi.dbs.elki.persistent.PageFile; import de.lmu.ifi.dbs.elki.persistent.PageFileFactory; @@ -44,9 +43,8 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter; * @apiviz.uses MkAppTreeIndex oneway - - «create» * * @param <O> Object type - * @param <D> Distance type */ -public class MkAppTreeFactory<O, D extends NumberDistance<D, ?>> extends AbstractMTreeFactory<O, D, MkAppTreeNode<O, D>, MkAppEntry, MkAppTreeIndex<O, D>, MkAppTreeSettings<O, D>> { +public class MkAppTreeFactory<O> extends AbstractMTreeFactory<O, MkAppTreeNode<O>, MkAppEntry, MkAppTreeIndex<O>, MkAppTreeSettings<O>> { /** * Parameter for nolog */ @@ -68,17 +66,17 @@ public class MkAppTreeFactory<O, D extends NumberDistance<D, ?>> extends Abstrac * @param pageFileFactory Data storage * @param settings Tree settings */ - public MkAppTreeFactory(PageFileFactory<?> pageFileFactory, MkAppTreeSettings<O, D> settings) { + public MkAppTreeFactory(PageFileFactory<?> pageFileFactory, MkAppTreeSettings<O> settings) { super(pageFileFactory, settings); } @Override - public MkAppTreeIndex<O, D> instantiate(Relation<O> relation) { - PageFile<MkAppTreeNode<O, D>> pagefile = makePageFile(getNodeClass()); + public MkAppTreeIndex<O> instantiate(Relation<O> relation) { + PageFile<MkAppTreeNode<O>> pagefile = makePageFile(getNodeClass()); return new MkAppTreeIndex<>(relation, pagefile, settings); } - protected Class<MkAppTreeNode<O, D>> getNodeClass() { + protected Class<MkAppTreeNode<O>> getNodeClass() { return ClassGenericsUtil.uglyCastIntoSubclass(MkAppTreeNode.class); } @@ -88,8 +86,10 @@ public class MkAppTreeFactory<O, D extends NumberDistance<D, ?>> extends Abstrac * @author Erich Schubert * * @apiviz.exclude + * + * @param <O> Object type */ - public static class Parameterizer<O, D extends NumberDistance<D, ?>> extends AbstractMTreeFactory.Parameterizer<O, D, MkAppTreeNode<O, D>, MkAppEntry, MkAppTreeSettings<O, D>> { + public static class Parameterizer<O> extends AbstractMTreeFactory.Parameterizer<O, MkAppTreeNode<O>, MkAppEntry, MkAppTreeSettings<O>> { @Override protected void makeOptions(Parameterization config) { super.makeOptions(config); @@ -112,12 +112,12 @@ public class MkAppTreeFactory<O, D extends NumberDistance<D, ?>> extends Abstrac } @Override - protected MkAppTreeFactory<O, D> makeInstance() { + protected MkAppTreeFactory<O> makeInstance() { return new MkAppTreeFactory<>(pageFileFactory, settings); } @Override - protected MkAppTreeSettings<O, D> makeSettings() { + protected MkAppTreeSettings<O> makeSettings() { return new MkAppTreeSettings<>(); } } diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeIndex.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeIndex.java index 2a630bf0..5db5d03c 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeIndex.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeIndex.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkapp; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -36,8 +36,6 @@ import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery; import de.lmu.ifi.dbs.elki.database.query.rknn.RKNNQuery; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.KNNIndex; import de.lmu.ifi.dbs.elki.index.RKNNIndex; import de.lmu.ifi.dbs.elki.index.RangeIndex; @@ -51,9 +49,8 @@ import de.lmu.ifi.dbs.elki.persistent.PageFile; * @author Erich Schubert * * @param <O> Object type - * @param <D> Distance type */ -public class MkAppTreeIndex<O, D extends NumberDistance<D, ?>> extends MkAppTree<O, D> implements RangeIndex<O>, KNNIndex<O>, RKNNIndex<O> { +public class MkAppTreeIndex<O> extends MkAppTree<O> implements RangeIndex<O>, KNNIndex<O>, RKNNIndex<O> { /** * The relation indexed */ @@ -66,7 +63,7 @@ public class MkAppTreeIndex<O, D extends NumberDistance<D, ?>> extends MkAppTree * @param pageFile Page file * @param settings Tree settings */ - public MkAppTreeIndex(Relation<O> relation, PageFile<MkAppTreeNode<O, D>> pageFile, MkAppTreeSettings<O, D> settings) { + public MkAppTreeIndex(Relation<O> relation, PageFile<MkAppTreeNode<O>> pageFile, MkAppTreeSettings<O> settings) { super(relation, pageFile, settings); this.relation = relation; } @@ -95,14 +92,13 @@ public class MkAppTreeIndex<O, D extends NumberDistance<D, ?>> extends MkAppTree insertAll(objs); } - @SuppressWarnings("unchecked") @Override - public <S extends Distance<S>> KNNQuery<O, S> getKNNQuery(DistanceQuery<O, S> distanceQuery, Object... hints) { + public KNNQuery<O> getKNNQuery(DistanceQuery<O> distanceQuery, Object... hints) { // Query on the relation we index if (distanceQuery.getRelation() != relation) { return null; } - DistanceFunction<? super O, D> distanceFunction = (DistanceFunction<? super O, D>) distanceQuery.getDistanceFunction(); + DistanceFunction<? super O> distanceFunction = (DistanceFunction<? super O>) distanceQuery.getDistanceFunction(); if (!this.getDistanceFunction().equals(distanceFunction)) { if (getLogger().isDebugging()) { getLogger().debug("Distance function not supported by index - or 'equals' not implemented right!"); @@ -115,18 +111,16 @@ public class MkAppTreeIndex<O, D extends NumberDistance<D, ?>> extends MkAppTree return null; } } - DistanceQuery<O, D> dq = distanceFunction.instantiate(relation); - return (KNNQuery<O, S>) MTreeQueryUtil.getKNNQuery(this, dq, hints); + return MTreeQueryUtil.getKNNQuery(this, distanceQuery, hints); } - @SuppressWarnings("unchecked") @Override - public <S extends Distance<S>> RangeQuery<O, S> getRangeQuery(DistanceQuery<O, S> distanceQuery, Object... hints) { + public RangeQuery<O> getRangeQuery(DistanceQuery<O> distanceQuery, Object... hints) { // Query on the relation we index if (distanceQuery.getRelation() != relation) { return null; } - DistanceFunction<? super O, D> distanceFunction = (DistanceFunction<? super O, D>) distanceQuery.getDistanceFunction(); + DistanceFunction<? super O> distanceFunction = (DistanceFunction<? super O>) distanceQuery.getDistanceFunction(); if (!this.getDistanceFunction().equals(distanceFunction)) { if (getLogger().isDebugging()) { getLogger().debug("Distance function not supported by index - or 'equals' not implemented right!"); @@ -139,14 +133,12 @@ public class MkAppTreeIndex<O, D extends NumberDistance<D, ?>> extends MkAppTree return null; } } - DistanceQuery<O, D> dq = distanceFunction.instantiate(relation); - return (RangeQuery<O, S>) MTreeQueryUtil.getRangeQuery(this, dq, hints); + return MTreeQueryUtil.getRangeQuery(this, distanceQuery, hints); } - @SuppressWarnings("unchecked") @Override - public <S extends Distance<S>> RKNNQuery<O, S> getRKNNQuery(DistanceQuery<O, S> distanceQuery, Object... hints) { - DistanceFunction<? super O, D> distanceFunction = (DistanceFunction<? super O, D>) distanceQuery.getDistanceFunction(); + public RKNNQuery<O> getRKNNQuery(DistanceQuery<O> distanceQuery, Object... hints) { + DistanceFunction<? super O> distanceFunction = (DistanceFunction<? super O>) distanceQuery.getDistanceFunction(); if (!this.getDistanceFunction().equals(distanceFunction)) { if (getLogger().isDebugging()) { getLogger().debug("Distance function not supported by index - or 'equals' not implemented right!"); @@ -159,8 +151,7 @@ public class MkAppTreeIndex<O, D extends NumberDistance<D, ?>> extends MkAppTree return null; } } - DistanceQuery<O, D> dq = distanceFunction.instantiate(relation); - return (RKNNQuery<O, S>) new MkTreeRKNNQuery<>(this, dq); + return (RKNNQuery<O>) new MkTreeRKNNQuery<>(this, distanceQuery); } @Override diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeNode.java index 29609274..e9eb66b3 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeNode.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeNode.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkapp; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -27,7 +27,6 @@ import java.util.Arrays; import java.util.logging.Logger; import de.lmu.ifi.dbs.elki.database.ids.DBID; -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode; import de.lmu.ifi.dbs.elki.logging.LoggingConfiguration; @@ -41,9 +40,8 @@ import de.lmu.ifi.dbs.elki.utilities.FormatUtil; * @apiviz.has MkAppEntry oneway - - contains * * @param <O> object type - * @param <D> distance type */ -class MkAppTreeNode<O, D extends NumberDistance<D, ?>> extends AbstractMTreeNode<O, D, MkAppTreeNode<O, D>, MkAppEntry> { +class MkAppTreeNode<O> extends AbstractMTreeNode<O, MkAppTreeNode<O>, MkAppEntry> { private static final long serialVersionUID = 2; /** @@ -92,7 +90,7 @@ class MkAppTreeNode<O, D extends NumberDistance<D, ?>> extends AbstractMTreeNode if(LoggingConfiguration.DEBUG) { StringBuilder msg = new StringBuilder(); - msg.append("b " + FormatUtil.format(b, 4)); + msg.append("b " + FormatUtil.format(b, FormatUtil.NF4)); Logger.getLogger(this.getClass().getName()).fine(msg.toString()); } @@ -109,13 +107,13 @@ class MkAppTreeNode<O, D extends NumberDistance<D, ?>> extends AbstractMTreeNode * @param mTree the M-Tree object holding this node */ @Override - public void adjustEntry(MkAppEntry entry, DBID routingObjectID, double parentDistance, AbstractMTree<O, D, MkAppTreeNode<O, D>, MkAppEntry, ?> mTree) { + public void adjustEntry(MkAppEntry entry, DBID routingObjectID, double parentDistance, AbstractMTree<O, MkAppTreeNode<O>, MkAppEntry, ?> mTree) { super.adjustEntry(entry, routingObjectID, parentDistance, mTree); // entry.setKnnDistanceApproximation(knnDistanceApproximation()); } @Override - protected void integrityCheckParameters(MkAppEntry parentEntry, MkAppTreeNode<O, D> parent, int index, AbstractMTree<O, D, MkAppTreeNode<O, D>, MkAppEntry, ?> mTree) { + protected void integrityCheckParameters(MkAppEntry parentEntry, MkAppTreeNode<O> parent, int index, AbstractMTree<O, MkAppTreeNode<O>, MkAppEntry, ?> mTree) { super.integrityCheckParameters(parentEntry, parent, index, mTree); MkAppEntry entry = parent.getEntry(index); diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeSettings.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeSettings.java index b9e0b8aa..3871586e 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeSettings.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/MkAppTreeSettings.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkapp; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,7 +23,6 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkapp; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.MkTreeSettings; /** @@ -32,9 +31,8 @@ import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.MkTreeSetti * @author Erich Schubert * * @param <O> Object type - * @param <D> Distance type */ -public class MkAppTreeSettings<O, D extends NumberDistance<D, ?>> extends MkTreeSettings<O, D, MkAppTreeNode<O, D>, MkAppEntry> { +public class MkAppTreeSettings<O> extends MkTreeSettings<O, MkAppTreeNode<O>, MkAppEntry> { /** * Parameter p. */ diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/PolynomialApproximation.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/PolynomialApproximation.java index f156c607..7d801a81 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/PolynomialApproximation.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/PolynomialApproximation.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkapp; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -28,7 +28,6 @@ import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectOutput; -import de.lmu.ifi.dbs.elki.math.MathUtil; import de.lmu.ifi.dbs.elki.utilities.FormatUtil; /** @@ -149,6 +148,6 @@ public class PolynomialApproximation implements Externalizable { */ @Override public String toString() { - return FormatUtil.format(b, 4); + return FormatUtil.format(b, FormatUtil.NF4); } } diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/package-info.java index 7b897fe3..c7597169 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkapp/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2013 +Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/ApproximationLine.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/ApproximationLine.java index 318c437b..bae501f3 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/ApproximationLine.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/ApproximationLine.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkcop; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/ConvexHull.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/ConvexHull.java index fe0e20b0..7cdb0728 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/ConvexHull.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/ConvexHull.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkcop; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPDirectoryEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPDirectoryEntry.java index 8b6282a3..aeb8e0ce 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPDirectoryEntry.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPDirectoryEntry.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkcop; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -56,7 +56,7 @@ class MkCoPDirectoryEntry extends MTreeDirectoryEntry implements MkCoPEntry { } /** - * Provides a new MkCoPDirectoryEntry with the given parameters. + * Constructor. * * @param objectID the id of the routing object * @param parentDistance the distance from the object to its parent diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPEntry.java index ae569d03..393a6c72 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPEntry.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPEntry.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkcop; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPLeafEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPLeafEntry.java index 7d241eba..b4b78ec5 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPLeafEntry.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPLeafEntry.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkcop; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -61,7 +61,7 @@ class MkCoPLeafEntry extends MTreeLeafEntry implements MkCoPEntry { } /** - * Provides a new MkCoPLeafEntry with the given parameters. + * Constructor. * * @param objectID the id of the underlying data object * @param parentDistance the distance from the underlying data object to its diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTree.java index b98d6821..126013b1 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTree.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTree.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkcop; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -31,21 +31,20 @@ 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.DoubleDBIDList; +import de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDListIter; +import de.lmu.ifi.dbs.elki.database.ids.KNNList; import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs; -import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList; -import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList; -import de.lmu.ifi.dbs.elki.database.ids.generic.GenericDistanceDBIDList; +import de.lmu.ifi.dbs.elki.database.ids.ModifiableDoubleDBIDList; import de.lmu.ifi.dbs.elki.database.relation.Relation; -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.AbstractMkTree; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.MkTreeSettings; import de.lmu.ifi.dbs.elki.index.tree.query.GenericMTreeDistanceSearchCandidate; import de.lmu.ifi.dbs.elki.logging.Logging; -import de.lmu.ifi.dbs.elki.persistent.ByteArrayUtil; import de.lmu.ifi.dbs.elki.persistent.PageFile; import de.lmu.ifi.dbs.elki.utilities.FormatUtil; import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.ComparableMinHeap; +import de.lmu.ifi.dbs.elki.utilities.io.ByteArrayUtil; /** * MkCopTree is a metrical index structure based on the concepts of the M-Tree @@ -58,9 +57,8 @@ import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.ComparableMinHeap; * @apiviz.has ConvexHull * * @param <O> Object type - * @param <D> Distance type */ -public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree<O, D, MkCoPTreeNode<O, D>, MkCoPEntry, MkTreeSettings<O, D, MkCoPTreeNode<O, D>, MkCoPEntry>> { +public class MkCoPTree<O> extends AbstractMkTree<O, MkCoPTreeNode<O>, MkCoPEntry, MkTreeSettings<O, MkCoPTreeNode<O>, MkCoPEntry>> { /** * The logger for this class. */ @@ -78,11 +76,11 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree * @param pagefile Page file * @param settings Tree settings */ - public MkCoPTree(Relation<O> relation, PageFile<MkCoPTreeNode<O, D>> pagefile, MkTreeSettings<O, D, MkCoPTreeNode<O, D>, MkCoPEntry> settings) { + public MkCoPTree(Relation<O> relation, PageFile<MkCoPTreeNode<O>> pagefile, MkTreeSettings<O, MkCoPTreeNode<O>, MkCoPEntry> settings) { super(relation, pagefile, settings); // init log k log_k = new double[settings.k_max]; - for (int k = 1; k <= settings.k_max; k++) { + for(int k = 1; k <= settings.k_max; k++) { log_k[k - 1] = Math.log(k); } } @@ -105,34 +103,34 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree @Override public void insertAll(List<MkCoPEntry> entries) { - if (entries.isEmpty()) { + if(entries.isEmpty()) { return; } - if (LOG.isDebugging()) { + if(LOG.isDebugging()) { LOG.debugFine("insert " + entries + "\n"); } - if (!initialized) { + if(!initialized) { initialize(entries.get(0)); } ModifiableDBIDs ids = DBIDUtil.newArray(entries.size()); // insert - for (MkCoPEntry entry : entries) { + for(MkCoPEntry entry : entries) { ids.add(entry.getRoutingObjectID()); // insert the object super.insert(entry, false); } // perform nearest neighbor queries - Map<DBID, KNNList<D>> knnLists = batchNN(getRoot(), ids, settings.k_max); + Map<DBID, KNNList> knnLists = batchNN(getRoot(), ids, settings.k_max); // adjust the knn distances adjustApproximatedKNNDistances(getRootEntry(), knnLists); - if (EXTRA_INTEGRITY_CHECKS) { + if(EXTRA_INTEGRITY_CHECKS) { getRoot().integrityCheck(this, getRootEntry()); } } @@ -146,17 +144,17 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree * @return a List of the query results */ @Override - public DistanceDBIDList<D> reverseKNNQuery(DBIDRef id, int k) { - if (k > settings.k_max) { + public DoubleDBIDList reverseKNNQuery(DBIDRef id, int k) { + if(k > settings.k_max) { throw new IllegalArgumentException("Parameter k has to be less or equal than " + "parameter kmax of the MCop-Tree!"); } - GenericDistanceDBIDList<D> result = new GenericDistanceDBIDList<>(); + ModifiableDoubleDBIDList result = DBIDUtil.newDistanceDBIDList(); ModifiableDBIDs candidates = DBIDUtil.newArray(); doReverseKNNQuery(k, id, result, candidates); // refinement of candidates - Map<DBID, KNNList<D>> knnLists = batchNN(getRoot(), candidates, k); + Map<DBID, KNNList> knnLists = batchNN(getRoot(), candidates, k); result.sort(); // Collections.sort(candidates); @@ -165,12 +163,12 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree // rkNNStatistics.addCandidates(candidates.size()); // rkNNStatistics.addTrueHits(result.size()); - for (DBIDIter iter = candidates.iter(); iter.valid(); iter.advance()) { + for(DBIDIter iter = candidates.iter(); iter.valid(); iter.advance()) { DBID cid = DBIDUtil.deref(iter); - KNNList<D> cands = knnLists.get(cid); - for (DistanceDBIDListIter<D> iter2 = cands.iter(); iter2.valid(); iter2.advance()) { - if (DBIDUtil.equal(id, iter2)) { - result.add(iter2.getDistance(), cid); + KNNList cands = knnLists.get(cid); + for(DoubleDBIDListIter iter2 = cands.iter(); iter2.valid(); iter2.advance()) { + if(DBIDUtil.equal(id, iter2)) { + result.add(iter2.doubleValue(), cid); break; } } @@ -200,7 +198,7 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree // overhead = index(4), numEntries(4), id(4), isLeaf(0.125) double overhead = 12.125; - if (getPageSize() - overhead < 0) { + if(getPageSize() - overhead < 0) { throw new RuntimeException("Node size of " + getPageSize() + " Bytes is chosen too small!"); } @@ -208,11 +206,11 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree // coveringRadius + parentDistance + consApprox) + 1 dirCapacity = (int) (getPageSize() - overhead) / (4 + 4 + distanceSize + distanceSize + 10) + 1; - if (dirCapacity <= 1) { + if(dirCapacity <= 1) { throw new RuntimeException("Node size of " + getPageSize() + " Bytes is chosen too small!"); } - if (dirCapacity < 10) { + if(dirCapacity < 10) { LOG.warning("Page size is choosen too small! Maximum number of entries " + "in a directory node = " + (dirCapacity - 1)); } @@ -221,17 +219,17 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree // consApprox + progrApprox) + 1 leafCapacity = (int) (getPageSize() - overhead) / (4 + distanceSize + 2 * 10) + 1; - if (leafCapacity <= 1) { + if(leafCapacity <= 1) { throw new RuntimeException("Node size of " + getPageSize() + " Bytes is chosen too small!"); } - if (leafCapacity < 10) { + if(leafCapacity < 10) { LOG.warning("Page size is choosen too small! Maximum number of entries " + "in a leaf node = " + (leafCapacity - 1)); } initialized = true; - if (LOG.isVerbose()) { + if(LOG.isVerbose()) { LOG.verbose("Directory Capacity: " + (dirCapacity - 1) + "\nLeaf Capacity: " + (leafCapacity - 1)); } } @@ -245,45 +243,46 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree * @param candidates holds possible candidates for the result (they need a * refinement) */ - private void doReverseKNNQuery(int k, DBIDRef q, GenericDistanceDBIDList<D> result, ModifiableDBIDs candidates) { + private void doReverseKNNQuery(int k, DBIDRef q, ModifiableDoubleDBIDList result, ModifiableDBIDs candidates) { final ComparableMinHeap<GenericMTreeDistanceSearchCandidate> pq = new ComparableMinHeap<>(); // push root pq.add(new GenericMTreeDistanceSearchCandidate(0., getRootID(), null)); // search in tree - while (!pq.isEmpty()) { + while(!pq.isEmpty()) { GenericMTreeDistanceSearchCandidate pqNode = pq.poll(); // FIXME: cache the distance to the routing object in the queue node! - MkCoPTreeNode<O, D> node = getNode(pqNode.nodeID); + MkCoPTreeNode<O> node = getNode(pqNode.nodeID); // directory node - if (!node.isLeaf()) { - for (int i = 0; i < node.getNumEntries(); i++) { + if(!node.isLeaf()) { + for(int i = 0; i < node.getNumEntries(); i++) { MkCoPEntry entry = node.getEntry(i); - double distance = distance(entry.getRoutingObjectID(), q).doubleValue(); + double distance = distance(entry.getRoutingObjectID(), q); double minDist = entry.getCoveringRadius() > distance ? 0. : distance - entry.getCoveringRadius(); double approximatedKnnDist_cons = entry.approximateConservativeKnnDistance(k); - if (minDist <= approximatedKnnDist_cons) { + if(minDist <= approximatedKnnDist_cons) { pq.add(new GenericMTreeDistanceSearchCandidate(minDist, getPageID(entry), entry.getRoutingObjectID())); } } } // data node else { - for (int i = 0; i < node.getNumEntries(); i++) { + for(int i = 0; i < node.getNumEntries(); i++) { MkCoPLeafEntry entry = (MkCoPLeafEntry) node.getEntry(i); - D distance = distance(entry.getRoutingObjectID(), q); + double distance = distance(entry.getRoutingObjectID(), q); double approximatedKnnDist_prog = entry.approximateProgressiveKnnDistance(k); - if (distance.doubleValue() <= approximatedKnnDist_prog) { + if(distance <= approximatedKnnDist_prog) { result.add(distance, entry.getRoutingObjectID()); - } else { + } + else { double approximatedKnnDist_cons = entry.approximateConservativeKnnDistance(k); - double diff = distance.doubleValue() - approximatedKnnDist_cons; - if (diff <= 1E-10) { + double diff = distance - approximatedKnnDist_cons; + if(diff <= 1E-10) { candidates.add(entry.getRoutingObjectID()); } } @@ -298,16 +297,17 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree * @param entry the root entry of the current subtree * @param knnLists a map of knn lists for each leaf entry */ - private void adjustApproximatedKNNDistances(MkCoPEntry entry, Map<DBID, KNNList<D>> knnLists) { - MkCoPTreeNode<O, D> node = getNode(entry); + private void adjustApproximatedKNNDistances(MkCoPEntry entry, Map<DBID, KNNList> knnLists) { + MkCoPTreeNode<O> node = getNode(entry); - if (node.isLeaf()) { - for (int i = 0; i < node.getNumEntries(); i++) { + if(node.isLeaf()) { + for(int i = 0; i < node.getNumEntries(); i++) { MkCoPLeafEntry leafEntry = (MkCoPLeafEntry) node.getEntry(i); approximateKnnDistances(leafEntry, knnLists.get(leafEntry.getRoutingObjectID())); } - } else { - for (int i = 0; i < node.getNumEntries(); i++) { + } + else { + for(int i = 0; i < node.getNumEntries(); i++) { MkCoPEntry dirEntry = node.getEntry(i); adjustApproximatedKNNDistances(dirEntry, knnLists); } @@ -323,7 +323,7 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree private double ssqerr(int k0, int kmax, double[] logk, double[] log_kDist, double m, double t) { int k = kmax - k0; double result = 0; - for (int i = 0; i < k; i++) { + for(int i = 0; i < k; i++) { // double h = log_kDist[i] - (m * (logk[i] - logk[0]) + t); ??? double h = log_kDist[i] - m * logk[i] - t; result += h * h; @@ -349,19 +349,20 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree * @param knnDistances TODO: Spezialbehandlung fuer identische Punkte in DB * (insbes. Distanz 0) */ - private void approximateKnnDistances(MkCoPLeafEntry entry, KNNList<D> knnDistances) { + private void approximateKnnDistances(MkCoPLeafEntry entry, KNNList knnDistances) { StringBuilder msg = LOG.isDebugging() ? new StringBuilder() : null; - if (msg != null) { + if(msg != null) { msg.append("\nknnDistances ").append(knnDistances); } // count the zero distances int k_0 = 0; - for (int i = 0; i < settings.k_max; i++) { - double dist = knnDistances.get(i).getDistance().doubleValue(); - if (dist == 0) { + for(int i = 0; i < settings.k_max; i++) { + double dist = knnDistances.get(i).doubleValue(); + if(dist == 0) { k_0++; - } else { + } + else { break; } } @@ -374,8 +375,8 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree double sum_log_k_kDist = 0; double[] log_kDist = new double[settings.k_max - k_0]; - for (int i = 0; i < settings.k_max - k_0; i++) { - double dist = knnDistances.get(i + k_0).getDistance().doubleValue(); + for(int i = 0; i < settings.k_max - k_0; i++) { + double dist = knnDistances.get(i + k_0).doubleValue(); log_kDist[i] = Math.log(dist); sum_log_kDist += log_kDist[i]; sum_log_k_kDist += log_kDist[i] * log_k[i]; @@ -384,12 +385,12 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree double sum_log_k = 0; double sum_log_k2 = 0; // noinspection ForLoopReplaceableByForEach - for (int i = 0; i < log_k.length; i++) { + for(int i = 0; i < log_k.length; i++) { sum_log_k += log_k[i]; sum_log_k2 += (log_k[i] * log_k[i]); } - if (msg != null) { + if(msg != null) { msg.append("\nk_0 ").append(k_0); msg.append("\nk_max ").append(settings.k_max); msg.append("\nlog_k(").append(log_k.length).append(") ").append(FormatUtil.format(log_k)); @@ -412,12 +413,12 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree double err1 = ssqerr(k_0, settings.k_max, log_k, log_kDist, conservative.getM(), conservative.getT()); double err2 = ssqerr(k_0, settings.k_max, log_k, log_kDist, c2.getM(), c2.getT()); - if (msg != null) { + if(msg != null) { msg.append("err1 ").append(err1); msg.append("err2 ").append(err2); } - if (err1 > err2 && err1 - err2 > 0.000000001) { + if(err1 > err2 && err1 - err2 > 0.000000001) { // if (err1 > err2) { StringBuilder warning = new StringBuilder(); @@ -431,7 +432,7 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree warning.append("\nconservative1 ").append(conservative); warning.append("\nconservative2 ").append(c2); - for (int i = 0; i < u; i++) { + for(int i = 0; i < u; i++) { warning.append("\nlog_k[").append(upperHull[i]).append("] = ").append(log_k[upperHull[i]]); warning.append("\nlog_kDist[").append(upperHull[i]).append("] = ").append(log_kDist[upperHull[i]]); } @@ -444,7 +445,7 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree entry.setConservativeKnnDistanceApproximation(conservative); entry.setProgressiveKnnDistanceApproximation(progressive); - if (msg != null) { + if(msg != null) { LOG.debugFine(msg.toString()); } } @@ -470,12 +471,12 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree double low_m = 0.0; double low_t = 0.0; - for (int i = 1; i < l; i++) { + for(int i = 1; i < l; i++) { double cur_m = (log_kDist[lowerHull[i]] - log_kDist[lowerHull[i - 1]]) / (log_k[lowerHull[i]] - log_k[lowerHull[i - 1]]); double cur_t = log_kDist[lowerHull[i]] - cur_m * log_k[lowerHull[i]]; double cur_error = ssqerr(k_0, settings.k_max, log_k, log_kDist, cur_m, cur_t); msg.append(" Segment = ").append(i).append(" m = ").append(cur_m).append(" t = ").append(cur_t).append(" lowerror = ").append(cur_error).append("\n"); - if (cur_error < low_error) { + if(cur_error < low_error) { low_error = cur_error; low_m = cur_m; low_t = cur_t; @@ -484,13 +485,13 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree // linear search on all points of the lower convex hull boolean is_right = true; // NEEDED FOR PROOF CHECK - for (int i = 0; i < l; i++) { + for(int i = 0; i < l; i++) { double cur_m = optimize(k_0, settings.k_max, sum_log_k, sum_log_k2, log_k[lowerHull[i]], log_kDist[lowerHull[i]], sum_log_k_kDist, sum_log_kDist); double cur_t = log_kDist[lowerHull[i]] - cur_m * log_k[lowerHull[i]]; // only valid if both neighboring points are underneath y=mx+t - if ((i == 0 || log_kDist[lowerHull[i - 1]] >= log_kDist[lowerHull[i]] - cur_m * (log_k[lowerHull[i]] - log_k[lowerHull[i - 1]])) && (i == l - 1 || log_kDist[lowerHull[i + 1]] >= log_kDist[lowerHull[i]] + cur_m * (log_k[lowerHull[i + 1]] - log_k[lowerHull[i]]))) { + if((i == 0 || log_kDist[lowerHull[i - 1]] >= log_kDist[lowerHull[i]] - cur_m * (log_k[lowerHull[i]] - log_k[lowerHull[i - 1]])) && (i == l - 1 || log_kDist[lowerHull[i + 1]] >= log_kDist[lowerHull[i]] + cur_m * (log_k[lowerHull[i + 1]] - log_k[lowerHull[i]]))) { double cur_error = ssqerr(k_0, settings.k_max, log_k, log_kDist, cur_m, cur_t); - if (cur_error < low_error) { + if(cur_error < low_error) { low_error = cur_error; low_m = cur_m; low_t = cur_t; @@ -498,9 +499,9 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree } // check proof of bisection search - if (!(i > 0 && log_kDist[lowerHull[i - 1]] < log_kDist[lowerHull[i]] - cur_m * (log_k[lowerHull[i]] - log_k[lowerHull[i - 1]])) && !is_right) { + if(!(i > 0 && log_kDist[lowerHull[i - 1]] < log_kDist[lowerHull[i]] - cur_m * (log_k[lowerHull[i]] - log_k[lowerHull[i - 1]])) && !is_right) { // warning("ERROR lower: The bisection search will not work properly !"); - if (!(i < l - 1 && log_kDist[lowerHull[i + 1]] < log_kDist[lowerHull[i]] + cur_m * (log_k[lowerHull[i + 1]] - log_k[lowerHull[i]]))) { + if(!(i < l - 1 && log_kDist[lowerHull[i + 1]] < log_kDist[lowerHull[i]] + cur_m * (log_k[lowerHull[i + 1]] - log_k[lowerHull[i]]))) { is_right = false; } } @@ -519,14 +520,14 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree ApproximationLine approx = null; double error = Double.POSITIVE_INFINITY; - for (int i = 0; i < u - 1; i++) { + for(int i = 0; i < u - 1; i++) { int ii = upperHull[i]; int jj = upperHull[i + 1]; double current_m = (log_kDist[jj] - log_kDist[ii]) / (log_k[jj] - log_k[ii]); double current_t = log_kDist[ii] - current_m * log_k[ii]; ApproximationLine current_approx = new ApproximationLine(k_0, current_m, current_t); - if (LOG.isDebugging()) { + if(LOG.isDebugging()) { msg.append("\nlog_kDist[").append(jj).append("] ").append(log_kDist[jj]); msg.append("\nlog_kDist[").append(ii).append("] ").append(log_kDist[ii]); msg.append("\nlog_k[").append(jj).append("] ").append(log_k[jj]); @@ -537,22 +538,22 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree boolean ok = true; double currentError = 0; - for (int k = k_0; k <= settings.k_max; k++) { + for(int k = k_0; k <= settings.k_max; k++) { double appDist = current_approx.getValueAt(k); - if (appDist < log_kDist[k - k_0] && log_kDist[k - k_0] - appDist > 0.000000001) { + if(appDist < log_kDist[k - k_0] && log_kDist[k - k_0] - appDist > 0.000000001) { ok = false; break; } currentError += (appDist - log_kDist[k - k_0]); } - if (ok && currentError < error) { + if(ok && currentError < error) { approx = current_approx; error = currentError; } } - if (LOG.isDebugging()) { + if(LOG.isDebugging()) { msg.append("\nupper Approx ").append(approx); LOG.debugFine(msg.toString()); } @@ -570,7 +571,7 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree int k_0 = settings.k_max - upperHull.length + 1; int a = u / 2; - while (marked.size() != u) { + while(marked.size() != u) { marked.add(a); double x_a = log_k[upperHull[a]]; double y_a = log_kDist[upperHull[a]]; @@ -578,7 +579,7 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree double m_a = optimize(k_0, settings.k_max, sum_log_k, sum_log_k2, x_a, y_a, sum_log_k_kDist, sum_log_kDist); double t_a = y_a - m_a * x_a; - if (msg != null) { + if(msg != null) { msg.append("\na=").append(a).append(" m_a=").append(m_a).append(", t_a=").append(t_a); msg.append("\n err ").append(ssqerr(k_0, settings.k_max, log_k, log_kDist, m_a, m_a)); } @@ -591,23 +592,24 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree boolean lessThanPre = a == 0 || y_p <= m_a * x_p + t_a; boolean lessThanSuc = a == u || y_s <= m_a * x_s + t_a; - if (lessThanPre && lessThanSuc) { + if(lessThanPre && lessThanSuc) { ApproximationLine appr = new ApproximationLine(k_0, m_a, t_a); - if (msg != null) { + if(msg != null) { msg.append("\n1 anchor = ").append(a); LOG.debugFine(msg.toString()); } return appr; - } else if (!lessThanPre) { - if (marked.contains(a - 1)) { + } + else if(!lessThanPre) { + if(marked.contains(a - 1)) { m_a = (y_a - y_p) / (x_a - x_p); - if (y_a == y_p) { + if(y_a == y_p) { m_a = 0; } t_a = y_a - m_a * x_a; ApproximationLine appr = new ApproximationLine(k_0, m_a, t_a); - if (msg != null) { + if(msg != null) { msg.append("2 anchor = ").append(a); msg.append(" appr1 ").append(appr); msg.append(" x_a ").append(x_a).append(", y_a ").append(y_a); @@ -617,25 +619,28 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree LOG.debugFine(msg.toString()); } return appr; - } else { + } + else { a = a - 1; } - } else { - if (marked.contains(a + 1)) { + } + else { + if(marked.contains(a + 1)) { m_a = (y_a - y_s) / (x_a - x_s); - if (y_a == y_p) { + if(y_a == y_p) { m_a = 0; } t_a = y_a - m_a * x_a; ApproximationLine appr = new ApproximationLine(k_0, m_a, t_a); - if (msg != null) { + if(msg != null) { msg.append("3 anchor = ").append(a).append(" -- ").append((a + 1)); msg.append(" appr2 ").append(appr); LOG.debugFine(msg.toString()); } return appr; - } else { + } + else { a = a + 1; } } @@ -657,11 +662,11 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree double upp_error = Double.MAX_VALUE; double upp_m = 0.0; double upp_t = 0.0; - for (int i = 1; i < u; i++) { + for(int i = 1; i < u; i++) { double cur_m = (log_kDist[upperHull[i]] - log_kDist[upperHull[i - 1]]) / (log_k[upperHull[i]] - log_k[upperHull[i - 1]]); double cur_t = log_kDist[upperHull[i]] - cur_m * log_k[upperHull[i]]; double cur_error = ssqerr(k_0, settings.k_max, log_k, log_kDist, cur_m, cur_t); - if (cur_error < upp_error) { + if(cur_error < upp_error) { upp_error = cur_error; upp_m = cur_m; upp_t = cur_t; @@ -669,13 +674,13 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree } // linear search on all points of the upper convex hull boolean is_left = true; // NEEDED FOR PROOF CHECK - for (int i = 0; i < u; i++) { + for(int i = 0; i < u; i++) { double cur_m = optimize(k_0, settings.k_max, sum_log_k, sum_log_k2, log_k[upperHull[i]], log_kDist[upperHull[i]], sum_log_k_kDist, sum_log_kDist); double cur_t = log_kDist[upperHull[i]] - cur_m * log_k[upperHull[i]]; // only valid if both neighboring points are underneath y=mx+t - if ((i == 0 || log_kDist[upperHull[i - 1]] <= log_kDist[upperHull[i]] - cur_m * (log_k[upperHull[i]] - log_k[upperHull[i - 1]])) && (i == u - 1 || log_kDist[upperHull[i + 1]] <= log_kDist[upperHull[i]] + cur_m * (log_k[upperHull[i + 1]] - log_k[upperHull[i]]))) { + if((i == 0 || log_kDist[upperHull[i - 1]] <= log_kDist[upperHull[i]] - cur_m * (log_k[upperHull[i]] - log_k[upperHull[i - 1]])) && (i == u - 1 || log_kDist[upperHull[i + 1]] <= log_kDist[upperHull[i]] + cur_m * (log_k[upperHull[i + 1]] - log_k[upperHull[i]]))) { double cur_error = ssqerr(k_0, settings.k_max, log_k, log_kDist, cur_m, cur_t); - if (cur_error < upp_error) { + if(cur_error < upp_error) { upp_error = cur_error; upp_m = cur_m; upp_t = cur_t; @@ -683,12 +688,12 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree } // check proof of bisection search - if (!(i > 0 && log_kDist[upperHull[i - 1]] > log_kDist[upperHull[i]] - cur_m * (log_k[upperHull[i]] - log_k[upperHull[i - 1]])) && !is_left) { + if(!(i > 0 && log_kDist[upperHull[i - 1]] > log_kDist[upperHull[i]] - cur_m * (log_k[upperHull[i]] - log_k[upperHull[i - 1]])) && !is_left) { // warning("ERROR upper: The bisection search will not work properly !" // + // "\n" + Util.format(log_kDist)); } - if (!(i < u - 1 && log_kDist[upperHull[i + 1]] > log_kDist[upperHull[i]] + cur_m * (log_k[upperHull[i + 1]] - log_k[upperHull[i]]))) { + if(!(i < u - 1 && log_kDist[upperHull[i + 1]] > log_kDist[upperHull[i]] + cur_m * (log_k[upperHull[i + 1]] - log_k[upperHull[i]]))) { is_left = false; } } @@ -703,7 +708,7 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree * @return a new leaf node */ @Override - protected MkCoPTreeNode<O, D> createNewLeafNode() { + protected MkCoPTreeNode<O> createNewLeafNode() { return new MkCoPTreeNode<>(leafCapacity, true); } @@ -713,7 +718,7 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree * @return a new directory node */ @Override - protected MkCoPTreeNode<O, D> createNewDirectoryNode() { + protected MkCoPTreeNode<O> createNewDirectoryNode() { return new MkCoPTreeNode<>(dirCapacity, false); } @@ -726,7 +731,7 @@ public class MkCoPTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree * the routing object of the parent node */ @Override - protected MkCoPEntry createNewDirectoryEntry(MkCoPTreeNode<O, D> node, DBID routingObjectID, double parentDistance) { + protected MkCoPEntry createNewDirectoryEntry(MkCoPTreeNode<O> node, DBID routingObjectID, double parentDistance) { return new MkCoPDirectoryEntry(routingObjectID, parentDistance, node.getPageID(), node.coveringRadius(routingObjectID, this), null); // node.conservativeKnnDistanceApproximation(k_max)); } diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTreeIndex.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTreeIndex.java index 96def76b..1cce0a01 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTreeIndex.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTreeIndex.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkcop; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -36,8 +36,6 @@ import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery; import de.lmu.ifi.dbs.elki.database.query.rknn.RKNNQuery; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.KNNIndex; import de.lmu.ifi.dbs.elki.index.RKNNIndex; import de.lmu.ifi.dbs.elki.index.RangeIndex; @@ -52,9 +50,8 @@ import de.lmu.ifi.dbs.elki.persistent.PageFile; * @author Erich Schubert * * @param <O> Object type - * @param <D> Distance type */ -public class MkCoPTreeIndex<O, D extends NumberDistance<D, ?>> extends MkCoPTree<O, D> implements RangeIndex<O>, KNNIndex<O>, RKNNIndex<O> { +public class MkCoPTreeIndex<O> extends MkCoPTree<O> implements RangeIndex<O>, KNNIndex<O>, RKNNIndex<O> { /** * Relation indexed */ @@ -67,7 +64,7 @@ public class MkCoPTreeIndex<O, D extends NumberDistance<D, ?>> extends MkCoPTree * @param pageFile Page file * @param settings Tree settings */ - public MkCoPTreeIndex(Relation<O> relation, PageFile<MkCoPTreeNode<O, D>> pageFile, MkTreeSettings<O, D, MkCoPTreeNode<O, D>, MkCoPEntry> settings) { + public MkCoPTreeIndex(Relation<O> relation, PageFile<MkCoPTreeNode<O>> pageFile, MkTreeSettings<O, MkCoPTreeNode<O>, MkCoPEntry> settings) { super(relation, pageFile, settings); this.relation = relation; } @@ -89,7 +86,7 @@ public class MkCoPTreeIndex<O, D extends NumberDistance<D, ?>> extends MkCoPTree public void initialize() { super.initialize(); List<MkCoPEntry> objs = new ArrayList<>(relation.size()); - for (DBIDIter iter = relation.iterDBIDs(); iter.valid(); iter.advance()) { + for(DBIDIter iter = relation.iterDBIDs(); iter.valid(); iter.advance()) { DBID id = DBIDUtil.deref(iter); // FIXME: expensive final O object = relation.get(id); objs.add(createNewLeafEntry(id, object, Double.NaN)); @@ -97,72 +94,66 @@ public class MkCoPTreeIndex<O, D extends NumberDistance<D, ?>> extends MkCoPTree insertAll(objs); } - @SuppressWarnings("unchecked") @Override - public <S extends Distance<S>> KNNQuery<O, S> getKNNQuery(DistanceQuery<O, S> distanceQuery, Object... hints) { + public KNNQuery<O> getKNNQuery(DistanceQuery<O> distanceQuery, Object... hints) { // Query on the relation we index - if (distanceQuery.getRelation() != relation) { + if(distanceQuery.getRelation() != relation) { return null; } - DistanceFunction<? super O, D> distanceFunction = (DistanceFunction<? super O, D>) distanceQuery.getDistanceFunction(); - if (!this.getDistanceFunction().equals(distanceFunction)) { - if (getLogger().isDebugging()) { + DistanceFunction<? super O> distanceFunction = (DistanceFunction<? super O>) distanceQuery.getDistanceFunction(); + if(!this.getDistanceFunction().equals(distanceFunction)) { + if(getLogger().isDebugging()) { getLogger().debug("Distance function not supported by index - or 'equals' not implemented right!"); } return null; } // Bulk is not yet supported - for (Object hint : hints) { - if (hint == DatabaseQuery.HINT_BULK) { + for(Object hint : hints) { + if(hint == DatabaseQuery.HINT_BULK) { return null; } } - DistanceQuery<O, D> dq = distanceFunction.instantiate(relation); - return (KNNQuery<O, S>) MTreeQueryUtil.getKNNQuery(this, dq, hints); + return MTreeQueryUtil.getKNNQuery(this, distanceQuery, hints); } - @SuppressWarnings("unchecked") @Override - public <S extends Distance<S>> RangeQuery<O, S> getRangeQuery(DistanceQuery<O, S> distanceQuery, Object... hints) { + public RangeQuery<O> getRangeQuery(DistanceQuery<O> distanceQuery, Object... hints) { // Query on the relation we index - if (distanceQuery.getRelation() != relation) { + if(distanceQuery.getRelation() != relation) { return null; } - DistanceFunction<? super O, D> distanceFunction = (DistanceFunction<? super O, D>) distanceQuery.getDistanceFunction(); - if (!this.getDistanceFunction().equals(distanceFunction)) { - if (getLogger().isDebugging()) { + DistanceFunction<? super O> distanceFunction = (DistanceFunction<? super O>) distanceQuery.getDistanceFunction(); + if(!this.getDistanceFunction().equals(distanceFunction)) { + if(getLogger().isDebugging()) { getLogger().debug("Distance function not supported by index - or 'equals' not implemented right!"); } return null; } // Bulk is not yet supported - for (Object hint : hints) { - if (hint == DatabaseQuery.HINT_BULK) { + for(Object hint : hints) { + if(hint == DatabaseQuery.HINT_BULK) { return null; } } - DistanceQuery<O, D> dq = distanceFunction.instantiate(relation); - return (RangeQuery<O, S>) MTreeQueryUtil.getRangeQuery(this, dq, hints); + return MTreeQueryUtil.getRangeQuery(this, distanceQuery, hints); } - @SuppressWarnings("unchecked") @Override - public <S extends Distance<S>> RKNNQuery<O, S> getRKNNQuery(DistanceQuery<O, S> distanceQuery, Object... hints) { - DistanceFunction<? super O, D> distanceFunction = (DistanceFunction<? super O, D>) distanceQuery.getDistanceFunction(); - if (!this.getDistanceFunction().equals(distanceFunction)) { - if (getLogger().isDebugging()) { + public RKNNQuery<O> getRKNNQuery(DistanceQuery<O> distanceQuery, Object... hints) { + DistanceFunction<? super O> distanceFunction = (DistanceFunction<? super O>) distanceQuery.getDistanceFunction(); + if(!this.getDistanceFunction().equals(distanceFunction)) { + if(getLogger().isDebugging()) { getLogger().debug("Distance function not supported by index - or 'equals' not implemented right!"); } return null; } // Bulk is not yet supported - for (Object hint : hints) { - if (hint == DatabaseQuery.HINT_BULK) { + for(Object hint : hints) { + if(hint == DatabaseQuery.HINT_BULK) { return null; } } - DistanceQuery<O, D> dq = distanceFunction.instantiate(relation); - return (RKNNQuery<O, S>) new MkTreeRKNNQuery<>(this, dq); + return new MkTreeRKNNQuery<>(this, distanceQuery); } @Override diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTreeNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTreeNode.java index 79a9c6cc..dcaa7e05 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTreeNode.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCoPTreeNode.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkcop; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -24,7 +24,6 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkcop; */ import de.lmu.ifi.dbs.elki.database.ids.DBID; -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode; @@ -36,9 +35,8 @@ import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode; * @apiviz.has MkCoPEntry oneway - - contains * * @param <O> object type - * @param <D> distance type */ -class MkCoPTreeNode<O, D extends NumberDistance<D, ?>> extends AbstractMTreeNode<O, D, MkCoPTreeNode<O, D>, MkCoPEntry> { +class MkCoPTreeNode<O> extends AbstractMTreeNode<O, MkCoPTreeNode<O>, MkCoPEntry> { /** * Serial version UID */ @@ -142,7 +140,7 @@ class MkCoPTreeNode<O, D extends NumberDistance<D, ?>> extends AbstractMTreeNode } @Override - public void adjustEntry(MkCoPEntry entry, DBID routingObjectID, double parentDistance, AbstractMTree<O, D, MkCoPTreeNode<O, D>, MkCoPEntry, ?> mTree) { + public void adjustEntry(MkCoPEntry entry, DBID routingObjectID, double parentDistance, AbstractMTree<O, MkCoPTreeNode<O>, MkCoPEntry, ?> mTree) { super.adjustEntry(entry, routingObjectID, parentDistance, mTree); // adjust conservative distance approximation // int k_max = ((MkCoPTree<O,D>) mTree).getK_max(); @@ -150,11 +148,11 @@ class MkCoPTreeNode<O, D extends NumberDistance<D, ?>> extends AbstractMTreeNode } @Override - protected void integrityCheckParameters(MkCoPEntry parentEntry, MkCoPTreeNode<O, D> parent, int index, AbstractMTree<O, D, MkCoPTreeNode<O, D>, MkCoPEntry, ?> mTree) { + protected void integrityCheckParameters(MkCoPEntry parentEntry, MkCoPTreeNode<O> parent, int index, AbstractMTree<O, MkCoPTreeNode<O>, MkCoPEntry, ?> mTree) { super.integrityCheckParameters(parentEntry, parent, index, mTree); // test conservative approximation MkCoPEntry entry = parent.getEntry(index); - int k_max = ((MkCoPTree<O, D>) mTree).getK_max(); + int k_max = ((MkCoPTree<O>) mTree).getK_max(); ApproximationLine approx = conservativeKnnDistanceApproximation(k_max); if(!entry.getConservativeKnnDistanceApproximation().equals(approx)) { String soll = approx.toString(); diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCopTreeFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCopTreeFactory.java index fa7afbe2..e6b0ab12 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCopTreeFactory.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/MkCopTreeFactory.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkcop; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -24,7 +24,6 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkcop; */ import de.lmu.ifi.dbs.elki.database.relation.Relation; -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeFactory; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.MkTreeSettings; import de.lmu.ifi.dbs.elki.persistent.PageFile; @@ -44,9 +43,8 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter; * @apiviz.uses MkCoPTreeIndex oneway - - «create» * * @param <O> Object type - * @param <D> Distance type */ -public class MkCopTreeFactory<O, D extends NumberDistance<D, ?>> extends AbstractMTreeFactory<O, D, MkCoPTreeNode<O, D>, MkCoPEntry, MkCoPTreeIndex<O, D>, MkTreeSettings<O, D, MkCoPTreeNode<O, D>, MkCoPEntry>> { +public class MkCopTreeFactory<O> extends AbstractMTreeFactory<O, MkCoPTreeNode<O>, MkCoPEntry, MkCoPTreeIndex<O>, MkTreeSettings<O, MkCoPTreeNode<O>, MkCoPEntry>> { /** * Parameter for k */ @@ -58,17 +56,17 @@ public class MkCopTreeFactory<O, D extends NumberDistance<D, ?>> extends Abstrac * @param pageFileFactory Data storage * @param settings Tree settings */ - public MkCopTreeFactory(PageFileFactory<?> pageFileFactory, MkTreeSettings<O, D, MkCoPTreeNode<O, D>, MkCoPEntry> settings) { + public MkCopTreeFactory(PageFileFactory<?> pageFileFactory, MkTreeSettings<O, MkCoPTreeNode<O>, MkCoPEntry> settings) { super(pageFileFactory, settings); } @Override - public MkCoPTreeIndex<O, D> instantiate(Relation<O> relation) { - PageFile<MkCoPTreeNode<O, D>> pagefile = makePageFile(getNodeClass()); + public MkCoPTreeIndex<O> instantiate(Relation<O> relation) { + PageFile<MkCoPTreeNode<O>> pagefile = makePageFile(getNodeClass()); return new MkCoPTreeIndex<>(relation, pagefile, settings); } - protected Class<MkCoPTreeNode<O, D>> getNodeClass() { + protected Class<MkCoPTreeNode<O>> getNodeClass() { return ClassGenericsUtil.uglyCastIntoSubclass(MkCoPTreeNode.class); } @@ -78,8 +76,10 @@ public class MkCopTreeFactory<O, D extends NumberDistance<D, ?>> extends Abstrac * @author Erich Schubert * * @apiviz.exclude + * + * @param <O> Object type */ - public static class Parameterizer<O, D extends NumberDistance<D, ?>> extends AbstractMTreeFactory.Parameterizer<O, D, MkCoPTreeNode<O, D>, MkCoPEntry, MkTreeSettings<O, D, MkCoPTreeNode<O, D>, MkCoPEntry>> { + public static class Parameterizer<O> extends AbstractMTreeFactory.Parameterizer<O, MkCoPTreeNode<O>, MkCoPEntry, MkTreeSettings<O, MkCoPTreeNode<O>, MkCoPEntry>> { @Override protected void makeOptions(Parameterization config) { super.makeOptions(config); @@ -91,12 +91,12 @@ public class MkCopTreeFactory<O, D extends NumberDistance<D, ?>> extends Abstrac } @Override - protected MkCopTreeFactory<O, D> makeInstance() { + protected MkCopTreeFactory<O> makeInstance() { return new MkCopTreeFactory<>(pageFileFactory, settings); } @Override - protected MkTreeSettings<O, D, MkCoPTreeNode<O, D>, MkCoPEntry> makeSettings() { + protected MkTreeSettings<O, MkCoPTreeNode<O>, MkCoPEntry> makeSettings() { return new MkTreeSettings<>(); } } diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/package-info.java index c767c565..4adea565 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkcop/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2013 +Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxDirectoryEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxDirectoryEntry.java index b3e39ca0..1cd28215 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxDirectoryEntry.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxDirectoryEntry.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkmax; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -57,7 +57,7 @@ class MkMaxDirectoryEntry extends MTreeDirectoryEntry implements MkMaxEntry { } /** - * Provides a new MkMaxDirectoryEntry with the given parameters. + * Constructor. * * @param objectID the id of the routing object * @param parentDistance the distance from the routing object of this entry to diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxEntry.java index 9e5133c9..5db6d22c 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxEntry.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxEntry.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkmax; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxLeafEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxLeafEntry.java index d49f18ec..274e6a68 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxLeafEntry.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxLeafEntry.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkmax; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -56,7 +56,7 @@ class MkMaxLeafEntry extends MTreeLeafEntry implements MkMaxEntry { } /** - * Provides a new MkMaxLeafEntry with the given parameters. + * Constructor. * * @param objectID the id of the underlying data object * @param parentDistance the distance from the underlying data object to its diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTree.java index e3e4f71f..d099533b 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTree.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTree.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkmax; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -30,20 +30,18 @@ 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.DoubleDBIDList; +import de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDListIter; +import de.lmu.ifi.dbs.elki.database.ids.KNNHeap; +import de.lmu.ifi.dbs.elki.database.ids.KNNList; import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs; -import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList; -import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNHeap; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList; -import de.lmu.ifi.dbs.elki.database.ids.distance.ModifiableDistanceDBIDList; -import de.lmu.ifi.dbs.elki.database.ids.generic.GenericDistanceDBIDList; +import de.lmu.ifi.dbs.elki.database.ids.ModifiableDoubleDBIDList; import de.lmu.ifi.dbs.elki.database.relation.Relation; -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.AbstractMkTreeUnified; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.MkTreeSettings; import de.lmu.ifi.dbs.elki.logging.Logging; -import de.lmu.ifi.dbs.elki.persistent.ByteArrayUtil; import de.lmu.ifi.dbs.elki.persistent.PageFile; +import de.lmu.ifi.dbs.elki.utilities.io.ByteArrayUtil; import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleIntPair; /** @@ -57,9 +55,8 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleIntPair; * @apiviz.has MkMaxTreeNode oneway - - contains * * @param <O> the type of DatabaseObject to be stored in the MkMaxTree - * @param <D> the type of Distance used in the MkMaxTree */ -public class MkMaxTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTreeUnified<O, D, MkMaxTreeNode<O, D>, MkMaxEntry, MkTreeSettings<O, D, MkMaxTreeNode<O, D>, MkMaxEntry>> { +public class MkMaxTree<O> extends AbstractMkTreeUnified<O, MkMaxTreeNode<O>, MkMaxEntry, MkTreeSettings<O, MkMaxTreeNode<O>, MkMaxEntry>> { /** * The logger for this class. */ @@ -72,7 +69,7 @@ public class MkMaxTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree * @param pagefile Page file * @param settings Tree settings */ - public MkMaxTree(Relation<O> relation, PageFile<MkMaxTreeNode<O, D>> pagefile, MkTreeSettings<O, D, MkMaxTreeNode<O, D>, MkMaxEntry> settings) { + public MkMaxTree(Relation<O> relation, PageFile<MkMaxTreeNode<O>> pagefile, MkTreeSettings<O, MkMaxTreeNode<O>, MkMaxEntry> settings) { super(relation, pagefile, settings); } @@ -83,13 +80,13 @@ public class MkMaxTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree * in a second step. */ @Override - public DistanceDBIDList<D> reverseKNNQuery(DBIDRef id, int k) { + public DoubleDBIDList reverseKNNQuery(DBIDRef id, int k) { if (k > this.getKmax()) { throw new IllegalArgumentException("Parameter k has to be equal or less than " + "parameter k of the MkMax-Tree!"); } // get the candidates - GenericDistanceDBIDList<D> candidates = new GenericDistanceDBIDList<>(); + ModifiableDoubleDBIDList candidates = DBIDUtil.newDistanceDBIDList(); doReverseKNNQuery(id, getRoot(), null, candidates); if (k == this.getKmax()) { @@ -105,15 +102,15 @@ public class MkMaxTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree for (DBIDIter candidate = candidates.iter(); candidate.valid(); candidate.advance()) { candidateIDs.add(candidate); } - Map<DBID, KNNList<D>> knnLists = batchNN(getRoot(), candidateIDs, k); + Map<DBID, KNNList> knnLists = batchNN(getRoot(), candidateIDs, k); - GenericDistanceDBIDList<D> result = new GenericDistanceDBIDList<>(); + ModifiableDoubleDBIDList result = DBIDUtil.newDistanceDBIDList(); for (DBIDIter iter = candidateIDs.iter(); iter.valid(); iter.advance()) { DBID cid = DBIDUtil.deref(iter); - KNNList<D> cands = knnLists.get(cid); - for (DistanceDBIDListIter<D> iter2 = cands.iter(); iter2.valid(); iter2.advance()) { + KNNList cands = knnLists.get(cid); + for (DoubleDBIDListIter iter2 = cands.iter(); iter2.valid(); iter2.advance()) { if (DBIDUtil.equal(id, iter2)) { - result.add(iter2.getDistance(), cid); + result.add(iter2.doubleValue(), cid); break; } } @@ -132,7 +129,7 @@ public class MkMaxTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree */ @Override protected void preInsert(MkMaxEntry entry) { - KNNHeap<D> knns_o = DBIDUtil.newHeap(getDistanceFactory(), getKmax()); + KNNHeap knns_o = DBIDUtil.newHeap(getKmax()); preInsert(entry, getRootEntry(), knns_o); } @@ -140,13 +137,13 @@ public class MkMaxTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree * Adjusts the knn distance in the subtree of the specified root entry. */ @Override - protected void kNNdistanceAdjustment(MkMaxEntry entry, Map<DBID, KNNList<D>> knnLists) { - MkMaxTreeNode<O, D> node = getNode(entry); + protected void kNNdistanceAdjustment(MkMaxEntry entry, Map<DBID, KNNList> knnLists) { + MkMaxTreeNode<O> node = getNode(entry); double knnDist_node = 0.; if (node.isLeaf()) { for (int i = 0; i < node.getNumEntries(); i++) { MkMaxEntry leafEntry = node.getEntry(i); - leafEntry.setKnnDistance(knnLists.get(leafEntry.getRoutingObjectID()).getKNNDistance().doubleValue()); + leafEntry.setKnnDistance(knnLists.get(leafEntry.getRoutingObjectID()).getKNNDistance()); knnDist_node = Math.max(knnDist_node, leafEntry.getKnnDistance()); } } else { @@ -170,13 +167,13 @@ public class MkMaxTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree * @param node_entry the entry representing the node * @param result the list for the query result */ - private void doReverseKNNQuery(DBIDRef q, MkMaxTreeNode<O, D> node, MkMaxEntry node_entry, ModifiableDistanceDBIDList<D> result) { + private void doReverseKNNQuery(DBIDRef q, MkMaxTreeNode<O> node, MkMaxEntry node_entry, ModifiableDoubleDBIDList result) { // data node if (node.isLeaf()) { for (int i = 0; i < node.getNumEntries(); i++) { MkMaxEntry entry = node.getEntry(i); - D distance = distance(entry.getRoutingObjectID(), q); - if (distance.doubleValue() <= entry.getKnnDistance()) { + double distance = distance(entry.getRoutingObjectID(), q); + if (distance <= entry.getKnnDistance()) { result.add(distance, entry.getRoutingObjectID()); } } @@ -188,11 +185,11 @@ public class MkMaxTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree MkMaxEntry entry = node.getEntry(i); double node_knnDist = node_entry != null ? node_entry.getKnnDistance() : Double.POSITIVE_INFINITY; - double distance = distance(entry.getRoutingObjectID(), q).doubleValue(); + double distance = distance(entry.getRoutingObjectID(), q); double minDist = (entry.getCoveringRadius() > distance) ? 0.0 : distance - entry.getCoveringRadius(); if (minDist <= node_knnDist) { - MkMaxTreeNode<O, D> childNode = getNode(entry); + MkMaxTreeNode<O> childNode = getNode(entry); doReverseKNNQuery(q, childNode, entry, result); } } @@ -206,39 +203,39 @@ public class MkMaxTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree * @param nodeEntry the entry representing the root of the current subtree * @param knns_q the knns of q */ - private void preInsert(MkMaxEntry q, MkMaxEntry nodeEntry, KNNHeap<D> knns_q) { + private void preInsert(MkMaxEntry q, MkMaxEntry nodeEntry, KNNHeap knns_q) { if (LOG.isDebugging()) { LOG.debugFine("preInsert " + q + " - " + nodeEntry + "\n"); } - double knnDist_q = knns_q.getKNNDistance().doubleValue(); - MkMaxTreeNode<O, D> node = getNode(nodeEntry); + double knnDist_q = knns_q.getKNNDistance(); + MkMaxTreeNode<O> node = getNode(nodeEntry); double knnDist_node = 0.; // leaf node if (node.isLeaf()) { for (int i = 0; i < node.getNumEntries(); i++) { MkMaxEntry p = node.getEntry(i); - D dist_pq = distance(p.getRoutingObjectID(), q.getRoutingObjectID()); + double dist_pq = distance(p.getRoutingObjectID(), q.getRoutingObjectID()); // p is nearer to q than the farthest kNN-candidate of q // ==> p becomes a knn-candidate - if (dist_pq.doubleValue() <= knnDist_q) { + if (dist_pq <= knnDist_q) { knns_q.insert(dist_pq, p.getRoutingObjectID()); if (knns_q.size() >= getKmax()) { - knnDist_q = knns_q.getKNNDistance().doubleValue(); + knnDist_q = knns_q.getKNNDistance(); q.setKnnDistance(knnDist_q); } } // p is nearer to q than to its farthest knn-candidate // q becomes knn of p - if (dist_pq.doubleValue() <= p.getKnnDistance()) { - KNNList<D> knns_p = knnq.getKNNForDBID(p.getRoutingObjectID(), getKmax() - 1); + if (dist_pq <= p.getKnnDistance()) { + KNNList knns_p = knnq.getKNNForDBID(p.getRoutingObjectID(), getKmax() - 1); if (knns_p.size() + 1 < getKmax()) { p.setKnnDistance(Double.NaN); } else { - double knnDist_p = Math.max(dist_pq.doubleValue(), knns_p.getKNNDistance().doubleValue()); + double knnDist_p = Math.max(dist_pq, knns_p.getKNNDistance()); p.setKnnDistance(knnDist_p); } } @@ -254,7 +251,7 @@ public class MkMaxTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree if (distEntry.second < entry_knnDist || distEntry.second < knnDist_q) { preInsert(q, dirEntry, knns_q); - knnDist_q = knns_q.getKNNDistance().doubleValue(); + knnDist_q = knns_q.getKNNDistance(); } knnDist_node = Math.max(knnDist_node, dirEntry.getKnnDistance()); } @@ -305,7 +302,7 @@ public class MkMaxTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree * @return a new MkMaxTreeNode which is a leaf node */ @Override - protected MkMaxTreeNode<O, D> createNewLeafNode() { + protected MkMaxTreeNode<O> createNewLeafNode() { return new MkMaxTreeNode<>(leafCapacity, true); } @@ -313,7 +310,7 @@ public class MkMaxTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree * @return a new MkMaxTreeNode which is a directory node */ @Override - protected MkMaxTreeNode<O, D> createNewDirectoryNode() { + protected MkMaxTreeNode<O> createNewDirectoryNode() { return new MkMaxTreeNode<>(dirCapacity, false); } @@ -321,7 +318,7 @@ public class MkMaxTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree * @return a new MkMaxDirectoryEntry representing the specified node */ @Override - protected MkMaxEntry createNewDirectoryEntry(MkMaxTreeNode<O, D> node, DBID routingObjectID, double parentDistance) { + protected MkMaxEntry createNewDirectoryEntry(MkMaxTreeNode<O> node, DBID routingObjectID, double parentDistance) { return new MkMaxDirectoryEntry(routingObjectID, parentDistance, node.getPageID(), node.coveringRadius(routingObjectID, this), node.kNNDistance()); } diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeFactory.java index a03006f4..0838e6b6 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeFactory.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeFactory.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkmax; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -24,7 +24,6 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkmax; */ import de.lmu.ifi.dbs.elki.database.relation.Relation; -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.AbstractMkTreeUnifiedFactory; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.MkTreeSettings; import de.lmu.ifi.dbs.elki.persistent.PageFile; @@ -40,26 +39,25 @@ import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil; * @apiviz.uses MkMaxTreeIndex oneway - - «create» * * @param <O> Object type - * @param <D> Distance type */ -public class MkMaxTreeFactory<O, D extends NumberDistance<D, ?>> extends AbstractMkTreeUnifiedFactory<O, D, MkMaxTreeNode<O, D>, MkMaxEntry, MkMaxTreeIndex<O, D>, MkTreeSettings<O, D, MkMaxTreeNode<O, D>, MkMaxEntry>> { +public class MkMaxTreeFactory<O> extends AbstractMkTreeUnifiedFactory<O, MkMaxTreeNode<O>, MkMaxEntry, MkMaxTreeIndex<O>, MkTreeSettings<O, MkMaxTreeNode<O>, MkMaxEntry>> { /** * Constructor. * * @param pageFileFactory Data storage * @param settings Tree settings */ - public MkMaxTreeFactory(PageFileFactory<?> pageFileFactory, MkTreeSettings<O, D, MkMaxTreeNode<O, D>, MkMaxEntry> settings) { + public MkMaxTreeFactory(PageFileFactory<?> pageFileFactory, MkTreeSettings<O, MkMaxTreeNode<O>, MkMaxEntry> settings) { super(pageFileFactory, settings); } @Override - public MkMaxTreeIndex<O, D> instantiate(Relation<O> relation) { - PageFile<MkMaxTreeNode<O, D>> pagefile = makePageFile(getNodeClass()); + public MkMaxTreeIndex<O> instantiate(Relation<O> relation) { + PageFile<MkMaxTreeNode<O>> pagefile = makePageFile(getNodeClass()); return new MkMaxTreeIndex<>(relation, pagefile, settings); } - protected Class<MkMaxTreeNode<O, D>> getNodeClass() { + protected Class<MkMaxTreeNode<O>> getNodeClass() { return ClassGenericsUtil.uglyCastIntoSubclass(MkMaxTreeNode.class); } @@ -69,15 +67,17 @@ public class MkMaxTreeFactory<O, D extends NumberDistance<D, ?>> extends Abstrac * @author Erich Schubert * * @apiviz.exclude + * + * @param <O> Object type */ - public static class Parameterizer<O, D extends NumberDistance<D, ?>> extends AbstractMkTreeUnifiedFactory.Parameterizer<O, D, MkMaxTreeNode<O, D>, MkMaxEntry, MkTreeSettings<O, D, MkMaxTreeNode<O, D>, MkMaxEntry>> { + public static class Parameterizer<O> extends AbstractMkTreeUnifiedFactory.Parameterizer<O, MkMaxTreeNode<O>, MkMaxEntry, MkTreeSettings<O, MkMaxTreeNode<O>, MkMaxEntry>> { @Override - protected MkMaxTreeFactory<O, D> makeInstance() { + protected MkMaxTreeFactory<O> makeInstance() { return new MkMaxTreeFactory<>(pageFileFactory, settings); } @Override - protected MkTreeSettings<O, D, MkMaxTreeNode<O, D>, MkMaxEntry> makeSettings() { + protected MkTreeSettings<O, MkMaxTreeNode<O>, MkMaxEntry> makeSettings() { return new MkTreeSettings<>(); } } diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeIndex.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeIndex.java index 482c86eb..4468e8b3 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeIndex.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeIndex.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkmax; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -31,7 +31,7 @@ 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.distance.KNNList; +import de.lmu.ifi.dbs.elki.database.ids.KNNList; import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery; import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery; @@ -39,8 +39,6 @@ import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery; import de.lmu.ifi.dbs.elki.database.query.rknn.RKNNQuery; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.DynamicIndex; import de.lmu.ifi.dbs.elki.index.KNNIndex; import de.lmu.ifi.dbs.elki.index.RKNNIndex; @@ -58,9 +56,8 @@ import de.lmu.ifi.dbs.elki.utilities.exceptions.NotImplementedException; * @author Elke Achtert * * @param <O> Object type - * @param <D> Distance type */ -public class MkMaxTreeIndex<O, D extends NumberDistance<D, ?>> extends MkMaxTree<O, D> implements RangeIndex<O>, KNNIndex<O>, RKNNIndex<O>, DynamicIndex { +public class MkMaxTreeIndex<O> extends MkMaxTree<O> implements RangeIndex<O>, KNNIndex<O>, RKNNIndex<O>, DynamicIndex { /** * Relation indexed. */ @@ -73,7 +70,7 @@ public class MkMaxTreeIndex<O, D extends NumberDistance<D, ?>> extends MkMaxTree * @param pagefile Page file * @param settings Tree settings */ - public MkMaxTreeIndex(Relation<O> relation, PageFile<MkMaxTreeNode<O, D>> pagefile, MkTreeSettings<O, D, MkMaxTreeNode<O, D>, MkMaxEntry> settings) { + public MkMaxTreeIndex(Relation<O> relation, PageFile<MkMaxTreeNode<O>> pagefile, MkTreeSettings<O, MkMaxTreeNode<O>, MkMaxEntry> settings) { super(relation, pagefile, settings); this.relation = relation; } @@ -82,8 +79,8 @@ public class MkMaxTreeIndex<O, D extends NumberDistance<D, ?>> extends MkMaxTree * @return a new MkMaxLeafEntry representing the specified data object */ protected MkMaxLeafEntry createNewLeafEntry(DBID id, O object, double parentDistance) { - KNNList<D> knns = knnq.getKNNForObject(object, getKmax() - 1); - double knnDistance = knns.getKNNDistance().doubleValue(); + KNNList knns = knnq.getKNNForObject(object, getKmax() - 1); + double knnDistance = knns.getKNNDistance(); return new MkMaxLeafEntry(id, parentDistance, knnDistance); } @@ -133,14 +130,13 @@ public class MkMaxTreeIndex<O, D extends NumberDistance<D, ?>> extends MkMaxTree throw new NotImplementedException(ExceptionMessages.UNSUPPORTED_NOT_YET); } - @SuppressWarnings("unchecked") @Override - public <S extends Distance<S>> KNNQuery<O, S> getKNNQuery(DistanceQuery<O, S> distanceQuery, Object... hints) { + public KNNQuery<O> getKNNQuery(DistanceQuery<O> distanceQuery, Object... hints) { // Query on the relation we index if (distanceQuery.getRelation() != relation) { return null; } - DistanceFunction<? super O, D> distanceFunction = (DistanceFunction<? super O, D>) distanceQuery.getDistanceFunction(); + DistanceFunction<? super O> distanceFunction = (DistanceFunction<? super O>) distanceQuery.getDistanceFunction(); if (!this.getDistanceFunction().equals(distanceFunction)) { if (getLogger().isDebugging()) { getLogger().debug("Distance function not supported by index - or 'equals' not implemented right!"); @@ -153,18 +149,16 @@ public class MkMaxTreeIndex<O, D extends NumberDistance<D, ?>> extends MkMaxTree return null; } } - DistanceQuery<O, D> dq = distanceFunction.instantiate(relation); - return (KNNQuery<O, S>) MTreeQueryUtil.getKNNQuery(this, dq, hints); + return MTreeQueryUtil.getKNNQuery(this, distanceQuery, hints); } - @SuppressWarnings("unchecked") @Override - public <S extends Distance<S>> RangeQuery<O, S> getRangeQuery(DistanceQuery<O, S> distanceQuery, Object... hints) { + public RangeQuery<O> getRangeQuery(DistanceQuery<O> distanceQuery, Object... hints) { // Query on the relation we index if (distanceQuery.getRelation() != relation) { return null; } - DistanceFunction<? super O, D> distanceFunction = (DistanceFunction<? super O, D>) distanceQuery.getDistanceFunction(); + DistanceFunction<? super O> distanceFunction = (DistanceFunction<? super O>) distanceQuery.getDistanceFunction(); if (!this.getDistanceFunction().equals(distanceFunction)) { if (getLogger().isDebugging()) { getLogger().debug("Distance function not supported by index - or 'equals' not implemented right!"); @@ -177,14 +171,12 @@ public class MkMaxTreeIndex<O, D extends NumberDistance<D, ?>> extends MkMaxTree return null; } } - DistanceQuery<O, D> dq = distanceFunction.instantiate(relation); - return (RangeQuery<O, S>) MTreeQueryUtil.getRangeQuery(this, dq); + return MTreeQueryUtil.getRangeQuery(this, distanceQuery); } - @SuppressWarnings("unchecked") @Override - public <S extends Distance<S>> RKNNQuery<O, S> getRKNNQuery(DistanceQuery<O, S> distanceQuery, Object... hints) { - DistanceFunction<? super O, D> distanceFunction = (DistanceFunction<? super O, D>) distanceQuery.getDistanceFunction(); + public RKNNQuery<O> getRKNNQuery(DistanceQuery<O> distanceQuery, Object... hints) { + DistanceFunction<? super O> distanceFunction = (DistanceFunction<? super O>) distanceQuery.getDistanceFunction(); if (!this.getDistanceFunction().equals(distanceFunction)) { if (getLogger().isDebugging()) { getLogger().debug("Distance function not supported by index - or 'equals' not implemented right!"); @@ -197,8 +189,7 @@ public class MkMaxTreeIndex<O, D extends NumberDistance<D, ?>> extends MkMaxTree return null; } } - DistanceQuery<O, D> dq = distanceFunction.instantiate(relation); - return (RKNNQuery<O, S>) new MkTreeRKNNQuery<>(this, dq); + return new MkTreeRKNNQuery<>(this, distanceQuery); } @Override diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeNode.java index 84c8bdc4..0f9588aa 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeNode.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/MkMaxTreeNode.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkmax; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -24,7 +24,6 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mkmax; */ import de.lmu.ifi.dbs.elki.database.ids.DBID; -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode; @@ -36,9 +35,8 @@ import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode; * @apiviz.has MkMaxEntry oneway - - contains * * @param <O> the type of DatabaseObject to be stored in the MkMaxTree - * @param <D> the type of Distance used in the MkMaxTree */ -class MkMaxTreeNode<O, D extends NumberDistance<D, ?>> extends AbstractMTreeNode<O, D, MkMaxTreeNode<O, D>, MkMaxEntry> { +class MkMaxTreeNode<O> extends AbstractMTreeNode<O, MkMaxTreeNode<O>, MkMaxEntry> { /** * Serial version */ @@ -70,7 +68,7 @@ class MkMaxTreeNode<O, D extends NumberDistance<D, ?>> extends AbstractMTreeNode */ protected double kNNDistance() { double knnDist = 0.; - for (int i = 0; i < getNumEntries(); i++) { + for(int i = 0; i < getNumEntries(); i++) { MkMaxEntry entry = getEntry(i); knnDist = Math.max(knnDist, entry.getKnnDistance()); } @@ -83,7 +81,7 @@ class MkMaxTreeNode<O, D extends NumberDistance<D, ?>> extends AbstractMTreeNode * all its entries. */ @Override - public void adjustEntry(MkMaxEntry entry, DBID routingObjectID, double parentDistance, AbstractMTree<O, D, MkMaxTreeNode<O, D>, MkMaxEntry, ?> mTree) { + public void adjustEntry(MkMaxEntry entry, DBID routingObjectID, double parentDistance, AbstractMTree<O, MkMaxTreeNode<O>, MkMaxEntry, ?> mTree) { super.adjustEntry(entry, routingObjectID, parentDistance, mTree); // adjust knn distance entry.setKnnDistance(kNNDistance()); @@ -94,12 +92,12 @@ class MkMaxTreeNode<O, D extends NumberDistance<D, ?>> extends AbstractMTreeNode * node is correctly set. */ @Override - protected void integrityCheckParameters(MkMaxEntry parentEntry, MkMaxTreeNode<O, D> parent, int index, AbstractMTree<O, D, MkMaxTreeNode<O, D>, MkMaxEntry, ?> mTree) { + protected void integrityCheckParameters(MkMaxEntry parentEntry, MkMaxTreeNode<O> parent, int index, AbstractMTree<O, MkMaxTreeNode<O>, MkMaxEntry, ?> mTree) { super.integrityCheckParameters(parentEntry, parent, index, mTree); // test if knn distance is correctly set MkMaxEntry entry = parent.getEntry(index); double knnDistance = kNNDistance(); - if (Math.abs(entry.getKnnDistance() - knnDistance) > 0) { + if(Math.abs(entry.getKnnDistance() - knnDistance) > 0) { throw new RuntimeException("Wrong knnDistance in node " + parent.getPageID() + " at index " + index + " (child " + entry + ")" + "\nsoll: " + knnDistance + ",\n ist: " + entry.getKnnDistance()); } } diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/package-info.java index 7bd90d66..5b368d2e 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mkmax/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2013 +Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabDirectoryEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabDirectoryEntry.java index 9f088448..c8c9e040 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabDirectoryEntry.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabDirectoryEntry.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mktab; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -53,7 +53,7 @@ class MkTabDirectoryEntry extends MTreeDirectoryEntry implements MkTabEntry { } /** - * Provides a new MkMaxDirectoryEntry with the given parameters. + * Constructor. * * @param objectID the id of the routing object * @param parentDistance the distance from the routing object of this entry to @@ -113,7 +113,6 @@ class MkTabDirectoryEntry extends MTreeDirectoryEntry implements MkTabEntry { * cannot be found. */ @Override - @SuppressWarnings("unchecked") public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { super.readExternal(in); int k_max = in.readInt(); @@ -132,7 +131,6 @@ class MkTabDirectoryEntry extends MTreeDirectoryEntry implements MkTabEntry { * knnDistances as this entry. */ @Override - @SuppressWarnings("unchecked") public boolean equals(Object o) { if (this == o) { return true; diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabEntry.java index a741ed5b..f8e48f2a 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabEntry.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabEntry.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mktab; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabLeafEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabLeafEntry.java index 969ba781..122d031e 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabLeafEntry.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabLeafEntry.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mktab; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -53,7 +53,7 @@ class MkTabLeafEntry extends MTreeLeafEntry implements MkTabEntry { } /** - * Provides a new MkMaxLeafEntry with the given parameters. + * Constructor. * * @param objectID the id of the underlying data object * @param parentDistance the distance from the underlying data object to its @@ -115,7 +115,6 @@ class MkTabLeafEntry extends MTreeLeafEntry implements MkTabEntry { * cannot be found. */ @Override - @SuppressWarnings("unchecked") public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { super.readExternal(in); int k_max = in.readInt(); @@ -133,7 +132,6 @@ class MkTabLeafEntry extends MTreeLeafEntry implements MkTabEntry { * and has the same parameter k_max and knnDistances as this entry. */ @Override - @SuppressWarnings("unchecked") public boolean equals(Object o) { if (this == o) { return true; diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTree.java index 481392cb..3a377420 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTree.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTree.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mktab; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -27,17 +27,17 @@ import java.util.Map; 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.ids.distance.DistanceDBIDList; -import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList; -import de.lmu.ifi.dbs.elki.database.ids.generic.GenericDistanceDBIDList; +import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil; +import de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDList; +import de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDListIter; +import de.lmu.ifi.dbs.elki.database.ids.KNNList; +import de.lmu.ifi.dbs.elki.database.ids.ModifiableDoubleDBIDList; import de.lmu.ifi.dbs.elki.database.relation.Relation; -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.AbstractMkTreeUnified; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.MkTreeSettings; import de.lmu.ifi.dbs.elki.logging.Logging; -import de.lmu.ifi.dbs.elki.persistent.ByteArrayUtil; import de.lmu.ifi.dbs.elki.persistent.PageFile; +import de.lmu.ifi.dbs.elki.utilities.io.ByteArrayUtil; /** * MkTabTree is a metrical index structure based on the concepts of the M-Tree @@ -50,9 +50,8 @@ import de.lmu.ifi.dbs.elki.persistent.PageFile; * @apiviz.has MkTabTreeNode oneway - - contains * * @param <O> Object type - * @param <D> Distance type */ -public class MkTabTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTreeUnified<O, D, MkTabTreeNode<O, D>, MkTabEntry, MkTreeSettings<O, D, MkTabTreeNode<O, D>, MkTabEntry>> { +public class MkTabTree<O> extends AbstractMkTreeUnified<O, MkTabTreeNode<O>, MkTabEntry, MkTreeSettings<O, MkTabTreeNode<O>, MkTabEntry>> { /** * The logger for this class. */ @@ -65,7 +64,7 @@ public class MkTabTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree * @param pagefile Page file * @param settings Settings */ - public MkTabTree(Relation<O> relation, PageFile<MkTabTreeNode<O, D>> pagefile, MkTreeSettings<O, D, MkTabTreeNode<O, D>, MkTabEntry> settings) { + public MkTabTree(Relation<O> relation, PageFile<MkTabTreeNode<O>> pagefile, MkTreeSettings<O, MkTabTreeNode<O>, MkTabEntry> settings) { super(relation, pagefile, settings); } @@ -88,12 +87,12 @@ public class MkTabTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree } @Override - public DistanceDBIDList<D> reverseKNNQuery(DBIDRef id, int k) { - if (k > this.getKmax()) { + public DoubleDBIDList reverseKNNQuery(DBIDRef id, int k) { + if(k > this.getKmax()) { throw new IllegalArgumentException("Parameter k has to be less or equal than " + "parameter kmax of the MkTab-Tree!"); } - GenericDistanceDBIDList<D> result = new GenericDistanceDBIDList<>(); + ModifiableDoubleDBIDList result = DBIDUtil.newDistanceDBIDList(); doReverseKNNQuery(k, id, null, getRoot(), result); result.sort(); @@ -106,7 +105,7 @@ public class MkTabTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree // overhead = index(4), numEntries(4), id(4), isLeaf(0.125) double overhead = 12.125; - if (getPageSize() - overhead < 0) { + if(getPageSize() - overhead < 0) { throw new RuntimeException("Node size of " + getPageSize() + " Bytes is chosen too small!"); } @@ -114,11 +113,11 @@ public class MkTabTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree // coveringRadius + parentDistance + kmax + kmax * knnDistance) + 1 dirCapacity = (int) (getPageSize() - overhead) / (4 + 4 + distanceSize + distanceSize + 4 + getKmax() * distanceSize) + 1; - if (dirCapacity <= 1) { + if(dirCapacity <= 1) { throw new RuntimeException("Node size of " + getPageSize() + " Bytes is chosen too small!"); } - if (dirCapacity < 10) { + if(dirCapacity < 10) { LOG.warning("Page size is choosen too small! Maximum number of entries " + "in a directory node = " + (dirCapacity - 1)); } @@ -126,34 +125,35 @@ public class MkTabTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree // kmax + kmax * knnDistance) + 1 leafCapacity = (int) (getPageSize() - overhead) / (4 + distanceSize + 4 + getKmax() * distanceSize) + 1; - if (leafCapacity <= 1) { + if(leafCapacity <= 1) { throw new RuntimeException("Node size of " + getPageSize() + " Bytes is chosen too small!"); } - if (leafCapacity < 10) { + if(leafCapacity < 10) { LOG.warning("Page size is choosen too small! Maximum number of entries " + "in a leaf node = " + (leafCapacity - 1)); } } @Override - protected void kNNdistanceAdjustment(MkTabEntry entry, Map<DBID, KNNList<D>> knnLists) { - MkTabTreeNode<O, D> node = getNode(entry); + protected void kNNdistanceAdjustment(MkTabEntry entry, Map<DBID, KNNList> knnLists) { + MkTabTreeNode<O> node = getNode(entry); double[] knnDistances_node = initKnnDistanceList(); - if (node.isLeaf()) { - for (int i = 0; i < node.getNumEntries(); i++) { + if(node.isLeaf()) { + for(int i = 0; i < node.getNumEntries(); i++) { MkTabEntry leafEntry = node.getEntry(i); - KNNList<D> knns = knnLists.get(getPageID(leafEntry)); + KNNList knns = knnLists.get(getPageID(leafEntry)); double[] distances = new double[knns.size()]; int j = 0; - for (DistanceDBIDListIter<D> iter = knns.iter(); iter.valid(); iter.advance(), j++) { - distances[i] = iter.getDistance().doubleValue(); + for(DoubleDBIDListIter iter = knns.iter(); iter.valid(); iter.advance(), j++) { + distances[j] = iter.doubleValue(); } leafEntry.setKnnDistances(distances); // FIXME: save copy knnDistances_node = max(knnDistances_node, leafEntry.getKnnDistances()); } - } else { - for (int i = 0; i < node.getNumEntries(); i++) { + } + else { + for(int i = 0; i < node.getNumEntries(); i++) { MkTabEntry dirEntry = node.getEntry(i); kNNdistanceAdjustment(dirEntry, knnLists); // FIXME: save copy @@ -164,7 +164,7 @@ public class MkTabTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree } @Override - protected MkTabTreeNode<O, D> createNewLeafNode() { + protected MkTabTreeNode<O> createNewLeafNode() { return new MkTabTreeNode<>(leafCapacity, true); } @@ -174,7 +174,7 @@ public class MkTabTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree * @return a new directory node */ @Override - protected MkTabTreeNode<O, D> createNewDirectoryNode() { + protected MkTabTreeNode<O> createNewDirectoryNode() { return new MkTabTreeNode<>(dirCapacity, false); } @@ -187,7 +187,7 @@ public class MkTabTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree * the routing object of the parent node */ @Override - protected MkTabEntry createNewDirectoryEntry(MkTabTreeNode<O, D> node, DBID routingObjectID, double parentDistance) { + protected MkTabEntry createNewDirectoryEntry(MkTabTreeNode<O> node, DBID routingObjectID, double parentDistance) { return new MkTabDirectoryEntry(routingObjectID, parentDistance, node.getPageID(), node.coveringRadius(routingObjectID, this), node.kNNDistances()); } @@ -213,13 +213,13 @@ public class MkTabTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree * @param node the root of the subtree * @param result the list holding the query result */ - private void doReverseKNNQuery(int k, DBIDRef q, MkTabEntry node_entry, MkTabTreeNode<O, D> node, GenericDistanceDBIDList<D> result) { + private void doReverseKNNQuery(int k, DBIDRef q, MkTabEntry node_entry, MkTabTreeNode<O> node, ModifiableDoubleDBIDList result) { // data node - if (node.isLeaf()) { - for (int i = 0; i < node.getNumEntries(); i++) { + if(node.isLeaf()) { + for(int i = 0; i < node.getNumEntries(); i++) { MkTabEntry entry = node.getEntry(i); - D distance = distance(entry.getRoutingObjectID(), q); - if (distance.doubleValue() <= entry.getKnnDistance(k)) { + double distance = distance(entry.getRoutingObjectID(), q); + if(distance <= entry.getKnnDistance(k)) { result.add(distance, entry.getRoutingObjectID()); } } @@ -227,15 +227,15 @@ public class MkTabTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree // directory node else { - for (int i = 0; i < node.getNumEntries(); i++) { + for(int i = 0; i < node.getNumEntries(); i++) { MkTabEntry entry = node.getEntry(i); double node_knnDist = node_entry != null ? node_entry.getKnnDistance(k) : Double.POSITIVE_INFINITY; - double distance = distance(entry.getRoutingObjectID(), q).doubleValue(); + double distance = distance(entry.getRoutingObjectID(), q); double minDist = (entry.getCoveringRadius() > distance) ? 0. : distance - entry.getCoveringRadius(); - if (minDist <= node_knnDist) { - MkTabTreeNode<O, D> childNode = getNode(entry); + if(minDist <= node_knnDist) { + MkTabTreeNode<O> childNode = getNode(entry); doReverseKNNQuery(k, q, entry, childNode, result); } } @@ -252,12 +252,12 @@ public class MkTabTree<O, D extends NumberDistance<D, ?>> extends AbstractMkTree * in each index */ private double[] max(double[] distances1, double[] distances2) { - if (distances1.length != distances2.length) { + if(distances1.length != distances2.length) { throw new RuntimeException("different lengths!"); } double[] result = new double[distances1.length]; - for (int i = 0; i < distances1.length; i++) { + for(int i = 0; i < distances1.length; i++) { result[i] = Math.max(distances1[i], distances2[i]); } return result; diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTreeFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTreeFactory.java index 9ede76ad..565735f1 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTreeFactory.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTreeFactory.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mktab; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -24,7 +24,6 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mktab; */ import de.lmu.ifi.dbs.elki.database.relation.Relation; -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.AbstractMkTreeUnifiedFactory; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.MkTreeSettings; import de.lmu.ifi.dbs.elki.persistent.PageFile; @@ -40,26 +39,25 @@ import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil; * @apiviz.uses MkTabTreeIndex oneway - - «create» * * @param <O> Object type - * @param <D> Distance type */ -public class MkTabTreeFactory<O, D extends NumberDistance<D, ?>> extends AbstractMkTreeUnifiedFactory<O, D, MkTabTreeNode<O, D>, MkTabEntry, MkTabTreeIndex<O, D>, MkTreeSettings<O, D, MkTabTreeNode<O, D>, MkTabEntry>> { +public class MkTabTreeFactory<O> extends AbstractMkTreeUnifiedFactory<O, MkTabTreeNode<O>, MkTabEntry, MkTabTreeIndex<O>, MkTreeSettings<O, MkTabTreeNode<O>, MkTabEntry>> { /** * Constructor. * * @param pageFileFactory Data storage * @param settings Tree settings */ - public MkTabTreeFactory(PageFileFactory<?> pageFileFactory, MkTreeSettings<O, D, MkTabTreeNode<O, D>, MkTabEntry> settings) { + public MkTabTreeFactory(PageFileFactory<?> pageFileFactory, MkTreeSettings<O, MkTabTreeNode<O>, MkTabEntry> settings) { super(pageFileFactory, settings); } @Override - public MkTabTreeIndex<O, D> instantiate(Relation<O> relation) { - PageFile<MkTabTreeNode<O, D>> pagefile = makePageFile(getNodeClass()); + public MkTabTreeIndex<O> instantiate(Relation<O> relation) { + PageFile<MkTabTreeNode<O>> pagefile = makePageFile(getNodeClass()); return new MkTabTreeIndex<>(relation, pagefile, settings); } - protected Class<MkTabTreeNode<O, D>> getNodeClass() { + protected Class<MkTabTreeNode<O>> getNodeClass() { return ClassGenericsUtil.uglyCastIntoSubclass(MkTabTreeNode.class); } @@ -70,14 +68,14 @@ public class MkTabTreeFactory<O, D extends NumberDistance<D, ?>> extends Abstrac * * @apiviz.exclude */ - public static class Parameterizer<O, D extends NumberDistance<D, ?>> extends AbstractMkTreeUnifiedFactory.Parameterizer<O, D, MkTabTreeNode<O, D>, MkTabEntry, MkTreeSettings<O, D, MkTabTreeNode<O, D>, MkTabEntry>> { + public static class Parameterizer<O> extends AbstractMkTreeUnifiedFactory.Parameterizer<O, MkTabTreeNode<O>, MkTabEntry, MkTreeSettings<O, MkTabTreeNode<O>, MkTabEntry>> { @Override - protected MkTabTreeFactory<O, D> makeInstance() { + protected MkTabTreeFactory<O> makeInstance() { return new MkTabTreeFactory<>(pageFileFactory, settings); } @Override - protected MkTreeSettings<O, D, MkTabTreeNode<O, D>, MkTabEntry> makeSettings() { + protected MkTreeSettings<O, MkTabTreeNode<O>, MkTabEntry> makeSettings() { return new MkTreeSettings<>(); } } diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTreeIndex.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTreeIndex.java index 150f03e8..713514ff 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTreeIndex.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTreeIndex.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mktab; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -29,8 +29,8 @@ 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.DBIDUtil; -import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDListIter; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList; +import de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDListIter; +import de.lmu.ifi.dbs.elki.database.ids.KNNList; import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery; import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery; @@ -38,8 +38,6 @@ import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery; import de.lmu.ifi.dbs.elki.database.query.rknn.RKNNQuery; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.KNNIndex; import de.lmu.ifi.dbs.elki.index.RKNNIndex; import de.lmu.ifi.dbs.elki.index.RangeIndex; @@ -54,9 +52,8 @@ import de.lmu.ifi.dbs.elki.persistent.PageFile; * @author Erich Schubert * * @param <O> Object type - * @param <D> Distance type */ -public class MkTabTreeIndex<O, D extends NumberDistance<D, ?>> extends MkTabTree<O, D> implements RangeIndex<O>, KNNIndex<O>, RKNNIndex<O> { +public class MkTabTreeIndex<O> extends MkTabTree<O> implements RangeIndex<O>, KNNIndex<O>, RKNNIndex<O> { /** * The relation indexed. */ @@ -69,7 +66,7 @@ public class MkTabTreeIndex<O, D extends NumberDistance<D, ?>> extends MkTabTree * @param pagefile Page file * @param settings Tree settings */ - public MkTabTreeIndex(Relation<O> relation, PageFile<MkTabTreeNode<O, D>> pagefile, MkTreeSettings<O, D, MkTabTreeNode<O, D>, MkTabEntry> settings) { + public MkTabTreeIndex(Relation<O> relation, PageFile<MkTabTreeNode<O>> pagefile, MkTreeSettings<O, MkTabTreeNode<O>, MkTabEntry> settings) { super(relation, pagefile, settings); this.relation = relation; } @@ -93,11 +90,11 @@ public class MkTabTreeIndex<O, D extends NumberDistance<D, ?>> extends MkTabTree * @return the knn distance of the object with the specified id */ private double[] knnDistances(O object) { - KNNList<D> knns = knnq.getKNNForObject(object, getKmax() - 1); + KNNList knns = knnq.getKNNForObject(object, getKmax() - 1); double[] distances = new double[getKmax()]; int i = 0; - for (DistanceDBIDListIter<D> iter = knns.iter(); iter.valid() && i < getKmax(); iter.advance(), i++) { - distances[i] = iter.getDistance().doubleValue(); + for (DoubleDBIDListIter iter = knns.iter(); iter.valid() && i < getKmax(); iter.advance(), i++) { + distances[i] = iter.doubleValue(); } return distances; } @@ -114,14 +111,13 @@ public class MkTabTreeIndex<O, D extends NumberDistance<D, ?>> extends MkTabTree insertAll(objs); } - @SuppressWarnings("unchecked") @Override - public <S extends Distance<S>> KNNQuery<O, S> getKNNQuery(DistanceQuery<O, S> distanceQuery, Object... hints) { + public KNNQuery<O> getKNNQuery(DistanceQuery<O> distanceQuery, Object... hints) { // Query on the relation we index if (distanceQuery.getRelation() != relation) { return null; } - DistanceFunction<? super O, D> distanceFunction = (DistanceFunction<? super O, D>) distanceQuery.getDistanceFunction(); + DistanceFunction<? super O> distanceFunction = (DistanceFunction<? super O>) distanceQuery.getDistanceFunction(); if (!this.getDistanceFunction().equals(distanceFunction)) { if (getLogger().isDebugging()) { getLogger().debug("Distance function not supported by index - or 'equals' not implemented right!"); @@ -134,18 +130,16 @@ public class MkTabTreeIndex<O, D extends NumberDistance<D, ?>> extends MkTabTree return null; } } - DistanceQuery<O, D> dq = distanceFunction.instantiate(relation); - return (KNNQuery<O, S>) MTreeQueryUtil.getKNNQuery(this, dq, hints); + return MTreeQueryUtil.getKNNQuery(this, distanceQuery, hints); } - @SuppressWarnings("unchecked") @Override - public <S extends Distance<S>> RangeQuery<O, S> getRangeQuery(DistanceQuery<O, S> distanceQuery, Object... hints) { + public RangeQuery<O> getRangeQuery(DistanceQuery<O> distanceQuery, Object... hints) { // Query on the relation we index if (distanceQuery.getRelation() != relation) { return null; } - DistanceFunction<? super O, D> distanceFunction = (DistanceFunction<? super O, D>) distanceQuery.getDistanceFunction(); + DistanceFunction<? super O> distanceFunction = (DistanceFunction<? super O>) distanceQuery.getDistanceFunction(); if (!this.getDistanceFunction().equals(distanceFunction)) { if (getLogger().isDebugging()) { getLogger().debug("Distance function not supported by index - or 'equals' not implemented right!"); @@ -158,14 +152,12 @@ public class MkTabTreeIndex<O, D extends NumberDistance<D, ?>> extends MkTabTree return null; } } - DistanceQuery<O, D> dq = distanceFunction.instantiate(relation); - return (RangeQuery<O, S>) MTreeQueryUtil.getRangeQuery(this, dq); + return MTreeQueryUtil.getRangeQuery(this, distanceQuery); } - @SuppressWarnings("unchecked") @Override - public <S extends Distance<S>> RKNNQuery<O, S> getRKNNQuery(DistanceQuery<O, S> distanceQuery, Object... hints) { - DistanceFunction<? super O, D> distanceFunction = (DistanceFunction<? super O, D>) distanceQuery.getDistanceFunction(); + public RKNNQuery<O> getRKNNQuery(DistanceQuery<O> distanceQuery, Object... hints) { + DistanceFunction<? super O> distanceFunction = (DistanceFunction<? super O>) distanceQuery.getDistanceFunction(); if (!this.getDistanceFunction().equals(distanceFunction)) { if (getLogger().isDebugging()) { getLogger().debug("Distance function not supported by index - or 'equals' not implemented right!"); @@ -178,8 +170,7 @@ public class MkTabTreeIndex<O, D extends NumberDistance<D, ?>> extends MkTabTree return null; } } - DistanceQuery<O, D> dq = distanceFunction.instantiate(relation); - return (RKNNQuery<O, S>) new MkTreeRKNNQuery<>(this, dq); + return new MkTreeRKNNQuery<>(this, distanceQuery); } @Override diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTreeNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTreeNode.java index 1942a78b..913a3261 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTreeNode.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/MkTabTreeNode.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mktab; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -24,7 +24,6 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.mktab; */ import de.lmu.ifi.dbs.elki.database.ids.DBID; -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode; @@ -36,9 +35,8 @@ import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode; * @apiviz.has MkTabEntry oneway - - contains * * @param <O> object type - * @param <D> distance type */ -class MkTabTreeNode<O, D extends NumberDistance<D, ?>> extends AbstractMTreeNode<O, D, MkTabTreeNode<O, D>, MkTabEntry> { +class MkTabTreeNode<O> extends AbstractMTreeNode<O, MkTabTreeNode<O>, MkTabEntry> { private static final long serialVersionUID = 2; /** @@ -81,7 +79,7 @@ class MkTabTreeNode<O, D extends NumberDistance<D, ?>> extends AbstractMTreeNode } @Override - public void adjustEntry(MkTabEntry entry, DBID routingObjectID, double parentDistance, AbstractMTree<O, D, MkTabTreeNode<O, D>, MkTabEntry, ?> mTree) { + public void adjustEntry(MkTabEntry entry, DBID routingObjectID, double parentDistance, AbstractMTree<O, MkTabTreeNode<O>, MkTabEntry, ?> mTree) { super.adjustEntry(entry, routingObjectID, parentDistance, mTree); // adjust knn distances entry.setKnnDistances(kNNDistances()); @@ -96,7 +94,7 @@ class MkTabTreeNode<O, D extends NumberDistance<D, ?>> extends AbstractMTreeNode * @param mTree the underlying M-Tree */ @Override - protected void integrityCheckParameters(MkTabEntry parentEntry, MkTabTreeNode<O, D> parent, int index, AbstractMTree<O, D, MkTabTreeNode<O, D>, MkTabEntry, ?> mTree) { + protected void integrityCheckParameters(MkTabEntry parentEntry, MkTabTreeNode<O> parent, int index, AbstractMTree<O, MkTabTreeNode<O>, MkTabEntry, ?> mTree) { super.integrityCheckParameters(parentEntry, parent, index, mTree); // test knn distances MkTabEntry entry = parent.getEntry(index); diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/package-info.java index ed3e24d3..8b81f375 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/mktab/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2013 +Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/package-info.java index 13b23e16..976b3436 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mktrees/package-info.java @@ -7,7 +7,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2013 +Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTree.java index 1b3d1481..78a8b95e 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTree.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTree.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mtree; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -24,7 +24,6 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mtree; */ import de.lmu.ifi.dbs.elki.database.ids.DBID; -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeDirectoryEntry; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry; @@ -53,12 +52,11 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Title; * @apiviz.has MTreeNode oneway - - contains * * @param <O> the type of DatabaseObject to be stored in the metrical index - * @param <D> the type of Distance used in the metrical index */ @Title("M-Tree") @Description("Efficient Access Method for Similarity Search in Metric Spaces") @Reference(authors = "P. Ciaccia, M. Patella, P. Zezula", title = "M-tree: An Efficient Access Method for Similarity Search in Metric Spaces", booktitle = "VLDB'97, Proceedings of 23rd International Conference on Very Large Data Bases, August 25-29, 1997, Athens, Greece", url = "http://www.vldb.org/conf/1997/P426.PDF") -abstract public class MTree<O, D extends NumberDistance<D, ?>> extends AbstractMTree<O, D, MTreeNode<O, D>, MTreeEntry, MTreeSettings<O, D, MTreeNode<O, D>, MTreeEntry>> { +abstract public class MTree<O> extends AbstractMTree<O, MTreeNode<O>, MTreeEntry, MTreeSettings<O, MTreeNode<O>, MTreeEntry>> { /** * The logger for this class. */ @@ -70,7 +68,7 @@ abstract public class MTree<O, D extends NumberDistance<D, ?>> extends AbstractM * @param pagefile Page file * @param settings Tree settings */ - public MTree(PageFile<MTreeNode<O, D>> pagefile, MTreeSettings<O, D, MTreeNode<O, D>, MTreeEntry> settings) { + public MTree(PageFile<MTreeNode<O>> pagefile, MTreeSettings<O, MTreeNode<O>, MTreeEntry> settings) { super(pagefile, settings); } @@ -86,7 +84,7 @@ abstract public class MTree<O, D extends NumberDistance<D, ?>> extends AbstractM * @return a new MTreeDirectoryEntry representing the specified node */ @Override - protected MTreeEntry createNewDirectoryEntry(MTreeNode<O, D> node, DBID routingObjectID, double parentDistance) { + protected MTreeEntry createNewDirectoryEntry(MTreeNode<O> node, DBID routingObjectID, double parentDistance) { return new MTreeDirectoryEntry(routingObjectID, parentDistance, node.getPageID(), node.coveringRadius(routingObjectID, this)); } @@ -103,7 +101,7 @@ abstract public class MTree<O, D extends NumberDistance<D, ?>> extends AbstractM * @return a new MTreeNode which is a leaf node */ @Override - protected MTreeNode<O, D> createNewLeafNode() { + protected MTreeNode<O> createNewLeafNode() { return new MTreeNode<>(leafCapacity, true); } @@ -111,7 +109,7 @@ abstract public class MTree<O, D extends NumberDistance<D, ?>> extends AbstractM * @return a new MTreeNode which is a directory node */ @Override - protected MTreeNode<O, D> createNewDirectoryNode() { + protected MTreeNode<O> createNewDirectoryNode() { return new MTreeNode<>(dirCapacity, false); } diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeFactory.java index dbc27511..1d6a06a6 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeFactory.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeFactory.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mtree; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -24,7 +24,6 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mtree; */ import de.lmu.ifi.dbs.elki.database.relation.Relation; -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeFactory; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeSettings; @@ -42,27 +41,26 @@ import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil; * @apiviz.uses MTreeIndex oneway - - «create» * * @param <O> Object type - * @param <D> Distance type */ @Alias({ "mtree", "m" }) -public class MTreeFactory<O, D extends NumberDistance<D, ?>> extends AbstractMTreeFactory<O, D, MTreeNode<O, D>, MTreeEntry, MTreeIndex<O, D>, MTreeSettings<O, D, MTreeNode<O, D>, MTreeEntry>> { +public class MTreeFactory<O> extends AbstractMTreeFactory<O, MTreeNode<O>, MTreeEntry, MTreeIndex<O>, MTreeSettings<O, MTreeNode<O>, MTreeEntry>> { /** * Constructor. * * @param pageFileFactory Data storage * @param settings Tree settings */ - public MTreeFactory(PageFileFactory<?> pageFileFactory, MTreeSettings<O, D, MTreeNode<O, D>, MTreeEntry> settings) { + public MTreeFactory(PageFileFactory<?> pageFileFactory, MTreeSettings<O, MTreeNode<O>, MTreeEntry> settings) { super(pageFileFactory, settings); } @Override - public MTreeIndex<O, D> instantiate(Relation<O> relation) { - PageFile<MTreeNode<O, D>> pagefile = makePageFile(getNodeClass()); + public MTreeIndex<O> instantiate(Relation<O> relation) { + PageFile<MTreeNode<O>> pagefile = makePageFile(getNodeClass()); return new MTreeIndex<>(relation, pagefile, settings); } - protected Class<MTreeNode<O, D>> getNodeClass() { + protected Class<MTreeNode<O>> getNodeClass() { return ClassGenericsUtil.uglyCastIntoSubclass(MTreeNode.class); } @@ -72,15 +70,17 @@ public class MTreeFactory<O, D extends NumberDistance<D, ?>> extends AbstractMTr * @author Erich Schubert * * @apiviz.exclude + * + * @param <O> Object type */ - public static class Parameterizer<O, D extends NumberDistance<D, ?>> extends AbstractMTreeFactory.Parameterizer<O, D, MTreeNode<O, D>, MTreeEntry, MTreeSettings<O, D, MTreeNode<O, D>, MTreeEntry>> { + public static class Parameterizer<O> extends AbstractMTreeFactory.Parameterizer<O, MTreeNode<O>, MTreeEntry, MTreeSettings<O, MTreeNode<O>, MTreeEntry>> { @Override - protected MTreeFactory<O, D> makeInstance() { + protected MTreeFactory<O> makeInstance() { return new MTreeFactory<>(pageFileFactory, settings); } @Override - protected MTreeSettings<O, D, MTreeNode<O, D>, MTreeEntry> makeSettings() { + protected MTreeSettings<O, MTreeNode<O>, MTreeEntry> makeSettings() { return new MTreeSettings<>(); } } diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeIndex.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeIndex.java index 32908a1e..e5dd8972 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeIndex.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeIndex.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mtree; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -39,8 +39,6 @@ import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.database.relation.RelationUtil; import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.DynamicIndex; import de.lmu.ifi.dbs.elki.index.KNNIndex; import de.lmu.ifi.dbs.elki.index.RangeIndex; @@ -48,10 +46,10 @@ import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeLeafEntry; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeSettings; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query.MTreeQueryUtil; -import de.lmu.ifi.dbs.elki.persistent.ByteArrayUtil; import de.lmu.ifi.dbs.elki.persistent.PageFile; import de.lmu.ifi.dbs.elki.utilities.exceptions.ExceptionMessages; import de.lmu.ifi.dbs.elki.utilities.exceptions.NotImplementedException; +import de.lmu.ifi.dbs.elki.utilities.io.ByteArrayUtil; /** * Class for using an m-tree as database index. @@ -59,9 +57,8 @@ import de.lmu.ifi.dbs.elki.utilities.exceptions.NotImplementedException; * @author Erich Schubert * * @param <O> Object type - * @param <D> Distance type */ -public class MTreeIndex<O, D extends NumberDistance<D, ?>> extends MTree<O, D> implements RangeIndex<O>, KNNIndex<O>, DynamicIndex { +public class MTreeIndex<O> extends MTree<O> implements RangeIndex<O>, KNNIndex<O>, DynamicIndex { /** * The relation indexed. */ @@ -70,7 +67,7 @@ public class MTreeIndex<O, D extends NumberDistance<D, ?>> extends MTree<O, D> i /** * The distance query. */ - protected DistanceQuery<O, D> distanceQuery; + protected DistanceQuery<O> distanceQuery; /** * Constructor. @@ -79,16 +76,16 @@ public class MTreeIndex<O, D extends NumberDistance<D, ?>> extends MTree<O, D> i * @param pagefile Page file * @param settings Tree settings */ - public MTreeIndex(Relation<O> relation, PageFile<MTreeNode<O, D>> pagefile, MTreeSettings<O, D, MTreeNode<O, D>, MTreeEntry> settings) { + public MTreeIndex(Relation<O> relation, PageFile<MTreeNode<O>> pagefile, MTreeSettings<O, MTreeNode<O>, MTreeEntry> settings) { super(pagefile, settings); this.relation = relation; this.distanceQuery = getDistanceFunction().instantiate(relation); } @Override - public D distance(DBIDRef id1, DBIDRef id2) { + public double distance(DBIDRef id1, DBIDRef id2) { if (id1 == null || id2 == null) { - return getDistanceFactory().undefinedDistance(); + return Double.NaN; } statistics.countDistanceCalculation(); return distanceQuery.distance(id1, id2); @@ -196,14 +193,13 @@ public class MTreeIndex<O, D extends NumberDistance<D, ?>> extends MTree<O, D> i throw new NotImplementedException(ExceptionMessages.UNSUPPORTED_NOT_YET); } - @SuppressWarnings("unchecked") @Override - public <S extends Distance<S>> KNNQuery<O, S> getKNNQuery(DistanceQuery<O, S> distanceQuery, Object... hints) { + public KNNQuery<O> getKNNQuery(DistanceQuery<O> distanceQuery, Object... hints) { // Query on the relation we index if (distanceQuery.getRelation() != relation) { return null; } - DistanceFunction<? super O, D> distanceFunction = (DistanceFunction<? super O, D>) distanceQuery.getDistanceFunction(); + DistanceFunction<? super O> distanceFunction = (DistanceFunction<? super O>) distanceQuery.getDistanceFunction(); if (!this.getDistanceFunction().equals(distanceFunction)) { if (getLogger().isDebugging()) { getLogger().debug("Distance function not supported by index - or 'equals' not implemented right!"); @@ -216,18 +212,17 @@ public class MTreeIndex<O, D extends NumberDistance<D, ?>> extends MTree<O, D> i return null; } } - DistanceQuery<O, D> dq = distanceFunction.instantiate(relation); - return (KNNQuery<O, S>) MTreeQueryUtil.getKNNQuery(this, dq, hints); + DistanceQuery<O> dq = distanceFunction.instantiate(relation); + return MTreeQueryUtil.getKNNQuery(this, dq, hints); } - @SuppressWarnings("unchecked") @Override - public <S extends Distance<S>> RangeQuery<O, S> getRangeQuery(DistanceQuery<O, S> distanceQuery, Object... hints) { + public RangeQuery<O> getRangeQuery(DistanceQuery<O> distanceQuery, Object... hints) { // Query on the relation we index if (distanceQuery.getRelation() != relation) { return null; } - DistanceFunction<? super O, D> distanceFunction = (DistanceFunction<? super O, D>) distanceQuery.getDistanceFunction(); + DistanceFunction<? super O> distanceFunction = (DistanceFunction<? super O>) distanceQuery.getDistanceFunction(); if (!this.getDistanceFunction().equals(distanceFunction)) { if (getLogger().isDebugging()) { getLogger().debug("Distance function not supported by index - or 'equals' not implemented right!"); @@ -240,8 +235,8 @@ public class MTreeIndex<O, D extends NumberDistance<D, ?>> extends MTree<O, D> i return null; } } - DistanceQuery<O, D> dq = distanceFunction.instantiate(relation); - return (RangeQuery<O, S>) MTreeQueryUtil.getRangeQuery(this, dq); + DistanceQuery<O> dq = distanceFunction.instantiate(relation); + return MTreeQueryUtil.getRangeQuery(this, dq); } @Override diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeNode.java index b3aa77fb..61dc7594 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeNode.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/MTreeNode.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mtree; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,7 +23,6 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mtree; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry; @@ -32,9 +31,8 @@ import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry; * * @author Elke Achtert * @param <O> Object type - * @param <D> Distance type */ -public class MTreeNode<O, D extends NumberDistance<D, ?>> extends AbstractMTreeNode<O, D, MTreeNode<O, D>, MTreeEntry> { +public class MTreeNode<O> extends AbstractMTreeNode<O, MTreeNode<O>, MTreeEntry> { /** * Serial version */ diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/package-info.java index c10d683b..aec2fd17 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/mtree/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2013 +Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/package-info.java index 03a4a4d6..922a299a 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2013 +Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/DoubleDistanceMetricalIndexKNNQuery.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/DoubleDistanceMetricalIndexKNNQuery.java deleted file mode 100644 index b55b9fd0..00000000 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/DoubleDistanceMetricalIndexKNNQuery.java +++ /dev/null @@ -1,143 +0,0 @@ -package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query; - -/* - This file is part of ELKI: - Environment for Developing KDD-Applications Supported by Index-Structures - - Copyright (C) 2013 - Ludwig-Maximilians-Universität München - Lehr- und Forschungseinheit für Datenbanksysteme - ELKI Development Team - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -import de.lmu.ifi.dbs.elki.database.ids.DBID; -import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil; -import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNHeap; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList; -import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; -import de.lmu.ifi.dbs.elki.database.query.knn.AbstractDistanceKNNQuery; -import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; -import de.lmu.ifi.dbs.elki.index.tree.DirectoryEntry; -import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree; -import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode; -import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry; -import de.lmu.ifi.dbs.elki.index.tree.query.DoubleMTreeDistanceSearchCandidate; -import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.ComparableMinHeap; - -/** - * Instance of a KNN query for a particular spatial index. - * - * @author Erich Schubert - * - * @apiviz.uses AbstractMTree - * - * @param <O> Object type - */ -public class DoubleDistanceMetricalIndexKNNQuery<O> extends AbstractDistanceKNNQuery<O, DoubleDistance> { - /** - * The index to use - */ - protected final AbstractMTree<O, DoubleDistance, ?, ?, ?> index; - - /** - * Distance function - */ - protected PrimitiveDoubleDistanceFunction<? super O> distf; - - /** - * Constructor. - * - * @param index Index to use - * @param distanceQuery Distance query used - * @param distf Distance function - */ - public DoubleDistanceMetricalIndexKNNQuery(AbstractMTree<O, DoubleDistance, ?, ?, ?> index, DistanceQuery<O, DoubleDistance> distanceQuery, PrimitiveDoubleDistanceFunction<? super O> distf) { - super(distanceQuery); - this.index = index; - this.distf = distf; - } - - @Override - public KNNList<DoubleDistance> getKNNForObject(O q, int k) { - if (k < 1) { - throw new IllegalArgumentException("At least one object has to be requested!"); - } - index.statistics.countKNNQuery(); - - DoubleDistanceKNNHeap knnList = DBIDUtil.newDoubleDistanceHeap(k); - double d_k = Double.POSITIVE_INFINITY; - - final ComparableMinHeap<DoubleMTreeDistanceSearchCandidate> pq = new ComparableMinHeap<>(); - - // Push the root node - pq.add(new DoubleMTreeDistanceSearchCandidate(0, index.getRootID(), null, 0)); - - // search in tree - while (!pq.isEmpty()) { - DoubleMTreeDistanceSearchCandidate pqNode = pq.poll(); - DBID id_p = pqNode.routingObjectID; - double d1 = pqNode.routingDistance; - - if (knnList.size() >= k && pqNode.mindist > d_k) { - break; - } - - AbstractMTreeNode<?, DoubleDistance, ?, ?> node = index.getNode(pqNode.nodeID); - - // directory node - if (!node.isLeaf()) { - for (int i = 0; i < node.getNumEntries(); i++) { - final MTreeEntry entry = node.getEntry(i); - final DBID id_i = entry.getRoutingObjectID(); - double or_i = entry.getCoveringRadius(); - double d2 = id_p != null ? entry.getParentDistance() : 0; - double diff = Math.abs(d1 - d2); - - if (diff <= d_k + or_i) { - final O ob_i = relation.get(id_i); - double d3 = distf.doubleDistance(ob_i, q); - index.statistics.countDistanceCalculation(); - double d_min = Math.max(d3 - or_i, 0); - if (d_min <= d_k) { - pq.add(new DoubleMTreeDistanceSearchCandidate(d_min, ((DirectoryEntry) entry).getPageID(), id_i, d3)); - } - } - } - } - // data node - else { - for (int i = 0; i < node.getNumEntries(); i++) { - final MTreeEntry entry = node.getEntry(i); - final DBID id_i = entry.getRoutingObjectID(); - double d2 = id_p != null ? entry.getParentDistance() : 0; - double diff = Math.abs(d1 - d2); - - if (diff <= d_k) { - final O o_i = relation.get(id_i); - double d3 = distf.doubleDistance(o_i, q); - index.statistics.countDistanceCalculation(); - if (d3 <= d_k) { - knnList.insert(d3, id_i); - d_k = knnList.doubleKNNDistance(); - } - } - } - } - } - return knnList.toKNNList(); - } -} diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/DoubleDistanceMetricalIndexRangeQuery.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/DoubleDistanceMetricalIndexRangeQuery.java deleted file mode 100644 index 714498d4..00000000 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/DoubleDistanceMetricalIndexRangeQuery.java +++ /dev/null @@ -1,137 +0,0 @@ -package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query; - -/* - This file is part of ELKI: - Environment for Developing KDD-Applications Supported by Index-Structures - - Copyright (C) 2013 - Ludwig-Maximilians-Universität München - Lehr- und Forschungseinheit für Datenbanksysteme - ELKI Development Team - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -import de.lmu.ifi.dbs.elki.database.ids.DBID; -import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList; -import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPairList; -import de.lmu.ifi.dbs.elki.database.ids.distance.ModifiableDoubleDistanceDBIDList; -import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; -import de.lmu.ifi.dbs.elki.database.query.range.AbstractDistanceRangeQuery; -import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; -import de.lmu.ifi.dbs.elki.index.tree.DirectoryEntry; -import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree; -import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode; -import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry; - -/** - * Instance of a range query for a particular spatial index. - * - * @author Erich Schubert - * - * @apiviz.uses AbstractMTree - */ -public class DoubleDistanceMetricalIndexRangeQuery<O> extends AbstractDistanceRangeQuery<O, DoubleDistance> { - /** - * The index to use - */ - protected final AbstractMTree<O, DoubleDistance, ?, ?, ?> index; - - /** - * Distance function - */ - protected PrimitiveDoubleDistanceFunction<? super O> distf; - - /** - * Constructor. - * - * @param index Index to use - * @param distanceQuery Distance query used - * @param distf Distance function - */ - public DoubleDistanceMetricalIndexRangeQuery(AbstractMTree<O, DoubleDistance, ?, ?, ?> index, DistanceQuery<O, DoubleDistance> distanceQuery, PrimitiveDoubleDistanceFunction<? super O> distf) { - super(distanceQuery); - this.index = index; - this.distf = distf; - } - - /** - * Performs a range query on the specified subtree. It recursively traverses - * all paths from the specified node, which cannot be excluded from leading to - * qualifying objects. - * - * @param id_p the routing object of the specified node - * @param node the root of the subtree to be traversed - * @param q the query object - * @param r_q the query range - * @param result the list holding the query results - */ - private void doRangeQuery(DBID id_p, AbstractMTreeNode<O, DoubleDistance, ?, ?> node, O q, double r_q, ModifiableDoubleDistanceDBIDList result) { - final O o_p = id_p != null ? relation.get(id_p) : null; - double d1 = 0.; - if (id_p != null) { - d1 = distf.doubleDistance(o_p, q); - index.statistics.countDistanceCalculation(); - } - if (!node.isLeaf()) { - for (int i = 0; i < node.getNumEntries(); i++) { - MTreeEntry entry = node.getEntry(i); - - double r_or = entry.getCoveringRadius(); - double d2 = id_p != null ? entry.getParentDistance() : 0; - double diff = Math.abs(d1 - d2); - - double sum = r_q + r_or; - - if (diff <= sum) { - DBID id_r = entry.getRoutingObjectID(); - double d3 = distf.doubleDistance(relation.get(id_r), q); - index.statistics.countDistanceCalculation(); - if (d3 <= sum) { - AbstractMTreeNode<O, DoubleDistance, ?, ?> child = index.getNode(((DirectoryEntry) entry).getPageID()); - doRangeQuery(id_r, child, q, r_q, result); - } - } - } - } else { - for (int i = 0; i < node.getNumEntries(); i++) { - MTreeEntry entry = node.getEntry(i); - - double d2 = id_p != null ? entry.getParentDistance() : 0; - double diff = Math.abs(d1 - d2); - - if (diff <= r_q) { - DBID id_j = entry.getRoutingObjectID(); - O o_j = relation.get(id_j); - double d3 = distf.doubleDistance(o_j, q); - index.statistics.countDistanceCalculation(); - if (d3 <= r_q) { - result.add(d3, id_j); - } - } - } - } - } - - @Override - public DistanceDBIDList<DoubleDistance> getRangeForObject(O obj, DoubleDistance range) { - final DoubleDistanceDBIDPairList result = new DoubleDistanceDBIDPairList(); - - doRangeQuery(null, index.getRoot(), obj, range.doubleValue(), result); - index.statistics.countRangeQuery(); - result.sort(); - return result; - } -} diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MTreeQueryUtil.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MTreeQueryUtil.java index cc27b383..8bd0ceb0 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MTreeQueryUtil.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MTreeQueryUtil.java @@ -3,17 +3,13 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query; import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery; import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery; -import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancefunction.PrimitiveDoubleDistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree; /* This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -43,23 +39,12 @@ public final class MTreeQueryUtil { * possible. * * @param <O> Object type - * @param <D> Distance type * @param tree Tree to query * @param distanceQuery distance query * @param hints Optimizer hints * @return Query object */ - @SuppressWarnings({ "cast", "unchecked" }) - public static <O, D extends NumberDistance<D, ?>> KNNQuery<O, D> getKNNQuery(AbstractMTree<O, D, ?, ?, ?> tree, DistanceQuery<O, D> distanceQuery, Object... hints) { - DistanceFunction<? super O, D> df = distanceQuery.getDistanceFunction(); - // Can we use an optimized query? - if (df instanceof PrimitiveDoubleDistanceFunction) { - PrimitiveDoubleDistanceFunction<? super O> dfc = (PrimitiveDoubleDistanceFunction<? super O>) df; - AbstractMTree<O, DoubleDistance, ?, ?, ?> treec = (AbstractMTree<O, DoubleDistance, ?, ?, ?>) tree; - DistanceQuery<O, DoubleDistance> dqc = (DistanceQuery<O, DoubleDistance>) distanceQuery; - KNNQuery<O, ?> q = new DoubleDistanceMetricalIndexKNNQuery<>(treec, dqc, dfc); - return (KNNQuery<O, D>) q; - } + public static <O> KNNQuery<O> getKNNQuery(AbstractMTree<O, ?, ?, ?> tree, DistanceQuery<O> distanceQuery, Object... hints) { return new MetricalIndexKNNQuery<>(tree, distanceQuery); } @@ -68,23 +53,12 @@ public final class MTreeQueryUtil { * possible. * * @param <O> Object type - * @param <D> Distance type * @param tree Tree to query * @param distanceQuery distance query * @param hints Optimizer hints * @return Query object */ - @SuppressWarnings({ "cast", "unchecked" }) - public static <O, D extends NumberDistance<D, ?>> RangeQuery<O, D> getRangeQuery(AbstractMTree<O, D, ?, ?, ?> tree, DistanceQuery<O, D> distanceQuery, Object... hints) { - DistanceFunction<? super O, D> df = distanceQuery.getDistanceFunction(); - // Can we use an optimized query? - if (df instanceof PrimitiveDoubleDistanceFunction) { - PrimitiveDoubleDistanceFunction<? super O> dfc = (PrimitiveDoubleDistanceFunction<? super O>) df; - AbstractMTree<O, DoubleDistance, ?, ?, ?> treec = (AbstractMTree<O, DoubleDistance, ?, ?, ?>) tree; - DistanceQuery<O, DoubleDistance> dqc = (DistanceQuery<O, DoubleDistance>) distanceQuery; - RangeQuery<O, ?> q = new DoubleDistanceMetricalIndexRangeQuery<>(treec, dqc, dfc); - return (RangeQuery<O, D>) q; - } + public static <O> RangeQuery<O> getRangeQuery(AbstractMTree<O, ?, ?, ?> tree, DistanceQuery<O> distanceQuery, Object... hints) { return new MetricalIndexRangeQuery<>(tree, distanceQuery); } } diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MetricalIndexKNNQuery.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MetricalIndexKNNQuery.java index f21bac82..d839bed3 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MetricalIndexKNNQuery.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MetricalIndexKNNQuery.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -25,11 +25,10 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query; import de.lmu.ifi.dbs.elki.database.ids.DBID; import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNHeap; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList; +import de.lmu.ifi.dbs.elki.database.ids.KNNHeap; +import de.lmu.ifi.dbs.elki.database.ids.KNNList; import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; import de.lmu.ifi.dbs.elki.database.query.knn.AbstractDistanceKNNQuery; -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.tree.DirectoryEntry; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode; @@ -43,15 +42,15 @@ import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.ComparableMinHeap; * @author Erich Schubert * * @apiviz.uses AbstractMTree + * @apiviz.uses DoubleMTreeDistanceSearchCandidate * * @param <O> Object type - * @param <D> Distance type */ -public class MetricalIndexKNNQuery<O, D extends NumberDistance<D, ?>> extends AbstractDistanceKNNQuery<O, D> { +public class MetricalIndexKNNQuery<O> extends AbstractDistanceKNNQuery<O> { /** * The index to use */ - protected final AbstractMTree<O, D, ?, ?, ?> index; + protected final AbstractMTree<O, ?, ?, ?> index; /** * Constructor. @@ -59,41 +58,41 @@ public class MetricalIndexKNNQuery<O, D extends NumberDistance<D, ?>> extends Ab * @param index Index to use * @param distanceQuery Distance query used */ - public MetricalIndexKNNQuery(AbstractMTree<O, D, ?, ?, ?> index, DistanceQuery<O, D> distanceQuery) { + public MetricalIndexKNNQuery(AbstractMTree<O, ?, ?, ?> index, DistanceQuery<O> distanceQuery) { super(distanceQuery); this.index = index; } @Override - public KNNList<D> getKNNForObject(O q, int k) { - if (k < 1) { + public KNNList getKNNForObject(O q, int k) { + if(k < 1) { throw new IllegalArgumentException("At least one object has to be requested!"); } index.statistics.countKNNQuery(); - KNNHeap<D> knnList = DBIDUtil.newHeap(distanceQuery.getDistanceFactory(), k); - D d_k = knnList.getKNNDistance(); + KNNHeap knnList = DBIDUtil.newHeap(k); + double d_k = Double.POSITIVE_INFINITY; final ComparableMinHeap<DoubleMTreeDistanceSearchCandidate> pq = new ComparableMinHeap<>(); - // push root + // Push the root node pq.add(new DoubleMTreeDistanceSearchCandidate(0., index.getRootID(), null, 0.)); // search in tree - while (!pq.isEmpty()) { + while(!pq.isEmpty()) { DoubleMTreeDistanceSearchCandidate pqNode = pq.poll(); - if (knnList.size() >= k && pqNode.mindist > d_k.doubleValue()) { + if(knnList.size() >= k && pqNode.mindist > d_k) { break; } - AbstractMTreeNode<?, D, ?, ?> node = index.getNode(pqNode.nodeID); + AbstractMTreeNode<?, ?, ?> node = index.getNode(pqNode.nodeID); DBID id_p = pqNode.routingObjectID; double d1 = pqNode.routingDistance; // directory node - if (!node.isLeaf()) { - for (int i = 0; i < node.getNumEntries(); i++) { + if(!node.isLeaf()) { + for(int i = 0; i < node.getNumEntries(); i++) { MTreeEntry entry = node.getEntry(i); DBID o_r = entry.getRoutingObjectID(); double r_or = entry.getCoveringRadius(); @@ -101,13 +100,13 @@ public class MetricalIndexKNNQuery<O, D extends NumberDistance<D, ?>> extends Ab double diff = Math.abs(d1 - d2); - double sum = d_k.doubleValue() + r_or; + double sum = d_k + r_or; - if (diff <= sum) { - double d3 = distanceQuery.distance(o_r, q).doubleValue(); + if(diff <= sum) { + double d3 = distanceQuery.distance(o_r, q); index.statistics.countDistanceCalculation(); double d_min = Math.max(d3 - r_or, 0.); - if (d_min <= d_k.doubleValue()) { + if(d_min <= d_k) { pq.add(new DoubleMTreeDistanceSearchCandidate(d_min, ((DirectoryEntry) entry).getPageID(), o_r, d3)); } } @@ -115,7 +114,7 @@ public class MetricalIndexKNNQuery<O, D extends NumberDistance<D, ?>> extends Ab } // data node else { - for (int i = 0; i < node.getNumEntries(); i++) { + for(int i = 0; i < node.getNumEntries(); i++) { MTreeEntry entry = node.getEntry(i); DBID o_j = entry.getRoutingObjectID(); @@ -123,10 +122,10 @@ public class MetricalIndexKNNQuery<O, D extends NumberDistance<D, ?>> extends Ab double diff = Math.abs(d1 - d2); - if (diff <= d_k.doubleValue()) { - D d3 = distanceQuery.distance(o_j, q); + if(diff <= d_k) { + double d3 = distanceQuery.distance(o_j, q); index.statistics.countDistanceCalculation(); - if (d3.compareTo(d_k) <= 0) { + if(d3 <= d_k) { knnList.insert(d3, o_j); d_k = knnList.getKNNDistance(); } diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MetricalIndexRangeQuery.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MetricalIndexRangeQuery.java index fedf8ddb..b992977c 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MetricalIndexRangeQuery.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MetricalIndexRangeQuery.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -24,11 +24,11 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query; */ import de.lmu.ifi.dbs.elki.database.ids.DBID; -import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList; -import de.lmu.ifi.dbs.elki.database.ids.generic.GenericDistanceDBIDList; +import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil; +import de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDList; +import de.lmu.ifi.dbs.elki.database.ids.ModifiableDoubleDBIDList; import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; import de.lmu.ifi.dbs.elki.database.query.range.AbstractDistanceRangeQuery; -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.tree.DirectoryEntry; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode; @@ -40,12 +40,14 @@ import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry; * @author Erich Schubert * * @apiviz.uses AbstractMTree + * + * @param <O> Object type */ -public class MetricalIndexRangeQuery<O, D extends NumberDistance<D, ?>> extends AbstractDistanceRangeQuery<O, D> { +public class MetricalIndexRangeQuery<O> extends AbstractDistanceRangeQuery<O> { /** * The index to use */ - protected final AbstractMTree<O, D, ?, ?, ?> index; + protected final AbstractMTree<O, ?, ?, ?> index; /** * Constructor. @@ -53,7 +55,7 @@ public class MetricalIndexRangeQuery<O, D extends NumberDistance<D, ?>> extends * @param index Index to use * @param distanceQuery Distance query used */ - public MetricalIndexRangeQuery(AbstractMTree<O, D, ?, ?, ?> index, DistanceQuery<O, D> distanceQuery) { + public MetricalIndexRangeQuery(AbstractMTree<O, ?, ?, ?> index, DistanceQuery<O> distanceQuery) { super(distanceQuery); this.index = index; } @@ -65,18 +67,18 @@ public class MetricalIndexRangeQuery<O, D extends NumberDistance<D, ?>> extends * * @param o_p the routing object of the specified node * @param node the root of the subtree to be traversed - * @param q the id of the query object + * @param q the query object * @param r_q the query range * @param result the list holding the query results */ - private void doRangeQuery(DBID o_p, AbstractMTreeNode<O, D, ?, ?> node, O q, D r_q, GenericDistanceDBIDList<D> result) { + private void doRangeQuery(DBID o_p, AbstractMTreeNode<O, ?, ?> node, O q, double r_q, ModifiableDoubleDBIDList result) { double d1 = 0.; - if (o_p != null) { - d1 = distanceQuery.distance(o_p, q).doubleValue(); + if(o_p != null) { + d1 = distanceQuery.distance(o_p, q); index.statistics.countDistanceCalculation(); } - if (!node.isLeaf()) { - for (int i = 0; i < node.getNumEntries(); i++) { + if(!node.isLeaf()) { + for(int i = 0; i < node.getNumEntries(); i++) { MTreeEntry entry = node.getEntry(i); DBID o_r = entry.getRoutingObjectID(); @@ -84,19 +86,20 @@ public class MetricalIndexRangeQuery<O, D extends NumberDistance<D, ?>> extends double d2 = o_p != null ? entry.getParentDistance() : 0.; double diff = Math.abs(d1 - d2); - double sum = r_q.doubleValue() + r_or; + double sum = r_q + r_or; - if (diff <= sum) { - D d3 = distanceQuery.distance(o_r, q); + if(diff <= sum) { + double d3 = distanceQuery.distance(o_r, q); index.statistics.countDistanceCalculation(); - if (d3.doubleValue() <= sum) { - AbstractMTreeNode<O, D, ?, ?> child = index.getNode(((DirectoryEntry) entry).getPageID()); + if(d3 <= sum) { + AbstractMTreeNode<O, ?, ?> child = index.getNode(((DirectoryEntry) entry).getPageID()); doRangeQuery(o_r, child, q, r_q, result); } } } - } else { - for (int i = 0; i < node.getNumEntries(); i++) { + } + else { + for(int i = 0; i < node.getNumEntries(); i++) { MTreeEntry entry = node.getEntry(i); DBID o_j = entry.getRoutingObjectID(); @@ -104,10 +107,10 @@ public class MetricalIndexRangeQuery<O, D extends NumberDistance<D, ?>> extends double diff = Math.abs(d1 - d2); - if (diff <= r_q.doubleValue()) { - D d3 = distanceQuery.distance(o_j, q); + if(diff <= r_q) { + double d3 = distanceQuery.distance(o_j, q); index.statistics.countDistanceCalculation(); - if (d3.compareTo(r_q) <= 0) { + if(d3 <= r_q) { result.add(d3, o_j); } } @@ -116,8 +119,8 @@ public class MetricalIndexRangeQuery<O, D extends NumberDistance<D, ?>> extends } @Override - public DistanceDBIDList<D> getRangeForObject(O obj, D range) { - final GenericDistanceDBIDList<D> result = new GenericDistanceDBIDList<>(); + public DoubleDBIDList getRangeForObject(O obj, double range) { + final ModifiableDoubleDBIDList result = DBIDUtil.newDistanceDBIDList(); doRangeQuery(null, index.getRoot(), obj, range, result); index.statistics.countRangeQuery(); diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MkTreeRKNNQuery.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MkTreeRKNNQuery.java index c8cec69f..a00e44a9 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MkTreeRKNNQuery.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/MkTreeRKNNQuery.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.query; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -27,10 +27,9 @@ import java.util.List; import de.lmu.ifi.dbs.elki.database.ids.ArrayDBIDs; import de.lmu.ifi.dbs.elki.database.ids.DBIDRef; -import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList; +import de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDList; import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; import de.lmu.ifi.dbs.elki.database.query.rknn.AbstractRKNNQuery; -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.mktrees.AbstractMkTree; import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException; import de.lmu.ifi.dbs.elki.utilities.exceptions.ExceptionMessages; @@ -43,11 +42,11 @@ import de.lmu.ifi.dbs.elki.utilities.exceptions.NotImplementedException; * * @apiviz.uses AbstractMkTree */ -public class MkTreeRKNNQuery<O, D extends NumberDistance<D, ?>> extends AbstractRKNNQuery<O, D> { +public class MkTreeRKNNQuery<O> extends AbstractRKNNQuery<O> { /** * The index to use */ - protected final AbstractMkTree<O, D, ?, ?, ?> index; + protected final AbstractMkTree<O, ?, ?, ?> index; /** * Constructor. @@ -55,23 +54,23 @@ public class MkTreeRKNNQuery<O, D extends NumberDistance<D, ?>> extends Abstract * @param index Index to use * @param distanceQuery Distance query used */ - public MkTreeRKNNQuery(AbstractMkTree<O, D, ?, ?, ?> index, DistanceQuery<O, D> distanceQuery) { + public MkTreeRKNNQuery(AbstractMkTree<O, ?, ?, ?> index, DistanceQuery<O> distanceQuery) { super(distanceQuery); this.index = index; } @Override - public DistanceDBIDList<D> getRKNNForObject(O obj, int k) { + public DoubleDBIDList getRKNNForObject(O obj, int k) { throw new AbortException("Preprocessor KNN query only supports ID queries."); } @Override - public DistanceDBIDList<D> getRKNNForDBID(DBIDRef id, int k) { + public DoubleDBIDList getRKNNForDBID(DBIDRef id, int k) { return index.reverseKNNQuery(id, k); } @Override - public List<? extends DistanceDBIDList<D>> getRKNNForBulkDBIDs(ArrayDBIDs ids, int k) { + public List<? extends DoubleDBIDList> getRKNNForBulkDBIDs(ArrayDBIDs ids, int k) { // TODO: implement throw new NotImplementedException(ExceptionMessages.UNSUPPORTED_NOT_YET); } diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/package-info.java index a975fdff..5ad2593c 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/query/package-info.java @@ -6,7 +6,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2013 +Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/insert/MTreeInsert.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/insert/MTreeInsert.java index 65fc3768..5fff4143 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/insert/MTreeInsert.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/insert/MTreeInsert.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.insert; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -22,7 +22,6 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.insert; You should have received a copy of the GNU Affero General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.tree.IndexTreePath; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode; @@ -38,7 +37,7 @@ import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry; * * @author Erich Schubert */ -public interface MTreeInsert<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry> { +public interface MTreeInsert<O, N extends AbstractMTreeNode<O, N, E>, E extends MTreeEntry> { /** * Choose the subpath to insert into. * @@ -46,5 +45,5 @@ public interface MTreeInsert<O, D extends NumberDistance<D, ?>, N extends Abstra * @param object Object to insert * @return Path to insertion node */ - IndexTreePath<E> choosePath(AbstractMTree<O, D, N, E, ?> tree, E object); + IndexTreePath<E> choosePath(AbstractMTree<O, N, E, ?> tree, E object); } diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/insert/MinimumEnlargementInsert.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/insert/MinimumEnlargementInsert.java index f848f5f4..cb410a8d 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/insert/MinimumEnlargementInsert.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/insert/MinimumEnlargementInsert.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.insert; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -22,7 +22,6 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.insert; You should have received a copy of the GNU Affero General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.tree.IndexTreePath; import de.lmu.ifi.dbs.elki.index.tree.TreeIndexPathComponent; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree; @@ -44,9 +43,9 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Reference; * @author Erich Schubert */ @Reference(authors = "P. Ciaccia, M. Patella, P. Zezula", title = "M-tree: An Efficient Access Method for Similarity Search in Metric Spaces", booktitle = "VLDB'97, Proceedings of 23rd International Conference on Very Large Data Bases, August 25-29, 1997, Athens, Greece", url = "http://www.vldb.org/conf/1997/P426.PDF") -public class MinimumEnlargementInsert<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry> implements MTreeInsert<O, D, N, E> { +public class MinimumEnlargementInsert<O, N extends AbstractMTreeNode<O, N, E>, E extends MTreeEntry> implements MTreeInsert<O, N, E> { @Override - public IndexTreePath<E> choosePath(AbstractMTree<O, D, N, E, ?> tree, E object) { + public IndexTreePath<E> choosePath(AbstractMTree<O, N, E, ?> tree, E object) { return choosePath(tree, object, tree.getRootPath()); } @@ -59,7 +58,7 @@ public class MinimumEnlargementInsert<O, D extends NumberDistance<D, ?>, N exten * @param subtree the subtree to be tested for insertion * @return the path of the appropriate subtree to insert the given object */ - private IndexTreePath<E> choosePath(AbstractMTree<O, D, N, E, ?> tree, E object, IndexTreePath<E> subtree) { + private IndexTreePath<E> choosePath(AbstractMTree<O, N, E, ?> tree, E object, IndexTreePath<E> subtree) { N node = tree.getNode(subtree.getLastPathComponent().getEntry()); // leaf @@ -75,7 +74,7 @@ public class MinimumEnlargementInsert<O, D extends NumberDistance<D, ?>, N exten { bestIdx = 0; bestEntry = node.getEntry(0); - bestDistance = tree.distance(object.getRoutingObjectID(), bestEntry.getRoutingObjectID()).doubleValue(); + bestDistance = tree.distance(object.getRoutingObjectID(), bestEntry.getRoutingObjectID()); if (bestDistance <= bestEntry.getCoveringRadius()) { enlarge = 0.; } else { @@ -86,7 +85,7 @@ public class MinimumEnlargementInsert<O, D extends NumberDistance<D, ?>, N exten // Iterate over remaining for (int i = 1; i < node.getNumEntries(); i++) { E entry = node.getEntry(i); - double distance = tree.distance(object.getRoutingObjectID(), entry.getRoutingObjectID()).doubleValue(); + double distance = tree.distance(object.getRoutingObjectID(), entry.getRoutingObjectID()); if (distance <= entry.getCoveringRadius()) { if (enlarge > 0. || distance < bestDistance) { diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/insert/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/insert/package-info.java index 64a85c2d..655611c6 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/insert/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/insert/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/package-info.java index 0d019cf3..61d2d899 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/Assignments.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/Assignments.java index 1079a141..cbf7e3eb 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/Assignments.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/Assignments.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.split; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -69,7 +69,7 @@ public class Assignments<E extends MTreeEntry> { private List<DistanceEntry<E>> secondAssignments; /** - * Provides an assignment during a split of an MTree node. + * Constructor. * * @param id1 the first routing object * @param id2 the second routing object diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/DistanceEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/DistanceEntry.java index 642e5a63..4df9aa59 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/DistanceEntry.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/DistanceEntry.java @@ -6,7 +6,7 @@ import de.lmu.ifi.dbs.elki.index.tree.Entry; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/MLBDistSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/MLBDistSplit.java index d294d5b3..e24e87ed 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/MLBDistSplit.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/MLBDistSplit.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.split; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -24,7 +24,6 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.split; */ import de.lmu.ifi.dbs.elki.database.ids.DBID; -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry; @@ -45,12 +44,11 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Reference; * @author Elke Achtert * * @param <O> the type of DatabaseObject to be stored in the M-Tree - * @param <D> the type of Distance used in the M-Tree * @param <N> the type of AbstractMTreeNode used in the M-Tree * @param <E> the type of MetricalEntry used in the M-Tree */ @Reference(authors = "P. Ciaccia, M. Patella, P. Zezula", title = "M-tree: An Efficient Access Method for Similarity Search in Metric Spaces", booktitle = "VLDB'97, Proceedings of 23rd International Conference on Very Large Data Bases, August 25-29, 1997, Athens, Greece", url = "http://www.vldb.org/conf/1997/P426.PDF") -public class MLBDistSplit<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry> extends MTreeSplit<O, D, N, E> { +public class MLBDistSplit<O, N extends AbstractMTreeNode<O, N, E>, E extends MTreeEntry> extends MTreeSplit<O, N, E> { /** * Creates a new split object. */ @@ -70,19 +68,19 @@ public class MLBDistSplit<O, D extends NumberDistance<D, ?>, N extends AbstractM * @param node the node to be split */ @Override - public Assignments<E> split(AbstractMTree<O, D, N, E, ?> tree, N node) { + public Assignments<E> split(AbstractMTree<O, N, E, ?> tree, N node) { DBID firstPromoted = null; DBID secondPromoted = null; // choose first and second routing object double currentMaxDist = 0.; - for (int i = 0; i < node.getNumEntries(); i++) { + for(int i = 0; i < node.getNumEntries(); i++) { DBID id1 = node.getEntry(i).getRoutingObjectID(); - for (int j = i + 1; j < node.getNumEntries(); j++) { + for(int j = i + 1; j < node.getNumEntries(); j++) { DBID id2 = node.getEntry(j).getRoutingObjectID(); - double distance = tree.distance(id1, id2).doubleValue(); - if (distance >= currentMaxDist) { + double distance = tree.distance(id1, id2); + if(distance >= currentMaxDist) { firstPromoted = id1; secondPromoted = id2; currentMaxDist = distance; diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/MMRadSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/MMRadSplit.java index 232df088..2d3fd7f8 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/MMRadSplit.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/MMRadSplit.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.split; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,7 +23,6 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.split; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry; @@ -44,12 +43,11 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Reference; * @author Elke Achtert * * @param <O> the type of DatabaseObject to be stored in the M-Tree - * @param <D> the type of Distance used in the M-Tree * @param <N> the type of AbstractMTreeNode used in the M-Tree * @param <E> the type of MetricalEntry used in the M-Tree */ @Reference(authors = "P. Ciaccia, M. Patella, P. Zezula", title = "M-tree: An Efficient Access Method for Similarity Search in Metric Spaces", booktitle = "VLDB'97, Proceedings of 23rd International Conference on Very Large Data Bases, August 25-29, 1997, Athens, Greece", url = "http://www.vldb.org/conf/1997/P426.PDF") -public class MMRadSplit<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry> extends MTreeSplit<O, D, N, E> { +public class MMRadSplit<O, N extends AbstractMTreeNode<O, N, E>, E extends MTreeEntry> extends MTreeSplit<O, N, E> { /** * Creates a new split object. */ @@ -67,17 +65,17 @@ public class MMRadSplit<O, D extends NumberDistance<D, ?>, N extends AbstractMTr * @param node the node to be split */ @Override - public Assignments<E> split(AbstractMTree<O, D, N, E, ?> tree, N node) { + public Assignments<E> split(AbstractMTree<O, N, E, ?> tree, N node) { double miSumCR = Double.POSITIVE_INFINITY; double[] distanceMatrix = computeDistanceMatrix(tree, node); Assignments<E> bestAssignment = null; - for (int i = 0; i < node.getNumEntries(); i++) { - for (int j = i + 1; j < node.getNumEntries(); j++) { + for(int i = 0; i < node.getNumEntries(); i++) { + for(int j = i + 1; j < node.getNumEntries(); j++) { Assignments<E> currentAssignments = balancedPartition(tree, node, i, j, distanceMatrix); double maxCR = Math.max(currentAssignments.getFirstCoveringRadius(), currentAssignments.getSecondCoveringRadius()); - if (maxCR < miSumCR) { + if(maxCR < miSumCR) { miSumCR = maxCR; bestAssignment = currentAssignments; } diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/MRadSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/MRadSplit.java index 5de15356..3feb9d87 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/MRadSplit.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/MRadSplit.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.split; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,7 +23,6 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.split; along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry; @@ -44,12 +43,11 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Reference; * @author Elke Achtert * * @param <O> the type of DatabaseObject to be stored in the M-Tree - * @param <D> the type of Distance used in the M-Tree * @param <N> the type of AbstractMTreeNode used in the M-Tree * @param <E> the type of MetricalEntry used in the M-Tree */ @Reference(authors = "P. Ciaccia, M. Patella, P. Zezula", title = "M-tree: An Efficient Access Method for Similarity Search in Metric Spaces", booktitle = "VLDB'97, Proceedings of 23rd International Conference on Very Large Data Bases, August 25-29, 1997, Athens, Greece", url = "http://www.vldb.org/conf/1997/P426.PDF") -public class MRadSplit<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry> extends MTreeSplit<O, D, N, E> { +public class MRadSplit<O, N extends AbstractMTreeNode<O, N, E>, E extends MTreeEntry> extends MTreeSplit<O, N, E> { /** * Creates a new split object. */ @@ -67,17 +65,17 @@ public class MRadSplit<O, D extends NumberDistance<D, ?>, N extends AbstractMTre * @param node the node to be split */ @Override - public Assignments<E> split(AbstractMTree<O, D, N, E, ?> tree, N node) { + public Assignments<E> split(AbstractMTree<O, N, E, ?> tree, N node) { double miSumCR = Double.POSITIVE_INFINITY; double[] distanceMatrix = computeDistanceMatrix(tree, node); Assignments<E> bestAssignment = null; - for (int i = 0; i < node.getNumEntries(); i++) { - for (int j = i + 1; j < node.getNumEntries(); j++) { + for(int i = 0; i < node.getNumEntries(); i++) { + for(int j = i + 1; j < node.getNumEntries(); j++) { Assignments<E> currentAssignments = balancedPartition(tree, node, i, j, distanceMatrix); double sumCR = currentAssignments.getFirstCoveringRadius() + currentAssignments.getSecondCoveringRadius(); - if (sumCR < miSumCR) { + if(sumCR < miSumCR) { miSumCR = sumCR; bestAssignment = currentAssignments; } diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/MTreeSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/MTreeSplit.java index 167b5368..89b323a7 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/MTreeSplit.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/MTreeSplit.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.split; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -30,7 +30,6 @@ import java.util.List; import de.lmu.ifi.dbs.elki.database.ids.DBID; import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil; -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry; @@ -43,11 +42,10 @@ import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry; * @apiviz.composedOf Assignments * * @param <O> the type of DatabaseObject to be stored in the M-Tree - * @param <D> the type of Distance used in the M-Tree * @param <N> the type of AbstractMTreeNode used in the M-Tree * @param <E> the type of MetricalEntry used in the M-Tree */ -public abstract class MTreeSplit<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry> { +public abstract class MTreeSplit<O, N extends AbstractMTreeNode<O, N, E>, E extends MTreeEntry> { /** * Compute the pairwise distances in the given node. * @@ -55,18 +53,20 @@ public abstract class MTreeSplit<O, D extends NumberDistance<D, ?>, N extends Ab * @param node Node * @return Distance matrix */ - protected double[] computeDistanceMatrix(AbstractMTree<O, D, N, E, ?> tree, N node) { + protected double[] computeDistanceMatrix(AbstractMTree<O, N, E, ?> tree, N node) { final int n = node.getNumEntries(); double[] distancematrix = new double[n * n]; // Build distance matrix - for (int i = 0; i < n; i++) { + for(int i = 0; i < n; i++) { E ei = node.getEntry(i); - for (int j = 0; j < n; j++) { - if (i == j) { + for(int j = 0; j < n; j++) { + if(i == j) { distancematrix[i * n + j] = 0.0; - } else if (i < j) { - distancematrix[i * n + j] = tree.distance(ei, node.getEntry(j)).doubleValue(); - } else { // i > j + } + else if(i < j) { + distancematrix[i * n + j] = tree.distance(ei, node.getEntry(j)); + } + else { // i > j distancematrix[i * n + j] = distancematrix[j * n + i]; } } @@ -84,7 +84,7 @@ public abstract class MTreeSplit<O, D extends NumberDistance<D, ?>, N extends Ab * @return an assignment that holds a balanced partition of the entries of the * specified node */ - Assignments<E> balancedPartition(AbstractMTree<O, D, N, E, ?> tree, N node, DBID routingObject1, DBID routingObject2) { + Assignments<E> balancedPartition(AbstractMTree<O, N, E, ?> tree, N node, DBID routingObject1, DBID routingObject2) { BitSet assigned = new BitSet(node.getNumEntries()); List<DistanceEntry<E>> assigned1 = new ArrayList<>(node.getCapacity()); List<DistanceEntry<E>> assigned2 = new ArrayList<>(node.getCapacity()); @@ -96,20 +96,20 @@ public abstract class MTreeSplit<O, D extends NumberDistance<D, ?>, N extends Ab List<DistanceEntry<E>> list2 = new ArrayList<>(); // determine the nearest neighbors - for (int i = 0; i < node.getNumEntries(); i++) { + for(int i = 0; i < node.getNumEntries(); i++) { final E ent = node.getEntry(i); DBID id = ent.getRoutingObjectID(); - if (DBIDUtil.equal(id, routingObject1)) { + if(DBIDUtil.equal(id, routingObject1)) { assigned1.add(new DistanceEntry<>(ent, 0., i)); continue; } - if (DBIDUtil.equal(id, routingObject2)) { + if(DBIDUtil.equal(id, routingObject2)) { assigned2.add(new DistanceEntry<>(ent, 0., i)); continue; } // determine the distance of o to o1 / o2 - double d1 = tree.distance(routingObject1, id).doubleValue(); - double d2 = tree.distance(routingObject2, id).doubleValue(); + double d1 = tree.distance(routingObject1, id); + double d2 = tree.distance(routingObject2, id); list1.add(new DistanceEntry<>(ent, d1, i)); list2.add(new DistanceEntry<>(ent, d2, i)); @@ -117,10 +117,10 @@ public abstract class MTreeSplit<O, D extends NumberDistance<D, ?>, N extends Ab Collections.sort(list1, Collections.reverseOrder()); Collections.sort(list2, Collections.reverseOrder()); - for (int i = 2; i < node.getNumEntries(); i++) { + for(int i = 2; i < node.getNumEntries(); i++) { currentCR1 = assignNN(assigned, assigned1, list1, currentCR1, node.isLeaf()); i++; - if (i < node.getNumEntries()) { + if(i < node.getNumEntries()) { currentCR2 = assignNN(assigned, assigned2, list2, currentCR2, node.isLeaf()); } } @@ -138,7 +138,7 @@ public abstract class MTreeSplit<O, D extends NumberDistance<D, ?>, N extends Ab * @return an assignment that holds a balanced partition of the entries of the * specified node */ - Assignments<E> balancedPartition(AbstractMTree<O, D, N, E, ?> tree, N node, int routingEntNum1, int routingEntNum2, double[] distanceMatrix) { + Assignments<E> balancedPartition(AbstractMTree<O, N, E, ?> tree, N node, int routingEntNum1, int routingEntNum2, double[] distanceMatrix) { final int n = node.getNumEntries(); BitSet assigned = new BitSet(node.getNumEntries()); List<DistanceEntry<E>> assigned1 = new ArrayList<>(node.getCapacity()); @@ -152,14 +152,14 @@ public abstract class MTreeSplit<O, D extends NumberDistance<D, ?>, N extends Ab DBID routingObject1 = null, routingObject2 = null; // determine the nearest neighbors - for (int i = 0; i < node.getNumEntries(); i++) { + for(int i = 0; i < node.getNumEntries(); i++) { final E ent = node.getEntry(i); - if (i == routingEntNum1) { + if(i == routingEntNum1) { routingObject1 = ent.getRoutingObjectID(); assigned1.add(new DistanceEntry<>(ent, 0., i)); continue; } - if (i == routingEntNum2) { + if(i == routingEntNum2) { routingObject2 = ent.getRoutingObjectID(); assigned2.add(new DistanceEntry<>(ent, 0., i)); continue; @@ -174,10 +174,10 @@ public abstract class MTreeSplit<O, D extends NumberDistance<D, ?>, N extends Ab Collections.sort(list1, Collections.reverseOrder()); Collections.sort(list2, Collections.reverseOrder()); - for (int i = 2; i < node.getNumEntries(); i++) { + for(int i = 2; i < node.getNumEntries(); i++) { currentCR1 = assignNN(assigned, assigned1, list1, currentCR1, node.isLeaf()); i++; - if (i < node.getNumEntries()) { + if(i < node.getNumEntries()) { currentCR2 = assignNN(assigned, assigned2, list2, currentCR2, node.isLeaf()); } } @@ -199,15 +199,16 @@ public abstract class MTreeSplit<O, D extends NumberDistance<D, ?>, N extends Ab private double assignNN(BitSet assigned, List<DistanceEntry<E>> assigned1, List<DistanceEntry<E>> list, double currentCR, boolean isLeaf) { // Remove last unassigned: DistanceEntry<E> distEntry = list.remove(list.size() - 1); - while (assigned.get(distEntry.getIndex())) { + while(assigned.get(distEntry.getIndex())) { distEntry = list.remove(list.size() - 1); } assigned1.add(distEntry); assigned.set(distEntry.getIndex()); - if (isLeaf) { + if(isLeaf) { return Math.max(currentCR, distEntry.getDistance()); - } else { + } + else { return Math.max(currentCR, distEntry.getDistance() + (distEntry.getEntry()).getCoveringRadius()); } } @@ -219,5 +220,5 @@ public abstract class MTreeSplit<O, D extends NumberDistance<D, ?>, N extends Ab * @param node Node to split * @return the assignments of this split */ - abstract public Assignments<E> split(AbstractMTree<O, D, N, E, ?> tree, N node); + abstract public Assignments<E> split(AbstractMTree<O, N, E, ?> tree, N node); } diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/RandomSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/RandomSplit.java index ca54f51a..68a4edd1 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/RandomSplit.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/RandomSplit.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.split; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -26,11 +26,10 @@ package de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.strategies.split; import java.util.Random; import de.lmu.ifi.dbs.elki.database.ids.DBID; -import de.lmu.ifi.dbs.elki.distance.distancevalue.NumberDistance; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTree; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.AbstractMTreeNode; import de.lmu.ifi.dbs.elki.index.tree.metrical.mtreevariants.MTreeEntry; -import de.lmu.ifi.dbs.elki.utilities.RandomFactory; +import de.lmu.ifi.dbs.elki.math.random.RandomFactory; import de.lmu.ifi.dbs.elki.utilities.documentation.Reference; import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer; import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID; @@ -55,12 +54,11 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.RandomParameter; * @author Elke Achtert * * @param <O> the type of DatabaseObject to be stored in the M-Tree - * @param <D> the type of Distance used in the M-Tree * @param <N> the type of AbstractMTreeNode used in the M-Tree * @param <E> the type of MetricalEntry used in the M-Tree */ @Reference(authors = "P. Ciaccia, M. Patella, P. Zezula", title = "M-tree: An Efficient Access Method for Similarity Search in Metric Spaces", booktitle = "VLDB'97, Proceedings of 23rd International Conference on Very Large Data Bases, August 25-29, 1997, Athens, Greece", url = "http://www.vldb.org/conf/1997/P426.PDF") -public class RandomSplit<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry> extends MTreeSplit<O, D, N, E> { +public class RandomSplit<O, N extends AbstractMTreeNode<O, N, E>, E extends MTreeEntry> extends MTreeSplit<O, N, E> { /** * Random generator. */ @@ -84,10 +82,10 @@ public class RandomSplit<O, D extends NumberDistance<D, ?>, N extends AbstractMT * @param node the node to be split */ @Override - public Assignments<E> split(AbstractMTree<O, D, N, E, ?> tree, N node) { + public Assignments<E> split(AbstractMTree<O, N, E, ?> tree, N node) { int pos1 = random.nextInt(node.getNumEntries()); int pos2 = random.nextInt(node.getNumEntries() - 1); - if (pos2 >= pos1) { + if(pos2 >= pos1) { ++pos2; } DBID id1 = node.getEntry(pos1).getRoutingObjectID(); @@ -104,11 +102,10 @@ public class RandomSplit<O, D extends NumberDistance<D, ?>, N extends AbstractMT * @apiviz.exclude * * @param <O> the type of DatabaseObject to be stored in the M-Tree - * @param <D> the type of Distance used in the M-Tree * @param <N> the type of AbstractMTreeNode used in the M-Tree * @param <E> the type of MetricalEntry used in the M-Tree */ - public static class Parameterizer<O, D extends NumberDistance<D, ?>, N extends AbstractMTreeNode<O, D, N, E>, E extends MTreeEntry> extends AbstractParameterizer { + public static class Parameterizer<O, N extends AbstractMTreeNode<O, N, E>, E extends MTreeEntry> extends AbstractParameterizer { /** * Option ID for the random generator. */ @@ -123,13 +120,13 @@ public class RandomSplit<O, D extends NumberDistance<D, ?>, N extends AbstractMT protected void makeOptions(Parameterization config) { super.makeOptions(config); RandomParameter rndP = new RandomParameter(RANDOM_ID); - if (config.grab(rndP)) { + if(config.grab(rndP)) { rnd = rndP.getValue(); } } @Override - protected RandomSplit<O, D, N, E> makeInstance() { + protected RandomSplit<O, N, E> makeInstance() { return new RandomSplit<>(rnd); } } diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/package-info.java index ed0fd729..57c0d978 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/mtreevariants/strategies/split/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/package-info.java index b1a76d8b..eb9afac1 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/metrical/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/metrical/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2013 +Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/package-info.java index 6c34473f..0ab8843c 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2013 +Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/query/DoubleDistanceSearchCandidate.java b/src/de/lmu/ifi/dbs/elki/index/tree/query/DoubleDistanceSearchCandidate.java index fd9ee2f9..949bb96a 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/query/DoubleDistanceSearchCandidate.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/query/DoubleDistanceSearchCandidate.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.query; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/query/DoubleMTreeDistanceSearchCandidate.java b/src/de/lmu/ifi/dbs/elki/index/tree/query/DoubleMTreeDistanceSearchCandidate.java index 3be9ff09..8139c23b 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/query/DoubleMTreeDistanceSearchCandidate.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/query/DoubleMTreeDistanceSearchCandidate.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.query; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/query/GenericDistanceSearchCandidate.java b/src/de/lmu/ifi/dbs/elki/index/tree/query/GenericDistanceSearchCandidate.java deleted file mode 100644 index 278dec60..00000000 --- a/src/de/lmu/ifi/dbs/elki/index/tree/query/GenericDistanceSearchCandidate.java +++ /dev/null @@ -1,68 +0,0 @@ -package de.lmu.ifi.dbs.elki.index.tree.query; - -/* - This file is part of ELKI: - Environment for Developing KDD-Applications Supported by Index-Structures - - Copyright (C) 2013 - Ludwig-Maximilians-Universität München - Lehr- und Forschungseinheit für Datenbanksysteme - ELKI Development Team - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; - -/** - * Candidate for expansion in a distance search (generic implementation). - * - * @author Erich Schubert - * - * @param <D> Distance type - */ -public class GenericDistanceSearchCandidate<D extends Distance<D>> implements Comparable<GenericDistanceSearchCandidate<D>> { - /** - * Distance value - */ - public D mindist; - - /** - * Page id - */ - public int nodeID; - - /** - * Constructor. - * - * @param mindist The minimum distance to this candidate - * @param pagenr The page number of this candidate - */ - public GenericDistanceSearchCandidate(final D mindist, final int pagenr) { - super(); - this.mindist = mindist; - this.nodeID = pagenr; - } - - @Override - public boolean equals(Object obj) { - final GenericDistanceSearchCandidate<?> other = (GenericDistanceSearchCandidate<?>) obj; - return this.nodeID == other.nodeID; - } - - @Override - public int compareTo(GenericDistanceSearchCandidate<D> o) { - return this.mindist.compareTo(o.mindist); - } -}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/query/GenericMTreeDistanceSearchCandidate.java b/src/de/lmu/ifi/dbs/elki/index/tree/query/GenericMTreeDistanceSearchCandidate.java index cbe0451e..ca5c81d1 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/query/GenericMTreeDistanceSearchCandidate.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/query/GenericMTreeDistanceSearchCandidate.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.query; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/query/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/query/package-info.java index 29976738..98ccffc5 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/query/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/query/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2013 +Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialDirectoryEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialDirectoryEntry.java index 4a131cbf..ee7adf51 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialDirectoryEntry.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialDirectoryEntry.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialEntry.java index 4fe55adf..94c7bf33 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialEntry.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialEntry.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialIndexTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialIndexTree.java index b4bd5208..ad3ae29c 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialIndexTree.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialIndexTree.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialNode.java index 449992a2..27913d36 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialNode.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialNode.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialPair.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialPair.java index f69b1dd1..bc0c6c94 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialPair.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialPair.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialPointLeafEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialPointLeafEntry.java index d79893b0..61dbf7d7 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialPointLeafEntry.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/SpatialPointLeafEntry.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -39,7 +39,7 @@ import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector; * * @author Elke Achtert */ -public class SpatialPointLeafEntry extends AbstractLeafEntry implements SpatialEntry, NumberVector<Double> { +public class SpatialPointLeafEntry extends AbstractLeafEntry implements SpatialEntry, NumberVector { /** * Serial version. */ @@ -74,7 +74,7 @@ public class SpatialPointLeafEntry extends AbstractLeafEntry implements SpatialE * @param id Object id * @param vector Number vector */ - public SpatialPointLeafEntry(DBID id, NumberVector<?> vector) { + public SpatialPointLeafEntry(DBID id, NumberVector vector) { super(id); int dim = vector.getDimensionality(); this.values = new double[dim]; diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/kd/MinimalisticMemoryKDTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/kd/MinimalisticMemoryKDTree.java index ce1da63c..c55a454d 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/kd/MinimalisticMemoryKDTree.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/kd/MinimalisticMemoryKDTree.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.kd; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -31,10 +31,10 @@ import de.lmu.ifi.dbs.elki.data.type.TypeUtil; import de.lmu.ifi.dbs.elki.database.ids.ArrayModifiableDBIDs; import de.lmu.ifi.dbs.elki.database.ids.DBIDArrayIter; import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil; -import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPairList; -import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNHeap; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList; -import de.lmu.ifi.dbs.elki.database.ids.distance.ModifiableDoubleDistanceDBIDList; +import de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDList; +import de.lmu.ifi.dbs.elki.database.ids.KNNHeap; +import de.lmu.ifi.dbs.elki.database.ids.KNNList; +import de.lmu.ifi.dbs.elki.database.ids.ModifiableDoubleDBIDList; import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; import de.lmu.ifi.dbs.elki.database.query.knn.AbstractDistanceKNNQuery; import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery; @@ -43,12 +43,10 @@ import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery; import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.database.relation.RelationUtil; import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancefunction.DoubleNorm; +import de.lmu.ifi.dbs.elki.distance.distancefunction.Norm; import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.LPNormDistanceFunction; import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SparseLPNormDistanceFunction; import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SquaredEuclideanDistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; -import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; import de.lmu.ifi.dbs.elki.index.AbstractIndex; import de.lmu.ifi.dbs.elki.index.IndexFactory; import de.lmu.ifi.dbs.elki.index.KNNIndex; @@ -73,7 +71,7 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Reference; * @param <O> Vector type */ @Reference(authors = "J. L. Bentley", title = "Multidimensional binary search trees used for associative searching", booktitle = "Communications of the ACM, Vol. 18 Issue 9, Sept. 1975", url = "http://dx.doi.org/10.1145/361002.361007") -public class MinimalisticMemoryKDTree<O extends NumberVector<?>> extends AbstractIndex<O> implements KNNIndex<O>, RangeIndex<O> { +public class MinimalisticMemoryKDTree<O extends NumberVector> extends AbstractIndex<O> implements KNNIndex<O>, RangeIndex<O> { /** * Class logger */ @@ -187,36 +185,34 @@ public class MinimalisticMemoryKDTree<O extends NumberVector<?>> extends Abstrac } } - @SuppressWarnings("unchecked") @Override - public <D extends Distance<D>> KNNQuery<O, D> getKNNQuery(DistanceQuery<O, D> distanceQuery, Object... hints) { - DistanceFunction<? super O, D> df = distanceQuery.getDistanceFunction(); + public KNNQuery<O> getKNNQuery(DistanceQuery<O> distanceQuery, Object... hints) { + DistanceFunction<? super O> df = distanceQuery.getDistanceFunction(); // TODO: if we know this works for other distance functions, add them, too! if(df instanceof LPNormDistanceFunction) { - return (KNNQuery<O, D>) new KDTreeKNNQuery((DistanceQuery<O, DoubleDistance>) distanceQuery, (DoubleNorm<? super O>) df); + return new KDTreeKNNQuery(distanceQuery, (Norm<? super O>) df); } if(df instanceof SquaredEuclideanDistanceFunction) { - return (KNNQuery<O, D>) new KDTreeKNNQuery((DistanceQuery<O, DoubleDistance>) distanceQuery, (DoubleNorm<? super O>) df); + return new KDTreeKNNQuery(distanceQuery, (Norm<? super O>) df); } if(df instanceof SparseLPNormDistanceFunction) { - return (KNNQuery<O, D>) new KDTreeKNNQuery((DistanceQuery<O, DoubleDistance>) distanceQuery, (DoubleNorm<? super O>) df); + return new KDTreeKNNQuery(distanceQuery, (Norm<? super O>) df); } return null; } - @SuppressWarnings("unchecked") @Override - public <D extends Distance<D>> RangeQuery<O, D> getRangeQuery(DistanceQuery<O, D> distanceQuery, Object... hints) { - DistanceFunction<? super O, D> df = distanceQuery.getDistanceFunction(); + public RangeQuery<O> getRangeQuery(DistanceQuery<O> distanceQuery, Object... hints) { + DistanceFunction<? super O> df = distanceQuery.getDistanceFunction(); // TODO: if we know this works for other distance functions, add them, too! if(df instanceof LPNormDistanceFunction) { - return (RangeQuery<O, D>) new KDTreeRangeQuery((DistanceQuery<O, DoubleDistance>) distanceQuery, (DoubleNorm<? super O>) df); + return new KDTreeRangeQuery(distanceQuery, (Norm<? super O>) df); } if(df instanceof SquaredEuclideanDistanceFunction) { - return (RangeQuery<O, D>) new KDTreeRangeQuery((DistanceQuery<O, DoubleDistance>) distanceQuery, (DoubleNorm<? super O>) df); + return new KDTreeRangeQuery(distanceQuery, (Norm<? super O>) df); } if(df instanceof SparseLPNormDistanceFunction) { - return (RangeQuery<O, D>) new KDTreeRangeQuery((DistanceQuery<O, DoubleDistance>) distanceQuery, (DoubleNorm<? super O>) df); + return new KDTreeRangeQuery(distanceQuery, (Norm<? super O>) df); } return null; } @@ -226,11 +222,11 @@ public class MinimalisticMemoryKDTree<O extends NumberVector<?>> extends Abstrac * * @author Erich Schubert */ - public class KDTreeKNNQuery extends AbstractDistanceKNNQuery<O, DoubleDistance> { + public class KDTreeKNNQuery extends AbstractDistanceKNNQuery<O> { /** * Norm to use. */ - private DoubleNorm<? super O> norm; + private Norm<? super O> norm; /** * Constructor. @@ -238,14 +234,14 @@ public class MinimalisticMemoryKDTree<O extends NumberVector<?>> extends Abstrac * @param distanceQuery Distance query * @param norm Norm to use */ - public KDTreeKNNQuery(DistanceQuery<O, DoubleDistance> distanceQuery, DoubleNorm<? super O> norm) { + public KDTreeKNNQuery(DistanceQuery<O> distanceQuery, Norm<? super O> norm) { super(distanceQuery); this.norm = norm; } @Override - public KNNList<DoubleDistance> getKNNForObject(O obj, int k) { - final DoubleDistanceKNNHeap knns = DBIDUtil.newDoubleDistanceHeap(k); + public KNNList getKNNForObject(O obj, int k) { + final KNNHeap knns = DBIDUtil.newHeap(k); kdKNNSearch(0, sorted.size(), 0, obj, knns, sorted.iter(), Double.POSITIVE_INFINITY); return knns.toKNNList(); } @@ -262,7 +258,7 @@ public class MinimalisticMemoryKDTree<O extends NumberVector<?>> extends Abstrac * @param maxdist Current upper bound of kNN distance. * @return New upper bound of kNN distance. */ - private double kdKNNSearch(int left, int right, int axis, O query, DoubleDistanceKNNHeap knns, DBIDArrayIter iter, double maxdist) { + private double kdKNNSearch(int left, int right, int axis, O query, KNNHeap knns, DBIDArrayIter iter, double maxdist) { // Look at current node: final int middle = (left + right) >>> 1; iter.seek(middle); @@ -280,12 +276,12 @@ public class MinimalisticMemoryKDTree<O extends NumberVector<?>> extends Abstrac // Exact match chance (delta == 0)! // process first, then descend both sides. if(onleft && onright) { - double dist = norm.doubleDistance(query, split); + double dist = norm.distance(query, split); countDistanceComputation(); if(dist <= maxdist) { iter.seek(middle); knns.insert(dist, iter); - maxdist = knns.doubleKNNDistance(); + maxdist = knns.getKNNDistance(); } if(left < middle) { maxdist = kdKNNSearch(left, middle, next, query, knns, iter, maxdist); @@ -301,12 +297,12 @@ public class MinimalisticMemoryKDTree<O extends NumberVector<?>> extends Abstrac } // Look at splitting element (unless already above): if(Math.abs(delta) <= maxdist) { - double dist = norm.doubleDistance(query, split); + double dist = norm.distance(query, split); countDistanceComputation(); if(dist <= maxdist) { iter.seek(middle); knns.insert(dist, iter); - maxdist = knns.doubleKNNDistance(); + maxdist = knns.getKNNDistance(); } } if((middle + 1 < right) && (Math.abs(delta) <= maxdist)) { @@ -319,12 +315,12 @@ public class MinimalisticMemoryKDTree<O extends NumberVector<?>> extends Abstrac } // Look at splitting element (unless already above): if(Math.abs(delta) <= maxdist) { - double dist = norm.doubleDistance(query, split); + double dist = norm.distance(query, split); countDistanceComputation(); if(dist <= maxdist) { iter.seek(middle); knns.insert(dist, iter); - maxdist = knns.doubleKNNDistance(); + maxdist = knns.getKNNDistance(); } } if((left < middle) && (Math.abs(delta) <= maxdist)) { @@ -341,11 +337,11 @@ public class MinimalisticMemoryKDTree<O extends NumberVector<?>> extends Abstrac * * @author Erich Schubert */ - public class KDTreeRangeQuery extends AbstractDistanceRangeQuery<O, DoubleDistance> { + public class KDTreeRangeQuery extends AbstractDistanceRangeQuery<O> { /** * Norm to use. */ - private DoubleNorm<? super O> norm; + private Norm<? super O> norm; /** * Constructor. @@ -353,15 +349,15 @@ public class MinimalisticMemoryKDTree<O extends NumberVector<?>> extends Abstrac * @param distanceQuery Distance query * @param norm Norm to use */ - public KDTreeRangeQuery(DistanceQuery<O, DoubleDistance> distanceQuery, DoubleNorm<? super O> norm) { + public KDTreeRangeQuery(DistanceQuery<O> distanceQuery, Norm<? super O> norm) { super(distanceQuery); this.norm = norm; } @Override - public DoubleDistanceDBIDPairList getRangeForObject(O obj, DoubleDistance range) { - final DoubleDistanceDBIDPairList res = new DoubleDistanceDBIDPairList(); - kdRangeSearch(0, sorted.size(), 0, obj, res, sorted.iter(), range.doubleValue()); + public DoubleDBIDList getRangeForObject(O obj, double range) { + final ModifiableDoubleDBIDList res = DBIDUtil.newDistanceDBIDList(); + kdRangeSearch(0, sorted.size(), 0, obj, res, sorted.iter(), range); res.sort(); return res; } @@ -377,7 +373,7 @@ public class MinimalisticMemoryKDTree<O extends NumberVector<?>> extends Abstrac * @param iter Iterator variable (reduces memory footprint!) * @param radius Query radius */ - private void kdRangeSearch(int left, int right, int axis, O query, ModifiableDoubleDistanceDBIDList res, DBIDArrayIter iter, double radius) { + private void kdRangeSearch(int left, int right, int axis, O query, ModifiableDoubleDBIDList res, DBIDArrayIter iter, double radius) { // Look at current node: final int middle = (left + right) >>> 1; iter.seek(middle); @@ -395,7 +391,7 @@ public class MinimalisticMemoryKDTree<O extends NumberVector<?>> extends Abstrac // Current object: if(close) { - double dist = norm.doubleDistance(query, split); + double dist = norm.distance(query, split); countDistanceComputation(); if(dist <= radius) { iter.seek(middle); @@ -421,8 +417,8 @@ public class MinimalisticMemoryKDTree<O extends NumberVector<?>> extends Abstrac * * @param <O> Vector type */ - @Alias({"minikd", "kd"}) - public static class Factory<O extends NumberVector<?>> implements IndexFactory<O, MinimalisticMemoryKDTree<O>> { + @Alias({ "minikd", "kd" }) + public static class Factory<O extends NumberVector> implements IndexFactory<O, MinimalisticMemoryKDTree<O>> { /** * Constructor. Trivial parameterizable. */ diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/kd/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/kd/package-info.java index 88a42c2d..eab62562 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/kd/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/kd/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2013 +Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/package-info.java index 7fbdd2ac..d69e1516 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/package-info.java @@ -1,11 +1,13 @@ /** * <p>Tree-based index structures for <em>spatial</em> indexing.</p> + * + * @apiviz.exclude de.lmu.ifi.dbs.elki.tree.spatial.rstarvariants.deliclu */ /* This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2013 +Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRStarTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRStarTree.java index 63c8e8fa..8b0e5998 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRStarTree.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRStarTree.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRStarTreeFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRStarTreeFactory.java index 70e9f747..b51bfe10 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRStarTreeFactory.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRStarTreeFactory.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -56,7 +56,7 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter; * @param <E> Entry type * @param <I> Index type */ -public abstract class AbstractRStarTreeFactory<O extends NumberVector<?>, N extends AbstractRStarTreeNode<N, E>, E extends SpatialEntry, I extends AbstractRStarTree<N, E, S> & Index, S extends AbstractRTreeSettings> extends PagedIndexFactory<O, I> { +public abstract class AbstractRStarTreeFactory<O extends NumberVector, N extends AbstractRStarTreeNode<N, E>, E extends SpatialEntry, I extends AbstractRStarTree<N, E, S> & Index, S extends AbstractRTreeSettings> extends PagedIndexFactory<O, I> { /** * Tree settings */ @@ -88,7 +88,7 @@ public abstract class AbstractRStarTreeFactory<O extends NumberVector<?>, N exte * @param <O> Object type * @param <S> Settings class */ - public abstract static class Parameterizer<O extends NumberVector<?>, S extends AbstractRTreeSettings> extends PagedIndexFactory.Parameterizer<O> { + public abstract static class Parameterizer<O extends NumberVector, S extends AbstractRTreeSettings> extends PagedIndexFactory.Parameterizer<O> { /** * Fast-insertion parameter. Optional. */ diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRStarTreeNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRStarTreeNode.java index 6b5fc2f0..18f22ceb 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRStarTreeNode.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRStarTreeNode.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRTreeSettings.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRTreeSettings.java index f876be13..40a2aa6c 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRTreeSettings.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/AbstractRTreeSettings.java @@ -12,7 +12,7 @@ import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split.Top This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/NonFlatRStarTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/NonFlatRStarTree.java index 8a4f530f..eb04eec7 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/NonFlatRStarTree.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/NonFlatRStarTree.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluDirectoryEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluDirectoryEntry.java index 510120c9..eab4a7d6 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluDirectoryEntry.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluDirectoryEntry.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.deliclu; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluEntry.java index f72b7d8d..8478c0b5 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluEntry.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluEntry.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.deliclu; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluLeafEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluLeafEntry.java index 741ab840..a2c8490b 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluLeafEntry.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluLeafEntry.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.deliclu; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -62,7 +62,7 @@ public class DeLiCluLeafEntry extends SpatialPointLeafEntry implements DeLiCluEn * @param id the unique id of the underlying data object * @param vector the vector to store */ - public DeLiCluLeafEntry(DBID id, NumberVector<?> vector) { + public DeLiCluLeafEntry(DBID id, NumberVector vector) { super(id, vector); this.hasHandled = false; this.hasUnhandled = true; diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluNode.java index 7b3221c3..4fc22177 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluNode.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluNode.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.deliclu; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -61,7 +61,7 @@ public class DeLiCluNode extends AbstractRStarTreeNode<DeLiCluNode, DeLiCluEntry * handled data objects */ public boolean hasHandled() { - for(int i = 1; i < getNumEntries(); i++) { + for(int i = 0; i < getNumEntries(); i++) { boolean handled = getEntry(i).hasHandled(); if(handled) { return true; @@ -78,7 +78,7 @@ public class DeLiCluNode extends AbstractRStarTreeNode<DeLiCluNode, DeLiCluEntry * unhandled data objects */ public boolean hasUnhandled() { - for(int i = 1; i < getNumEntries(); i++) { + for(int i = 0; i < getNumEntries(); i++) { boolean handled = getEntry(i).hasUnhandled(); if(handled) { return true; diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluTree.java index 33366763..a2adca7f 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluTree.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluTree.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.deliclu; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluTreeFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluTreeFactory.java index a63b8004..b7770e79 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluTreeFactory.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluTreeFactory.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.deliclu; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -40,7 +40,7 @@ import de.lmu.ifi.dbs.elki.persistent.PageFileFactory; * * @param <O> Object type */ -public class DeLiCluTreeFactory<O extends NumberVector<?>> extends AbstractRStarTreeFactory<O, DeLiCluNode, DeLiCluEntry, DeLiCluTreeIndex<O>, AbstractRTreeSettings> { +public class DeLiCluTreeFactory<O extends NumberVector> extends AbstractRStarTreeFactory<O, DeLiCluNode, DeLiCluEntry, DeLiCluTreeIndex<O>, AbstractRTreeSettings> { /** * Constructor. * @@ -69,7 +69,7 @@ public class DeLiCluTreeFactory<O extends NumberVector<?>> extends AbstractRStar * * @apiviz.exclude */ - public static class Parameterizer<O extends NumberVector<?>> extends AbstractRStarTreeFactory.Parameterizer<O, AbstractRTreeSettings> { + public static class Parameterizer<O extends NumberVector> extends AbstractRStarTreeFactory.Parameterizer<O, AbstractRTreeSettings> { @Override protected DeLiCluTreeFactory<O> makeInstance() { return new DeLiCluTreeFactory<>(pageFileFactory, settings); diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluTreeIndex.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluTreeIndex.java index 67c9c9e0..6bc6c171 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluTreeIndex.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/DeLiCluTreeIndex.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.deliclu; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -37,7 +37,6 @@ import de.lmu.ifi.dbs.elki.database.query.distance.SpatialDistanceQuery; import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery; import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery; import de.lmu.ifi.dbs.elki.database.relation.Relation; -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; import de.lmu.ifi.dbs.elki.index.DynamicIndex; import de.lmu.ifi.dbs.elki.index.KNNIndex; import de.lmu.ifi.dbs.elki.index.RangeIndex; @@ -56,7 +55,7 @@ import de.lmu.ifi.dbs.elki.utilities.exceptions.AbortException; * * @param <O> Object type */ -public class DeLiCluTreeIndex<O extends NumberVector<?>> extends DeLiCluTree implements KNNIndex<O>, RangeIndex<O>, DynamicIndex { +public class DeLiCluTreeIndex<O extends NumberVector> extends DeLiCluTree implements KNNIndex<O>, RangeIndex<O>, DynamicIndex { /** * The relation we index. */ @@ -97,14 +96,14 @@ public class DeLiCluTreeIndex<O extends NumberVector<?>> extends DeLiCluTree imp * @return the path of node ids from the root to the objects's parent */ public synchronized List<TreeIndexPathComponent<DeLiCluEntry>> setHandled(DBID id, O obj) { - if (LOG.isDebugging()) { + if(LOG.isDebugging()) { LOG.debugFine("setHandled " + id + ", " + obj + "\n"); } // find the leaf node containing o IndexTreePath<DeLiCluEntry> pathToObject = findPathToObject(getRootPath(), obj, id); - if (pathToObject == null) { + if(pathToObject == null) { throw new AbortException("Object not found in setHandled."); } @@ -113,12 +112,12 @@ public class DeLiCluTreeIndex<O extends NumberVector<?>> extends DeLiCluTree imp entry.setHasHandled(true); entry.setHasUnhandled(false); - for (IndexTreePath<DeLiCluEntry> path = pathToObject; path.getParentPath() != null; path = path.getParentPath()) { + for(IndexTreePath<DeLiCluEntry> path = pathToObject; path.getParentPath() != null; path = path.getParentPath()) { DeLiCluEntry parentEntry = path.getParentPath().getLastPathComponent().getEntry(); DeLiCluNode node = getNode(parentEntry); boolean hasHandled = false; boolean hasUnhandled = false; - for (int i = 0; i < node.getNumEntries(); i++) { + for(int i = 0; i < node.getNumEntries(); i++) { final DeLiCluEntry nodeEntry = node.getEntry(i); hasHandled = hasHandled || nodeEntry.hasHandled(); hasUnhandled = hasUnhandled || nodeEntry.hasUnhandled(); @@ -154,19 +153,20 @@ public class DeLiCluTreeIndex<O extends NumberVector<?>> extends DeLiCluTree imp */ @Override public final void insertAll(DBIDs ids) { - if (ids.isEmpty() || (ids.size() == 1)) { + if(ids.isEmpty() || (ids.size() == 1)) { return; } // Make an example leaf - if (canBulkLoad()) { + if(canBulkLoad()) { List<DeLiCluEntry> leafs = new ArrayList<>(ids.size()); - for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { + for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { leafs.add(createNewLeafEntry(DBIDUtil.deref(iter))); } bulkLoad(leafs); - } else { - for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { + } + else { + for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { insert(iter); } } @@ -185,7 +185,7 @@ public class DeLiCluTreeIndex<O extends NumberVector<?>> extends DeLiCluTree imp // find the leaf node containing o O obj = relation.get(id); IndexTreePath<DeLiCluEntry> deletionPath = findPathToObject(getRootPath(), obj, id); - if (deletionPath == null) { + if(deletionPath == null) { return false; } deletePath(deletionPath); @@ -194,36 +194,36 @@ public class DeLiCluTreeIndex<O extends NumberVector<?>> extends DeLiCluTree imp @Override public void deleteAll(DBIDs ids) { - for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { + for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { delete(DBIDUtil.deref(iter)); } } @Override - public <D extends Distance<D>> RangeQuery<O, D> getRangeQuery(DistanceQuery<O, D> distanceQuery, Object... hints) { + public RangeQuery<O> getRangeQuery(DistanceQuery<O> distanceQuery, Object... hints) { // Query on the relation we index - if (distanceQuery.getRelation() != relation) { + if(distanceQuery.getRelation() != relation) { return null; } // Can we support this distance function - spatial distances only! - if (!(distanceQuery instanceof SpatialDistanceQuery)) { + if(!(distanceQuery instanceof SpatialDistanceQuery)) { return null; } - SpatialDistanceQuery<O, D> dq = (SpatialDistanceQuery<O, D>) distanceQuery; + SpatialDistanceQuery<O> dq = (SpatialDistanceQuery<O>) distanceQuery; return RStarTreeUtil.getRangeQuery(this, dq, hints); } @Override - public <D extends Distance<D>> KNNQuery<O, D> getKNNQuery(DistanceQuery<O, D> distanceQuery, Object... hints) { + public KNNQuery<O> getKNNQuery(DistanceQuery<O> distanceQuery, Object... hints) { // Query on the relation we index - if (distanceQuery.getRelation() != relation) { + if(distanceQuery.getRelation() != relation) { return null; } // Can we support this distance function - spatial distances only! - if (!(distanceQuery instanceof SpatialDistanceQuery)) { + if(!(distanceQuery instanceof SpatialDistanceQuery)) { return null; } - SpatialDistanceQuery<O, D> dq = (SpatialDistanceQuery<O, D>) distanceQuery; + SpatialDistanceQuery<O> dq = (SpatialDistanceQuery<O>) distanceQuery; return RStarTreeUtil.getKNNQuery(this, dq, hints); } diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/package-info.java index f8bec8cb..e17df1ca 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/deliclu/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2013 +Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/flat/FlatRStarTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/flat/FlatRStarTree.java new file mode 100644 index 00000000..498abc58 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/flat/FlatRStarTree.java @@ -0,0 +1,228 @@ +package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.flat; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2014 + 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.data.ModifiableHyperBoundingBox; +import de.lmu.ifi.dbs.elki.index.tree.TreeIndexHeader; +import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialDirectoryEntry; +import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRStarTree; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRTreeSettings; +import de.lmu.ifi.dbs.elki.logging.Logging; +import de.lmu.ifi.dbs.elki.persistent.PageFile; + +/** + * FlatRTree is a spatial index structure based on a R*-Tree but with a flat + * directory. Apart from organizing the objects it also provides several methods + * to search for certain object in the structure and ensures persistence. + * + * @author Elke Achtert + * + * @apiviz.has FlatRStarTreeNode oneway - - contains + */ +public class FlatRStarTree extends AbstractRStarTree<FlatRStarTreeNode, SpatialEntry, AbstractRTreeSettings> { + /** + * The logger for this class. + */ + private static final Logging LOG = Logging.getLogger(FlatRStarTree.class); + + /** + * The root of this flat RTree. + */ + private FlatRStarTreeNode root; + + /** + * Constructor. + * + * @param pagefile Page file + * @param settings Tree settings + */ + public FlatRStarTree(PageFile<FlatRStarTreeNode> pagefile, AbstractRTreeSettings settings) { + super(pagefile, settings); + } + + /** + * Initializes the flat RTree from an existing persistent file. + */ + @Override + public void initializeFromFile(TreeIndexHeader header, PageFile<FlatRStarTreeNode> file) { + super.initializeFromFile(header, file); + + // reconstruct root + int nextPageID = file.getNextPageID(); + dirCapacity = nextPageID; + root = createNewDirectoryNode(); + for(int i = 1; i < nextPageID; i++) { + FlatRStarTreeNode node = getNode(i); + root.addDirectoryEntry(createNewDirectoryEntry(node)); + } + + if(LOG.isDebugging()) { + LOG.debugFine("root: " + root + " with " + nextPageID + " leafNodes."); + } + } + + /** + * Returns the root node of this RTree. + * + * @return the root node of this RTree + */ + @Override + public FlatRStarTreeNode getRoot() { + return root; + } + + /** + * Returns the height of this FlatRTree. + * + * @return 2 + */ + @Override + protected int computeHeight() { + return 2; + } + + /** + * Performs a bulk load on this RTree with the specified data. Is called by + * the constructor and should be overwritten by subclasses if necessary. + */ + @Override + protected void bulkLoad(List<SpatialEntry> spatialObjects) { + if(!initialized) { + initialize(spatialObjects.get(0)); + } + // create leaf nodes + getFile().setNextPageID(getRootID() + 1); + List<SpatialEntry> nodes = createBulkLeafNodes(spatialObjects); + int numNodes = nodes.size(); + if(LOG.isDebugging()) { + LOG.debugFine(" numLeafNodes = " + numNodes); + } + + // create root + root = createNewDirectoryNode(); + root.setPageID(getRootID()); + for(SpatialEntry entry : nodes) { + root.addDirectoryEntry(entry); + } + numNodes++; + setHeight(2); + + if(LOG.isDebugging()) { + StringBuilder msg = new StringBuilder(); + msg.append(" root = ").append(getRoot()); + msg.append("\n numNodes = ").append(numNodes); + msg.append("\n height = ").append(getHeight()); + LOG.debugFine(msg.toString() + "\n"); + } + doExtraIntegrityChecks(); + } + + @Override + protected void createEmptyRoot(SpatialEntry exampleLeaf) { + root = createNewDirectoryNode(); + root.setPageID(getRootID()); + + getFile().setNextPageID(getRootID() + 1); + FlatRStarTreeNode leaf = createNewLeafNode(); + writeNode(leaf); + ModifiableHyperBoundingBox mbr = new ModifiableHyperBoundingBox(new double[exampleLeaf.getDimensionality()], new double[exampleLeaf.getDimensionality()]); + root.addDirectoryEntry(new SpatialDirectoryEntry(leaf.getPageID(), mbr)); + + setHeight(2); + } + + /** + * Returns true if in the specified node an overflow occurred, false + * otherwise. + * + * @param node the node to be tested for overflow + * @return true if in the specified node an overflow occurred, false otherwise + */ + @Override + protected boolean hasOverflow(FlatRStarTreeNode node) { + if(node.isLeaf()) { + return node.getNumEntries() == leafCapacity; + } + else if(node.getNumEntries() == node.getCapacity()) { + node.increaseEntries(); + } + return false; + } + + /** + * Returns true if in the specified node an underflow occurred, false + * otherwise. + * + * @param node the node to be tested for underflow + * @return true if in the specified node an underflow occurred, false + * otherwise + */ + @Override + protected boolean hasUnderflow(FlatRStarTreeNode node) { + if(node.isLeaf()) { + return node.getNumEntries() < leafMinimum; + } + else { + return false; + } + } + + /** + * Creates a new leaf node with the specified capacity. + * + * @return a new leaf node + */ + @Override + protected FlatRStarTreeNode createNewLeafNode() { + return new FlatRStarTreeNode(leafCapacity, true); + } + + /** + * Creates a new directory node with the specified capacity. + * + * @return a new directory node + */ + @Override + protected FlatRStarTreeNode createNewDirectoryNode() { + return new FlatRStarTreeNode(dirCapacity, false); + } + + @Override + protected SpatialEntry createNewDirectoryEntry(FlatRStarTreeNode node) { + return new SpatialDirectoryEntry(node.getPageID(), node.computeMBR()); + } + + @Override + protected SpatialEntry createRootEntry() { + return new SpatialDirectoryEntry(0, null); + } + + @Override + protected Logging getLogger() { + return LOG; + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/flat/FlatRStarTreeFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/flat/FlatRStarTreeFactory.java new file mode 100644 index 00000000..ea631ecd --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/flat/FlatRStarTreeFactory.java @@ -0,0 +1,84 @@ +package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.flat; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2014 + 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.data.NumberVector; +import de.lmu.ifi.dbs.elki.database.relation.Relation; +import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRStarTreeFactory; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRTreeSettings; +import de.lmu.ifi.dbs.elki.persistent.PageFile; +import de.lmu.ifi.dbs.elki.persistent.PageFileFactory; + +/** + * Factory for flat R*-Trees. + * + * @author Erich Schubert + * + * @apiviz.stereotype factory + * @apiviz.uses FlatRStarTreeIndex oneway - - «create» + * + * @param <O> Object type + */ +public class FlatRStarTreeFactory<O extends NumberVector> extends AbstractRStarTreeFactory<O, FlatRStarTreeNode, SpatialEntry, FlatRStarTreeIndex<O>, AbstractRTreeSettings> { + /** + * Constructor. + * + * @param pageFileFactory Data storage + * @param settings Index settings + */ + public FlatRStarTreeFactory(PageFileFactory<?> pageFileFactory, AbstractRTreeSettings settings) { + super(pageFileFactory, settings); + } + + @Override + public FlatRStarTreeIndex<O> instantiate(Relation<O> relation) { + PageFile<FlatRStarTreeNode> pagefile = makePageFile(getNodeClass()); + FlatRStarTreeIndex<O> index = new FlatRStarTreeIndex<>(relation, pagefile, settings); + return index; + } + + protected Class<FlatRStarTreeNode> getNodeClass() { + return FlatRStarTreeNode.class; + } + + /** + * Parameterization class. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + public static class Parameterizer<O extends NumberVector> extends AbstractRStarTreeFactory.Parameterizer<O, AbstractRTreeSettings> { + @Override + protected FlatRStarTreeFactory<O> makeInstance() { + return new FlatRStarTreeFactory<>(pageFileFactory, settings); + } + + @Override + protected AbstractRTreeSettings createSettings() { + return new AbstractRTreeSettings(); + } + } +} diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/flat/FlatRStarTreeIndex.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/flat/FlatRStarTreeIndex.java new file mode 100644 index 00000000..6b5204e5 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/flat/FlatRStarTreeIndex.java @@ -0,0 +1,203 @@ +package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.flat; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2014 + 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.List; + +import de.lmu.ifi.dbs.elki.data.NumberVector; +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.query.distance.DistanceQuery; +import de.lmu.ifi.dbs.elki.database.query.distance.SpatialDistanceQuery; +import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery; +import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery; +import de.lmu.ifi.dbs.elki.database.relation.Relation; +import de.lmu.ifi.dbs.elki.index.DynamicIndex; +import de.lmu.ifi.dbs.elki.index.KNNIndex; +import de.lmu.ifi.dbs.elki.index.RangeIndex; +import de.lmu.ifi.dbs.elki.index.tree.IndexTreePath; +import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry; +import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialPointLeafEntry; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRTreeSettings; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.query.RStarTreeUtil; +import de.lmu.ifi.dbs.elki.logging.Logging; +import de.lmu.ifi.dbs.elki.persistent.PageFile; + +/** + * The common use of the flat rstar tree: indexing number vectors. + * + * @author Erich Schubert + * + * @param <O> Object type + */ +public class FlatRStarTreeIndex<O extends NumberVector> extends FlatRStarTree implements RangeIndex<O>, KNNIndex<O>, DynamicIndex { + /** + * The relation we index + */ + private Relation<O> relation; + + /** + * Constructor. + * + * @param relation Relation to index + * @param pagefile Page file + * @param settings Tree settings + */ + public FlatRStarTreeIndex(Relation<O> relation, PageFile<FlatRStarTreeNode> pagefile, AbstractRTreeSettings settings) { + super(pagefile, settings); + this.relation = relation; + } + + /** + * The appropriate logger for this index. + */ + private static final Logging LOG = Logging.getLogger(FlatRStarTreeIndex.class); + + /** + * Wrap a vector as spatial point leaf entry. + * + * @param id Object DBID + * @return spatial leaf + */ + protected SpatialEntry createNewLeafEntry(DBID id) { + return new SpatialPointLeafEntry(id, relation.get(id)); + } + + @Override + public void initialize() { + super.initialize(); + insertAll(relation.getDBIDs()); + } + + /** + * Inserts the specified real vector object into this index. + * + * @param id the object id that was inserted + */ + @Override + public final void insert(DBIDRef id) { + insertLeaf(createNewLeafEntry(DBIDUtil.deref(id))); + } + + /** + * Inserts the specified objects into this index. If a bulk load mode is + * implemented, the objects are inserted in one bulk. + * + * @param ids the objects to be inserted + */ + @Override + public final void insertAll(DBIDs ids) { + if(ids.isEmpty() || (ids.size() == 1)) { + return; + } + + // Make an example leaf + if(canBulkLoad()) { + List<SpatialEntry> leafs = new ArrayList<>(ids.size()); + for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { + leafs.add(createNewLeafEntry(DBIDUtil.deref(iter))); + } + bulkLoad(leafs); + } + else { + for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { + insert(iter); + } + } + + doExtraIntegrityChecks(); + } + + /** + * Deletes the specified object from this index. + * + * @return true if this index did contain the object with the specified id, + * false otherwise + */ + @Override + public final boolean delete(DBIDRef id) { + // find the leaf node containing o + O obj = relation.get(id); + IndexTreePath<SpatialEntry> deletionPath = findPathToObject(getRootPath(), obj, id); + if(deletionPath == null) { + return false; + } + deletePath(deletionPath); + return true; + } + + @Override + public void deleteAll(DBIDs ids) { + for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { + delete(DBIDUtil.deref(iter)); + } + } + + @Override + public RangeQuery<O> getRangeQuery(DistanceQuery<O> distanceQuery, Object... hints) { + // Query on the relation we index + if(distanceQuery.getRelation() != relation) { + return null; + } + // Can we support this distance function - spatial distances only! + if(!(distanceQuery instanceof SpatialDistanceQuery)) { + return null; + } + SpatialDistanceQuery<O> dq = (SpatialDistanceQuery<O>) distanceQuery; + return RStarTreeUtil.getRangeQuery(this, dq, hints); + } + + @Override + public KNNQuery<O> getKNNQuery(DistanceQuery<O> distanceQuery, Object... hints) { + // Query on the relation we index + if(distanceQuery.getRelation() != relation) { + return null; + } + // Can we support this distance function - spatial distances only! + if(!(distanceQuery instanceof SpatialDistanceQuery)) { + return null; + } + SpatialDistanceQuery<O> dq = (SpatialDistanceQuery<O>) distanceQuery; + return RStarTreeUtil.getKNNQuery(this, dq, hints); + } + + @Override + public String getLongName() { + return "Flat R*-Tree"; + } + + @Override + public String getShortName() { + return "flatrstartree"; + } + + @Override + protected Logging getLogger() { + return LOG; + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/flat/FlatRStarTreeNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/flat/FlatRStarTreeNode.java new file mode 100644 index 00000000..7015577d --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/flat/FlatRStarTreeNode.java @@ -0,0 +1,81 @@ +package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.flat; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2014 + 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.index.tree.spatial.SpatialEntry; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRStarTreeNode; +import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil; + +/** + * Represents a node in a flat R*-Tree. + * + * @author Elke Achtert + */ +public class FlatRStarTreeNode extends AbstractRStarTreeNode<FlatRStarTreeNode, SpatialEntry> { + /** + * Serial version + */ + private static final long serialVersionUID = 1; + + /** + * Empty constructor for Externalizable interface. + */ + public FlatRStarTreeNode() { + // empty constructor + } + + /** + * Deletes the entry at the specified index and shifts all entries after the + * index to left. + * + * @param index the index at which the entry is to be deleted + */ + @Override + public boolean deleteEntry(int index) { + if(this.getPageID() == 0 && index == 0 && getNumEntries() == 1) { + return false; + } + return super.deleteEntry(index); + } + + /** + * Creates a new FlatRStarTreeNode with the specified parameters. + * + * @param capacity the capacity (maximum number of entries plus 1 for + * overflow) of this node + * @param isLeaf indicates whether this node is a leaf node + */ + public FlatRStarTreeNode(int capacity, boolean isLeaf) { + super(capacity, isLeaf, SpatialEntry.class); + } + + /** + * Increases the length of the entries array to entries.length + 1. + */ + public final void increaseEntries() { + SpatialEntry[] tmp = entries; + entries = ClassGenericsUtil.newArrayOfNull(tmp.length + 1, SpatialEntry.class); + System.arraycopy(tmp, 0, entries, 0, tmp.length); + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/flat/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/flat/package-info.java new file mode 100644 index 00000000..fd092666 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/flat/package-info.java @@ -0,0 +1,26 @@ +/** + * <p>{@link de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.flat.FlatRStarTree}</p> + */ +/* +This file is part of ELKI: +Environment for Developing KDD-Applications Supported by Index-Structures + +Copyright (C) 2014 +Ludwig-Maximilians-Universität München +Lehr- und Forschungseinheit für Datenbanksysteme +ELKI Development Team + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.flat;
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/package-info.java index e50cc513..aa47110c 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2013 +Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/EuclideanRStarTreeKNNQuery.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/EuclideanRStarTreeKNNQuery.java new file mode 100644 index 00000000..e1763d3e --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/EuclideanRStarTreeKNNQuery.java @@ -0,0 +1,167 @@ +package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.query; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2014 + 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.HashMap; +import java.util.List; +import java.util.Map; + +import de.lmu.ifi.dbs.elki.data.NumberVector; +import de.lmu.ifi.dbs.elki.database.QueryUtil; +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.DBIDUtil; +import de.lmu.ifi.dbs.elki.database.ids.KNNHeap; +import de.lmu.ifi.dbs.elki.database.ids.KNNList; +import de.lmu.ifi.dbs.elki.database.relation.Relation; +import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction; +import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SquaredEuclideanDistanceFunction; +import de.lmu.ifi.dbs.elki.index.tree.query.DoubleDistanceSearchCandidate; +import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialDirectoryEntry; +import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialPointLeafEntry; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRStarTree; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRStarTreeNode; +import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.ComparableMinHeap; +import de.lmu.ifi.dbs.elki.utilities.documentation.Reference; + +/** + * Instance of a KNN query for a particular spatial index. + * + * Reference: + * <p> + * G. R. Hjaltason, H. Samet<br /> + * Ranking in spatial databases<br /> + * In: 4th Symposium on Advances in Spatial Databases, SSD'95 + * </p> + * + * @author Erich Schubert + * + * @apiviz.uses EuclideanDistanceFunction + * @apiviz.uses SquaredEuclideanDistanceFunction + */ +@Reference(authors = "G. R. Hjaltason, H. Samet", // +title = "Ranking in spatial databases", // +booktitle = "Advances in Spatial Databases - 4th Symposium, SSD'95", // +url = "http://dx.doi.org/10.1007/3-540-60159-7_6") +public class EuclideanRStarTreeKNNQuery<O extends NumberVector> extends RStarTreeKNNQuery<O> { + /** + * Squared euclidean distance function. + */ + private static final SquaredEuclideanDistanceFunction SQUARED = SquaredEuclideanDistanceFunction.STATIC; + + /** + * Constructor. + * + * @param tree Index to use + * @param relation Data relation to query + */ + public EuclideanRStarTreeKNNQuery(AbstractRStarTree<?, ?, ?> tree, Relation<? extends O> relation) { + super(tree, relation, EuclideanDistanceFunction.STATIC); + } + + @Override + public KNNList getKNNForObject(O obj, int k) { + if(k < 1) { + throw new IllegalArgumentException("At least one neighbor has to be requested!"); + } + tree.statistics.countKNNQuery(); + + final KNNHeap knnList = DBIDUtil.newHeap(k); + final ComparableMinHeap<DoubleDistanceSearchCandidate> pq = new ComparableMinHeap<>(Math.min(knnList.getK() << 1, 21)); + + // expand root + double maxDist = expandNode(obj, knnList, pq, Double.MAX_VALUE, tree.getRootID()); + + // search in tree + while(!pq.isEmpty()) { + DoubleDistanceSearchCandidate pqNode = pq.poll(); + + if(pqNode.mindist > maxDist) { + break; + } + maxDist = expandNode(obj, knnList, pq, maxDist, pqNode.nodeID); + } + return QueryUtil.applySqrt(knnList.toKNNList()); + } + + private double expandNode(O object, KNNHeap knnList, final ComparableMinHeap<DoubleDistanceSearchCandidate> pq, double maxDist, final int nodeID) { + AbstractRStarTreeNode<?, ?> node = tree.getNode(nodeID); + // data node + if(node.isLeaf()) { + for(int i = 0; i < node.getNumEntries(); i++) { + SpatialPointLeafEntry entry = (SpatialPointLeafEntry) node.getEntry(i); + double distance = SQUARED.minDist(entry, object); + tree.statistics.countDistanceCalculation(); + if(distance <= maxDist) { + maxDist = knnList.insert(distance, entry.getDBID()); + } + } + } + // directory node + else { + for(int i = 0; i < node.getNumEntries(); i++) { + SpatialDirectoryEntry entry = (SpatialDirectoryEntry) node.getEntry(i); + double distance = SQUARED.minDist(entry, object); + tree.statistics.countDistanceCalculation(); + // Greedy expand, bypassing the queue + if(distance <= 0) { + expandNode(object, knnList, pq, maxDist, entry.getPageID()); + } + else { + if(distance <= maxDist) { + pq.add(new DoubleDistanceSearchCandidate(distance, entry.getPageID())); + } + } + } + } + return maxDist; + } + + @Override + public List<KNNList> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) { + if(k < 1) { + throw new IllegalArgumentException("At least one enumeration has to be requested!"); + } + + // While this works, it seems to be slow at least for large sets! + // TODO: use a DataStore instead of a map. + final Map<DBID, KNNHeap> knnLists = new HashMap<>(ids.size()); + for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { + DBID id = DBIDUtil.deref(iter); + knnLists.put(id, DBIDUtil.newHeap(k)); + } + + batchNN(tree.getRoot(), knnLists); + + List<KNNList> result = new ArrayList<>(); + for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { + DBID id = DBIDUtil.deref(iter); + tree.statistics.countKNNQuery(); + result.add(QueryUtil.applySqrt(knnLists.get(id).toKNNList())); + } + return result; + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/EuclideanRStarTreeRangeQuery.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/EuclideanRStarTreeRangeQuery.java new file mode 100644 index 00000000..0fcb633b --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/EuclideanRStarTreeRangeQuery.java @@ -0,0 +1,120 @@ +package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.query; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2014 + 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.data.NumberVector; +import de.lmu.ifi.dbs.elki.database.ids.DBIDUtil; +import de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDList; +import de.lmu.ifi.dbs.elki.database.ids.ModifiableDoubleDBIDList; +import de.lmu.ifi.dbs.elki.database.relation.Relation; +import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction; +import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SquaredEuclideanDistanceFunction; +import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialDirectoryEntry; +import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialPointLeafEntry; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRStarTree; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRStarTreeNode; +import de.lmu.ifi.dbs.elki.utilities.documentation.Reference; + +/** + * Instance of a range query for a particular spatial index. + * + * Reference: + * <p> + * J. Kuan, P. Lewis<br /> + * Fast k nearest neighbour search for R-tree family<br /> + * In Proc. Int. Conf Information, Communications and Signal Processing, ICICS + * 1997 + * </p> + * + * @author Erich Schubert + * + * @apiviz.uses EuclideanDistanceFunction + * @apiviz.uses SquaredEuclideanDistanceFunction + */ +@Reference(authors = "J. Kuan, P. Lewis", title = "Fast k nearest neighbour search for R-tree family", booktitle = "Proc. Int. Conf Information, Communications and Signal Processing, ICICS 1997", url = "http://dx.doi.org/10.1109/ICICS.1997.652114") +public class EuclideanRStarTreeRangeQuery<O extends NumberVector> extends RStarTreeRangeQuery<O> { + /** + * Squared euclidean distance function. + */ + private static final SquaredEuclideanDistanceFunction SQUARED = SquaredEuclideanDistanceFunction.STATIC; + + /** + * Constructor. + * + * @param tree Index to use + * @param relation Relation to use. + */ + public EuclideanRStarTreeRangeQuery(AbstractRStarTree<?, ?, ?> tree, Relation<? extends O> relation) { + super(tree, relation, EuclideanDistanceFunction.STATIC); + } + + @Override + public DoubleDBIDList getRangeForObject(O object, double range) { + tree.statistics.countRangeQuery(); + ModifiableDoubleDBIDList result = DBIDUtil.newDistanceDBIDList(); + + final double sqepsilon = range * range; + + // Processing queue. + int[] pq = new int[101]; + int ps = 0; + pq[ps++] = tree.getRootID(); + + // search in tree + while(ps > 0) { + int pqNode = pq[--ps]; // Pop last. + AbstractRStarTreeNode<?, ?> node = tree.getNode(pqNode); + final int numEntries = node.getNumEntries(); + + if(node.isLeaf()) { + for(int i = 0; i < numEntries; i++) { + SpatialPointLeafEntry entry = (SpatialPointLeafEntry) node.getEntry(i); + double distance = SQUARED.minDist(object, entry); + tree.statistics.countDistanceCalculation(); + if(distance <= sqepsilon) { + result.add(Math.sqrt(distance), entry.getDBID()); + } + } + } + else { + for(int i = 0; i < numEntries; i++) { + SpatialDirectoryEntry entry = (SpatialDirectoryEntry) node.getEntry(i); + double distance = SQUARED.minDist(object, entry); + if(distance <= sqepsilon) { + if(ps == pq.length) { // Resize: + pq = Arrays.copyOf(pq, pq.length + (pq.length >>> 1)); + } + pq[ps++] = entry.getEntryID(); + } + } + } + } + + // sort the result according to the distances + result.sort(); + return result; + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/GenericRStarTreeKNNQuery.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/GenericRStarTreeKNNQuery.java deleted file mode 100644 index 229758ea..00000000 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/GenericRStarTreeKNNQuery.java +++ /dev/null @@ -1,243 +0,0 @@ -package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.query; - -/* - This file is part of ELKI: - Environment for Developing KDD-Applications Supported by Index-Structures - - Copyright (C) 2013 - Ludwig-Maximilians-Universität München - Lehr- und Forschungseinheit für Datenbanksysteme - ELKI Development Team - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; -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.DBIDUtil; -import de.lmu.ifi.dbs.elki.database.ids.DBIDs; -import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNHeap; -import de.lmu.ifi.dbs.elki.database.ids.distance.KNNList; -import de.lmu.ifi.dbs.elki.database.query.distance.SpatialDistanceQuery; -import de.lmu.ifi.dbs.elki.database.query.knn.AbstractDistanceKNNQuery; -import de.lmu.ifi.dbs.elki.distance.DistanceUtil; -import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; -import de.lmu.ifi.dbs.elki.index.tree.DirectoryEntry; -import de.lmu.ifi.dbs.elki.index.tree.LeafEntry; -import de.lmu.ifi.dbs.elki.index.tree.query.GenericDistanceSearchCandidate; -import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialEntry; -import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRStarTree; -import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRStarTreeNode; -import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.ComparableMinHeap; -import de.lmu.ifi.dbs.elki.utilities.documentation.Reference; -import de.lmu.ifi.dbs.elki.utilities.pairs.FCPair; - -/** - * Instance of a KNN query for a particular spatial index. - * - * Reference: - * <p> - * G. R. Hjaltason, H. Samet<br /> - * Ranking in spatial databases<br /> - * In: 4th Symposium on Advances in Spatial Databases, SSD'95 - * </p> - * - * @author Erich Schubert - * - * @apiviz.uses AbstractRStarTree - * @apiviz.uses SpatialPrimitiveDistanceFunction - */ -@Reference(authors = "G. R. Hjaltason, H. Samet", title = "Ranking in spatial databases", booktitle = "Advances in Spatial Databases - 4th Symposium, SSD'95", url = "http://dx.doi.org/10.1007/3-540-60159-7_6") -public class GenericRStarTreeKNNQuery<O extends SpatialComparable, D extends Distance<D>> extends AbstractDistanceKNNQuery<O, D> { - /** - * The index to use - */ - protected final AbstractRStarTree<?, ?, ?> tree; - - /** - * Spatial primitive distance function - */ - protected final SpatialPrimitiveDistanceFunction<? super O, D> distanceFunction; - - /** - * Constructor. - * - * @param tree Index to use - * @param distanceQuery Distance query to use - */ - public GenericRStarTreeKNNQuery(AbstractRStarTree<?, ?, ?> tree, SpatialDistanceQuery<O, D> distanceQuery) { - super(distanceQuery); - this.tree = tree; - this.distanceFunction = distanceQuery.getDistanceFunction(); - } - - /** - * Performs a batch knn query. - * - * @param node the node for which the query should be performed - * @param knnLists a map containing the knn lists for each query objects - */ - protected void batchNN(AbstractRStarTreeNode<?, ?> node, Map<DBID, KNNHeap<D>> knnLists) { - if(node.isLeaf()) { - for(int i = 0; i < node.getNumEntries(); i++) { - SpatialEntry p = node.getEntry(i); - for(Entry<DBID, KNNHeap<D>> ent : knnLists.entrySet()) { - final DBID q = ent.getKey(); - final KNNHeap<D> knns_q = ent.getValue(); - D knn_q_maxDist = knns_q.getKNNDistance(); - - DBID pid = ((LeafEntry) p).getDBID(); - // FIXME: objects are NOT accessible by DBID in a plain rtree context! - D dist_pq = distanceQuery.distance(pid, q); - tree.statistics.countDistanceCalculation(); - if(dist_pq.compareTo(knn_q_maxDist) <= 0) { - knns_q.insert(dist_pq, pid); - } - } - } - } - else { - ModifiableDBIDs ids = DBIDUtil.newArray(knnLists.size()); - for(DBID id : knnLists.keySet()) { - ids.add(id); - } - List<FCPair<D, SpatialEntry>> entries = getSortedEntries(node, ids); - for(FCPair<D, SpatialEntry> distEntry : entries) { - D minDist = distEntry.first; - for(Entry<DBID, KNNHeap<D>> ent : knnLists.entrySet()) { - final KNNHeap<D> knns_q = ent.getValue(); - D knn_q_maxDist = knns_q.getKNNDistance(); - - if(minDist.compareTo(knn_q_maxDist) <= 0) { - SpatialEntry entry = distEntry.second; - AbstractRStarTreeNode<?, ?> child = tree.getNode(((DirectoryEntry) entry).getPageID().intValue()); - batchNN(child, knnLists); - break; - } - } - } - } - } - - /** - * Sorts the entries of the specified node according to their minimum distance - * to the specified objects. - * - * @param node the node - * @param ids the id of the objects - * @return a list of the sorted entries - */ - protected List<FCPair<D, SpatialEntry>> getSortedEntries(AbstractRStarTreeNode<?, ?> node, DBIDs ids) { - List<FCPair<D, SpatialEntry>> result = new ArrayList<>(); - - for(int i = 0; i < node.getNumEntries(); i++) { - SpatialEntry entry = node.getEntry(i); - D minMinDist = distanceQuery.getDistanceFactory().infiniteDistance(); - for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { - D minDist = distanceFunction.minDist(entry, relation.get(iter)); - tree.statistics.countDistanceCalculation(); - minMinDist = DistanceUtil.min(minDist, minMinDist); - } - result.add(new FCPair<>(minMinDist, entry)); - } - - Collections.sort(result); - return result; - } - - @Override - public KNNList<D> getKNNForObject(O obj, int k) { - final KNNHeap<D> knnList = DBIDUtil.newHeap(distanceFunction.getDistanceFactory(), k); - final ComparableMinHeap<GenericDistanceSearchCandidate<D>> pq = new ComparableMinHeap<>(Math.min(knnList.getK() << 1, 20)); - tree.statistics.countKNNQuery(); - - // push root - pq.add(new GenericDistanceSearchCandidate<>(distanceFunction.getDistanceFactory().nullDistance(), tree.getRootID())); - D maxDist = distanceFunction.getDistanceFactory().infiniteDistance(); - - // search in tree - while(!pq.isEmpty()) { - GenericDistanceSearchCandidate<D> pqNode = pq.poll(); - - if(pqNode.mindist.compareTo(maxDist) > 0) { - break; - } - maxDist = expandNode(obj, knnList, pq, maxDist, pqNode.nodeID); - } - return knnList.toKNNList(); - } - - private D expandNode(O object, KNNHeap<D> knnList, final ComparableMinHeap<GenericDistanceSearchCandidate<D>> pq, D maxDist, final int nodeID) { - AbstractRStarTreeNode<?, ?> node = tree.getNode(nodeID); - // data node - if(node.isLeaf()) { - for(int i = 0; i < node.getNumEntries(); i++) { - SpatialEntry entry = node.getEntry(i); - D distance = distanceFunction.minDist(entry, object); - tree.statistics.countDistanceCalculation(); - if(distance.compareTo(maxDist) <= 0) { - knnList.insert(distance, ((LeafEntry) entry).getDBID()); - maxDist = knnList.getKNNDistance(); - } - } - } - // directory node - else { - for(int i = 0; i < node.getNumEntries(); i++) { - SpatialEntry entry = node.getEntry(i); - D distance = distanceFunction.minDist(entry, object); - tree.statistics.countDistanceCalculation(); - // Greedy expand, bypassing the queue - if(distance.isNullDistance()) { - expandNode(object, knnList, pq, maxDist, ((DirectoryEntry) entry).getPageID()); - } - else { - if(distance.compareTo(maxDist) <= 0) { - pq.add(new GenericDistanceSearchCandidate<>(distance, ((DirectoryEntry) entry).getPageID())); - } - } - } - } - return maxDist; - } - - @Override - public List<KNNList<D>> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) { - // While this works, it seems to be slow at least for large sets! - final Map<DBID, KNNHeap<D>> knnLists = new HashMap<>(ids.size()); - for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { - knnLists.put(DBIDUtil.deref(iter), DBIDUtil.newHeap(distanceFunction.getDistanceFactory(), k)); - } - - batchNN(tree.getRoot(), knnLists); - - List<KNNList<D>> result = new ArrayList<>(); - for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { - tree.statistics.countKNNQuery(); - result.add(knnLists.get(DBIDUtil.deref(iter)).toKNNList()); - } - return result; - } -} diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/GenericRStarTreeRangeQuery.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/GenericRStarTreeRangeQuery.java deleted file mode 100644 index 16a3393a..00000000 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/GenericRStarTreeRangeQuery.java +++ /dev/null @@ -1,131 +0,0 @@ -package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.query; - -/* - This file is part of ELKI: - Environment for Developing KDD-Applications Supported by Index-Structures - - Copyright (C) 2013 - Ludwig-Maximilians-Universität München - Lehr- und Forschungseinheit für Datenbanksysteme - ELKI Development Team - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; -import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList; -import de.lmu.ifi.dbs.elki.database.ids.generic.GenericDistanceDBIDList; -import de.lmu.ifi.dbs.elki.database.query.distance.SpatialDistanceQuery; -import de.lmu.ifi.dbs.elki.database.query.range.AbstractDistanceRangeQuery; -import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; -import de.lmu.ifi.dbs.elki.index.tree.DirectoryEntry; -import de.lmu.ifi.dbs.elki.index.tree.LeafEntry; -import de.lmu.ifi.dbs.elki.index.tree.query.GenericDistanceSearchCandidate; -import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRStarTree; -import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRStarTreeNode; -import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.ComparableMinHeap; -import de.lmu.ifi.dbs.elki.utilities.documentation.Reference; - -/** - * Instance of a range query for a particular spatial index. - * - * Reference: - * <p> - * J. Kuan, P. Lewis<br /> - * Fast k nearest neighbour search for R-tree family<br /> - * In Proc. Int. Conf Information, Communications and Signal Processing, ICICS - * 1997 - * </p> - * - * @author Erich Schubert - * - * @apiviz.uses AbstractRStarTree - * @apiviz.uses SpatialPrimitiveDistanceFunction - */ -@Reference(authors = "J. Kuan, P. Lewis", title = "Fast k nearest neighbour search for R-tree family", booktitle = "Proc. Int. Conf Information, Communications and Signal Processing, ICICS 1997", url = "http://dx.doi.org/10.1109/ICICS.1997.652114") -public class GenericRStarTreeRangeQuery<O extends SpatialComparable, D extends Distance<D>> extends AbstractDistanceRangeQuery<O, D> { - /** - * The index to use - */ - protected final AbstractRStarTree<?, ?, ?> tree; - - /** - * Spatial primitive distance function - */ - protected final SpatialPrimitiveDistanceFunction<? super O, D> distanceFunction; - - /** - * Constructor. - * - * @param tree Index to use - * @param distanceQuery Distance query to use - */ - public GenericRStarTreeRangeQuery(AbstractRStarTree<?, ?, ?> tree, SpatialDistanceQuery<O, D> distanceQuery) { - super(distanceQuery); - this.tree = tree; - this.distanceFunction = distanceQuery.getDistanceFunction(); - } - - /** - * Perform the actual query process. - * - * @param object Query object - * @param epsilon Query range - * @return Objects contained in query range. - */ - protected DistanceDBIDList<D> doRangeQuery(O object, D epsilon) { - final GenericDistanceDBIDList<D> result = new GenericDistanceDBIDList<>(); - final ComparableMinHeap<GenericDistanceSearchCandidate<D>> pq = new ComparableMinHeap<>(); - tree.statistics.countRangeQuery(); - - // push root - pq.add(new GenericDistanceSearchCandidate<>(distanceFunction.getDistanceFactory().nullDistance(), tree.getRootID())); - - // search in tree - while(!pq.isEmpty()) { - GenericDistanceSearchCandidate<D> pqNode = pq.poll(); - if(pqNode.mindist.compareTo(epsilon) > 0) { - break; - } - - AbstractRStarTreeNode<?, ?> node = tree.getNode(pqNode.nodeID); - final int numEntries = node.getNumEntries(); - - for(int i = 0; i < numEntries; i++) { - D distance = distanceFunction.minDist(node.getEntry(i), object); - tree.statistics.countDistanceCalculation(); - if(distance.compareTo(epsilon) <= 0) { - if(node.isLeaf()) { - LeafEntry entry = (LeafEntry) node.getEntry(i); - result.add(distance, entry.getDBID()); - } - else { - DirectoryEntry entry = (DirectoryEntry) node.getEntry(i); - pq.add(new GenericDistanceSearchCandidate<>(distance, entry.getEntryID())); - } - } - } - } - - // sort the result according to the distances - result.sort(); - return result; - } - - @Override - public DistanceDBIDList<D> getRangeForObject(O obj, D range) { - return doRangeQuery(obj, range); - } -}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/DoubleDistanceRStarTreeKNNQuery.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/RStarTreeKNNQuery.java index 472e4b57..f0e6e01e 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/DoubleDistanceRStarTreeKNNQuery.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/RStarTreeKNNQuery.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.query; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -34,16 +34,15 @@ import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; 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.ids.DBIDs; +import de.lmu.ifi.dbs.elki.database.ids.KNNHeap; +import de.lmu.ifi.dbs.elki.database.ids.KNNList; import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs; -import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNHeap; -import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNList; -import de.lmu.ifi.dbs.elki.database.ids.integer.DoubleDistanceIntegerDBIDKNNHeap; -import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; -import de.lmu.ifi.dbs.elki.database.query.knn.AbstractDistanceKNNQuery; -import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDoubleDistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; +import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery; +import de.lmu.ifi.dbs.elki.database.relation.Relation; +import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDistanceFunction; import de.lmu.ifi.dbs.elki.index.tree.DirectoryEntry; import de.lmu.ifi.dbs.elki.index.tree.LeafEntry; import de.lmu.ifi.dbs.elki.index.tree.query.DoubleDistanceSearchCandidate; @@ -68,41 +67,56 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Reference; * @author Erich Schubert * * @apiviz.uses AbstractRStarTree - * @apiviz.uses SpatialPrimitiveDoubleDistanceFunction + * @apiviz.uses SpatialPrimitiveDistanceFunction + * @apiviz.uses DoubleDistanceSearchCandidate */ -@Reference(authors = "G. R. Hjaltason, H. Samet", title = "Ranking in spatial databases", booktitle = "Advances in Spatial Databases - 4th Symposium, SSD'95", url = "http://dx.doi.org/10.1007/3-540-60159-7_6") -public class DoubleDistanceRStarTreeKNNQuery<O extends SpatialComparable> extends AbstractDistanceKNNQuery<O, DoubleDistance> { +@Reference(authors = "G. R. Hjaltason, H. Samet", // +title = "Ranking in spatial databases", // +booktitle = "Advances in Spatial Databases - 4th Symposium, SSD'95", // +url = "http://dx.doi.org/10.1007/3-540-60159-7_6") +public class RStarTreeKNNQuery<O extends SpatialComparable> implements KNNQuery<O> { /** * The index to use */ protected final AbstractRStarTree<?, ?, ?> tree; /** - * Spatial primitive distance function + * Spatial primitive distance function. */ - protected final SpatialPrimitiveDoubleDistanceFunction<? super O> distanceFunction; + protected final SpatialPrimitiveDistanceFunction<? super O> distanceFunction; + + /** + * Relation we query. + */ + protected Relation<? extends O> relation; /** * Constructor. * * @param tree Index to use - * @param distanceQuery Distance query to use + * @param relation Data relation to query * @param distanceFunction Distance function */ - public DoubleDistanceRStarTreeKNNQuery(AbstractRStarTree<?, ?, ?> tree, DistanceQuery<O, DoubleDistance> distanceQuery, SpatialPrimitiveDoubleDistanceFunction<? super O> distanceFunction) { - super(distanceQuery); + public RStarTreeKNNQuery(AbstractRStarTree<?, ?, ?> tree, Relation<? extends O> relation, SpatialPrimitiveDistanceFunction<? super O> distanceFunction) { + super(); + this.relation = relation; this.tree = tree; this.distanceFunction = distanceFunction; } @Override - public DoubleDistanceKNNList getKNNForObject(O obj, int k) { + public KNNList getKNNForDBID(DBIDRef id, int k) { + return getKNNForObject(relation.get(id), k); + } + + @Override + public KNNList getKNNForObject(O obj, int k) { if(k < 1) { throw new IllegalArgumentException("At least one neighbor has to be requested!"); } tree.statistics.countKNNQuery(); - final DoubleDistanceKNNHeap knnList = new DoubleDistanceIntegerDBIDKNNHeap(k); + final KNNHeap knnList = DBIDUtil.newHeap(k); final ComparableMinHeap<DoubleDistanceSearchCandidate> pq = new ComparableMinHeap<>(Math.min(knnList.getK() << 1, 21)); // expand root @@ -120,13 +134,13 @@ public class DoubleDistanceRStarTreeKNNQuery<O extends SpatialComparable> extend return knnList.toKNNList(); } - private double expandNode(O object, DoubleDistanceKNNHeap knnList, final ComparableMinHeap<DoubleDistanceSearchCandidate> pq, double maxDist, final int nodeID) { + private double expandNode(O object, KNNHeap knnList, final ComparableMinHeap<DoubleDistanceSearchCandidate> pq, double maxDist, final int nodeID) { AbstractRStarTreeNode<?, ?> node = tree.getNode(nodeID); // data node if(node.isLeaf()) { for(int i = 0; i < node.getNumEntries(); i++) { SpatialPointLeafEntry entry = (SpatialPointLeafEntry) node.getEntry(i); - double distance = distanceFunction.doubleMinDist(entry, object); + double distance = distanceFunction.minDist(entry, object); tree.statistics.countDistanceCalculation(); if(distance <= maxDist) { maxDist = knnList.insert(distance, entry.getDBID()); @@ -137,7 +151,7 @@ public class DoubleDistanceRStarTreeKNNQuery<O extends SpatialComparable> extend else { for(int i = 0; i < node.getNumEntries(); i++) { SpatialDirectoryEntry entry = (SpatialDirectoryEntry) node.getEntry(i); - double distance = distanceFunction.doubleMinDist(entry, object); + double distance = distanceFunction.minDist(entry, object); tree.statistics.countDistanceCalculation(); // Greedy expand, bypassing the queue if(distance <= 0) { @@ -159,19 +173,19 @@ public class DoubleDistanceRStarTreeKNNQuery<O extends SpatialComparable> extend * @param node the node for which the query should be performed * @param knnLists a map containing the knn lists for each query objects */ - protected void batchNN(AbstractRStarTreeNode<?, ?> node, Map<DBID, DoubleDistanceKNNHeap> knnLists) { + protected void batchNN(AbstractRStarTreeNode<?, ?> node, Map<DBID, KNNHeap> knnLists) { if(node.isLeaf()) { for(int i = 0; i < node.getNumEntries(); i++) { SpatialEntry p = node.getEntry(i); - for(Entry<DBID, DoubleDistanceKNNHeap> ent : knnLists.entrySet()) { + for(Entry<DBID, KNNHeap> ent : knnLists.entrySet()) { final DBID q = ent.getKey(); - final DoubleDistanceKNNHeap knns_q = ent.getValue(); - double knn_q_maxDist = knns_q.doubleKNNDistance(); + final KNNHeap knns_q = ent.getValue(); + double knn_q_maxDist = knns_q.getKNNDistance(); DBID pid = ((LeafEntry) p).getDBID(); // FIXME: objects are NOT accessible by DBID in a plain R-tree // context! - double dist_pq = distanceFunction.doubleDistance(relation.get(pid), relation.get(q)); + double dist_pq = distanceFunction.distance(relation.get(pid), relation.get(q)); tree.statistics.countDistanceCalculation(); if(dist_pq <= knn_q_maxDist) { knns_q.insert(dist_pq, pid); @@ -187,9 +201,9 @@ public class DoubleDistanceRStarTreeKNNQuery<O extends SpatialComparable> extend List<DoubleDistanceEntry> entries = getSortedEntries(node, ids); for(DoubleDistanceEntry distEntry : entries) { double minDist = distEntry.distance; - for(Entry<DBID, DoubleDistanceKNNHeap> ent : knnLists.entrySet()) { - final DoubleDistanceKNNHeap knns_q = ent.getValue(); - double knn_q_maxDist = knns_q.doubleKNNDistance(); + for(Entry<DBID, KNNHeap> ent : knnLists.entrySet()) { + final KNNHeap knns_q = ent.getValue(); + double knn_q_maxDist = knns_q.getKNNDistance(); if(minDist <= knn_q_maxDist) { SpatialEntry entry = distEntry.entry; @@ -217,7 +231,7 @@ public class DoubleDistanceRStarTreeKNNQuery<O extends SpatialComparable> extend SpatialEntry entry = node.getEntry(i); double minMinDist = Double.MAX_VALUE; for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { - double minDist = distanceFunction.doubleMinDist(entry, relation.get(iter)); + double minDist = distanceFunction.minDist(entry, relation.get(iter)); tree.statistics.countDistanceCalculation(); minMinDist = Math.min(minDist, minMinDist); } @@ -235,7 +249,7 @@ public class DoubleDistanceRStarTreeKNNQuery<O extends SpatialComparable> extend * * @apiviz.hidden */ - class DoubleDistanceEntry implements Comparable<DoubleDistanceEntry> { + static class DoubleDistanceEntry implements Comparable<DoubleDistanceEntry> { /** * Referenced entry */ @@ -264,22 +278,22 @@ public class DoubleDistanceRStarTreeKNNQuery<O extends SpatialComparable> extend } @Override - public List<DoubleDistanceKNNList> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) { + public List<KNNList> getKNNForBulkDBIDs(ArrayDBIDs ids, int k) { if(k < 1) { throw new IllegalArgumentException("At least one enumeration has to be requested!"); } // While this works, it seems to be slow at least for large sets! // TODO: use a DataStore instead of a map. - final Map<DBID, DoubleDistanceKNNHeap> knnLists = new HashMap<>(ids.size()); + final Map<DBID, KNNHeap> knnLists = new HashMap<>(ids.size()); for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { DBID id = DBIDUtil.deref(iter); - knnLists.put(id, new DoubleDistanceIntegerDBIDKNNHeap(k)); + knnLists.put(id, DBIDUtil.newHeap(k)); } batchNN(tree.getRoot(), knnLists); - List<DoubleDistanceKNNList> result = new ArrayList<>(); + List<KNNList> result = new ArrayList<>(); for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { DBID id = DBIDUtil.deref(iter); tree.statistics.countKNNQuery(); diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/DoubleDistanceRStarTreeRangeQuery.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/RStarTreeRangeQuery.java index 4fe2719e..aad67fed 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/DoubleDistanceRStarTreeRangeQuery.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/RStarTreeRangeQuery.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.query; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -26,13 +26,13 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.query; import java.util.Arrays; import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; -import de.lmu.ifi.dbs.elki.database.ids.distance.DistanceDBIDList; -import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDList; -import de.lmu.ifi.dbs.elki.database.ids.integer.DoubleDistanceIntegerDBIDList; -import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; -import de.lmu.ifi.dbs.elki.database.query.range.AbstractDistanceRangeQuery; -import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDoubleDistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; +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.DoubleDBIDList; +import de.lmu.ifi.dbs.elki.database.ids.ModifiableDoubleDBIDList; +import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery; +import de.lmu.ifi.dbs.elki.database.relation.Relation; +import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDistanceFunction; import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialDirectoryEntry; import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialPointLeafEntry; import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRStarTree; @@ -53,10 +53,10 @@ import de.lmu.ifi.dbs.elki.utilities.documentation.Reference; * @author Erich Schubert * * @apiviz.uses AbstractRStarTree - * @apiviz.uses SpatialPrimitiveDoubleDistanceFunction + * @apiviz.uses SpatialPrimitiveDistanceFunction */ @Reference(authors = "J. Kuan, P. Lewis", title = "Fast k nearest neighbour search for R-tree family", booktitle = "Proc. Int. Conf Information, Communications and Signal Processing, ICICS 1997", url = "http://dx.doi.org/10.1109/ICICS.1997.652114") -public class DoubleDistanceRStarTreeRangeQuery<O extends SpatialComparable> extends AbstractDistanceRangeQuery<O, DoubleDistance> { +public class RStarTreeRangeQuery<O extends SpatialComparable> implements RangeQuery<O> { /** * The index to use */ @@ -65,31 +65,36 @@ public class DoubleDistanceRStarTreeRangeQuery<O extends SpatialComparable> exte /** * Spatial primitive distance function */ - protected final SpatialPrimitiveDoubleDistanceFunction<? super O> distanceFunction; + protected final SpatialPrimitiveDistanceFunction<? super O> distanceFunction; + + /** + * Relation we query. + */ + protected Relation<? extends O> relation; /** * Constructor. * * @param tree Index to use - * @param distanceQuery Distance query to use + * @param relation Data relation to query * @param distanceFunction Distance function */ - public DoubleDistanceRStarTreeRangeQuery(AbstractRStarTree<?, ?, ?> tree, DistanceQuery<O, DoubleDistance> distanceQuery, SpatialPrimitiveDoubleDistanceFunction<? super O> distanceFunction) { - super(distanceQuery); + public RStarTreeRangeQuery(AbstractRStarTree<?, ?, ?> tree, Relation<? extends O> relation, SpatialPrimitiveDistanceFunction<? super O> distanceFunction) { + super(); + this.relation = relation; this.tree = tree; this.distanceFunction = distanceFunction; } - /** - * Perform the actual query process. - * - * @param object Query object - * @param epsilon Query range - * @return Objects contained in query range. - */ - protected DoubleDistanceDBIDList doRangeQuery(O object, double epsilon) { + @Override + public DoubleDBIDList getRangeForDBID(DBIDRef id, double range) { + return getRangeForObject(relation.get(id), range); + } + + @Override + public DoubleDBIDList getRangeForObject(O obj, double range) { tree.statistics.countRangeQuery(); - final DoubleDistanceIntegerDBIDList result = new DoubleDistanceIntegerDBIDList(); + ModifiableDoubleDBIDList result = DBIDUtil.newDistanceDBIDList(); // Processing queue. int[] pq = new int[101]; @@ -105,9 +110,9 @@ public class DoubleDistanceRStarTreeRangeQuery<O extends SpatialComparable> exte if(node.isLeaf()) { for(int i = 0; i < numEntries; i++) { SpatialPointLeafEntry entry = (SpatialPointLeafEntry) node.getEntry(i); - double distance = distanceFunction.doubleMinDist(object, entry); + double distance = distanceFunction.minDist(obj, entry); tree.statistics.countDistanceCalculation(); - if(distance <= epsilon) { + if(distance <= range) { result.add(distance, entry.getDBID()); } } @@ -115,8 +120,8 @@ public class DoubleDistanceRStarTreeRangeQuery<O extends SpatialComparable> exte else { for(int i = 0; i < numEntries; i++) { SpatialDirectoryEntry entry = (SpatialDirectoryEntry) node.getEntry(i); - double distance = distanceFunction.doubleMinDist(object, entry); - if(distance <= epsilon) { + double distance = distanceFunction.minDist(obj, entry); + if(distance <= range) { if(ps == pq.length) { pq = Arrays.copyOf(pq, pq.length + (pq.length >>> 1)); } @@ -130,9 +135,4 @@ public class DoubleDistanceRStarTreeRangeQuery<O extends SpatialComparable> exte result.sort(); return result; } - - @Override - public DistanceDBIDList<DoubleDistance> getRangeForObject(O obj, DoubleDistance range) { - return doRangeQuery(obj, range.doubleValue()); - } }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/RStarTreeUtil.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/RStarTreeUtil.java index 46c814ee..d76cb504 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/RStarTreeUtil.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/RStarTreeUtil.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.query; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,15 +23,14 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.query; along with this program. If not, see <http://www.gnu.org/licenses/>. */ +import de.lmu.ifi.dbs.elki.data.NumberVector; import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; -import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; import de.lmu.ifi.dbs.elki.database.query.distance.SpatialDistanceQuery; import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery; import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery; +import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDoubleDistanceFunction; -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; -import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance; +import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction; import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRStarTree; /** @@ -42,10 +41,8 @@ import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRStarTree; * @apiviz.landmark * * @apiviz.uses AbstractRStarTree - * @apiviz.uses DoubleDistanceRStarTreeKNNQuery - * @apiviz.uses DoubleDistanceRStarTreeRangeQuery - * @apiviz.uses GenericRStarTreeKNNQuery - * @apiviz.uses GenericRStarTreeRangeQuery + * @apiviz.uses EuclideanRStarTreeKNNQuery + * @apiviz.uses EuclideanRStarTreeRangeQuery * @apiviz.has RangeQuery * @apiviz.has KNNQuery */ @@ -55,24 +52,19 @@ public final class RStarTreeUtil { * possible. * * @param <O> Object type - * @param <D> Distance type * @param tree Tree to query * @param distanceQuery distance query * @param hints Optimizer hints * @return Query object */ @SuppressWarnings({ "cast", "unchecked" }) - public static <O extends SpatialComparable, D extends Distance<D>> RangeQuery<O, D> getRangeQuery(AbstractRStarTree<?, ?, ?> tree, SpatialDistanceQuery<O, D> distanceQuery, Object... hints) { + public static <O extends SpatialComparable> RangeQuery<O> getRangeQuery(AbstractRStarTree<?, ?, ?> tree, SpatialDistanceQuery<O> distanceQuery, Object... hints) { // Can we support this distance function - spatial distances only! - SpatialPrimitiveDistanceFunction<? super O, D> df = distanceQuery.getDistanceFunction(); - // Can we use an optimized query? - if(df instanceof SpatialPrimitiveDoubleDistanceFunction) { - DistanceQuery<O, DoubleDistance> dqc = (DistanceQuery<O, DoubleDistance>) DistanceQuery.class.cast(distanceQuery); - SpatialPrimitiveDoubleDistanceFunction<? super O> dfc = (SpatialPrimitiveDoubleDistanceFunction<? super O>) SpatialPrimitiveDoubleDistanceFunction.class.cast(df); - RangeQuery<O, ?> q = new DoubleDistanceRStarTreeRangeQuery<>(tree, dqc, dfc); - return (RangeQuery<O, D>) q; + SpatialPrimitiveDistanceFunction<? super O> df = distanceQuery.getDistanceFunction(); + if(EuclideanDistanceFunction.STATIC.equals(df)) { + return (RangeQuery<O>) new EuclideanRStarTreeRangeQuery<>(tree, (Relation<NumberVector>) distanceQuery.getRelation()); } - return new GenericRStarTreeRangeQuery<>(tree, distanceQuery); + return new RStarTreeRangeQuery<>(tree, distanceQuery.getRelation(), df); } /** @@ -80,23 +72,18 @@ public final class RStarTreeUtil { * possible. * * @param <O> Object type - * @param <D> Distance type * @param tree Tree to query * @param distanceQuery distance query * @param hints Optimizer hints * @return Query object */ @SuppressWarnings({ "cast", "unchecked" }) - public static <O extends SpatialComparable, D extends Distance<D>> KNNQuery<O, D> getKNNQuery(AbstractRStarTree<?, ?, ?> tree, SpatialDistanceQuery<O, D> distanceQuery, Object... hints) { + public static <O extends SpatialComparable> KNNQuery<O> getKNNQuery(AbstractRStarTree<?, ?, ?> tree, SpatialDistanceQuery<O> distanceQuery, Object... hints) { // Can we support this distance function - spatial distances only! - SpatialPrimitiveDistanceFunction<? super O, D> df = distanceQuery.getDistanceFunction(); - // Can we use an optimized query? - if(df instanceof SpatialPrimitiveDoubleDistanceFunction) { - DistanceQuery<O, DoubleDistance> dqc = (DistanceQuery<O, DoubleDistance>) DistanceQuery.class.cast(distanceQuery); - SpatialPrimitiveDoubleDistanceFunction<? super O> dfc = (SpatialPrimitiveDoubleDistanceFunction<? super O>) SpatialPrimitiveDoubleDistanceFunction.class.cast(df); - KNNQuery<O, ?> q = new DoubleDistanceRStarTreeKNNQuery<>(tree, dqc, dfc); - return (KNNQuery<O, D>) q; + SpatialPrimitiveDistanceFunction<? super O> df = distanceQuery.getDistanceFunction(); + if(EuclideanDistanceFunction.STATIC.equals(df)) { + return (KNNQuery<O>) new EuclideanRStarTreeKNNQuery<>(tree, (Relation<NumberVector>) distanceQuery.getRelation()); } - return new GenericRStarTreeKNNQuery<>(tree, distanceQuery); + return new RStarTreeKNNQuery<>(tree, distanceQuery.getRelation(), df); } }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/package-info.java index 69bcd3d0..35dd34e7 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/query/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2013 +Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rdknn/RdKNNDirectoryEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rdknn/RdKNNDirectoryEntry.java new file mode 100644 index 00000000..b824bc77 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rdknn/RdKNNDirectoryEntry.java @@ -0,0 +1,129 @@ +package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rdknn; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2014 + 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.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; + +import de.lmu.ifi.dbs.elki.data.ModifiableHyperBoundingBox; +import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialDirectoryEntry; + +/** + * Represents an entry in a directory node of an RdKNN-Tree. Additionally to a + * SpatialDirectoryEntry a RdKNNDirectoryEntry holds the knn distance of the + * underlying RdKNN-Tree node. + * + * @author Elke Achtert + * @param Distance type + */ +public class RdKNNDirectoryEntry extends SpatialDirectoryEntry implements RdKNNEntry { + private static final long serialVersionUID = 2; + + /** + * The aggregated knn distance of this entry. + */ + private double knnDistance; + + /** + * Empty constructor for serialization purposes. + */ + public RdKNNDirectoryEntry() { + // empty constructor + } + + /** + * Constructs a new RDkNNDirectoryEntry object with the given parameters. + * + * @param id the unique id of the underlying node + * @param mbr the minimum bounding rectangle of the underlying node + * @param knnDistance the aggregated knn distance of this entry + */ + public RdKNNDirectoryEntry(int id, ModifiableHyperBoundingBox mbr, double knnDistance) { + super(id, mbr); + this.knnDistance = knnDistance; + } + + @Override + public double getKnnDistance() { + return knnDistance; + } + + @Override + public void setKnnDistance(double knnDistance) { + this.knnDistance = knnDistance; + } + + /** + * Calls the super method and writes the knn distance of this entry to the + * specified stream. + * + * @param out the stream to write the object to + * @throws java.io.IOException Includes any I/O exceptions that may occur + */ + @Override + public void writeExternal(ObjectOutput out) throws IOException { + super.writeExternal(out); + out.writeDouble(knnDistance); + } + + /** + * Calls the super method and reads the knn distance of this entry from the + * specified input stream. + * + * @param in the stream to read data from in order to restore the object + * @throws java.io.IOException if I/O errors occur + * @throws ClassNotFoundException If the class for an object being restored + * cannot be found. + */ + @Override + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + super.readExternal(in); + this.knnDistance = in.readDouble(); + } + + /** + * Indicates whether some other object is "equal to" this one. + * + * @param o the object to be tested + * @return true, if the super method returns true and o is an + * RDkNNDirectoryEntry and has the same knnDistance as this entry. + */ + @Override + public boolean equals(Object o) { + if(this == o) { + return true; + } + if(o == null || getClass() != o.getClass()) { + return false; + } + if(!super.equals(o)) { + return false; + } + + final RdKNNDirectoryEntry that = (RdKNNDirectoryEntry) o; + + return knnDistance == that.knnDistance; + } +} diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rdknn/RdKNNEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rdknn/RdKNNEntry.java new file mode 100644 index 00000000..f96a6419 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rdknn/RdKNNEntry.java @@ -0,0 +1,49 @@ +package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rdknn; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2014 + 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.index.tree.spatial.SpatialEntry; + +/** + * Defines the requirements for an entry in an RdKNN-Tree node. Additionally to + * an entry in an R*-Tree an RDkNNEntry holds the knn distance of the underlying + * data object or RdKNN-Tree node. + * + * @author Elke Achtert + */ +interface RdKNNEntry extends SpatialEntry { + /** + * Returns the knn distance of this entry. + * + * @return the knn distance of this entry + */ + public double getKnnDistance(); + + /** + * Sets the knn distance of this entry. + * + * @param knnDistance the knn distance to be set + */ + public void setKnnDistance(double knnDistance); +} diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rdknn/RdKNNLeafEntry.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rdknn/RdKNNLeafEntry.java new file mode 100644 index 00000000..6d665eb9 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rdknn/RdKNNLeafEntry.java @@ -0,0 +1,129 @@ +package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rdknn; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2014 + 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.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectOutput; + +import de.lmu.ifi.dbs.elki.data.NumberVector; +import de.lmu.ifi.dbs.elki.database.ids.DBID; +import de.lmu.ifi.dbs.elki.index.tree.spatial.SpatialPointLeafEntry; + +/** + * Represents an entry in a leaf node of an RdKNN-Tree. Additionally to a + * SpatialLeafEntry a RdKNNLeafEntry holds the knn distance of the underlying + * data object. + * + * @author Elke Achtert + */ +public class RdKNNLeafEntry extends SpatialPointLeafEntry implements RdKNNEntry { + private static final long serialVersionUID = 2; + + /** + * The knn distance of the underlying data object. + */ + private double knnDistance; + + /** + * Empty constructor for serialization purposes. + */ + public RdKNNLeafEntry() { + super(); + } + + /** + * Constructs a new RDkNNLeafEntry object with the given parameters. + * + * @param id the unique id of the underlying data object + * @param vector the underlying data object + * @param knnDistance the knn distance of the underlying data object + */ + public RdKNNLeafEntry(DBID id, NumberVector vector, double knnDistance) { + super(id, vector); + this.knnDistance = knnDistance; + } + + @Override + public double getKnnDistance() { + return knnDistance; + } + + @Override + public void setKnnDistance(double knnDistance) { + this.knnDistance = knnDistance; + } + + /** + * Calls the super method and writes the knn distance of this entry to the + * specified stream. + * + * @param out the stream to write the object to + * @throws java.io.IOException Includes any I/O exceptions that may occur + */ + @Override + public void writeExternal(ObjectOutput out) throws IOException { + super.writeExternal(out); + out.writeDouble(knnDistance); + } + + /** + * Calls the super method and reads the knn distance of this entry from the + * specified input stream. + * + * @param in the stream to read data from in order to restore the object + * @throws java.io.IOException if I/O errors occur + * @throws ClassNotFoundException If the class for an object being restored + * cannot be found. + */ + @Override + public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + super.readExternal(in); + this.knnDistance = in.readDouble(); + } + + /** + * Indicates whether some other object is "equal to" this one. + * + * @param o the object to be tested + * @return true, if the super method returns true and o is an RDkNNLeafEntry + * and has the same knnDistance as this entry. + */ + @Override + public boolean equals(Object o) { + if(this == o) { + return true; + } + if(o == null || getClass() != o.getClass()) { + return false; + } + if(!super.equals(o)) { + return false; + } + + final RdKNNLeafEntry that = (RdKNNLeafEntry) o; + + return knnDistance == that.knnDistance; + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rdknn/RdKNNNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rdknn/RdKNNNode.java new file mode 100644 index 00000000..89e231b4 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rdknn/RdKNNNode.java @@ -0,0 +1,96 @@ +package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rdknn; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2014 + 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.index.tree.spatial.rstarvariants.AbstractRStarTreeNode; + +/** + * Represents a node in a RDkNN-Tree. + * + * @author Elke Achtert + * + * @apiviz.has RdKNNEntry oneway - - contains + */ +public class RdKNNNode extends AbstractRStarTreeNode<RdKNNNode, RdKNNEntry> { + private static final long serialVersionUID = 1; + + /** + * Empty constructor for Externalizable interface. + */ + public RdKNNNode() { + // empty constructor + } + + /** + * Creates a new RdKNNNode object. + * + * @param capacity the capacity (maximum number of entries plus 1 for + * overflow) of this node + * @param isLeaf indicates whether this node is a leaf node + */ + public RdKNNNode(int capacity, boolean isLeaf) { + super(capacity, isLeaf, RdKNNEntry.class); + } + + /** + * Computes and returns the aggregated knn distance of this node + * + * @return the aggregated knn distance of this node + */ + protected double kNNDistance() { + double result = getEntry(0).getKnnDistance(); + for(int i = 1; i < getNumEntries(); i++) { + double knnDistance = getEntry(i).getKnnDistance(); + result = (result < knnDistance) ? knnDistance : result; + } + return result; + } + + @Override + public boolean adjustEntry(RdKNNEntry entry) { + boolean changed = super.adjustEntry(entry); + entry.setKnnDistance(kNNDistance()); + return changed; + } + + /** + * Tests, if the parameters of the entry representing this node, are correctly + * set. Subclasses may need to overwrite this method. + * + * @param parent the parent holding the entry representing this node + * @param index the index of the entry in the parents child array + */ + @Override + protected void integrityCheckParameters(RdKNNNode parent, int index) { + super.integrityCheckParameters(parent, index); + // test if knn distance is correctly set + RdKNNEntry entry = parent.getEntry(index); + double knnDistance = kNNDistance(); + if(entry.getKnnDistance() != knnDistance) { + double soll = knnDistance; + double ist = entry.getKnnDistance(); + throw new RuntimeException("Wrong knnDistance in node " + parent.getPageID() + " at index " + index + " (child " + entry + ")" + "\nsoll: " + soll + ",\n ist: " + ist); + } + } +}
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rdknn/RdKNNTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rdknn/RdKNNTree.java new file mode 100644 index 00000000..374e9592 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rdknn/RdKNNTree.java @@ -0,0 +1,672 @@ +package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rdknn; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2014 + Ludwig-Maximilians-Universität München + Lehr- und Forschungseinheit für Datenbanksysteme + ELKI Development Team + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import de.lmu.ifi.dbs.elki.data.NumberVector; +import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; +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.ids.DBIDs; +import de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDList; +import de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDListIter; +import de.lmu.ifi.dbs.elki.database.ids.KNNHeap; +import de.lmu.ifi.dbs.elki.database.ids.KNNList; +import de.lmu.ifi.dbs.elki.database.ids.ModifiableDBIDs; +import de.lmu.ifi.dbs.elki.database.ids.ModifiableDoubleDBIDList; +import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery; +import de.lmu.ifi.dbs.elki.database.query.distance.SpatialDistanceQuery; +import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery; +import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery; +import de.lmu.ifi.dbs.elki.database.query.rknn.RKNNQuery; +import de.lmu.ifi.dbs.elki.database.relation.Relation; +import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDistanceFunction; +import de.lmu.ifi.dbs.elki.index.DynamicIndex; +import de.lmu.ifi.dbs.elki.index.KNNIndex; +import de.lmu.ifi.dbs.elki.index.RKNNIndex; +import de.lmu.ifi.dbs.elki.index.RangeIndex; +import de.lmu.ifi.dbs.elki.index.tree.IndexTreePath; +import de.lmu.ifi.dbs.elki.index.tree.LeafEntry; +import de.lmu.ifi.dbs.elki.index.tree.TreeIndexHeader; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRStarTreeNode; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.NonFlatRStarTree; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.query.RStarTreeUtil; +import de.lmu.ifi.dbs.elki.logging.Logging; +import de.lmu.ifi.dbs.elki.persistent.PageFile; +import de.lmu.ifi.dbs.elki.utilities.io.ByteArrayUtil; +import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleObjPair; + +/** + * RDkNNTree is a spatial index structure based on the concepts of the R*-Tree + * supporting efficient processing of reverse k nearest neighbor queries. The + * k-nn distance is stored in each entry of a node. + * <p/> + * TODO: noch nicht fertig!!! + * + * @author Elke Achtert + * + * @apiviz.has RdKNNNode + * @apiviz.has RdKNNTreeHeader + * + * @param <O> Object type + */ +// FIXME: currently does not yet return RKNNQuery objects! +public class RdKNNTree<O extends NumberVector> extends NonFlatRStarTree<RdKNNNode, RdKNNEntry, RdkNNSettings<O>> implements RangeIndex<O>, KNNIndex<O>, RKNNIndex<O>, DynamicIndex { + /** + * The logger for this class. + */ + private static final Logging LOG = Logging.getLogger(RdKNNTree.class); + + /** + * The distance function. + */ + private SpatialDistanceQuery<O> distanceQuery; + + /** + * Internal knn query object, for updating the rKNN. + */ + protected KNNQuery<O> knnQuery; + + /** + * The relation we query. + */ + private Relation<O> relation; + + /** + * Constructor. + * + * @param relation Relation to index + * @param pagefile Data storage + * @param settings Tree settings + */ + public RdKNNTree(Relation<O> relation, PageFile<RdKNNNode> pagefile, RdkNNSettings<O> settings) { + super(pagefile, settings); + this.relation = relation; + this.distanceQuery = settings.distanceFunction.instantiate(relation); + this.knnQuery = relation.getDatabase().getKNNQuery(distanceQuery); + } + + /** + * Performs necessary operations before inserting the specified entry. + * + * @param entry the entry to be inserted + */ + @Override + protected void preInsert(RdKNNEntry entry) { + KNNHeap knns_o = DBIDUtil.newHeap(settings.k_max); + preInsert(entry, getRootEntry(), knns_o); + } + + /** + * Performs necessary operations after deleting the specified object. + */ + @Override + protected void postDelete(RdKNNEntry entry) { + // reverse knn of o + ModifiableDoubleDBIDList rnns = DBIDUtil.newDistanceDBIDList(); + doReverseKNN(getRoot(), ((RdKNNLeafEntry) entry).getDBID(), rnns); + + // knn of rnn + ArrayModifiableDBIDs ids = DBIDUtil.newArray(rnns); + ids.sort(); + List<? extends KNNList> knnLists = knnQuery.getKNNForBulkDBIDs(ids, settings.k_max); + + // adjust knn distances + adjustKNNDistance(getRootEntry(), ids, knnLists); + } + + /** + * Performs a bulk load on this RTree with the specified data. Is called by + * the constructor and should be overwritten by subclasses if necessary. + */ + @Override + protected void bulkLoad(List<RdKNNEntry> entries) { + super.bulkLoad(entries); + + // adjust all knn distances + ArrayModifiableDBIDs ids = DBIDUtil.newArray(entries.size()); + for(RdKNNEntry entry : entries) { + DBID id = ((RdKNNLeafEntry) entry).getDBID(); + ids.add(id); + } + ids.sort(); + List<? extends KNNList> knnLists = knnQuery.getKNNForBulkDBIDs(ids, settings.k_max); + adjustKNNDistance(getRootEntry(), ids, knnLists); + + // test + doExtraIntegrityChecks(); + } + + public DoubleDBIDList reverseKNNQuery(DBID oid, int k, SpatialPrimitiveDistanceFunction<? super O> distanceFunction, KNNQuery<O> knnQuery) { + checkDistanceFunction(distanceFunction); + if(k > settings.k_max) { + throw new IllegalArgumentException("Parameter k is not supported, k > k_max: " + k + " > " + settings.k_max); + } + + // get candidates + ModifiableDoubleDBIDList candidates = DBIDUtil.newDistanceDBIDList(); + doReverseKNN(getRoot(), oid, candidates); + + if(k == settings.k_max) { + candidates.sort(); + return candidates; + } + + // refinement of candidates, if k < k_max + ArrayModifiableDBIDs candidateIDs = DBIDUtil.newArray(candidates); + candidateIDs.sort(); + List<? extends KNNList> knnLists = knnQuery.getKNNForBulkDBIDs(candidateIDs, k); + + ModifiableDoubleDBIDList result = DBIDUtil.newDistanceDBIDList(); + int i = 0; + for(DBIDIter iter = candidateIDs.iter(); iter.valid(); iter.advance(), i++) { + for(DoubleDBIDListIter qr = knnLists.get(i).iter(); qr.valid(); qr.advance()) { + if(DBIDUtil.equal(oid, qr)) { + result.add(qr.doubleValue(), iter); + break; + } + } + } + + result.sort(); + return result; + } + + public List<ModifiableDoubleDBIDList> bulkReverseKNNQueryForID(DBIDs ids, int k, SpatialPrimitiveDistanceFunction<? super O> distanceFunction, KNNQuery<O> knnQuery) { + checkDistanceFunction(distanceFunction); + if(k > settings.k_max) { + throw new IllegalArgumentException("Parameter k is not supported, k > k_max: " + k + " > " + settings.k_max); + } + + // get candidates + Map<DBID, ModifiableDoubleDBIDList> candidateMap = new HashMap<>(); + for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { + DBID id = DBIDUtil.deref(iter); + candidateMap.put(id, DBIDUtil.newDistanceDBIDList()); + } + doBulkReverseKNN(getRoot(), ids, candidateMap); + + if(k == settings.k_max) { + List<ModifiableDoubleDBIDList> resultList = new ArrayList<>(); + for(ModifiableDoubleDBIDList candidates : candidateMap.values()) { + candidates.sort(); + resultList.add(candidates); + } + return resultList; + } + + // refinement of candidates, if k < k_max + // perform a knn query for the candidates + ArrayModifiableDBIDs candidateIDs = DBIDUtil.newArray(); + for(ModifiableDoubleDBIDList candidates : candidateMap.values()) { + candidateIDs.addDBIDs(candidates); + } + candidateIDs.sort(); + List<? extends KNNList> knnLists = knnQuery.getKNNForBulkDBIDs(candidateIDs, k); + + // and add candidate c to the result if o is a knn of c + List<ModifiableDoubleDBIDList> resultList = new ArrayList<>(); + for(DBID id : candidateMap.keySet()) { + ModifiableDoubleDBIDList candidates = candidateMap.get(id); + ModifiableDoubleDBIDList result = DBIDUtil.newDistanceDBIDList(); + for(DoubleDBIDListIter candidate = candidates.iter(); candidate.valid(); candidate.advance()) { + int pos = candidateIDs.binarySearch(candidate); + assert (pos >= 0); + for(DoubleDBIDListIter qr = knnLists.get(pos).iter(); qr.valid(); qr.advance()) { + if(DBIDUtil.equal(id, qr)) { + result.add(qr.doubleValue(), candidate); + break; + } + } + } + resultList.add(result); + } + return resultList; + } + + @Override + protected TreeIndexHeader createHeader() { + return new RdKNNTreeHeader(getPageSize(), dirCapacity, leafCapacity, dirMinimum, leafCapacity, settings.k_max); + } + + @Override + protected void initializeCapacities(RdKNNEntry exampleLeaf) { + int dimensionality = exampleLeaf.getDimensionality(); + int distanceSize = ByteArrayUtil.SIZE_DOUBLE; + + // overhead = index(4), numEntries(4), parentID(4), id(4), isLeaf(0.125) + double overhead = 16.125; + if(getPageSize() - overhead < 0) { + throw new RuntimeException("Node size of " + getPageSize() + " Bytes is chosen too small!"); + } + + // dirCapacity = (pageSize - overhead) / (childID + childMBR + knnDistance) + // + 1 + dirCapacity = (int) ((getPageSize() - overhead) / (4 + 16 * dimensionality + distanceSize)) + 1; + + if(dirCapacity <= 1) { + throw new RuntimeException("Node size of " + getPageSize() + " Bytes is chosen too small!"); + } + + if(dirCapacity < 10) { + LOG.warning("Page size is choosen too small! Maximum number of entries " + "in a directory node = " + (dirCapacity - 1)); + } + + // minimum entries per directory node + dirMinimum = (int) Math.round((dirCapacity - 1) * 0.5); + if(dirMinimum < 2) { + dirMinimum = 2; + } + + // leafCapacity = (pageSize - overhead) / (childID + childValues + + // knnDistance) + 1 + leafCapacity = (int) ((getPageSize() - overhead) / (4 + 8 * dimensionality + distanceSize)) + 1; + + if(leafCapacity <= 1) { + throw new RuntimeException("Node size of " + getPageSize() + " Bytes is chosen too small!"); + } + + if(leafCapacity < 10) { + LOG.warning("Page size is choosen too small! Maximum number of entries " + "in a leaf node = " + (leafCapacity - 1)); + } + + // minimum entries per leaf node + leafMinimum = (int) Math.round((leafCapacity - 1) * 0.5); + if(leafMinimum < 2) { + leafMinimum = 2; + } + + if(LOG.isVerbose()) { + LOG.verbose("Directory Capacity: " + dirCapacity + "\nLeaf Capacity: " + leafCapacity); + } + } + + /** + * Sorts the entries of the specified node according to their minimum distance + * to the specified object. + * + * @param node the node + * @param q the query object + * @param distanceFunction the distance function for computing the distances + * @return a list of the sorted entries + */ + // TODO: move somewhere else? + protected List<DoubleObjPair<RdKNNEntry>> getSortedEntries(AbstractRStarTreeNode<?, ?> node, SpatialComparable q, SpatialPrimitiveDistanceFunction<?> distanceFunction) { + List<DoubleObjPair<RdKNNEntry>> result = new ArrayList<>(); + + for(int i = 0; i < node.getNumEntries(); i++) { + RdKNNEntry entry = (RdKNNEntry) node.getEntry(i); + double minDist = distanceFunction.minDist(entry, q); + result.add(new DoubleObjPair<>(minDist, entry)); + } + + Collections.sort(result); + return result; + } + + /** + * Adapts the knn distances before insertion of entry q. + * + * @param q the entry to be inserted + * @param nodeEntry the entry representing the root of the current subtree + * @param knns_q the knns of q + */ + private void preInsert(RdKNNEntry q, RdKNNEntry nodeEntry, KNNHeap knns_q) { + double knnDist_q = knns_q.getKNNDistance(); + RdKNNNode node = getNode(nodeEntry); + double knnDist_node = 0.; + + // leaf node + if(node.isLeaf()) { + for(int i = 0; i < node.getNumEntries(); i++) { + RdKNNLeafEntry p = (RdKNNLeafEntry) node.getEntry(i); + double dist_pq = distanceQuery.distance(p.getDBID(), ((LeafEntry) q).getDBID()); + + // p is nearer to q than the farthest kNN-candidate of q + // ==> p becomes a knn-candidate + if(dist_pq <= knnDist_q) { + knns_q.insert(dist_pq, p.getDBID()); + if(knns_q.size() >= settings.k_max) { + knnDist_q = knns_q.getKNNDistance(); + q.setKnnDistance(knnDist_q); + } + + } + // p is nearer to q than to its farthest knn-candidate + // q becomes knn of p + if(dist_pq <= p.getKnnDistance()) { + O obj = relation.get(p.getDBID()); + KNNList knns_without_q = knnQuery.getKNNForObject(obj, settings.k_max); + + if(knns_without_q.size() + 1 < settings.k_max) { + p.setKnnDistance(Double.NaN); + } + else { + double knnDist_p = Math.min(knns_without_q.get(knns_without_q.size() - 1).doubleValue(), dist_pq); + p.setKnnDistance(knnDist_p); + } + } + knnDist_node = Math.max(knnDist_node, p.getKnnDistance()); + } + } + // directory node + else { + O obj = relation.get(((LeafEntry) q).getDBID()); + List<DoubleObjPair<RdKNNEntry>> entries = getSortedEntries(node, obj, settings.distanceFunction); + for(DoubleObjPair<RdKNNEntry> distEntry : entries) { + RdKNNEntry entry = distEntry.second; + double entry_knnDist = entry.getKnnDistance(); + + if(distEntry.first < entry_knnDist || distEntry.first < knnDist_q) { + preInsert(q, entry, knns_q); + knnDist_q = knns_q.getKNNDistance(); + } + knnDist_node = Math.max(knnDist_node, entry.getKnnDistance()); + } + } + nodeEntry.setKnnDistance(knnDist_node); + } + + /** + * Performs a reverse knn query in the specified subtree. + * + * @param node the root node of the current subtree + * @param oid the id of the object for which the rknn query is performed + * @param result the list containing the query results + */ + private void doReverseKNN(RdKNNNode node, DBID oid, ModifiableDoubleDBIDList result) { + if(node.isLeaf()) { + for(int i = 0; i < node.getNumEntries(); i++) { + RdKNNLeafEntry entry = (RdKNNLeafEntry) node.getEntry(i); + double distance = distanceQuery.distance(entry.getDBID(), oid); + if(distance <= entry.getKnnDistance()) { + result.add(distance, entry.getDBID()); + } + } + } + // node is a inner node + else { + for(int i = 0; i < node.getNumEntries(); i++) { + RdKNNDirectoryEntry entry = (RdKNNDirectoryEntry) node.getEntry(i); + double minDist = distanceQuery.minDist(entry, oid); + if(minDist <= entry.getKnnDistance()) { + doReverseKNN(getNode(entry), oid, result); + } + } + } + } + + /** + * Performs a bulk reverse knn query in the specified subtree. + * + * @param node the root node of the current subtree + * @param ids the object ids for which the rknn query is performed + * @param result the map containing the query results for each object + */ + private void doBulkReverseKNN(RdKNNNode node, DBIDs ids, Map<DBID, ModifiableDoubleDBIDList> result) { + if(node.isLeaf()) { + for(int i = 0; i < node.getNumEntries(); i++) { + RdKNNLeafEntry entry = (RdKNNLeafEntry) node.getEntry(i); + for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { + DBID id = DBIDUtil.deref(iter); + double distance = distanceQuery.distance(entry.getDBID(), id); + if(distance <= entry.getKnnDistance()) { + result.get(id).add(distance, entry.getDBID()); + } + } + } + } + // node is a inner node + else { + for(int i = 0; i < node.getNumEntries(); i++) { + RdKNNDirectoryEntry entry = (RdKNNDirectoryEntry) node.getEntry(i); + ModifiableDBIDs candidates = DBIDUtil.newArray(); + for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { + DBID id = DBIDUtil.deref(iter); + double minDist = distanceQuery.minDist(entry, id); + if(minDist <= entry.getKnnDistance()) { + candidates.add(id); + } + if(!candidates.isEmpty()) { + doBulkReverseKNN(getNode(entry), candidates, result); + } + } + } + } + } + + /** + * Adjusts the knn distance in the subtree of the specified root entry. + * + * @param entry the root entry of the current subtree + * @param ids <em>Sorted</em> list of IDs + * @param knnLists a map of knn lists for each leaf entry + */ + private void adjustKNNDistance(RdKNNEntry entry, ArrayDBIDs ids, List<? extends KNNList> knnLists) { + RdKNNNode node = getNode(entry); + double knnDist_node = 0.; + if(node.isLeaf()) { + for(int i = 0; i < node.getNumEntries(); i++) { + RdKNNEntry leafEntry = node.getEntry(i); + DBID id = ((LeafEntry) leafEntry).getDBID(); + int pos = ids.binarySearch(id); + if(pos >= 0) { + leafEntry.setKnnDistance(knnLists.get(pos).getKNNDistance()); + } + knnDist_node = Math.max(knnDist_node, leafEntry.getKnnDistance()); + } + } + else { + for(int i = 0; i < node.getNumEntries(); i++) { + RdKNNEntry dirEntry = node.getEntry(i); + adjustKNNDistance(dirEntry, ids, knnLists); + knnDist_node = Math.max(knnDist_node, dirEntry.getKnnDistance()); + } + } + entry.setKnnDistance(knnDist_node); + } + + /** + * Creates a new leaf node with the specified capacity. + * + * @return a new leaf node + */ + @Override + protected RdKNNNode createNewLeafNode() { + return new RdKNNNode(leafCapacity, true); + } + + /** + * Creates a new directory node with the specified capacity. + * + * @return a new directory node + */ + @Override + protected RdKNNNode createNewDirectoryNode() { + return new RdKNNNode(dirCapacity, false); + } + + /** + * Creates a new directory entry representing the specified node. + * + * @param node the node to be represented by the new entry + */ + @Override + protected RdKNNEntry createNewDirectoryEntry(RdKNNNode node) { + return new RdKNNDirectoryEntry(node.getPageID(), node.computeMBR(), node.kNNDistance()); + } + + /** + * Creates an entry representing the root node. + * + * @return an entry representing the root node + */ + @Override + protected RdKNNEntry createRootEntry() { + return new RdKNNDirectoryEntry(0, null, Double.NaN); + } + + /** + * Throws an IllegalArgumentException if the specified distance function is + * not an instance of the distance function used by this index. + * + * @throws IllegalArgumentException + * @param distanceFunction the distance function to be checked + */ + private void checkDistanceFunction(SpatialPrimitiveDistanceFunction<? super O> distanceFunction) { + if(!settings.distanceFunction.equals(distanceFunction)) { + throw new IllegalArgumentException("Parameter distanceFunction must be an instance of " + this.distanceQuery.getClass() + ", but is " + distanceFunction.getClass()); + } + } + + protected RdKNNLeafEntry createNewLeafEntry(DBID id) { + return new RdKNNLeafEntry(id, relation.get(id), Double.NaN); + } + + @Override + public void initialize() { + super.initialize(); + insertAll(relation.getDBIDs()); + } + + /** + * Inserts the specified real vector object into this index. + * + * @param id the object id that was inserted + */ + @Override + public final void insert(DBIDRef id) { + insertLeaf(createNewLeafEntry(DBIDUtil.deref(id))); + } + + /** + * Inserts the specified objects into this index. If a bulk load mode is + * implemented, the objects are inserted in one bulk. + * + * @param ids the objects to be inserted + */ + @Override + public final void insertAll(DBIDs ids) { + if(ids.isEmpty() || (ids.size() == 1)) { + return; + } + + // Make an example leaf + if(canBulkLoad()) { + List<RdKNNEntry> leafs = new ArrayList<>(ids.size()); + for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { + leafs.add(createNewLeafEntry(DBIDUtil.deref(iter))); + } + bulkLoad(leafs); + } + else { + for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { + insert(iter); + } + } + + doExtraIntegrityChecks(); + } + + /** + * Deletes the specified object from this index. + * + * @return true if this index did contain the object with the specified id, + * false otherwise + */ + @Override + public final boolean delete(DBIDRef id) { + // find the leaf node containing o + O obj = relation.get(id); + IndexTreePath<RdKNNEntry> deletionPath = findPathToObject(getRootPath(), obj, id); + if(deletionPath == null) { + return false; + } + deletePath(deletionPath); + return true; + } + + @Override + public void deleteAll(DBIDs ids) { + for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { + delete(DBIDUtil.deref(iter)); + } + } + + @Override + public RangeQuery<O> getRangeQuery(DistanceQuery<O> distanceQuery, Object... hints) { + // Query on the relation we index + if(distanceQuery.getRelation() != relation) { + return null; + } + // Can we support this distance function - spatial distances only! + if(!(distanceQuery instanceof SpatialDistanceQuery)) { + return null; + } + return RStarTreeUtil.getRangeQuery(this, (SpatialDistanceQuery<O>) distanceQuery, hints); + } + + @Override + public KNNQuery<O> getKNNQuery(DistanceQuery<O> distanceQuery, Object... hints) { + // Query on the relation we index + if(distanceQuery.getRelation() != relation) { + return null; + } + // Can we support this distance function - spatial distances only! + if(!(distanceQuery instanceof SpatialDistanceQuery)) { + return null; + } + return RStarTreeUtil.getKNNQuery(this, (SpatialDistanceQuery<O>) distanceQuery, hints); + } + + @Override + public RKNNQuery<O> getRKNNQuery(DistanceQuery<O> distanceQuery, Object... hints) { + // FIXME: re-add + return null; + } + + @Override + public String getLongName() { + return "RdKNNTree"; + } + + @Override + public String getShortName() { + return "rdknntree"; + } + + @Override + protected Logging getLogger() { + return LOG; + } +} diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rdknn/RdKNNTreeFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rdknn/RdKNNTreeFactory.java new file mode 100644 index 00000000..a2c9d110 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rdknn/RdKNNTreeFactory.java @@ -0,0 +1,120 @@ +package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rdknn; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2014 + 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.data.NumberVector; +import de.lmu.ifi.dbs.elki.database.relation.Relation; +import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDistanceFunction; +import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.EuclideanDistanceFunction; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRStarTreeFactory; +import de.lmu.ifi.dbs.elki.persistent.PageFile; +import de.lmu.ifi.dbs.elki.persistent.PageFileFactory; +import de.lmu.ifi.dbs.elki.utilities.ClassGenericsUtil; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.CommonConstraints; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter; +import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.ObjectParameter; + +/** + * Factory for RdKNN R*-Trees. + * + * @author Erich Schubert + * + * @apiviz.stereotype factory + * @apiviz.uses RdKNNTreeIndex oneway - - «create» + * + * @param <O> Object type + */ +public class RdKNNTreeFactory<O extends NumberVector> extends AbstractRStarTreeFactory<O, RdKNNNode, RdKNNEntry, RdKNNTree<O>, RdkNNSettings<O>> { + /** + * Parameter for k + */ + public static final OptionID K_ID = new OptionID("rdknn.k", "positive integer specifying the maximal number k of reverse " + "k nearest neighbors to be supported."); + + /** + * The default distance function. + */ + public static final Class<?> DEFAULT_DISTANCE_FUNCTION = EuclideanDistanceFunction.class; + + /** + * Parameter for distance function + */ + public static final OptionID DISTANCE_FUNCTION_ID = new OptionID("rdknn.distancefunction", "Distance function to determine the distance between database objects."); + + /** + * Constructor. + * + * @param pageFileFactory Data storage + * @param settings Settings class + */ + public RdKNNTreeFactory(PageFileFactory<?> pageFileFactory, RdkNNSettings<O> settings) { + super(pageFileFactory, settings); + } + + @Override + public RdKNNTree<O> instantiate(Relation<O> relation) { + PageFile<RdKNNNode> pagefile = makePageFile(getNodeClass()); + RdKNNTree<O> index = new RdKNNTree<>(relation, pagefile, settings); + return index; + } + + protected Class<RdKNNNode> getNodeClass() { + return ClassGenericsUtil.uglyCastIntoSubclass(RdKNNNode.class); + } + + /** + * Parameterization class. + * + * @author Erich Schubert + * + * @apiviz.exclude + */ + public static class Parameterizer<O extends NumberVector> extends AbstractRStarTreeFactory.Parameterizer<O, RdkNNSettings<O>> { + @Override + protected void makeOptions(Parameterization config) { + super.makeOptions(config); + IntParameter k_maxP = new IntParameter(K_ID); + k_maxP.addConstraint(CommonConstraints.GREATER_EQUAL_ONE_INT); + if(config.grab(k_maxP)) { + settings.k_max = k_maxP.intValue(); + } + + ObjectParameter<SpatialPrimitiveDistanceFunction<O>> distanceFunctionP = new ObjectParameter<>(DISTANCE_FUNCTION_ID, SpatialPrimitiveDistanceFunction.class, DEFAULT_DISTANCE_FUNCTION); + if(config.grab(distanceFunctionP)) { + settings.distanceFunction = distanceFunctionP.instantiateClass(config); + } + } + + @Override + protected RdKNNTreeFactory<O> makeInstance() { + return new RdKNNTreeFactory<>(pageFileFactory, settings); + } + + @Override + protected RdkNNSettings<O> createSettings() { + return new RdkNNSettings<>(); + } + } +} diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rdknn/RdKNNTreeHeader.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rdknn/RdKNNTreeHeader.java new file mode 100644 index 00000000..fdcff104 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rdknn/RdKNNTreeHeader.java @@ -0,0 +1,101 @@ +package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rdknn; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2014 + 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.io.IOException; +import java.io.RandomAccessFile; + +import de.lmu.ifi.dbs.elki.index.tree.TreeIndexHeader; + +/** + * Encapsulates the header information of a RDkNN-Tree. This information is + * needed for persistent storage. + * + * @author Elke Achtert + */ +class RdKNNTreeHeader extends TreeIndexHeader { + /** + * The size of this header in Bytes, which is 4 Bytes (for {@link #k_max}). + */ + private static int SIZE = 4; + + /** + * The maximum number k of reverse kNN queries to be supported. + */ + int k_max; + + /** + * Empty constructor for serialization. + */ + public RdKNNTreeHeader() { + super(); + } + + /** + * Creates a new header with the specified parameters. + * + * @param pageSize the size of a page in bytes + * @param dirCapacity the maximum number of entries in a directory node + * @param leafCapacity the maximum number of entries in a leaf node + * @param dirMinimum the minimum number of entries in a directory node + * @param leafMinimum the minimum number of entries in a leaf node + * @param k_max the maximum number k of reverse kNN queries to be supported + */ + public RdKNNTreeHeader(int pageSize, int dirCapacity, int leafCapacity, int dirMinimum, int leafMinimum, int k_max) { + super(pageSize, dirCapacity, leafCapacity, dirMinimum, leafMinimum); + this.k_max = k_max; + } + + /** + * Initializes this header from the specified file. Calls + * {@link de.lmu.ifi.dbs.elki.index.tree.TreeIndexHeader#readHeader(java.io.RandomAccessFile) + * TreeIndexHeader#readHeader(file)} and reads additionally the integer value + * of {@link #k_max} from the file. + */ + @Override + public void readHeader(RandomAccessFile file) throws IOException { + super.readHeader(file); + this.k_max = file.readInt(); + } + + /** + * Writes this header to the specified file. Calls + * {@link de.lmu.ifi.dbs.elki.index.tree.TreeIndexHeader#writeHeader(java.io.RandomAccessFile)} + * and writes additionally the integer value of {@link #k_max} to the file. + */ + @Override + public void writeHeader(RandomAccessFile file) throws IOException { + super.writeHeader(file); + file.writeInt(this.k_max); + } + + /** + * Returns {@link de.lmu.ifi.dbs.elki.index.tree.TreeIndexHeader#size()} plus + * the value of {@link #SIZE}). + */ + @Override + public int size() { + return super.size() + SIZE; + } +} diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rdknn/RdkNNSettings.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rdknn/RdkNNSettings.java new file mode 100644 index 00000000..3f9997e2 --- /dev/null +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rdknn/RdkNNSettings.java @@ -0,0 +1,46 @@ +package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rdknn; + +/* + This file is part of ELKI: + Environment for Developing KDD-Applications Supported by Index-Structures + + Copyright (C) 2014 + 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.data.NumberVector; +import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDistanceFunction; +import de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.AbstractRTreeSettings; + +/** + * Settings for the RdKNN Tree. + * + * @author Erich Schubert + * + * @param <O> Object type + */ +public class RdkNNSettings<O extends NumberVector> extends AbstractRTreeSettings { + /** + * Parameter k. + */ + int k_max; + + /** + * The distance function. + */ + SpatialPrimitiveDistanceFunction<O> distanceFunction; +} diff --git a/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rdknn/package-info.java index 4c529c66..972376d6 100644 --- a/src/de/lmu/ifi/dbs/elki/index/preprocessed/subspaceproj/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rdknn/package-info.java @@ -1,11 +1,11 @@ /** - * <p>Index using a preprocessed local subspaces.</p> + * <p>{@link de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rdknn.RdKNNTree}</p> */ /* This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2013 +Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,4 +23,4 @@ GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -package de.lmu.ifi.dbs.elki.index.preprocessed.subspaceproj;
\ No newline at end of file +package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rdknn;
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTree.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTree.java index 1c2a7fe8..f7ee9bb5 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTree.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTree.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rstar; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTreeFactory.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTreeFactory.java index 72f7f7dd..74a6f54d 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTreeFactory.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTreeFactory.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rstar; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -43,7 +43,7 @@ import de.lmu.ifi.dbs.elki.utilities.Alias; * @param <O> Object type */ @Alias({"rstar", "r*"}) -public class RStarTreeFactory<O extends NumberVector<?>> extends AbstractRStarTreeFactory<O, RStarTreeNode, SpatialEntry, RStarTreeIndex<O>, AbstractRTreeSettings> { +public class RStarTreeFactory<O extends NumberVector> extends AbstractRStarTreeFactory<O, RStarTreeNode, SpatialEntry, RStarTreeIndex<O>, AbstractRTreeSettings> { /** * Constructor. * @@ -73,7 +73,7 @@ public class RStarTreeFactory<O extends NumberVector<?>> extends AbstractRStarTr * * @param <O> Object type */ - public static class Parameterizer<O extends NumberVector<?>> extends AbstractRStarTreeFactory.Parameterizer<O, AbstractRTreeSettings> { + public static class Parameterizer<O extends NumberVector> extends AbstractRStarTreeFactory.Parameterizer<O, AbstractRTreeSettings> { @Override protected RStarTreeFactory<O> makeInstance() { return new RStarTreeFactory<>(pageFileFactory, settings); diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTreeIndex.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTreeIndex.java index 15b43e64..f94d20dd 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTreeIndex.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTreeIndex.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rstar; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -36,7 +36,6 @@ import de.lmu.ifi.dbs.elki.database.query.distance.SpatialDistanceQuery; import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery; import de.lmu.ifi.dbs.elki.database.query.range.RangeQuery; import de.lmu.ifi.dbs.elki.database.relation.Relation; -import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance; import de.lmu.ifi.dbs.elki.index.DynamicIndex; import de.lmu.ifi.dbs.elki.index.KNNIndex; import de.lmu.ifi.dbs.elki.index.RangeIndex; @@ -55,7 +54,7 @@ import de.lmu.ifi.dbs.elki.persistent.PageFile; * * @param <O> Object type */ -public class RStarTreeIndex<O extends NumberVector<?>> extends RStarTree implements RangeIndex<O>, KNNIndex<O>, DynamicIndex { +public class RStarTreeIndex<O extends NumberVector> extends RStarTree implements RangeIndex<O>, KNNIndex<O>, DynamicIndex { /** * The appropriate logger for this index. */ @@ -93,7 +92,7 @@ public class RStarTreeIndex<O extends NumberVector<?>> extends RStarTree impleme super.initialize(); insertAll(relation.getDBIDs()); // Will check for actual bulk load! } - + /** * Inserts the specified reel vector object into this index. * @@ -119,13 +118,13 @@ public class RStarTreeIndex<O extends NumberVector<?>> extends RStarTree impleme // Make an example leaf if(canBulkLoad()) { List<SpatialEntry> leafs = new ArrayList<>(ids.size()); - for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { + for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { leafs.add(createNewLeafEntry(iter)); } bulkLoad(leafs); } else { - for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { + for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { insert(DBIDUtil.deref(iter)); } } @@ -153,13 +152,13 @@ public class RStarTreeIndex<O extends NumberVector<?>> extends RStarTree impleme @Override public void deleteAll(DBIDs ids) { - for (DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { + for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) { delete(iter); } } @Override - public <D extends Distance<D>> RangeQuery<O, D> getRangeQuery(DistanceQuery<O, D> distanceQuery, Object... hints) { + public RangeQuery<O> getRangeQuery(DistanceQuery<O> distanceQuery, Object... hints) { // Query on the relation we index if(distanceQuery.getRelation() != relation) { return null; @@ -168,12 +167,12 @@ public class RStarTreeIndex<O extends NumberVector<?>> extends RStarTree impleme if(!(distanceQuery instanceof SpatialDistanceQuery)) { return null; } - SpatialDistanceQuery<O, D> dq = (SpatialDistanceQuery<O, D>) distanceQuery; + SpatialDistanceQuery<O> dq = (SpatialDistanceQuery<O>) distanceQuery; return RStarTreeUtil.getRangeQuery(this, dq, hints); } @Override - public <D extends Distance<D>> KNNQuery<O, D> getKNNQuery(DistanceQuery<O, D> distanceQuery, Object... hints) { + public KNNQuery<O> getKNNQuery(DistanceQuery<O> distanceQuery, Object... hints) { // Query on the relation we index if(distanceQuery.getRelation() != relation) { return null; @@ -182,7 +181,7 @@ public class RStarTreeIndex<O extends NumberVector<?>> extends RStarTree impleme if(!(distanceQuery instanceof SpatialDistanceQuery)) { return null; } - SpatialDistanceQuery<O, D> dq = (SpatialDistanceQuery<O, D>) distanceQuery; + SpatialDistanceQuery<O> dq = (SpatialDistanceQuery<O>) distanceQuery; return RStarTreeUtil.getKNNQuery(this, dq, hints); } diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTreeNode.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTreeNode.java index 7226fa1c..833b32d0 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTreeNode.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/RStarTreeNode.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.rstar; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/package-info.java index 7897fae1..8d8b2355 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/rstar/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2013 +Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/AbstractBulkSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/AbstractBulkSplit.java index 7d463a03..6f656be6 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/AbstractBulkSplit.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/AbstractBulkSplit.java @@ -7,7 +7,7 @@ import java.util.List; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/AdaptiveSortTileRecursiveBulkSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/AdaptiveSortTileRecursiveBulkSplit.java index fbbf7d8f..5794bc0d 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/AdaptiveSortTileRecursiveBulkSplit.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/AdaptiveSortTileRecursiveBulkSplit.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/BulkSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/BulkSplit.java index c32a512c..d42f03e2 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/BulkSplit.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/BulkSplit.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -26,14 +26,13 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk; import java.util.List; import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable; /** * Interface for a bulk split strategy. * * @author Erich Schubert */ -public interface BulkSplit extends Parameterizable { +public interface BulkSplit { /** * Partitions the specified feature vectors * diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/FileOrderBulkSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/FileOrderBulkSplit.java index 8b0dfd77..77aaf071 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/FileOrderBulkSplit.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/FileOrderBulkSplit.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/MaxExtensionBulkSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/MaxExtensionBulkSplit.java index 5251e18b..edf11285 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/MaxExtensionBulkSplit.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/MaxExtensionBulkSplit.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/MaxExtensionSortTileRecursiveBulkSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/MaxExtensionSortTileRecursiveBulkSplit.java index 6bf37642..8852bffa 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/MaxExtensionSortTileRecursiveBulkSplit.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/MaxExtensionSortTileRecursiveBulkSplit.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/OneDimSortBulkSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/OneDimSortBulkSplit.java index 5d2083b3..f691789e 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/OneDimSortBulkSplit.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/OneDimSortBulkSplit.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/SortTileRecursiveBulkSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/SortTileRecursiveBulkSplit.java index 6cd7a598..a5431819 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/SortTileRecursiveBulkSplit.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/SortTileRecursiveBulkSplit.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/SpatialSortBulkSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/SpatialSortBulkSplit.java index 6e2b6369..b99764ab 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/SpatialSortBulkSplit.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/SpatialSortBulkSplit.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.bulk; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/package-info.java index 5c52de3e..e2e2e593 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/bulk/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2013 +Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/ApproximativeLeastOverlapInsertionStrategy.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/ApproximativeLeastOverlapInsertionStrategy.java index 01dde189..fe9698ba 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/ApproximativeLeastOverlapInsertionStrategy.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/ApproximativeLeastOverlapInsertionStrategy.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/CombinedInsertionStrategy.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/CombinedInsertionStrategy.java index 837f0312..ac055184 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/CombinedInsertionStrategy.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/CombinedInsertionStrategy.java @@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/InsertionStrategy.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/InsertionStrategy.java index 477f0f48..964bce27 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/InsertionStrategy.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/InsertionStrategy.java @@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -24,14 +24,13 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert; import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayAdapter; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable; /** * RTree insertion strategy interface. * * @author Erich Schubert */ -public interface InsertionStrategy extends Parameterizable { +public interface InsertionStrategy { /** * Choose insertion rectangle. * diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastEnlargementInsertionStrategy.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastEnlargementInsertionStrategy.java index 39348bf5..93d80436 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastEnlargementInsertionStrategy.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastEnlargementInsertionStrategy.java @@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastEnlargementWithAreaInsertionStrategy.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastEnlargementWithAreaInsertionStrategy.java index 627428e9..cf1267f7 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastEnlargementWithAreaInsertionStrategy.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastEnlargementWithAreaInsertionStrategy.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastOverlapInsertionStrategy.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastOverlapInsertionStrategy.java index 18855d90..8ed0b2b1 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastOverlapInsertionStrategy.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/LeastOverlapInsertionStrategy.java @@ -3,7 +3,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.insert; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/package-info.java index d425c7bd..6c2f26b2 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/insert/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/LimitedReinsertOverflowTreatment.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/LimitedReinsertOverflowTreatment.java index 0af90d78..b7184f93 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/LimitedReinsertOverflowTreatment.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/LimitedReinsertOverflowTreatment.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.overflow This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/OverflowTreatment.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/OverflowTreatment.java index 4b2f94b1..06dcd215 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/OverflowTreatment.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/OverflowTreatment.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.overflow This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/SplitOnlyOverflowTreatment.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/SplitOnlyOverflowTreatment.java index 82ceb4ef..5aea9e5c 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/SplitOnlyOverflowTreatment.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/SplitOnlyOverflowTreatment.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.overflow This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/package-info.java index fc7f16f0..28cbc3eb 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/overflow/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/package-info.java index 7d2dfc0a..d3b6de11 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/AbstractPartialReinsert.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/AbstractPartialReinsert.java index f73699ea..02b98e3b 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/AbstractPartialReinsert.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/AbstractPartialReinsert.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.reinsert This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -23,7 +23,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.reinsert along with this program. If not, see <http://www.gnu.org/licenses/>. */ -import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDoubleDistanceFunction; +import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDistanceFunction; import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.SquaredEuclideanDistanceFunction; import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer; import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID; @@ -47,7 +47,7 @@ public abstract class AbstractPartialReinsert implements ReinsertStrategy { /** * Distance function to use for measuring */ - SpatialPrimitiveDoubleDistanceFunction<?> distanceFunction; + SpatialPrimitiveDistanceFunction<?> distanceFunction; /** * Constructor. @@ -55,7 +55,7 @@ public abstract class AbstractPartialReinsert implements ReinsertStrategy { * @param reinsertAmount Relative amount of objects to reinsert. * @param distanceFunction Distance function to use */ - public AbstractPartialReinsert(double reinsertAmount, SpatialPrimitiveDoubleDistanceFunction<?> distanceFunction) { + public AbstractPartialReinsert(double reinsertAmount, SpatialPrimitiveDistanceFunction<?> distanceFunction) { super(); this.reinsertAmount = reinsertAmount; this.distanceFunction = distanceFunction; @@ -87,7 +87,7 @@ public abstract class AbstractPartialReinsert implements ReinsertStrategy { /** * Distance function to use for measuring */ - SpatialPrimitiveDoubleDistanceFunction<?> distanceFunction; + SpatialPrimitiveDistanceFunction<?> distanceFunction; @Override protected void makeOptions(Parameterization config) { @@ -98,7 +98,7 @@ public abstract class AbstractPartialReinsert implements ReinsertStrategy { if(config.grab(reinsertAmountP)) { reinsertAmount = reinsertAmountP.getValue(); } - ObjectParameter<SpatialPrimitiveDoubleDistanceFunction<?>> distanceP = new ObjectParameter<>(REINSERT_DISTANCE_ID, SpatialPrimitiveDoubleDistanceFunction.class, SquaredEuclideanDistanceFunction.class); + ObjectParameter<SpatialPrimitiveDistanceFunction<?>> distanceP = new ObjectParameter<>(REINSERT_DISTANCE_ID, SpatialPrimitiveDistanceFunction.class, SquaredEuclideanDistanceFunction.class); if(config.grab(distanceP)) { distanceFunction = distanceP.instantiateClass(config); } diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/CloseReinsert.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/CloseReinsert.java index 3002f18b..05dcffb9 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/CloseReinsert.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/CloseReinsert.java @@ -6,7 +6,7 @@ import java.util.Collections; import de.lmu.ifi.dbs.elki.data.DoubleVector; import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil; -import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDoubleDistanceFunction; +import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDistanceFunction; import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayAdapter; import de.lmu.ifi.dbs.elki.utilities.documentation.Reference; import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleIntPair; @@ -15,7 +15,7 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleIntPair; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -42,24 +42,27 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleIntPair; * * @author Erich Schubert */ -@Reference(authors = "N. Beckmann, H.-P. Kriegel, R. Schneider, B. Seeger", title = "The R*-tree: an efficient and robust access method for points and rectangles", booktitle = "Proceedings of the 1990 ACM SIGMOD International Conference on Management of Data, Atlantic City, NJ, May 23-25, 1990", url = "http://dx.doi.org/10.1145/93597.98741") +@Reference(authors = "N. Beckmann, H.-P. Kriegel, R. Schneider, B. Seeger", // +title = "The R*-tree: an efficient and robust access method for points and rectangles", // +booktitle = "Proceedings of the 1990 ACM SIGMOD International Conference on Management of Data, Atlantic City, NJ, May 23-25, 1990", // +url = "http://dx.doi.org/10.1145/93597.98741") public class CloseReinsert extends AbstractPartialReinsert { /** * Constructor. - * + * * @param reinsertAmount Amount of objects to reinsert * @param distanceFunction Distance function to use for reinsertion */ - public CloseReinsert(double reinsertAmount, SpatialPrimitiveDoubleDistanceFunction<?> distanceFunction) { + public CloseReinsert(double reinsertAmount, SpatialPrimitiveDistanceFunction<?> distanceFunction) { super(reinsertAmount, distanceFunction); } @Override public <A> int[] computeReinserts(A entries, ArrayAdapter<? extends SpatialComparable, ? super A> getter, SpatialComparable page) { DoubleIntPair[] order = new DoubleIntPair[getter.size(entries)]; - DoubleVector centroid = new DoubleVector(SpatialUtil.centroid(page)); + DoubleVector centroid = new DoubleVector(SpatialUtil.centroid(page)); for(int i = 0; i < order.length; i++) { - double distance = distanceFunction.doubleMinDist(new DoubleVector(SpatialUtil.centroid(getter.get(entries, i))), centroid); + double distance = distanceFunction.minDist(new DoubleVector(SpatialUtil.centroid(getter.get(entries, i))), centroid); order[i] = new DoubleIntPair(distance, i); } Arrays.sort(order, Collections.reverseOrder()); @@ -71,7 +74,7 @@ public class CloseReinsert extends AbstractPartialReinsert { } return re; } - + /** * Parameterization class. * @@ -81,7 +84,7 @@ public class CloseReinsert extends AbstractPartialReinsert { */ public static class Parameterizer extends AbstractPartialReinsert.Parameterizer { @Override - protected Object makeInstance() { + protected CloseReinsert makeInstance() { return new CloseReinsert(reinsertAmount, distanceFunction); } } diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/FarReinsert.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/FarReinsert.java index 02c1d4d7..bdb7790a 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/FarReinsert.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/FarReinsert.java @@ -6,7 +6,7 @@ import java.util.Collections; import de.lmu.ifi.dbs.elki.data.DoubleVector; import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; import de.lmu.ifi.dbs.elki.data.spatial.SpatialUtil; -import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDoubleDistanceFunction; +import de.lmu.ifi.dbs.elki.distance.distancefunction.SpatialPrimitiveDistanceFunction; import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayAdapter; import de.lmu.ifi.dbs.elki.utilities.documentation.Reference; import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleIntPair; @@ -15,7 +15,7 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleIntPair; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -42,7 +42,10 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleIntPair; * * @author Erich Schubert */ -@Reference(authors = "N. Beckmann, H.-P. Kriegel, R. Schneider, B. Seeger", title = "The R*-tree: an efficient and robust access method for points and rectangles", booktitle = "Proceedings of the 1990 ACM SIGMOD International Conference on Management of Data, Atlantic City, NJ, May 23-25, 1990", url = "http://dx.doi.org/10.1145/93597.98741") +@Reference(authors = "N. Beckmann, H.-P. Kriegel, R. Schneider, B. Seeger", // +title = "The R*-tree: an efficient and robust access method for points and rectangles", // +booktitle = "Proceedings of the 1990 ACM SIGMOD International Conference on Management of Data, Atlantic City, NJ, May 23-25, 1990", // +url = "http://dx.doi.org/10.1145/93597.98741") public class FarReinsert extends AbstractPartialReinsert { /** * Constructor. @@ -50,7 +53,7 @@ public class FarReinsert extends AbstractPartialReinsert { * @param reinsertAmount Amount to reinsert * @param distanceFunction Distance function */ - public FarReinsert(double reinsertAmount, SpatialPrimitiveDoubleDistanceFunction<?> distanceFunction) { + public FarReinsert(double reinsertAmount, SpatialPrimitiveDistanceFunction<?> distanceFunction) { super(reinsertAmount, distanceFunction); } @@ -59,7 +62,7 @@ public class FarReinsert extends AbstractPartialReinsert { DoubleIntPair[] order = new DoubleIntPair[getter.size(entries)]; DoubleVector centroid = new DoubleVector(SpatialUtil.centroid(page)); for(int i = 0; i < order.length; i++) { - double distance = distanceFunction.doubleMinDist(new DoubleVector(SpatialUtil.centroid(getter.get(entries, i))), centroid); + double distance = distanceFunction.minDist(new DoubleVector(SpatialUtil.centroid(getter.get(entries, i))), centroid); order[i] = new DoubleIntPair(distance, i); } Arrays.sort(order, Collections.reverseOrder()); @@ -81,8 +84,8 @@ public class FarReinsert extends AbstractPartialReinsert { */ public static class Parameterizer extends AbstractPartialReinsert.Parameterizer { @Override - protected Object makeInstance() { - return new CloseReinsert(reinsertAmount, distanceFunction); + protected FarReinsert makeInstance() { + return new FarReinsert(reinsertAmount, distanceFunction); } } }
\ No newline at end of file diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/ReinsertStrategy.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/ReinsertStrategy.java index 2a4f130f..4b350123 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/ReinsertStrategy.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/ReinsertStrategy.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.reinsert This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/package-info.java index 2d2c6871..e96642f6 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/reinsert/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/AngTanLinearSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/AngTanLinearSplit.java index c31abc2d..60ba9457 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/AngTanLinearSplit.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/AngTanLinearSplit.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/GreeneSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/GreeneSplit.java index d00479cf..5bee1302 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/GreeneSplit.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/GreeneSplit.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/RTreeLinearSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/RTreeLinearSplit.java index 4dc9b15d..75f37a71 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/RTreeLinearSplit.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/RTreeLinearSplit.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/RTreeQuadraticSplit.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/RTreeQuadraticSplit.java index 91ef8f16..2ac7c176 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/RTreeQuadraticSplit.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/RTreeQuadraticSplit.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/SplitStrategy.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/SplitStrategy.java index 0bc1ffcf..0bd4f39f 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/SplitStrategy.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/SplitStrategy.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -27,14 +27,13 @@ import java.util.BitSet; import de.lmu.ifi.dbs.elki.data.spatial.SpatialComparable; import de.lmu.ifi.dbs.elki.utilities.datastructures.arraylike.ArrayAdapter; -import de.lmu.ifi.dbs.elki.utilities.optionhandling.Parameterizable; /** * Generic interface for split strategies. * * @author Erich Schubert */ -public interface SplitStrategy extends Parameterizable { +public interface SplitStrategy { /** * Split a page * diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/TopologicalSplitter.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/TopologicalSplitter.java index dc9092ad..259c83b1 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/TopologicalSplitter.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/TopologicalSplitter.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.strategies.split; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/package-info.java index bb8cb1e2..78bffb0f 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/strategies/split/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/NodeArrayAdapter.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/NodeArrayAdapter.java index def824ba..86cb360a 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/NodeArrayAdapter.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/NodeArrayAdapter.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.tree.spatial.rstarvariants.util; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/package-info.java b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/package-info.java index 22088417..6f2686f6 100644 --- a/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/tree/spatial/rstarvariants/util/package-info.java @@ -6,7 +6,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures -Copyright (C) 2013 +Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team diff --git a/src/de/lmu/ifi/dbs/elki/index/vafile/DAFile.java b/src/de/lmu/ifi/dbs/elki/index/vafile/DAFile.java index 089397dd..dcc54e2a 100644 --- a/src/de/lmu/ifi/dbs/elki/index/vafile/DAFile.java +++ b/src/de/lmu/ifi/dbs/elki/index/vafile/DAFile.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.vafile; This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011
+ Copyright (C) 2014
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team @@ -28,8 +28,8 @@ import java.util.Arrays; import de.lmu.ifi.dbs.elki.data.NumberVector;
import de.lmu.ifi.dbs.elki.database.ids.DBIDIter;
import de.lmu.ifi.dbs.elki.database.relation.Relation;
-import de.lmu.ifi.dbs.elki.persistent.ByteArrayUtil;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.io.ByteArrayUtil;
/**
* Dimension approximation file, a one-dimensional part of the
@@ -66,7 +66,7 @@ public class DAFile { * @param dimension Dimension of this file
* @param partitions Number of partitions
*/
- public DAFile(Relation<? extends NumberVector<?>> relation, int dimension, int partitions) {
+ public DAFile(Relation<? extends NumberVector> relation, int dimension, int partitions) {
final int size = relation.size();
this.dimension = dimension;
this.splitPositions = new double[partitions + 1];
diff --git a/src/de/lmu/ifi/dbs/elki/index/vafile/PartialVAFile.java b/src/de/lmu/ifi/dbs/elki/index/vafile/PartialVAFile.java index e66b4011..a7dd0a29 100644 --- a/src/de/lmu/ifi/dbs/elki/index/vafile/PartialVAFile.java +++ b/src/de/lmu/ifi/dbs/elki/index/vafile/PartialVAFile.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.vafile; This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011
+ Copyright (C) 2014
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team @@ -25,7 +25,6 @@ package de.lmu.ifi.dbs.elki.index.vafile; import java.util.ArrayList;
import java.util.Arrays;
-import java.util.BitSet;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
@@ -38,9 +37,10 @@ import de.lmu.ifi.dbs.elki.data.type.TypeUtil; 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.DBIDUtil;
-import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPairList;
-import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNHeap;
-import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNList;
+import de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.KNNHeap;
+import de.lmu.ifi.dbs.elki.database.ids.KNNList;
+import de.lmu.ifi.dbs.elki.database.ids.ModifiableDoubleDBIDList;
import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
@@ -50,8 +50,6 @@ import de.lmu.ifi.dbs.elki.database.relation.RelationUtil; import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.LPNormDistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancefunction.subspace.SubspaceLPNormDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.index.AbstractRefiningIndex;
import de.lmu.ifi.dbs.elki.index.IndexFactory;
import de.lmu.ifi.dbs.elki.index.KNNIndex;
@@ -61,9 +59,10 @@ import de.lmu.ifi.dbs.elki.logging.statistics.Counter; import de.lmu.ifi.dbs.elki.math.MathUtil;
import de.lmu.ifi.dbs.elki.math.linearalgebra.Vector;
import de.lmu.ifi.dbs.elki.persistent.AbstractPageFileFactory;
-import de.lmu.ifi.dbs.elki.persistent.ByteArrayUtil;
+import de.lmu.ifi.dbs.elki.utilities.BitsUtil;
import de.lmu.ifi.dbs.elki.utilities.datastructures.heap.DoubleMaxHeap;
import de.lmu.ifi.dbs.elki.utilities.documentation.Reference;
+import de.lmu.ifi.dbs.elki.utilities.io.ByteArrayUtil;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.AbstractParameterizer;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.CommonConstraints;
@@ -96,7 +95,7 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleObjPair; * @param <V> Vector type
*/
@Reference(authors = "Hans-Peter Kriegel, Peer Kröger, Matthias Schubert, Ziyue Zhu", title = "Efficient Query Processing in Arbitrary Subspaces Using Vector Approximations", booktitle = "Proc. 18th Int. Conf. on Scientific and Statistical Database Management (SSDBM 06), Wien, Austria, 2006", url = "http://dx.doi.org/10.1109/SSDBM.2006.23")
-public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIndex<V> implements KNNIndex<V>, RangeIndex<V> {
+public class PartialVAFile<V extends NumberVector> extends AbstractRefiningIndex<V> implements KNNIndex<V>, RangeIndex<V> {
/**
* Class logger.
*/
@@ -152,7 +151,7 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn throw new IllegalStateException("Data already inserted.");
}
- if((Math.log(partitions) / MathUtil.LOG2) != (int) (Math.log(partitions) / MathUtil.LOG2)) {
+ if(MathUtil.log2(partitions) != (int) MathUtil.log2(partitions)) {
throw new IllegalArgumentException("Number of partitions must be a power of 2!");
}
@@ -196,21 +195,6 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn }
/**
- * Fake subspace (full-dimensional).
- *
- * @param relation Relation with full dimensionality
- * @return Bit set with all bits set.
- */
- protected static BitSet fakeSubspace(Relation<? extends NumberVector<?>> relation) {
- int dim = RelationUtil.dimensionality(relation);
- BitSet bits = new BitSet();
- for(int i = 0; i < dim; i++) {
- bits.set(i);
- }
- return bits;
- }
-
- /**
* Calculate the VA file position given the existing borders.
*
* @param id Object ID
@@ -247,51 +231,41 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn return new VectorApproximation(id, approximation);
}
- @SuppressWarnings("unchecked")
@Override
- public <D extends Distance<D>> KNNQuery<V, D> getKNNQuery(DistanceQuery<V, D> distanceQuery, Object... hints) {
+ public KNNQuery<V> getKNNQuery(DistanceQuery<V> distanceQuery, Object... hints) {
for(Object hint : hints) {
if(hint == DatabaseQuery.HINT_BULK) {
// FIXME: support bulk?
return null;
}
}
- DistanceFunction<? super V, ?> df = distanceQuery.getDistanceFunction();
+ DistanceFunction<? super V> df = distanceQuery.getDistanceFunction();
if(df instanceof SubspaceLPNormDistanceFunction) {
double p = ((SubspaceLPNormDistanceFunction) df).getP();
- BitSet bits = ((SubspaceLPNormDistanceFunction) df).getSelectedDimensions();
- DistanceQuery<V, ?> ddq = (DistanceQuery<V, ?>) distanceQuery;
- KNNQuery<V, ?> dq = new PartialVAFileKNNQuery((DistanceQuery<V, DoubleDistance>) ddq, p, bits);
- return (KNNQuery<V, D>) dq;
+ long[] bits = ((SubspaceLPNormDistanceFunction) df).getSelectedDimensions();
+ return new PartialVAFileKNNQuery(distanceQuery, p, bits);
}
if(df instanceof LPNormDistanceFunction) {
double p = ((LPNormDistanceFunction) df).getP();
- BitSet bits = fakeSubspace(distanceQuery.getRelation());
- DistanceQuery<V, ?> ddq = (DistanceQuery<V, ?>) distanceQuery;
- KNNQuery<V, ?> dq = new PartialVAFileKNNQuery((DistanceQuery<V, DoubleDistance>) ddq, p, bits);
- return (KNNQuery<V, D>) dq;
+ long[] bits = BitsUtil.ones(RelationUtil.dimensionality(distanceQuery.getRelation()));
+ return new PartialVAFileKNNQuery(distanceQuery, p, bits);
}
// Not supported.
return null;
}
- @SuppressWarnings("unchecked")
@Override
- public <D extends Distance<D>> RangeQuery<V, D> getRangeQuery(DistanceQuery<V, D> distanceQuery, Object... hints) {
- DistanceFunction<? super V, ?> df = distanceQuery.getDistanceFunction();
+ public RangeQuery<V> getRangeQuery(DistanceQuery<V> distanceQuery, Object... hints) {
+ DistanceFunction<? super V> df = distanceQuery.getDistanceFunction();
if(df instanceof SubspaceLPNormDistanceFunction) {
double p = ((SubspaceLPNormDistanceFunction) df).getP();
- BitSet bits = ((SubspaceLPNormDistanceFunction) df).getSelectedDimensions();
- DistanceQuery<V, ?> ddq = (DistanceQuery<V, ?>) distanceQuery;
- RangeQuery<V, ?> dq = new PartialVAFileRangeQuery((DistanceQuery<V, DoubleDistance>) ddq, p, bits);
- return (RangeQuery<V, D>) dq;
+ long[] bits = ((SubspaceLPNormDistanceFunction) df).getSelectedDimensions();
+ return new PartialVAFileRangeQuery(distanceQuery, p, bits);
}
if(df instanceof LPNormDistanceFunction) {
double p = ((LPNormDistanceFunction) df).getP();
- BitSet bits = fakeSubspace(distanceQuery.getRelation());
- DistanceQuery<V, ?> ddq = (DistanceQuery<V, ?>) distanceQuery;
- RangeQuery<V, ?> dq = new PartialVAFileRangeQuery((DistanceQuery<V, DoubleDistance>) ddq, p, bits);
- return (RangeQuery<V, D>) dq;
+ long[] bits = BitsUtil.ones(RelationUtil.dimensionality(distanceQuery.getRelation()));
+ return new PartialVAFileRangeQuery(distanceQuery, p, bits);
}
// Not supported.
return null;
@@ -304,7 +278,7 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn * @param query Query vector
* @param epsilon Epsilon radius
*/
- protected static void calculateSelectivityCoeffs(List<DoubleObjPair<DAFile>> daFiles, NumberVector<?> query, double epsilon) {
+ protected static void calculateSelectivityCoeffs(List<DoubleObjPair<DAFile>> daFiles, NumberVector query, double epsilon) {
final int dimensions = query.getDimensionality();
double[] lowerVals = new double[dimensions];
double[] upperVals = new double[dimensions];
@@ -337,7 +311,7 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn * @param daFiles List of approximations to use
* @return Vector approximation
*/
- protected static VectorApproximation calculatePartialApproximation(DBID id, NumberVector<?> dv, List<DoubleObjPair<DAFile>> daFiles) {
+ protected static VectorApproximation calculatePartialApproximation(DBID id, NumberVector dv, List<DoubleObjPair<DAFile>> daFiles) {
int[] approximation = new int[dv.getDimensionality()];
for(int i = 0; i < daFiles.size(); i++) {
double val = dv.doubleValue(i);
@@ -484,7 +458,7 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn * @author Erich Schubert
* @author Thomas Bernecker
*/
- public class PartialVAFileRangeQuery extends AbstractRefiningIndex<V>.AbstractRangeQuery<DoubleDistance> {
+ public class PartialVAFileRangeQuery extends AbstractRefiningIndex<V>.AbstractRangeQuery {
/**
* Lp-Norm p.
*/
@@ -493,7 +467,7 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn /**
* Subspace.
*/
- private BitSet subspace;
+ private long[] subspace;
/**
* Constructor.
@@ -502,18 +476,18 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn * @param p LP Norm p
* @param subspace Subspace
*/
- public PartialVAFileRangeQuery(DistanceQuery<V, DoubleDistance> ddq, double p, BitSet subspace) {
+ public PartialVAFileRangeQuery(DistanceQuery<V> ddq, double p, long[] subspace) {
super(ddq);
this.p = p;
this.subspace = subspace;
}
@Override
- public DoubleDistanceDBIDPairList getRangeForObject(V query, DoubleDistance range) {
+ public DoubleDBIDList getRangeForObject(V query, double range) {
stats.incrementIssuedQueries();
long t = System.nanoTime();
- final double epsilonP = Math.pow(range.doubleValue(), p);
+ final double epsilonP = Math.pow(range, p);
// generate query approximation and lookup table
final VectorApproximation queryApprox = calculateFullApproximation(null, query);
@@ -524,12 +498,12 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn // filter step
// calculate selectivity coefficients
- List<DoubleObjPair<DAFile>> subspaceDAFiles = new ArrayList<>(subspace.cardinality());
- for(int d = subspace.nextSetBit(0); d >= 0; d = subspace.nextSetBit(d + 1)) {
+ List<DoubleObjPair<DAFile>> subspaceDAFiles = new ArrayList<>(BitsUtil.cardinality(subspace));
+ for(int d = BitsUtil.nextSetBit(subspace, 0); d >= 0; d = BitsUtil.nextSetBit(subspace, d + 1)) {
DAFile daFile = daFiles.get(d);
subspaceDAFiles.add(new DoubleObjPair<>(-1, daFile));
}
- calculateSelectivityCoeffs(subspaceDAFiles, query, range.doubleValue());
+ calculateSelectivityCoeffs(subspaceDAFiles, query, range);
// sort DA files by selectivity
// TODO: validate that this is the correct order
Collections.sort(subspaceDAFiles, Collections.reverseOrder());
@@ -537,7 +511,7 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn // create candidate list (all objects) and prune candidates w.r.t.
// mindist (i.e. remove them from the list)
// important: this structure contains the maxDist values for refinement!
- DoubleDistanceDBIDPairList result = new DoubleDistanceDBIDPairList();
+ ModifiableDoubleDBIDList result = DBIDUtil.newDistanceDBIDList();
int candidates = 0;
for(VectorApproximation va : vectorApprox) {
DBID id = va.getId();
@@ -560,20 +534,20 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn // candidate cannot be dropped
// TODO: actually: no refinement needed - need API that allows
// reporting maxdists only.
- result.add(refine(id, query).doubleValue(), id);
+ result.add(refine(id, query), id);
}
else { // refine candidate - true refinement
- DoubleDistance dis = refine(id, query);
+ double dis = refine(id, query);
stats.incrementRefinements();
- if(dis.doubleValue() <= range.doubleValue()) {
- result.add(dis.doubleValue(), id);
+ if(dis <= range) {
+ result.add(dis, id);
}
}
}
}
result.sort();
- stats.incrementScannedBytes(relation.size() * VectorApproximation.byteOnDisk(subspace.cardinality(), partitions));
+ stats.incrementScannedBytes(relation.size() * VectorApproximation.byteOnDisk(BitsUtil.cardinality(subspace), partitions));
stats.incrementQueryTime(System.nanoTime() - t);
@@ -592,7 +566,7 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn * @author Erich Schubert
* @author Thomas Bernecker
*/
- public class PartialVAFileKNNQuery extends AbstractRefiningIndex<V>.AbstractKNNQuery<DoubleDistance> {
+ public class PartialVAFileKNNQuery extends AbstractRefiningIndex<V>.AbstractKNNQuery {
/**
* Lp-Norm p.
*/
@@ -601,7 +575,7 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn /**
* Subspace.
*/
- private BitSet subspace;
+ private long[] subspace;
/**
* Constructor.
@@ -610,14 +584,14 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn * @param p LP-norm p
* @param subspace Subspace to query
*/
- public PartialVAFileKNNQuery(DistanceQuery<V, DoubleDistance> ddq, double p, BitSet subspace) {
+ public PartialVAFileKNNQuery(DistanceQuery<V> ddq, double p, long[] subspace) {
super(ddq);
this.p = p;
this.subspace = subspace;
}
@Override
- public DoubleDistanceKNNList getKNNForObject(V query, int k) {
+ public KNNList getKNNForObject(V query, int k) {
stats.incrementIssuedQueries();
long t = System.nanoTime();
@@ -628,7 +602,7 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn // sort DA files by worst case distance
List<DAFile> daFiles = getWorstCaseDistOrder(dist, subspace);
- final int currentSubspaceDims = subspace.cardinality();
+ final int currentSubspaceDims = BitsUtil.cardinality(subspace);
int reducedDims = (2 * currentSubspaceDims) / 3;
reducedDims = Math.max(1, reducedDims);
if(LOG.isDebuggingFine()) {
@@ -690,7 +664,7 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn ArrayList<PartialVACandidate> sortedCandidates = new ArrayList<>(candidates2);
// sort candidates by lower bound (minDist)
Collections.sort(sortedCandidates);
- DoubleDistanceKNNList result = retrieveAccurateDistances(sortedCandidates, k, subspace, query);
+ KNNList result = retrieveAccurateDistances(sortedCandidates, k, subspace, query);
stats.incrementQueryTime(System.nanoTime() - t);
return result;
@@ -758,26 +732,26 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn * @param subspace Subspace
* @return Ordered list of dimension files
*/
- public List<DAFile> getWorstCaseDistOrder(VALPNormDistance dist, BitSet subspace) {
- int subspaceLength = subspace.cardinality();
+ public List<DAFile> getWorstCaseDistOrder(VALPNormDistance dist, long[] subspace) {
+ int subspaceLength = BitsUtil.cardinality(subspace);
List<DAFile> result = new ArrayList<>(subspaceLength);
- for(int i = subspace.nextSetBit(0); i >= 0; i = subspace.nextSetBit(i + 1)) {
+ for(int i = BitsUtil.nextSetBit(subspace, 0); i >= 0; i = BitsUtil.nextSetBit(subspace, i + 1)) {
result.add(daFiles.get(i));
}
Collections.sort(result, new WorstCaseDistComparator(dist));
return result;
}
- protected DoubleDistanceKNNList retrieveAccurateDistances(List<PartialVACandidate> sortedCandidates, int k, BitSet subspace, V query) {
- DoubleDistanceKNNHeap result = DBIDUtil.newDoubleDistanceHeap(k);
+ protected KNNList retrieveAccurateDistances(List<PartialVACandidate> sortedCandidates, int k, long[] subspace, V query) {
+ KNNHeap result = DBIDUtil.newHeap(k);
for(PartialVACandidate va : sortedCandidates) {
- double stopdist = result.doubleKNNDistance();
+ double stopdist = result.getKNNDistance();
DBID currentID = va.getId();
if(result.size() < k || va.minDistP < stopdist) {
- DoubleDistance dist = refine(currentID, query);
+ double dist = refine(currentID, query);
stats.incrementRefinements();
- if(dist.doubleValue() < stopdist) {
- result.insert(dist.doubleValue(), currentID);
+ if(dist < stopdist) {
+ result.insert(dist, currentID);
}
}
}
@@ -813,7 +787,7 @@ public class PartialVAFile<V extends NumberVector<?>> extends AbstractRefiningIn *
* @param <V> Vector type
*/
- public static class Factory<V extends NumberVector<?>> implements IndexFactory<V, PartialVAFile<V>> {
+ public static class Factory<V extends NumberVector> implements IndexFactory<V, PartialVAFile<V>> {
/**
* Number of partitions to use in each dimension.
*
diff --git a/src/de/lmu/ifi/dbs/elki/index/vafile/VAFile.java b/src/de/lmu/ifi/dbs/elki/index/vafile/VAFile.java index 42651b15..bdf30d15 100644 --- a/src/de/lmu/ifi/dbs/elki/index/vafile/VAFile.java +++ b/src/de/lmu/ifi/dbs/elki/index/vafile/VAFile.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.vafile; This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011
+ Copyright (C) 2014
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team @@ -25,7 +25,6 @@ package de.lmu.ifi.dbs.elki.index.vafile; import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
import de.lmu.ifi.dbs.elki.data.NumberVector;
@@ -34,9 +33,11 @@ import de.lmu.ifi.dbs.elki.data.type.TypeUtil; 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.DBIDUtil;
-import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceDBIDPairList;
-import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNHeap;
-import de.lmu.ifi.dbs.elki.database.ids.distance.DoubleDistanceKNNList;
+import de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDList;
+import de.lmu.ifi.dbs.elki.database.ids.DoubleDBIDListIter;
+import de.lmu.ifi.dbs.elki.database.ids.KNNHeap;
+import de.lmu.ifi.dbs.elki.database.ids.KNNList;
+import de.lmu.ifi.dbs.elki.database.ids.ModifiableDoubleDBIDList;
import de.lmu.ifi.dbs.elki.database.query.DatabaseQuery;
import de.lmu.ifi.dbs.elki.database.query.distance.DistanceQuery;
import de.lmu.ifi.dbs.elki.database.query.knn.KNNQuery;
@@ -45,8 +46,6 @@ import de.lmu.ifi.dbs.elki.database.relation.Relation; import de.lmu.ifi.dbs.elki.database.relation.RelationUtil;
import de.lmu.ifi.dbs.elki.distance.distancefunction.DistanceFunction;
import de.lmu.ifi.dbs.elki.distance.distancefunction.minkowski.LPNormDistanceFunction;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.Distance;
-import de.lmu.ifi.dbs.elki.distance.distancevalue.DoubleDistance;
import de.lmu.ifi.dbs.elki.index.AbstractRefiningIndex;
import de.lmu.ifi.dbs.elki.index.IndexFactory;
import de.lmu.ifi.dbs.elki.index.KNNIndex;
@@ -61,7 +60,6 @@ import de.lmu.ifi.dbs.elki.utilities.optionhandling.OptionID; import de.lmu.ifi.dbs.elki.utilities.optionhandling.constraints.CommonConstraints;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameterization.Parameterization;
import de.lmu.ifi.dbs.elki.utilities.optionhandling.parameters.IntParameter;
-import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleObjPair;
/**
* Vector-approximation file (VAFile)
@@ -87,7 +85,7 @@ import de.lmu.ifi.dbs.elki.utilities.pairs.DoubleObjPair; */
@Title("An approximation based data structure for similarity search")
@Reference(authors = "Weber, R. and Blott, S.", title = "An approximation based data structure for similarity search", booktitle = "Report TR1997b, ETH Zentrum, Zurich, Switzerland", url = "http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.40.480&rep=rep1&type=pdf")
-public class VAFile<V extends NumberVector<?>> extends AbstractRefiningIndex<V> implements KNNIndex<V>, RangeIndex<V> {
+public class VAFile<V extends NumberVector> extends AbstractRefiningIndex<V> implements KNNIndex<V>, RangeIndex<V> {
/**
* Logging class.
*/
@@ -244,35 +242,29 @@ public class VAFile<V extends NumberVector<?>> extends AbstractRefiningIndex<V> return "va-file";
}
- @SuppressWarnings("unchecked")
@Override
- public <D extends Distance<D>> KNNQuery<V, D> getKNNQuery(DistanceQuery<V, D> distanceQuery, Object... hints) {
+ public KNNQuery<V> getKNNQuery(DistanceQuery<V> distanceQuery, Object... hints) {
for(Object hint : hints) {
if(hint == DatabaseQuery.HINT_BULK) {
// FIXME: support bulk?
return null;
}
}
- DistanceFunction<? super V, ?> df = distanceQuery.getDistanceFunction();
+ DistanceFunction<? super V> df = distanceQuery.getDistanceFunction();
if(df instanceof LPNormDistanceFunction) {
double p = ((LPNormDistanceFunction) df).getP();
- DistanceQuery<V, ?> ddq = (DistanceQuery<V, ?>) distanceQuery;
- KNNQuery<V, ?> dq = new VAFileKNNQuery((DistanceQuery<V, DoubleDistance>) ddq, p);
- return (KNNQuery<V, D>) dq;
+ return new VAFileKNNQuery(distanceQuery, p);
}
// Not supported.
return null;
}
- @SuppressWarnings("unchecked")
@Override
- public <D extends Distance<D>> RangeQuery<V, D> getRangeQuery(DistanceQuery<V, D> distanceQuery, Object... hints) {
- DistanceFunction<? super V, ?> df = distanceQuery.getDistanceFunction();
+ public RangeQuery<V> getRangeQuery(DistanceQuery<V> distanceQuery, Object... hints) {
+ DistanceFunction<? super V> df = distanceQuery.getDistanceFunction();
if(df instanceof LPNormDistanceFunction) {
double p = ((LPNormDistanceFunction) df).getP();
- DistanceQuery<V, ?> ddq = (DistanceQuery<V, ?>) distanceQuery;
- RangeQuery<V, ?> dq = new VAFileRangeQuery((DistanceQuery<V, DoubleDistance>) ddq, p);
- return (RangeQuery<V, D>) dq;
+ return new VAFileRangeQuery(distanceQuery, p);
}
// Not supported.
return null;
@@ -283,7 +275,7 @@ public class VAFile<V extends NumberVector<?>> extends AbstractRefiningIndex<V> *
* @author Erich Schubert
*/
- public class VAFileRangeQuery extends AbstractRefiningIndex<V>.AbstractRangeQuery<DoubleDistance> {
+ public class VAFileRangeQuery extends AbstractRefiningIndex<V>.AbstractRangeQuery {
/**
* LP Norm p parameter.
*/
@@ -296,14 +288,13 @@ public class VAFile<V extends NumberVector<?>> extends AbstractRefiningIndex<V> * @param p LP norm p
*/
- public VAFileRangeQuery(DistanceQuery<V, DoubleDistance> distanceQuery, double p) {
+ public VAFileRangeQuery(DistanceQuery<V> distanceQuery, double p) {
super(distanceQuery);
this.p = p;
}
@Override
- public DoubleDistanceDBIDPairList getRangeForObject(V query, DoubleDistance range) {
- final double eps = range.doubleValue();
+ public DoubleDBIDList getRangeForObject(V query, double eps) {
// generate query approximation and lookup table
VectorApproximation queryApprox = calculateApproximation(null, query);
@@ -313,7 +304,7 @@ public class VAFile<V extends NumberVector<?>> extends AbstractRefiningIndex<V> // Count a VA file scan
scans += 1;
- DoubleDistanceDBIDPairList result = new DoubleDistanceDBIDPairList();
+ ModifiableDoubleDBIDList result = DBIDUtil.newDistanceDBIDList();
// Approximation step
for(int i = 0; i < vectorApprox.size(); i++) {
VectorApproximation va = vectorApprox.get(i);
@@ -327,7 +318,7 @@ public class VAFile<V extends NumberVector<?>> extends AbstractRefiningIndex<V> // interested in the DBID only! But this needs an API change.
// refine the next element
- final double dist = refine(va.id, query).doubleValue();
+ final double dist = refine(va.id, query);
if(dist <= eps) {
result.add(dist, va.id);
}
@@ -342,7 +333,7 @@ public class VAFile<V extends NumberVector<?>> extends AbstractRefiningIndex<V> *
* @author Erich Schubert
*/
- public class VAFileKNNQuery extends AbstractRefiningIndex<V>.AbstractKNNQuery<DoubleDistance> {
+ public class VAFileKNNQuery extends AbstractRefiningIndex<V>.AbstractKNNQuery {
/**
* LP Norm p parameter.
*/
@@ -354,13 +345,13 @@ public class VAFile<V extends NumberVector<?>> extends AbstractRefiningIndex<V> * @param distanceQuery Distance query object
* @param p LP norm p
*/
- public VAFileKNNQuery(DistanceQuery<V, DoubleDistance> distanceQuery, double p) {
+ public VAFileKNNQuery(DistanceQuery<V> distanceQuery, double p) {
super(distanceQuery);
this.p = p;
}
@Override
- public DoubleDistanceKNNList getKNNForObject(V query, int k) {
+ public KNNList getKNNForObject(V query, int k) {
// generate query approximation and lookup table
VectorApproximation queryApprox = calculateApproximation(null, query);
@@ -371,7 +362,7 @@ public class VAFile<V extends NumberVector<?>> extends AbstractRefiningIndex<V> DoubleMaxHeap minMaxHeap = new DoubleMaxHeap(k + 1);
double minMaxDist = Double.POSITIVE_INFINITY;
// Candidates with minDist <= kth maxDist
- ArrayList<DoubleObjPair<DBID>> candidates = new ArrayList<>(vectorApprox.size());
+ ModifiableDoubleDBIDList candidates = DBIDUtil.newDistanceDBIDList(vectorApprox.size());
// Count a VA file scan
scans += 1;
@@ -386,7 +377,7 @@ public class VAFile<V extends NumberVector<?>> extends AbstractRefiningIndex<V> if(minDist > minMaxDist) {
continue;
}
- candidates.add(new DoubleObjPair<>(minDist, va.id));
+ candidates.add(minDist, va.id);
// Update candidate pruning heap
minMaxHeap.add(maxDist, k);
@@ -395,25 +386,25 @@ public class VAFile<V extends NumberVector<?>> extends AbstractRefiningIndex<V> }
}
// sort candidates by lower bound (minDist)
- Collections.sort(candidates);
+ candidates.sort();
// refinement step
- DoubleDistanceKNNHeap result = DBIDUtil.newDoubleDistanceHeap(k);
+ KNNHeap result = DBIDUtil.newHeap(k);
// log.fine("candidates size " + candidates.size());
// retrieve accurate distances
- for(DoubleObjPair<DBID> va : candidates) {
+ for(DoubleDBIDListIter iter = candidates.iter(); iter.valid(); iter.advance()) {
// Stop when we are sure to have all elements
if(result.size() >= k) {
- double kDist = result.doubleKNNDistance();
- if(va.first > kDist) {
+ double kDist = result.getKNNDistance();
+ if(iter.doubleValue() > kDist) {
break;
}
}
// refine the next element
- final double dist = refine(va.second, query).doubleValue();
- result.insert(dist, va.second);
+ final double dist = refine(iter, query);
+ result.insert(dist, iter);
}
if(LOG.isDebuggingFinest()) {
LOG.finest("query = (" + query + ")");
@@ -434,7 +425,7 @@ public class VAFile<V extends NumberVector<?>> extends AbstractRefiningIndex<V> *
* @param <V> Vector type
*/
- public static class Factory<V extends NumberVector<?>> implements IndexFactory<V, VAFile<V>> {
+ public static class Factory<V extends NumberVector> implements IndexFactory<V, VAFile<V>> {
/**
* Number of partitions to use in each dimension.
*
diff --git a/src/de/lmu/ifi/dbs/elki/index/vafile/VALPNormDistance.java b/src/de/lmu/ifi/dbs/elki/index/vafile/VALPNormDistance.java index d0b4a8e5..92ef5097 100644 --- a/src/de/lmu/ifi/dbs/elki/index/vafile/VALPNormDistance.java +++ b/src/de/lmu/ifi/dbs/elki/index/vafile/VALPNormDistance.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.vafile; This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team @@ -54,7 +54,7 @@ public class VALPNormDistance { * @param query Query vector * @param queryApprox Query approximation */ - public VALPNormDistance(double p, double[][] splitPositions, NumberVector<?> query, VectorApproximation queryApprox) { + public VALPNormDistance(double p, double[][] splitPositions, NumberVector query, VectorApproximation queryApprox) { super(); this.onebyp = 1.0 / p; this.queryApprox = queryApprox; @@ -155,7 +155,7 @@ public class VALPNormDistance { * @param query Query vector * @param p p */ - private void initializeLookupTable(double[][] splitPositions, NumberVector<?> query, double p) { + private void initializeLookupTable(double[][] splitPositions, NumberVector query, double p) { final int dimensions = splitPositions.length; final int bordercount = splitPositions[0].length; lookup = new double[dimensions][bordercount]; diff --git a/src/de/lmu/ifi/dbs/elki/index/vafile/VectorApproximation.java b/src/de/lmu/ifi/dbs/elki/index/vafile/VectorApproximation.java index f679cf16..464eee11 100644 --- a/src/de/lmu/ifi/dbs/elki/index/vafile/VectorApproximation.java +++ b/src/de/lmu/ifi/dbs/elki/index/vafile/VectorApproximation.java @@ -4,7 +4,7 @@ package de.lmu.ifi.dbs.elki.index.vafile; This file is part of ELKI:
Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2011
+ Copyright (C) 2014
Ludwig-Maximilians-Universität München
Lehr- und Forschungseinheit für Datenbanksysteme
ELKI Development Team @@ -26,7 +26,7 @@ package de.lmu.ifi.dbs.elki.index.vafile; import java.util.Arrays;
import de.lmu.ifi.dbs.elki.database.ids.DBID;
-import de.lmu.ifi.dbs.elki.persistent.ByteArrayUtil;
+import de.lmu.ifi.dbs.elki.utilities.io.ByteArrayUtil;
/**
* Object in a VA approximation.
diff --git a/src/de/lmu/ifi/dbs/elki/index/vafile/package-info.java b/src/de/lmu/ifi/dbs/elki/index/vafile/package-info.java index 10aae35c..362d0b79 100644 --- a/src/de/lmu/ifi/dbs/elki/index/vafile/package-info.java +++ b/src/de/lmu/ifi/dbs/elki/index/vafile/package-info.java @@ -5,7 +5,7 @@ This file is part of ELKI: Environment for Developing KDD-Applications Supported by Index-Structures - Copyright (C) 2013 + Copyright (C) 2014 Ludwig-Maximilians-Universität München Lehr- und Forschungseinheit für Datenbanksysteme ELKI Development Team |